X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fsparc64%2Fmath-emu%2Fmath.c;h=6ee496c2864a8eb8c12e0132004563d2a253ce8d;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=48dfa37ddd72d4c5685156be72c171910b3cb298;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/arch/sparc64/math-emu/math.c b/arch/sparc64/math-emu/math.c index 48dfa37dd..6ee496c28 100644 --- a/arch/sparc64/math-emu/math.c +++ b/arch/sparc64/math-emu/math.c @@ -185,7 +185,7 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f) die_if_kernel("unfinished/unimplemented FPop from kernel", regs); if (test_thread_flag(TIF_32BIT)) pc = (u32)pc; - if (get_user(insn, (u32 *)pc) != -EFAULT) { + if (get_user(insn, (u32 __user *) pc) != -EFAULT) { if ((insn & 0xc1f80000) == 0x81a00000) /* FPOP1 */ { switch ((insn >> 5) & 0x1ff) { /* QUAD - ftt == 3 */ @@ -206,9 +206,29 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f) case FSTOQ: TYPE(3,3,1,1,1,0,0); break; case FDTOQ: TYPE(3,3,1,2,1,0,0); break; case FQTOI: TYPE(3,1,0,3,1,0,0); break; + + /* We can get either unimplemented or unfinished + * for these cases. Pre-Niagara systems generate + * unfinished fpop for SUBNORMAL cases, and Niagara + * always gives unimplemented fpop for fsqrt{s,d}. + */ + case FSQRTS: { + unsigned long x = current_thread_info()->xfsr[0]; + + x = (x >> 14) & 0xf; + TYPE(x,1,1,1,1,0,0); + break; + } + + case FSQRTD: { + unsigned long x = current_thread_info()->xfsr[0]; + + x = (x >> 14) & 0xf; + TYPE(x,2,1,2,1,0,0); + break; + } + /* SUBNORMAL - ftt == 2 */ - case FSQRTS: TYPE(2,1,1,1,1,0,0); break; - case FSQRTD: TYPE(2,2,1,2,1,0,0); break; case FADDD: case FSUBD: case FMULD: @@ -298,14 +318,14 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f) else if (freg < 16) XR = regs->u_regs[freg]; else if (test_thread_flag(TIF_32BIT)) { - struct reg_window32 *win32; + struct reg_window32 __user *win32; flushw_user (); - win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP])); + win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); get_user(XR, &win32->locals[freg - 16]); } else { - struct reg_window *win; + struct reg_window __user *win; flushw_user (); - win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); + win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS); get_user(XR, &win->locals[freg - 16]); } IR = 0;