|
@@ -163,7 +163,7 @@ typedef union {
|
|
|
u64 q[2];
|
|
|
} *argp;
|
|
|
|
|
|
-int do_mathemu(struct pt_regs *regs, struct fpustate *f)
|
|
|
+int do_mathemu(struct pt_regs *regs, struct fpustate *f, bool illegal_insn_trap)
|
|
|
{
|
|
|
unsigned long pc = regs->tpc;
|
|
|
unsigned long tstate = regs->tstate;
|
|
@@ -218,7 +218,7 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f)
|
|
|
case FSQRTS: {
|
|
|
unsigned long x = current_thread_info()->xfsr[0];
|
|
|
|
|
|
- x = (x >> 14) & 0xf;
|
|
|
+ x = (x >> 14) & 0x7;
|
|
|
TYPE(x,1,1,1,1,0,0);
|
|
|
break;
|
|
|
}
|
|
@@ -226,7 +226,7 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f)
|
|
|
case FSQRTD: {
|
|
|
unsigned long x = current_thread_info()->xfsr[0];
|
|
|
|
|
|
- x = (x >> 14) & 0xf;
|
|
|
+ x = (x >> 14) & 0x7;
|
|
|
TYPE(x,2,1,2,1,0,0);
|
|
|
break;
|
|
|
}
|
|
@@ -357,9 +357,17 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f)
|
|
|
if (type) {
|
|
|
argp rs1 = NULL, rs2 = NULL, rd = NULL;
|
|
|
|
|
|
- freg = (current_thread_info()->xfsr[0] >> 14) & 0xf;
|
|
|
- if (freg != (type >> 9))
|
|
|
- goto err;
|
|
|
+ /* Starting with UltraSPARC-T2, the cpu does not set the FP Trap
|
|
|
+ * Type field in the %fsr to unimplemented_FPop. Nor does it
|
|
|
+ * use the fp_exception_other trap. Instead it signals an
|
|
|
+ * illegal instruction and leaves the FP trap type field of
|
|
|
+ * the %fsr unchanged.
|
|
|
+ */
|
|
|
+ if (!illegal_insn_trap) {
|
|
|
+ int ftt = (current_thread_info()->xfsr[0] >> 14) & 0x7;
|
|
|
+ if (ftt != (type >> 9))
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
current_thread_info()->xfsr[0] &= ~0x1c000;
|
|
|
freg = ((insn >> 14) & 0x1f);
|
|
|
switch (type & 0x3) {
|