Re: [Qemu-devel] [PATCH 16/52] target-m68k: update CPU flags management

2016-05-06 Thread Richard Henderson

On 05/04/2016 10:11 AM, Laurent Vivier wrote:

Copied from target-i386

Signed-off-by: Laurent Vivier 
---
 target-m68k/cpu.h   |   5 +-
 target-m68k/translate.c | 121 +---
 2 files changed, 86 insertions(+), 40 deletions(-)


Reviewed-by: Richard Henderson 


r~




[Qemu-devel] [PATCH 16/52] target-m68k: update CPU flags management

2016-05-04 Thread Laurent Vivier
Copied from target-i386

Signed-off-by: Laurent Vivier 
---
 target-m68k/cpu.h   |   5 +-
 target-m68k/translate.c | 121 +---
 2 files changed, 86 insertions(+), 40 deletions(-)

diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index d3acd33..8dafaab 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -130,7 +130,7 @@ int cpu_m68k_exec(CPUState *cpu);
 int cpu_m68k_signal_handler(int host_signum, void *pinfo,
void *puc);
 
-enum {
+typedef enum {
 CC_OP_DYNAMIC, /* Use env->cc_op  */
 CC_OP_FLAGS, /* CC_DEST = CVZN, CC_SRC = unused */
 CC_OP_LOGICB, /* CC_DEST = result, CC_SRC = unused */
@@ -151,7 +151,8 @@ enum {
 CC_OP_SHIFTB, /* CC_DEST = result, CC_SRC = carry */
 CC_OP_SHIFTW, /* CC_DEST = result, CC_SRC = carry */
 CC_OP_SHIFT, /* CC_DEST = result, CC_SRC = carry */
-};
+CC_OP_NB,
+} CCOp;
 
 #define CCF_C 0x01
 #define CCF_V 0x02
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 16f09ca..82c22b2 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -131,7 +131,7 @@ typedef struct DisasContext {
 target_ulong insn_pc; /* Start of the current instruction.  */
 target_ulong pc;
 int is_jmp;
-int cc_op;
+CCOp cc_op; /* Current CC operation */
 int user;
 uint32_t fpcr;
 struct TranslationBlock *tb;
@@ -173,6 +173,53 @@ typedef void (*disas_proc)(CPUM68KState *env, DisasContext 
*s, uint16_t insn);
  uint16_t insn)
 #endif
 
+enum {
+USES_CC_DST  = 1,
+USES_CC_SRC  = 2,
+};
+
+static const uint8_t cc_op_live[CC_OP_NB] = {
+[CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC,
+[CC_OP_FLAGS] = USES_CC_DST,
+[CC_OP_LOGICB ... CC_OP_LOGIC] = USES_CC_DST,
+[CC_OP_ADDB ... CC_OP_ADD] = USES_CC_DST | USES_CC_SRC,
+[CC_OP_SUBB ... CC_OP_SUB] = USES_CC_DST | USES_CC_SRC,
+[CC_OP_ADDXB ... CC_OP_ADDX] = USES_CC_DST | USES_CC_SRC,
+[CC_OP_SUBXB ... CC_OP_SUBX] = USES_CC_DST | USES_CC_SRC,
+[CC_OP_SHIFTB ... CC_OP_SHIFT] = USES_CC_DST | USES_CC_SRC,
+};
+
+static void set_cc_op(DisasContext *s, CCOp op)
+{
+int dead;
+
+if (s->cc_op == op) {
+return;
+}
+
+/* Discard CC computation that will no longer be used.  */
+
+dead = cc_op_live[s->cc_op] & ~cc_op_live[op];
+if (dead & USES_CC_DST) {
+tcg_gen_discard_i32(QREG_CC_DEST);
+}
+if (dead & USES_CC_SRC) {
+tcg_gen_discard_i32(QREG_CC_SRC);
+}
+if (s->cc_op == CC_OP_DYNAMIC) {
+tcg_gen_discard_i32(QREG_CC_OP);
+}
+s->cc_op = op;
+}
+
+/* Update the CPU env CC_OP state.  */
+static inline void update_cc_op(DisasContext *s)
+{
+if (s->cc_op != CC_OP_DYNAMIC) {
+tcg_gen_movi_i32(QREG_CC_OP, s->cc_op);
+}
+}
+
 /* Generate a load from the specified address.  Narrow values are
sign extended to full register width.  */
 static inline TCGv gen_load(DisasContext * s, int opsize, TCGv addr, int sign)
@@ -409,31 +456,28 @@ static TCGv gen_lea_indexed(CPUM68KState *env, 
DisasContext *s, TCGv base)
 return add;
 }
 
-/* Update the CPU env CC_OP state.  */
-static inline void gen_flush_cc_op(DisasContext *s)
-{
-if (s->cc_op != CC_OP_DYNAMIC)
-tcg_gen_movi_i32(QREG_CC_OP, s->cc_op);
-}
-
 /* Evaluate all the CC flags.  */
+
 static inline void gen_flush_flags(DisasContext *s)
 {
 if (s->cc_op == CC_OP_FLAGS)
 return;
-gen_flush_cc_op(s);
-gen_helper_flush_flags(QREG_CC_DEST, cpu_env, QREG_CC_OP);
-s->cc_op = CC_OP_FLAGS;
+if (s->cc_op == CC_OP_DYNAMIC) {
+gen_helper_flush_flags(QREG_CC_DEST, cpu_env, QREG_CC_OP);
+} else {
+gen_helper_flush_flags(QREG_CC_DEST, cpu_env, tcg_const_i32(s->cc_op));
+}
+set_cc_op(s, CC_OP_FLAGS);
 }
 
 #define SET_CC_OP(opsize, op) do { \
 switch (opsize) { \
 case OS_BYTE: \
-s->cc_op = CC_OP_##op##B; break; \
+set_cc_op(s, CC_OP_##op##B); break; \
 case OS_WORD: \
-s->cc_op = CC_OP_##op##W; break; \
+set_cc_op(s, CC_OP_##op##W); break; \
 case OS_LONG: \
-s->cc_op = CC_OP_##op; break; \
+set_cc_op(s, CC_OP_##op); break; \
 default: \
 abort(); \
 } \
@@ -716,7 +760,7 @@ static void gen_jmpcc(DisasContext *s, int cond, TCGLabel 
*l1)
 /* TODO: Optimize compare/branch pairs rather than always flushing
flag state to CC_OP_FLAGS.  */
 gen_flush_flags(s);
-gen_flush_cc_op(s);
+update_cc_op(s);
 switch (cond) {
 case 0: /* T */
 tcg_gen_br(l1);
@@ -833,7 +877,7 @@ DISAS_INSN(scc)
 /* Force a TB lookup after an instruction that changes the CPU state.  */
 static void gen_lookup_tb(DisasContext *s)
 {
-gen_flush_cc_op(s);
+update_cc_op(s);
 tcg_gen_movi_i32(QREG_PC, s->pc);
 s->is_jmp = DISAS_UPDATE;
 }
@@ -841,7 +885,7 @@ static void gen_lookup_tb(DisasContext *s)
 /* Generate a jump to an immediate