Signed-off-by: Laurent Vivier <laur...@vivier.eu> --- target-m68k/translate.c | 95 ++++++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 37 deletions(-)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 6a426e1..9e379b3 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -1343,6 +1343,42 @@ DISAS_INSN(bitop_im) DEST_EA(env, insn, opsize, tmp, &addr); } } + +static TCGv gen_get_ccr(DisasContext *s) +{ + TCGv dest; + + gen_flush_flags(s); + dest = tcg_temp_new(); + tcg_gen_shli_i32(dest, QREG_CC_X, 4); + tcg_gen_or_i32(dest, dest, QREG_CC_DEST); + return dest; +} + +static TCGv gen_get_sr(DisasContext *s) +{ + TCGv ccr; + TCGv sr; + + ccr = gen_get_ccr(s); + sr = tcg_temp_new(); + tcg_gen_andi_i32(sr, QREG_SR, 0xffe0); + tcg_gen_or_i32(sr, sr, ccr); + return sr; +} + +static void gen_set_sr(DisasContext *s, TCGv val, int ccr_only) +{ + TCGv tmp; + tmp = tcg_temp_new(); + tcg_gen_andi_i32(QREG_CC_DEST, val, 0xf); + tcg_gen_shri_i32(tmp, val, 4); + tcg_gen_andi_i32(QREG_CC_X, tmp, 1); + if (!ccr_only) { + gen_helper_set_sr(cpu_env, val); + } +} + DISAS_INSN(arith_im) { int op; @@ -1367,7 +1403,20 @@ DISAS_INSN(arith_im) default: abort(); } - SRC_EA(env, src1, opsize, -1, (op == 6) ? NULL : &addr); + if ((op == 0 || op == 1) && + (insn & 0x3f) == 0x3c) { + if (opsize == OS_BYTE) { + src1 = gen_get_ccr(s); + } else { + if (IS_USER(s)) { + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE); + return; + } + src1 = gen_get_sr(s); + } + } else { + SRC_EA(env, src1, opsize, -1, (op == 6) ? NULL : &addr); + } dest = tcg_temp_new(); switch (op) { case 0: /* ori */ @@ -1405,7 +1454,14 @@ DISAS_INSN(arith_im) default: abort(); } - DEST_EA(env, insn, opsize, dest, &addr); + if (op != 6) { + if ((op == 0 || op == 1) && + (insn & 0x3f) == 0x3c) { + gen_set_sr(s, dest, opsize == OS_BYTE); + } else { + DEST_EA(env, insn, opsize, dest, &addr); + } + } } DISAS_INSN(byterev) @@ -1488,17 +1544,6 @@ DISAS_INSN(clr) gen_logic_cc(s, zero, opsize); } -static TCGv gen_get_ccr(DisasContext *s) -{ - TCGv dest; - - gen_flush_flags(s); - dest = tcg_temp_new(); - tcg_gen_shli_i32(dest, QREG_CC_X, 4); - tcg_gen_or_i32(dest, dest, QREG_CC_DEST); - return dest; -} - DISAS_INSN(move_from_ccr) { TCGv reg; @@ -1536,18 +1581,6 @@ static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only) set_cc_op(s, CC_OP_FLAGS); } -static void gen_set_sr(DisasContext *s, TCGv val, int ccr_only) -{ - TCGv tmp; - tmp = tcg_temp_new(); - tcg_gen_andi_i32(QREG_CC_DEST, val, 0xf); - tcg_gen_shri_i32(tmp, val, 4); - tcg_gen_andi_i32(QREG_CC_X, tmp, 1); - if (!ccr_only) { - gen_helper_set_sr(cpu_env, val); - } -} - static void gen_move_to_sr(CPUM68KState *env, DisasContext *s, uint16_t insn, int ccr_only) { @@ -2068,18 +2101,6 @@ DISAS_INSN(ff1) gen_helper_ff1(reg, reg); } -static TCGv gen_get_sr(DisasContext *s) -{ - TCGv ccr; - TCGv sr; - - ccr = gen_get_ccr(s); - sr = tcg_temp_new(); - tcg_gen_andi_i32(sr, QREG_SR, 0xffe0); - tcg_gen_or_i32(sr, sr, ccr); - return sr; -} - DISAS_INSN(strldsr) { uint16_t ext; -- 2.4.3