diff options
Diffstat (limited to 'arch/sparc/kernel/muldiv.c')
| -rw-r--r-- | arch/sparc/kernel/muldiv.c | 238 | 
1 files changed, 0 insertions, 238 deletions
diff --git a/arch/sparc/kernel/muldiv.c b/arch/sparc/kernel/muldiv.c deleted file mode 100644 index f7db516b07d..00000000000 --- a/arch/sparc/kernel/muldiv.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * muldiv.c: Hardware multiply/division illegal instruction trap - *		for sun4c/sun4 (which do not have those instructions) - * - * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) - * - * 2004-12-25	Krzysztof Helt (krzysztof.h1@wp.pl)  - *		- fixed registers constrains in inline assembly declarations - */ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <asm/ptrace.h> -#include <asm/processor.h> -#include <asm/uaccess.h> - -#include "kernel.h" - -/* #define DEBUG_MULDIV */ - -static inline int has_imm13(int insn) -{ -	return (insn & 0x2000); -} - -static inline int is_foocc(int insn) -{ -	return (insn & 0x800000); -} - -static inline int sign_extend_imm13(int imm) -{ -	return imm << 19 >> 19; -} - -static inline void advance(struct pt_regs *regs) -{ -	regs->pc   = regs->npc; -	regs->npc += 4; -} - -static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2, -				       unsigned int rd) -{ -	if(rs2 >= 16 || rs1 >= 16 || rd >= 16) { -		/* Wheee... */ -		__asm__ __volatile__("save %sp, -0x40, %sp\n\t" -				     "save %sp, -0x40, %sp\n\t" -				     "save %sp, -0x40, %sp\n\t" -				     "save %sp, -0x40, %sp\n\t" -				     "save %sp, -0x40, %sp\n\t" -				     "save %sp, -0x40, %sp\n\t" -				     "save %sp, -0x40, %sp\n\t" -				     "restore; restore; restore; restore;\n\t" -				     "restore; restore; restore;\n\t"); -	} -} - -#define fetch_reg(reg, regs) ({						\ -	struct reg_window32 __user *win;					\ -	register unsigned long ret;					\ -									\ -	if (!(reg)) ret = 0;						\ -	else if ((reg) < 16) {						\ -		ret = regs->u_regs[(reg)];				\ -	} else {							\ -		/* Ho hum, the slightly complicated case. */		\ -		win = (struct reg_window32 __user *)regs->u_regs[UREG_FP];\ -		if (get_user (ret, &win->locals[(reg) - 16])) return -1;\ -	}								\ -	ret;								\ -}) - -static inline int -store_reg(unsigned int result, unsigned int reg, struct pt_regs *regs) -{ -	struct reg_window32 __user *win; - -	if (!reg) -		return 0; -	if (reg < 16) { -		regs->u_regs[reg] = result; -		return 0; -	} else { -		/* need to use put_user() in this case: */ -		win = (struct reg_window32 __user *) regs->u_regs[UREG_FP]; -		return (put_user(result, &win->locals[reg - 16])); -	} -} - -/* Should return 0 if mul/div emulation succeeded and SIGILL should - * not be issued. - */ -int do_user_muldiv(struct pt_regs *regs, unsigned long pc) -{ -	unsigned int insn; -	int inst; -	unsigned int rs1, rs2, rdv; - -	if (!pc) -		return -1; /* This happens to often, I think */ -	if (get_user (insn, (unsigned int __user *)pc)) -		return -1; -	if ((insn & 0xc1400000) != 0x80400000) -		return -1; -	inst = ((insn >> 19) & 0xf); -	if ((inst & 0xe) != 10 && (inst & 0xe) != 14) -		return -1; - -	/* Now we know we have to do something with umul, smul, udiv or sdiv */ -	rs1 = (insn >> 14) & 0x1f; -	rs2 = insn & 0x1f; -	rdv = (insn >> 25) & 0x1f; -	if (has_imm13(insn)) { -		maybe_flush_windows(rs1, 0, rdv); -		rs2 = sign_extend_imm13(insn); -	} else { -		maybe_flush_windows(rs1, rs2, rdv); -		rs2 = fetch_reg(rs2, regs); -	} -	rs1 = fetch_reg(rs1, regs); -	switch (inst) { -	case 10: /* umul */ -#ifdef DEBUG_MULDIV	 -		printk ("unsigned muldiv: 0x%x * 0x%x = ", rs1, rs2); -#endif		 -		__asm__ __volatile__ ("\n\t" -			"mov	%0, %%o0\n\t" -			"call	.umul\n\t" -			" mov	%1, %%o1\n\t" -			"mov	%%o0, %0\n\t" -			"mov	%%o1, %1\n\t" -			: "=r" (rs1), "=r" (rs2) -		        : "0" (rs1), "1" (rs2) -			: "o0", "o1", "o2", "o3", "o4", "o5", "o7", "cc"); -#ifdef DEBUG_MULDIV -		printk ("0x%x%08x\n", rs2, rs1); -#endif -		if (store_reg(rs1, rdv, regs)) -			return -1; -		regs->y = rs2; -		break; -	case 11: /* smul */ -#ifdef DEBUG_MULDIV -		printk ("signed muldiv: 0x%x * 0x%x = ", rs1, rs2); -#endif -		__asm__ __volatile__ ("\n\t" -			"mov	%0, %%o0\n\t" -			"call	.mul\n\t" -			" mov	%1, %%o1\n\t" -			"mov	%%o0, %0\n\t" -			"mov	%%o1, %1\n\t" -			: "=r" (rs1), "=r" (rs2) -		        : "0" (rs1), "1" (rs2) -			: "o0", "o1", "o2", "o3", "o4", "o5", "o7", "cc"); -#ifdef DEBUG_MULDIV -		printk ("0x%x%08x\n", rs2, rs1); -#endif -		if (store_reg(rs1, rdv, regs)) -			return -1; -		regs->y = rs2; -		break; -	case 14: /* udiv */ -#ifdef DEBUG_MULDIV -		printk ("unsigned muldiv: 0x%x%08x / 0x%x = ", regs->y, rs1, rs2); -#endif -		if (!rs2) { -#ifdef DEBUG_MULDIV -			printk ("DIVISION BY ZERO\n"); -#endif -			handle_hw_divzero (regs, pc, regs->npc, regs->psr); -			return 0; -		} -		__asm__ __volatile__ ("\n\t" -			"mov	%2, %%o0\n\t" -			"mov	%0, %%o1\n\t" -			"mov	%%g0, %%o2\n\t" -			"call	__udivdi3\n\t" -			" mov	%1, %%o3\n\t" -			"mov	%%o1, %0\n\t" -			"mov	%%o0, %1\n\t" -			: "=r" (rs1), "=r" (rs2) -			: "r" (regs->y), "0" (rs1), "1" (rs2) -			: "o0", "o1", "o2", "o3", "o4", "o5", "o7", -			  "g1", "g2", "g3", "cc"); -#ifdef DEBUG_MULDIV -		printk ("0x%x\n", rs1); -#endif -		if (store_reg(rs1, rdv, regs)) -			return -1; -		break; -	case 15: /* sdiv */ -#ifdef DEBUG_MULDIV -		printk ("signed muldiv: 0x%x%08x / 0x%x = ", regs->y, rs1, rs2); -#endif -		if (!rs2) { -#ifdef DEBUG_MULDIV -			printk ("DIVISION BY ZERO\n"); -#endif -			handle_hw_divzero (regs, pc, regs->npc, regs->psr); -			return 0; -		} -		__asm__ __volatile__ ("\n\t" -			"mov	%2, %%o0\n\t" -			"mov	%0, %%o1\n\t" -			"mov	%%g0, %%o2\n\t" -			"call	__divdi3\n\t" -			" mov	%1, %%o3\n\t" -			"mov	%%o1, %0\n\t" -			"mov	%%o0, %1\n\t" -			: "=r" (rs1), "=r" (rs2) -			: "r" (regs->y), "0" (rs1), "1" (rs2) -			: "o0", "o1", "o2", "o3", "o4", "o5", "o7", -			  "g1", "g2", "g3", "cc"); -#ifdef DEBUG_MULDIV -		printk ("0x%x\n", rs1); -#endif -		if (store_reg(rs1, rdv, regs)) -			return -1; -		break; -	} -	if (is_foocc (insn)) { -		regs->psr &= ~PSR_ICC; -		if ((inst & 0xe) == 14) { -			/* ?div */ -			if (rs2) regs->psr |= PSR_V; -		} -		if (!rs1) regs->psr |= PSR_Z; -		if (((int)rs1) < 0) regs->psr |= PSR_N; -#ifdef DEBUG_MULDIV -		printk ("psr muldiv: %08x\n", regs->psr); -#endif -	} -	advance(regs); -	return 0; -}  |