This patch is the translation of MIPS ASE DSP.
Signed-off-by: Jia Liu<pro...@gmail.com>
---
target-mips/translate.c | 1114 +++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 1088 insertions(+), 26 deletions(-)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 8361d88..1fa5b28 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -249,6 +249,11 @@ enum {
OPC_SYNCI = (0x1F<< 16) | OPC_REGIMM,
};
+/* REGIMM mipsdsp opcodes */
+enum {
+ OPC_BPOSGE32 = (0x1C<< 16) | OPC_REGIMM,
+};
+
/* Special2 opcodes */
#define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op& 0x3F)
@@ -312,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 */
@@ -331,6 +351,231 @@ enum {
OPC_DSHD = (0x05<< 6) | OPC_DBSHFL,
};
+#define MASK_ABSQ_S_PH(op) MASK_SPECIAL3(op) | (op& (0x1F<< 6))
+/* MIPS DSP */
+enum {
+ OPC_ABSQ_S_PH = (0x09<< 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_ABSQ_S_W = (0x11<< 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_BITREV = (0x1B<< 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_PRECEQ_W_PHL = (0x0C<< 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_PRECEQ_W_PHR = (0x0D<< 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_PRECEQU_PH_QBL = (0x04<< 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_PRECEQU_PH_QBLA = (0x06<< 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_PRECEQU_PH_QBR = (0x05<< 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_PRECEQU_PH_QBRA = (0x07<< 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_PRECEU_PH_QBL = (0x1C<< 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_PRECEU_PH_QBLA = (0x1E<< 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_PRECEU_PH_QBR = (0x1D<< 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_PRECEU_PH_QBRA = (0x1F<< 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_REPL_PH = (0x0A<< 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_REPL_QB = (0x02<< 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_REPLV_PH = (0x0B<< 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_REPLV_QB = (0x03<< 6) | OPC_ABSQ_S_PH_DSP,
+};
+
+/* MIPS DSPR2 */
+enum {
+ OPC_ABSQ_S_QB = (0x01<< 6) | OPC_ABSQ_S_PH_DSP,
+};
+
+#define MASK_ADDU_QB(op) MASK_SPECIAL3(op) | (op& (0x1F<< 6))
+/* MIPS DSP */
+enum {
+ OPC_ADDQ_PH = (0x0A<< 6) | OPC_ADDU_QB_DSP,
+ OPC_ADDQ_S_PH = (0x0E<< 6) | OPC_ADDU_QB_DSP,
+ OPC_ADDQ_S_W = (0x16<< 6) | OPC_ADDU_QB_DSP,
+ OPC_ADDSC = (0x10<< 6) | OPC_ADDU_QB_DSP,
+ OPC_ADDU_QB = (0x00<< 6) | OPC_ADDU_QB_DSP,
+ OPC_ADDU_S_QB = (0x04<< 6) | OPC_ADDU_QB_DSP,
+ OPC_ADDWC = (0x11<< 6) | OPC_ADDU_QB_DSP,
+ OPC_MODSUB = (0x12<< 6) | OPC_ADDU_QB_DSP,
+ OPC_MULEQ_S_W_PHL = (0x1C<< 6) | OPC_ADDU_QB_DSP,
+ OPC_MULEQ_S_W_PHR = (0x1D<< 6) | OPC_ADDU_QB_DSP,
+ OPC_MULEU_S_PH_QBL = (0x06<< 6) | OPC_ADDU_QB_DSP,
+ OPC_MULEU_S_PH_QBR = (0x07<< 6) | OPC_ADDU_QB_DSP,
+ OPC_MULQ_RS_PH = (0x1F<< 6) | OPC_ADDU_QB_DSP,
+ OPC_RADDU_W_QB = (0x14<< 6) | OPC_ADDU_QB_DSP,
+ OPC_SUBQ_PH = (0x0B<< 6) | OPC_ADDU_QB_DSP,
+ OPC_SUBQ_S_PH = (0x0F<< 6) | OPC_ADDU_QB_DSP,
+ OPC_SUBQ_S_W = (0x17<< 6) | OPC_ADDU_QB_DSP,
+ OPC_SUBU_QB = (0x01<< 6) | OPC_ADDU_QB_DSP,
+ OPC_SUBU_S_QB = (0x05<< 6) | OPC_ADDU_QB_DSP,
+};
+
+/* MIPS DSPR2 */
+enum {
+ OPC_ADDU_PH = (0x08<< 6) | OPC_ADDU_QB_DSP,
+ OPC_ADDU_S_PH = (0x0C<< 6) | OPC_ADDU_QB_DSP,
+ OPC_MULQ_S_PH = (0x1E<< 6) | OPC_ADDU_QB_DSP,
+ OPC_SUBU_PH = (0x09<< 6) | OPC_ADDU_QB_DSP,
+ OPC_SUBU_S_PH = (0x0D<< 6) | OPC_ADDU_QB_DSP,
+};
+
+#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
+#define MASK_ADDUH_QB(op) MASK_SPECIAL3(op) | (op& (0x1F<< 6))
+/* MIPS DSPR2 */
+enum {
+ OPC_ADDQH_PH = (0x08<< 6) | OPC_ADDUH_QB_DSP,
+ OPC_ADDQH_R_PH = (0x0A<< 6) | OPC_ADDUH_QB_DSP,
+ OPC_ADDQH_W = (0x10<< 6) | OPC_ADDUH_QB_DSP,
+ OPC_ADDQH_R_W = (0x12<< 6) | OPC_ADDUH_QB_DSP,
+ OPC_ADDUH_QB = (0x00<< 6) | OPC_ADDUH_QB_DSP,
+ OPC_ADDUH_R_QB = (0x02<< 6) | OPC_ADDUH_QB_DSP,
+ OPC_MUL_PH = (0x0C<< 6) | OPC_ADDUH_QB_DSP,
+ OPC_MUL_S_PH = (0x0E<< 6) | OPC_ADDUH_QB_DSP,
+ OPC_SUBQH_PH = (0x09<< 6) | OPC_ADDUH_QB_DSP,
+ OPC_SUBQH_R_PH = (0x0B<< 6) | OPC_ADDUH_QB_DSP,
+ OPC_SUBQH_W = (0x11<< 6) | OPC_ADDUH_QB_DSP,
+ OPC_SUBQH_R_W = (0x13<< 6) | OPC_ADDUH_QB_DSP,
+ OPC_SUBUH_QB = (0x01<< 6) | OPC_ADDUH_QB_DSP,
+ OPC_SUBUH_R_QB = (0x03<< 6) | OPC_ADDUH_QB_DSP,
+};
+
+#define OPC_MUL_PH_DSP OPC_ADDUH_QB_DSP
+/* #define MASK_MUL_PH(op) MASK_SPECIAL3(op) | (op& (0x1F<< 6)) */
+/* MIPS DSPR2 */
+enum {
+ OPC_MULQ_RS_W = (0x17<< 6) | OPC_MUL_PH_DSP,
+ OPC_MULQ_S_W = (0x16<< 6) | OPC_MUL_PH_DSP,
+};
+
+#define MASK_APPEND(op) MASK_SPECIAL3(op) | (op& (0x1F<< 6))
+/* MIPS DSPR2 */
+enum {
+ OPC_APPEND = (0x00<< 6) | OPC_APPEND_DSP,
+ OPC_BALIGN = (0x10<< 6) | OPC_APPEND_DSP,
+ OPC_PREPEND = (0x01<< 6) | OPC_APPEND_DSP,
+};
+
+#define MASK_CMPU_EQ_QB(op) MASK_SPECIAL3(op) | (op& (0x1F<< 6))
+/* MIPS DSP */
+enum {
+ OPC_CMP_EQ_PH = (0x08<< 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_CMP_LT_PH = (0x09<< 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_CMP_LE_PH = (0x0A<< 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_CMPGU_EQ_QB = (0x04<< 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_CMPGU_LT_QB = (0x05<< 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_CMPGU_LE_QB = (0x06<< 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_CMPU_EQ_QB = (0x00<< 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_CMPU_LT_QB = (0x01<< 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_CMPU_LE_QB = (0x02<< 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_PACKRL_PH = (0x0E<< 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_PICK_QB = (0x03<< 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_PICK_PH = (0x0B<< 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_PRECRQ_QB_PH = (0x0C<< 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_PRECRQ_PH_W = (0x14<< 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_PRECRQ_RS_PH_W = (0x15<< 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_PRECRQU_S_QB_PH = (0x0F<< 6) | OPC_CMPU_EQ_QB_DSP,
+};
+
+/* MIPS DSPR2 */
+enum {
+ OPC_CMPGDU_EQ_QB = (0x18<< 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_CMPGDU_LT_QB = (0x19<< 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_CMPGDU_LE_QB = (0x1A<< 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_PRECR_QB_PH = (0x0D<< 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_PRECR_SRA_PH_W = (0x1E<< 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_PRECR_SRA_R_PH_W = (0x1F<< 6) | OPC_CMPU_EQ_QB_DSP,
+};
+
+#define MASK_DPA_W_PH(op) MASK_SPECIAL3(op) | (op& (0x1F<< 6))
+/* MIPS DSP */
+enum {
+ OPC_DPAQ_S_W_PH = (0x04<< 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPAQ_SA_L_W = (0x0C<< 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPAU_H_QBL = (0x03<< 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPAU_H_QBR = (0x07<< 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPSQ_S_W_PH = (0x05<< 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPSQ_SA_L_W = (0x0D<< 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPSU_H_QBL = (0x0B<< 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPSU_H_QBR = (0x0F<< 6) | OPC_DPA_W_PH_DSP,
+ OPC_MAQ_S_W_PHL = (0x14<< 6) | OPC_DPA_W_PH_DSP,
+ OPC_MAQ_SA_W_PHL = (0x10<< 6) | OPC_DPA_W_PH_DSP,
+ OPC_MAQ_S_W_PHR = (0x16<< 6) | OPC_DPA_W_PH_DSP,
+ OPC_MAQ_SA_W_PHR = (0x12<< 6) | OPC_DPA_W_PH_DSP,
+ OPC_MULSAQ_S_W_PH = (0x06<< 6) | OPC_DPA_W_PH_DSP,
+};
+
+/* MIPS DSPR2 */
+enum{
+ OPC_DPA_W_PH = (0x00<< 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPAQX_S_W_PH = (0x18<< 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPAQX_SA_W_PH = (0x1A<< 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPAX_W_PH = (0x08<< 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPS_W_PH = (0x01<< 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPSQX_S_W_PH = (0x19<< 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPSQX_SA_W_PH = (0x1B<< 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPSX_W_PH = (0x09<< 6) | OPC_DPA_W_PH_DSP,
+ OPC_MULSA_W_PH = (0x02<< 6) | OPC_DPA_W_PH_DSP,
+};
+
+#define MASK_EXTR_W(op) MASK_SPECIAL3(op) | (op& (0x1F<< 6))
+/* MIPS DSP */
+enum {
+ OPC_EXTP = (0x02<< 6) | OPC_EXTR_W_DSP,
+ OPC_EXTPDP = (0x0A<< 6) | OPC_EXTR_W_DSP,
+ OPC_EXTPDPV = (0x0B<< 6) | OPC_EXTR_W_DSP,
+ OPC_EXTPV = (0x03<< 6) | OPC_EXTR_W_DSP,
+ OPC_EXTR_S_H = (0x0E<< 6) | OPC_EXTR_W_DSP,
+ OPC_EXTR_W = (0x00<< 6) | OPC_EXTR_W_DSP,
+ OPC_EXTR_R_W = (0x04<< 6) | OPC_EXTR_W_DSP,
+ OPC_EXTR_RS_W = (0x06<< 6) | OPC_EXTR_W_DSP,
+ OPC_EXTRV_S_H = (0x0F<< 6) | OPC_EXTR_W_DSP,
+ OPC_EXTRV_W = (0x01<< 6) | OPC_EXTR_W_DSP,
+ OPC_EXTRV_R_W = (0x05<< 6) | OPC_EXTR_W_DSP,
+ OPC_EXTRV_RS_W = (0x07<< 6) | OPC_EXTR_W_DSP,
+ OPC_MTHLIP = (0x1F<< 6) | OPC_EXTR_W_DSP,
+ OPC_RDDSP = (0x12<< 6) | OPC_EXTR_W_DSP,
+ OPC_SHILO = (0x1A<< 6) | OPC_EXTR_W_DSP,
+ OPC_SHILOV = (0x1B<< 6) | OPC_EXTR_W_DSP,
+ OPC_WRDSP = (0x13<< 6) | OPC_EXTR_W_DSP,
+};
+
+#define MASK_INSV(op) MASK_SPECIAL3(op) | (op& (0x1F<< 6))
+/* MIPS DSP */
+enum {
+ OPC_INSV = (0x00<< 6) | OPC_INSV_DSP,
+};
+
+#define MASK_LX(op) MASK_SPECIAL3(op) | (op& (0x1F<< 6))
+/* MIPS DSP */
+enum {
+ OPC_LBUX = (0x06<< 6) | OPC_LX_DSP,
+ OPC_LHX = (0x04<< 6) | OPC_LX_DSP,
+ OPC_LWX = (0x00<< 6) | OPC_LX_DSP,
+};
+
+#define MASK_SHLL_QB(op) MASK_SPECIAL3(op) | (op& (0x1F<< 6))
+/* MIPS DSP */
+enum {
+ OPC_SHLL_PH = (0x08<< 6) | OPC_SHLL_QB_DSP,
+ OPC_SHLL_S_PH = (0x0C<< 6) | OPC_SHLL_QB_DSP,
+ OPC_SHLL_QB = (0x00<< 6) | OPC_SHLL_QB_DSP,
+ OPC_SHLL_S_W = (0x14<< 6) | OPC_SHLL_QB_DSP,
+ OPC_SHLLV_PH = (0x0A<< 6) | OPC_SHLL_QB_DSP,
+ OPC_SHLLV_S_PH = (0x0E<< 6) | OPC_SHLL_QB_DSP,
+ OPC_SHLLV_QB = (0x02<< 6) | OPC_SHLL_QB_DSP,
+ OPC_SHLLV_S_W = (0x16<< 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRA_PH = (0x09<< 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRA_R_PH = (0x0D<< 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRA_R_W = (0x15<< 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRAV_PH = (0x0B<< 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRAV_R_PH = (0x0F<< 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRAV_R_W = (0x17<< 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRL_QB = (0x01<< 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRLV_QB = (0x03<< 6) | OPC_SHLL_QB_DSP,
+};
+
+/* MIPS DSPR2 */
+enum {
+ OPC_SHRA_QB = (0x04<< 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRA_R_QB = (0x05<< 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRAV_QB = (0x06<< 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRAV_R_QB = (0x07<< 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRL_PH = (0x19<< 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRLV_PH = (0x1B<< 6) | OPC_SHLL_QB_DSP,
+};
+
/* Coprocessor 0 (rs field) */
#define MASK_CP0(op) MASK_OP_MAJOR(op) | (op& (0x1F<< 21))
@@ -1972,6 +2217,7 @@ static void gen_shift (CPUState *env, DisasContext *ctx,
uint32_t opc,
static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
{
const char *opn = "hilo";
+ int acc = 0;
if (reg == 0&& (opc == OPC_MFHI || opc == OPC_MFLO)) {
/* Treat as NOP. */
@@ -1980,25 +2226,29 @@ static void gen_HILO (DisasContext *ctx, uint32_t opc,
int reg)
}
switch (opc) {
case OPC_MFHI:
- tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
+ acc = ((ctx->opcode)>> 21)& 0x03;
+ tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
opn = "mfhi";
break;
case OPC_MFLO:
- tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
+ acc = ((ctx->opcode)>> 21)& 0x03;
+ tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
opn = "mflo";
break;
case OPC_MTHI:
+ acc = ((ctx->opcode)>> 11)& 0x03;
if (reg != 0)
- tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
+ tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
else
- tcg_gen_movi_tl(cpu_HI[0], 0);
+ tcg_gen_movi_tl(cpu_HI[acc], 0);
opn = "mthi";
break;
case OPC_MTLO:
+ acc = ((ctx->opcode)>> 11)& 0x03;
if (reg != 0)
- tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
+ tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
else
- tcg_gen_movi_tl(cpu_LO[0], 0);
+ tcg_gen_movi_tl(cpu_LO[acc], 0);
opn = "mtlo";
break;
}
@@ -2011,6 +2261,7 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
{
const char *opn = "mul/div";
TCGv t0, t1;
+ int acc = 0;
switch (opc) {
case OPC_DIV:
@@ -2073,6 +2324,7 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
{
TCGv_i64 t2 = tcg_temp_new_i64();
TCGv_i64 t3 = tcg_temp_new_i64();
+ acc = (ctx->opcode>> 11)& 0x03;
tcg_gen_ext_tl_i64(t2, t0);
tcg_gen_ext_tl_i64(t3, t1);
@@ -2082,8 +2334,8 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
tcg_gen_shri_i64(t2, t2, 32);
tcg_gen_trunc_i64_tl(t1, t2);
tcg_temp_free_i64(t2);
- tcg_gen_ext32s_tl(cpu_LO[0], t0);
- tcg_gen_ext32s_tl(cpu_HI[0], t1);
+ tcg_gen_ext32s_tl(cpu_LO[acc], t0);
+ tcg_gen_ext32s_tl(cpu_HI[acc], t1);
}
opn = "mult";
break;
@@ -2091,6 +2343,7 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
{
TCGv_i64 t2 = tcg_temp_new_i64();
TCGv_i64 t3 = tcg_temp_new_i64();
+ acc = (ctx->opcode>> 11)& 0x03;
tcg_gen_ext32u_tl(t0, t0);
tcg_gen_ext32u_tl(t1, t1);
@@ -2102,9 +2355,9 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
tcg_gen_shri_i64(t2, t2, 32);
tcg_gen_trunc_i64_tl(t1, t2);
tcg_temp_free_i64(t2);
- tcg_gen_ext32s_tl(cpu_LO[0], t0);
- tcg_gen_ext32s_tl(cpu_HI[0], t1);
- }
+ tcg_gen_ext32s_tl(cpu_LO[acc], t0);
+ tcg_gen_ext32s_tl(cpu_HI[acc], t1);
+ }
opn = "multu";
break;
#if defined(TARGET_MIPS64)
@@ -2150,41 +2403,43 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
{
TCGv_i64 t2 = tcg_temp_new_i64();
TCGv_i64 t3 = tcg_temp_new_i64();
+ acc = (ctx->opcode>> 11)& 0x03;
tcg_gen_ext_tl_i64(t2, t0);
tcg_gen_ext_tl_i64(t3, t1);
tcg_gen_mul_i64(t2, t2, t3);
- tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
+ tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
tcg_gen_add_i64(t2, t2, t3);
tcg_temp_free_i64(t3);
tcg_gen_trunc_i64_tl(t0, t2);
tcg_gen_shri_i64(t2, t2, 32);
tcg_gen_trunc_i64_tl(t1, t2);
tcg_temp_free_i64(t2);
- tcg_gen_ext32s_tl(cpu_LO[0], t0);
- tcg_gen_ext32s_tl(cpu_HI[0], t1);
- }
+ tcg_gen_ext32s_tl(cpu_LO[acc], t0);
+ tcg_gen_ext32s_tl(cpu_HI[acc], t1);
+ }
opn = "madd";
break;
case OPC_MADDU:
{
TCGv_i64 t2 = tcg_temp_new_i64();
TCGv_i64 t3 = tcg_temp_new_i64();
+ acc = (ctx->opcode)& 0x03;
tcg_gen_ext32u_tl(t0, t0);
tcg_gen_ext32u_tl(t1, t1);
tcg_gen_extu_tl_i64(t2, t0);
tcg_gen_extu_tl_i64(t3, t1);
tcg_gen_mul_i64(t2, t2, t3);
- tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
+ tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
tcg_gen_add_i64(t2, t2, t3);
tcg_temp_free_i64(t3);
tcg_gen_trunc_i64_tl(t0, t2);
tcg_gen_shri_i64(t2, t2, 32);
tcg_gen_trunc_i64_tl(t1, t2);
tcg_temp_free_i64(t2);
- tcg_gen_ext32s_tl(cpu_LO[0], t0);
- tcg_gen_ext32s_tl(cpu_HI[0], t1);
+ tcg_gen_ext32s_tl(cpu_LO[acc], t0);
+ tcg_gen_ext32s_tl(cpu_HI[acc], t1);
}
opn = "maddu";
break;
@@ -2192,19 +2447,20 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
{
TCGv_i64 t2 = tcg_temp_new_i64();
TCGv_i64 t3 = tcg_temp_new_i64();
+ acc = (ctx->opcode>> 11)& 0x03;
tcg_gen_ext_tl_i64(t2, t0);
tcg_gen_ext_tl_i64(t3, t1);
tcg_gen_mul_i64(t2, t2, t3);
- tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
+ tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
tcg_gen_sub_i64(t2, t3, t2);
tcg_temp_free_i64(t3);
tcg_gen_trunc_i64_tl(t0, t2);
tcg_gen_shri_i64(t2, t2, 32);
tcg_gen_trunc_i64_tl(t1, t2);
tcg_temp_free_i64(t2);
- tcg_gen_ext32s_tl(cpu_LO[0], t0);
- tcg_gen_ext32s_tl(cpu_HI[0], t1);
+ tcg_gen_ext32s_tl(cpu_LO[acc], t0);
+ tcg_gen_ext32s_tl(cpu_HI[acc], t1);
}
opn = "msub";
break;
@@ -2212,21 +2468,22 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
{
TCGv_i64 t2 = tcg_temp_new_i64();
TCGv_i64 t3 = tcg_temp_new_i64();
+ acc = (ctx->opcode>> 11)& 0x03;
tcg_gen_ext32u_tl(t0, t0);
tcg_gen_ext32u_tl(t1, t1);
tcg_gen_extu_tl_i64(t2, t0);
tcg_gen_extu_tl_i64(t3, t1);
tcg_gen_mul_i64(t2, t2, t3);
- tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
+ tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
tcg_gen_sub_i64(t2, t3, t2);
tcg_temp_free_i64(t3);
tcg_gen_trunc_i64_tl(t0, t2);
tcg_gen_shri_i64(t2, t2, 32);
tcg_gen_trunc_i64_tl(t1, t2);
tcg_temp_free_i64(t2);
- tcg_gen_ext32s_tl(cpu_LO[0], t0);
- tcg_gen_ext32s_tl(cpu_HI[0], t1);
+ tcg_gen_ext32s_tl(cpu_LO[acc], t0);
+ tcg_gen_ext32s_tl(cpu_HI[acc], t1);
}
opn = "msubu";
break;
@@ -2743,6 +3000,12 @@ static void gen_compute_branch (DisasContext *ctx,
uint32_t opc,
}
btgt = ctx->pc + insn_bytes + offset;
break;
+ case OPC_BPOSGE32:
+ t0 = cpu_dspctrl;
+ tcg_gen_andi_i32(t0, t0, 0x3F);
+ bcond_compute = 1;
+ btgt = ctx->pc + insn_bytes + offset;
+ break;
case OPC_J:
case OPC_JAL:
case OPC_JALX:
@@ -2931,6 +3194,10 @@ static void gen_compute_branch (DisasContext *ctx,
uint32_t opc,
tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
goto likely;
+ case OPC_BPOSGE32:
+ tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 31);
+ MIPS_DEBUG("bposge32 %s, " TARGET_FMT_lx, t0, btgt);
+ goto not_likely;
case OPC_BLTZALS:
case OPC_BLTZAL:
ctx->hflags |= (opc == OPC_BLTZALS
@@ -11168,8 +11435,6 @@ static void decode_micromips32_opc (CPUState *env,
DisasContext *ctx,
*is_branch = 1;
break;
case BPOSGE64:
- case BPOSGE32:
- /* MIPS DSP: not implemented */
/* Fall through */
default:
MIPS_INVAL("pool32i");
@@ -12033,10 +12298,801 @@ static void decode_opc (CPUState *env, DisasContext
*ctx, int *is_branch)
break;
case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
+ /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
+ * the same mask and op1. */
+ if(op1 == OPC_MULT_G_2E){
+ int is_mult_g_2e = 0;
+ op2 = MASK_ADDUH_QB(ctx->opcode);
+ switch(op2){
+ /* MIPS DSPR2 */
+ case OPC_ADDQH_PH:
+ gen_helper_addqhph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDQH_R_PH:
+ gen_helper_addqhrph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDQH_W:
+ gen_helper_addqhw(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDQH_R_W:
+ gen_helper_addqhrw(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDUH_QB:
+ gen_helper_adduhqb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDUH_R_QB:
+ gen_helper_adduhrqb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_MUL_PH:
+ gen_helper_mulph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_MUL_S_PH:
+ gen_helper_mulsph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBQH_PH:
+ gen_helper_subqhph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBQH_R_PH:
+ gen_helper_subqhrph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBQH_W:
+ gen_helper_subqhw(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBQH_R_W:
+ gen_helper_subqhrw(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBUH_QB:
+ gen_helper_subuhqb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBUH_R_QB:
+ gen_helper_subuhrqb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ /* OPC_MUL_PH_DSP */
+ /* MIPS DSPR2 */
+ case OPC_MULQ_RS_W:
+ gen_helper_mulqrsw(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_MULQ_S_W:
+ gen_helper_mulqsw(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ default:
+ is_mult_g_2e = 1;
+ break;
+ }
+ if(0 == is_mult_g_2e)
+ break;
+ }
case OPC_MOD_G_2E ... OPC_MODU_G_2E:
check_insn(env, ctx, INSN_LOONGSON2E);
gen_loongson_integer(ctx, op1, rd, rs, rt);
break;
+ /* MIPS DSP opcodes */
+ case OPC_ABSQ_S_PH_DSP:
+ op2 = MASK_ABSQ_S_PH(ctx->opcode);
+ switch(op2){
+ /* MIPS DSP */
+ case OPC_ABSQ_S_PH:
+ gen_helper_absqsph(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_ABSQ_S_W:
+ gen_helper_absqsw (cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_BITREV:
+ gen_helper_bitrev(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_PRECEQ_W_PHL:
+ gen_helper_preceqwphl(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_PRECEQ_W_PHR:
+ gen_helper_preceqwphr(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_PRECEQU_PH_QBL:
+ gen_helper_precequphqbl(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_PRECEQU_PH_QBLA:
+ gen_helper_precequphqbla(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_PRECEQU_PH_QBR:
+ gen_helper_precequphqbr(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_PRECEQU_PH_QBRA:
+ gen_helper_precequphqbra(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_PRECEU_PH_QBL:
+ gen_helper_preceuphqbl(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_PRECEU_PH_QBLA:
+ gen_helper_preceuphqbla(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_PRECEU_PH_QBR:
+ gen_helper_preceuphqbr(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_PRECEU_PH_QBRA:
+ gen_helper_preceuphqbra(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_REPL_PH:
+ {
+ TCGv temp_imm;
+ imm = (ctx->opcode>>16)& 0x03FF;
+ temp_imm = tcg_const_i32(imm);
+ gen_helper_replph(cpu_gpr[rd], temp_imm);
+ tcg_temp_free(temp_imm);
+ break;
+ }
+ case OPC_REPL_QB:
+ {
+ TCGv temp_imm;
+ imm = (ctx->opcode>> 16)& 0xFF;
+ temp_imm = tcg_const_i32(imm);
+ gen_helper_replqb(cpu_gpr[rd], temp_imm);
+ tcg_temp_free(temp_imm);
+ break;
+ }
+ case OPC_REPLV_PH:
+ gen_helper_replvph(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_REPLV_QB:
+ gen_helper_replvqb(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ /* MIPS DSPR2 */
+ case OPC_ABSQ_S_QB:
+ gen_helper_absqsqb(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ }
+ break;
+ case OPC_ADDU_QB_DSP:
+ op2 = MASK_ADDU_QB(ctx->opcode);
+ switch(op2){
+ /* MIPS DSP */
+ case OPC_ADDQ_PH:
+ gen_helper_addqph (cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDQ_S_PH:
+ gen_helper_addqsph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDQ_S_W:
+ gen_helper_addqsw (cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDSC:
+ gen_helper_addsc(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDU_QB:
+ gen_helper_adduqb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDU_S_QB:
+ gen_helper_addusqb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDWC:
+ gen_helper_addwc(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_MODSUB:
+ gen_helper_modsub(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_MULEQ_S_W_PHL:
+ gen_helper_muleqswphl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_MULEQ_S_W_PHR:
+ gen_helper_muleqswphr(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_MULEU_S_PH_QBL:
+ gen_helper_muleusphqbl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_MULEU_S_PH_QBR:
+ gen_helper_muleusphqbr(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_MULQ_RS_PH:
+ gen_helper_mulqrsph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_RADDU_W_QB:
+ gen_helper_radduwqb(cpu_gpr[rd], cpu_gpr[rs]);
+ break;
+ case OPC_SUBQ_PH:
+ gen_helper_subqph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBQ_S_PH:
+ gen_helper_subqsph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBQ_S_W:
+ gen_helper_subqsw(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBU_QB:
+ gen_helper_subuqb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBU_S_QB:
+ gen_helper_subusqb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ /* MIPS DSPR2 */
+ case OPC_ADDU_PH:
+ gen_helper_adduph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDU_S_PH:
+ gen_helper_addusph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_MULQ_S_PH:
+ gen_helper_mulqsph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBU_PH:
+ gen_helper_subuph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBU_S_PH:
+ gen_helper_subusph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ }
+ break;
+ case OPC_APPEND_DSP:
+ op2 = MASK_APPEND(ctx->opcode);
+ switch(op2){
+ /* MIPS DSPR2 */
+ case OPC_APPEND:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_append(cpu_gpr[rt], cpu_gpr[rt],
+ cpu_gpr[rs], temp_rd);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_BALIGN:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_balign(cpu_gpr[rt], cpu_gpr[rt],
+ cpu_gpr[rs], temp_rd);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_PREPEND:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_prepend(cpu_gpr[rt], temp_rd,
+ cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ }
+ break;
+ case OPC_CMPU_EQ_QB_DSP:
+ op2 = MASK_CMPU_EQ_QB(ctx->opcode);
+ switch(op2){
+ /* MIPS DSP */
+ case OPC_CMP_EQ_PH:
+ gen_helper_cmpeqph(cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_CMP_LT_PH:
+ gen_helper_cmpltph(cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_CMP_LE_PH:
+ gen_helper_cmpleph(cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_CMPGU_EQ_QB:
+ gen_helper_cmpgueqqb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_CMPGU_LT_QB:
+ gen_helper_cmpgultqb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_CMPGU_LE_QB:
+ gen_helper_cmpguleqb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_CMPU_EQ_QB:
+ gen_helper_cmpueqqb(cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_CMPU_LT_QB:
+ gen_helper_cmpultqb(cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_CMPU_LE_QB:
+ gen_helper_cmpuleqb(cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_PACKRL_PH:
+ gen_helper_packrlph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_PICK_QB:
+ gen_helper_pickqb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_PICK_PH:
+ gen_helper_pickph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_PRECRQ_QB_PH:
+ gen_helper_precrqqbph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_PRECRQ_PH_W:
+ gen_helper_precrqphw(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_PRECRQ_RS_PH_W:
+ gen_helper_precrqrsphw(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_PRECRQU_S_QB_PH:
+ gen_helper_precrqusqbph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ /* MIPS DSPR2 */
+ case OPC_CMPGDU_EQ_QB:
+ gen_helper_cmpgdueqqb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_CMPGDU_LT_QB:
+ gen_helper_cmpgdultqb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_CMPGDU_LE_QB:
+ gen_helper_cmpgduleqb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_PRECR_QB_PH:
+ gen_helper_precrqbph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_PRECR_SRA_PH_W:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_precrsraphw(cpu_gpr[rt], temp_rd,
+ cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_PRECR_SRA_R_PH_W:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_precrsrarphw(cpu_gpr[rt], temp_rd,
+ cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ }
+ }
+ break;
+ case OPC_DPA_W_PH_DSP:
+ op2 = MASK_DPA_W_PH(ctx->opcode);
+ switch(op2){
+ /* MIPS DSP */
+ case OPC_DPAQ_S_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpaqswph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPAQ_SA_L_W:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpaqsalw(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPAU_H_QBL:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpauhqbl(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPAU_H_QBR:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpauhqbr(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPSQ_S_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpsqswph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPSQ_SA_L_W:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpsqsalw(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPSU_H_QBL:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpsuhqbl(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPSU_H_QBR:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpsuhqbr(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_MAQ_S_W_PHL:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_maqswphl(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_MAQ_SA_W_PHL:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_maqsawphl(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_MAQ_S_W_PHR:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_maqswphr(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_MAQ_SA_W_PHR:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_maqsawphr(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_MULSAQ_S_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_mulsaqswph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ /* MIPS DSPR2 */
+ case OPC_DPA_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpawph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPAQX_S_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpaqxswph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPAQX_SA_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpaqxsawph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPAX_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpaxwph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPS_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpswph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPSQX_S_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpsqxswph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPSQX_SA_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpsqxsawph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPSX_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpsxwph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_MULSA_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_mulsawph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ }
+ break;
+ case OPC_EXTR_W_DSP:
+ op2 = MASK_EXTR_W(ctx->opcode);
+ switch(op2){
+ /* MIPS DSP */
+ case OPC_EXTP:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ TCGv temp_rs = tcg_const_i32(rs);
+ TCGv temp_rt = tcg_const_i32(rt);
+ gen_helper_extp(temp_rd, temp_rs, temp_rt);
+ tcg_temp_free(temp_rd);
+ tcg_temp_free(temp_rs);
+ tcg_temp_free(temp_rt);
+ break;
+ }
+ case OPC_EXTPDP:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ TCGv temp_rs = tcg_const_i32(rs);
+ TCGv temp_rt = tcg_const_i32(rt);
+ gen_helper_extpdp(temp_rd, temp_rs, temp_rt);
+ tcg_temp_free(temp_rd);
+ tcg_temp_free(temp_rs);
+ tcg_temp_free(temp_rt);
+ break;
+ }
+ case OPC_EXTPDPV:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ TCGv temp_rt = tcg_const_i32(rt);
+ gen_helper_extpdpv(temp_rd, cpu_gpr[rs], temp_rt);
+ tcg_temp_free(temp_rd);
+ tcg_temp_free(temp_rt);
+ break;
+ }
+ case OPC_EXTPV:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ TCGv temp_rt = tcg_const_i32(rt);
+ gen_helper_extpv(temp_rd, cpu_gpr[rs], temp_rt);
+ tcg_temp_free(temp_rd);
+ tcg_temp_free(temp_rt);
+ break;
+ }
+ case OPC_EXTR_S_H:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ TCGv temp_rs = tcg_const_i32(rs);
+ TCGv temp_rt = tcg_const_i32(rt);
+ gen_helper_extrsh(temp_rd, temp_rs, temp_rt);
+ tcg_temp_free(temp_rd);
+ tcg_temp_free(temp_rs);
+ tcg_temp_free(temp_rt);
+ break;
+ }
+ case OPC_EXTR_W:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ TCGv temp_rs = tcg_const_i32(rs);
+ TCGv temp_rt = tcg_const_i32(rt);
+ gen_helper_extrw(temp_rd, temp_rs, temp_rt);
+ tcg_temp_free(temp_rd);
+ tcg_temp_free(temp_rs);
+ tcg_temp_free(temp_rt);
+ break;
+ }
+ case OPC_EXTR_R_W:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ TCGv temp_rs = tcg_const_i32(rs);
+ TCGv temp_rt = tcg_const_i32(rt);
+ gen_helper_extrrw(temp_rd, temp_rs, temp_rt);
+ tcg_temp_free(temp_rd);
+ tcg_temp_free(temp_rs);
+ tcg_temp_free(temp_rt);
+ break;
+ }
+ case OPC_EXTR_RS_W:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ TCGv temp_rs = tcg_const_i32(rs);
+ TCGv temp_rt = tcg_const_i32(rt);
+ gen_helper_extrrsw(temp_rd, temp_rs, temp_rt);
+ tcg_temp_free(temp_rd);
+ tcg_temp_free(temp_rs);
+ tcg_temp_free(temp_rt);
+ break;
+ }
+ case OPC_EXTRV_S_H:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_extrvsh(cpu_gpr[rt], temp_rd, cpu_gpr[rs]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_EXTRV_W:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ TCGv temp_rt = tcg_const_i32(rt);
+ gen_helper_extrvw(temp_rd, cpu_gpr[rs], temp_rt);
+ tcg_temp_free(temp_rd);
+ tcg_temp_free(temp_rt);
+ break;
+ }
+ case OPC_EXTRV_R_W:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ TCGv temp_rt = tcg_const_i32(rt);
+ gen_helper_extrvrw(temp_rd, cpu_gpr[rs], temp_rt);
+ tcg_temp_free(temp_rd);
+ tcg_temp_free(temp_rt);
+ break;
+ }
+ case OPC_EXTRV_RS_W:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ TCGv temp_rt = tcg_const_i32(rt);
+ gen_helper_extrvrsw(temp_rd, cpu_gpr[rs], temp_rt);
+ tcg_temp_free(temp_rd);
+ tcg_temp_free(temp_rt);
+ break;
+ }
+ case OPC_MTHLIP:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_mthlip(temp_rd, cpu_gpr[rs]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_RDDSP:
+ {
+ TCGv temp_imm;
+ imm = (ctx->opcode>> 16)& 0x03FF;
+ temp_imm = tcg_const_i32(imm);
+ gen_helper_rddsp(cpu_gpr[rd], temp_imm);
+ tcg_temp_free(temp_imm);
+ break;
+ }
+ case OPC_SHILO:
+ {
+ TCGv temp_imm;
+ TCGv temp_rd = tcg_const_i32(rd);
+ imm = (ctx->opcode>> 20)& 0x3F;
+ temp_imm = tcg_const_i32(imm);
+ gen_helper_shilo(temp_rd, temp_imm);
+ tcg_temp_free(temp_imm);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_SHILOV:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_shilov(temp_rd, cpu_gpr[rs]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_WRDSP:
+ {
+ TCGv temp_imm;
+ imm = (ctx->opcode>> 11)& 0x3FF;
+ temp_imm = tcg_const_i32(imm);
+ gen_helper_wrdsp(cpu_gpr[rs], temp_imm);
+ tcg_temp_free(temp_imm);
+ break;
+ }
+ }
+ break;
+ case OPC_INSV_DSP:
+ op2 = MASK_INSV(ctx->opcode);
+ switch(op2) {
+ /* MIPS DSP */
+ case OPC_INSV:
+ {
+ TCGv temp_rt = tcg_const_i32(rt);
+ gen_helper_insv(temp_rt, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rt);
+ break;
+ }
+ }
+ 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;
+ case OPC_SHLL_QB_DSP:
+ {
+ TCGv temp_rs = tcg_const_i32(rs);
+ op2 = MASK_SHLL_QB(ctx->opcode);
+ switch(op2){