]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/mips/math-emu/cp1emu.c
GCC bulletproofing: __mips64 is only defined when compiling for 64-bit
[linux-2.6-omap-h63xx.git] / arch / mips / math-emu / cp1emu.c
index 99c550632d44a541f29a7c70ee7052ae09869fa9..096780ce939de880e778806147a599a1fe1bb2c5 100644 (file)
@@ -70,7 +70,7 @@ static int fpux_emu(struct pt_regs *,
 
 /* Further private data for which no space exists in mips_fpu_soft_struct */
 
-struct mips_fpu_emulator_private fpuemuprivate;
+struct mips_fpu_emulator_stats fpuemustats;
 
 /* Control registers */
 
@@ -79,7 +79,17 @@ struct mips_fpu_emulator_private fpuemuprivate;
 
 /* Convert Mips rounding mode (0..3) to IEEE library modes. */
 static const unsigned char ieee_rm[4] = {
-       IEEE754_RN, IEEE754_RZ, IEEE754_RU, IEEE754_RD
+       [FPU_CSR_RN] = IEEE754_RN,
+       [FPU_CSR_RZ] = IEEE754_RZ,
+       [FPU_CSR_RU] = IEEE754_RU,
+       [FPU_CSR_RD] = IEEE754_RD,
+};
+/* Convert IEEE library modes to Mips rounding mode (0..3). */
+static const unsigned char mips_rm[4] = {
+       [IEEE754_RN] = FPU_CSR_RN,
+       [IEEE754_RZ] = FPU_CSR_RZ,
+       [IEEE754_RD] = FPU_CSR_RD,
+       [IEEE754_RU] = FPU_CSR_RU,
 };
 
 #if __mips >= 4
@@ -196,11 +206,11 @@ static int isBranchInstr(mips_instruction * i)
 static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
 {
        mips_instruction ir;
-       vaddr_t emulpc, contpc;
+       void * emulpc, *contpc;
        unsigned int cond;
 
        if (get_user(ir, (mips_instruction *) xcp->cp0_epc)) {
-               fpuemuprivate.stats.errors++;
+               fpuemustats.errors++;
                return SIGBUS;
        }
 
@@ -221,41 +231,40 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
                 * Linux MIPS branch emulator operates on context, updating the
                 * cp0_epc.
                 */
-               emulpc = REG_TO_VA(xcp->cp0_epc + 4);   /* Snapshot emulation target */
+               emulpc = (void *) (xcp->cp0_epc + 4);   /* Snapshot emulation target */
 
                if (__compute_return_epc(xcp)) {
 #ifdef CP1DBG
                        printk("failed to emulate branch at %p\n",
-                               REG_TO_VA(xcp->cp0_epc));
+                               (void *) (xcp->cp0_epc));
 #endif
                        return SIGILL;
                }
                if (get_user(ir, (mips_instruction *) emulpc)) {
-                       fpuemuprivate.stats.errors++;
+                       fpuemustats.errors++;
                        return SIGBUS;
                }
                /* __compute_return_epc() will have updated cp0_epc */
-               contpc = REG_TO_VA xcp->cp0_epc;
+               contpc = (void *)  xcp->cp0_epc;
                /* In order not to confuse ptrace() et al, tweak context */
-               xcp->cp0_epc = VA_TO_REG emulpc - 4;
-       }
-       else {
-               emulpc = REG_TO_VA xcp->cp0_epc;
-               contpc = REG_TO_VA(xcp->cp0_epc + 4);
+               xcp->cp0_epc = (unsigned long) emulpc - 4;
+       } else {
+               emulpc = (void *)  xcp->cp0_epc;
+               contpc = (void *) (xcp->cp0_epc + 4);
        }
 
       emul:
-       fpuemuprivate.stats.emulated++;
+       fpuemustats.emulated++;
        switch (MIPSInst_OPCODE(ir)) {
 #ifndef SINGLE_ONLY_FPU
        case ldc1_op:{
-               u64 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] +
+               u64 *va = (void *) (xcp->regs[MIPSInst_RS(ir)] +
                        MIPSInst_SIMM(ir));
                u64 val;
 
-               fpuemuprivate.stats.loads++;
+               fpuemustats.loads++;
                if (get_user(val, va)) {
-                       fpuemuprivate.stats.errors++;
+                       fpuemustats.errors++;
                        return SIGBUS;
                }
                DITOREG(val, MIPSInst_RT(ir));
@@ -263,14 +272,14 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
        }
 
        case sdc1_op:{
-               u64 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] +
+               u64 *va = (void *) (xcp->regs[MIPSInst_RS(ir)] +
                        MIPSInst_SIMM(ir));
                u64 val;
 
-               fpuemuprivate.stats.stores++;
+               fpuemustats.stores++;
                DIFROMREG(val, MIPSInst_RT(ir));
                if (put_user(val, va)) {
-                       fpuemuprivate.stats.errors++;
+                       fpuemustats.errors++;
                        return SIGBUS;
                }
                break;
@@ -278,13 +287,13 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
 #endif
 
        case lwc1_op:{
-               u32 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] +
+               u32 *va = (void *) (xcp->regs[MIPSInst_RS(ir)] +
                        MIPSInst_SIMM(ir));
                u32 val;
 
-               fpuemuprivate.stats.loads++;
+               fpuemustats.loads++;
                if (get_user(val, va)) {
-                       fpuemuprivate.stats.errors++;
+                       fpuemustats.errors++;
                        return SIGBUS;
                }
 #ifdef SINGLE_ONLY_FPU
@@ -298,11 +307,11 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
        }
 
        case swc1_op:{
-               u32 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] +
+               u32 *va = (void *) (xcp->regs[MIPSInst_RS(ir)] +
                        MIPSInst_SIMM(ir));
                u32 val;
 
-               fpuemuprivate.stats.stores++;
+               fpuemustats.stores++;
 #ifdef SINGLE_ONLY_FPU
                if (MIPSInst_RT(ir) & 1) {
                        /* illegal register in single-float mode */
@@ -311,7 +320,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
 #endif
                SIFROMREG(val, MIPSInst_RT(ir));
                if (put_user(val, va)) {
-                       fpuemuprivate.stats.errors++;
+                       fpuemustats.errors++;
                        return SIGBUS;
                }
                break;
@@ -369,9 +378,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
                        }
                        if (MIPSInst_RD(ir) == FPCREG_CSR) {
                                value = ctx->fcr31;
+                               value = (value & ~0x3) | mips_rm[value & 0x3];
 #ifdef CSRTRACE
                                printk("%p gpr[%d]<-csr=%08x\n",
-                                       REG_TO_VA(xcp->cp0_epc),
+                                       (void *) (xcp->cp0_epc),
                                        MIPSInst_RT(ir), value);
 #endif
                        }
@@ -398,14 +408,13 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
                        if (MIPSInst_RD(ir) == FPCREG_CSR) {
 #ifdef CSRTRACE
                                printk("%p gpr[%d]->csr=%08x\n",
-                                       REG_TO_VA(xcp->cp0_epc),
+                                       (void *) (xcp->cp0_epc),
                                        MIPSInst_RT(ir), value);
 #endif
-                               ctx->fcr31 = value;
-                               /* copy new rounding mode and
-                                  flush bit to ieee library state! */
-                               ieee754_csr.nod = (ctx->fcr31 & 0x1000000) != 0;
-                               ieee754_csr.rm = ieee_rm[value & 0x3];
+                               value &= (FPU_CSR_FLUSH | FPU_CSR_ALL_E | FPU_CSR_ALL_S | 0x03);
+                               ctx->fcr31 &= ~(FPU_CSR_FLUSH | FPU_CSR_ALL_E | FPU_CSR_ALL_S | 0x03);
+                               /* convert to ieee library modes */
+                               ctx->fcr31 |= (value & ~0x3) | ieee_rm[value & 0x3];
                        }
                        if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
                                return SIGFPE;
@@ -445,20 +454,20 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
                                 * instruction
                                 */
                                xcp->cp0_epc += 4;
-                               contpc = REG_TO_VA
+                               contpc = (void *)
                                        (xcp->cp0_epc +
                                        (MIPSInst_SIMM(ir) << 2));
 
                                if (get_user(ir, (mips_instruction *)
-                                               REG_TO_VA xcp->cp0_epc)) {
-                                       fpuemuprivate.stats.errors++;
+                                               (void *)  xcp->cp0_epc)) {
+                                       fpuemustats.errors++;
                                        return SIGBUS;
                                }
 
                                switch (MIPSInst_OPCODE(ir)) {
                                case lwc1_op:
                                case swc1_op:
-#if (__mips >= 2 || __mips64) && !defined(SINGLE_ONLY_FPU)
+#if (__mips >= 2 || defined(__mips64)) && !defined(SINGLE_ONLY_FPU)
                                case ldc1_op:
                                case sdc1_op:
 #endif
@@ -480,7 +489,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
                                 * Single step the non-cp1
                                 * instruction in the dslot
                                 */
-                               return mips_dsemul(xcp, ir, VA_TO_REG contpc);
+                               return mips_dsemul(xcp, ir, (unsigned long) contpc);
                        }
                        else {
                                /* branch not taken */
@@ -539,8 +548,9 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
        }
 
        /* we did it !! */
-       xcp->cp0_epc = VA_TO_REG(contpc);
+       xcp->cp0_epc = (unsigned long) contpc;
        xcp->cp0_cause &= ~CAUSEF_BD;
+
        return 0;
 }
 
@@ -570,7 +580,7 @@ static const unsigned char cmptab[8] = {
 static ieee754##p fpemu_##p##_##name (ieee754##p r, ieee754##p s, \
     ieee754##p t) \
 { \
-       struct ieee754_csr ieee754_csr_save; \
+       struct _ieee754_csr ieee754_csr_save; \
        s = f1 (s, t); \
        ieee754_csr_save = ieee754_csr; \
        s = f2 (s, r); \
@@ -616,7 +626,7 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
 {
        unsigned rcsr = 0;      /* resulting csr */
 
-       fpuemuprivate.stats.cp1xops++;
+       fpuemustats.cp1xops++;
 
        switch (MIPSInst_FMA_FFMT(ir)) {
        case s_fmt:{            /* 0 */
@@ -628,12 +638,12 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
 
                switch (MIPSInst_FUNC(ir)) {
                case lwxc1_op:
-                       va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] +
+                       va = (void *) (xcp->regs[MIPSInst_FR(ir)] +
                                xcp->regs[MIPSInst_FT(ir)]);
 
-                       fpuemuprivate.stats.loads++;
+                       fpuemustats.loads++;
                        if (get_user(val, va)) {
-                               fpuemuprivate.stats.errors++;
+                               fpuemustats.errors++;
                                return SIGBUS;
                        }
 #ifdef SINGLE_ONLY_FPU
@@ -648,10 +658,10 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
                        break;
 
                case swxc1_op:
-                       va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] +
+                       va = (void *) (xcp->regs[MIPSInst_FR(ir)] +
                                xcp->regs[MIPSInst_FT(ir)]);
 
-                       fpuemuprivate.stats.stores++;
+                       fpuemustats.stores++;
 #ifdef SINGLE_ONLY_FPU
                        if (MIPSInst_FS(ir) & 1) {
                                /* illegal register in single-float
@@ -663,7 +673,7 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
 
                        SIFROMREG(val, MIPSInst_FS(ir));
                        if (put_user(val, va)) {
-                               fpuemuprivate.stats.errors++;
+                               fpuemustats.errors++;
                                return SIGBUS;
                        }
                        break;
@@ -699,8 +709,6 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
                                rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S;
 
                        ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr;
-                       if (ieee754_csr.nod)
-                               ctx->fcr31 |= 0x1000000;
                        if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
                                /*printk ("SIGFPE: fpu csr = %08x\n",
                                   ctx->fcr31); */
@@ -724,25 +732,25 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
 
                switch (MIPSInst_FUNC(ir)) {
                case ldxc1_op:
-                       va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] +
+                       va = (void *) (xcp->regs[MIPSInst_FR(ir)] +
                                xcp->regs[MIPSInst_FT(ir)]);
 
-                       fpuemuprivate.stats.loads++;
+                       fpuemustats.loads++;
                        if (get_user(val, va)) {
-                               fpuemuprivate.stats.errors++;
+                               fpuemustats.errors++;
                                return SIGBUS;
                        }
                        DITOREG(val, MIPSInst_FD(ir));
                        break;
 
                case sdxc1_op:
-                       va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] +
+                       va = (void *) (xcp->regs[MIPSInst_FR(ir)] +
                                xcp->regs[MIPSInst_FT(ir)]);
 
-                       fpuemuprivate.stats.stores++;
+                       fpuemustats.stores++;
                        DIFROMREG(val, MIPSInst_FS(ir));
                        if (put_user(val, va)) {
-                               fpuemuprivate.stats.errors++;
+                               fpuemustats.errors++;
                                return SIGBUS;
                        }
                        break;
@@ -810,7 +818,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
 #endif
        } rv;                   /* resulting value */
 
-       fpuemuprivate.stats.cp1ops++;
+       fpuemustats.cp1ops++;
        switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
        case s_fmt:{            /* 0 */
                union {
@@ -834,7 +842,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
                        goto scopbop;
 
                        /* unary  ops */
-#if __mips >= 2 || __mips64
+#if __mips >= 2 || defined(__mips64)
                case fsqrt_op:
                        handler.u = ieee754sp_sqrt;
                        goto scopuop;
@@ -933,7 +941,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
                        goto copcsr;
                }
 
-#if __mips >= 2 || __mips64
+#if __mips >= 2 || defined(__mips64)
                case fround_op:
                case ftrunc_op:
                case fceil_op:
@@ -974,7 +982,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
                        rfmt = l_fmt;
                        goto copcsr;
                }
-#endif /* __mips64 && !fpu(single) */
+#endif /* defined(__mips64) && !fpu(single) */
 
                default:
                        if (MIPSInst_FUNC(ir) >= fcmp_op) {
@@ -1024,7 +1032,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
                        goto dcopbop;
 
                        /* unary  ops */
-#if __mips >= 2 || __mips64
+#if __mips >= 2 || defined(__mips64)
                case fsqrt_op:
                        handler.u = ieee754dp_sqrt;
                        goto dcopuop;
@@ -1108,7 +1116,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
                        goto copcsr;
                }
 
-#if __mips >= 2 || __mips64
+#if __mips >= 2 || defined(__mips64)
                case fround_op:
                case ftrunc_op:
                case fceil_op:
@@ -1282,7 +1290,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
 int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp,
        struct mips_fpu_soft_struct *ctx)
 {
-       gpreg_t oldepc, prevepc;
+       unsigned long oldepc, prevepc;
        mips_instruction insn;
        int sig = 0;
 
@@ -1291,18 +1299,23 @@ int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp,
                prevepc = xcp->cp0_epc;
 
                if (get_user(insn, (mips_instruction *) xcp->cp0_epc)) {
-                       fpuemuprivate.stats.errors++;
+                       fpuemustats.errors++;
                        return SIGBUS;
                }
                if (insn == 0)
                        xcp->cp0_epc += 4;      /* skip nops */
                else {
-                       /* Update ieee754_csr. Only relevant if we have a
-                          h/w FPU */
-                       ieee754_csr.nod = (ctx->fcr31 & 0x1000000) != 0;
-                       ieee754_csr.rm = ieee_rm[ctx->fcr31 & 0x3];
-                       ieee754_csr.cx = (ctx->fcr31 >> 12) & 0x1f;
+                       /*
+                        * The 'ieee754_csr' is an alias of
+                        * ctx->fcr31.  No need to copy ctx->fcr31 to
+                        * ieee754_csr.  But ieee754_csr.rm is ieee
+                        * library modes. (not mips rounding mode)
+                        */
+                       /* convert to ieee library modes */
+                       ieee754_csr.rm = ieee_rm[ieee754_csr.rm];
                        sig = cop1Emulate(xcp, ctx);
+                       /* revert to mips rounding mode */
+                       ieee754_csr.rm = mips_rm[ieee754_csr.rm];
                }
 
                if (cpu_has_fpu)