From: Laurent Vivier <laur...@vivier.eu> Add support for all opsize (byte, word) instead of only long. On 680x0, don't clear/modify the X flag.
Signed-off-by: Laurent Vivier <laur...@vivier.eu> --- target-m68k/cpu.h | 2 + target-m68k/helper.c | 31 +++++++++++++++------ target-m68k/translate.c | 70 +++++++++++++++++++++++------------------------ 3 files changed, 58 insertions(+), 45 deletions(-) diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index ae4f6fa..0d5e3d3 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -134,6 +134,8 @@ void cpu_m68k_flush_flags(CPUM68KState *, int); 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 */ + CC_OP_LOGICW, /* CC_DEST = result, CC_SRC = unused */ CC_OP_LOGIC, /* CC_DEST = result, CC_SRC = unused */ CC_OP_ADDB, /* CC_DEST = result, CC_SRC = source */ CC_OP_ADDW, /* CC_DEST = result, CC_SRC = source */ diff --git a/target-m68k/helper.c b/target-m68k/helper.c index 914147a..dfa7c10 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -282,15 +282,15 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op) #define HIGHBIT(type) (1u << (sizeof(type) * 8 - 1)) -#define SET_NZ(x) do { \ - if ((x) == 0) \ +#define SET_NZ(x, type) do { \ + if ((type)(x) == 0) \ flags |= CCF_Z; \ - else if ((int32_t)(x) < 0) \ + else if ((type)(x) < 0) \ flags |= CCF_N; \ } while (0) #define SET_FLAGS_SUB(type, utype) do { \ - SET_NZ((type)dest); \ + SET_NZ(dest, type); \ tmp = dest + src; \ if ((utype) tmp < (utype) src) \ flags |= CCF_C; \ @@ -299,7 +299,7 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op) } while (0) #define SET_FLAGS_ADD(type, utype) do { \ - SET_NZ((type)dest); \ + SET_NZ(dest, type); \ if ((utype) dest < (utype) src) \ flags |= CCF_C; \ tmp = dest - src; \ @@ -308,7 +308,7 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op) } while (0) #define SET_FLAGS_ADDX(type, utype) do { \ - SET_NZ((type)dest); \ + SET_NZ(dest, type); \ if ((utype) dest <= (utype) src) \ flags |= CCF_C; \ tmp = dest - src - 1; \ @@ -317,7 +317,7 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op) } while (0) #define SET_FLAGS_SUBX(type, utype) do { \ - SET_NZ((type)dest); \ + SET_NZ(dest, type); \ tmp = dest + src + 1; \ if ((utype) tmp <= (utype) src) \ flags |= CCF_C; \ @@ -326,7 +326,7 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op) } while (0) #define SET_FLAGS_SHIFT(type) do { \ - SET_NZ((type)dest); \ + SET_NZ(dest, type); \ if (src) \ flags |= CCF_C; \ } while(0) @@ -338,8 +338,21 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op) case CC_OP_FLAGS: flags = dest; break; + case CC_OP_LOGICB: + SET_NZ(dest, int8_t); + goto set_x; + break; + case CC_OP_LOGICW: + SET_NZ(dest, int16_t); + goto set_x; + break; case CC_OP_LOGIC: - SET_NZ(dest); + SET_NZ(dest, int32_t); +set_x: + if (env->cc_x && m68k_feature(env, M68K_FEATURE_M68000)) { + /* Unlike m68k, coldfire always clears the overflow bit. */ + flags |= CCF_X; + } break; case CC_OP_ADDB: SET_FLAGS_ADD(int8_t, uint8_t); diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 3ce5f53..cad2e26 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -431,10 +431,19 @@ static inline void gen_flush_flags(DisasContext *s) s->cc_op = CC_OP_FLAGS; } -static void gen_logic_cc(DisasContext *s, TCGv val) +#define SET_CC_OP(opsize, op) do { \ + switch (opsize) { \ + case OS_BYTE: s->cc_op = CC_OP_##op##B; break; \ + case OS_WORD: s->cc_op = CC_OP_##op##W; break; \ + case OS_LONG: s->cc_op = CC_OP_##op; break; \ + default: abort(); \ + } \ +} while (0) + +static void gen_logic_cc(DisasContext *s, TCGv val, int opsize) { tcg_gen_mov_i32(QREG_CC_DEST, val); - s->cc_op = CC_OP_LOGIC; + SET_CC_OP(opsize, LOGIC); } static void gen_update_cc_add(TCGv dest, TCGv src) @@ -467,15 +476,6 @@ static inline int insn_opsize(int insn, int pos) } } -#define SET_CC_OP(opsize, op) do { \ - switch (opsize) { \ - case OS_BYTE: s->cc_op = CC_OP_##op##B; break; \ - case OS_WORD: s->cc_op = CC_OP_##op##W; break; \ - case OS_LONG: s->cc_op = CC_OP_##op; break; \ - default: abort(); \ - } \ -} while (0) - /* Assign value to a register. If the width is less than the register width only the low part of the register is set. */ static void gen_partset_reg(int opsize, TCGv reg, TCGv val) @@ -980,8 +980,7 @@ DISAS_INSN(mulw) SRC_EA(src, OS_WORD, sign, NULL); tcg_gen_mul_i32(tmp, tmp, src); tcg_gen_mov_i32(reg, tmp); - /* Unlike m68k, coldfire always clears the overflow bit. */ - gen_logic_cc(s, tmp); + gen_logic_cc(s, tmp, OS_WORD); } DISAS_INSN(divw) @@ -1172,7 +1171,7 @@ DISAS_INSN(sats) reg = DREG(insn, 0); gen_flush_flags(s); gen_helper_sats(reg, reg, QREG_CC_DEST); - gen_logic_cc(s, reg); + gen_logic_cc(s, reg, OS_LONG); } static void gen_push(DisasContext *s, TCGv val) @@ -1334,11 +1333,11 @@ DISAS_INSN(arith_im) switch (op) { case 0: /* ori */ tcg_gen_ori_i32(dest, src1, im); - gen_logic_cc(s, dest); + gen_logic_cc(s, dest, opsize); break; case 1: /* andi */ tcg_gen_andi_i32(dest, src1, im); - gen_logic_cc(s, dest); + gen_logic_cc(s, dest, opsize); break; case 2: /* subi */ tcg_gen_mov_i32(dest, src1); @@ -1356,7 +1355,7 @@ DISAS_INSN(arith_im) break; case 5: /* eori */ tcg_gen_xori_i32(dest, src1, im); - gen_logic_cc(s, dest); + gen_logic_cc(s, dest, opsize); break; case 6: /* cmpi */ tcg_gen_mov_i32(dest, src1); @@ -1422,7 +1421,7 @@ DISAS_INSN(cas) res = tcg_temp_new(); tcg_gen_sub_i32(res, dest, cmp); - gen_logic_cc(s, res); + gen_logic_cc(s, res, opsize); l1 = gen_new_label(); l2 = gen_new_label(); @@ -1478,7 +1477,7 @@ DISAS_INSN(move) dest_ea = ((insn >> 9) & 7) | (op << 3); DEST_EA(dest_ea, opsize, src, NULL); /* This will be correct because loads sign extend. */ - gen_logic_cc(s, src); + gen_logic_cc(s, src, opsize); } } @@ -1511,7 +1510,7 @@ DISAS_INSN(clr) opsize = insn_opsize(insn, 6); DEST_EA(insn, opsize, tcg_const_i32(0), NULL); - gen_logic_cc(s, tcg_const_i32(0)); + gen_logic_cc(s, tcg_const_i32(0), opsize); } static TCGv gen_get_ccr(DisasContext *s) @@ -1607,7 +1606,7 @@ DISAS_INSN(not) dest = tcg_temp_new(); tcg_gen_not_i32(dest, src1); DEST_EA(insn, opsize, dest, &addr); - gen_logic_cc(s, dest); + gen_logic_cc(s, dest, opsize); } DISAS_INSN(swap) @@ -1622,7 +1621,7 @@ DISAS_INSN(swap) tcg_gen_shli_i32(src1, reg, 16); tcg_gen_shri_i32(src2, reg, 16); tcg_gen_or_i32(reg, src1, src2); - gen_logic_cc(s, reg); + gen_logic_cc(s, reg, OS_LONG); } DISAS_INSN(pea) @@ -1654,7 +1653,7 @@ DISAS_INSN(ext) gen_partset_reg(OS_WORD, reg, tmp); else tcg_gen_mov_i32(reg, tmp); - gen_logic_cc(s, tmp); + gen_logic_cc(s, tmp, OS_LONG); } DISAS_INSN(tst) @@ -1664,7 +1663,7 @@ DISAS_INSN(tst) opsize = insn_opsize(insn, 6); SRC_EA(tmp, opsize, -1, NULL); - gen_logic_cc(s, tmp); + gen_logic_cc(s, tmp, opsize); } DISAS_INSN(pulse) @@ -1686,7 +1685,7 @@ DISAS_INSN(tas) dest = tcg_temp_new(); SRC_EA(src1, OS_BYTE, 1, &addr); - gen_logic_cc(s, src1); + gen_logic_cc(s, src1, OS_BYTE); tcg_gen_ori_i32(dest, src1, 0x80); DEST_EA(insn, OS_BYTE, dest, &addr); } @@ -1732,9 +1731,8 @@ DISAS_INSN(mull) s->cc_op = CC_OP_FLAGS; } else { tcg_gen_mul_i32(dest, src1, reg); - /* Unlike m68k, coldfire always clears the overflow bit. */ - gen_logic_cc(s, dest); } + gen_logic_cc(s, dest, OS_LONG); tcg_gen_mov_i32(reg, dest); } @@ -1915,7 +1913,7 @@ DISAS_INSN(moveq) val = (int8_t)insn; tcg_gen_movi_i32(DREG(insn, 9), val); - gen_logic_cc(s, tcg_const_i32(val)); + gen_logic_cc(s, tcg_const_i32(val), OS_LONG); } DISAS_INSN(mvzs) @@ -1931,7 +1929,7 @@ DISAS_INSN(mvzs) SRC_EA(src, opsize, (insn & 0x80) == 0, NULL); reg = DREG(insn, 9); tcg_gen_mov_i32(reg, src); - gen_logic_cc(s, src); + gen_logic_cc(s, src, opsize); } DISAS_INSN(or) @@ -1954,7 +1952,7 @@ DISAS_INSN(or) tcg_gen_or_i32(dest, src, reg); gen_partset_reg(opsize, reg, dest); } - gen_logic_cc(s, dest); + gen_logic_cc(s, dest, opsize); } DISAS_INSN(suba) @@ -1987,7 +1985,7 @@ DISAS_INSN(mov3q) if (val == 0) val = -1; src = tcg_const_i32(val); - gen_logic_cc(s, src); + gen_logic_cc(s, src, OS_LONG); DEST_EA(insn, OS_LONG, src, NULL); } @@ -2040,7 +2038,7 @@ DISAS_INSN(eor) reg = DREG(insn, 9); dest = tcg_temp_new(); tcg_gen_xor_i32(dest, src, reg); - gen_logic_cc(s, dest); + gen_logic_cc(s, dest, opsize); DEST_EA(insn, opsize, dest, &addr); } @@ -2064,7 +2062,7 @@ DISAS_INSN(and) tcg_gen_and_i32(dest, src, reg); gen_partset_reg(opsize, reg, dest); } - gen_logic_cc(s, dest); + gen_logic_cc(s, dest, opsize); } DISAS_INSN(adda) @@ -2530,7 +2528,7 @@ DISAS_INSN(bitfield_reg) tmp1 = tcg_temp_new_i32(); gen_helper_rol32(tmp1, tmp, offset); - gen_logic_cc(s, tmp1); + gen_logic_cc(s, tmp1, OS_LONG); reg2 = DREG(ext, 12); switch (op) { @@ -2599,7 +2597,7 @@ static TCGv gen_bitfield_cc(DisasContext *s, /* compute cc */ tcg_gen_and_i32(dest, dest, mask_cc); - gen_logic_cc(s, dest); + gen_logic_cc(s, dest, OS_LONG); return dest; } @@ -2771,7 +2769,7 @@ DISAS_INSN(ff1) { TCGv reg; reg = DREG(insn, 0); - gen_logic_cc(s, reg); + gen_logic_cc(s, reg, OS_LONG); gen_helper_ff1(reg, reg); } -- 1.7.2.3