365 |
}; |
}; |
366 |
|
|
367 |
static GenOpFunc *gen_op_arith_T0_T1_cc[8] = { |
static GenOpFunc *gen_op_arith_T0_T1_cc[8] = { |
|
gen_op_addl_T0_T1_cc, |
|
|
gen_op_orl_T0_T1_cc, |
|
368 |
NULL, |
NULL, |
369 |
|
gen_op_orl_T0_T1, |
370 |
|
NULL, |
371 |
|
NULL, |
372 |
|
gen_op_andl_T0_T1, |
373 |
|
NULL, |
374 |
|
gen_op_xorl_T0_T1, |
375 |
NULL, |
NULL, |
|
gen_op_andl_T0_T1_cc, |
|
|
gen_op_subl_T0_T1_cc, |
|
|
gen_op_xorl_T0_T1_cc, |
|
|
gen_op_cmpl_T0_T1_cc, |
|
376 |
}; |
}; |
377 |
|
|
378 |
static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = { |
static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = { |
748 |
gen_op_fdiv_STN_ST0, |
gen_op_fdiv_STN_ST0, |
749 |
}; |
}; |
750 |
|
|
751 |
static void gen_op(DisasContext *s1, int op, int ot, int d, int s) |
/* if d == OR_TMP0, it means memory operand (address in A0) */ |
752 |
|
static void gen_op(DisasContext *s1, int op, int ot, int d) |
753 |
{ |
{ |
754 |
if (d != OR_TMP0) |
GenOpFunc *gen_update_cc; |
755 |
|
|
756 |
|
if (d != OR_TMP0) { |
757 |
gen_op_mov_TN_reg[ot][0][d](); |
gen_op_mov_TN_reg[ot][0][d](); |
758 |
if (s != OR_TMP1) |
} else { |
759 |
gen_op_mov_TN_reg[ot][1][s](); |
gen_op_ld_T0_A0[ot](); |
760 |
if (op == OP_ADCL || op == OP_SBBL) { |
} |
761 |
|
switch(op) { |
762 |
|
case OP_ADCL: |
763 |
|
case OP_SBBL: |
764 |
if (s1->cc_op != CC_OP_DYNAMIC) |
if (s1->cc_op != CC_OP_DYNAMIC) |
765 |
gen_op_set_cc_op(s1->cc_op); |
gen_op_set_cc_op(s1->cc_op); |
766 |
gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL](); |
gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL](); |
767 |
s1->cc_op = CC_OP_DYNAMIC; |
s1->cc_op = CC_OP_DYNAMIC; |
768 |
} else { |
/* XXX: incorrect: CC_OP must also be modified AFTER memory access */ |
769 |
|
gen_update_cc = gen_op_update2_cc; |
770 |
|
break; |
771 |
|
case OP_ADDL: |
772 |
|
gen_op_addl_T0_T1(); |
773 |
|
s1->cc_op = CC_OP_ADDB + ot; |
774 |
|
gen_update_cc = gen_op_update2_cc; |
775 |
|
break; |
776 |
|
case OP_SUBL: |
777 |
|
gen_op_subl_T0_T1(); |
778 |
|
s1->cc_op = CC_OP_SUBB + ot; |
779 |
|
gen_update_cc = gen_op_update2_cc; |
780 |
|
break; |
781 |
|
default: |
782 |
|
case OP_ANDL: |
783 |
|
case OP_ORL: |
784 |
|
case OP_XORL: |
785 |
gen_op_arith_T0_T1_cc[op](); |
gen_op_arith_T0_T1_cc[op](); |
786 |
s1->cc_op = cc_op_arithb[op] + ot; |
s1->cc_op = CC_OP_LOGICB + ot; |
787 |
|
gen_update_cc = gen_op_update1_cc; |
788 |
|
break; |
789 |
|
case OP_CMPL: |
790 |
|
gen_op_cmpl_T0_T1_cc(); |
791 |
|
s1->cc_op = CC_OP_SUBB + ot; |
792 |
|
gen_update_cc = NULL; |
793 |
|
break; |
794 |
} |
} |
795 |
if (d != OR_TMP0 && op != OP_CMPL) |
if (op != OP_CMPL) { |
796 |
gen_op_mov_reg_T0[ot][d](); |
if (d != OR_TMP0) |
797 |
} |
gen_op_mov_reg_T0[ot][d](); |
798 |
|
else |
799 |
static void gen_opi(DisasContext *s1, int op, int ot, int d, int c) |
gen_op_st_T0_A0[ot](); |
800 |
{ |
} |
801 |
gen_op_movl_T1_im(c); |
/* the flags update must happen after the memory write (precise |
802 |
gen_op(s1, op, ot, d, OR_TMP1); |
exception support) */ |
803 |
|
if (gen_update_cc) |
804 |
|
gen_update_cc(); |
805 |
} |
} |
806 |
|
|
807 |
|
/* if d == OR_TMP0, it means memory operand (address in A0) */ |
808 |
static void gen_inc(DisasContext *s1, int ot, int d, int c) |
static void gen_inc(DisasContext *s1, int ot, int d, int c) |
809 |
{ |
{ |
810 |
if (d != OR_TMP0) |
if (d != OR_TMP0) |
811 |
gen_op_mov_TN_reg[ot][0][d](); |
gen_op_mov_TN_reg[ot][0][d](); |
812 |
|
else |
813 |
|
gen_op_ld_T0_A0[ot](); |
814 |
if (s1->cc_op != CC_OP_DYNAMIC) |
if (s1->cc_op != CC_OP_DYNAMIC) |
815 |
gen_op_set_cc_op(s1->cc_op); |
gen_op_set_cc_op(s1->cc_op); |
816 |
if (c > 0) { |
if (c > 0) { |
817 |
gen_op_incl_T0_cc(); |
gen_op_incl_T0(); |
818 |
s1->cc_op = CC_OP_INCB + ot; |
s1->cc_op = CC_OP_INCB + ot; |
819 |
} else { |
} else { |
820 |
gen_op_decl_T0_cc(); |
gen_op_decl_T0(); |
821 |
s1->cc_op = CC_OP_DECB + ot; |
s1->cc_op = CC_OP_DECB + ot; |
822 |
} |
} |
823 |
if (d != OR_TMP0) |
if (d != OR_TMP0) |
824 |
gen_op_mov_reg_T0[ot][d](); |
gen_op_mov_reg_T0[ot][d](); |
825 |
|
else |
826 |
|
gen_op_st_T0_A0[ot](); |
827 |
|
gen_op_update_inc_cc(); |
828 |
} |
} |
829 |
|
|
830 |
static void gen_shift(DisasContext *s1, int op, int ot, int d, int s) |
static void gen_shift(DisasContext *s1, int op, int ot, int d, int s) |
1496 |
rm = modrm & 7; |
rm = modrm & 7; |
1497 |
if (mod != 3) { |
if (mod != 3) { |
1498 |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
gen_op_ld_T0_A0[ot](); |
|
1499 |
opreg = OR_TMP0; |
opreg = OR_TMP0; |
1500 |
} else { |
} else { |
1501 |
opreg = OR_EAX + rm; |
opreg = OR_EAX + rm; |
1502 |
} |
} |
1503 |
gen_op(s, op, ot, opreg, reg); |
gen_op_mov_TN_reg[ot][1][reg](); |
1504 |
if (mod != 3 && op != 7) { |
gen_op(s, op, ot, opreg); |
|
gen_op_st_T0_A0[ot](); |
|
|
} |
|
1505 |
break; |
break; |
1506 |
case 1: /* OP Gv, Ev */ |
case 1: /* OP Gv, Ev */ |
1507 |
modrm = ldub(s->pc++); |
modrm = ldub(s->pc++); |
1511 |
if (mod != 3) { |
if (mod != 3) { |
1512 |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
1513 |
gen_op_ld_T1_A0[ot](); |
gen_op_ld_T1_A0[ot](); |
|
opreg = OR_TMP1; |
|
1514 |
} else { |
} else { |
1515 |
opreg = OR_EAX + rm; |
gen_op_mov_TN_reg[ot][1][rm](); |
1516 |
} |
} |
1517 |
gen_op(s, op, ot, reg, opreg); |
gen_op(s, op, ot, reg); |
1518 |
break; |
break; |
1519 |
case 2: /* OP A, Iv */ |
case 2: /* OP A, Iv */ |
1520 |
val = insn_get(s, ot); |
val = insn_get(s, ot); |
1521 |
gen_opi(s, op, ot, OR_EAX, val); |
gen_op_movl_T1_im(val); |
1522 |
|
gen_op(s, op, ot, OR_EAX); |
1523 |
break; |
break; |
1524 |
} |
} |
1525 |
} |
} |
1543 |
|
|
1544 |
if (mod != 3) { |
if (mod != 3) { |
1545 |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
gen_op_ld_T0_A0[ot](); |
|
1546 |
opreg = OR_TMP0; |
opreg = OR_TMP0; |
1547 |
} else { |
} else { |
1548 |
opreg = rm + OR_EAX; |
opreg = rm + OR_EAX; |
1558 |
val = (int8_t)insn_get(s, OT_BYTE); |
val = (int8_t)insn_get(s, OT_BYTE); |
1559 |
break; |
break; |
1560 |
} |
} |
1561 |
|
gen_op_movl_T1_im(val); |
1562 |
gen_opi(s, op, ot, opreg, val); |
gen_op(s, op, ot, opreg); |
|
if (op != 7 && mod != 3) { |
|
|
gen_op_st_T0_A0[ot](); |
|
|
} |
|
1563 |
} |
} |
1564 |
break; |
break; |
1565 |
|
|
1607 |
} |
} |
1608 |
break; |
break; |
1609 |
case 3: /* neg */ |
case 3: /* neg */ |
1610 |
gen_op_negl_T0_cc(); |
gen_op_negl_T0(); |
1611 |
if (mod != 3) { |
if (mod != 3) { |
1612 |
gen_op_st_T0_A0[ot](); |
gen_op_st_T0_A0[ot](); |
1613 |
} else { |
} else { |
1614 |
gen_op_mov_reg_T0[ot][rm](); |
gen_op_mov_reg_T0[ot][rm](); |
1615 |
} |
} |
1616 |
|
gen_op_update_neg_cc(); |
1617 |
s->cc_op = CC_OP_SUBB + ot; |
s->cc_op = CC_OP_SUBB + ot; |
1618 |
break; |
break; |
1619 |
case 4: /* mul */ |
case 4: /* mul */ |
1695 |
} |
} |
1696 |
if (mod != 3) { |
if (mod != 3) { |
1697 |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
1698 |
if (op != 3 && op != 5) |
if (op >= 2 && op != 3 && op != 5) |
1699 |
gen_op_ld_T0_A0[ot](); |
gen_op_ld_T0_A0[ot](); |
1700 |
} else { |
} else { |
1701 |
gen_op_mov_TN_reg[ot][0][rm](); |
gen_op_mov_TN_reg[ot][0][rm](); |
1703 |
|
|
1704 |
switch(op) { |
switch(op) { |
1705 |
case 0: /* inc Ev */ |
case 0: /* inc Ev */ |
|
gen_inc(s, ot, OR_TMP0, 1); |
|
1706 |
if (mod != 3) |
if (mod != 3) |
1707 |
gen_op_st_T0_A0[ot](); |
opreg = OR_TMP0; |
1708 |
else |
else |
1709 |
gen_op_mov_reg_T0[ot][rm](); |
opreg = rm; |
1710 |
|
gen_inc(s, ot, opreg, 1); |
1711 |
break; |
break; |
1712 |
case 1: /* dec Ev */ |
case 1: /* dec Ev */ |
|
gen_inc(s, ot, OR_TMP0, -1); |
|
1713 |
if (mod != 3) |
if (mod != 3) |
1714 |
gen_op_st_T0_A0[ot](); |
opreg = OR_TMP0; |
1715 |
else |
else |
1716 |
gen_op_mov_reg_T0[ot][rm](); |
opreg = rm; |
1717 |
|
gen_inc(s, ot, opreg, -1); |
1718 |
break; |
break; |
1719 |
case 2: /* call Ev */ |
case 2: /* call Ev */ |
1720 |
/* XXX: optimize if memory (no and is necessary) */ |
/* XXX: optimize if memory (no and is necessary) */ |
1853 |
rm = modrm & 7; |
rm = modrm & 7; |
1854 |
gen_op_mov_TN_reg[ot][0][reg](); |
gen_op_mov_TN_reg[ot][0][reg](); |
1855 |
gen_op_mov_TN_reg[ot][1][rm](); |
gen_op_mov_TN_reg[ot][1][rm](); |
1856 |
gen_op_addl_T0_T1_cc(); |
gen_op_addl_T0_T1(); |
1857 |
gen_op_mov_reg_T0[ot][rm](); |
gen_op_mov_reg_T0[ot][rm](); |
1858 |
gen_op_mov_reg_T1[ot][reg](); |
gen_op_mov_reg_T1[ot][reg](); |
1859 |
} else { |
} else { |
1860 |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
1861 |
gen_op_mov_TN_reg[ot][0][reg](); |
gen_op_mov_TN_reg[ot][0][reg](); |
1862 |
gen_op_ld_T1_A0[ot](); |
gen_op_ld_T1_A0[ot](); |
1863 |
gen_op_addl_T0_T1_cc(); |
gen_op_addl_T0_T1(); |
1864 |
gen_op_st_T0_A0[ot](); |
gen_op_st_T0_A0[ot](); |
1865 |
gen_op_mov_reg_T1[ot][reg](); |
gen_op_mov_reg_T1[ot][reg](); |
1866 |
} |
} |
1867 |
|
gen_op_update2_cc(); |
1868 |
s->cc_op = CC_OP_ADDB + ot; |
s->cc_op = CC_OP_ADDB + ot; |
1869 |
break; |
break; |
1870 |
case 0x1b0: |
case 0x1b0: |
3639 |
[INDEX_op_sbbl_T0_T1_cc] = CC_C, |
[INDEX_op_sbbl_T0_T1_cc] = CC_C, |
3640 |
|
|
3641 |
/* subtle: due to the incl/decl implementation, C is used */ |
/* subtle: due to the incl/decl implementation, C is used */ |
3642 |
[INDEX_op_incl_T0_cc] = CC_C, |
[INDEX_op_update_inc_cc] = CC_C, |
|
[INDEX_op_decl_T0_cc] = CC_C, |
|
3643 |
|
|
3644 |
[INDEX_op_into] = CC_O, |
[INDEX_op_into] = CC_O, |
3645 |
|
|
3719 |
|
|
3720 |
/* flags written by an operation */ |
/* flags written by an operation */ |
3721 |
static uint16_t opc_write_flags[NB_OPS] = { |
static uint16_t opc_write_flags[NB_OPS] = { |
3722 |
[INDEX_op_addl_T0_T1_cc] = CC_OSZAPC, |
[INDEX_op_update2_cc] = CC_OSZAPC, |
3723 |
[INDEX_op_orl_T0_T1_cc] = CC_OSZAPC, |
[INDEX_op_update1_cc] = CC_OSZAPC, |
3724 |
[INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC, |
[INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC, |
3725 |
[INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC, |
[INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC, |
3726 |
[INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC, |
[INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC, |
3727 |
[INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC, |
[INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC, |
3728 |
[INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC, |
[INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC, |
3729 |
[INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC, |
[INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC, |
|
[INDEX_op_andl_T0_T1_cc] = CC_OSZAPC, |
|
|
[INDEX_op_subl_T0_T1_cc] = CC_OSZAPC, |
|
|
[INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC, |
|
3730 |
[INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC, |
[INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC, |
3731 |
[INDEX_op_negl_T0_cc] = CC_OSZAPC, |
[INDEX_op_update_neg_cc] = CC_OSZAPC, |
3732 |
/* subtle: due to the incl/decl implementation, C is used */ |
/* subtle: due to the incl/decl implementation, C is used */ |
3733 |
[INDEX_op_incl_T0_cc] = CC_OSZAPC, |
[INDEX_op_update_inc_cc] = CC_OSZAPC, |
|
[INDEX_op_decl_T0_cc] = CC_OSZAPC, |
|
3734 |
[INDEX_op_testl_T0_T1_cc] = CC_OSZAPC, |
[INDEX_op_testl_T0_T1_cc] = CC_OSZAPC, |
3735 |
|
|
3736 |
[INDEX_op_mulb_AL_T0] = CC_OSZAPC, |
[INDEX_op_mulb_AL_T0] = CC_OSZAPC, |
3839 |
|
|
3840 |
/* simpler form of an operation if no flags need to be generated */ |
/* simpler form of an operation if no flags need to be generated */ |
3841 |
static uint16_t opc_simpler[NB_OPS] = { |
static uint16_t opc_simpler[NB_OPS] = { |
3842 |
[INDEX_op_addl_T0_T1_cc] = INDEX_op_addl_T0_T1, |
[INDEX_op_update2_cc] = INDEX_op_nop, |
3843 |
[INDEX_op_orl_T0_T1_cc] = INDEX_op_orl_T0_T1, |
[INDEX_op_update1_cc] = INDEX_op_nop, |
3844 |
[INDEX_op_andl_T0_T1_cc] = INDEX_op_andl_T0_T1, |
[INDEX_op_update_neg_cc] = INDEX_op_nop, |
3845 |
[INDEX_op_subl_T0_T1_cc] = INDEX_op_subl_T0_T1, |
[INDEX_op_update_inc_cc] = INDEX_op_nop, |
|
[INDEX_op_xorl_T0_T1_cc] = INDEX_op_xorl_T0_T1, |
|
|
[INDEX_op_negl_T0_cc] = INDEX_op_negl_T0, |
|
|
[INDEX_op_incl_T0_cc] = INDEX_op_incl_T0, |
|
|
[INDEX_op_decl_T0_cc] = INDEX_op_decl_T0, |
|
3846 |
|
|
3847 |
[INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1, |
[INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1, |
3848 |
[INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1, |
[INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1, |