diff options
author | Laurent Vivier <laurent@vivier.eu> | 2018-01-04 02:29:03 +0100 |
---|---|---|
committer | Laurent Vivier <laurent@vivier.eu> | 2018-01-04 17:24:31 +0100 |
commit | 8bf6cbaf396a8b54b138bb8a7c3377f2868ed16e (patch) | |
tree | a7481fbfb122a9821aff78d409753ad719876644 /target/m68k/translate.c | |
parent | d2f8fb8e7f8e7d082103d705e178c9f72e0bea77 (diff) |
target/m68k: add chk and chk2
chk and chk2 compare a value to boundaries, and
trigger a CHK exception if the value is out of bounds.
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20180104012913.30763-8-laurent@vivier.eu>
Diffstat (limited to 'target/m68k/translate.c')
-rw-r--r-- | target/m68k/translate.c | 77 |
1 files changed, 76 insertions, 1 deletions
diff --git a/target/m68k/translate.c b/target/m68k/translate.c index a1e424e3db..7f52065375 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -4203,6 +4203,80 @@ DISAS_INSN(ff1) gen_helper_ff1(reg, reg); } +DISAS_INSN(chk) +{ + TCGv src, reg; + int opsize; + + switch ((insn >> 7) & 3) { + case 3: + opsize = OS_WORD; + break; + case 2: + if (m68k_feature(env, M68K_FEATURE_CHK2)) { + opsize = OS_LONG; + break; + } + /* fallthru */ + default: + gen_exception(s, s->insn_pc, EXCP_ILLEGAL); + return; + } + SRC_EA(env, src, opsize, 1, NULL); + reg = gen_extend(DREG(insn, 9), opsize, 1); + + gen_flush_flags(s); + gen_helper_chk(cpu_env, reg, src); +} + +DISAS_INSN(chk2) +{ + uint16_t ext; + TCGv addr1, addr2, bound1, bound2, reg; + int opsize; + + switch ((insn >> 9) & 3) { + case 0: + opsize = OS_BYTE; + break; + case 1: + opsize = OS_WORD; + break; + case 2: + opsize = OS_LONG; + break; + default: + gen_exception(s, s->insn_pc, EXCP_ILLEGAL); + return; + } + + ext = read_im16(env, s); + if ((ext & 0x0800) == 0) { + gen_exception(s, s->insn_pc, EXCP_ILLEGAL); + return; + } + + addr1 = gen_lea(env, s, insn, OS_UNSIZED); + addr2 = tcg_temp_new(); + tcg_gen_addi_i32(addr2, addr1, opsize_bytes(opsize)); + + bound1 = gen_load(s, opsize, addr1, 1); + tcg_temp_free(addr1); + bound2 = gen_load(s, opsize, addr2, 1); + tcg_temp_free(addr2); + + reg = tcg_temp_new(); + if (ext & 0x8000) { + tcg_gen_mov_i32(reg, AREG(ext, 12)); + } else { + gen_ext(reg, DREG(ext, 12), opsize, 1); + } + + gen_flush_flags(s); + gen_helper_chk2(cpu_env, reg, bound1, bound2); + tcg_temp_free(reg); +} + static TCGv gen_get_sr(DisasContext *s) { TCGv ccr; @@ -5306,7 +5380,7 @@ void register_m68k_insns (CPUM68KState *env) BASE(undef, 0000, 0000); INSN(arith_im, 0080, fff8, CF_ISA_A); INSN(arith_im, 0000, ff00, M68000); - INSN(undef, 00c0, ffc0, M68000); + INSN(chk2, 00c0, f9c0, CHK2); INSN(bitrev, 00c0, fff8, CF_ISA_APLUSC); BASE(bitop_reg, 0100, f1c0); BASE(bitop_reg, 0140, f1c0); @@ -5339,6 +5413,7 @@ void register_m68k_insns (CPUM68KState *env) BASE(move, 1000, f000); BASE(move, 2000, f000); BASE(move, 3000, f000); + INSN(chk, 4000, f040, M68000); INSN(strldsr, 40e7, ffff, CF_ISA_APLUSC); INSN(negx, 4080, fff8, CF_ISA_A); INSN(negx, 4000, ff00, M68000); |