From 01150e151ee7496619c61e243e5cc9fa43db6cdb Mon Sep 17 00:00:00 2001 From: Pavel Dovgalyuk Date: Wed, 7 Mar 2018 11:51:26 -0500 Subject: [PATCH] m68k: implement movep instruction This patch implements movep instruction. It moves data between a data register and alternate bytes within the address space starting at the location specified and incrementing by two. It was designed for the original 68000 and used in firmwares for interfacing the 8-bit peripherals through the 16-bit data bus. Without this patch opcode for this instruction is recognized as some bitop. Backports commit 1226e212292e271b8795265c9639d5c0553df199 from qemu --- qemu/target/m68k/cpu.c | 2 ++ qemu/target/m68k/cpu.h | 1 + qemu/target/m68k/translate.c | 47 ++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/qemu/target/m68k/cpu.c b/qemu/target/m68k/cpu.c index 5f4d533e..67f3af55 100644 --- a/qemu/target/m68k/cpu.c +++ b/qemu/target/m68k/cpu.c @@ -107,6 +107,7 @@ static void m68000_cpu_initfn(struct uc_struct *uc, Object *obj, void *opaque) m68k_set_feature(env, M68K_FEATURE_M68000); m68k_set_feature(env, M68K_FEATURE_USP); m68k_set_feature(env, M68K_FEATURE_WORD_INDEX); + m68k_set_feature(env, M68K_FEATURE_MOVEP); } static void m68020_cpu_initfn(struct uc_struct *uc, Object *obj, void *opaque) @@ -129,6 +130,7 @@ static void m68020_cpu_initfn(struct uc_struct *uc, Object *obj, void *opaque) m68k_set_feature(env, M68K_FEATURE_BKPT); m68k_set_feature(env, M68K_FEATURE_RTD); m68k_set_feature(env, M68K_FEATURE_CHK2); + m68k_set_feature(env, M68K_FEATURE_MOVEP); } #define m68030_cpu_initfn m68020_cpu_initfn diff --git a/qemu/target/m68k/cpu.h b/qemu/target/m68k/cpu.h index aef02c5a..731eca75 100644 --- a/qemu/target/m68k/cpu.h +++ b/qemu/target/m68k/cpu.h @@ -489,6 +489,7 @@ enum m68k_features { M68K_FEATURE_RTD, M68K_FEATURE_CHK2, M68K_FEATURE_M68040, /* instructions specific to MC68040 */ + M68K_FEATURE_MOVEP, }; static inline int m68k_feature(CPUM68KState *env, int feature) diff --git a/qemu/target/m68k/translate.c b/qemu/target/m68k/translate.c index b62dd20f..99a5f979 100644 --- a/qemu/target/m68k/translate.c +++ b/qemu/target/m68k/translate.c @@ -2139,6 +2139,52 @@ DISAS_INSN(movem) tcg_temp_free(tcg_ctx, addr); } +DISAS_INSN(movep) +{ + TCGContext *tcg_ctx = s->uc->tcg_ctx; + uint8_t i; + int16_t displ; + TCGv reg; + TCGv addr; + TCGv abuf; + TCGv dbuf; + + displ = read_im16(env, s); + + addr = AREG(insn, 0); + reg = DREG(insn, 9); + + abuf = tcg_temp_new(tcg_ctx); + tcg_gen_addi_i32(tcg_ctx, abuf, addr, displ); + dbuf = tcg_temp_new(tcg_ctx); + + if (insn & 0x40) { + i = 4; + } else { + i = 2; + } + + if (insn & 0x80) { + for ( ; i > 0 ; i--) { + tcg_gen_shri_i32(tcg_ctx, dbuf, reg, (i - 1) * 8); + tcg_gen_qemu_st8(s->uc, dbuf, abuf, IS_USER(s)); + if (i > 1) { + tcg_gen_addi_i32(tcg_ctx, abuf, abuf, 2); + } + } + } else { + for ( ; i > 0 ; i--) { + tcg_gen_qemu_ld8u(s->uc, dbuf, abuf, IS_USER(s)); + tcg_gen_deposit_i32(tcg_ctx, reg, reg, dbuf, (i - 1) * 8, 8); + if (i > 1) { + tcg_gen_addi_i32(tcg_ctx, abuf, abuf, 2); + } + } + } + tcg_temp_free(tcg_ctx, abuf); + tcg_temp_free(tcg_ctx, dbuf); +} + DISAS_INSN(bitop_im) { TCGContext *tcg_ctx = s->uc->tcg_ctx; @@ -5899,6 +5945,7 @@ void register_m68k_insns (CPUM68KState *env) BASE(bitop_reg, 0140, f1c0); BASE(bitop_reg, 0180, f1c0); BASE(bitop_reg, 01c0, f1c0); + INSN(movep, 0108, f138, MOVEP); INSN(arith_im, 0280, fff8, CF_ISA_A); INSN(arith_im, 0200, ff00, M68000); INSN(undef, 02c0, ffc0, M68000);