aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2008-05-17 18:44:58 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2008-05-17 18:44:58 +0000
commit6191b05901ef1a85c64383e34406024daa4eda12 (patch)
treed0a4405b885c0999c3dcdfbe6af47a02452df8c9
parent7c6ce4baedfcd0c39250f313926ef61dcb47d74c (diff)
BSR/BSF TCG conversion
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4477 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r--target-i386/helper.c31
-rw-r--r--target-i386/helper.h2
-rw-r--r--target-i386/ops_template.h45
-rw-r--r--target-i386/translate.c48
4 files changed, 54 insertions, 72 deletions
diff --git a/target-i386/helper.c b/target-i386/helper.c
index ce99c957d2..d888eaf9c3 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -5240,6 +5240,37 @@ void helper_movq(uint64_t *d, uint64_t *s)
#endif
+/* bit operations */
+target_ulong helper_bsf(target_ulong t0)
+{
+ int count;
+ target_ulong res;
+
+ res = t0;
+ count = 0;
+ while ((res & 1) == 0) {
+ count++;
+ res >>= 1;
+ }
+ return count;
+}
+
+target_ulong helper_bsr(target_ulong t0)
+{
+ int count;
+ target_ulong res, mask;
+
+ res = t0;
+ count = TARGET_LONG_BITS - 1;
+ mask = (target_ulong)1 << (TARGET_LONG_BITS - 1);
+ while ((res & mask) == 0) {
+ count--;
+ res <<= 1;
+ }
+ return count;
+}
+
+
static int compute_all_eflags(void)
{
return CC_SRC;
diff --git a/target-i386/helper.h b/target-i386/helper.h
index c55d111ed2..d8b2829cbc 100644
--- a/target-i386/helper.h
+++ b/target-i386/helper.h
@@ -187,6 +187,8 @@ void helper_fsave(target_ulong ptr, int data32);
void helper_frstor(target_ulong ptr, int data32);
void helper_fxsave(target_ulong ptr, int data64);
void helper_fxrstor(target_ulong ptr, int data64);
+target_ulong helper_bsf(target_ulong t0);
+target_ulong helper_bsr(target_ulong t0);
/* MMX/SSE */
diff --git a/target-i386/ops_template.h b/target-i386/ops_template.h
index 9a91c074b8..f91d19e397 100644
--- a/target-i386/ops_template.h
+++ b/target-i386/ops_template.h
@@ -200,51 +200,6 @@ void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2);
}
-/* bit operations */
-#if DATA_BITS >= 16
-
-void OPPROTO glue(glue(op_bsf, SUFFIX), _T0_cc)(void)
-{
- int count;
- target_long res;
-
- res = T0 & DATA_MASK;
- if (res != 0) {
- count = 0;
- while ((res & 1) == 0) {
- count++;
- res >>= 1;
- }
- T1 = count;
- CC_DST = 1; /* ZF = 0 */
- } else {
- CC_DST = 0; /* ZF = 1 */
- }
- FORCE_RET();
-}
-
-void OPPROTO glue(glue(op_bsr, SUFFIX), _T0_cc)(void)
-{
- int count;
- target_long res;
-
- res = T0 & DATA_MASK;
- if (res != 0) {
- count = DATA_BITS - 1;
- while ((res & SIGN_MASK) == 0) {
- count--;
- res <<= 1;
- }
- T1 = count;
- CC_DST = 1; /* ZF = 0 */
- } else {
- CC_DST = 0; /* ZF = 1 */
- }
- FORCE_RET();
-}
-
-#endif
-
/* string operations */
void OPPROTO glue(op_movl_T0_Dshift, SUFFIX)(void)
diff --git a/target-i386/translate.c b/target-i386/translate.c
index e8a4bbdc95..485ba718b8 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -498,23 +498,6 @@ static GenOpFunc *gen_op_cmov_reg_T1_T0[NB_OP_SIZES - 1][CPU_NB_REGS] = {
#endif
};
-static GenOpFunc *gen_op_bsx_T0_cc[3][2] = {
- [0] = {
- gen_op_bsfw_T0_cc,
- gen_op_bsrw_T0_cc,
- },
- [1] = {
- gen_op_bsfl_T0_cc,
- gen_op_bsrl_T0_cc,
- },
-#ifdef TARGET_X86_64
- [2] = {
- gen_op_bsfq_T0_cc,
- gen_op_bsrq_T0_cc,
- },
-#endif
-};
-
static inline void gen_op_lds_T0_A0(int idx)
{
int mem_index = (idx >> 2) - 1;
@@ -5837,16 +5820,27 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
break;
case 0x1bc: /* bsf */
case 0x1bd: /* bsr */
- ot = dflag + OT_WORD;
- modrm = ldub_code(s->pc++);
- reg = ((modrm >> 3) & 7) | rex_r;
- gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
- /* NOTE: in order to handle the 0 case, we must load the
- result. It could be optimized with a generated jump */
- gen_op_mov_TN_reg(ot, 1, reg);
- gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
- gen_op_mov_reg_T1(ot, reg);
- s->cc_op = CC_OP_LOGICB + ot;
+ {
+ int label1;
+ ot = dflag + OT_WORD;
+ modrm = ldub_code(s->pc++);
+ reg = ((modrm >> 3) & 7) | rex_r;
+ gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
+ gen_extu(ot, cpu_T[0]);
+ label1 = gen_new_label();
+ tcg_gen_movi_tl(cpu_cc_dst, 0);
+ tcg_gen_brcond_tl(TCG_COND_EQ, cpu_T[0], tcg_const_tl(0), label1);
+ if (b & 1) {
+ tcg_gen_helper_1_1(helper_bsr, cpu_T[0], cpu_T[0]);
+ } else {
+ tcg_gen_helper_1_1(helper_bsf, cpu_T[0], cpu_T[0]);
+ }
+ gen_op_mov_reg_T0(ot, reg);
+ tcg_gen_movi_tl(cpu_cc_dst, 1);
+ gen_set_label(label1);
+ tcg_gen_discard_tl(cpu_cc_src);
+ s->cc_op = CC_OP_LOGICB + ot;
+ }
break;
/************************/
/* bcd */