From: Stuart B. <zu...@us...> - 2007-03-13 05:37:26
|
Update of /cvsroot/hppaqemu/hppaqemu/target-hppa In directory sc8-pr-cvs5.sourceforge.net:/tmp/cvs-serv9452/target-hppa Modified Files: op.c translate.c Log Message: Implement nullification, and logical and unit conditions. Index: translate.c =================================================================== RCS file: /cvsroot/hppaqemu/hppaqemu/target-hppa/translate.c,v retrieving revision 1.25 retrieving revision 1.26 diff -C2 -d -r1.25 -r1.26 *** translate.c 13 Mar 2007 02:50:44 -0000 1.25 --- translate.c 13 Mar 2007 05:37:19 -0000 1.26 *************** *** 640,643 **** --- 640,644 ---- } + /* T0 == opd1, T1 == opd2 */ static GenOpFunc * const gen_cond_add[8] = { gen_op_eval_never, *************** *** 651,654 **** --- 652,656 ---- }; + /* T0 == opd1, T1 == opd2 */ static GenOpFunc * const gen_cond_cmp[8] = { gen_op_eval_never, *************** *** 662,665 **** --- 664,703 ---- }; + /* T0 == res */ + static GenOpFunc * const gen_cond_log[8] = { + gen_op_eval_never, + gen_op_eval_log_eq, + gen_op_eval_log_slt, + gen_op_eval_log_slteq, + gen_op_eval_never, /* undefined */ + gen_op_eval_never, /* undefined */ + gen_op_eval_never, /* undefined */ + gen_op_eval_log_od, + }; + + /* T0 == res */ + static GenOpFunc * const gen_cond_unit[8] = { + gen_op_eval_never, + gen_op_eval_never, /* undefined */ + gen_op_eval_unit_sbz, + gen_op_eval_unit_shz, + gen_op_eval_unit_sdc, + gen_op_eval_never, /* undefined */ + gen_op_eval_unit_sbc, + gen_op_eval_unit_shc, + }; + + /* T0 == res, T2 == carry */ + static GenOpFunc * const gen_cond_sed[8] = { + gen_op_eval_never, + gen_op_eval_log_eq, + gen_op_eval_log_slt, + gen_op_eval_log_od, + gen_op_eval_always, + gen_op_eval_log_neq, + gen_op_eval_log_sgteq, + gen_op_eval_log_ev, + }; + static void gen_branch_cond(DisasContext *dc, long tb, target_ulong disp, int n, int f) { *************** *** 671,677 **** if (f) - gen_op_jz_T2_label(l1); - else gen_op_jnz_T2_label(l1); /* taken branch */ --- 709,715 ---- if (f) gen_op_jnz_T2_label(l1); + else + gen_op_jz_T2_label(l1); /* taken branch */ *************** *** 690,693 **** --- 728,754 ---- } + static void gen_nullify_cond(DisasContext *dc, long tb, int f) + { + int l1; + + l1 = gen_new_label(); + + if (f) + gen_op_jnz_T2_label(l1); + else + gen_op_jz_T2_label(l1); + + /* nullify */ + gen_goto_tb(dc, 0, dc->iaoq[1] + 4, dc->iaoq[1] + 8); + + gen_set_label(l1); + + /* don't nullify */ + gen_goto_tb(dc, 1, dc->iaoq[1], dc->iaoq[1] + 4); + + /* FIXME */ + dc->is_br = 1; + } + static void save_state(DisasContext *dc) { *************** *** 1024,1039 **** */ - /* two possible ways to do nullification - * easiest is probably to generate code to check the N flag on each insn - * (which also sucks) - * - * actually can use the DisasContext so that checking is only done - * where the insn could be anulled - */ - - /* possily anulled? */ - - /* if so, check N flag. if set, branch and clear flag */ - /* Major Opcodes */ switch(op) { --- 1085,1088 ---- *************** *** 1256,1262 **** case 0x02: /* Arith/Log */ { ! uint32_t t, r1, r2; r2 = field(insn, 21, 5); r1 = field(insn, 16, 5); ext6 = field(insn, 6, 6); t = field(insn, 0, 5); --- 1305,1313 ---- case 0x02: /* Arith/Log */ { ! uint32_t t, f, c, r1, r2; r2 = field(insn, 21, 5); r1 = field(insn, 16, 5); + c = field(insn, 13, 3); + f = field(insn, 12, 1); ext6 = field(insn, 6, 6); t = field(insn, 0, 5); *************** *** 1267,1278 **** switch(ext6) { case 0x18: /* ADD */ gen_op_add_T1_T0_cc(); break; case 0x38: /* ADDO */ ! gen_op_copy_T2_T0(); ! gen_op_addo_T1_T0(); ! /* if sign(T0) != sign(T1) && ! sign(T1) == sign(T2) ! overflow(); */ break; case 0x1C: /* ADDC */ --- 1318,1331 ---- switch(ext6) { case 0x18: /* ADD */ + if (c && f) + gen_cond_add[c](); gen_op_add_T1_T0_cc(); break; case 0x38: /* ADDO */ ! gen_op_eval_add_sv(); ! /* gen_op_overflow_trap(); */ ! if (c && f) ! gen_cond_add[c](); ! gen_op_add_T1_T0_cc(); break; case 0x1C: /* ADDC */ *************** *** 1284,1319 **** case 0x19: /* SH1ADD */ gen_shift_T0(1); gen_op_add_T1_T0_cc(); break; case 0x39: /* SH1ADDO */ gen_shift_T0(1); gen_op_addo_T1_T0(); break; case 0x1a: /* SH2ADD */ gen_shift_T0(2); gen_op_add_T1_T0_cc(); break; case 0x3a: /* SH2ADDO */ gen_shift_T0(2); gen_op_addo_T1_T0(); break; case 0x1b: /* SH3ADD */ gen_shift_T0(3); gen_op_add_T1_T0_cc(); break; case 0x3b: /* SH3ADDO */ gen_shift_T0(3); gen_op_addo_T1_T0(); break; case 0x10: /* SUB */ gen_op_sub_T1_T0_cc(); break; case 0x30: /* SUBO */ ! gen_op_subo_T1_T0(); break; case 0x13: /* SUBT */ gen_op_subt_T1_T0(); break; case 0x33: /* SUBTO */ gen_op_subto_T1_T0(); break; --- 1337,1392 ---- case 0x19: /* SH1ADD */ gen_shift_T0(1); + if (c && f) + gen_cond_add[c](); gen_op_add_T1_T0_cc(); break; case 0x39: /* SH1ADDO */ gen_shift_T0(1); + if (c && f) + gen_cond_add[c](); gen_op_addo_T1_T0(); break; case 0x1a: /* SH2ADD */ gen_shift_T0(2); + if (c && f) + gen_cond_add[c](); gen_op_add_T1_T0_cc(); break; case 0x3a: /* SH2ADDO */ gen_shift_T0(2); + if (c && f) + gen_cond_add[c](); gen_op_addo_T1_T0(); break; case 0x1b: /* SH3ADD */ gen_shift_T0(3); + if (c && f) + gen_cond_add[c](); gen_op_add_T1_T0_cc(); break; case 0x3b: /* SH3ADDO */ gen_shift_T0(3); + if (c && f) + gen_cond_add[c](); gen_op_addo_T1_T0(); break; case 0x10: /* SUB */ + if (c && f) + gen_cond_cmp[c](); gen_op_sub_T1_T0_cc(); break; case 0x30: /* SUBO */ ! if (c && f) ! gen_cond_cmp[c](); ! gen_op_sub_T1_T0(); break; case 0x13: /* SUBT */ + if (c && f) + gen_cond_cmp[c](); gen_op_subt_T1_T0(); break; case 0x33: /* SUBTO */ + if (c && f) + gen_cond_cmp[c](); gen_op_subto_T1_T0(); break; *************** *** 1329,1368 **** case 0x00: /* ANDCM */ gen_op_andcm_T1_T0(); break; case 0x08: /* AND */ gen_op_and_T1_T0(); break; case 0x09: /* OR */ gen_op_or_T1_T0(); break; case 0x0A: /* XOR */ gen_op_xor_T1_T0(); break; case 0x0E: /* UXOR */ gen_op_uxor_T1_T0(); break; case 0x22: /* COMCLR */ ! gen_op_comclr_T1_T0(); break; case 0x26: /* UADDCM */ gen_op_com_T1(); gen_op_addl_T1_T0(); break; case 0x27: /* UADDCMT */ ! gen_op_uaddcmt_T1_T0(); break; case 0x28: /* ADDL */ gen_op_addl_T1_T0(); break; case 0x29: /* SH1ADDL */ gen_shift_T0(1); gen_op_addl_T1_T0(); break; case 0x2A: /* SH2ADDL */ gen_shift_T0(2); gen_op_addl_T1_T0(); break; case 0x2B: /* SH3ADDL */ gen_shift_T0(3); gen_op_addl_T1_T0(); break; --- 1402,1467 ---- case 0x00: /* ANDCM */ gen_op_andcm_T1_T0(); + if (c && f) + gen_cond_log[c](); break; case 0x08: /* AND */ gen_op_and_T1_T0(); + if (c && f) + gen_cond_log[c](); break; case 0x09: /* OR */ gen_op_or_T1_T0(); + if (c && f) + gen_cond_log[c](); break; case 0x0A: /* XOR */ gen_op_xor_T1_T0(); + if (c && f) + gen_cond_log[c](); break; case 0x0E: /* UXOR */ gen_op_uxor_T1_T0(); + if (c && f) + gen_cond_unit[c](); break; case 0x22: /* COMCLR */ ! if (c && f) ! gen_cond_cmp[c](); ! gen_movl_T0_im(0); break; case 0x26: /* UADDCM */ gen_op_com_T1(); gen_op_addl_T1_T0(); + if (c && f) + gen_cond_unit[c](); break; case 0x27: /* UADDCMT */ ! gen_op_com_T1(); ! gen_op_addl_T1_T0(); ! if (c && f) ! gen_cond_unit[c](); ! /* gen_cond_trap(); */ break; case 0x28: /* ADDL */ + if (c && f) + gen_cond_add[c](); gen_op_addl_T1_T0(); break; case 0x29: /* SH1ADDL */ gen_shift_T0(1); + if (c && f) + gen_cond_add[c](); gen_op_addl_T1_T0(); break; case 0x2A: /* SH2ADDL */ gen_shift_T0(2); + if (c && f) + gen_cond_add[c](); gen_op_addl_T1_T0(); break; case 0x2B: /* SH3ADDL */ gen_shift_T0(3); + if (c && f) + gen_cond_add[c](); gen_op_addl_T1_T0(); break; *************** *** 1388,1391 **** --- 1487,1492 ---- } gen_movl_reg_T0(t); + if (c && f) + gen_nullify_cond(dc, (long)dc->tb, f); break; } Index: op.c =================================================================== RCS file: /cvsroot/hppaqemu/hppaqemu/target-hppa/op.c,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -d -r1.21 -r1.22 *** op.c 13 Mar 2007 02:50:44 -0000 1.21 --- op.c 13 Mar 2007 05:37:19 -0000 1.22 *************** *** 786,789 **** --- 786,794 ---- } + void OPPROTO op_eval_always(void) + { + T2 = 1; + } + /* Addition conditions: * See table 5-4 in PA1.1 Specification *************** *** 890,893 **** --- 895,977 ---- } + /* Logical conditions: + * See table 5-5 in PA1.1 Specification + */ + + /* = */ + void OPPROTO op_eval_log_eq(void) + { + T2 = (T0 == 0); + } + + /* < */ + void OPPROTO op_eval_log_slt(void) + { + T2 = ((int32_t)T0 < 0); + } + + /* <= */ + void OPPROTO op_eval_log_slteq(void) + { + T2 = ((int32_t)T1 <= 0); + } + + /* od */ + void OPPROTO op_eval_log_od(void) + { + T2 = (T0 & 1); + } + + /* Unit conditions: + * See table 5-6 in PA1.1 Specification + */ + + void OPPROTO op_eval_unit_sbz(void) + { + T2 = ((T0 - 0x01010101) & ~T0 & 0x80808080); + } + + void OPPROTO op_eval_unit_shz(void) + { + T2 = ((T0 - 0x00010001) & ~T0 & 0x80008000); + } + + void OPPROTO op_eval_unit_sdc(void) + { + T2 &= 0x88888888; + } + + void OPPROTO op_eval_unit_sbc(void) + { + T2 &= 0x80808080; + } + + void OPPROTO op_eval_unit_shc(void) + { + T2 &= 0x80008000; + } + + /* Shift/extract/deposit conditions + * See table 5-7 in PA1.1 Specification + */ + + /* <> */ + void OPPROTO op_eval_log_neq(void) + { + T2 = (T0 != 0); + } + + /* >= */ + void OPPROTO op_eval_log_sgteq(void) + { + T2 = ((int32_t)T0 >= 0); + } + + /* ev */ + void OPPROTO op_eval_log_ev(void) + { + T2 = !(T0 & 1); + } + /* ------ */ |