Commit 9d4f0429 authored by Laurent Vivier's avatar Laurent Vivier
Browse files

target/m68k: add move16



move16 moves the source line to the destination line. Lines are aligned
to 16-byte boundaries and are 16 bytes long.

Signed-off-by: default avatarLaurent Vivier <laurent@vivier.eu>
Reviewed-by: default avatarRichard Henderson <richard.henderson@linaro.org>
Message-Id: <20180104012913.30763-9-laurent@vivier.eu>
parent 8bf6cbaf
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -137,7 +137,15 @@ static void m68020_cpu_initfn(Object *obj)
    m68k_set_feature(env, M68K_FEATURE_CHK2);
}
#define m68030_cpu_initfn m68020_cpu_initfn
#define m68040_cpu_initfn m68020_cpu_initfn

static void m68040_cpu_initfn(Object *obj)
{
    M68kCPU *cpu = M68K_CPU(obj);
    CPUM68KState *env = &cpu->env;

    m68020_cpu_initfn(obj);
    m68k_set_feature(env, M68K_FEATURE_M68040);
}

static void m68060_cpu_initfn(Object *obj)
{
+1 −0
Original line number Diff line number Diff line
@@ -306,6 +306,7 @@ enum m68k_features {
    M68K_FEATURE_BKPT,
    M68K_FEATURE_RTD,
    M68K_FEATURE_CHK2,
    M68K_FEATURE_M68040, /* instructions specific to MC68040 */
};

static inline int m68k_feature(CPUM68KState *env, int feature)
+72 −0
Original line number Diff line number Diff line
@@ -4277,6 +4277,76 @@ DISAS_INSN(chk2)
    tcg_temp_free(reg);
}

static void m68k_copy_line(TCGv dst, TCGv src, int index)
{
    TCGv addr;
    TCGv_i64 t0, t1;

    addr = tcg_temp_new();

    t0 = tcg_temp_new_i64();
    t1 = tcg_temp_new_i64();

    tcg_gen_andi_i32(addr, src, ~15);
    tcg_gen_qemu_ld64(t0, addr, index);
    tcg_gen_addi_i32(addr, addr, 8);
    tcg_gen_qemu_ld64(t1, addr, index);

    tcg_gen_andi_i32(addr, dst, ~15);
    tcg_gen_qemu_st64(t0, addr, index);
    tcg_gen_addi_i32(addr, addr, 8);
    tcg_gen_qemu_st64(t1, addr, index);

    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
    tcg_temp_free(addr);
}

DISAS_INSN(move16_reg)
{
    int index = IS_USER(s);
    TCGv tmp;
    uint16_t ext;

    ext = read_im16(env, s);
    if ((ext & (1 << 15)) == 0) {
        gen_exception(s, s->insn_pc, EXCP_ILLEGAL);
    }

    m68k_copy_line(AREG(ext, 12), AREG(insn, 0), index);

    /* Ax can be Ay, so save Ay before incrementing Ax */
    tmp = tcg_temp_new();
    tcg_gen_mov_i32(tmp, AREG(ext, 12));
    tcg_gen_addi_i32(AREG(insn, 0), AREG(insn, 0), 16);
    tcg_gen_addi_i32(AREG(ext, 12), tmp, 16);
    tcg_temp_free(tmp);
}

DISAS_INSN(move16_mem)
{
    int index = IS_USER(s);
    TCGv reg, addr;

    reg = AREG(insn, 0);
    addr = tcg_const_i32(read_im32(env, s));

    if ((insn >> 3) & 1) {
        /* MOVE16 (xxx).L, (Ay) */
        m68k_copy_line(reg, addr, index);
    } else {
        /* MOVE16 (Ay), (xxx).L */
        m68k_copy_line(addr, reg, index);
    }

    tcg_temp_free(addr);

    if (((insn >> 3) & 2) == 0) {
        /* (Ay)+ */
        tcg_gen_addi_i32(reg, reg, 16);
    }
}

static TCGv gen_get_sr(DisasContext *s)
{
    TCGv ccr;
@@ -5578,6 +5648,8 @@ void register_m68k_insns (CPUM68KState *env)
    INSN(fsave,     f300, ffc0, FPU);
    INSN(intouch,   f340, ffc0, CF_ISA_A);
    INSN(cpushl,    f428, ff38, CF_ISA_A);
    INSN(move16_mem, f600, ffe0, M68040);
    INSN(move16_reg, f620, fff8, M68040);
    INSN(wddata,    fb00, ff00, CF_ISA_A);
    INSN(wdebug,    fbc0, ffc0, CF_ISA_A);
#undef INSN