aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDavid Daney <ddaney@caviumnetworks.com>2009-11-02 14:33:46 -0500
committerRalf Baechle <ralf@linux-mips.org>2009-11-13 12:10:37 -0500
commitda0bac33413b2888d3623dad3ad19ce76b688f07 (patch)
tree6d95ce81145b0a11868dd38f5571f58d9d8a79e6 /arch
parent156171c71a0dc4bce12b4408bb1591f8fe32dc1a (diff)
MIPS: Fix emulation of 64-bit FPU on FPU-less 64-bit CPUs.
Running a 64-bit kernel on a 64-bit CPU without an FPU would cause the emulator to run in 32-bit mode. The c0_Status.FR bit is wired to zero on systems without an FPU, so using that bit to decide how the emulator behaves doesn't allow for proper emulation on 64-bit FPU-less processors. Instead, we need to select the emulator mode based on the user-space ABI. Since the thread flag TIF_32BIT_REGS is used to set c0_Status.FR, we can just use it to decide if the emulator should be in 32-bit or 64-bit mode. Signed-off-by: David Daney <ddaney@caviumnetworks.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/math-emu/cp1emu.c41
1 files changed, 21 insertions, 20 deletions
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 890f77927d62..454b53924490 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -163,33 +163,34 @@ static int isBranchInstr(mips_instruction * i)
163 163
164/* 164/*
165 * In the Linux kernel, we support selection of FPR format on the 165 * In the Linux kernel, we support selection of FPR format on the
166 * basis of the Status.FR bit. This does imply that, if a full 32 166 * basis of the Status.FR bit. If an FPU is not present, the FR bit
167 * FPRs are desired, there needs to be a flip-flop that can be written 167 * is hardwired to zero, which would imply a 32-bit FPU even for
168 * to one at that bit position. In any case, O32 MIPS ABI uses 168 * 64-bit CPUs. For 64-bit kernels with no FPU we use TIF_32BIT_REGS
169 * only the even FPRs (Status.FR = 0). 169 * as a proxy for the FR bit so that a 64-bit FPU is emulated. In any
170 * case, for a 32-bit kernel which uses the O32 MIPS ABI, only the
171 * even FPRs are used (Status.FR = 0).
170 */ 172 */
171 173static inline int cop1_64bit(struct pt_regs *xcp)
172#define CP0_STATUS_FR_SUPPORT 174{
173 175 if (cpu_has_fpu)
174#ifdef CP0_STATUS_FR_SUPPORT 176 return xcp->cp0_status & ST0_FR;
175#define FR_BIT ST0_FR 177#ifdef CONFIG_64BIT
178 return !test_thread_flag(TIF_32BIT_REGS);
176#else 179#else
177#define FR_BIT 0 180 return 0;
178#endif 181#endif
182}
183
184#define SIFROMREG(si, x) ((si) = cop1_64bit(xcp) || !(x & 1) ? \
185 (int)ctx->fpr[x] : (int)(ctx->fpr[x & ~1] >> 32))
179 186
180#define SIFROMREG(si, x) ((si) = \ 187#define SITOREG(si, x) (ctx->fpr[x & ~(cop1_64bit(xcp) == 0)] = \
181 (xcp->cp0_status & FR_BIT) || !(x & 1) ? \ 188 cop1_64bit(xcp) || !(x & 1) ? \
182 (int)ctx->fpr[x] : \
183 (int)(ctx->fpr[x & ~1] >> 32 ))
184#define SITOREG(si, x) (ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)] = \
185 (xcp->cp0_status & FR_BIT) || !(x & 1) ? \
186 ctx->fpr[x & ~1] >> 32 << 32 | (u32)(si) : \ 189 ctx->fpr[x & ~1] >> 32 << 32 | (u32)(si) : \
187 ctx->fpr[x & ~1] << 32 >> 32 | (u64)(si) << 32) 190 ctx->fpr[x & ~1] << 32 >> 32 | (u64)(si) << 32)
188 191
189#define DIFROMREG(di, x) ((di) = \ 192#define DIFROMREG(di, x) ((di) = ctx->fpr[x & ~(cop1_64bit(xcp) == 0)])
190 ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)]) 193#define DITOREG(di, x) (ctx->fpr[x & ~(cop1_64bit(xcp) == 0)] = (di))
191#define DITOREG(di, x) (ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)] \
192 = (di))
193 194
194#define SPFROMREG(sp, x) SIFROMREG((sp).bits, x) 195#define SPFROMREG(sp, x) SIFROMREG((sp).bits, x)
195#define SPTOREG(sp, x) SITOREG((sp).bits, x) 196#define SPTOREG(sp, x) SITOREG((sp).bits, x)