diff --git a/target-mips/translate.c b/target-mips/translate.c
index 206ba83..d1f3106 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -2571,10 +2571,9 @@ static void gen_shift (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
 }
 
 /* Arithmetic on HI/LO registers */
-static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
+static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
 {
     const char *opn = "hilo";
-    unsigned int acc;
 
     if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
         /* Treat as NOP. */
@@ -2582,12 +2581,6 @@ static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
         return;
     }
 
-    if (opc == OPC_MFHI || opc == OPC_MFLO) {
-        acc = ((ctx->opcode) >> 21) & 0x03;
-    } else {
-        acc = ((ctx->opcode) >> 11) & 0x03;
-    }
-
     if (acc != 0) {
         check_dsp(ctx);
     }
@@ -2650,12 +2643,11 @@ static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
     MIPS_DEBUG("%s %s", opn, regnames[reg]);
 }
 
-static void gen_muldiv (DisasContext *ctx, uint32_t opc,
-                        int rs, int rt)
+static void gen_muldiv(DisasContext *ctx, uint32_t opc,
+                       int acc, int rs, int rt)
 {
     const char *opn = "mul/div";
     TCGv t0, t1;
-    unsigned int acc;
 
     t0 = tcg_temp_new();
     t1 = tcg_temp_new();
@@ -2663,6 +2655,10 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
     gen_load_gpr(t0, rs);
     gen_load_gpr(t1, rt);
 
+    if (acc != 0) {
+        check_dsp(ctx);
+    }
+
     switch (opc) {
     case OPC_DIV:
         {
@@ -2677,10 +2673,10 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
             tcg_gen_or_tl(t2, t2, t3);
             tcg_gen_movi_tl(t3, 0);
             tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
-            tcg_gen_div_tl(cpu_LO[0], t0, t1);
-            tcg_gen_rem_tl(cpu_HI[0], t0, t1);
-            tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
-            tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
+            tcg_gen_div_tl(cpu_LO[acc], t0, t1);
+            tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
+            tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
+            tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
             tcg_temp_free(t3);
             tcg_temp_free(t2);
         }
@@ -2693,10 +2689,10 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
             tcg_gen_ext32u_tl(t0, t0);
             tcg_gen_ext32u_tl(t1, t1);
             tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
-            tcg_gen_divu_tl(cpu_LO[0], t0, t1);
-            tcg_gen_remu_tl(cpu_HI[0], t0, t1);
-            tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
-            tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
+            tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
+            tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
+            tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
+            tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
             tcg_temp_free(t3);
             tcg_temp_free(t2);
         }
@@ -2706,10 +2702,6 @@ 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;
-            if (acc != 0) {
-                check_dsp(ctx);
-            }
 
             tcg_gen_ext_tl_i64(t2, t0);
             tcg_gen_ext_tl_i64(t3, t1);
@@ -2728,10 +2720,6 @@ 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;
-            if (acc != 0) {
-                check_dsp(ctx);
-            }
 
             tcg_gen_ext32u_tl(t0, t0);
             tcg_gen_ext32u_tl(t1, t1);
@@ -2760,8 +2748,8 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
             tcg_gen_or_tl(t2, t2, t3);
             tcg_gen_movi_tl(t3, 0);
             tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
-            tcg_gen_div_tl(cpu_LO[0], t0, t1);
-            tcg_gen_rem_tl(cpu_HI[0], t0, t1);
+            tcg_gen_div_tl(cpu_LO[acc], t0, t1);
+            tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
             tcg_temp_free(t3);
             tcg_temp_free(t2);
         }
@@ -2772,8 +2760,8 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
             TCGv t2 = tcg_const_tl(0);
             TCGv t3 = tcg_const_tl(1);
             tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
-            tcg_gen_divu_i64(cpu_LO[0], t0, t1);
-            tcg_gen_remu_i64(cpu_HI[0], t0, t1);
+            tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
+            tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
             tcg_temp_free(t3);
             tcg_temp_free(t2);
         }
@@ -2792,10 +2780,6 @@ 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;
-            if (acc != 0) {
-                check_dsp(ctx);
-            }
 
             tcg_gen_ext_tl_i64(t2, t0);
             tcg_gen_ext_tl_i64(t3, t1);
@@ -2816,10 +2800,6 @@ 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;
-            if (acc != 0) {
-                check_dsp(ctx);
-            }
 
             tcg_gen_ext32u_tl(t0, t0);
             tcg_gen_ext32u_tl(t1, t1);
@@ -2842,10 +2822,6 @@ 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;
-            if (acc != 0) {
-                check_dsp(ctx);
-            }
 
             tcg_gen_ext_tl_i64(t2, t0);
             tcg_gen_ext_tl_i64(t3, t1);
@@ -2866,10 +2842,6 @@ 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;
-            if (acc != 0) {
-                check_dsp(ctx);
-            }
 
             tcg_gen_ext32u_tl(t0, t0);
             tcg_gen_ext32u_tl(t1, t1);
@@ -10134,7 +10106,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
             gen_logic(env, ctx, OPC_NOR, rx, ry, 0);
             break;
         case RR_MFHI:
-            gen_HILO(ctx, OPC_MFHI, rx);
+            gen_HILO(ctx, OPC_MFHI, 0, rx);
             break;
         case RR_CNVT:
             switch (cnvt_op) {
@@ -10166,7 +10138,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
             }
             break;
         case RR_MFLO:
-            gen_HILO(ctx, OPC_MFLO, rx);
+            gen_HILO(ctx, OPC_MFLO, 0, rx);
             break;
 #if defined (TARGET_MIPS64)
         case RR_DSRA:
@@ -10187,33 +10159,33 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
             break;
 #endif
         case RR_MULT:
-            gen_muldiv(ctx, OPC_MULT, rx, ry);
+            gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
             break;
         case RR_MULTU:
-            gen_muldiv(ctx, OPC_MULTU, rx, ry);
+            gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
             break;
         case RR_DIV:
-            gen_muldiv(ctx, OPC_DIV, rx, ry);
+            gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
             break;
         case RR_DIVU:
-            gen_muldiv(ctx, OPC_DIVU, rx, ry);
+            gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
             break;
 #if defined (TARGET_MIPS64)
         case RR_DMULT:
             check_mips_64(ctx);
-            gen_muldiv(ctx, OPC_DMULT, rx, ry);
+            gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
             break;
         case RR_DMULTU:
             check_mips_64(ctx);
-            gen_muldiv(ctx, OPC_DMULTU, rx, ry);
+            gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
             break;
         case RR_DDIV:
             check_mips_64(ctx);
-            gen_muldiv(ctx, OPC_DDIV, rx, ry);
+            gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
             break;
         case RR_DDIVU:
             check_mips_64(ctx);
-            gen_muldiv(ctx, OPC_DDIVU, rx, ry);
+            gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
             break;
 #endif
         default:
@@ -10922,11 +10894,11 @@ static void gen_pool16c_insn (CPUMIPSState *env, DisasContext *ctx, int *is_bran
         break;
     case MFHI16 + 0:
     case MFHI16 + 1:
-        gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
+        gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
         break;
     case MFLO16 + 0:
     case MFLO16 + 1:
-        gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
+        gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
         break;
     case BREAK16:
         generate_exception(ctx, EXCP_BREAK);
@@ -11124,30 +11096,33 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
             break;
         case MULT:
             mips32_op = OPC_MULT;
-            goto do_muldiv;
+            goto do_mul;
         case MULTU:
             mips32_op = OPC_MULTU;
-            goto do_muldiv;
+            goto do_mul;
         case DIV:
             mips32_op = OPC_DIV;
-            goto do_muldiv;
+            goto do_div;
         case DIVU:
             mips32_op = OPC_DIVU;
-            goto do_muldiv;
+        do_div:
+            check_insn(env, ctx, ISA_MIPS32);
+            gen_muldiv(ctx, mips32_op, 0, rs, rt);
+            break;
         case MADD:
             mips32_op = OPC_MADD;
-            goto do_muldiv;
+            goto do_mul;
         case MADDU:
             mips32_op = OPC_MADDU;
-            goto do_muldiv;
+            goto do_mul;
         case MSUB:
             mips32_op = OPC_MSUB;
-            goto do_muldiv;
+            goto do_mul;
         case MSUBU:
             mips32_op = OPC_MSUBU;
-        do_muldiv:
+        do_mul:
             check_insn(env, ctx, ISA_MIPS32);
-            gen_muldiv(ctx, mips32_op, rs, rt);
+            gen_muldiv(ctx, mips32_op, (ctx->opcode >> 14) & 3, rs, rt);
             break;
         default:
             goto pool32axf_invalid;
@@ -11284,18 +11259,18 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
         }
         break;
     case 0x35:
-        switch (minor) {
+        switch (minor & 3) {
         case MFHI32:
-            gen_HILO(ctx, OPC_MFHI, rs);
+            gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
             break;
         case MFLO32:
-            gen_HILO(ctx, OPC_MFLO, rs);
+            gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
             break;
         case MTHI32:
-            gen_HILO(ctx, OPC_MTHI, rs);
+            gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
             break;
         case MTLO32:
-            gen_HILO(ctx, OPC_MTLO, rs);
+            gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
             break;
         default:
             goto pool32axf_invalid;
@@ -14429,13 +14404,18 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
         case OPC_XOR:
             gen_logic(env, ctx, op1, rd, rs, rt);
             break;
-        case OPC_MULT ... OPC_DIVU:
+        case OPC_MULT:
+        case OPC_MULTU:
             if (sa) {
                 check_insn(env, ctx, INSN_VR54XX);
                 op1 = MASK_MUL_VR54XX(ctx->opcode);
                 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
             } else
-                gen_muldiv(ctx, op1, rs, rt);
+                gen_muldiv(ctx, op1, rd & 3, rs, rt);
+            break;
+        case OPC_DIV:
+        case OPC_DIVU:
+            gen_muldiv(ctx, op1, 0, rs, rt);
             break;
         case OPC_JR ... OPC_JALR:
             gen_compute_branch(ctx, op1, 4, rs, rd, sa);
@@ -14447,11 +14427,11 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             break;
         case OPC_MFHI:          /* Move from HI/LO */
         case OPC_MFLO:
-            gen_HILO(ctx, op1, rd);
+            gen_HILO(ctx, op1, rs & 3, rd);
             break;
         case OPC_MTHI:
         case OPC_MTLO:          /* Move to HI/LO */
-            gen_HILO(ctx, op1, rs);
+            gen_HILO(ctx, op1, rd & 3, rs);
             break;
         case OPC_PMON:          /* Pmon entry point, also R4010 selsl */
 #ifdef MIPS_STRICT_STANDARD
@@ -14571,7 +14551,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
         case OPC_DMULT ... OPC_DDIVU:
             check_insn(env, ctx, ISA_MIPS3);
             check_mips_64(ctx);
-            gen_muldiv(ctx, op1, rs, rt);
+            gen_muldiv(ctx, op1, 0, rs, rt);
             break;
 #endif
         default:            /* Invalid */
@@ -14586,7 +14566,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
         case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
         case OPC_MSUB ... OPC_MSUBU:
             check_insn(env, ctx, ISA_MIPS32);
-            gen_muldiv(ctx, op1, rs, rt);
+            gen_muldiv(ctx, op1, rd & 3, rs, rt);
             break;
         case OPC_MUL:
             gen_arith(env, ctx, op1, rd, rs, rt);
