Add MIPS DSP Bit/Manipulation instructions Support. Signed-off-by: Jia Liu <pro...@gmail.com> --- target-mips/dsp_helper.c | 42 +++++++++++++++++++ target-mips/helper.h | 4 ++ target-mips/translate.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 0 deletions(-)
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c index 893e915..1c5e858 100644 --- a/target-mips/dsp_helper.c +++ b/target-mips/dsp_helper.c @@ -2979,6 +2979,48 @@ void helper_mulsa_w_ph(CPUMIPSState *env, int ac, uint32_t rs, uint32_t rt) env->active_tc.LO[ac] = acc & MIPSDSP_LLO; } +/** DSP Bit/Manipulation Sub-class insns **/ +uint32_t helper_bitrev(uint32_t rt) +{ + int32_t temp; + uint32_t rd; + int i, last; + + temp = rt & MIPSDSP_LO; + rd = 0; + for (i = 0; i < 16; i++) { + last = temp % 2; + temp = temp >> 1; + rd = rd | (last << (15 - i)); + } + + return rd; +} + +uint32_t helper_insv(CPUMIPSState *env, uint32_t rs, uint32_t rt) +{ + uint32_t pos, size, msb, lsb, rs_f, rt_f; + uint32_t temp, temprs, temprt; + target_ulong dspc; + + dspc = env->active_tc.DSPControl; + pos = dspc & 0x1F; + size = (dspc >> 7) & 0x1F; + msb = pos + size - 1; + lsb = pos; + + if (lsb > msb) { + return rt; + } + + rs_f = (((int32_t)0x01 << (msb - lsb + 1 + 1)) - 1) << lsb; + rt_f = rs_f ^ 0xFFFFFFFF; + temprs = rs & rs_f; + temprt = rt & rt_f; + temp = temprs | temprt; + return temp; +} + #undef MIPSDSP_LHI #undef MIPSDSP_LLO #undef MIPSDSP_HI diff --git a/target-mips/helper.h b/target-mips/helper.h index bd6f3b5..669537b 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -410,4 +410,8 @@ DEF_HELPER_FLAGS_3(mulq_s_w, 0, i32, env, i32, i32) DEF_HELPER_FLAGS_3(mulq_rs_w, 0, i32, env, i32, i32) DEF_HELPER_FLAGS_4(mulsa_w_ph, 0, void, env, int, i32, i32) +/* DSP Bit/Manipulation Sub-class insns */ +DEF_HELPER_FLAGS_1(bitrev, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32) +DEF_HELPER_FLAGS_3(insv, 0, i32, env, i32, i32) + #include "def-helper.h" diff --git a/target-mips/translate.c b/target-mips/translate.c index 69a6929..7d385f2 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -327,6 +327,8 @@ enum { /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */ /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */ OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3, + /* DSP Bit/Manipulation Sub-class */ + OPC_INSV_DSP = 0x0C | OPC_SPECIAL3, }; /* BSHFL opcodes */ @@ -428,6 +430,12 @@ enum { OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP, OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP, OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP, + /* DSP Bit/Manipulation Sub-class */ + OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP, + OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP, + OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP, + OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP, + OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP, }; #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) @@ -496,6 +504,12 @@ enum { OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP, }; +#define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) +enum { + /* DSP Bit/Manipulation Sub-class */ + OPC_INSV = (0x00 << 6) | OPC_INSV_DSP, +}; + /* Coprocessor 0 (rs field) */ #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21)) @@ -12369,6 +12383,82 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_PRECEU_PH_QBRA: gen_helper_preceu_ph_qbra(cpu_gpr[rd], cpu_gpr[rt]); break; + case OPC_BITREV: + gen_helper_bitrev(cpu_gpr[rd], cpu_gpr[rt]); + break; + case OPC_REPL_QB: + { + TCGv imm3, imm2, imm1, imm0; + imm = (ctx->opcode >> 16) & 0xFF; + imm3 = tcg_const_i32(imm); + imm2 = tcg_const_i32(imm); + imm1 = tcg_const_i32(imm); + imm0 = tcg_const_i32(imm); + tcg_gen_shli_i32(imm3, imm3, 24); + tcg_gen_shli_i32(imm2, imm2, 16); + tcg_gen_shli_i32(imm1, imm1, 8); + tcg_gen_or_i32(cpu_gpr[rd], imm3, imm2); + tcg_gen_or_i32(cpu_gpr[rd], cpu_gpr[rd], imm1); + tcg_gen_or_i32(cpu_gpr[rd], cpu_gpr[rd], imm0); + tcg_temp_free(imm3); + tcg_temp_free(imm2); + tcg_temp_free(imm1); + tcg_temp_free(imm0); + break; + } + case OPC_REPLV_QB: + { + TCGv rt3, rt2, rt1, rt0; + + rt3 = tcg_const_i32(0); + rt2 = tcg_const_i32(0); + rt1 = tcg_const_i32(0); + rt0 = tcg_const_i32(0); + + tcg_gen_andi_i32(rt3, cpu_gpr[rt], 0xFF); + tcg_gen_andi_i32(rt2, cpu_gpr[rt], 0xFF); + tcg_gen_andi_i32(rt1, cpu_gpr[rt], 0xFF); + tcg_gen_andi_i32(rt0, cpu_gpr[rt], 0xFF); + + tcg_gen_shli_i32(rt3, rt3, 24); + tcg_gen_shli_i32(rt2, rt2, 16); + tcg_gen_shli_i32(rt1, rt1, 8); + + tcg_gen_or_i32(cpu_gpr[rd], rt3, rt2); + tcg_gen_or_i32(cpu_gpr[rd], cpu_gpr[rd], rt1); + tcg_gen_or_i32(cpu_gpr[rd], cpu_gpr[rd], rt0); + + tcg_temp_free(rt3); + tcg_temp_free(rt2); + tcg_temp_free(rt1); + tcg_temp_free(rt0); + break; + } + case OPC_REPL_PH: + { + TCGv immhi, immlo; + imm = (ctx->opcode >> 16) & 0x03FF; + immhi = tcg_const_i32(imm); + immlo = tcg_const_i32(imm); + tcg_gen_shli_i32(immhi, immhi, 16); + tcg_gen_or_i32(cpu_gpr[rd], immhi, immlo); + tcg_temp_free(immhi); + tcg_temp_free(immlo); + break; + } + case OPC_REPLV_PH: + { + TCGv rt0, rt1; + rt0 = tcg_const_i32(0); + rt1 = tcg_const_i32(0); + tcg_gen_andi_i32(rt0, cpu_gpr[rt], 0xFFFF); + tcg_gen_andi_i32(rt1, cpu_gpr[rt], 0xFFFF); + tcg_gen_shli_i32(rt1, rt1, 16); + tcg_gen_or_i32(cpu_gpr[rd], rt1, rt0); + tcg_temp_free(rt0); + tcg_temp_free(rt1); + break; + } } break; case OPC_ADDU_QB_DSP: @@ -12773,6 +12863,19 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) } } break; + case OPC_INSV_DSP: + op2 = MASK_INSV(ctx->opcode); + switch (op2) { + case OPC_INSV: + { + TCGv temp_rt = tcg_const_i32(rt); + gen_helper_insv(cpu_gpr[rt], cpu_env, + cpu_gpr[rs], cpu_gpr[rt]); + tcg_temp_free(temp_rt); + break; + } + } + break; #if defined(TARGET_MIPS64) case OPC_DEXTM ... OPC_DEXT: case OPC_DINSM ... OPC_DINS: -- 1.7.5.4