diff options
author | Richard Henderson <rth@twiddle.net> | 2013-01-29 13:38:43 -0800 |
---|---|---|
committer | Richard Henderson <rth@twiddle.net> | 2013-02-19 23:05:18 -0800 |
commit | 436ff2d227588d42970c4f0ed1cdfcb87c872fba (patch) | |
tree | 490749eb20535f821b9937d8fb25d7a38faad2a9 /target-i386 | |
parent | 321c535105a182501b888f095f7ec4dbb5f3f6ae (diff) |
target-i386: Add CC_OP_CLR
Special case xor with self. We need not even store the known
zero into cc_src.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'target-i386')
-rw-r--r-- | target-i386/cc_helper.c | 3 | ||||
-rw-r--r-- | target-i386/cpu.h | 2 | ||||
-rw-r--r-- | target-i386/helper.c | 2 | ||||
-rw-r--r-- | target-i386/translate.c | 17 |
4 files changed, 21 insertions, 3 deletions
diff --git a/target-i386/cc_helper.c b/target-i386/cc_helper.c index 6cf57a76b3..9daa1a06b8 100644 --- a/target-i386/cc_helper.c +++ b/target-i386/cc_helper.c @@ -102,6 +102,8 @@ target_ulong helper_cc_compute_all(target_ulong dst, target_ulong src1, case CC_OP_EFLAGS: return src1; + case CC_OP_CLR: + return CC_Z; case CC_OP_MULB: return compute_all_mulb(dst, src1); @@ -228,6 +230,7 @@ target_ulong helper_cc_compute_c(target_ulong dst, target_ulong src1, case CC_OP_LOGICW: case CC_OP_LOGICL: case CC_OP_LOGICQ: + case CC_OP_CLR: return 0; case CC_OP_EFLAGS: diff --git a/target-i386/cpu.h b/target-i386/cpu.h index e0443d8917..493dda8bb6 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -645,6 +645,8 @@ typedef enum { CC_OP_ADOX, /* CC_DST = O, CC_SRC = rest. */ CC_OP_ADCOX, /* CC_DST = C, CC_SRC2 = O, CC_SRC = rest. */ + CC_OP_CLR, /* Z set, all other flags clear. */ + CC_OP_NB, } CCOp; diff --git a/target-i386/helper.c b/target-i386/helper.c index 66c3624733..82a731c77d 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -117,6 +117,8 @@ static const char *cc_op_str[CC_OP_NB] = { "ADCX", "ADOX", "ADCOX", + + "CLR", }; static void diff --git a/target-i386/translate.c b/target-i386/translate.c index 97c565f697..007d32602a 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -213,6 +213,7 @@ static const uint8_t cc_op_live[CC_OP_NB] = { [CC_OP_ADCX] = USES_CC_DST | USES_CC_SRC, [CC_OP_ADOX] = USES_CC_SRC | USES_CC_SRC2, [CC_OP_ADCOX] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2, + [CC_OP_CLR] = 0, }; static void set_cc_op(DisasContext *s, CCOp op) @@ -906,6 +907,11 @@ static void gen_compute_eflags(DisasContext *s) if (s->cc_op == CC_OP_EFLAGS) { return; } + if (s->cc_op == CC_OP_CLR) { + tcg_gen_movi_tl(cpu_cc_src, CC_Z); + set_cc_op(s, CC_OP_EFLAGS); + return; + } TCGV_UNUSED(zero); dst = cpu_cc_dst; @@ -974,6 +980,7 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg) .reg2 = t1, .mask = -1, .use_reg2 = true }; case CC_OP_LOGICB ... CC_OP_LOGICQ: + case CC_OP_CLR: return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 }; case CC_OP_INCB ... CC_OP_INCQ: @@ -1040,6 +1047,8 @@ static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg) case CC_OP_ADCOX: return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src, .mask = CC_S }; + case CC_OP_CLR: + return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 }; default: { int size = (s->cc_op - CC_OP_ADDB) & 3; @@ -1057,7 +1066,8 @@ static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg) case CC_OP_ADCOX: return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src2, .mask = -1, .no_setcond = true }; - + case CC_OP_CLR: + return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 }; default: gen_compute_eflags(s); return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src, @@ -1078,6 +1088,8 @@ static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg) case CC_OP_ADCOX: return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src, .mask = CC_Z }; + case CC_OP_CLR: + return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 }; default: { int size = (s->cc_op - CC_OP_ADDB) & 3; @@ -4890,10 +4902,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, } else if (op == OP_XORL && rm == reg) { xor_zero: /* xor reg, reg optimisation */ + set_cc_op(s, CC_OP_CLR); gen_op_movl_T0_0(); - set_cc_op(s, CC_OP_LOGICB + ot); gen_op_mov_reg_T0(ot, reg); - gen_op_update1_cc(); break; } else { opreg = rm; |