aboutsummaryrefslogtreecommitdiff
path: root/translate-i386.c
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-03-05 22:24:48 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-03-05 22:24:48 +0000
commit77f8dd5add8f02253dcea1454c9d2c76d7c788a7 (patch)
treefbe97a8744410aa6c8857f882b6497ba341943bd /translate-i386.c
parentc5e9815da4e67d42d2a0f8dce4282e8e6d691b88 (diff)
float fixes - added bsr/bsf support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@23 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'translate-i386.c')
-rw-r--r--translate-i386.c83
1 files changed, 66 insertions, 17 deletions
diff --git a/translate-i386.c b/translate-i386.c
index 69c769c198..5c1fc3dd7b 100644
--- a/translate-i386.c
+++ b/translate-i386.c
@@ -431,6 +431,17 @@ static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
},
};
+static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
+ [0] = {
+ gen_op_bsfw_T0_cc,
+ gen_op_bsrw_T0_cc,
+ },
+ [1] = {
+ gen_op_bsfl_T0_cc,
+ gen_op_bsrl_T0_cc,
+ },
+};
+
static GenOpFunc *gen_op_lds_T0_A0[3] = {
gen_op_ldsb_T0_A0,
gen_op_ldsw_T0_A0,
@@ -652,15 +663,16 @@ static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
gen_op_fdivr_ST0_FT0,
};
+/* NOTE the exception in "r" op ordering */
static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
gen_op_fadd_STN_ST0,
gen_op_fmul_STN_ST0,
NULL,
NULL,
- gen_op_fsub_STN_ST0,
gen_op_fsubr_STN_ST0,
- gen_op_fdiv_STN_ST0,
+ gen_op_fsub_STN_ST0,
gen_op_fdivr_STN_ST0,
+ gen_op_fdiv_STN_ST0,
};
static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
@@ -1866,13 +1878,25 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
case 0x0f: /* fnstcw mem */
gen_op_fnstcw_A0();
break;
+ case 0x1d: /* fldt mem */
+ gen_op_fpush();
+ gen_op_fldt_ST0_A0();
+ break;
+ case 0x1f: /* fstpt mem */
+ gen_op_fstt_ST0_A0();
+ gen_op_fpop();
+ break;
case 0x2f: /* fnstsw mem */
gen_op_fnstsw_A0();
break;
case 0x3c: /* fbld */
+ gen_op_fpush();
+ op_fbld_ST0_A0();
+ break;
case 0x3e: /* fbstp */
- error("float BCD not hanlded");
- return -1;
+ gen_op_fbst_ST0_A0();
+ gen_op_fpop();
+ break;
case 0x3d: /* fildll */
gen_op_fpush();
gen_op_fildll_ST0_A0();
@@ -1882,7 +1906,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
gen_op_fpop();
break;
default:
- error("unhandled memory FP [op=0x%02x]\n", op);
+ error("unhandled FPm [op=0x%02x]\n", op);
return -1;
}
} else {
@@ -1895,7 +1919,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
gen_op_fmov_ST0_STN((opreg + 1) & 7);
break;
case 0x09: /* fxchg sti */
- gen_op_fxchg_ST0_STN((opreg + 1) & 7);
+ gen_op_fxchg_ST0_STN(opreg);
break;
case 0x0a: /* grp d9/2 */
switch(rm) {
@@ -1929,24 +1953,31 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
{
switch(rm) {
case 0:
+ gen_op_fpush();
gen_op_fld1_ST0();
break;
case 1:
- gen_op_fld2t_ST0();
+ gen_op_fpush();
+ gen_op_fldl2t_ST0();
break;
case 2:
- gen_op_fld2e_ST0();
+ gen_op_fpush();
+ gen_op_fldl2e_ST0();
break;
case 3:
+ gen_op_fpush();
gen_op_fldpi_ST0();
break;
case 4:
+ gen_op_fpush();
gen_op_fldlg2_ST0();
break;
case 5:
+ gen_op_fpush();
gen_op_fldln2_ST0();
break;
case 6:
+ gen_op_fpush();
gen_op_fldz_ST0();
break;
default:
@@ -2021,12 +2052,12 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
op1 = op & 7;
if (op >= 0x20) {
gen_op_fp_arith_STN_ST0[op1](opreg);
+ if (op >= 0x30)
+ gen_op_fpop();
} else {
gen_op_fmov_FT0_STN(opreg);
gen_op_fp_arith_ST0_FT0[op1]();
}
- if (op >= 0x30)
- gen_op_fpop();
}
break;
case 0x02: /* fcom */
@@ -2042,7 +2073,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
switch(rm) {
case 1: /* fucompp */
gen_op_fmov_FT0_STN(1);
- gen_op_fcom_ST0_FT0();
+ gen_op_fucom_ST0_FT0();
gen_op_fpop();
gen_op_fpop();
break;
@@ -2057,6 +2088,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
gen_op_fmov_STN_ST0(opreg);
gen_op_fpop();
break;
+ case 0x2c: /* fucom st(i) */
+ gen_op_fmov_FT0_STN(opreg);
+ gen_op_fucom_ST0_FT0();
+ break;
+ case 0x2d: /* fucomp st(i) */
+ gen_op_fmov_FT0_STN(opreg);
+ gen_op_fucom_ST0_FT0();
+ gen_op_fpop();
+ break;
case 0x33: /* de/3 */
switch(rm) {
case 1: /* fcompp */
@@ -2071,18 +2111,16 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
break;
case 0x3c: /* df/4 */
switch(rm) {
-#if 0
case 0:
- gen_insn3(OP_FNSTS, OR_EAX, OR_ZERO, OR_ZERO);
+ gen_op_fnstsw_EAX();
break;
-#endif
default:
- error("unhandled FP df/4\n");
+ error("unhandled FP %x df/4\n", rm);
return -1;
}
break;
default:
- error("unhandled FP\n");
+ error("unhandled FPr [op=0x%x]\n", op);
return -1;
}
}
@@ -2413,7 +2451,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
gen_op_mov_reg_T0[ot][rm]();
}
break;
-
+ case 0x1bc: /* bsf */
+ case 0x1bd: /* bsr */
+ ot = dflag ? OT_LONG : OT_WORD;
+ modrm = ldub(s->pc++);
+ reg = (modrm >> 3) & 7;
+ gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
+ gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
+ /* NOTE: we always write back the result. Intel doc says it is
+ undefined if T0 == 0 */
+ gen_op_mov_reg_T0[ot][reg]();
+ s->cc_op = CC_OP_LOGICB + ot;
+ break;
/************************/
/* misc */
case 0x90: /* nop */