From: Laurent Vivier <laur...@vivier.eu> This patch defines shift8_im, shift16_im, shift8_reg, shift16_reg, shift_mem and attach them to M68000 feature.
Signed-off-by: Andreas Schwab <sch...@linux-m68k.org> Signed-off-by: Laurent Vivier <laur...@vivier.eu> --- target-m68k/cpu.h | 2 + target-m68k/helper.c | 160 +++++++++++++++++++++++++++-------------------- target-m68k/helpers.h | 12 +++- target-m68k/translate.c | 155 +++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 249 insertions(+), 80 deletions(-) diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index ff57564..91d3141 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -147,6 +147,8 @@ enum { CC_OP_SUBXB, /* CC_DEST = result, CC_SRC = source */ CC_OP_SUBXW, /* CC_DEST = result, CC_SRC = source */ CC_OP_SUBX, /* CC_DEST = result, CC_SRC = source */ + 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 */ }; diff --git a/target-m68k/helper.c b/target-m68k/helper.c index dd9079f..0025ab5 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -287,6 +287,12 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op) flags |= CCF_V; \ } while (0) +#define SET_FLAGS_SHIFT(type) do { \ + SET_NZ((type)dest); \ + if (src) \ + flags |= CCF_C; \ + } while(0) + flags = 0; src = env->cc_src; dest = env->cc_dest; @@ -333,10 +339,14 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op) case CC_OP_SUBX: SET_FLAGS_SUBX(int32_t, uint32_t); break; + case CC_OP_SHIFTB: + SET_FLAGS_SHIFT(int8_t); + break; + case CC_OP_SHIFTW: + SET_FLAGS_SHIFT(int16_t); + break; case CC_OP_SHIFT: - SET_NZ(dest); - if (src) - flags |= CCF_C; + SET_FLAGS_SHIFT(int32_t); break; default: cpu_abort(env, "Bad CC_OP %d", cc_op); @@ -538,77 +548,89 @@ void HELPER(set_sr)(CPUState *env, uint32_t val) m68k_switch_sp(env); } -uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift) -{ - uint32_t result; - uint32_t cf; - - shift &= 63; - if (shift == 0) { - result = val; - cf = env->cc_src & CCF_C; - } else if (shift < 32) { - result = val << shift; - cf = (val >> (32 - shift)) & 1; - } else if (shift == 32) { - result = 0; - cf = val & 1; - } else /* shift > 32 */ { - result = 0; - cf = 0; - } - env->cc_src = cf; - env->cc_x = (cf != 0); - env->cc_dest = result; - return result; -} - -uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift) -{ - uint32_t result; - uint32_t cf; - - shift &= 63; - if (shift == 0) { - result = val; - cf = env->cc_src & CCF_C; - } else if (shift < 32) { - result = val >> shift; - cf = (val >> (shift - 1)) & 1; - } else if (shift == 32) { - result = 0; - cf = val >> 31; - } else /* shift > 32 */ { - result = 0; - cf = 0; - } - env->cc_src = cf; - env->cc_x = (cf != 0); - env->cc_dest = result; - return result; -} - -uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift) -{ - uint32_t result; - uint32_t cf; - - shift &= 63; - if (shift == 0) { - result = val; - cf = (env->cc_src & CCF_C) != 0; - } else if (shift < 32) { - result = (int32_t)val >> shift; - cf = (val >> (shift - 1)) & 1; - } else /* shift >= 32 */ { - result = (int32_t)val >> 31; - cf = val >> 31; - } - env->cc_src = cf; - env->cc_x = cf; - env->cc_dest = result; - return result; -} +#define HELPER_SHL(type, bits) \ +uint32_t HELPER(glue(glue(shl, bits),_cc))(CPUState *env, uint32_t val, uint32_t shift) \ +{ \ + type result; \ + uint32_t cf; \ + shift &= 63; \ + 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; \ + env->cc_x = (cf != 0); \ + env->cc_dest = result; \ + return result; \ +} + +HELPER_SHL(uint8_t, 8) +HELPER_SHL(uint16_t, 16) +HELPER_SHL(uint32_t, 32) + +#define HELPER_SHR(type, bits) \ +uint32_t HELPER(glue(glue(shr, bits), _cc))(CPUState *env, uint32_t val, uint32_t shift) \ +{ \ + type result; \ + uint32_t cf; \ + shift &= 63; \ + if (shift == 0) { \ + result = (type)val; \ + cf = env->cc_src & CCF_C; \ + } else if (shift < bits) { \ + result = (type)val >> shift; \ + cf = ((type)val >> (shift - 1)) & 1; \ + } else if (shift == bits) { \ + result = 0; \ + cf = (type)val >> (bits - 1); \ + } else /* shift > bits */ { \ + result = 0; \ + cf = 0; \ + } \ + env->cc_src = cf; \ + env->cc_x = (cf != 0); \ + env->cc_dest = result; \ + return result; \ +} + +HELPER_SHR(uint8_t, 8) +HELPER_SHR(uint16_t, 16) +HELPER_SHR(uint32_t, 32) + +#define HELPER_SAR(type, bits) \ +uint32_t HELPER(glue(glue(sar, bits), _cc))(CPUState *env, uint32_t val, uint32_t shift) \ +{ \ + type result; \ + uint32_t cf; \ + shift &= 63; \ + if (shift == 0) { \ + result = (type)val; \ + cf = (env->cc_src & CCF_C) != 0; \ + } else if (shift < bits) { \ + result = (type)val >> shift; \ + cf = ((type)val >> (shift - 1)) & 1; \ + } else /* shift >= bits */ { \ + result = (type)val >> (bits - 1); \ + cf = (type)val >> (bits - 1); \ + } \ + env->cc_src = cf; \ + env->cc_x = cf; \ + env->cc_dest = result; \ + return result; \ +} + +HELPER_SAR(int8_t, 8) +HELPER_SAR(int16_t, 16) +HELPER_SAR(int32_t, 32) /* FPU helpers. */ uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val) diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h index ca2bf82..d1993ab 100644 --- a/target-m68k/helpers.h +++ b/target-m68k/helpers.h @@ -13,9 +13,15 @@ DEF_HELPER_3(mulu64, i32, env, i32, i32) DEF_HELPER_3(muls64, i32, env, i32, i32) DEF_HELPER_3(addx_cc, i32, env, i32, i32) DEF_HELPER_3(subx_cc, i32, env, i32, i32) -DEF_HELPER_3(shl_cc, i32, env, i32, i32) -DEF_HELPER_3(shr_cc, i32, env, i32, i32) -DEF_HELPER_3(sar_cc, i32, env, i32, i32) +DEF_HELPER_3(shl8_cc, i32, env, i32, i32) +DEF_HELPER_3(shl16_cc, i32, env, i32, i32) +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(sar8_cc, i32, env, i32, i32) +DEF_HELPER_3(sar16_cc, i32, env, i32, i32) +DEF_HELPER_3(sar32_cc, i32, env, i32, i32) DEF_HELPER_2(xflag_lt, i32, i32, i32) DEF_HELPER_2(set_sr, void, env, i32) DEF_HELPER_3(movec, void, env, i32, i32) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 8fb71b8..ecbd516 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2009,6 +2009,63 @@ DISAS_INSN(addx) } /* TODO: This could be implemented without helper functions. */ +DISAS_INSN(shift8_im) +{ + TCGv reg; + int tmp; + TCGv shift; + TCGv dest; + + reg = DREG(insn, 0); + tmp = (insn >> 9) & 7; + if (tmp == 0) + tmp = 8; + shift = tcg_const_i32(tmp); + 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); + } else { + if (insn & 8) { + gen_helper_shr8_cc(dest, cpu_env, reg, shift); + } else { + gen_helper_sar8_cc(dest, cpu_env, reg, shift); + } + } + s->cc_op = CC_OP_SHIFTB; + gen_partset_reg(OS_BYTE, reg, dest); +} + +/* TODO: This could be implemented without helper functions. */ +DISAS_INSN(shift16_im) +{ + TCGv reg; + int tmp; + TCGv shift; + TCGv dest; + + reg = DREG(insn, 0); + tmp = (insn >> 9) & 7; + if (tmp == 0) + tmp = 8; + shift = tcg_const_i32(tmp); + 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); + } else { + if (insn & 8) { + gen_helper_shr16_cc(dest, cpu_env, reg, shift); + } else { + gen_helper_sar16_cc(dest, cpu_env, reg, shift); + } + } + s->cc_op = CC_OP_SHIFTW; + gen_partset_reg(OS_WORD, reg, dest); +} + + +/* TODO: This could be implemented without helper functions. */ DISAS_INSN(shift_im) { TCGv reg; @@ -2022,17 +2079,71 @@ 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_shl_cc(reg, cpu_env, reg, shift); + gen_helper_shl32_cc(reg, cpu_env, reg, shift); } else { if (insn & 8) { - gen_helper_shr_cc(reg, cpu_env, reg, shift); + gen_helper_shr32_cc(reg, cpu_env, reg, shift); } else { - gen_helper_sar_cc(reg, cpu_env, reg, shift); + gen_helper_sar32_cc(reg, cpu_env, reg, shift); } } s->cc_op = CC_OP_SHIFT; } +DISAS_INSN(shift8_reg) +{ + TCGv reg; + TCGv shift; + TCGv dest; + TCGv tmp; + + reg = DREG(insn, 0); + shift = DREG(insn, 9); + tmp = tcg_temp_new_i32(); + tcg_gen_andi_i32(tmp, shift, 63); + dest = tcg_temp_new_i32(); + /* Shift by zero leaves C flag unmodified. */ + gen_flush_flags(s); + if (insn & 0x100) { + gen_helper_shl8_cc(dest, cpu_env, reg, tmp); + } else { + if (insn & 8) { + gen_helper_shr8_cc(dest, cpu_env, reg, tmp); + } else { + gen_helper_sar8_cc(dest, cpu_env, reg, tmp); + } + } + s->cc_op = CC_OP_SHIFTB; + gen_partset_reg(OS_BYTE, reg, dest); +} + +DISAS_INSN(shift16_reg) +{ + TCGv reg; + TCGv shift; + TCGv dest; + TCGv tmp; + + reg = DREG(insn, 0); + shift = DREG(insn, 9); + tmp = tcg_temp_new_i32(); + tcg_gen_andi_i32(tmp, shift, 63); + dest = tcg_temp_new_i32(); + /* Shift by zero leaves C flag unmodified. */ + gen_flush_flags(s); + if (insn & 0x100) { + gen_helper_shl16_cc(dest, cpu_env, reg, tmp); + } else { + if (insn & 8) { + gen_helper_shr16_cc(dest, cpu_env, reg, tmp); + } else { + gen_helper_sar16_cc(dest, cpu_env, reg, tmp); + } + } + s->cc_op = CC_OP_SHIFTW; + gen_partset_reg(OS_WORD, reg, dest); +} + DISAS_INSN(shift_reg) { TCGv reg; @@ -2043,17 +2154,40 @@ DISAS_INSN(shift_reg) /* Shift by zero leaves C flag unmodified. */ gen_flush_flags(s); if (insn & 0x100) { - gen_helper_shl_cc(reg, cpu_env, reg, shift); + gen_helper_shl32_cc(reg, cpu_env, reg, shift); } else { if (insn & 8) { - gen_helper_shr_cc(reg, cpu_env, reg, shift); + gen_helper_shr32_cc(reg, cpu_env, reg, shift); } else { - gen_helper_sar_cc(reg, cpu_env, reg, shift); + gen_helper_sar32_cc(reg, cpu_env, reg, shift); } } s->cc_op = CC_OP_SHIFT; } +DISAS_INSN(shift_mem) +{ + TCGv src; + TCGv dest; + TCGv addr; + TCGv shift; + + SRC_EA(src, OS_WORD, 0, &addr); + dest = tcg_temp_new_i32(); + shift = tcg_const_i32(1); + if (insn & 0x100) { + gen_helper_shl16_cc(dest, cpu_env, src, shift); + } else { + if (insn & 8) { + gen_helper_shr16_cc(dest, cpu_env, src, shift); + } else { + gen_helper_sar16_cc(dest, cpu_env, src, shift); + } + } + s->cc_op = CC_OP_SHIFTW; + DEST_EA(insn, OS_WORD, dest, &addr); +} + DISAS_INSN(ff1) { TCGv reg; @@ -3182,8 +3316,13 @@ void register_m68k_insns (CPUM68KState *env) INSN(adda, d0c0, f0c0, M68000); INSN(shift_im, e080, f0f0, CF_ISA_A); INSN(shift_reg, e0a0, f0f0, CF_ISA_A); - INSN(shift_im, e080, f0f0, M68000); - INSN(shift_reg, e0a0, f0f0, M68000); + INSN(shift8_im, e000, f0f0, M68000); + INSN(shift16_im, e040, f0f0, M68000); + INSN(shift_im, e080, f0f0, M68000); + INSN(shift8_reg, e020, f0f0, M68000); + INSN(shift16_reg, e060, f0f0, M68000); + INSN(shift_reg, e0a0, f0f0, M68000); + INSN(shift_mem, e0c0, fcc0, M68000); INSN(undef_fpu, f000, f000, CF_ISA_A); INSN(undef_fpu, f000, f000, M68000); INSN(fpu, f200, ffc0, CF_FPU); -- 1.7.2.3