Commit 1226e212 authored by Pavel Dovgalyuk's avatar Pavel Dovgalyuk Committed by Laurent Vivier
Browse files

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.

Signed-off-by: default avatarPavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
Signed-off-by: default avatarMihail Abakumov <mikhail.abakumov@ispras.ru>
Tested-by: default avatarLaurent Vivier <laurent@vivier.eu>
Reviewed-by: default avatarLaurent Vivier <laurent@vivier.eu>
Message-Id: <20180206124431.31433.91946.stgit@pasha-VirtualBox>
Signed-off-by: default avatarLaurent Vivier <laurent@vivier.eu>
parent bec9c64e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -113,6 +113,7 @@ static void m68000_cpu_initfn(Object *obj)
    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(Object *obj)
@@ -135,6 +136,7 @@ static void m68020_cpu_initfn(Object *obj)
    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

+1 −0
Original line number Diff line number Diff line
@@ -492,6 +492,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)
+46 −0
Original line number Diff line number Diff line
@@ -2078,6 +2078,51 @@ DISAS_INSN(movem)
    tcg_temp_free(addr);
}

DISAS_INSN(movep)
{
    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_gen_addi_i32(abuf, addr, displ);
    dbuf = tcg_temp_new();

    if (insn & 0x40) {
        i = 4;
    } else {
        i = 2;
    }

    if (insn & 0x80) {
        for ( ; i > 0 ; i--) {
            tcg_gen_shri_i32(dbuf, reg, (i - 1) * 8);
            tcg_gen_qemu_st8(dbuf, abuf, IS_USER(s));
            if (i > 1) {
                tcg_gen_addi_i32(abuf, abuf, 2);
            }
        }
    } else {
        for ( ; i > 0 ; i--) {
            tcg_gen_qemu_ld8u(dbuf, abuf, IS_USER(s));
            tcg_gen_deposit_i32(reg, reg, dbuf, (i - 1) * 8, 8);
            if (i > 1) {
                tcg_gen_addi_i32(abuf, abuf, 2);
            }
        }
    }
    tcg_temp_free(abuf);
    tcg_temp_free(dbuf);
}

DISAS_INSN(bitop_im)
{
    int opsize;
@@ -5678,6 +5723,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);