aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/math-emu/cp1emu.c
diff options
context:
space:
mode:
authorPaul Burton <paul.burton@imgtec.com>2014-01-27 12:14:47 -0500
committerRalf Baechle <ralf@linux-mips.org>2014-03-26 18:09:10 -0400
commitef1c47afc0e1b7cd1b0102e02d3c3a57fe5f16d8 (patch)
tree4a7912f9c445ceb5a6fec92e3257048e507c56c2 /arch/mips/math-emu/cp1emu.c
parent6bbfd65e28c9d72eb140373c7796ce269616f2c0 (diff)
MIPS: Clear upper bits of FP registers on emulator writes
The upper bits of an FP register are architecturally defined as unpredictable following an instructions which only writes the lower bits. The prior behaviour of the kernel is to leave them unmodified. This patch modifies that to clear the upper bits to zero. This is what the MSA architecture reference manual specifies should happen for its wider registers and is still permissible for scalar FP instructions given the bits unpredictability there. Signed-off-by: Paul Burton <paul.burton@imgtec.com> Cc: linux-mips@linux-mips.org Cc: sergei.shtylyov@cogentembedded.com Patchwork: https://patchwork.linux-mips.org/patch/6435/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/math-emu/cp1emu.c')
-rw-r--r--arch/mips/math-emu/cp1emu.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 196cf1ab65af..71a697c9d385 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -884,20 +884,35 @@ static inline int cop1_64bit(struct pt_regs *xcp)
884} while (0) 884} while (0)
885 885
886#define SITOREG(si, x) do { \ 886#define SITOREG(si, x) do { \
887 if (cop1_64bit(xcp)) \ 887 if (cop1_64bit(xcp)) { \
888 unsigned i; \
888 set_fpr32(&ctx->fpr[x], 0, si); \ 889 set_fpr32(&ctx->fpr[x], 0, si); \
889 else \ 890 for (i = 1; i < ARRAY_SIZE(ctx->fpr[x].val32); i++) \
891 set_fpr32(&ctx->fpr[x], i, 0); \
892 } else { \
890 set_fpr32(&ctx->fpr[(x) & ~1], (x) & 1, si); \ 893 set_fpr32(&ctx->fpr[(x) & ~1], (x) & 1, si); \
894 } \
891} while (0) 895} while (0)
892 896
893#define SIFROMHREG(si, x) ((si) = get_fpr32(&ctx->fpr[x], 1)) 897#define SIFROMHREG(si, x) ((si) = get_fpr32(&ctx->fpr[x], 1))
894#define SITOHREG(si, x) set_fpr32(&ctx->fpr[x], 1, si) 898
899#define SITOHREG(si, x) do { \
900 unsigned i; \
901 set_fpr32(&ctx->fpr[x], 1, si); \
902 for (i = 2; i < ARRAY_SIZE(ctx->fpr[x].val32); i++) \
903 set_fpr32(&ctx->fpr[x], i, 0); \
904} while (0)
895 905
896#define DIFROMREG(di, x) \ 906#define DIFROMREG(di, x) \
897 ((di) = get_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) == 0)], 0)) 907 ((di) = get_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) == 0)], 0))
898 908
899#define DITOREG(di, x) \ 909#define DITOREG(di, x) do { \
900 set_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) == 0)], 0, di) 910 unsigned fpr, i; \
911 fpr = (x) & ~(cop1_64bit(xcp) == 0); \
912 set_fpr64(&ctx->fpr[fpr], 0, di); \
913 for (i = 1; i < ARRAY_SIZE(ctx->fpr[x].val64); i++) \
914 set_fpr64(&ctx->fpr[fpr], i, 0); \
915} while (0)
901 916
902#define SPFROMREG(sp, x) SIFROMREG((sp).bits, x) 917#define SPFROMREG(sp, x) SIFROMREG((sp).bits, x)
903#define SPTOREG(sp, x) SITOREG((sp).bits, x) 918#define SPTOREG(sp, x) SITOREG((sp).bits, x)