diff options
Diffstat (limited to 'arch/sparc/math-emu/math_64.c')
-rw-r--r-- | arch/sparc/math-emu/math_64.c | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/arch/sparc/math-emu/math_64.c b/arch/sparc/math-emu/math_64.c index 2bbe2f28ad23..1704068da928 100644 --- a/arch/sparc/math-emu/math_64.c +++ b/arch/sparc/math-emu/math_64.c | |||
@@ -163,7 +163,7 @@ typedef union { | |||
163 | u64 q[2]; | 163 | u64 q[2]; |
164 | } *argp; | 164 | } *argp; |
165 | 165 | ||
166 | int do_mathemu(struct pt_regs *regs, struct fpustate *f) | 166 | int do_mathemu(struct pt_regs *regs, struct fpustate *f, bool illegal_insn_trap) |
167 | { | 167 | { |
168 | unsigned long pc = regs->tpc; | 168 | unsigned long pc = regs->tpc; |
169 | unsigned long tstate = regs->tstate; | 169 | unsigned long tstate = regs->tstate; |
@@ -218,7 +218,7 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f) | |||
218 | case FSQRTS: { | 218 | case FSQRTS: { |
219 | unsigned long x = current_thread_info()->xfsr[0]; | 219 | unsigned long x = current_thread_info()->xfsr[0]; |
220 | 220 | ||
221 | x = (x >> 14) & 0xf; | 221 | x = (x >> 14) & 0x7; |
222 | TYPE(x,1,1,1,1,0,0); | 222 | TYPE(x,1,1,1,1,0,0); |
223 | break; | 223 | break; |
224 | } | 224 | } |
@@ -226,7 +226,7 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f) | |||
226 | case FSQRTD: { | 226 | case FSQRTD: { |
227 | unsigned long x = current_thread_info()->xfsr[0]; | 227 | unsigned long x = current_thread_info()->xfsr[0]; |
228 | 228 | ||
229 | x = (x >> 14) & 0xf; | 229 | x = (x >> 14) & 0x7; |
230 | TYPE(x,2,1,2,1,0,0); | 230 | TYPE(x,2,1,2,1,0,0); |
231 | break; | 231 | break; |
232 | } | 232 | } |
@@ -357,9 +357,17 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f) | |||
357 | if (type) { | 357 | if (type) { |
358 | argp rs1 = NULL, rs2 = NULL, rd = NULL; | 358 | argp rs1 = NULL, rs2 = NULL, rd = NULL; |
359 | 359 | ||
360 | freg = (current_thread_info()->xfsr[0] >> 14) & 0xf; | 360 | /* Starting with UltraSPARC-T2, the cpu does not set the FP Trap |
361 | if (freg != (type >> 9)) | 361 | * Type field in the %fsr to unimplemented_FPop. Nor does it |
362 | goto err; | 362 | * use the fp_exception_other trap. Instead it signals an |
363 | * illegal instruction and leaves the FP trap type field of | ||
364 | * the %fsr unchanged. | ||
365 | */ | ||
366 | if (!illegal_insn_trap) { | ||
367 | int ftt = (current_thread_info()->xfsr[0] >> 14) & 0x7; | ||
368 | if (ftt != (type >> 9)) | ||
369 | goto err; | ||
370 | } | ||
363 | current_thread_info()->xfsr[0] &= ~0x1c000; | 371 | current_thread_info()->xfsr[0] &= ~0x1c000; |
364 | freg = ((insn >> 14) & 0x1f); | 372 | freg = ((insn >> 14) & 0x1f); |
365 | switch (type & 0x3) { | 373 | switch (type & 0x3) { |