Add MIPS DSP Load instructions Support. Signed-off-by: Jia Liu <pro...@gmail.com> --- target-mips/helper.h | 6 ++++ target-mips/op_helper.c | 37 ++++++++++++++++++++++++++ target-mips/translate.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 0 deletions(-)
diff --git a/target-mips/helper.h b/target-mips/helper.h index 76fb451..c32c835 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -297,4 +297,10 @@ DEF_HELPER_0(rdhwr_ccres, tl) DEF_HELPER_1(pmon, void, int) DEF_HELPER_0(wait, void) +/*** MIPS DSP ***/ +/* DSP load */ +DEF_HELPER_2(lbux, tl, tl, int) +DEF_HELPER_2(lhx, i32, i32, int) +DEF_HELPER_2(lwx, i32, i32, int) + #include "def-helper.h" diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index ce01225..2864f33 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -3410,3 +3410,40 @@ FOP_COND_PS(le, float32_le(fst0, fst1, &env->active_fpu.fp_status), float32_le(fsth0, fsth1, &env->active_fpu.fp_status)) FOP_COND_PS(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status), float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) || float32_le(fsth0, fsth1, &env->active_fpu.fp_status)) + +/* MIPS DSP load */ +#define MIPSDSP_Q0 0x000000FF +target_ulong helper_lbux(target_ulong addr, int mem_idx) +{ + target_ulong temp; + + temp = do_lbu(addr, mem_idx); + temp = temp & MIPSDSP_Q0; + + return temp; +} + +uint32_t helper_lhx(target_ulong vaddr, int mem_idx) +{ + target_ulong temp; + int16_t half; + uint32_t rd; + + temp = do_lw(vaddr, mem_idx); + half = temp & 0x0000FFFF; + rd = (int32_t)half; + + return rd; +} + +uint32_t helper_lwx(target_ulong vaddr, int mem_idx) +{ + target_ulong temp; + uint32_t rd; + + temp = do_lw(vaddr, mem_idx); + rd = (int32_t)temp; + + return rd; +} +#undef MIPSDSP_Q0 diff --git a/target-mips/translate.c b/target-mips/translate.c index d2bd1ae..c698e78 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -317,6 +317,21 @@ enum { OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3, OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3, OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3, + + /* MIPS DSP */ + OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3, + OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3, + /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */ + /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */ + OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3, + OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3, + OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3, + OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3, + OPC_INSV_DSP = 0x0C | OPC_SPECIAL3, + OPC_LX_DSP = 0x0A | OPC_SPECIAL3, + /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */ + /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */ + OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3, }; /* BSHFL opcodes */ @@ -336,6 +351,14 @@ enum { OPC_DSHD = (0x05 << 6) | OPC_DBSHFL, }; +#define MASK_LX(op) MASK_SPECIAL3(op) | (op & (0x1F << 6)) +/* MIPS DSP load */ +enum { + OPC_LBUX = (0x06 << 6) | OPC_LX_DSP, + OPC_LHX = (0x04 << 6) | OPC_LX_DSP, + OPC_LWX = (0x00 << 6) | OPC_LX_DSP, +}; + /* Coprocessor 0 (rs field) */ #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21)) @@ -12062,6 +12085,50 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) check_insn(env, ctx, INSN_LOONGSON2E); gen_loongson_integer(ctx, op1, rd, rs, rt); break; + case OPC_LX_DSP: + op2 = MASK_LX(ctx->opcode); + switch (op2) { + case OPC_LBUX: + { + TCGv addr = tcg_temp_new(); + TCGv temp_mem = tcg_temp_new(); + + save_cpu_state(ctx, 1); + gen_op_addr_add(ctx, addr, cpu_gpr[rs], cpu_gpr[rt]); + temp_mem = tcg_const_i32(ctx->mem_idx); + gen_helper_lbux(cpu_gpr[rd], addr, temp_mem); + tcg_temp_free_i32(addr); + tcg_temp_free_i32(temp_mem); + break; + } + case OPC_LHX: + { + TCGv addr = tcg_temp_new(); + TCGv temp_mem = tcg_temp_new(); + + save_cpu_state(ctx, 1); + gen_op_addr_add(ctx, addr, cpu_gpr[rs], cpu_gpr[rt]); + temp_mem = tcg_const_i32(ctx->mem_idx); + gen_helper_lhx(cpu_gpr[rd], addr, temp_mem); + tcg_temp_free_i32(addr); + tcg_temp_free_i32(temp_mem); + break; + } + case OPC_LWX: + { + TCGv addr = tcg_temp_new(); + TCGv temp_mem = tcg_temp_new(); + + save_cpu_state(ctx, 1); + gen_op_addr_add(ctx, addr, cpu_gpr[rs], cpu_gpr[rt]); + temp_mem = tcg_const_i32(ctx->mem_idx); + gen_helper_lwx(cpu_gpr[rd], addr, temp_mem); + tcg_temp_free_i32(addr); + tcg_temp_free_i32(temp_mem); + break; + } + } + break; #if defined(TARGET_MIPS64) case OPC_DEXTM ... OPC_DEXT: case OPC_DINSM ... OPC_DINS: -- 1.7.5.4