*/
 enum cop_op {
        mfc_op        = 0x00, dmfc_op       = 0x01,
-       cfc_op        = 0x02, mtc_op        = 0x04,
-       dmtc_op       = 0x05, ctc_op        = 0x06,
+       cfc_op        = 0x02, mfhc_op       = 0x03,
+       mtc_op        = 0x04, dmtc_op       = 0x05,
+       ctc_op        = 0x06, mthc_op       = 0x07,
        bc_op         = 0x08, cop_op        = 0x10,
        copm_op       = 0x18
 };
 
                        ctx->fpr[x & ~1] >> 32 << 32 | (u32)(si) : \
                        ctx->fpr[x & ~1] << 32 >> 32 | (u64)(si) << 32)
 
+#define SIFROMHREG(si, x)      ((si) = (int)(ctx->fpr[x] >> 32))
+#define SITOHREG(si, x)                (ctx->fpr[x] = \
+                               ctx->fpr[x] << 32 >> 32 | (u64)(si) << 32)
+
 #define DIFROMREG(di, x) ((di) = ctx->fpr[x & ~(cop1_64bit(xcp) == 0)])
 #define DITOREG(di, x) (ctx->fpr[x & ~(cop1_64bit(xcp) == 0)] = (di))
 
                        break;
 #endif
 
+               case mfhc_op:
+                       if (!cpu_has_mips_r2)
+                               goto sigill;
+
+                       /* copregister rd -> gpr[rt] */
+                       if (MIPSInst_RT(ir) != 0) {
+                               SIFROMHREG(xcp->regs[MIPSInst_RT(ir)],
+                                       MIPSInst_RD(ir));
+                       }
+                       break;
+
+               case mthc_op:
+                       if (!cpu_has_mips_r2)
+                               goto sigill;
+
+                       /* copregister rd <- gpr[rt] */
+                       SITOHREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));
+                       break;
+
                case mfc_op:
                        /* copregister rd -> gpr[rt] */
                        if (MIPSInst_RT(ir) != 0) {
 #endif
 
        default:
+sigill:
                return SIGILL;
        }