qemu-devel
[Top][All Lists]
Advanced

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

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


From: Stefan Weil
Subject: Re: [Qemu-devel] [PATCH 3/4] add MIPS DSP translation
Date: Wed, 21 Mar 2012 09:33:24 +0100
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.16) Gecko/20120207 Iceowl/1.0b1 Icedove/3.0.11

Please see my inline comments.

Regards,
Stefan Weil


Am 12.03.2012 09:32, schrieb Jia Liu:
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;

acc is an unsigned value, isn't it?
Is the initialization with 0 needed here?


      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){

Missing space before {. There are more lines like this.

+              /* 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;
+            }

Is there any reason for the {} used here?

          default:            /* Invalid */
              MIPS_INVAL("regimm");
              generate_exception(ctx, EXCP_RI);




reply via email to

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