diff options
Diffstat (limited to 'arch/mips/math-emu')
-rw-r--r-- | arch/mips/math-emu/cp1emu.c | 37 | ||||
-rw-r--r-- | arch/mips/math-emu/kernel_linkage.c | 21 |
2 files changed, 36 insertions, 22 deletions
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 506925b2c3f3..196cf1ab65af 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -876,20 +876,28 @@ static inline int cop1_64bit(struct pt_regs *xcp) #endif } -#define SIFROMREG(si, x) ((si) = cop1_64bit(xcp) || !(x & 1) ? \ - (int)ctx->fpr[x] : (int)(ctx->fpr[x & ~1] >> 32)) +#define SIFROMREG(si, x) do { \ + if (cop1_64bit(xcp)) \ + (si) = get_fpr32(&ctx->fpr[x], 0); \ + else \ + (si) = get_fpr32(&ctx->fpr[(x) & ~1], (x) & 1); \ +} while (0) -#define SITOREG(si, x) (ctx->fpr[x & ~(cop1_64bit(xcp) == 0)] = \ - cop1_64bit(xcp) || !(x & 1) ? \ - ctx->fpr[x & ~1] >> 32 << 32 | (u32)(si) : \ - ctx->fpr[x & ~1] << 32 >> 32 | (u64)(si) << 32) +#define SITOREG(si, x) do { \ + if (cop1_64bit(xcp)) \ + set_fpr32(&ctx->fpr[x], 0, si); \ + else \ + set_fpr32(&ctx->fpr[(x) & ~1], (x) & 1, si); \ +} while (0) -#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 SIFROMHREG(si, x) ((si) = get_fpr32(&ctx->fpr[x], 1)) +#define SITOHREG(si, x) set_fpr32(&ctx->fpr[x], 1, si) -#define DIFROMREG(di, x) ((di) = ctx->fpr[x & ~(cop1_64bit(xcp) == 0)]) -#define DITOREG(di, x) (ctx->fpr[x & ~(cop1_64bit(xcp) == 0)] = (di)) +#define DIFROMREG(di, x) \ + ((di) = get_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) == 0)], 0)) + +#define DITOREG(di, x) \ + set_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) == 0)], 0, di) #define SPFROMREG(sp, x) SIFROMREG((sp).bits, x) #define SPTOREG(sp, x) SITOREG((sp).bits, x) @@ -1960,15 +1968,18 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, #if defined(__mips64) case l_fmt:{ + u64 bits; + DIFROMREG(bits, MIPSInst_FS(ir)); + switch (MIPSInst_FUNC(ir)) { case fcvts_op: /* convert long to single precision real */ - rv.s = ieee754sp_flong(ctx->fpr[MIPSInst_FS(ir)]); + rv.s = ieee754sp_flong(bits); rfmt = s_fmt; goto copcsr; case fcvtd_op: /* convert long to double precision real */ - rv.d = ieee754dp_flong(ctx->fpr[MIPSInst_FS(ir)]); + rv.d = ieee754dp_flong(bits); rfmt = d_fmt; goto copcsr; default: diff --git a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c index 3aeae07ed5b8..9b46213b1035 100644 --- a/arch/mips/math-emu/kernel_linkage.c +++ b/arch/mips/math-emu/kernel_linkage.c @@ -40,9 +40,8 @@ void fpu_emulator_init_fpu(void) } current->thread.fpu.fcr31 = 0; - for (i = 0; i < 32; i++) { - current->thread.fpu.fpr[i] = SIGNALLING_NAN; - } + for (i = 0; i < 32; i++) + set_fpr64(¤t->thread.fpu.fpr[i], 0, SIGNALLING_NAN); } @@ -59,7 +58,8 @@ int fpu_emulator_save_context(struct sigcontext __user *sc) for (i = 0; i < 32; i++) { err |= - __put_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]); + __put_user(get_fpr64(¤t->thread.fpu.fpr[i], 0), + &sc->sc_fpregs[i]); } err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr); @@ -70,10 +70,11 @@ int fpu_emulator_restore_context(struct sigcontext __user *sc) { int i; int err = 0; + u64 fpr_val; for (i = 0; i < 32; i++) { - err |= - __get_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]); + err |= __get_user(fpr_val, &sc->sc_fpregs[i]); + set_fpr64(¤t->thread.fpu.fpr[i], 0, fpr_val); } err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr); @@ -93,7 +94,8 @@ int fpu_emulator_save_context32(struct sigcontext32 __user *sc) for (i = 0; i < 32; i += inc) { err |= - __put_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]); + __put_user(get_fpr64(¤t->thread.fpu.fpr[i], 0), + &sc->sc_fpregs[i]); } err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr); @@ -105,10 +107,11 @@ int fpu_emulator_restore_context32(struct sigcontext32 __user *sc) int i; int err = 0; int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1; + u64 fpr_val; for (i = 0; i < 32; i += inc) { - err |= - __get_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]); + err |= __get_user(fpr_val, &sc->sc_fpregs[i]); + set_fpr64(¤t->thread.fpu.fpr[i], 0, fpr_val); } err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr); |