From bbd426f542cb61f2322e15dab4507f2661090c06 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 13 Feb 2014 11:26:41 +0000 Subject: MIPS: Simplify FP context access This patch replaces the fpureg_t typedef with a "union fpureg" enabling easier access to 32 & 64 bit values. This allows the access macros used in cp1emu.c to be simplified somewhat. It will also make it easier to expand the width of the FP registers as will be done in a future patch in order to support the 128 bit registers introduced with MSA. No behavioural change is intended by this patch. Signed-off-by: Paul Burton Reviewed-by: Qais Yousef Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6532/ Signed-off-by: Ralf Baechle --- arch/mips/math-emu/cp1emu.c | 37 ++++++++++++++++++++++++------------- arch/mips/math-emu/kernel_linkage.c | 21 ++++++++++++--------- 2 files changed, 36 insertions(+), 22 deletions(-) (limited to 'arch/mips/math-emu') diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 506925b..196cf1a 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 3aeae07..9b46213 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); -- cgit v1.1