qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 3/4] add MIPS DSP translation


From: Jia Liu
Subject: [Qemu-devel] [PATCH 3/4] add MIPS DSP translation
Date: Mon, 12 Mar 2012 16:32:38 +0800

This patch is the translation of MIPS ASE DSP.

Signed-off-by: Jia Liu <address@hidden>
---
 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){
+              /* MIPS DSP */
+              case OPC_SHLL_PH:
+                  gen_helper_shllph(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+                  break;
+              case OPC_SHLL_S_PH:
+                  gen_helper_shllsph(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+                  break;
+              case OPC_SHLL_QB:
+                  gen_helper_shllqb(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+                  break;
+              case OPC_SHLL_S_W:
+                  gen_helper_shllsw(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+                  break;
+              case OPC_SHLLV_PH:
+                  gen_helper_shllvph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                  break;
+              case OPC_SHLLV_S_PH:
+                  gen_helper_shllvsph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                  break;
+              case OPC_SHLLV_QB:
+                  gen_helper_shllvqb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                  break;
+              case OPC_SHLLV_S_W:
+                  gen_helper_shllvsw(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                  break;
+              case OPC_SHRA_PH:
+                  gen_helper_shraph(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+                  break;
+              case OPC_SHRA_R_PH:
+                  gen_helper_shrarph(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+                  break;
+              case OPC_SHRA_R_W:
+                  gen_helper_shrarw(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+                  break;
+              case OPC_SHRAV_PH:
+                  gen_helper_shravph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                  break;
+              case OPC_SHRAV_R_PH:
+                  gen_helper_shravrph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                  break;
+              case OPC_SHRAV_R_W:
+                  gen_helper_shravrw(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                  break;
+              case OPC_SHRL_QB:
+                  gen_helper_shrlqb(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+                  break;
+              case OPC_SHRLV_QB:
+                  gen_helper_shrlvqb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                  break;
+              /* MIPS DSPR2 */
+              case OPC_SHRA_QB:
+                  gen_helper_shraqb(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+                  break;
+              case OPC_SHRA_R_QB:
+                  gen_helper_shrarqb(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+                  break;
+              case OPC_SHRAV_QB:
+                  gen_helper_shravqb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                  break;
+              case OPC_SHRAV_R_QB:
+                  gen_helper_shravrqb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                  break;
+              case OPC_SHRL_PH:
+                  gen_helper_shrlph(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+                  break;
+              case OPC_SHRLV_PH:
+                  gen_helper_shrlvph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                  break;
+              }
+              tcg_temp_free(temp_rs);
+              break;
+          }
 #if defined(TARGET_MIPS64)
         case OPC_DEXTM ... OPC_DEXT:
         case OPC_DINSM ... OPC_DINS:
@@ -12079,6 +13135,12 @@ static void decode_opc (CPUState *env, DisasContext 
*ctx, int *is_branch)
             check_insn(env, ctx, ISA_MIPS32R2);
             /* Treat as NOP. */
             break;
+        case OPC_BPOSGE32:    /* mipsdsp branch */
+            {
+                gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2);
+                *is_branch = 1;
+                break;
+            }
         default:            /* Invalid */
             MIPS_INVAL("regimm");
             generate_exception(ctx, EXCP_RI);
-- 
1.7.5.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]