* better performance by compiling with -msoft-float!
*/
#include <linux/sched.h>
+#include <linux/debugfs.h>
#include <asm/inst.h>
#include <asm/bootinfo.h>
-#include <asm/cpu.h>
-#include <asm/cpu-features.h>
#include <asm/processor.h>
#include <asm/ptrace.h>
#include <asm/signal.h>
#define FR_BIT 0
#endif
-#define SIFROMREG(si,x) ((si) = \
+#define SIFROMREG(si, x) ((si) = \
(xcp->cp0_status & FR_BIT) || !(x & 1) ? \
(int)ctx->fpr[x] : \
(int)(ctx->fpr[x & ~1] >> 32 ))
-#define SITOREG(si,x) (ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)] = \
+#define SITOREG(si, x) (ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)] = \
(xcp->cp0_status & FR_BIT) || !(x & 1) ? \
ctx->fpr[x & ~1] >> 32 << 32 | (u32)(si) : \
ctx->fpr[x & ~1] << 32 >> 32 | (u64)(si) << 32)
-#define DIFROMREG(di,x) ((di) = \
+#define DIFROMREG(di, x) ((di) = \
ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)])
-#define DITOREG(di,x) (ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)] \
+#define DITOREG(di, x) (ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)] \
= (di))
-#define SPFROMREG(sp,x) SIFROMREG((sp).bits,x)
-#define SPTOREG(sp,x) SITOREG((sp).bits,x)
-#define DPFROMREG(dp,x) DIFROMREG((dp).bits,x)
-#define DPTOREG(dp,x) DITOREG((dp).bits,x)
+#define SPFROMREG(sp, x) SIFROMREG((sp).bits, x)
+#define SPTOREG(sp, x) SITOREG((sp).bits, x)
+#define DPFROMREG(dp, x) DIFROMREG((dp).bits, x)
+#define DPTOREG(dp, x) DITOREG((dp).bits, x)
/*
* Emulate the single floating point instruction pointed at by EPC.
static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
{
mips_instruction ir;
- void * emulpc, *contpc;
+ unsigned long emulpc, contpc;
unsigned int cond;
if (get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) {
* Linux MIPS branch emulator operates on context, updating the
* cp0_epc.
*/
- emulpc = (void *) (xcp->cp0_epc + 4); /* Snapshot emulation target */
+ emulpc = xcp->cp0_epc + 4; /* Snapshot emulation target */
if (__compute_return_epc(xcp)) {
#ifdef CP1DBG
return SIGBUS;
}
/* __compute_return_epc() will have updated cp0_epc */
- contpc = (void *) xcp->cp0_epc;
+ contpc = xcp->cp0_epc;
/* In order not to confuse ptrace() et al, tweak context */
- xcp->cp0_epc = (unsigned long) emulpc - 4;
+ xcp->cp0_epc = emulpc - 4;
} else {
- emulpc = (void *) xcp->cp0_epc;
- contpc = (void *) (xcp->cp0_epc + 4);
+ emulpc = xcp->cp0_epc;
+ contpc = xcp->cp0_epc + 4;
}
emul:
* instruction
*/
xcp->cp0_epc += 4;
- contpc = (void *)
- (xcp->cp0_epc +
+ contpc = (xcp->cp0_epc +
(MIPSInst_SIMM(ir) << 2));
if (get_user(ir,
* Single step the non-cp1
* instruction in the dslot
*/
- return mips_dsemul(xcp, ir, (unsigned long) contpc);
+ return mips_dsemul(xcp, ir, contpc);
}
else {
/* branch not taken */
}
/* we did it !! */
- xcp->cp0_epc = (unsigned long) contpc;
+ xcp->cp0_epc = contpc;
xcp->cp0_cause &= ~CAUSEF_BD;
return 0;
*/
#define DEF3OP(name, p, f1, f2, f3) \
-static ieee754##p fpemu_##p##_##name (ieee754##p r, ieee754##p s, \
+static ieee754##p fpemu_##p##_##name(ieee754##p r, ieee754##p s, \
ieee754##p t) \
{ \
struct _ieee754_csr ieee754_csr_save; \
- s = f1 (s, t); \
+ s = f1(s, t); \
ieee754_csr_save = ieee754_csr; \
- s = f2 (s, r); \
+ s = f2(s, r); \
ieee754_csr_save.cx |= ieee754_csr.cx; \
ieee754_csr_save.sx |= ieee754_csr.sx; \
- s = f3 (s); \
+ s = f3(s); \
ieee754_csr.cx |= ieee754_csr_save.cx; \
ieee754_csr.sx |= ieee754_csr_save.sx; \
return s; \
return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s));
}
-DEF3OP(madd, sp, ieee754sp_mul, ieee754sp_add,);
-DEF3OP(msub, sp, ieee754sp_mul, ieee754sp_sub,);
+DEF3OP(madd, sp, ieee754sp_mul, ieee754sp_add, );
+DEF3OP(msub, sp, ieee754sp_mul, ieee754sp_sub, );
DEF3OP(nmadd, sp, ieee754sp_mul, ieee754sp_add, ieee754sp_neg);
DEF3OP(nmsub, sp, ieee754sp_mul, ieee754sp_sub, ieee754sp_neg);
-DEF3OP(madd, dp, ieee754dp_mul, ieee754dp_add,);
-DEF3OP(msub, dp, ieee754dp_mul, ieee754dp_sub,);
+DEF3OP(madd, dp, ieee754dp_mul, ieee754dp_add, );
+DEF3OP(msub, dp, ieee754dp_mul, ieee754dp_sub, );
DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg);
DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg);
return 0;
}
-int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
+int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
+ int has_fpu)
{
unsigned long oldepc, prevepc;
mips_instruction insn;
ieee754_csr.rm = mips_rm[ieee754_csr.rm];
}
- if (cpu_has_fpu)
+ if (has_fpu)
break;
if (sig)
break;
return sig;
}
+
+#ifdef CONFIG_DEBUG_FS
+extern struct dentry *mips_debugfs_dir;
+static int __init debugfs_fpuemu(void)
+{
+ struct dentry *d, *dir;
+ int i;
+ static struct {
+ const char *name;
+ unsigned int *v;
+ } vars[] __initdata = {
+ { "emulated", &fpuemustats.emulated },
+ { "loads", &fpuemustats.loads },
+ { "stores", &fpuemustats.stores },
+ { "cp1ops", &fpuemustats.cp1ops },
+ { "cp1xops", &fpuemustats.cp1xops },
+ { "errors", &fpuemustats.errors },
+ };
+
+ if (!mips_debugfs_dir)
+ return -ENODEV;
+ dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir);
+ if (!dir)
+ return -ENOMEM;
+ for (i = 0; i < ARRAY_SIZE(vars); i++) {
+ d = debugfs_create_u32(vars[i].name, S_IRUGO, dir, vars[i].v);
+ if (!d)
+ return -ENOMEM;
+ }
+ return 0;
+}
+__initcall(debugfs_fpuemu);
+#endif