From: Laurent Vivier <laur...@vivier.eu> Signed-off-by: Laurent Vivier <laur...@vivier.eu> --- target-m68k/helper.c | 49 ++++++++++++++++++++++++++++++++++++++++++---- target-m68k/helpers.h | 3 ++ target-m68k/translate.c | 36 ++++++++++++++++++++++++++++----- 3 files changed, 77 insertions(+), 11 deletions(-)
diff --git a/target-m68k/helper.c b/target-m68k/helper.c index 8bf4920..bdfe9aa 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -327,8 +327,7 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op) #define SET_FLAGS_SHIFT(type) do { \ SET_NZ(dest, type); \ - if (src) \ - flags |= CCF_C; \ + flags |= src; \ } while(0) flags = 0; @@ -751,7 +750,7 @@ uint32_t HELPER(glue(glue(shl, bits),_cc))(CPUState *env, uint32_t val, uint32_t result = 0; \ cf = 0; \ } \ - env->cc_src = cf; \ + env->cc_src = cf ? CCF_C : 0; \ if (shift) env->cc_x = (cf != 0); \ env->cc_dest = result; \ return result; \ @@ -780,7 +779,7 @@ uint32_t HELPER(glue(glue(shr, bits), _cc))(CPUState *env, uint32_t val, uint32_ result = 0; \ cf = 0; \ } \ - env->cc_src = cf; \ + env->cc_src = cf ? CCF_C : 0; \ if (shift) env->cc_x = (cf != 0); \ env->cc_dest = result; \ return result; \ @@ -790,6 +789,46 @@ HELPER_SHR(uint8_t, 8) HELPER_SHR(uint16_t, 16) HELPER_SHR(uint32_t, 32) +#define HELPER_SAL(type, bits) \ +uint32_t HELPER(glue(glue(sal, bits),_cc))(CPUState *env, uint32_t val, uint32_t shift) \ +{ \ + type result; \ + uint32_t cf; \ + uint32_t vf; \ + uint32_t m; \ + shift &= 63; \ + if (shift == 0) { \ + vf = 0; \ + } else if (shift < bits) { \ + m = ((1llu << (shift + 1)) - 1) << (bits - shift - 1); \ + vf = (val & m) != m && (val & m) != 0; \ + } else {\ + m = (1llu << bits) - 1; \ + vf = (val & m) != 0; \ + }\ + if (shift == 0) { \ + result = (type)val; \ + cf = env->cc_src & CCF_C; \ + } else if (shift < bits) { \ + result = (type)val << shift; \ + cf = ((type)val >> (bits - shift)) & 1; \ + } else if (shift == bits) { \ + result = 0; \ + cf = val & 1; \ + } else /* shift > bits */ { \ + result = 0; \ + cf = 0; \ + } \ + env->cc_src = (cf ? CCF_C : 0) | (vf ? CCF_V : 0); \ + if (shift) env->cc_x = (cf != 0); \ + env->cc_dest = result; \ + return result; \ +} + +HELPER_SAL(int8_t, 8) +HELPER_SAL(int16_t, 16) +HELPER_SAL(int32_t, 32) + #define HELPER_SAR(type, bits) \ uint32_t HELPER(glue(glue(sar, bits), _cc))(CPUState *env, uint32_t val, uint32_t shift) \ { \ @@ -806,7 +845,7 @@ uint32_t HELPER(glue(glue(sar, bits), _cc))(CPUState *env, uint32_t val, uint32_ result = (type)val >> (bits - 1); \ cf = (type)val >> (bits - 1); \ } \ - env->cc_src = cf; \ + env->cc_src = cf ? CCF_C : 0; \ if (shift) env->cc_x = (cf != 0); \ env->cc_dest = result; \ return result; \ diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h index 8f6d333..aa835eb 100644 --- a/target-m68k/helpers.h +++ b/target-m68k/helpers.h @@ -26,6 +26,9 @@ DEF_HELPER_3(shl32_cc, i32, env, i32, i32) DEF_HELPER_3(shr8_cc, i32, env, i32, i32) DEF_HELPER_3(shr16_cc, i32, env, i32, i32) DEF_HELPER_3(shr32_cc, i32, env, i32, i32) +DEF_HELPER_3(sal8_cc, i32, env, i32, i32) +DEF_HELPER_3(sal16_cc, i32, env, i32, i32) +DEF_HELPER_3(sal32_cc, i32, env, i32, i32) DEF_HELPER_3(sar8_cc, i32, env, i32, i32) DEF_HELPER_3(sar16_cc, i32, env, i32, i32) DEF_HELPER_3(sar32_cc, i32, env, i32, i32) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index bc1cf04..37ee841 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2298,7 +2298,11 @@ DISAS_INSN(shift8_im) dest = tcg_temp_new_i32(); /* No need to flush flags becuse we know we will set C flag. */ if (insn & 0x100) { - gen_helper_shl8_cc(dest, cpu_env, reg, shift); + if (insn & 8) { + gen_helper_shl8_cc(dest, cpu_env, reg, shift); + } else { + gen_helper_sal8_cc(dest, cpu_env, reg, shift); + } } else { if (insn & 8) { gen_helper_shr8_cc(dest, cpu_env, reg, shift); @@ -2326,7 +2330,11 @@ DISAS_INSN(shift16_im) dest = tcg_temp_new_i32(); /* No need to flush flags becuse we know we will set C flag. */ if (insn & 0x100) { - gen_helper_shl16_cc(dest, cpu_env, reg, shift); + if (insn & 8) { + gen_helper_shl16_cc(dest, cpu_env, reg, shift); + } else { + gen_helper_sal16_cc(dest, cpu_env, reg, shift); + } } else { if (insn & 8) { gen_helper_shr16_cc(dest, cpu_env, reg, shift); @@ -2353,7 +2361,11 @@ DISAS_INSN(shift_im) shift = tcg_const_i32(tmp); /* No need to flush flags becuse we know we will set C flag. */ if (insn & 0x100) { - gen_helper_shl32_cc(reg, cpu_env, reg, shift); + if (insn & 8) { + gen_helper_shl32_cc(reg, cpu_env, reg, shift); + } else { + gen_helper_sal32_cc(reg, cpu_env, reg, shift); + } } else { if (insn & 8) { gen_helper_shr32_cc(reg, cpu_env, reg, shift); @@ -2379,7 +2391,11 @@ DISAS_INSN(shift8_reg) /* Shift by zero leaves C flag unmodified. */ gen_flush_flags(s); if (insn & 0x100) { - gen_helper_shl8_cc(dest, cpu_env, reg, tmp); + if (insn & 8) { + gen_helper_shl8_cc(dest, cpu_env, reg, tmp); + } else { + gen_helper_sal8_cc(dest, cpu_env, reg, tmp); + } } else { if (insn & 8) { gen_helper_shr8_cc(dest, cpu_env, reg, tmp); @@ -2406,7 +2422,11 @@ DISAS_INSN(shift16_reg) /* Shift by zero leaves C flag unmodified. */ gen_flush_flags(s); if (insn & 0x100) { - gen_helper_shl16_cc(dest, cpu_env, reg, tmp); + if (insn & 8) { + gen_helper_shl16_cc(dest, cpu_env, reg, tmp); + } else { + gen_helper_sal16_cc(dest, cpu_env, reg, tmp); + } } else { if (insn & 8) { gen_helper_shr16_cc(dest, cpu_env, reg, tmp); @@ -2428,7 +2448,11 @@ DISAS_INSN(shift_reg) /* Shift by zero leaves C flag unmodified. */ gen_flush_flags(s); if (insn & 0x100) { - gen_helper_shl32_cc(reg, cpu_env, reg, shift); + if (insn & 8) { + gen_helper_shl32_cc(reg, cpu_env, reg, shift); + } else { + gen_helper_sal32_cc(reg, cpu_env, reg, shift); + } } else { if (insn & 8) { gen_helper_shr32_cc(reg, cpu_env, reg, shift); -- 1.7.2.3