MIPS: math-emu: Add mfhc1 & mthc1 support.
authorLeonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Thu, 7 Nov 2013 12:48:28 +0000 (12:48 +0000)
committerRalf Baechle <ralf@linux-mips.org>
Mon, 13 Jan 2014 22:40:55 +0000 (23:40 +0100)
This patch adds support for the mfhc1 & mthc1 instructions to the FPU
emulator. These instructions were introduced in release 2 of the MIPS32
& MIPS64 architectures and allow access to the most significant 32 bits
of a 64-bit FP register.

[ralf@linux-mips.org: Fix ifdef hell added by original patch.]

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Steven J. Hill <Steven.Hill@imgtec.com>
Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/6112/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/include/uapi/asm/inst.h
arch/mips/math-emu/cp1emu.c

index e5a676e3d3c04ce267dc6254652ff48520565823..0ee96563e6f0f3918690afbabd56c7f9dc544db8 100644 (file)
@@ -98,8 +98,9 @@ enum rt_op {
  */
 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
 };
index efe008846ed056759dd2e66c83a54cfe2d4d789c..aaf7c92f462994da9fd5f6b112248b8a1adb28a9 100644 (file)
@@ -878,6 +878,10 @@ static inline int cop1_64bit(struct pt_regs *xcp)
                        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))
 
@@ -1055,6 +1059,25 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                        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) {
@@ -1263,6 +1286,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 #endif
 
        default:
+sigill:
                return SIGILL;
        }