diff options
Diffstat (limited to 'arch/mips/math-emu')
47 files changed, 1514 insertions, 2842 deletions
diff --git a/arch/mips/math-emu/Makefile b/arch/mips/math-emu/Makefile index 121a848a359..619cfc1a244 100644 --- a/arch/mips/math-emu/Makefile +++ b/arch/mips/math-emu/Makefile @@ -2,10 +2,12 @@  # Makefile for the Linux/MIPS kernel FPU emulation.  # -obj-y	:= cp1emu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \ -	   ieee754xcpt.o dp_frexp.o dp_modf.o dp_div.o dp_mul.o dp_sub.o \ -	   dp_add.o dp_fsp.o dp_cmp.o dp_logb.o dp_scalb.o dp_simple.o \ -	   dp_tint.o dp_fint.o dp_tlong.o dp_flong.o sp_frexp.o sp_modf.o \ -	   sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_logb.o \ -	   sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \ -	   dp_sqrt.o sp_sqrt.o kernel_linkage.o dsemul.o +obj-y	+= cp1emu.o ieee754dp.o ieee754sp.o ieee754.o dp_div.o dp_mul.o \ +	   dp_sub.o dp_add.o dp_fsp.o dp_cmp.o dp_simple.o dp_tint.o \ +	   dp_fint.o dp_tlong.o dp_flong.o sp_div.o sp_mul.o sp_sub.o \ +	   sp_add.o sp_fdp.o sp_cmp.o sp_simple.o sp_tint.o sp_fint.o \ +	   sp_tlong.o sp_flong.o dsemul.o + +lib-y	+= ieee754d.o dp_sqrt.o sp_sqrt.o + +obj-$(CONFIG_DEBUG_FS) += me-debugfs.o diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index efe008846ed..736c17a226e 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -1,5 +1,5 @@  /* - * cp1emu.c: a MIPS coprocessor 1 (fpu) instruction emulator + * cp1emu.c: a MIPS coprocessor 1 (FPU) instruction emulator   *   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd. @@ -18,61 +18,46 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   *   * A complete emulator for MIPS coprocessor 1 instructions.  This is   * required for #float(switch) or #float(trap), where it catches all   * COP1 instructions via the "CoProcessor Unusable" exception.   *   * More surprisingly it is also required for #float(ieee), to help out - * the hardware fpu at the boundaries of the IEEE-754 representation + * the hardware FPU at the boundaries of the IEEE-754 representation   * (denormalised values, infinities, underflow, etc).  It is made   * quite nasty because emulation of some non-COP1 instructions is   * required, e.g. in branch delay slots.   * - * Note if you know that you won't have an fpu, then you'll get much + * Note if you know that you won't have an FPU, then you'll get much   * better performance by compiling with -msoft-float!   */  #include <linux/sched.h> -#include <linux/module.h>  #include <linux/debugfs.h> +#include <linux/kconfig.h> +#include <linux/percpu-defs.h>  #include <linux/perf_event.h> +#include <asm/branch.h>  #include <asm/inst.h> -#include <asm/bootinfo.h> -#include <asm/processor.h>  #include <asm/ptrace.h>  #include <asm/signal.h> -#include <asm/mipsregs.h> +#include <asm/uaccess.h> + +#include <asm/processor.h>  #include <asm/fpu_emulator.h>  #include <asm/fpu.h> -#include <asm/uaccess.h> -#include <asm/branch.h>  #include "ieee754.h" -/* Strap kernel emulator for full MIPS IV emulation */ - -#ifdef __mips -#undef __mips -#endif -#define __mips 4 -  /* Function which emulates a floating point instruction. */  static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,  	mips_instruction); -#if __mips >= 4 && __mips != 32  static int fpux_emu(struct pt_regs *,  	struct mips_fpu_struct *, mips_instruction, void *__user *); -#endif - -/* Further private data for which no space exists in mips_fpu_struct */ - -#ifdef CONFIG_DEBUG_FS -DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats); -#endif  /* Control registers */ @@ -82,27 +67,6 @@ DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);  /* Determine rounding mode from the RM bits of the FCSR */  #define modeindex(v) ((v) & FPU_CSR_RM) -/* microMIPS bitfields */ -#define MM_POOL32A_MINOR_MASK	0x3f -#define MM_POOL32A_MINOR_SHIFT	0x6 -#define MM_MIPS32_COND_FC	0x30 - -/* Convert Mips rounding mode (0..3) to IEEE library modes. */ -static const unsigned char ieee_rm[4] = { -	[FPU_CSR_RN] = IEEE754_RN, -	[FPU_CSR_RZ] = IEEE754_RZ, -	[FPU_CSR_RU] = IEEE754_RU, -	[FPU_CSR_RD] = IEEE754_RD, -}; -/* Convert IEEE library modes to Mips rounding mode (0..3). */ -static const unsigned char mips_rm[4] = { -	[IEEE754_RN] = FPU_CSR_RN, -	[IEEE754_RZ] = FPU_CSR_RZ, -	[IEEE754_RD] = FPU_CSR_RD, -	[IEEE754_RU] = FPU_CSR_RU, -}; - -#if __mips >= 4  /* convert condition code register number to csr bit */  static const unsigned int fpucondbit[8] = {  	FPU_CSR_COND0, @@ -114,10 +78,6 @@ static const unsigned int fpucondbit[8] = {  	FPU_CSR_COND6,  	FPU_CSR_COND7  }; -#endif - -/* (microMIPS) Convert 16-bit register encoding to 32-bit register encoding. */ -static const unsigned int reg16to32map[8] = {16, 17, 2, 3, 4, 5, 6, 7};  /* (microMIPS) Convert certain microMIPS instructions to MIPS32 format. */  static const int sd_format[] = {16, 17, 0, 0, 0, 0, 0, 0}; @@ -417,14 +377,20 @@ static int microMIPS32_to_MIPS32(union mips_instruction *insn_ptr)  			case mm_mtc1_op:  			case mm_cfc1_op:  			case mm_ctc1_op: +			case mm_mfhc1_op: +			case mm_mthc1_op:  				if (insn.mm_fp1_format.op == mm_mfc1_op)  					op = mfc_op;  				else if (insn.mm_fp1_format.op == mm_mtc1_op)  					op = mtc_op;  				else if (insn.mm_fp1_format.op == mm_cfc1_op)  					op = cfc_op; -				else +				else if (insn.mm_fp1_format.op == mm_ctc1_op)  					op = ctc_op; +				else if (insn.mm_fp1_format.op == mm_mfhc1_op) +					op = mfhc_op; +				else +					op = mthc_op;  				mips32_insn.fp1_format.opcode = cop1_op;  				mips32_insn.fp1_format.op = op;  				mips32_insn.fp1_format.rt = @@ -460,199 +426,6 @@ static int microMIPS32_to_MIPS32(union mips_instruction *insn_ptr)  	return 0;  } -int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, -		     unsigned long *contpc) -{ -	union mips_instruction insn = (union mips_instruction)dec_insn.insn; -	int bc_false = 0; -	unsigned int fcr31; -	unsigned int bit; - -	if (!cpu_has_mmips) -		return 0; - -	switch (insn.mm_i_format.opcode) { -	case mm_pool32a_op: -		if ((insn.mm_i_format.simmediate & MM_POOL32A_MINOR_MASK) == -		    mm_pool32axf_op) { -			switch (insn.mm_i_format.simmediate >> -				MM_POOL32A_MINOR_SHIFT) { -			case mm_jalr_op: -			case mm_jalrhb_op: -			case mm_jalrs_op: -			case mm_jalrshb_op: -				if (insn.mm_i_format.rt != 0)	/* Not mm_jr */ -					regs->regs[insn.mm_i_format.rt] = -						regs->cp0_epc + -						dec_insn.pc_inc + -						dec_insn.next_pc_inc; -				*contpc = regs->regs[insn.mm_i_format.rs]; -				return 1; -			} -		} -		break; -	case mm_pool32i_op: -		switch (insn.mm_i_format.rt) { -		case mm_bltzals_op: -		case mm_bltzal_op: -			regs->regs[31] = regs->cp0_epc + -				dec_insn.pc_inc + -				dec_insn.next_pc_inc; -			/* Fall through */ -		case mm_bltz_op: -			if ((long)regs->regs[insn.mm_i_format.rs] < 0) -				*contpc = regs->cp0_epc + -					dec_insn.pc_inc + -					(insn.mm_i_format.simmediate << 1); -			else -				*contpc = regs->cp0_epc + -					dec_insn.pc_inc + -					dec_insn.next_pc_inc; -			return 1; -		case mm_bgezals_op: -		case mm_bgezal_op: -			regs->regs[31] = regs->cp0_epc + -					dec_insn.pc_inc + -					dec_insn.next_pc_inc; -			/* Fall through */ -		case mm_bgez_op: -			if ((long)regs->regs[insn.mm_i_format.rs] >= 0) -				*contpc = regs->cp0_epc + -					dec_insn.pc_inc + -					(insn.mm_i_format.simmediate << 1); -			else -				*contpc = regs->cp0_epc + -					dec_insn.pc_inc + -					dec_insn.next_pc_inc; -			return 1; -		case mm_blez_op: -			if ((long)regs->regs[insn.mm_i_format.rs] <= 0) -				*contpc = regs->cp0_epc + -					dec_insn.pc_inc + -					(insn.mm_i_format.simmediate << 1); -			else -				*contpc = regs->cp0_epc + -					dec_insn.pc_inc + -					dec_insn.next_pc_inc; -			return 1; -		case mm_bgtz_op: -			if ((long)regs->regs[insn.mm_i_format.rs] <= 0) -				*contpc = regs->cp0_epc + -					dec_insn.pc_inc + -					(insn.mm_i_format.simmediate << 1); -			else -				*contpc = regs->cp0_epc + -					dec_insn.pc_inc + -					dec_insn.next_pc_inc; -			return 1; -		case mm_bc2f_op: -		case mm_bc1f_op: -			bc_false = 1; -			/* Fall through */ -		case mm_bc2t_op: -		case mm_bc1t_op: -			preempt_disable(); -			if (is_fpu_owner()) -				asm volatile("cfc1\t%0,$31" : "=r" (fcr31)); -			else -				fcr31 = current->thread.fpu.fcr31; -			preempt_enable(); - -			if (bc_false) -				fcr31 = ~fcr31; - -			bit = (insn.mm_i_format.rs >> 2); -			bit += (bit != 0); -			bit += 23; -			if (fcr31 & (1 << bit)) -				*contpc = regs->cp0_epc + -					dec_insn.pc_inc + -					(insn.mm_i_format.simmediate << 1); -			else -				*contpc = regs->cp0_epc + -					dec_insn.pc_inc + dec_insn.next_pc_inc; -			return 1; -		} -		break; -	case mm_pool16c_op: -		switch (insn.mm_i_format.rt) { -		case mm_jalr16_op: -		case mm_jalrs16_op: -			regs->regs[31] = regs->cp0_epc + -				dec_insn.pc_inc + dec_insn.next_pc_inc; -			/* Fall through */ -		case mm_jr16_op: -			*contpc = regs->regs[insn.mm_i_format.rs]; -			return 1; -		} -		break; -	case mm_beqz16_op: -		if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] == 0) -			*contpc = regs->cp0_epc + -				dec_insn.pc_inc + -				(insn.mm_b1_format.simmediate << 1); -		else -			*contpc = regs->cp0_epc + -				dec_insn.pc_inc + dec_insn.next_pc_inc; -		return 1; -	case mm_bnez16_op: -		if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] != 0) -			*contpc = regs->cp0_epc + -				dec_insn.pc_inc + -				(insn.mm_b1_format.simmediate << 1); -		else -			*contpc = regs->cp0_epc + -				dec_insn.pc_inc + dec_insn.next_pc_inc; -		return 1; -	case mm_b16_op: -		*contpc = regs->cp0_epc + dec_insn.pc_inc + -			 (insn.mm_b0_format.simmediate << 1); -		return 1; -	case mm_beq32_op: -		if (regs->regs[insn.mm_i_format.rs] == -		    regs->regs[insn.mm_i_format.rt]) -			*contpc = regs->cp0_epc + -				dec_insn.pc_inc + -				(insn.mm_i_format.simmediate << 1); -		else -			*contpc = regs->cp0_epc + -				dec_insn.pc_inc + -				dec_insn.next_pc_inc; -		return 1; -	case mm_bne32_op: -		if (regs->regs[insn.mm_i_format.rs] != -		    regs->regs[insn.mm_i_format.rt]) -			*contpc = regs->cp0_epc + -				dec_insn.pc_inc + -				(insn.mm_i_format.simmediate << 1); -		else -			*contpc = regs->cp0_epc + -				dec_insn.pc_inc + dec_insn.next_pc_inc; -		return 1; -	case mm_jalx32_op: -		regs->regs[31] = regs->cp0_epc + -			dec_insn.pc_inc + dec_insn.next_pc_inc; -		*contpc = regs->cp0_epc + dec_insn.pc_inc; -		*contpc >>= 28; -		*contpc <<= 28; -		*contpc |= (insn.j_format.target << 2); -		return 1; -	case mm_jals32_op: -	case mm_jal32_op: -		regs->regs[31] = regs->cp0_epc + -			dec_insn.pc_inc + dec_insn.next_pc_inc; -		/* Fall through */ -	case mm_j32_op: -		*contpc = regs->cp0_epc + dec_insn.pc_inc; -		*contpc >>= 27; -		*contpc <<= 27; -		*contpc |= (insn.j_format.target << 1); -		set_isa16_mode(*contpc); -		return 1; -	} -	return 0; -} -  /*   * Redundant with logic already in kernel/branch.c,   * embedded in compute_return_epc.  At some point, @@ -811,7 +584,11 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,  		if (insn.i_format.rs == bc_op) {  			preempt_disable();  			if (is_fpu_owner()) -				asm volatile("cfc1\t%0,$31" : "=r" (fcr31)); +				asm volatile( +					".set push\n" +					"\t.set mips1\n" +					"\tcfc1\t%0,$31\n" +					"\t.set pop" : "=r" (fcr31));  			else  				fcr31 = current->thread.fpu.fcr31;  			preempt_enable(); @@ -853,33 +630,64 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,   * In the Linux kernel, we support selection of FPR format on the   * basis of the Status.FR bit.	If an FPU is not present, the FR bit   * is hardwired to zero, which would imply a 32-bit FPU even for - * 64-bit CPUs so we rather look at TIF_32BIT_REGS. + * 64-bit CPUs so we rather look at TIF_32BIT_FPREGS.   * FPU emu is slow and bulky and optimizing this function offers fairly   * sizeable benefits so we try to be clever and make this function return   * a constant whenever possible, that is on 64-bit kernels without O32 - * compatibility enabled and on 32-bit kernels. + * compatibility enabled and on 32-bit without 64-bit FPU support.   */  static inline int cop1_64bit(struct pt_regs *xcp)  { -#if defined(CONFIG_64BIT) && !defined(CONFIG_MIPS32_O32) -	return 1; -#elif defined(CONFIG_64BIT) && defined(CONFIG_MIPS32_O32) -	return !test_thread_flag(TIF_32BIT_REGS); -#else -	return 0; -#endif -} - -#define SIFROMREG(si, x) ((si) = cop1_64bit(xcp) || !(x & 1) ? \ -			(int)ctx->fpr[x] : (int)(ctx->fpr[x & ~1] >> 32)) +	if (config_enabled(CONFIG_64BIT) && !config_enabled(CONFIG_MIPS32_O32)) +		return 1; +	else if (config_enabled(CONFIG_32BIT) && +		 !config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT)) +		return 0; -#define SITOREG(si, x)	(ctx->fpr[x & ~(cop1_64bit(xcp) == 0)] = \ -			cop1_64bit(xcp) || !(x & 1) ? \ -			ctx->fpr[x & ~1] >> 32 << 32 | (u32)(si) : \ -			ctx->fpr[x & ~1] << 32 >> 32 | (u64)(si) << 32) +	return !test_thread_flag(TIF_32BIT_FPREGS); +} -#define DIFROMREG(di, x) ((di) = ctx->fpr[x & ~(cop1_64bit(xcp) == 0)]) -#define DITOREG(di, x)	(ctx->fpr[x & ~(cop1_64bit(xcp) == 0)] = (di)) +#define SIFROMREG(si, x)						\ +do {									\ +	if (cop1_64bit(xcp))						\ +		(si) = get_fpr32(&ctx->fpr[x], 0);			\ +	else								\ +		(si) = get_fpr32(&ctx->fpr[(x) & ~1], (x) & 1);		\ +} while (0) + +#define SITOREG(si, x)							\ +do {									\ +	if (cop1_64bit(xcp)) {						\ +		unsigned i;						\ +		set_fpr32(&ctx->fpr[x], 0, si);				\ +		for (i = 1; i < ARRAY_SIZE(ctx->fpr[x].val32); i++)	\ +			set_fpr32(&ctx->fpr[x], i, 0);			\ +	} else {							\ +		set_fpr32(&ctx->fpr[(x) & ~1], (x) & 1, si);		\ +	}								\ +} while (0) + +#define SIFROMHREG(si, x)	((si) = get_fpr32(&ctx->fpr[x], 1)) + +#define SITOHREG(si, x)							\ +do {									\ +	unsigned i;							\ +	set_fpr32(&ctx->fpr[x], 1, si);					\ +	for (i = 2; i < ARRAY_SIZE(ctx->fpr[x].val32); i++)		\ +		set_fpr32(&ctx->fpr[x], i, 0);				\ +} while (0) + +#define DIFROMREG(di, x)						\ +	((di) = get_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) == 0)], 0)) + +#define DITOREG(di, x)							\ +do {									\ +	unsigned fpr, i;						\ +	fpr = (x) & ~(cop1_64bit(xcp) == 0);				\ +	set_fpr64(&ctx->fpr[fpr], 0, di);				\ +	for (i = 1; i < ARRAY_SIZE(ctx->fpr[x].val64); i++)		\ +		set_fpr64(&ctx->fpr[fpr], i, 0);			\ +} while (0)  #define SPFROMREG(sp, x) SIFROMREG((sp).bits, x)  #define SPTOREG(sp, x)	SITOREG((sp).bits, x) @@ -894,23 +702,36 @@ static inline int cop1_64bit(struct pt_regs *xcp)  static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  		struct mm_decoded_insn dec_insn, void *__user *fault_addr)  { -	mips_instruction ir;  	unsigned long contpc = xcp->cp0_epc + dec_insn.pc_inc; -	unsigned int cond; -	int pc_inc; +	unsigned int cond, cbit; +	mips_instruction ir; +	int likely, pc_inc; +	u32 __user *wva; +	u64 __user *dva; +	u32 value; +	u32 wval; +	u64 dval; +	int sig; + +	/* +	 * These are giving gcc a gentle hint about what to expect in +	 * dec_inst in order to do better optimization. +	 */ +	if (!cpu_has_mmips && dec_insn.micro_mips_mode) +		unreachable();  	/* XXX NEC Vr54xx bug workaround */ -	if (xcp->cp0_cause & CAUSEF_BD) { +	if (delay_slot(xcp)) {  		if (dec_insn.micro_mips_mode) {  			if (!mm_isBranchInstr(xcp, dec_insn, &contpc)) -				xcp->cp0_cause &= ~CAUSEF_BD; +				clear_delay_slot(xcp);  		} else {  			if (!isBranchInstr(xcp, dec_insn, &contpc)) -				xcp->cp0_cause &= ~CAUSEF_BD; +				clear_delay_slot(xcp);  		}  	} -	if (xcp->cp0_cause & CAUSEF_BD) { +	if (delay_slot(xcp)) {  		/*  		 * The instruction to be emulated is in a branch delay slot  		 * which means that we have to	emulate the branch instruction @@ -952,96 +773,85 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  			return SIGILL;  	} -      emul: +emul:  	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, xcp, 0);  	MIPS_FPU_EMU_INC_STATS(emulated);  	switch (MIPSInst_OPCODE(ir)) { -	case ldc1_op:{ -		u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] + -			MIPSInst_SIMM(ir)); -		u64 val; - +	case ldc1_op: +		dva = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] + +				     MIPSInst_SIMM(ir));  		MIPS_FPU_EMU_INC_STATS(loads); -		if (!access_ok(VERIFY_READ, va, sizeof(u64))) { +		if (!access_ok(VERIFY_READ, dva, sizeof(u64))) {  			MIPS_FPU_EMU_INC_STATS(errors); -			*fault_addr = va; +			*fault_addr = dva;  			return SIGBUS;  		} -		if (__get_user(val, va)) { +		if (__get_user(dval, dva)) {  			MIPS_FPU_EMU_INC_STATS(errors); -			*fault_addr = va; +			*fault_addr = dva;  			return SIGSEGV;  		} -		DITOREG(val, MIPSInst_RT(ir)); +		DITOREG(dval, MIPSInst_RT(ir));  		break; -	} - -	case sdc1_op:{ -		u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] + -			MIPSInst_SIMM(ir)); -		u64 val; +	case sdc1_op: +		dva = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] + +				      MIPSInst_SIMM(ir));  		MIPS_FPU_EMU_INC_STATS(stores); -		DIFROMREG(val, MIPSInst_RT(ir)); -		if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) { +		DIFROMREG(dval, MIPSInst_RT(ir)); +		if (!access_ok(VERIFY_WRITE, dva, sizeof(u64))) {  			MIPS_FPU_EMU_INC_STATS(errors); -			*fault_addr = va; +			*fault_addr = dva;  			return SIGBUS;  		} -		if (__put_user(val, va)) { +		if (__put_user(dval, dva)) {  			MIPS_FPU_EMU_INC_STATS(errors); -			*fault_addr = va; +			*fault_addr = dva;  			return SIGSEGV;  		}  		break; -	} - -	case lwc1_op:{ -		u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] + -			MIPSInst_SIMM(ir)); -		u32 val; +	case lwc1_op: +		wva = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] + +				      MIPSInst_SIMM(ir));  		MIPS_FPU_EMU_INC_STATS(loads); -		if (!access_ok(VERIFY_READ, va, sizeof(u32))) { +		if (!access_ok(VERIFY_READ, wva, sizeof(u32))) {  			MIPS_FPU_EMU_INC_STATS(errors); -			*fault_addr = va; +			*fault_addr = wva;  			return SIGBUS;  		} -		if (__get_user(val, va)) { +		if (__get_user(wval, wva)) {  			MIPS_FPU_EMU_INC_STATS(errors); -			*fault_addr = va; +			*fault_addr = wva;  			return SIGSEGV;  		} -		SITOREG(val, MIPSInst_RT(ir)); +		SITOREG(wval, MIPSInst_RT(ir));  		break; -	} - -	case swc1_op:{ -		u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] + -			MIPSInst_SIMM(ir)); -		u32 val; +	case swc1_op: +		wva = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] + +				      MIPSInst_SIMM(ir));  		MIPS_FPU_EMU_INC_STATS(stores); -		SIFROMREG(val, MIPSInst_RT(ir)); -		if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) { +		SIFROMREG(wval, MIPSInst_RT(ir)); +		if (!access_ok(VERIFY_WRITE, wva, sizeof(u32))) {  			MIPS_FPU_EMU_INC_STATS(errors); -			*fault_addr = va; +			*fault_addr = wva;  			return SIGBUS;  		} -		if (__put_user(val, va)) { +		if (__put_user(wval, wva)) {  			MIPS_FPU_EMU_INC_STATS(errors); -			*fault_addr = va; +			*fault_addr = wva;  			return SIGSEGV;  		}  		break; -	}  	case cop1_op:  		switch (MIPSInst_RS(ir)) { - -#if defined(__mips64)  		case dmfc_op: +			if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) +				return SIGILL; +  			/* copregister fs -> gpr[rt] */  			if (MIPSInst_RT(ir) != 0) {  				DIFROMREG(xcp->regs[MIPSInst_RT(ir)], @@ -1050,10 +860,31 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  			break;  		case dmtc_op: +			if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) +				return SIGILL; +  			/* copregister fs <- rt */  			DITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));  			break; -#endif + +		case mfhc_op: +			if (!cpu_has_mips_r2) +				goto sigill; + +			/* copregister rd -> gpr[rt] */ +			if (MIPSInst_RT(ir) != 0) { +				SIFROMHREG(xcp->regs[MIPSInst_RT(ir)], +					MIPSInst_RD(ir)); +			} +			break; + +		case mthc_op: +			if (!cpu_has_mips_r2) +				goto sigill; + +			/* copregister rd <- gpr[rt] */ +			SITOHREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir)); +			break;  		case mfc_op:  			/* copregister rd -> gpr[rt] */ @@ -1068,19 +899,14 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  			SITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));  			break; -		case cfc_op:{ +		case cfc_op:  			/* cop control register rd -> gpr[rt] */ -			u32 value; -  			if (MIPSInst_RD(ir) == FPCREG_CSR) {  				value = ctx->fcr31; -				value = (value & ~FPU_CSR_RM) | -					mips_rm[modeindex(value)]; -#ifdef CSRTRACE -				printk("%p gpr[%d]<-csr=%08x\n", -					(void *) (xcp->cp0_epc), -					MIPSInst_RT(ir), value); -#endif +				value = (value & ~FPU_CSR_RM) | modeindex(value); +				pr_debug("%p gpr[%d]<-csr=%08x\n", +					 (void *) (xcp->cp0_epc), +					 MIPSInst_RT(ir), value);  			}  			else if (MIPSInst_RD(ir) == FPCREG_RID)  				value = 0; @@ -1089,12 +915,9 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  			if (MIPSInst_RT(ir))  				xcp->regs[MIPSInst_RT(ir)] = value;  			break; -		} -		case ctc_op:{ +		case ctc_op:  			/* copregister rd <- rt */ -			u32 value; -  			if (MIPSInst_RT(ir) == 0)  				value = 0;  			else @@ -1103,37 +926,33 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  			/* we only have one writable control reg  			 */  			if (MIPSInst_RD(ir) == FPCREG_CSR) { -#ifdef CSRTRACE -				printk("%p gpr[%d]->csr=%08x\n", -					(void *) (xcp->cp0_epc), -					MIPSInst_RT(ir), value); -#endif +				pr_debug("%p gpr[%d]->csr=%08x\n", +					 (void *) (xcp->cp0_epc), +					 MIPSInst_RT(ir), value);  				/*  				 * Don't write reserved bits,  				 * and convert to ieee library modes  				 */ -				ctx->fcr31 = (value & -						~(FPU_CSR_RSVD | FPU_CSR_RM)) | -						ieee_rm[modeindex(value)]; +				ctx->fcr31 = (value & ~(FPU_CSR_RSVD | FPU_CSR_RM)) | +					     modeindex(value);  			}  			if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {  				return SIGFPE;  			}  			break; -		} - -		case bc_op:{ -			int likely = 0; -			if (xcp->cp0_cause & CAUSEF_BD) +		case bc_op: +			if (delay_slot(xcp))  				return SIGILL; -#if __mips >= 4 -			cond = ctx->fcr31 & fpucondbit[MIPSInst_RT(ir) >> 2]; -#else -			cond = ctx->fcr31 & FPU_CSR_COND; -#endif +			if (cpu_has_mips_4_5_r) +				cbit = fpucondbit[MIPSInst_RT(ir) >> 2]; +			else +				cbit = FPU_CSR_COND; +			cond = ctx->fcr31 & cbit; + +			likely = 0;  			switch (MIPSInst_RT(ir) & 3) {  			case bcfl_op:  				likely = 1; @@ -1149,10 +968,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  				return SIGILL;  			} -			xcp->cp0_cause |= CAUSEF_BD; +			set_delay_slot(xcp);  			if (cond) { -				/* branch taken: emulate dslot -				 * instruction +				/* +				 * Branch taken: emulate dslot instruction  				 */  				xcp->cp0_epc += dec_insn.pc_inc; @@ -1186,23 +1005,37 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  				switch (MIPSInst_OPCODE(ir)) {  				case lwc1_op: +					goto emul; +  				case swc1_op: -#if (__mips >= 2 || defined(__mips64)) +					goto emul; +  				case ldc1_op:  				case sdc1_op: -#endif +					if (cpu_has_mips_2_3_4_5 || +					    cpu_has_mips64) +						goto emul; + +					return SIGILL; +					goto emul; +  				case cop1_op: -#if __mips >= 4 && __mips != 32 -				case cop1x_op: -#endif -					/* its one of ours */  					goto emul; -#if __mips >= 4 + +				case cop1x_op: +					if (cpu_has_mips_4_5 || cpu_has_mips64) +						/* its one of ours */ +						goto emul; + +					return SIGILL; +  				case spec_op: +					if (!cpu_has_mips_4_5_r) +						return SIGILL; +  					if (MIPSInst_FUNC(ir) == movc_op)  						goto emul;  					break; -#endif  				}  				/* @@ -1210,10 +1043,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  				 * instruction in the dslot  				 */  				return mips_dsemul(xcp, ir, contpc); -			} -			else { -				/* branch not taken */ -				if (likely) { +			} else if (likely) {	/* branch not taken */  					/*  					 * branch likely nullifies  					 * dslot if not taken @@ -1225,34 +1055,31 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  					 * dslot as normal insn  					 */  				} -			}  			break; -		}  		default:  			if (!(MIPSInst_RS(ir) & 0x10))  				return SIGILL; -			{ -				int sig; -				/* a real fpu computation instruction */ -				if ((sig = fpu_emu(xcp, ctx, ir))) -					return sig; -			} +			/* a real fpu computation instruction */ +			if ((sig = fpu_emu(xcp, ctx, ir))) +				return sig;  		}  		break; -#if __mips >= 4 && __mips != 32 -	case cop1x_op:{ -		int sig = fpux_emu(xcp, ctx, ir, fault_addr); +	case cop1x_op: +		if (!cpu_has_mips_4_5 && !cpu_has_mips64) +			return SIGILL; + +		sig = fpux_emu(xcp, ctx, ir, fault_addr);  		if (sig)  			return sig;  		break; -	} -#endif -#if __mips >= 4  	case spec_op: +		if (!cpu_has_mips_4_5_r) +			return SIGILL; +  		if (MIPSInst_FUNC(ir) != movc_op)  			return SIGILL;  		cond = fpucondbit[MIPSInst_RT(ir) >> 2]; @@ -1260,15 +1087,14 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  			xcp->regs[MIPSInst_RD(ir)] =  				xcp->regs[MIPSInst_RS(ir)];  		break; -#endif -  	default: +sigill:  		return SIGILL;  	}  	/* we did it !! */  	xcp->cp0_epc = contpc; -	xcp->cp0_cause &= ~CAUSEF_BD; +	clear_delay_slot(xcp);  	return 0;  } @@ -1289,44 +1115,42 @@ static const unsigned char cmptab[8] = {  }; -#if __mips >= 4 && __mips != 32 -  /*   * Additional MIPS4 instructions   */ -#define DEF3OP(name, p, f1, f2, f3) \ -static ieee754##p fpemu_##p##_##name(ieee754##p r, ieee754##p s, \ -    ieee754##p t) \ -{ \ -	struct _ieee754_csr ieee754_csr_save; \ -	s = f1(s, t); \ -	ieee754_csr_save = ieee754_csr; \ -	s = f2(s, r); \ -	ieee754_csr_save.cx |= ieee754_csr.cx; \ -	ieee754_csr_save.sx |= ieee754_csr.sx; \ -	s = f3(s); \ -	ieee754_csr.cx |= ieee754_csr_save.cx; \ -	ieee754_csr.sx |= ieee754_csr_save.sx; \ -	return s; \ +#define DEF3OP(name, p, f1, f2, f3)					\ +static union ieee754##p fpemu_##p##_##name(union ieee754##p r,		\ +	union ieee754##p s, union ieee754##p t)				\ +{									\ +	struct _ieee754_csr ieee754_csr_save;				\ +	s = f1(s, t);							\ +	ieee754_csr_save = ieee754_csr;					\ +	s = f2(s, r);							\ +	ieee754_csr_save.cx |= ieee754_csr.cx;				\ +	ieee754_csr_save.sx |= ieee754_csr.sx;				\ +	s = f3(s);							\ +	ieee754_csr.cx |= ieee754_csr_save.cx;				\ +	ieee754_csr.sx |= ieee754_csr_save.sx;				\ +	return s;							\  } -static ieee754dp fpemu_dp_recip(ieee754dp d) +static union ieee754dp fpemu_dp_recip(union ieee754dp d)  {  	return ieee754dp_div(ieee754dp_one(0), d);  } -static ieee754dp fpemu_dp_rsqrt(ieee754dp d) +static union ieee754dp fpemu_dp_rsqrt(union ieee754dp d)  {  	return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d));  } -static ieee754sp fpemu_sp_recip(ieee754sp s) +static union ieee754sp fpemu_sp_recip(union ieee754sp s)  {  	return ieee754sp_div(ieee754sp_one(0), s);  } -static ieee754sp fpemu_sp_rsqrt(ieee754sp s) +static union ieee754sp fpemu_sp_rsqrt(union ieee754sp s)  {  	return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s));  } @@ -1350,8 +1174,8 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  	switch (MIPSInst_FMA_FFMT(ir)) {  	case s_fmt:{		/* 0 */ -		ieee754sp(*handler) (ieee754sp, ieee754sp, ieee754sp); -		ieee754sp fd, fr, fs, ft; +		union ieee754sp(*handler) (union ieee754sp, union ieee754sp, union ieee754sp); +		union ieee754sp fd, fr, fs, ft;  		u32 __user *va;  		u32 val; @@ -1414,18 +1238,26 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  			SPTOREG(fd, MIPSInst_FD(ir));  		      copcsr: -			if (ieee754_cxtest(IEEE754_INEXACT)) +			if (ieee754_cxtest(IEEE754_INEXACT)) { +				MIPS_FPU_EMU_INC_STATS(ieee754_inexact);  				rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S; -			if (ieee754_cxtest(IEEE754_UNDERFLOW)) +			} +			if (ieee754_cxtest(IEEE754_UNDERFLOW)) { +				MIPS_FPU_EMU_INC_STATS(ieee754_underflow);  				rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S; -			if (ieee754_cxtest(IEEE754_OVERFLOW)) +			} +			if (ieee754_cxtest(IEEE754_OVERFLOW)) { +				MIPS_FPU_EMU_INC_STATS(ieee754_overflow);  				rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S; -			if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) +			} +			if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) { +				MIPS_FPU_EMU_INC_STATS(ieee754_invalidop);  				rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S; +			}  			ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr;  			if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { -				/*printk ("SIGFPE: fpu csr = %08x\n", +				/*printk ("SIGFPE: FPU csr = %08x\n",  				   ctx->fcr31); */  				return SIGFPE;  			} @@ -1439,8 +1271,8 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  	}  	case d_fmt:{		/* 1 */ -		ieee754dp(*handler) (ieee754dp, ieee754dp, ieee754dp); -		ieee754dp fd, fr, fs, ft; +		union ieee754dp(*handler) (union ieee754dp, union ieee754dp, union ieee754dp); +		union ieee754dp fd, fr, fs, ft;  		u64 __user *va;  		u64 val; @@ -1508,10 +1340,10 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  		break;  	} -	case 0x7:		/* 7 */ -		if (MIPSInst_FUNC(ir) != pfetch_op) { +	case 0x3: +		if (MIPSInst_FUNC(ir) != pfetch_op)  			return SIGILL; -		} +  		/* ignore prefx operation */  		break; @@ -1521,7 +1353,6 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  	return 0;  } -#endif @@ -1533,23 +1364,25 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  {  	int rfmt;		/* resulting format */  	unsigned rcsr = 0;	/* resulting csr */ +	unsigned int oldrm; +	unsigned int cbit;  	unsigned cond;  	union { -		ieee754dp d; -		ieee754sp s; +		union ieee754dp d; +		union ieee754sp s;  		int w; -#ifdef __mips64  		s64 l; -#endif  	} rv;			/* resulting value */ +	u64 bits;  	MIPS_FPU_EMU_INC_STATS(cp1ops);  	switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) { -	case s_fmt:{		/* 0 */ +	case s_fmt: {		/* 0 */  		union { -			ieee754sp(*b) (ieee754sp, ieee754sp); -			ieee754sp(*u) (ieee754sp); +			union ieee754sp(*b) (union ieee754sp, union ieee754sp); +			union ieee754sp(*u) (union ieee754sp);  		} handler; +		union ieee754sp fs, ft;  		switch (MIPSInst_FUNC(ir)) {  			/* binary ops */ @@ -1567,148 +1400,167 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  			goto scopbop;  			/* unary  ops */ -#if __mips >= 2 || defined(__mips64)  		case fsqrt_op: +			if (!cpu_has_mips_4_5_r) +				return SIGILL; +  			handler.u = ieee754sp_sqrt;  			goto scopuop; -#endif -#if __mips >= 4 && __mips != 32 + +		/* +		 * Note that on some MIPS IV implementations such as the +		 * R5000 and R8000 the FSQRT and FRECIP instructions do not +		 * achieve full IEEE-754 accuracy - however this emulator does. +		 */  		case frsqrt_op: +			if (!cpu_has_mips_4_5_r2) +				return SIGILL; +  			handler.u = fpemu_sp_rsqrt;  			goto scopuop; +  		case frecip_op: +			if (!cpu_has_mips_4_5_r2) +				return SIGILL; +  			handler.u = fpemu_sp_recip;  			goto scopuop; -#endif -#if __mips >= 4 +  		case fmovc_op: +			if (!cpu_has_mips_4_5_r) +				return SIGILL; +  			cond = fpucondbit[MIPSInst_FT(ir) >> 2];  			if (((ctx->fcr31 & cond) != 0) !=  				((MIPSInst_FT(ir) & 1) != 0))  				return 0;  			SPFROMREG(rv.s, MIPSInst_FS(ir));  			break; +  		case fmovz_op: +			if (!cpu_has_mips_4_5_r) +				return SIGILL; +  			if (xcp->regs[MIPSInst_FT(ir)] != 0)  				return 0;  			SPFROMREG(rv.s, MIPSInst_FS(ir));  			break; +  		case fmovn_op: +			if (!cpu_has_mips_4_5_r) +				return SIGILL; +  			if (xcp->regs[MIPSInst_FT(ir)] == 0)  				return 0;  			SPFROMREG(rv.s, MIPSInst_FS(ir));  			break; -#endif +  		case fabs_op:  			handler.u = ieee754sp_abs;  			goto scopuop; +  		case fneg_op:  			handler.u = ieee754sp_neg;  			goto scopuop; +  		case fmov_op:  			/* an easy one */  			SPFROMREG(rv.s, MIPSInst_FS(ir));  			goto copcsr;  			/* binary op on handler */ -		      scopbop: -			{ -				ieee754sp fs, ft; - -				SPFROMREG(fs, MIPSInst_FS(ir)); -				SPFROMREG(ft, MIPSInst_FT(ir)); - -				rv.s = (*handler.b) (fs, ft); -				goto copcsr; -			} -		      scopuop: -			{ -				ieee754sp fs; +scopbop: +			SPFROMREG(fs, MIPSInst_FS(ir)); +			SPFROMREG(ft, MIPSInst_FT(ir)); -				SPFROMREG(fs, MIPSInst_FS(ir)); -				rv.s = (*handler.u) (fs); -				goto copcsr; -			} -		      copcsr: -			if (ieee754_cxtest(IEEE754_INEXACT)) +			rv.s = (*handler.b) (fs, ft); +			goto copcsr; +scopuop: +			SPFROMREG(fs, MIPSInst_FS(ir)); +			rv.s = (*handler.u) (fs); +			goto copcsr; +copcsr: +			if (ieee754_cxtest(IEEE754_INEXACT)) { +				MIPS_FPU_EMU_INC_STATS(ieee754_inexact);  				rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S; -			if (ieee754_cxtest(IEEE754_UNDERFLOW)) +			} +			if (ieee754_cxtest(IEEE754_UNDERFLOW)) { +				MIPS_FPU_EMU_INC_STATS(ieee754_underflow);  				rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S; -			if (ieee754_cxtest(IEEE754_OVERFLOW)) +			} +			if (ieee754_cxtest(IEEE754_OVERFLOW)) { +				MIPS_FPU_EMU_INC_STATS(ieee754_overflow);  				rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S; -			if (ieee754_cxtest(IEEE754_ZERO_DIVIDE)) +			} +			if (ieee754_cxtest(IEEE754_ZERO_DIVIDE)) { +				MIPS_FPU_EMU_INC_STATS(ieee754_zerodiv);  				rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S; -			if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) +			} +			if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) { +				MIPS_FPU_EMU_INC_STATS(ieee754_invalidop);  				rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S; +			}  			break;  			/* unary conv ops */  		case fcvts_op:  			return SIGILL;	/* not defined */ -		case fcvtd_op:{ -			ieee754sp fs; +		case fcvtd_op:  			SPFROMREG(fs, MIPSInst_FS(ir));  			rv.d = ieee754dp_fsp(fs);  			rfmt = d_fmt;  			goto copcsr; -		} -		case fcvtw_op:{ -			ieee754sp fs; +		case fcvtw_op:  			SPFROMREG(fs, MIPSInst_FS(ir));  			rv.w = ieee754sp_tint(fs);  			rfmt = w_fmt;  			goto copcsr; -		} -#if __mips >= 2 || defined(__mips64)  		case fround_op:  		case ftrunc_op:  		case fceil_op: -		case ffloor_op:{ -			unsigned int oldrm = ieee754_csr.rm; -			ieee754sp fs; +		case ffloor_op: +			if (!cpu_has_mips_2_3_4_5 && !cpu_has_mips64) +				return SIGILL; +			oldrm = ieee754_csr.rm;  			SPFROMREG(fs, MIPSInst_FS(ir)); -			ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; +			ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir));  			rv.w = ieee754sp_tint(fs);  			ieee754_csr.rm = oldrm;  			rfmt = w_fmt;  			goto copcsr; -		} -#endif /* __mips >= 2 */ -#if defined(__mips64) -		case fcvtl_op:{ -			ieee754sp fs; +		case fcvtl_op: +			if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) +				return SIGILL;  			SPFROMREG(fs, MIPSInst_FS(ir));  			rv.l = ieee754sp_tlong(fs);  			rfmt = l_fmt;  			goto copcsr; -		}  		case froundl_op:  		case ftruncl_op:  		case fceill_op: -		case ffloorl_op:{ -			unsigned int oldrm = ieee754_csr.rm; -			ieee754sp fs; +		case ffloorl_op: +			if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) +				return SIGILL; +			oldrm = ieee754_csr.rm;  			SPFROMREG(fs, MIPSInst_FS(ir)); -			ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; +			ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir));  			rv.l = ieee754sp_tlong(fs);  			ieee754_csr.rm = oldrm;  			rfmt = l_fmt;  			goto copcsr; -		} -#endif /* defined(__mips64) */  		default:  			if (MIPSInst_FUNC(ir) >= fcmp_op) {  				unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op; -				ieee754sp fs, ft; +				union ieee754sp fs, ft;  				SPFROMREG(fs, MIPSInst_FS(ir));  				SPFROMREG(ft, MIPSInst_FT(ir)); @@ -1721,19 +1573,18 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  				else  					goto copcsr; -			} -			else { +			} else  				return SIGILL; -			}  			break;  		}  		break;  	} -	case d_fmt:{ +	case d_fmt: { +		union ieee754dp fs, ft;  		union { -			ieee754dp(*b) (ieee754dp, ieee754dp); -			ieee754dp(*u) (ieee754dp); +			union ieee754dp(*b) (union ieee754dp, union ieee754dp); +			union ieee754dp(*u) (union ieee754dp);  		} handler;  		switch (MIPSInst_FUNC(ir)) { @@ -1752,21 +1603,33 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  			goto dcopbop;  			/* unary  ops */ -#if __mips >= 2 || defined(__mips64)  		case fsqrt_op: +			if (!cpu_has_mips_2_3_4_5_r) +				return SIGILL; +  			handler.u = ieee754dp_sqrt;  			goto dcopuop; -#endif -#if __mips >= 4 && __mips != 32 +		/* +		 * Note that on some MIPS IV implementations such as the +		 * R5000 and R8000 the FSQRT and FRECIP instructions do not +		 * achieve full IEEE-754 accuracy - however this emulator does. +		 */  		case frsqrt_op: +			if (!cpu_has_mips_4_5_r2) +				return SIGILL; +  			handler.u = fpemu_dp_rsqrt;  			goto dcopuop;  		case frecip_op: +			if (!cpu_has_mips_4_5_r2) +				return SIGILL; +  			handler.u = fpemu_dp_recip;  			goto dcopuop; -#endif -#if __mips >= 4  		case fmovc_op: +			if (!cpu_has_mips_4_5_r) +				return SIGILL; +  			cond = fpucondbit[MIPSInst_FT(ir) >> 2];  			if (((ctx->fcr31 & cond) != 0) !=  				((MIPSInst_FT(ir) & 1) != 0)) @@ -1774,16 +1637,21 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  			DPFROMREG(rv.d, MIPSInst_FS(ir));  			break;  		case fmovz_op: +			if (!cpu_has_mips_4_5_r) +				return SIGILL; +  			if (xcp->regs[MIPSInst_FT(ir)] != 0)  				return 0;  			DPFROMREG(rv.d, MIPSInst_FS(ir));  			break;  		case fmovn_op: +			if (!cpu_has_mips_4_5_r) +				return SIGILL; +  			if (xcp->regs[MIPSInst_FT(ir)] == 0)  				return 0;  			DPFROMREG(rv.d, MIPSInst_FS(ir));  			break; -#endif  		case fabs_op:  			handler.u = ieee754dp_abs;  			goto dcopuop; @@ -1798,91 +1666,78 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  			goto copcsr;  			/* binary op on handler */ -		      dcopbop:{ -				ieee754dp fs, ft; - -				DPFROMREG(fs, MIPSInst_FS(ir)); -				DPFROMREG(ft, MIPSInst_FT(ir)); - -				rv.d = (*handler.b) (fs, ft); -				goto copcsr; -			} -		      dcopuop:{ -				ieee754dp fs; - -				DPFROMREG(fs, MIPSInst_FS(ir)); -				rv.d = (*handler.u) (fs); -				goto copcsr; -			} +dcopbop: +			DPFROMREG(fs, MIPSInst_FS(ir)); +			DPFROMREG(ft, MIPSInst_FT(ir)); -			/* unary conv ops */ -		case fcvts_op:{ -			ieee754dp fs; +			rv.d = (*handler.b) (fs, ft); +			goto copcsr; +dcopuop: +			DPFROMREG(fs, MIPSInst_FS(ir)); +			rv.d = (*handler.u) (fs); +			goto copcsr; +		/* +		 * unary conv ops +		 */ +		case fcvts_op:  			DPFROMREG(fs, MIPSInst_FS(ir));  			rv.s = ieee754sp_fdp(fs);  			rfmt = s_fmt;  			goto copcsr; -		} +  		case fcvtd_op:  			return SIGILL;	/* not defined */ -		case fcvtw_op:{ -			ieee754dp fs; - +		case fcvtw_op:  			DPFROMREG(fs, MIPSInst_FS(ir));  			rv.w = ieee754dp_tint(fs);	/* wrong */  			rfmt = w_fmt;  			goto copcsr; -		} -#if __mips >= 2 || defined(__mips64)  		case fround_op:  		case ftrunc_op:  		case fceil_op: -		case ffloor_op:{ -			unsigned int oldrm = ieee754_csr.rm; -			ieee754dp fs; +		case ffloor_op: +			if (!cpu_has_mips_2_3_4_5_r) +				return SIGILL; +			oldrm = ieee754_csr.rm;  			DPFROMREG(fs, MIPSInst_FS(ir)); -			ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; +			ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir));  			rv.w = ieee754dp_tint(fs);  			ieee754_csr.rm = oldrm;  			rfmt = w_fmt;  			goto copcsr; -		} -#endif -#if defined(__mips64) -		case fcvtl_op:{ -			ieee754dp fs; +		case fcvtl_op: +			if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) +				return SIGILL;  			DPFROMREG(fs, MIPSInst_FS(ir));  			rv.l = ieee754dp_tlong(fs);  			rfmt = l_fmt;  			goto copcsr; -		}  		case froundl_op:  		case ftruncl_op:  		case fceill_op: -		case ffloorl_op:{ -			unsigned int oldrm = ieee754_csr.rm; -			ieee754dp fs; +		case ffloorl_op: +			if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) +				return SIGILL; +			oldrm = ieee754_csr.rm;  			DPFROMREG(fs, MIPSInst_FS(ir)); -			ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; +			ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir));  			rv.l = ieee754dp_tlong(fs);  			ieee754_csr.rm = oldrm;  			rfmt = l_fmt;  			goto copcsr; -		} -#endif /* __mips >= 3 */  		default:  			if (MIPSInst_FUNC(ir) >= fcmp_op) {  				unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op; -				ieee754dp fs, ft; +				union ieee754dp fs, ft;  				DPFROMREG(fs, MIPSInst_FS(ir));  				DPFROMREG(ft, MIPSInst_FT(ir)); @@ -1904,11 +1759,8 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  			break;  		}  		break; -	} - -	case w_fmt:{ -		ieee754sp fs; +	case w_fmt:  		switch (MIPSInst_FUNC(ir)) {  		case fcvts_op:  			/* convert word to single precision real */ @@ -1928,25 +1780,28 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  		break;  	} -#if defined(__mips64) -	case l_fmt:{ +	case l_fmt: + +		if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) +			return SIGILL; + +		DIFROMREG(bits, MIPSInst_FS(ir)); +  		switch (MIPSInst_FUNC(ir)) {  		case fcvts_op:  			/* convert long to single precision real */ -			rv.s = ieee754sp_flong(ctx->fpr[MIPSInst_FS(ir)]); +			rv.s = ieee754sp_flong(bits);  			rfmt = s_fmt;  			goto copcsr;  		case fcvtd_op:  			/* convert long to double precision real */ -			rv.d = ieee754dp_flong(ctx->fpr[MIPSInst_FS(ir)]); +			rv.d = ieee754dp_flong(bits);  			rfmt = d_fmt;  			goto copcsr;  		default:  			return SIGILL;  		}  		break; -	} -#endif  	default:  		return SIGILL; @@ -1961,7 +1816,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  	 */  	ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr;  	if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { -		/*printk ("SIGFPE: fpu csr = %08x\n",ctx->fcr31); */ +		/*printk ("SIGFPE: FPU csr = %08x\n",ctx->fcr31); */  		return SIGFPE;  	} @@ -1969,18 +1824,18 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  	 * Now we can safely write the result back to the register file.  	 */  	switch (rfmt) { -	case -1:{ -#if __mips >= 4 -		cond = fpucondbit[MIPSInst_FD(ir) >> 2]; -#else -		cond = FPU_CSR_COND; -#endif +	case -1: + +		if (cpu_has_mips_4_5_r) +			cbit = fpucondbit[MIPSInst_RT(ir) >> 2]; +		else +			cbit = FPU_CSR_COND;  		if (rv.w) -			ctx->fcr31 |= cond; +			ctx->fcr31 |= cbit;  		else -			ctx->fcr31 &= ~cond; +			ctx->fcr31 &= ~cbit;  		break; -	} +  	case d_fmt:  		DPTOREG(rv.d, MIPSInst_FD(ir));  		break; @@ -1990,11 +1845,12 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  	case w_fmt:  		SITOREG(rv.w, MIPSInst_FD(ir));  		break; -#if defined(__mips64)  	case l_fmt: +		if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) +			return SIGILL; +  		DITOREG(rv.l, MIPSInst_FD(ir));  		break; -#endif  	default:  		return SIGILL;  	} @@ -2082,11 +1938,7 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  			 * ieee754_csr.	 But ieee754_csr.rm is ieee  			 * library modes. (not mips rounding mode)  			 */ -			/* convert to ieee library modes */ -			ieee754_csr.rm = ieee_rm[ieee754_csr.rm];  			sig = cop1Emulate(xcp, ctx, dec_insn, fault_addr); -			/* revert to mips rounding mode */ -			ieee754_csr.rm = mips_rm[ieee754_csr.rm];  		}  		if (has_fpu) @@ -2099,58 +1951,8 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  	/* SIGILL indicates a non-fpu instruction */  	if (sig == SIGILL && xcp->cp0_epc != oldepc) -		/* but if epc has advanced, then ignore it */ +		/* but if EPC has advanced, then ignore it */  		sig = 0;  	return sig;  } - -#ifdef CONFIG_DEBUG_FS - -static int fpuemu_stat_get(void *data, u64 *val) -{ -	int cpu; -	unsigned long sum = 0; -	for_each_online_cpu(cpu) { -		struct mips_fpu_emulator_stats *ps; -		local_t *pv; -		ps = &per_cpu(fpuemustats, cpu); -		pv = (void *)ps + (unsigned long)data; -		sum += local_read(pv); -	} -	*val = sum; -	return 0; -} -DEFINE_SIMPLE_ATTRIBUTE(fops_fpuemu_stat, fpuemu_stat_get, NULL, "%llu\n"); - -extern struct dentry *mips_debugfs_dir; -static int __init debugfs_fpuemu(void) -{ -	struct dentry *d, *dir; - -	if (!mips_debugfs_dir) -		return -ENODEV; -	dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir); -	if (!dir) -		return -ENOMEM; - -#define FPU_STAT_CREATE(M)						\ -	do {								\ -		d = debugfs_create_file(#M , S_IRUGO, dir,		\ -			(void *)offsetof(struct mips_fpu_emulator_stats, M), \ -			&fops_fpuemu_stat);				\ -		if (!d)							\ -			return -ENOMEM;					\ -	} while (0) - -	FPU_STAT_CREATE(emulated); -	FPU_STAT_CREATE(loads); -	FPU_STAT_CREATE(stores); -	FPU_STAT_CREATE(cp1ops); -	FPU_STAT_CREATE(cp1xops); -	FPU_STAT_CREATE(errors); - -	return 0; -} -__initcall(debugfs_fpuemu); -#endif diff --git a/arch/mips/math-emu/dp_add.c b/arch/mips/math-emu/dp_add.c index c57c8adc42c..7f64577df98 100644 --- a/arch/mips/math-emu/dp_add.c +++ b/arch/mips/math-emu/dp_add.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,24 +16,22 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754dp.h" -ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y) +union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y)  { +	int s; +  	COMPXDP;  	COMPYDP;  	EXPLODEXDP;  	EXPLODEYDP; -	CLEARCX; +	ieee754_clearcx();  	FLUSHXDP;  	FLUSHYDP; @@ -52,8 +48,8 @@ ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754dp_nanxcpt(ieee754dp_indef(), "add", x, y); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754dp_nanxcpt(ieee754dp_indef());  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -69,14 +65,14 @@ ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)  		return x; -		/* Infinity handling -		 */ - +	/* +	 * Infinity handling +	 */  	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):  		if (xs == ys)  			return x; -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754dp_xcpt(ieee754dp_indef(), "add", x, y); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754dp_indef();  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): @@ -88,15 +84,14 @@ ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)  	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):  		return x; -		/* Zero handling -		 */ - +	/* +	 * Zero handling +	 */  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):  		if (xs == ys)  			return x;  		else -			return ieee754dp_zero(ieee754_csr.rm == -					      IEEE754_RD); +			return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD);  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):  	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): @@ -125,20 +120,24 @@ ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)  	assert(xm & DP_HIDDEN_BIT);  	assert(ym & DP_HIDDEN_BIT); -	/* provide guard,round and stick bit space */ +	/* +	 * Provide guard,round and stick bit space. +	 */  	xm <<= 3;  	ym <<= 3;  	if (xe > ye) { -		/* have to shift y fraction right to align +		/* +		 * Have to shift y fraction right to align.  		 */ -		int s = xe - ye; +		s = xe - ye;  		ym = XDPSRS(ym, s);  		ye += s;  	} else if (ye > xe) { -		/* have to shift x fraction right to align +		/* +		 * Have to shift x fraction right to align.  		 */ -		int s = ye - xe; +		s = ye - xe;  		xm = XDPSRS(xm, s);  		xe += s;  	} @@ -146,14 +145,15 @@ ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)  	assert(xe <= DP_EMAX);  	if (xs == ys) { -		/* generate 28 bit result of adding two 27 bit numbers -		 * leaving result in xm,xs,xe +		/* +		 * Generate 28 bit result of adding two 27 bit numbers +		 * leaving result in xm, xs and xe.  		 */  		xm = xm + ym;  		xe = xe;  		xs = xs; -		if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */ +		if (xm >> (DP_FBITS + 1 + 3)) { /* carry out */  			xm = XDPSRS1(xm);  			xe++;  		} @@ -168,15 +168,16 @@ ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)  			xs = ys;  		}  		if (xm == 0) -			return ieee754dp_zero(ieee754_csr.rm == -					      IEEE754_RD); +			return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD); -		/* normalize to rounding precision */ -		while ((xm >> (DP_MBITS + 3)) == 0) { +		/* +		 * Normalize to rounding precision. +		 */ +		while ((xm >> (DP_FBITS + 3)) == 0) {  			xm <<= 1;  			xe--;  		} -  	} -	DPNORMRET2(xs, xe, xm, "add", x, y); + +	return ieee754dp_format(xs, xe, xm);  } diff --git a/arch/mips/math-emu/dp_cmp.c b/arch/mips/math-emu/dp_cmp.c index 0f32486b0ed..30f95f6e9ac 100644 --- a/arch/mips/math-emu/dp_cmp.c +++ b/arch/mips/math-emu/dp_cmp.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,16 +16,16 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754dp.h" -int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cmp, int sig) +int ieee754dp_cmp(union ieee754dp x, union ieee754dp y, int cmp, int sig)  { +	s64 vx; +	s64 vy; +  	COMPXDP;  	COMPYDP; @@ -35,21 +33,21 @@ int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cmp, int sig)  	EXPLODEYDP;  	FLUSHXDP;  	FLUSHYDP; -	CLEARCX;	/* Even clear inexact flag here */ +	ieee754_clearcx();	/* Even clear inexact flag here */  	if (ieee754dp_isnan(x) || ieee754dp_isnan(y)) {  		if (sig || xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN) -			SETCX(IEEE754_INVALID_OPERATION); +			ieee754_setcx(IEEE754_INVALID_OPERATION);  		if (cmp & IEEE754_CUN)  			return 1;  		if (cmp & (IEEE754_CLT | IEEE754_CGT)) { -			if (sig && SETANDTESTCX(IEEE754_INVALID_OPERATION)) -				return ieee754si_xcpt(0, "fcmpf", x); +			if (sig && ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) +				return 0;  		}  		return 0;  	} else { -		s64 vx = x.bits; -		s64 vy = y.bits; +		vx = x.bits; +		vy = y.bits;  		if (vx < 0)  			vx = -vx ^ DP_SIGN_BIT; diff --git a/arch/mips/math-emu/dp_div.c b/arch/mips/math-emu/dp_div.c index a1bce1b7c09..bef0e55e593 100644 --- a/arch/mips/math-emu/dp_div.c +++ b/arch/mips/math-emu/dp_div.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,23 +16,24 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754dp.h" -ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y) +union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y)  { +	u64 rm; +	int re; +	u64 bm; +  	COMPXDP;  	COMPYDP;  	EXPLODEXDP;  	EXPLODEYDP; -	CLEARCX; +	ieee754_clearcx();  	FLUSHXDP;  	FLUSHYDP; @@ -51,8 +50,8 @@ ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y)  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754dp_nanxcpt(ieee754dp_indef(), "div", x, y); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754dp_nanxcpt(ieee754dp_indef());  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -68,12 +67,12 @@ ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y)  		return x; -		/* Infinity handling -		 */ - +	/* +	 * Infinity handling +	 */  	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754dp_indef();  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): @@ -85,17 +84,17 @@ ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y)  	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):  		return ieee754dp_inf(xs ^ ys); -		/* Zero handling -		 */ - +	/* +	 * Zero handling +	 */  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754dp_indef();  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):  	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): -		SETCX(IEEE754_ZERO_DIVIDE); -		return ieee754dp_xcpt(ieee754dp_inf(xs ^ ys), "div", x, y); +		ieee754_setcx(IEEE754_ZERO_DIVIDE); +		return ieee754dp_inf(xs ^ ys);  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): @@ -122,35 +121,34 @@ ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y)  	xm <<= 3;  	ym <<= 3; -	{ -		/* now the dirty work */ - -		u64 rm = 0; -		int re = xe - ye; -		u64 bm; - -		for (bm = DP_MBIT(DP_MBITS + 2); bm; bm >>= 1) { -			if (xm >= ym) { -				xm -= ym; -				rm |= bm; -				if (xm == 0) -					break; -			} -			xm <<= 1; -		} -		rm <<= 1; -		if (xm) -			rm |= 1;	/* have remainder, set sticky */ +	/* now the dirty work */ -		assert(rm); +	rm = 0; +	re = xe - ye; -		/* normalise rm to rounding precision ? -		 */ -		while ((rm >> (DP_MBITS + 3)) == 0) { -			rm <<= 1; -			re--; +	for (bm = DP_MBIT(DP_FBITS + 2); bm; bm >>= 1) { +		if (xm >= ym) { +			xm -= ym; +			rm |= bm; +			if (xm == 0) +				break;  		} +		xm <<= 1; +	} + +	rm <<= 1; +	if (xm) +		rm |= 1;	/* have remainder, set sticky */ -		DPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y); +	assert(rm); + +	/* +	 * Normalise rm to rounding precision ? +	 */ +	while ((rm >> (DP_FBITS + 3)) == 0) { +		rm <<= 1; +		re--;  	} + +	return ieee754dp_format(xs == ys ? 0 : 1, re, rm);  } diff --git a/arch/mips/math-emu/dp_fint.c b/arch/mips/math-emu/dp_fint.c index 88571288c9e..10258f0afd6 100644 --- a/arch/mips/math-emu/dp_fint.c +++ b/arch/mips/math-emu/dp_fint.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,21 +16,18 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754dp.h" -ieee754dp ieee754dp_fint(int x) +union ieee754dp ieee754dp_fint(int x)  {  	u64 xm;  	int xe;  	int xs; -	CLEARCX; +	ieee754_clearcx();  	if (x == 0)  		return ieee754dp_zero(0); @@ -51,29 +46,11 @@ ieee754dp ieee754dp_fint(int x)  		xm = x;  	} -#if 1  	/* normalize - result can never be inexact or overflow */ -	xe = DP_MBITS; -	while ((xm >> DP_MBITS) == 0) { +	xe = DP_FBITS; +	while ((xm >> DP_FBITS) == 0) {  		xm <<= 1;  		xe--;  	}  	return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT); -#else -	/* normalize */ -	xe = DP_MBITS + 3; -	while ((xm >> (DP_MBITS + 3)) == 0) { -		xm <<= 1; -		xe--; -	} -	DPNORMRET1(xs, xe, xm, "fint", x); -#endif -} - -ieee754dp ieee754dp_funs(unsigned int u) -{ -	if ((int) u < 0) -		return ieee754dp_add(ieee754dp_1e31(), -				     ieee754dp_fint(u & ~(1 << 31))); -	return ieee754dp_fint(u);  } diff --git a/arch/mips/math-emu/dp_flong.c b/arch/mips/math-emu/dp_flong.c index 14fc01ec742..a267c2e39d7 100644 --- a/arch/mips/math-emu/dp_flong.c +++ b/arch/mips/math-emu/dp_flong.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,21 +16,18 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754dp.h" -ieee754dp ieee754dp_flong(s64 x) +union ieee754dp ieee754dp_flong(s64 x)  {  	u64 xm;  	int xe;  	int xs; -	CLEARCX; +	ieee754_clearcx();  	if (x == 0)  		return ieee754dp_zero(0); @@ -52,26 +47,19 @@ ieee754dp ieee754dp_flong(s64 x)  	}  	/* normalize */ -	xe = DP_MBITS + 3; -	if (xm >> (DP_MBITS + 1 + 3)) { +	xe = DP_FBITS + 3; +	if (xm >> (DP_FBITS + 1 + 3)) {  		/* shunt out overflow bits */ -		while (xm >> (DP_MBITS + 1 + 3)) { +		while (xm >> (DP_FBITS + 1 + 3)) {  			XDPSRSX1();  		}  	} else {  		/* normalize in grs extended double precision */ -		while ((xm >> (DP_MBITS + 3)) == 0) { +		while ((xm >> (DP_FBITS + 3)) == 0) {  			xm <<= 1;  			xe--;  		}  	} -	DPNORMRET1(xs, xe, xm, "dp_flong", x); -} -ieee754dp ieee754dp_fulong(u64 u) -{ -	if ((s64) u < 0) -		return ieee754dp_add(ieee754dp_1e63(), -				     ieee754dp_flong(u & ~(1ULL << 63))); -	return ieee754dp_flong(u); +	return ieee754dp_format(xs, xe, xm);  } diff --git a/arch/mips/math-emu/dp_frexp.c b/arch/mips/math-emu/dp_frexp.c deleted file mode 100644 index cb15a5eaecb..00000000000 --- a/arch/mips/math-emu/dp_frexp.c +++ /dev/null @@ -1,52 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. - * - * ######################################################################## - * - *  This program is free software; you can distribute it and/or modify it - *  under the terms of the GNU General Public License (Version 2) as - *  published by the Free Software Foundation. - * - *  This program is distributed in the hope it will be useful, but WITHOUT - *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License - *  for more details. - * - *  You should have received a copy of the GNU General Public License along - *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -/* close to ieeep754dp_logb -*/ -ieee754dp ieee754dp_frexp(ieee754dp x, int *eptr) -{ -	COMPXDP; -	CLEARCX; -	EXPLODEXDP; - -	switch (xc) { -	case IEEE754_CLASS_SNAN: -	case IEEE754_CLASS_QNAN: -	case IEEE754_CLASS_INF: -	case IEEE754_CLASS_ZERO: -		*eptr = 0; -		return x; -	case IEEE754_CLASS_DNORM: -		DPDNORMX; -		break; -	case IEEE754_CLASS_NORM: -		break; -	} -	*eptr = xe + 1; -	return builddp(xs, -1 + DP_EBIAS, xm & ~DP_HIDDEN_BIT); -} diff --git a/arch/mips/math-emu/dp_fsp.c b/arch/mips/math-emu/dp_fsp.c index daed6834dc1..ffb69c5830b 100644 --- a/arch/mips/math-emu/dp_fsp.c +++ b/arch/mips/math-emu/dp_fsp.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,56 +16,58 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ - +#include "ieee754sp.h"  #include "ieee754dp.h" -ieee754dp ieee754dp_fsp(ieee754sp x) +union ieee754dp ieee754dp_fsp(union ieee754sp x)  {  	COMPXSP;  	EXPLODEXSP; -	CLEARCX; +	ieee754_clearcx();  	FLUSHXSP;  	switch (xc) {  	case IEEE754_CLASS_SNAN: -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754dp_nanxcpt(ieee754dp_indef(), "fsp"); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754dp_nanxcpt(ieee754dp_indef()); +  	case IEEE754_CLASS_QNAN:  		return ieee754dp_nanxcpt(builddp(xs,  						 DP_EMAX + 1 + DP_EBIAS,  						 ((u64) xm -						  << (DP_MBITS - -						      SP_MBITS))), "fsp", -					 x); +						  << (DP_FBITS - +						      SP_FBITS))));  	case IEEE754_CLASS_INF:  		return ieee754dp_inf(xs); +  	case IEEE754_CLASS_ZERO:  		return ieee754dp_zero(xs); +  	case IEEE754_CLASS_DNORM:  		/* normalize */ -		while ((xm >> SP_MBITS) == 0) { +		while ((xm >> SP_FBITS) == 0) {  			xm <<= 1;  			xe--;  		}  		break; +  	case IEEE754_CLASS_NORM:  		break;  	} -	/* CAN'T possibly overflow,underflow, or need rounding +	/* +	 * Can't possibly overflow,underflow, or need rounding  	 */  	/* drop the hidden bit */  	xm &= ~SP_HIDDEN_BIT;  	return builddp(xs, xe + DP_EBIAS, -		       (u64) xm << (DP_MBITS - SP_MBITS)); +		       (u64) xm << (DP_FBITS - SP_FBITS));  } diff --git a/arch/mips/math-emu/dp_logb.c b/arch/mips/math-emu/dp_logb.c deleted file mode 100644 index 151127e59f5..00000000000 --- a/arch/mips/math-emu/dp_logb.c +++ /dev/null @@ -1,53 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. - * - * ######################################################################## - * - *  This program is free software; you can distribute it and/or modify it - *  under the terms of the GNU General Public License (Version 2) as - *  published by the Free Software Foundation. - * - *  This program is distributed in the hope it will be useful, but WITHOUT - *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License - *  for more details. - * - *  You should have received a copy of the GNU General Public License along - *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -ieee754dp ieee754dp_logb(ieee754dp x) -{ -	COMPXDP; - -	CLEARCX; - -	EXPLODEXDP; - -	switch (xc) { -	case IEEE754_CLASS_SNAN: -		return ieee754dp_nanxcpt(x, "logb", x); -	case IEEE754_CLASS_QNAN: -		return x; -	case IEEE754_CLASS_INF: -		return ieee754dp_inf(0); -	case IEEE754_CLASS_ZERO: -		return ieee754dp_inf(1); -	case IEEE754_CLASS_DNORM: -		DPDNORMX; -		break; -	case IEEE754_CLASS_NORM: -		break; -	} -	return ieee754dp_fint(xe); -} diff --git a/arch/mips/math-emu/dp_modf.c b/arch/mips/math-emu/dp_modf.c deleted file mode 100644 index b01f9cf6d40..00000000000 --- a/arch/mips/math-emu/dp_modf.c +++ /dev/null @@ -1,79 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. - * - * ######################################################################## - * - *  This program is free software; you can distribute it and/or modify it - *  under the terms of the GNU General Public License (Version 2) as - *  published by the Free Software Foundation. - * - *  This program is distributed in the hope it will be useful, but WITHOUT - *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License - *  for more details. - * - *  You should have received a copy of the GNU General Public License along - *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -/* modf function is always exact for a finite number -*/ -ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp *ip) -{ -	COMPXDP; - -	CLEARCX; - -	EXPLODEXDP; - -	switch (xc) { -	case IEEE754_CLASS_SNAN: -	case IEEE754_CLASS_QNAN: -	case IEEE754_CLASS_INF: -	case IEEE754_CLASS_ZERO: -		*ip = x; -		return x; -	case IEEE754_CLASS_DNORM: -		/* far to small */ -		*ip = ieee754dp_zero(xs); -		return x; -	case IEEE754_CLASS_NORM: -		break; -	} -	if (xe < 0) { -		*ip = ieee754dp_zero(xs); -		return x; -	} -	if (xe >= DP_MBITS) { -		*ip = x; -		return ieee754dp_zero(xs); -	} -	/* generate ipart mantissa by clearing bottom bits -	 */ -	*ip = builddp(xs, xe + DP_EBIAS, -		      ((xm >> (DP_MBITS - xe)) << (DP_MBITS - xe)) & -		      ~DP_HIDDEN_BIT); - -	/* generate fpart mantissa by clearing top bits -	 * and normalizing (must be able to normalize) -	 */ -	xm = (xm << (64 - (DP_MBITS - xe))) >> (64 - (DP_MBITS - xe)); -	if (xm == 0) -		return ieee754dp_zero(xs); - -	while ((xm >> DP_MBITS) == 0) { -		xm <<= 1; -		xe--; -	} -	return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT); -} diff --git a/arch/mips/math-emu/dp_mul.c b/arch/mips/math-emu/dp_mul.c index 09175f46192..d3acdedb5b9 100644 --- a/arch/mips/math-emu/dp_mul.c +++ b/arch/mips/math-emu/dp_mul.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,23 +16,32 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754dp.h" -ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y) +union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y)  { +	int re; +	int rs; +	u64 rm; +	unsigned lxm; +	unsigned hxm; +	unsigned lym; +	unsigned hym; +	u64 lrm; +	u64 hrm; +	u64 t; +	u64 at; +  	COMPXDP;  	COMPYDP;  	EXPLODEXDP;  	EXPLODEYDP; -	CLEARCX; +	ieee754_clearcx();  	FLUSHXDP;  	FLUSHYDP; @@ -51,8 +58,8 @@ ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y)  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754dp_nanxcpt(ieee754dp_indef(), "mul", x, y); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754dp_nanxcpt(ieee754dp_indef());  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -68,12 +75,13 @@ ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y)  		return x; -		/* Infinity handling */ - +	/* +	 * Infinity handling +	 */  	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754dp_xcpt(ieee754dp_indef(), "mul", x, y); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754dp_indef();  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):  	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): @@ -107,70 +115,59 @@ ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y)  	/* rm = xm * ym, re = xe+ye basically */  	assert(xm & DP_HIDDEN_BIT);  	assert(ym & DP_HIDDEN_BIT); -	{ -		int re = xe + ye; -		int rs = xs ^ ys; -		u64 rm; -		/* shunt to top of word */ -		xm <<= 64 - (DP_MBITS + 1); -		ym <<= 64 - (DP_MBITS + 1); +	re = xe + ye; +	rs = xs ^ ys; + +	/* shunt to top of word */ +	xm <<= 64 - (DP_FBITS + 1); +	ym <<= 64 - (DP_FBITS + 1); -		/* multiply 32bits xm,ym to give high 32bits rm with stickness -		 */ +	/* +	 * Multiply 32 bits xm, ym to give high 32 bits rm with stickness. +	 */ -		/* 32 * 32 => 64 */ +	/* 32 * 32 => 64 */  #define DPXMULT(x, y)	((u64)(x) * (u64)y) -		{ -			unsigned lxm = xm; -			unsigned hxm = xm >> 32; -			unsigned lym = ym; -			unsigned hym = ym >> 32; -			u64 lrm; -			u64 hrm; - -			lrm = DPXMULT(lxm, lym); -			hrm = DPXMULT(hxm, hym); - -			{ -				u64 t = DPXMULT(lxm, hym); -				{ -					u64 at = -					    lrm + (t << 32); -					hrm += at < lrm; -					lrm = at; -				} -				hrm = hrm + (t >> 32); -			} - -			{ -				u64 t = DPXMULT(hxm, lym); -				{ -					u64 at = -					    lrm + (t << 32); -					hrm += at < lrm; -					lrm = at; -				} -				hrm = hrm + (t >> 32); -			} -			rm = hrm | (lrm != 0); -		} - -		/* -		 * sticky shift down to normal rounding precision -		 */ -		if ((s64) rm < 0) { -			rm = -			    (rm >> (64 - (DP_MBITS + 1 + 3))) | -			    ((rm << (DP_MBITS + 1 + 3)) != 0); +	lxm = xm; +	hxm = xm >> 32; +	lym = ym; +	hym = ym >> 32; + +	lrm = DPXMULT(lxm, lym); +	hrm = DPXMULT(hxm, hym); + +	t = DPXMULT(lxm, hym); + +	at = lrm + (t << 32); +	hrm += at < lrm; +	lrm = at; + +	hrm = hrm + (t >> 32); + +	t = DPXMULT(hxm, lym); + +	at = lrm + (t << 32); +	hrm += at < lrm; +	lrm = at; + +	hrm = hrm + (t >> 32); + +	rm = hrm | (lrm != 0); + +	/* +	 * Sticky shift down to normal rounding precision. +	 */ +	if ((s64) rm < 0) { +		rm = (rm >> (64 - (DP_FBITS + 1 + 3))) | +		     ((rm << (DP_FBITS + 1 + 3)) != 0);  			re++; -		} else { -			rm = -			    (rm >> (64 - (DP_MBITS + 1 + 3 + 1))) | -			    ((rm << (DP_MBITS + 1 + 3 + 1)) != 0); -		} -		assert(rm & (DP_HIDDEN_BIT << 3)); -		DPNORMRET2(rs, re, rm, "mul", x, y); +	} else { +		rm = (rm >> (64 - (DP_FBITS + 1 + 3 + 1))) | +		     ((rm << (DP_FBITS + 1 + 3 + 1)) != 0);  	} +	assert(rm & (DP_HIDDEN_BIT << 3)); + +	return ieee754dp_format(rs, re, rm);  } diff --git a/arch/mips/math-emu/dp_scalb.c b/arch/mips/math-emu/dp_scalb.c deleted file mode 100644 index 6f5df438dda..00000000000 --- a/arch/mips/math-emu/dp_scalb.c +++ /dev/null @@ -1,57 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. - * - * ######################################################################## - * - *  This program is free software; you can distribute it and/or modify it - *  under the terms of the GNU General Public License (Version 2) as - *  published by the Free Software Foundation. - * - *  This program is distributed in the hope it will be useful, but WITHOUT - *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License - *  for more details. - * - *  You should have received a copy of the GNU General Public License along - *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -ieee754dp ieee754dp_scalb(ieee754dp x, int n) -{ -	COMPXDP; - -	CLEARCX; - -	EXPLODEXDP; - -	switch (xc) { -	case IEEE754_CLASS_SNAN: -		return ieee754dp_nanxcpt(x, "scalb", x, n); -	case IEEE754_CLASS_QNAN: -	case IEEE754_CLASS_INF: -	case IEEE754_CLASS_ZERO: -		return x; -	case IEEE754_CLASS_DNORM: -		DPDNORMX; -		break; -	case IEEE754_CLASS_NORM: -		break; -	} -	DPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n); -} - - -ieee754dp ieee754dp_ldexp(ieee754dp x, int n) -{ -	return ieee754dp_scalb(x, n); -} diff --git a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c index 79ce2673a71..bccbe90efce 100644 --- a/arch/mips/math-emu/dp_simple.c +++ b/arch/mips/math-emu/dp_simple.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,33 +16,17 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754dp.h" -int ieee754dp_finite(ieee754dp x) -{ -	return DPBEXP(x) != DP_EMAX + 1 + DP_EBIAS; -} - -ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y) -{ -	CLEARCX; -	DPSIGN(x) = DPSIGN(y); -	return x; -} - - -ieee754dp ieee754dp_neg(ieee754dp x) +union ieee754dp ieee754dp_neg(union ieee754dp x)  {  	COMPXDP;  	EXPLODEXDP; -	CLEARCX; +	ieee754_clearcx();  	FLUSHXDP;  	/* @@ -55,30 +37,29 @@ ieee754dp ieee754dp_neg(ieee754dp x)  	DPSIGN(x) ^= 1;  	if (xc == IEEE754_CLASS_SNAN) { -		ieee754dp y = ieee754dp_indef(); -		SETCX(IEEE754_INVALID_OPERATION); +		union ieee754dp y = ieee754dp_indef(); +		ieee754_setcx(IEEE754_INVALID_OPERATION);  		DPSIGN(y) = DPSIGN(x); -		return ieee754dp_nanxcpt(y, "neg"); +		return ieee754dp_nanxcpt(y);  	}  	return x;  } - -ieee754dp ieee754dp_abs(ieee754dp x) +union ieee754dp ieee754dp_abs(union ieee754dp x)  {  	COMPXDP;  	EXPLODEXDP; -	CLEARCX; +	ieee754_clearcx();  	FLUSHXDP;  	/* Clear sign ALWAYS, irrespective of NaN */  	DPSIGN(x) = 0;  	if (xc == IEEE754_CLASS_SNAN) { -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754dp_nanxcpt(ieee754dp_indef(), "abs"); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754dp_nanxcpt(ieee754dp_indef());  	}  	return x; diff --git a/arch/mips/math-emu/dp_sqrt.c b/arch/mips/math-emu/dp_sqrt.c index b874d60a942..041bbb6124b 100644 --- a/arch/mips/math-emu/dp_sqrt.c +++ b/arch/mips/math-emu/dp_sqrt.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,12 +16,9 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754dp.h"  static const unsigned table[] = { @@ -34,44 +29,49 @@ static const unsigned table[] = {  	1742, 661, 130  }; -ieee754dp ieee754dp_sqrt(ieee754dp x) +union ieee754dp ieee754dp_sqrt(union ieee754dp x)  {  	struct _ieee754_csr oldcsr; -	ieee754dp y, z, t; +	union ieee754dp y, z, t;  	unsigned scalx, yh;  	COMPXDP;  	EXPLODEXDP; -	CLEARCX; +	ieee754_clearcx();  	FLUSHXDP;  	/* x == INF or NAN? */  	switch (xc) {  	case IEEE754_CLASS_QNAN:  		/* sqrt(Nan) = Nan */ -		return ieee754dp_nanxcpt(x, "sqrt"); +		return ieee754dp_nanxcpt(x); +  	case IEEE754_CLASS_SNAN: -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt"); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754dp_nanxcpt(ieee754dp_indef()); +  	case IEEE754_CLASS_ZERO:  		/* sqrt(0) = 0 */  		return x; +  	case IEEE754_CLASS_INF:  		if (xs) {  			/* sqrt(-Inf) = Nan */ -			SETCX(IEEE754_INVALID_OPERATION); -			return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt"); +			ieee754_setcx(IEEE754_INVALID_OPERATION); +			return ieee754dp_nanxcpt(ieee754dp_indef());  		}  		/* sqrt(+Inf) = Inf */  		return x; +  	case IEEE754_CLASS_DNORM:  		DPDNORMX;  		/* fall through */ +  	case IEEE754_CLASS_NORM:  		if (xs) {  			/* sqrt(-x) = Nan */ -			SETCX(IEEE754_INVALID_OPERATION); -			return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt"); +			ieee754_setcx(IEEE754_INVALID_OPERATION); +			return ieee754dp_nanxcpt(ieee754dp_indef());  		}  		break;  	} @@ -80,7 +80,7 @@ ieee754dp ieee754dp_sqrt(ieee754dp x)  	oldcsr = ieee754_csr;  	ieee754_csr.mx &= ~IEEE754_INEXACT;  	ieee754_csr.sx &= ~IEEE754_INEXACT; -	ieee754_csr.rm = IEEE754_RN; +	ieee754_csr.rm = FPU_CSR_RN;  	/* adjust exponent to prevent overflow */  	scalx = 0; @@ -110,19 +110,19 @@ ieee754dp ieee754dp_sqrt(ieee754dp x)  	/* triple to almost 56 sig. bits: y ~= sqrt(x) to within 1 ulp */  	/* t=y*y; z=t;	pt[n0]+=0x00100000; t+=z; z=(x-z)*y; */  	z = t = ieee754dp_mul(y, y); -	t.parts.bexp += 0x001; +	t.bexp += 0x001;  	t = ieee754dp_add(t, z);  	z = ieee754dp_mul(ieee754dp_sub(x, z), y);  	/* t=z/(t+x) ;	pt[n0]+=0x00100000; y+=t; */  	t = ieee754dp_div(z, ieee754dp_add(t, x)); -	t.parts.bexp += 0x001; +	t.bexp += 0x001;  	y = ieee754dp_add(y, t);  	/* twiddle last bit to force y correctly rounded */  	/* set RZ, clear INEX flag */ -	ieee754_csr.rm = IEEE754_RZ; +	ieee754_csr.rm = FPU_CSR_RZ;  	ieee754_csr.sx &= ~IEEE754_INEXACT;  	/* t=x/y; ...chopped quotient, possibly inexact */ @@ -139,10 +139,10 @@ ieee754dp ieee754dp_sqrt(ieee754dp x)  		oldcsr.sx |= IEEE754_INEXACT;  		switch (oldcsr.rm) { -		case IEEE754_RP: +		case FPU_CSR_RU:  			y.bits += 1;  			/* drop through */ -		case IEEE754_RN: +		case FPU_CSR_RN:  			t.bits += 1;  			break;  		} @@ -155,7 +155,7 @@ ieee754dp ieee754dp_sqrt(ieee754dp x)  	}  	/* py[n0]=py[n0]+scalx; ...scale back y */ -	y.parts.bexp += scalx; +	y.bexp += scalx;  	/* restore rounding mode, possibly set inexact */  	ieee754_csr = oldcsr; diff --git a/arch/mips/math-emu/dp_sub.c b/arch/mips/math-emu/dp_sub.c index 91e0a4b5cbc..7a174029043 100644 --- a/arch/mips/math-emu/dp_sub.c +++ b/arch/mips/math-emu/dp_sub.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,23 +16,22 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754dp.h" -ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y) +union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y)  { +	int s; +  	COMPXDP;  	COMPYDP;  	EXPLODEXDP;  	EXPLODEYDP; -	CLEARCX; +	ieee754_clearcx();  	FLUSHXDP;  	FLUSHYDP; @@ -51,8 +48,8 @@ ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754dp_nanxcpt(ieee754dp_indef(), "sub", x, y); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754dp_nanxcpt(ieee754dp_indef());  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -68,14 +65,14 @@ ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)  		return x; -		/* Infinity handling -		 */ - +	/* +	 * Infinity handling +	 */  	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):  		if (xs != ys)  			return x; -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754dp_xcpt(ieee754dp_indef(), "sub", x, y); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754dp_indef();  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):  	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): @@ -87,15 +84,14 @@ ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)  	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):  		return x; -		/* Zero handling -		 */ - +	/* +	 * Zero handling +	 */  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):  		if (xs != ys)  			return x;  		else -			return ieee754dp_zero(ieee754_csr.rm == -					      IEEE754_RD); +			return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD);  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):  	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): @@ -136,15 +132,17 @@ ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)  	ym <<= 3;  	if (xe > ye) { -		/* have to shift y fraction right to align +		/* +		 * Have to shift y fraction right to align  		 */ -		int s = xe - ye; +		s = xe - ye;  		ym = XDPSRS(ym, s);  		ye += s;  	} else if (ye > xe) { -		/* have to shift x fraction right to align +		/* +		 * Have to shift x fraction right to align  		 */ -		int s = ye - xe; +		s = ye - xe;  		xm = XDPSRS(xm, s);  		xe += s;  	} @@ -158,7 +156,7 @@ ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)  		xe = xe;  		xs = xs; -		if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */ +		if (xm >> (DP_FBITS + 1 + 3)) { /* carry out */  			xm = XDPSRS1(xm);	/* shift preserving sticky */  			xe++;  		} @@ -173,7 +171,7 @@ ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)  			xs = ys;  		}  		if (xm == 0) { -			if (ieee754_csr.rm == IEEE754_RD) +			if (ieee754_csr.rm == FPU_CSR_RD)  				return ieee754dp_zero(1);	/* round negative inf. => sign = -1 */  			else  				return ieee754dp_zero(0);	/* other round modes   => sign = 1 */ @@ -181,10 +179,11 @@ ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)  		/* normalize to rounding precision  		 */ -		while ((xm >> (DP_MBITS + 3)) == 0) { +		while ((xm >> (DP_FBITS + 3)) == 0) {  			xm <<= 1;  			xe--;  		}  	} -	DPNORMRET2(xs, xe, xm, "sub", x, y); + +	return ieee754dp_format(xs, xe, xm);  } diff --git a/arch/mips/math-emu/dp_tint.c b/arch/mips/math-emu/dp_tint.c index 0ebe8598b94..6ffc336c530 100644 --- a/arch/mips/math-emu/dp_tint.c +++ b/arch/mips/math-emu/dp_tint.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,20 +16,21 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ - -#include <linux/kernel.h>  #include "ieee754dp.h" -int ieee754dp_tint(ieee754dp x) +int ieee754dp_tint(union ieee754dp x)  { +	u64 residue; +	int round; +	int sticky; +	int odd; +  	COMPXDP; -	CLEARCX; +	ieee754_clearcx();  	EXPLODEXDP;  	FLUSHXDP; @@ -40,10 +39,12 @@ int ieee754dp_tint(ieee754dp x)  	case IEEE754_CLASS_SNAN:  	case IEEE754_CLASS_QNAN:  	case IEEE754_CLASS_INF: -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754si_indef(); +  	case IEEE754_CLASS_ZERO:  		return 0; +  	case IEEE754_CLASS_DNORM:  	case IEEE754_CLASS_NORM:  		break; @@ -51,44 +52,39 @@ int ieee754dp_tint(ieee754dp x)  	if (xe > 31) {  		/* Set invalid. We will only use overflow for floating  		   point overflow */ -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754si_indef();  	}  	/* oh gawd */ -	if (xe > DP_MBITS) { -		xm <<= xe - DP_MBITS; -	} else if (xe < DP_MBITS) { -		u64 residue; -		int round; -		int sticky; -		int odd; - +	if (xe > DP_FBITS) { +		xm <<= xe - DP_FBITS; +	} else if (xe < DP_FBITS) {  		if (xe < -1) {  			residue = xm;  			round = 0;  			sticky = residue != 0;  			xm = 0;  		} else { -			residue = xm << (64 - DP_MBITS + xe); +			residue = xm << (64 - DP_FBITS + xe);  			round = (residue >> 63) != 0;  			sticky = (residue << 1) != 0; -			xm >>= DP_MBITS - xe; +			xm >>= DP_FBITS - xe;  		}  		/* Note: At this point upper 32 bits of xm are guaranteed  		   to be zero */  		odd = (xm & 0x1) != 0x0;  		switch (ieee754_csr.rm) { -		case IEEE754_RN: +		case FPU_CSR_RN:  			if (round && (sticky || odd))  				xm++;  			break; -		case IEEE754_RZ: +		case FPU_CSR_RZ:  			break; -		case IEEE754_RU:	/* toward +Infinity */ +		case FPU_CSR_RU:	/* toward +Infinity */  			if ((round || sticky) && !xs)  				xm++;  			break; -		case IEEE754_RD:	/* toward -Infinity */ +		case FPU_CSR_RD:	/* toward -Infinity */  			if ((round || sticky) && xs)  				xm++;  			break; @@ -96,27 +92,14 @@ int ieee754dp_tint(ieee754dp x)  		/* look for valid corner case 0x80000000 */  		if ((xm >> 31) != 0 && (xs == 0 || xm != 0x80000000)) {  			/* This can happen after rounding */ -			SETCX(IEEE754_INVALID_OPERATION); -			return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x); +			ieee754_setcx(IEEE754_INVALID_OPERATION); +			return ieee754si_indef();  		}  		if (round || sticky) -			SETCX(IEEE754_INEXACT); +			ieee754_setcx(IEEE754_INEXACT);  	}  	if (xs)  		return -xm;  	else  		return xm;  } - - -unsigned int ieee754dp_tuns(ieee754dp x) -{ -	ieee754dp hb = ieee754dp_1e31(); - -	/* what if x < 0 ?? */ -	if (ieee754dp_lt(x, hb)) -		return (unsigned) ieee754dp_tint(x); - -	return (unsigned) ieee754dp_tint(ieee754dp_sub(x, hb)) | -	    ((unsigned) 1 << 31); -} diff --git a/arch/mips/math-emu/dp_tlong.c b/arch/mips/math-emu/dp_tlong.c index 133ce2ba001..9cdc145b75e 100644 --- a/arch/mips/math-emu/dp_tlong.c +++ b/arch/mips/math-emu/dp_tlong.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,19 +16,21 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754dp.h" -s64 ieee754dp_tlong(ieee754dp x) +s64 ieee754dp_tlong(union ieee754dp x)  { +	u64 residue; +	int round; +	int sticky; +	int odd; +  	COMPXDP; -	CLEARCX; +	ieee754_clearcx();  	EXPLODEXDP;  	FLUSHXDP; @@ -39,10 +39,12 @@ s64 ieee754dp_tlong(ieee754dp x)  	case IEEE754_CLASS_SNAN:  	case IEEE754_CLASS_QNAN:  	case IEEE754_CLASS_INF: -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754di_indef(); +  	case IEEE754_CLASS_ZERO:  		return 0; +  	case IEEE754_CLASS_DNORM:  	case IEEE754_CLASS_NORM:  		break; @@ -53,18 +55,13 @@ s64 ieee754dp_tlong(ieee754dp x)  			return -0x8000000000000000LL;  		/* Set invalid. We will only use overflow for floating  		   point overflow */ -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754di_indef();  	}  	/* oh gawd */ -	if (xe > DP_MBITS) { -		xm <<= xe - DP_MBITS; -	} else if (xe < DP_MBITS) { -		u64 residue; -		int round; -		int sticky; -		int odd; - +	if (xe > DP_FBITS) { +		xm <<= xe - DP_FBITS; +	} else if (xe < DP_FBITS) {  		if (xe < -1) {  			residue = xm;  			round = 0; @@ -75,51 +72,38 @@ s64 ieee754dp_tlong(ieee754dp x)  			* so we do it in two steps. Be aware that xe  			* may be -1 */  			residue = xm << (xe + 1); -			residue <<= 63 - DP_MBITS; +			residue <<= 63 - DP_FBITS;  			round = (residue >> 63) != 0;  			sticky = (residue << 1) != 0; -			xm >>= DP_MBITS - xe; +			xm >>= DP_FBITS - xe;  		}  		odd = (xm & 0x1) != 0x0;  		switch (ieee754_csr.rm) { -		case IEEE754_RN: +		case FPU_CSR_RN:  			if (round && (sticky || odd))  				xm++;  			break; -		case IEEE754_RZ: +		case FPU_CSR_RZ:  			break; -		case IEEE754_RU:	/* toward +Infinity */ +		case FPU_CSR_RU:	/* toward +Infinity */  			if ((round || sticky) && !xs)  				xm++;  			break; -		case IEEE754_RD:	/* toward -Infinity */ +		case FPU_CSR_RD:	/* toward -Infinity */  			if ((round || sticky) && xs)  				xm++;  			break;  		}  		if ((xm >> 63) != 0) {  			/* This can happen after rounding */ -			SETCX(IEEE754_INVALID_OPERATION); -			return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); +			ieee754_setcx(IEEE754_INVALID_OPERATION); +			return ieee754di_indef();  		}  		if (round || sticky) -			SETCX(IEEE754_INEXACT); +			ieee754_setcx(IEEE754_INEXACT);  	}  	if (xs)  		return -xm;  	else  		return xm;  } - - -u64 ieee754dp_tulong(ieee754dp x) -{ -	ieee754dp hb = ieee754dp_1e63(); - -	/* what if x < 0 ?? */ -	if (ieee754dp_lt(x, hb)) -		return (u64) ieee754dp_tlong(x); - -	return (u64) ieee754dp_tlong(ieee754dp_sub(x, hb)) | -	    (1ULL << 63); -} diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c index 7ea622ab8da..4f514f3724c 100644 --- a/arch/mips/math-emu/dsemul.c +++ b/arch/mips/math-emu/dsemul.c @@ -1,30 +1,12 @@ -#include <linux/compiler.h> -#include <linux/mm.h> -#include <linux/signal.h> -#include <linux/smp.h> - -#include <asm/asm.h> -#include <asm/bootinfo.h> -#include <asm/byteorder.h> -#include <asm/cpu.h> -#include <asm/inst.h> -#include <asm/processor.h> -#include <asm/uaccess.h>  #include <asm/branch.h> -#include <asm/mipsregs.h>  #include <asm/cacheflush.h> -  #include <asm/fpu_emulator.h> +#include <asm/inst.h> +#include <asm/mipsregs.h> +#include <asm/uaccess.h>  #include "ieee754.h" -/* Strap kernel emulator for full MIPS IV emulation */ - -#ifdef __mips -#undef __mips -#endif -#define __mips 4 -  /*   * Emulate the arbritrary instruction ir at xcp->cp0_epc.  Required when   * we have to emulate the instruction in a COP1 branch delay slot.  Do @@ -59,13 +41,11 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)  		(ir == 0)) {  		/* NOP is easy */  		regs->cp0_epc = cpc; -		regs->cp0_cause &= ~CAUSEF_BD; +		clear_delay_slot(regs);  		return 0;  	} -#ifdef DSEMUL_TRACE -	printk("dsemul %lx %lx\n", regs->cp0_epc, cpc); -#endif +	pr_debug("dsemul %lx %lx\n", regs->cp0_epc, cpc);  	/*  	 * The strategy is to push the instruction onto the user stack @@ -167,9 +147,8 @@ int do_dsemulret(struct pt_regs *xcp)  	 * emulating the branch delay instruction.  	 */ -#ifdef DSEMUL_TRACE -	printk("dsemulret\n"); -#endif +	pr_debug("dsemulret\n"); +  	if (__get_user(epc, &fr->epc)) {		/* Saved EPC */  		/* This is not a good situation to be in */  		force_sig(SIGBUS, current); diff --git a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c index 0015cf1989d..8e97acbbe22 100644 --- a/arch/mips/math-emu/ieee754.c +++ b/arch/mips/math-emu/ieee754.c @@ -10,8 +10,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -23,105 +21,74 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ +#include <linux/compiler.h> -#include "ieee754int.h" +#include "ieee754.h"  #include "ieee754sp.h"  #include "ieee754dp.h" -#define DP_EBIAS	1023 -#define DP_EMIN		(-1022) -#define DP_EMAX		1023 - -#define SP_EBIAS	127 -#define SP_EMIN		(-126) -#define SP_EMAX		127 - -/* special constants -*/ - - -#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__) -#define SPSTR(s, b, m) {m, b, s} -#define DPSTR(s, b, mh, ml) {ml, mh, b, s} -#endif +/* + * Special constants + */ -#ifdef __MIPSEB__ -#define SPSTR(s, b, m) {s, b, m} -#define DPSTR(s, b, mh, ml) {s, b, mh, ml} -#endif +/* + * Older GCC requires the inner braces for initialization of union ieee754dp's + * anonymous struct member.  Without an error will result. + */ +#define xPCNST(s, b, m, ebias)						\ +{									\ +	{								\ +		.sign	= (s),						\ +		.bexp	= (b) + ebias,					\ +		.mant	= (m)						\ +	}								\ +} -const struct ieee754dp_konst __ieee754dp_spcvals[] = { -	DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* + zero   */ -	DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* - zero   */ -	DPSTR(0, DP_EBIAS, 0, 0),	/* + 1.0   */ -	DPSTR(1, DP_EBIAS, 0, 0),	/* - 1.0   */ -	DPSTR(0, 3 + DP_EBIAS, 0x40000, 0),	/* + 10.0   */ -	DPSTR(1, 3 + DP_EBIAS, 0x40000, 0),	/* - 10.0   */ -	DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* + infinity */ -	DPSTR(1, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* - infinity */ -	DPSTR(0, DP_EMAX+1+DP_EBIAS, 0x7FFFF, 0xFFFFFFFF), /* + indef quiet Nan */ -	DPSTR(0, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF),	/* + max */ -	DPSTR(1, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF),	/* - max */ -	DPSTR(0, DP_EMIN + DP_EBIAS, 0, 0),	/* + min normal */ -	DPSTR(1, DP_EMIN + DP_EBIAS, 0, 0),	/* - min normal */ -	DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* + min denormal */ -	DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* - min denormal */ -	DPSTR(0, 31 + DP_EBIAS, 0, 0),	/* + 1.0e31 */ -	DPSTR(0, 63 + DP_EBIAS, 0, 0),	/* + 1.0e63 */ -}; +#define DPCNST(s, b, m)							\ +	xPCNST(s, b, m, DP_EBIAS) -const struct ieee754sp_konst __ieee754sp_spcvals[] = { -	SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 0),	/* + zero   */ -	SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 0),	/* - zero   */ -	SPSTR(0, SP_EBIAS, 0),	/* + 1.0   */ -	SPSTR(1, SP_EBIAS, 0),	/* - 1.0   */ -	SPSTR(0, 3 + SP_EBIAS, 0x200000),	/* + 10.0   */ -	SPSTR(1, 3 + SP_EBIAS, 0x200000),	/* - 10.0   */ -	SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0),	/* + infinity */ -	SPSTR(1, SP_EMAX + 1 + SP_EBIAS, 0),	/* - infinity */ -	SPSTR(0, SP_EMAX+1+SP_EBIAS, 0x3FFFFF),	    /* + indef quiet Nan  */ -	SPSTR(0, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* + max normal */ -	SPSTR(1, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* - max normal */ -	SPSTR(0, SP_EMIN + SP_EBIAS, 0),	/* + min normal */ -	SPSTR(1, SP_EMIN + SP_EBIAS, 0),	/* - min normal */ -	SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 1),	/* + min denormal */ -	SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 1),	/* - min denormal */ -	SPSTR(0, 31 + SP_EBIAS, 0),	/* + 1.0e31 */ -	SPSTR(0, 63 + SP_EBIAS, 0),	/* + 1.0e63 */ +const union ieee754dp __ieee754dp_spcvals[] = { +	DPCNST(0, DP_EMIN - 1, 0x0000000000000ULL),	/* + zero   */ +	DPCNST(1, DP_EMIN - 1, 0x0000000000000ULL),	/* - zero   */ +	DPCNST(0, 0,	       0x0000000000000ULL),	/* + 1.0   */ +	DPCNST(1, 0,	       0x0000000000000ULL),	/* - 1.0   */ +	DPCNST(0, 3,           0x4000000000000ULL),	/* + 10.0   */ +	DPCNST(1, 3,           0x4000000000000ULL),	/* - 10.0   */ +	DPCNST(0, DP_EMAX + 1, 0x0000000000000ULL),	/* + infinity */ +	DPCNST(1, DP_EMAX + 1, 0x0000000000000ULL),	/* - infinity */ +	DPCNST(0, DP_EMAX + 1, 0x7FFFFFFFFFFFFULL),	/* + indef quiet Nan */ +	DPCNST(0, DP_EMAX,     0xFFFFFFFFFFFFFULL),	/* + max */ +	DPCNST(1, DP_EMAX,     0xFFFFFFFFFFFFFULL),	/* - max */ +	DPCNST(0, DP_EMIN,     0x0000000000000ULL),	/* + min normal */ +	DPCNST(1, DP_EMIN,     0x0000000000000ULL),	/* - min normal */ +	DPCNST(0, DP_EMIN - 1, 0x0000000000001ULL),	/* + min denormal */ +	DPCNST(1, DP_EMIN - 1, 0x0000000000001ULL),	/* - min denormal */ +	DPCNST(0, 31,          0x0000000000000ULL),	/* + 1.0e31 */ +	DPCNST(0, 63,          0x0000000000000ULL),	/* + 1.0e63 */  }; +#define SPCNST(s, b, m)							\ +	xPCNST(s, b, m, SP_EBIAS) -int ieee754si_xcpt(int r, const char *op, ...) -{ -	struct ieee754xctx ax; - -	if (!TSTX()) -		return r; -	ax.op = op; -	ax.rt = IEEE754_RT_SI; -	ax.rv.si = r; -	va_start(ax.ap, op); -	ieee754_xcpt(&ax); -	va_end(ax.ap); -	return ax.rv.si; -} - -s64 ieee754di_xcpt(s64 r, const char *op, ...) -{ -	struct ieee754xctx ax; - -	if (!TSTX()) -		return r; -	ax.op = op; -	ax.rt = IEEE754_RT_DI; -	ax.rv.di = r; -	va_start(ax.ap, op); -	ieee754_xcpt(&ax); -	va_end(ax.ap); -	return ax.rv.di; -} +const union ieee754sp __ieee754sp_spcvals[] = { +	SPCNST(0, SP_EMIN - 1, 0x000000),	/* + zero   */ +	SPCNST(1, SP_EMIN - 1, 0x000000),	/* - zero   */ +	SPCNST(0, 0,	       0x000000),	/* + 1.0   */ +	SPCNST(1, 0,	       0x000000),	/* - 1.0   */ +	SPCNST(0, 3,	       0x200000),	/* + 10.0   */ +	SPCNST(1, 3,	       0x200000),	/* - 10.0   */ +	SPCNST(0, SP_EMAX + 1, 0x000000),	/* + infinity */ +	SPCNST(1, SP_EMAX + 1, 0x000000),	/* - infinity */ +	SPCNST(0, SP_EMAX + 1, 0x3FFFFF),	/* + indef quiet Nan  */ +	SPCNST(0, SP_EMAX,     0x7FFFFF),	/* + max normal */ +	SPCNST(1, SP_EMAX,     0x7FFFFF),	/* - max normal */ +	SPCNST(0, SP_EMIN,     0x000000),	/* + min normal */ +	SPCNST(1, SP_EMIN,     0x000000),	/* - min normal */ +	SPCNST(0, SP_EMIN - 1, 0x000001),	/* + min denormal */ +	SPCNST(1, SP_EMIN - 1, 0x000001),	/* - min denormal */ +	SPCNST(0, 31,	       0x000000),	/* + 1.0e31 */ +	SPCNST(0, 63,	       0x000000),	/* + 1.0e63 */ +}; diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h index 22796e01206..43c4fb522ac 100644 --- a/arch/mips/math-emu/ieee754.h +++ b/arch/mips/math-emu/ieee754.h @@ -13,7 +13,7 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   *   *  Nov 7, 2000   *  Modification to allow integration with Linux kernel @@ -24,186 +24,93 @@  #ifndef __ARCH_MIPS_MATH_EMU_IEEE754_H  #define __ARCH_MIPS_MATH_EMU_IEEE754_H +#include <linux/compiler.h>  #include <asm/byteorder.h> +#include <linux/kernel.h>  #include <linux/types.h>  #include <linux/sched.h> +#include <asm/bitfield.h> -/* - * Not very pretty, but the Linux kernel's normal va_list definition - * does not allow it to be used as a structure element, as it is here. - */ -#ifndef _STDARG_H -#include <stdarg.h> -#endif - -#ifdef __LITTLE_ENDIAN -struct ieee754dp_konst { -	unsigned mantlo:32; -	unsigned manthi:20; -	unsigned bexp:11; -	unsigned sign:1; -}; -struct ieee754sp_konst { -	unsigned mant:23; -	unsigned bexp:8; -	unsigned sign:1; -}; - -typedef union _ieee754dp { -	struct ieee754dp_konst oparts; +union ieee754dp {  	struct { -		u64 mant:52; -		unsigned int bexp:11; -		unsigned int sign:1; -	} parts; +		__BITFIELD_FIELD(unsigned int sign:1, +		__BITFIELD_FIELD(unsigned int bexp:11, +		__BITFIELD_FIELD(u64 mant:52, +		;))) +	};  	u64 bits; -	double d; -} ieee754dp; - -typedef union _ieee754sp { -	struct ieee754sp_konst parts; -	float f; -	u32 bits; -} ieee754sp; -#endif - -#ifdef __BIG_ENDIAN -struct ieee754dp_konst { -	unsigned sign:1; -	unsigned bexp:11; -	unsigned manthi:20; -	unsigned mantlo:32;  }; -typedef union _ieee754dp { -	struct ieee754dp_konst oparts; +union ieee754sp {  	struct { -		unsigned int sign:1; -		unsigned int bexp:11; -		u64 mant:52; -	} parts; -	double d; -	u64 bits; -} ieee754dp; - -struct ieee754sp_konst { -	unsigned sign:1; -	unsigned bexp:8; -	unsigned mant:23; -}; - -typedef union _ieee754sp { -	struct ieee754sp_konst parts; -	float f; +		__BITFIELD_FIELD(unsigned sign:1, +		__BITFIELD_FIELD(unsigned bexp:8, +		__BITFIELD_FIELD(unsigned mant:23, +		;))) +	};  	u32 bits; -} ieee754sp; -#endif +};  /*   * single precision (often aka float)  */ -int ieee754sp_finite(ieee754sp x); -int ieee754sp_class(ieee754sp x); - -ieee754sp ieee754sp_abs(ieee754sp x); -ieee754sp ieee754sp_neg(ieee754sp x); -ieee754sp ieee754sp_scalb(ieee754sp x, int); -ieee754sp ieee754sp_logb(ieee754sp x); - -/* x with sign of y */ -ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y); - -ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y); -ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y); -ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y); -ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y); - -ieee754sp ieee754sp_fint(int x); -ieee754sp ieee754sp_funs(unsigned x); -ieee754sp ieee754sp_flong(s64 x); -ieee754sp ieee754sp_fulong(u64 x); -ieee754sp ieee754sp_fdp(ieee754dp x); - -int ieee754sp_tint(ieee754sp x); -unsigned int ieee754sp_tuns(ieee754sp x); -s64 ieee754sp_tlong(ieee754sp x); -u64 ieee754sp_tulong(ieee754sp x); - -int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cop, int sig); -/* - * basic sp math - */ -ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip); -ieee754sp ieee754sp_frexp(ieee754sp x, int *exp); -ieee754sp ieee754sp_ldexp(ieee754sp x, int exp); +int ieee754sp_class(union ieee754sp x); -ieee754sp ieee754sp_ceil(ieee754sp x); -ieee754sp ieee754sp_floor(ieee754sp x); -ieee754sp ieee754sp_trunc(ieee754sp x); +union ieee754sp ieee754sp_abs(union ieee754sp x); +union ieee754sp ieee754sp_neg(union ieee754sp x); -ieee754sp ieee754sp_sqrt(ieee754sp x); +union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y); +union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y); +union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y); +union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y); -/* - * double precision (often aka double) -*/ -int ieee754dp_finite(ieee754dp x); -int ieee754dp_class(ieee754dp x); +union ieee754sp ieee754sp_fint(int x); +union ieee754sp ieee754sp_flong(s64 x); +union ieee754sp ieee754sp_fdp(union ieee754dp x); -/* x with sign of y */ -ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y); +int ieee754sp_tint(union ieee754sp x); +s64 ieee754sp_tlong(union ieee754sp x); -ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y); -ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y); -ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y); -ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y); +int ieee754sp_cmp(union ieee754sp x, union ieee754sp y, int cop, int sig); -ieee754dp ieee754dp_abs(ieee754dp x); -ieee754dp ieee754dp_neg(ieee754dp x); -ieee754dp ieee754dp_scalb(ieee754dp x, int); +union ieee754sp ieee754sp_sqrt(union ieee754sp x); -/* return exponent as integer in floating point format - */ -ieee754dp ieee754dp_logb(ieee754dp x); +/* + * double precision (often aka double) +*/ +int ieee754dp_class(union ieee754dp x); -ieee754dp ieee754dp_fint(int x); -ieee754dp ieee754dp_funs(unsigned x); -ieee754dp ieee754dp_flong(s64 x); -ieee754dp ieee754dp_fulong(u64 x); -ieee754dp ieee754dp_fsp(ieee754sp x); +union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y); +union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y); +union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y); +union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y); -ieee754dp ieee754dp_ceil(ieee754dp x); -ieee754dp ieee754dp_floor(ieee754dp x); -ieee754dp ieee754dp_trunc(ieee754dp x); +union ieee754dp ieee754dp_abs(union ieee754dp x); +union ieee754dp ieee754dp_neg(union ieee754dp x); -int ieee754dp_tint(ieee754dp x); -unsigned int ieee754dp_tuns(ieee754dp x); -s64 ieee754dp_tlong(ieee754dp x); -u64 ieee754dp_tulong(ieee754dp x); +union ieee754dp ieee754dp_fint(int x); +union ieee754dp ieee754dp_flong(s64 x); +union ieee754dp ieee754dp_fsp(union ieee754sp x); -int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cop, int sig); -/* - * basic sp math - */ -ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip); -ieee754dp ieee754dp_frexp(ieee754dp x, int *exp); -ieee754dp ieee754dp_ldexp(ieee754dp x, int exp); +int ieee754dp_tint(union ieee754dp x); +s64 ieee754dp_tlong(union ieee754dp x); -ieee754dp ieee754dp_ceil(ieee754dp x); -ieee754dp ieee754dp_floor(ieee754dp x); -ieee754dp ieee754dp_trunc(ieee754dp x); +int ieee754dp_cmp(union ieee754dp x, union ieee754dp y, int cop, int sig); -ieee754dp ieee754dp_sqrt(ieee754dp x); +union ieee754dp ieee754dp_sqrt(union ieee754dp x);  /* 5 types of floating point number  */ -#define IEEE754_CLASS_NORM	0x00 -#define IEEE754_CLASS_ZERO	0x01 -#define IEEE754_CLASS_DNORM	0x02 -#define IEEE754_CLASS_INF	0x03 -#define IEEE754_CLASS_SNAN	0x04 -#define IEEE754_CLASS_QNAN	0x05 +enum { +	IEEE754_CLASS_NORM	= 0x00, +	IEEE754_CLASS_ZERO	= 0x01, +	IEEE754_CLASS_DNORM	= 0x02, +	IEEE754_CLASS_INF	= 0x03, +	IEEE754_CLASS_SNAN	= 0x04, +	IEEE754_CLASS_QNAN	= 0x05, +};  /* exception numbers */  #define IEEE754_INEXACT			0x01 @@ -219,114 +126,84 @@ ieee754dp ieee754dp_sqrt(ieee754dp x);  #define IEEE754_CGT	0x04  #define IEEE754_CUN	0x08 -/* rounding mode -*/ -#define IEEE754_RN	0	/* round to nearest */ -#define IEEE754_RZ	1	/* round toward zero  */ -#define IEEE754_RD	2	/* round toward -Infinity */ -#define IEEE754_RU	3	/* round toward +Infinity */ - -/* other naming */ -#define IEEE754_RM	IEEE754_RD -#define IEEE754_RP	IEEE754_RU -  /* "normal" comparisons  */ -static inline int ieee754sp_eq(ieee754sp x, ieee754sp y) +static inline int ieee754sp_eq(union ieee754sp x, union ieee754sp y)  {  	return ieee754sp_cmp(x, y, IEEE754_CEQ, 0);  } -static inline int ieee754sp_ne(ieee754sp x, ieee754sp y) +static inline int ieee754sp_ne(union ieee754sp x, union ieee754sp y)  {  	return ieee754sp_cmp(x, y,  			     IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0);  } -static inline int ieee754sp_lt(ieee754sp x, ieee754sp y) +static inline int ieee754sp_lt(union ieee754sp x, union ieee754sp y)  {  	return ieee754sp_cmp(x, y, IEEE754_CLT, 0);  } -static inline int ieee754sp_le(ieee754sp x, ieee754sp y) +static inline int ieee754sp_le(union ieee754sp x, union ieee754sp y)  {  	return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0);  } -static inline int ieee754sp_gt(ieee754sp x, ieee754sp y) +static inline int ieee754sp_gt(union ieee754sp x, union ieee754sp y)  {  	return ieee754sp_cmp(x, y, IEEE754_CGT, 0);  } -static inline int ieee754sp_ge(ieee754sp x, ieee754sp y) +static inline int ieee754sp_ge(union ieee754sp x, union ieee754sp y)  {  	return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0);  } -static inline int ieee754dp_eq(ieee754dp x, ieee754dp y) +static inline int ieee754dp_eq(union ieee754dp x, union ieee754dp y)  {  	return ieee754dp_cmp(x, y, IEEE754_CEQ, 0);  } -static inline int ieee754dp_ne(ieee754dp x, ieee754dp y) +static inline int ieee754dp_ne(union ieee754dp x, union ieee754dp y)  {  	return ieee754dp_cmp(x, y,  			     IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0);  } -static inline int ieee754dp_lt(ieee754dp x, ieee754dp y) +static inline int ieee754dp_lt(union ieee754dp x, union ieee754dp y)  {  	return ieee754dp_cmp(x, y, IEEE754_CLT, 0);  } -static inline int ieee754dp_le(ieee754dp x, ieee754dp y) +static inline int ieee754dp_le(union ieee754dp x, union ieee754dp y)  {  	return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0);  } -static inline int ieee754dp_gt(ieee754dp x, ieee754dp y) +static inline int ieee754dp_gt(union ieee754dp x, union ieee754dp y)  {  	return ieee754dp_cmp(x, y, IEEE754_CGT, 0);  } -static inline int ieee754dp_ge(ieee754dp x, ieee754dp y) +static inline int ieee754dp_ge(union ieee754dp x, union ieee754dp y)  {  	return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0);  } - -/* - * Like strtod - */ -ieee754dp ieee754dp_fstr(const char *s, char **endp); -char *ieee754dp_tstr(ieee754dp x, int prec, int fmt, int af); - -  /*   * The control status register   */  struct _ieee754_csr { -#ifdef __BIG_ENDIAN -	unsigned pad0:7; -	unsigned nod:1;		/* set 1 for no denormalised numbers */ -	unsigned c:1;		/* condition */ -	unsigned pad1:5; -	unsigned cx:6;		/* exceptions this operation */ -	unsigned mx:5;		/* exception enable  mask */ -	unsigned sx:5;		/* exceptions total */ -	unsigned rm:2;		/* current rounding mode */ -#endif -#ifdef __LITTLE_ENDIAN -	unsigned rm:2;		/* current rounding mode */ -	unsigned sx:5;		/* exceptions total */ -	unsigned mx:5;		/* exception enable  mask */ -	unsigned cx:6;		/* exceptions this operation */ -	unsigned pad1:5; -	unsigned c:1;		/* condition */ -	unsigned nod:1;		/* set 1 for no denormalised numbers */ -	unsigned pad0:7; -#endif +	__BITFIELD_FIELD(unsigned pad0:7, +	__BITFIELD_FIELD(unsigned nod:1,	/* set 1 for no denormalised numbers */ +	__BITFIELD_FIELD(unsigned c:1,		/* condition */ +	__BITFIELD_FIELD(unsigned pad1:5, +	__BITFIELD_FIELD(unsigned cx:6,		/* exceptions this operation */ +	__BITFIELD_FIELD(unsigned mx:5,		/* exception enable  mask */ +	__BITFIELD_FIELD(unsigned sx:5,		/* exceptions total */ +	__BITFIELD_FIELD(unsigned rm:2,		/* current rounding mode */ +	;))))))))  };  #define ieee754_csr (*(struct _ieee754_csr *)(¤t->thread.fpu.fcr31)) @@ -377,8 +254,8 @@ static inline int ieee754_sxtest(unsigned n)  }  /* debugging */ -ieee754sp ieee754sp_dump(char *s, ieee754sp x); -ieee754dp ieee754dp_dump(char *s, ieee754dp x); +union ieee754sp ieee754sp_dump(char *s, union ieee754sp x); +union ieee754dp ieee754dp_dump(char *s, union ieee754dp x);  #define IEEE754_SPCVAL_PZERO	0  #define IEEE754_SPCVAL_NZERO	1 @@ -398,10 +275,10 @@ ieee754dp ieee754dp_dump(char *s, ieee754dp x);  #define IEEE754_SPCVAL_P1E31	15	/* + 1.0e31 */  #define IEEE754_SPCVAL_P1E63	16	/* + 1.0e63 */ -extern const struct ieee754dp_konst __ieee754dp_spcvals[]; -extern const struct ieee754sp_konst __ieee754sp_spcvals[]; -#define ieee754dp_spcvals ((const ieee754dp *)__ieee754dp_spcvals) -#define ieee754sp_spcvals ((const ieee754sp *)__ieee754sp_spcvals) +extern const union ieee754dp __ieee754dp_spcvals[]; +extern const union ieee754sp __ieee754sp_spcvals[]; +#define ieee754dp_spcvals ((const union ieee754dp *)__ieee754dp_spcvals) +#define ieee754sp_spcvals ((const union ieee754sp *)__ieee754sp_spcvals)  /*   * Return infinity with given sign @@ -431,28 +308,15 @@ extern const struct ieee754sp_konst __ieee754sp_spcvals[];  /*   * Indefinite integer value   */ -#define ieee754si_indef()	INT_MAX -#ifdef LONG_LONG_MAX -#define ieee754di_indef()	LONG_LONG_MAX -#else -#define ieee754di_indef()	((s64)(~0ULL>>1)) -#endif - -/* IEEE exception context, passed to handler */ -struct ieee754xctx { -	const char *op;		/* operation name */ -	int rt;			/* result type */ -	union { -		ieee754sp sp;	/* single precision */ -		ieee754dp dp;	/* double precision */ -#ifdef IEEE854_XP -		ieee754xp xp;	/* extended precision */ -#endif -		int si;		/* standard signed integer (32bits) */ -		s64 di;		/* extended signed integer (64bits) */ -	} rv;			/* default result format implied by op */ -	va_list ap; -}; +static inline int ieee754si_indef(void) +{ +	return INT_MAX; +} + +static inline s64 ieee754di_indef(void) +{ +	return S64_MAX; +}  /* result types for xctx.rt */  #define IEEE754_RT_SP	0 @@ -461,8 +325,6 @@ struct ieee754xctx {  #define IEEE754_RT_SI	3  #define IEEE754_RT_DI	4 -extern void ieee754_xcpt(struct ieee754xctx *xcp); -  /* compat */  #define ieee754dp_fix(x)	ieee754dp_tint(x)  #define ieee754sp_fix(x)	ieee754sp_tint(x) diff --git a/arch/mips/math-emu/ieee754d.c b/arch/mips/math-emu/ieee754d.c index 9599bdd3258..a04e8a7e5ac 100644 --- a/arch/mips/math-emu/ieee754d.c +++ b/arch/mips/math-emu/ieee754d.c @@ -16,7 +16,7 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   *   *  Nov 7, 2000   *  Modified to build and operate in Linux kernel environment. @@ -25,38 +25,13 @@   *  Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.   */ -#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/printk.h>  #include "ieee754.h" +#include "ieee754sp.h" +#include "ieee754dp.h" -#define DP_EBIAS	1023 -#define DP_EMIN		(-1022) -#define DP_EMAX		1023 -#define DP_FBITS	52 - -#define SP_EBIAS	127 -#define SP_EMIN		(-126) -#define SP_EMAX		127 -#define SP_FBITS	23 - -#define DP_MBIT(x)	((u64)1 << (x)) -#define DP_HIDDEN_BIT	DP_MBIT(DP_FBITS) -#define DP_SIGN_BIT	DP_MBIT(63) - - -#define SP_MBIT(x)	((u32)1 << (x)) -#define SP_HIDDEN_BIT	SP_MBIT(SP_FBITS) -#define SP_SIGN_BIT	SP_MBIT(31) - - -#define SPSIGN(sp)	(sp.parts.sign) -#define SPBEXP(sp)	(sp.parts.bexp) -#define SPMANT(sp)	(sp.parts.mant) - -#define DPSIGN(dp)	(dp.parts.sign) -#define DPBEXP(dp)	(dp.parts.bexp) -#define DPMANT(dp)	(dp.parts.mant) - -ieee754dp ieee754dp_dump(char *m, ieee754dp x) +union ieee754dp ieee754dp_dump(char *m, union ieee754dp x)  {  	int i; @@ -96,7 +71,7 @@ ieee754dp ieee754dp_dump(char *m, ieee754dp x)  	return x;  } -ieee754sp ieee754sp_dump(char *m, ieee754sp x) +union ieee754sp ieee754sp_dump(char *m, union ieee754sp x)  {  	int i; diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c index 068e56be8de..fd134675fc2 100644 --- a/arch/mips/math-emu/ieee754dp.c +++ b/arch/mips/math-emu/ieee754dp.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,104 +16,68 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ +#include <linux/compiler.h>  #include "ieee754dp.h" -int ieee754dp_class(ieee754dp x) +int ieee754dp_class(union ieee754dp x)  {  	COMPXDP;  	EXPLODEXDP;  	return xc;  } -int ieee754dp_isnan(ieee754dp x) +int ieee754dp_isnan(union ieee754dp x)  {  	return ieee754dp_class(x) >= IEEE754_CLASS_SNAN;  } -int ieee754dp_issnan(ieee754dp x) +static inline int ieee754dp_issnan(union ieee754dp x)  {  	assert(ieee754dp_isnan(x)); -	return ((DPMANT(x) & DP_MBIT(DP_MBITS-1)) == DP_MBIT(DP_MBITS-1)); +	return ((DPMANT(x) & DP_MBIT(DP_FBITS-1)) == DP_MBIT(DP_FBITS-1));  } -ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...) -{ -	struct ieee754xctx ax; -	if (!TSTX()) -		return r; - -	ax.op = op; -	ax.rt = IEEE754_RT_DP; -	ax.rv.dp = r; -	va_start(ax.ap, op); -	ieee754_xcpt(&ax); -	va_end(ax.ap); -	return ax.rv.dp; -} - -ieee754dp ieee754dp_nanxcpt(ieee754dp r, const char *op, ...) +union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp r)  { -	struct ieee754xctx ax; -  	assert(ieee754dp_isnan(r));  	if (!ieee754dp_issnan(r))	/* QNAN does not cause invalid op !! */  		return r; -	if (!SETANDTESTCX(IEEE754_INVALID_OPERATION)) { +	if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) {  		/* not enabled convert to a quiet NaN */ -		DPMANT(r) &= (~DP_MBIT(DP_MBITS-1)); +		DPMANT(r) &= (~DP_MBIT(DP_FBITS-1));  		if (ieee754dp_isnan(r))  			return r;  		else  			return ieee754dp_indef();  	} -	ax.op = op; -	ax.rt = 0; -	ax.rv.dp = r; -	va_start(ax.ap, op); -	ieee754_xcpt(&ax); -	va_end(ax.ap); -	return ax.rv.dp; +	return r;  } -ieee754dp ieee754dp_bestnan(ieee754dp x, ieee754dp y) -{ -	assert(ieee754dp_isnan(x)); -	assert(ieee754dp_isnan(y)); - -	if (DPMANT(x) > DPMANT(y)) -		return x; -	else -		return y; -} - - -static u64 get_rounding(int sn, u64 xm) +static u64 ieee754dp_get_rounding(int sn, u64 xm)  {  	/* inexact must round of 3 bits  	 */  	if (xm & (DP_MBIT(3) - 1)) {  		switch (ieee754_csr.rm) { -		case IEEE754_RZ: +		case FPU_CSR_RZ:  			break; -		case IEEE754_RN: +		case FPU_CSR_RN:  			xm += 0x3 + ((xm >> 3) & 1);  			/* xm += (xm&0x8)?0x4:0x3 */  			break; -		case IEEE754_RU:	/* toward +Infinity */ +		case FPU_CSR_RU:	/* toward +Infinity */  			if (!sn)	/* ?? */  				xm += 0x8;  			break; -		case IEEE754_RD:	/* toward -Infinity */ +		case FPU_CSR_RD:	/* toward -Infinity */  			if (sn) /* ?? */  				xm += 0x8;  			break; @@ -130,11 +92,11 @@ static u64 get_rounding(int sn, u64 xm)   * xe is an unbiased exponent   * xm is 3bit extended precision value.   */ -ieee754dp ieee754dp_format(int sn, int xe, u64 xm) +union ieee754dp ieee754dp_format(int sn, int xe, u64 xm)  {  	assert(xm);		/* we don't gen exact zeros (probably should) */ -	assert((xm >> (DP_MBITS + 1 + 3)) == 0);	/* no execess */ +	assert((xm >> (DP_FBITS + 1 + 3)) == 0);	/* no execess */  	assert(xm & (DP_HIDDEN_BIT << 3));  	if (xe < DP_EMIN) { @@ -142,32 +104,32 @@ ieee754dp ieee754dp_format(int sn, int xe, u64 xm)  		int es = DP_EMIN - xe;  		if (ieee754_csr.nod) { -			SETCX(IEEE754_UNDERFLOW); -			SETCX(IEEE754_INEXACT); +			ieee754_setcx(IEEE754_UNDERFLOW); +			ieee754_setcx(IEEE754_INEXACT);  			switch(ieee754_csr.rm) { -			case IEEE754_RN: -			case IEEE754_RZ: +			case FPU_CSR_RN: +			case FPU_CSR_RZ:  				return ieee754dp_zero(sn); -			case IEEE754_RU:    /* toward +Infinity */ -				if(sn == 0) +			case FPU_CSR_RU:    /* toward +Infinity */ +				if (sn == 0)  					return ieee754dp_min(0);  				else  					return ieee754dp_zero(1); -			case IEEE754_RD:    /* toward -Infinity */ -				if(sn == 0) +			case FPU_CSR_RD:    /* toward -Infinity */ +				if (sn == 0)  					return ieee754dp_zero(0);  				else  					return ieee754dp_min(1);  			}  		} -		if (xe == DP_EMIN - 1 -				&& get_rounding(sn, xm) >> (DP_MBITS + 1 + 3)) +		if (xe == DP_EMIN - 1 && +		    ieee754dp_get_rounding(sn, xm) >> (DP_FBITS + 1 + 3))  		{  			/* Not tiny after rounding */ -			SETCX(IEEE754_INEXACT); -			xm = get_rounding(sn, xm); +			ieee754_setcx(IEEE754_INEXACT); +			xm = ieee754dp_get_rounding(sn, xm);  			xm >>= 1;  			/* Clear grs bits */  			xm &= ~(DP_MBIT(3) - 1); @@ -183,17 +145,17 @@ ieee754dp ieee754dp_format(int sn, int xe, u64 xm)  		}  	}  	if (xm & (DP_MBIT(3) - 1)) { -		SETCX(IEEE754_INEXACT); +		ieee754_setcx(IEEE754_INEXACT);  		if ((xm & (DP_HIDDEN_BIT << 3)) == 0) { -			SETCX(IEEE754_UNDERFLOW); +			ieee754_setcx(IEEE754_UNDERFLOW);  		}  		/* inexact must round of 3 bits  		 */ -		xm = get_rounding(sn, xm); +		xm = ieee754dp_get_rounding(sn, xm);  		/* adjust exponent for rounding add overflowing  		 */ -		if (xm >> (DP_MBITS + 3 + 1)) { +		if (xm >> (DP_FBITS + 3 + 1)) {  			/* add causes mantissa overflow */  			xm >>= 1;  			xe++; @@ -202,24 +164,24 @@ ieee754dp ieee754dp_format(int sn, int xe, u64 xm)  	/* strip grs bits */  	xm >>= 3; -	assert((xm >> (DP_MBITS + 1)) == 0);	/* no execess */ +	assert((xm >> (DP_FBITS + 1)) == 0);	/* no execess */  	assert(xe >= DP_EMIN);  	if (xe > DP_EMAX) { -		SETCX(IEEE754_OVERFLOW); -		SETCX(IEEE754_INEXACT); +		ieee754_setcx(IEEE754_OVERFLOW); +		ieee754_setcx(IEEE754_INEXACT);  		/* -O can be table indexed by (rm,sn) */  		switch (ieee754_csr.rm) { -		case IEEE754_RN: +		case FPU_CSR_RN:  			return ieee754dp_inf(sn); -		case IEEE754_RZ: +		case FPU_CSR_RZ:  			return ieee754dp_max(sn); -		case IEEE754_RU:	/* toward +Infinity */ +		case FPU_CSR_RU:	/* toward +Infinity */  			if (sn == 0)  				return ieee754dp_inf(0);  			else  				return ieee754dp_max(1); -		case IEEE754_RD:	/* toward -Infinity */ +		case FPU_CSR_RD:	/* toward -Infinity */  			if (sn == 0)  				return ieee754dp_max(0);  			else @@ -232,10 +194,10 @@ ieee754dp ieee754dp_format(int sn, int xe, u64 xm)  		/* we underflow (tiny/zero) */  		assert(xe == DP_EMIN);  		if (ieee754_csr.mx & IEEE754_UNDERFLOW) -			SETCX(IEEE754_UNDERFLOW); +			ieee754_setcx(IEEE754_UNDERFLOW);  		return builddp(sn, DP_EMIN - 1 + DP_EBIAS, xm);  	} else { -		assert((xm >> (DP_MBITS + 1)) == 0);	/* no execess */ +		assert((xm >> (DP_FBITS + 1)) == 0);	/* no execess */  		assert(xm & DP_HIDDEN_BIT);  		return builddp(sn, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT); diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h index f139c724c59..61fd6fd3135 100644 --- a/arch/mips/math-emu/ieee754dp.h +++ b/arch/mips/math-emu/ieee754dp.h @@ -6,8 +6,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -19,64 +17,66 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ +#include <linux/compiler.h>  #include "ieee754int.h"  #define assert(expr) ((void)0) +#define DP_EBIAS	1023 +#define DP_EMIN		(-1022) +#define DP_EMAX		1023 +#define DP_FBITS	52 +#define DP_MBITS	52 + +#define DP_MBIT(x)	((u64)1 << (x)) +#define DP_HIDDEN_BIT	DP_MBIT(DP_FBITS) +#define DP_SIGN_BIT	DP_MBIT(63) + +#define DPSIGN(dp)	(dp.sign) +#define DPBEXP(dp)	(dp.bexp) +#define DPMANT(dp)	(dp.mant) + +static inline int ieee754dp_finite(union ieee754dp x) +{ +	return DPBEXP(x) != DP_EMAX + 1 + DP_EBIAS; +} +  /* 3bit extended double precision sticky right shift */  #define XDPSRS(v,rs)	\ -  ((rs > (DP_MBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0)) +	((rs > (DP_FBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0))  #define XDPSRSX1() \ -  (xe++, (xm = (xm >> 1) | (xm & 1))) +	(xe++, (xm = (xm >> 1) | (xm & 1)))  #define XDPSRS1(v)	\ -  (((v) >> 1) | ((v) & 1)) +	(((v) >> 1) | ((v) & 1))  /* convert denormal to normalized with extended exponent */  #define DPDNORMx(m,e) \ -  while( (m >> DP_MBITS) == 0) { m <<= 1; e--; } +	while ((m >> DP_FBITS) == 0) { m <<= 1; e--; }  #define DPDNORMX	DPDNORMx(xm, xe)  #define DPDNORMY	DPDNORMx(ym, ye) -static inline ieee754dp builddp(int s, int bx, u64 m) +static inline union ieee754dp builddp(int s, int bx, u64 m)  { -	ieee754dp r; +	union ieee754dp r;  	assert((s) == 0 || (s) == 1);  	assert((bx) >= DP_EMIN - 1 + DP_EBIAS  	       && (bx) <= DP_EMAX + 1 + DP_EBIAS); -	assert(((m) >> DP_MBITS) == 0); +	assert(((m) >> DP_FBITS) == 0); -	r.parts.sign = s; -	r.parts.bexp = bx; -	r.parts.mant = m; -	return r; -} +	r.sign = s; +	r.bexp = bx; +	r.mant = m; -extern int ieee754dp_isnan(ieee754dp); -extern int ieee754dp_issnan(ieee754dp); -extern int ieee754si_xcpt(int, const char *, ...); -extern s64 ieee754di_xcpt(s64, const char *, ...); -extern ieee754dp ieee754dp_xcpt(ieee754dp, const char *, ...); -extern ieee754dp ieee754dp_nanxcpt(ieee754dp, const char *, ...); -extern ieee754dp ieee754dp_bestnan(ieee754dp, ieee754dp); -extern ieee754dp ieee754dp_format(int, int, u64); - - -#define DPNORMRET2(s, e, m, name, a0, a1) \ -{ \ -    ieee754dp V = ieee754dp_format(s, e, m); \ -    if(TSTX()) \ -      return ieee754dp_xcpt(V, name, a0, a1); \ -    else \ -      return V; \ +	return r;  } -#define DPNORMRET1(s, e, m, name, a0)  DPNORMRET2(s, e, m, name, a0, a0) +extern int ieee754dp_isnan(union ieee754dp); +extern union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp); +extern union ieee754dp ieee754dp_format(int, int, u64); diff --git a/arch/mips/math-emu/ieee754int.h b/arch/mips/math-emu/ieee754int.h index 4b6c6fb3530..f0365bb8674 100644 --- a/arch/mips/math-emu/ieee754int.h +++ b/arch/mips/math-emu/ieee754int.h @@ -6,8 +6,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -19,146 +17,125 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ - +#ifndef __IEEE754INT_H +#define __IEEE754INT_H  #include "ieee754.h" -#define DP_EBIAS	1023 -#define DP_EMIN		(-1022) -#define DP_EMAX		1023 -#define DP_MBITS	52 - -#define SP_EBIAS	127 -#define SP_EMIN		(-126) -#define SP_EMAX		127 -#define SP_MBITS	23 - -#define DP_MBIT(x)	((u64)1 << (x)) -#define DP_HIDDEN_BIT	DP_MBIT(DP_MBITS) -#define DP_SIGN_BIT	DP_MBIT(63) - -#define SP_MBIT(x)	((u32)1 << (x)) -#define SP_HIDDEN_BIT	SP_MBIT(SP_MBITS) -#define SP_SIGN_BIT	SP_MBIT(31) - - -#define SPSIGN(sp)	(sp.parts.sign) -#define SPBEXP(sp)	(sp.parts.bexp) -#define SPMANT(sp)	(sp.parts.mant) - -#define DPSIGN(dp)	(dp.parts.sign) -#define DPBEXP(dp)	(dp.parts.bexp) -#define DPMANT(dp)	(dp.parts.mant) -  #define CLPAIR(x, y)	((x)*6+(y)) -#define CLEARCX \ -  (ieee754_csr.cx = 0) - -#define SETCX(x) \ -  (ieee754_csr.cx |= (x), ieee754_csr.sx |= (x)) +static inline void ieee754_clearcx(void) +{ +	ieee754_csr.cx = 0; +} -#define SETANDTESTCX(x) \ -  (SETCX(x), ieee754_csr.mx & (x)) +static inline void ieee754_setcx(const unsigned int flags) +{ +	ieee754_csr.cx |= flags; +	ieee754_csr.sx |= flags; +} -#define TSTX()	\ -	(ieee754_csr.cx & ieee754_csr.mx) +static inline int ieee754_setandtestcx(const unsigned int x) +{ +	ieee754_setcx(x); +	return ieee754_csr.mx & x; +}  #define COMPXSP \ -  unsigned xm; int xe; int xs __maybe_unused; int xc +	unsigned xm; int xe; int xs __maybe_unused; int xc  #define COMPYSP \ -  unsigned ym; int ye; int ys; int yc - -#define EXPLODESP(v, vc, vs, ve, vm) \ -{\ -    vs = SPSIGN(v);\ -    ve = SPBEXP(v);\ -    vm = SPMANT(v);\ -    if(ve == SP_EMAX+1+SP_EBIAS){\ -	if(vm == 0)\ -	  vc = IEEE754_CLASS_INF;\ -	else if(vm & SP_MBIT(SP_MBITS-1)) \ -	  vc = IEEE754_CLASS_SNAN;\ -	else \ -	  vc = IEEE754_CLASS_QNAN;\ -    } else if(ve == SP_EMIN-1+SP_EBIAS) {\ -	if(vm) {\ -	    ve = SP_EMIN;\ -	    vc = IEEE754_CLASS_DNORM;\ -	} else\ -	  vc = IEEE754_CLASS_ZERO;\ -    } else {\ -	ve -= SP_EBIAS;\ -	vm |= SP_HIDDEN_BIT;\ -	vc = IEEE754_CLASS_NORM;\ -    }\ +	unsigned ym; int ye; int ys; int yc + +#define EXPLODESP(v, vc, vs, ve, vm)					\ +{									\ +	vs = SPSIGN(v);							\ +	ve = SPBEXP(v);							\ +	vm = SPMANT(v);							\ +	if (ve == SP_EMAX+1+SP_EBIAS) {					\ +		if (vm == 0)						\ +			vc = IEEE754_CLASS_INF;				\ +		else if (vm & SP_MBIT(SP_FBITS-1))			\ +			vc = IEEE754_CLASS_SNAN;			\ +	else								\ +		vc = IEEE754_CLASS_QNAN;				\ +	} else if (ve == SP_EMIN-1+SP_EBIAS) {				\ +		if (vm) {						\ +			ve = SP_EMIN;					\ +			vc = IEEE754_CLASS_DNORM;			\ +		} else							\ +			vc = IEEE754_CLASS_ZERO;			\ +	} else {							\ +		ve -= SP_EBIAS;						\ +		vm |= SP_HIDDEN_BIT;					\ +		vc = IEEE754_CLASS_NORM;				\ +	}								\  }  #define EXPLODEXSP EXPLODESP(x, xc, xs, xe, xm)  #define EXPLODEYSP EXPLODESP(y, yc, ys, ye, ym)  #define COMPXDP \ -u64 xm; int xe; int xs __maybe_unused; int xc +	u64 xm; int xe; int xs __maybe_unused; int xc  #define COMPYDP \ -u64 ym; int ye; int ys; int yc - -#define EXPLODEDP(v, vc, vs, ve, vm) \ -{\ -    vm = DPMANT(v);\ -    vs = DPSIGN(v);\ -    ve = DPBEXP(v);\ -    if(ve == DP_EMAX+1+DP_EBIAS){\ -	if(vm == 0)\ -	  vc = IEEE754_CLASS_INF;\ -	else if(vm & DP_MBIT(DP_MBITS-1)) \ -	  vc = IEEE754_CLASS_SNAN;\ -	else \ -	  vc = IEEE754_CLASS_QNAN;\ -    } else if(ve == DP_EMIN-1+DP_EBIAS) {\ -	if(vm) {\ -	    ve = DP_EMIN;\ -	    vc = IEEE754_CLASS_DNORM;\ -	} else\ -	  vc = IEEE754_CLASS_ZERO;\ -    } else {\ -	ve -= DP_EBIAS;\ -	vm |= DP_HIDDEN_BIT;\ -	vc = IEEE754_CLASS_NORM;\ -    }\ +	u64 ym; int ye; int ys; int yc + +#define EXPLODEDP(v, vc, vs, ve, vm)					\ +{									\ +	vm = DPMANT(v);							\ +	vs = DPSIGN(v);							\ +	ve = DPBEXP(v);							\ +	if (ve == DP_EMAX+1+DP_EBIAS) {					\ +		if (vm == 0)						\ +			vc = IEEE754_CLASS_INF;				\ +		else if (vm & DP_MBIT(DP_FBITS-1))			\ +			vc = IEEE754_CLASS_SNAN;			\ +		else							\ +			vc = IEEE754_CLASS_QNAN;			\ +	} else if (ve == DP_EMIN-1+DP_EBIAS) {				\ +		if (vm) {						\ +			ve = DP_EMIN;					\ +			vc = IEEE754_CLASS_DNORM;			\ +	} else								\ +		vc = IEEE754_CLASS_ZERO;				\ +	} else {							\ +		ve -= DP_EBIAS;						\ +		vm |= DP_HIDDEN_BIT;					\ +		vc = IEEE754_CLASS_NORM;				\ +	}								\  }  #define EXPLODEXDP EXPLODEDP(x, xc, xs, xe, xm)  #define EXPLODEYDP EXPLODEDP(y, yc, ys, ye, ym) -#define FLUSHDP(v, vc, vs, ve, vm) \ -	if(vc==IEEE754_CLASS_DNORM) {\ -	    if(ieee754_csr.nod) {\ -		SETCX(IEEE754_INEXACT);\ -		vc = IEEE754_CLASS_ZERO;\ -		ve = DP_EMIN-1+DP_EBIAS;\ -		vm = 0;\ -		v = ieee754dp_zero(vs);\ -	    }\ +#define FLUSHDP(v, vc, vs, ve, vm)					\ +	if (vc==IEEE754_CLASS_DNORM) {					\ +		if (ieee754_csr.nod) {					\ +			ieee754_setcx(IEEE754_INEXACT);			\ +			vc = IEEE754_CLASS_ZERO;			\ +			ve = DP_EMIN-1+DP_EBIAS;			\ +			vm = 0;						\ +			v = ieee754dp_zero(vs);				\ +		}							\  	} -#define FLUSHSP(v, vc, vs, ve, vm) \ -	if(vc==IEEE754_CLASS_DNORM) {\ -	    if(ieee754_csr.nod) {\ -		SETCX(IEEE754_INEXACT);\ -		vc = IEEE754_CLASS_ZERO;\ -		ve = SP_EMIN-1+SP_EBIAS;\ -		vm = 0;\ -		v = ieee754sp_zero(vs);\ -	    }\ +#define FLUSHSP(v, vc, vs, ve, vm)					\ +	if (vc==IEEE754_CLASS_DNORM) {					\ +		if (ieee754_csr.nod) {					\ +			ieee754_setcx(IEEE754_INEXACT);			\ +			vc = IEEE754_CLASS_ZERO;			\ +			ve = SP_EMIN-1+SP_EBIAS;			\ +			vm = 0;						\ +			v = ieee754sp_zero(vs);				\ +		}							\  	}  #define FLUSHXDP FLUSHDP(x, xc, xs, xe, xm)  #define FLUSHYDP FLUSHDP(y, yc, ys, ye, ym)  #define FLUSHXSP FLUSHSP(x, xc, xs, xe, xm)  #define FLUSHYSP FLUSHSP(y, yc, ys, ye, ym) + +#endif /* __IEEE754INT_H  */ diff --git a/arch/mips/math-emu/ieee754m.c b/arch/mips/math-emu/ieee754m.c deleted file mode 100644 index 24190f3c9dd..00000000000 --- a/arch/mips/math-emu/ieee754m.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * floor, trunc, ceil - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. - * - * ######################################################################## - * - *  This program is free software; you can distribute it and/or modify it - *  under the terms of the GNU General Public License (Version 2) as - *  published by the Free Software Foundation. - * - *  This program is distributed in the hope it will be useful, but WITHOUT - *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License - *  for more details. - * - *  You should have received a copy of the GNU General Public License along - *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754.h" - -ieee754dp ieee754dp_floor(ieee754dp x) -{ -	ieee754dp i; - -	if (ieee754dp_lt(ieee754dp_modf(x, &i), ieee754dp_zero(0))) -		return ieee754dp_sub(i, ieee754dp_one(0)); -	else -		return i; -} - -ieee754dp ieee754dp_ceil(ieee754dp x) -{ -	ieee754dp i; - -	if (ieee754dp_gt(ieee754dp_modf(x, &i), ieee754dp_zero(0))) -		return ieee754dp_add(i, ieee754dp_one(0)); -	else -		return i; -} - -ieee754dp ieee754dp_trunc(ieee754dp x) -{ -	ieee754dp i; - -	(void) ieee754dp_modf(x, &i); -	return i; -} diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index 15d1e36cfe6..d348efe9144 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,105 +16,68 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ +#include <linux/compiler.h>  #include "ieee754sp.h" -int ieee754sp_class(ieee754sp x) +int ieee754sp_class(union ieee754sp x)  {  	COMPXSP;  	EXPLODEXSP;  	return xc;  } -int ieee754sp_isnan(ieee754sp x) +int ieee754sp_isnan(union ieee754sp x)  {  	return ieee754sp_class(x) >= IEEE754_CLASS_SNAN;  } -int ieee754sp_issnan(ieee754sp x) +static inline int ieee754sp_issnan(union ieee754sp x)  {  	assert(ieee754sp_isnan(x)); -	return (SPMANT(x) & SP_MBIT(SP_MBITS-1)); +	return (SPMANT(x) & SP_MBIT(SP_FBITS-1));  } -ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...) -{ -	struct ieee754xctx ax; - -	if (!TSTX()) -		return r; - -	ax.op = op; -	ax.rt = IEEE754_RT_SP; -	ax.rv.sp = r; -	va_start(ax.ap, op); -	ieee754_xcpt(&ax); -	va_end(ax.ap); -	return ax.rv.sp; -} - -ieee754sp ieee754sp_nanxcpt(ieee754sp r, const char *op, ...) +union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r)  { -	struct ieee754xctx ax; -  	assert(ieee754sp_isnan(r));  	if (!ieee754sp_issnan(r))	/* QNAN does not cause invalid op !! */  		return r; -	if (!SETANDTESTCX(IEEE754_INVALID_OPERATION)) { +	if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) {  		/* not enabled convert to a quiet NaN */ -		SPMANT(r) &= (~SP_MBIT(SP_MBITS-1)); +		SPMANT(r) &= (~SP_MBIT(SP_FBITS-1));  		if (ieee754sp_isnan(r))  			return r;  		else  			return ieee754sp_indef();  	} -	ax.op = op; -	ax.rt = 0; -	ax.rv.sp = r; -	va_start(ax.ap, op); -	ieee754_xcpt(&ax); -	va_end(ax.ap); -	return ax.rv.sp; -} - -ieee754sp ieee754sp_bestnan(ieee754sp x, ieee754sp y) -{ -	assert(ieee754sp_isnan(x)); -	assert(ieee754sp_isnan(y)); - -	if (SPMANT(x) > SPMANT(y)) -		return x; -	else -		return y; +	return r;  } - -static unsigned get_rounding(int sn, unsigned xm) +static unsigned ieee754sp_get_rounding(int sn, unsigned xm)  {  	/* inexact must round of 3 bits  	 */  	if (xm & (SP_MBIT(3) - 1)) {  		switch (ieee754_csr.rm) { -		case IEEE754_RZ: +		case FPU_CSR_RZ:  			break; -		case IEEE754_RN: +		case FPU_CSR_RN:  			xm += 0x3 + ((xm >> 3) & 1);  			/* xm += (xm&0x8)?0x4:0x3 */  			break; -		case IEEE754_RU:	/* toward +Infinity */ +		case FPU_CSR_RU:	/* toward +Infinity */  			if (!sn)	/* ?? */  				xm += 0x8;  			break; -		case IEEE754_RD:	/* toward -Infinity */ +		case FPU_CSR_RD:	/* toward -Infinity */  			if (sn) /* ?? */  				xm += 0x8;  			break; @@ -131,11 +92,11 @@ static unsigned get_rounding(int sn, unsigned xm)   * xe is an unbiased exponent   * xm is 3bit extended precision value.   */ -ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) +union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)  {  	assert(xm);		/* we don't gen exact zeros (probably should) */ -	assert((xm >> (SP_MBITS + 1 + 3)) == 0);	/* no execess */ +	assert((xm >> (SP_FBITS + 1 + 3)) == 0);	/* no execess */  	assert(xm & (SP_HIDDEN_BIT << 3));  	if (xe < SP_EMIN) { @@ -143,38 +104,37 @@ ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)  		int es = SP_EMIN - xe;  		if (ieee754_csr.nod) { -			SETCX(IEEE754_UNDERFLOW); -			SETCX(IEEE754_INEXACT); +			ieee754_setcx(IEEE754_UNDERFLOW); +			ieee754_setcx(IEEE754_INEXACT);  			switch(ieee754_csr.rm) { -			case IEEE754_RN: -			case IEEE754_RZ: +			case FPU_CSR_RN: +			case FPU_CSR_RZ:  				return ieee754sp_zero(sn); -			case IEEE754_RU:      /* toward +Infinity */ -				if(sn == 0) +			case FPU_CSR_RU:      /* toward +Infinity */ +				if (sn == 0)  					return ieee754sp_min(0);  				else  					return ieee754sp_zero(1); -			case IEEE754_RD:      /* toward -Infinity */ -				if(sn == 0) +			case FPU_CSR_RD:      /* toward -Infinity */ +				if (sn == 0)  					return ieee754sp_zero(0);  				else  					return ieee754sp_min(1);  			}  		} -		if (xe == SP_EMIN - 1 -				&& get_rounding(sn, xm) >> (SP_MBITS + 1 + 3)) +		if (xe == SP_EMIN - 1 && +		    ieee754sp_get_rounding(sn, xm) >> (SP_FBITS + 1 + 3))  		{  			/* Not tiny after rounding */ -			SETCX(IEEE754_INEXACT); -			xm = get_rounding(sn, xm); +			ieee754_setcx(IEEE754_INEXACT); +			xm = ieee754sp_get_rounding(sn, xm);  			xm >>= 1;  			/* Clear grs bits */  			xm &= ~(SP_MBIT(3) - 1);  			xe++; -		} -		else { +		} else {  			/* sticky right shift es bits  			 */  			SPXSRSXn(es); @@ -183,17 +143,17 @@ ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)  		}  	}  	if (xm & (SP_MBIT(3) - 1)) { -		SETCX(IEEE754_INEXACT); +		ieee754_setcx(IEEE754_INEXACT);  		if ((xm & (SP_HIDDEN_BIT << 3)) == 0) { -			SETCX(IEEE754_UNDERFLOW); +			ieee754_setcx(IEEE754_UNDERFLOW);  		}  		/* inexact must round of 3 bits  		 */ -		xm = get_rounding(sn, xm); +		xm = ieee754sp_get_rounding(sn, xm);  		/* adjust exponent for rounding add overflowing  		 */ -		if (xm >> (SP_MBITS + 1 + 3)) { +		if (xm >> (SP_FBITS + 1 + 3)) {  			/* add causes mantissa overflow */  			xm >>= 1;  			xe++; @@ -202,24 +162,24 @@ ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)  	/* strip grs bits */  	xm >>= 3; -	assert((xm >> (SP_MBITS + 1)) == 0);	/* no execess */ +	assert((xm >> (SP_FBITS + 1)) == 0);	/* no execess */  	assert(xe >= SP_EMIN);  	if (xe > SP_EMAX) { -		SETCX(IEEE754_OVERFLOW); -		SETCX(IEEE754_INEXACT); +		ieee754_setcx(IEEE754_OVERFLOW); +		ieee754_setcx(IEEE754_INEXACT);  		/* -O can be table indexed by (rm,sn) */  		switch (ieee754_csr.rm) { -		case IEEE754_RN: +		case FPU_CSR_RN:  			return ieee754sp_inf(sn); -		case IEEE754_RZ: +		case FPU_CSR_RZ:  			return ieee754sp_max(sn); -		case IEEE754_RU:	/* toward +Infinity */ +		case FPU_CSR_RU:	/* toward +Infinity */  			if (sn == 0)  				return ieee754sp_inf(0);  			else  				return ieee754sp_max(1); -		case IEEE754_RD:	/* toward -Infinity */ +		case FPU_CSR_RD:	/* toward -Infinity */  			if (sn == 0)  				return ieee754sp_max(0);  			else @@ -232,10 +192,10 @@ ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)  		/* we underflow (tiny/zero) */  		assert(xe == SP_EMIN);  		if (ieee754_csr.mx & IEEE754_UNDERFLOW) -			SETCX(IEEE754_UNDERFLOW); +			ieee754_setcx(IEEE754_UNDERFLOW);  		return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm);  	} else { -		assert((xm >> (SP_MBITS + 1)) == 0);	/* no execess */ +		assert((xm >> (SP_FBITS + 1)) == 0);	/* no execess */  		assert(xm & SP_HIDDEN_BIT);  		return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT); diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h index 754fd54649b..ad268e33231 100644 --- a/arch/mips/math-emu/ieee754sp.h +++ b/arch/mips/math-emu/ieee754sp.h @@ -6,8 +6,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -19,70 +17,71 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ +#include <linux/compiler.h>  #include "ieee754int.h"  #define assert(expr) ((void)0) +#define SP_EBIAS	127 +#define SP_EMIN		(-126) +#define SP_EMAX		127 +#define SP_FBITS	23 +#define SP_MBITS	23 + +#define SP_MBIT(x)	((u32)1 << (x)) +#define SP_HIDDEN_BIT	SP_MBIT(SP_FBITS) +#define SP_SIGN_BIT	SP_MBIT(31) + +#define SPSIGN(sp)	(sp.sign) +#define SPBEXP(sp)	(sp.bexp) +#define SPMANT(sp)	(sp.mant) + +static inline int ieee754sp_finite(union ieee754sp x) +{ +	return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS; +} +  /* 3bit extended single precision sticky right shift */ -#define SPXSRSXn(rs) \ -  (xe += rs, \ -   xm = (rs > (SP_MBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0)) +#define SPXSRSXn(rs)							\ +	(xe += rs,							\ +	 xm = (rs > (SP_FBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0))  #define SPXSRSX1() \ -  (xe++, (xm = (xm >> 1) | (xm & 1))) +	(xe++, (xm = (xm >> 1) | (xm & 1))) -#define SPXSRSYn(rs) \ -   (ye+=rs, \ -    ym = (rs > (SP_MBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0)) +#define SPXSRSYn(rs)								\ +	(ye+=rs,								\ +	 ym = (rs > (SP_FBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0))  #define SPXSRSY1() \ -   (ye++, (ym = (ym >> 1) | (ym & 1))) +	(ye++, (ym = (ym >> 1) | (ym & 1)))  /* convert denormal to normalized with extended exponent */  #define SPDNORMx(m,e) \ -  while( (m >> SP_MBITS) == 0) { m <<= 1; e--; } +	while ((m >> SP_FBITS) == 0) { m <<= 1; e--; }  #define SPDNORMX	SPDNORMx(xm, xe)  #define SPDNORMY	SPDNORMx(ym, ye) -static inline ieee754sp buildsp(int s, int bx, unsigned m) +static inline union ieee754sp buildsp(int s, int bx, unsigned m)  { -	ieee754sp r; +	union ieee754sp r;  	assert((s) == 0 || (s) == 1);  	assert((bx) >= SP_EMIN - 1 + SP_EBIAS  	       && (bx) <= SP_EMAX + 1 + SP_EBIAS); -	assert(((m) >> SP_MBITS) == 0); +	assert(((m) >> SP_FBITS) == 0); -	r.parts.sign = s; -	r.parts.bexp = bx; -	r.parts.mant = m; +	r.sign = s; +	r.bexp = bx; +	r.mant = m;  	return r;  } -extern int ieee754sp_isnan(ieee754sp); -extern int ieee754sp_issnan(ieee754sp); -extern int ieee754si_xcpt(int, const char *, ...); -extern s64 ieee754di_xcpt(s64, const char *, ...); -extern ieee754sp ieee754sp_xcpt(ieee754sp, const char *, ...); -extern ieee754sp ieee754sp_nanxcpt(ieee754sp, const char *, ...); -extern ieee754sp ieee754sp_bestnan(ieee754sp, ieee754sp); -extern ieee754sp ieee754sp_format(int, int, unsigned); - - -#define SPNORMRET2(s, e, m, name, a0, a1) \ -{ \ -    ieee754sp V = ieee754sp_format(s, e, m); \ -    if(TSTX()) \ -      return ieee754sp_xcpt(V, name, a0, a1); \ -    else \ -      return V; \ -} - -#define SPNORMRET1(s, e, m, name, a0)  SPNORMRET2(s, e, m, name, a0, a0) +extern int ieee754sp_isnan(union ieee754sp); +extern union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp); +extern union ieee754sp ieee754sp_format(int, int, unsigned); diff --git a/arch/mips/math-emu/ieee754xcpt.c b/arch/mips/math-emu/ieee754xcpt.c deleted file mode 100644 index 967167116ae..00000000000 --- a/arch/mips/math-emu/ieee754xcpt.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. - * - * ######################################################################## - * - *  This program is free software; you can distribute it and/or modify it - *  under the terms of the GNU General Public License (Version 2) as - *  published by the Free Software Foundation. - * - *  This program is distributed in the hope it will be useful, but WITHOUT - *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License - *  for more details. - * - *  You should have received a copy of the GNU General Public License along - *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - -/************************************************************************** - *  Nov 7, 2000 - *  Added preprocessor hacks to map to Linux kernel diagnostics. - * - *  Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com - *  Copyright (C) 2000 MIPS Technologies, Inc.	All rights reserved. - *************************************************************************/ - -#include <linux/kernel.h> -#include "ieee754.h" - -/* - * Very naff exception handler (you can plug in your own and - * override this). - */ - -static const char *const rtnames[] = { -	"sp", "dp", "xp", "si", "di" -}; - -void ieee754_xcpt(struct ieee754xctx *xcp) -{ -	printk(KERN_DEBUG "floating point exception in \"%s\", type=%s\n", -		xcp->op, rtnames[xcp->rt]); -} diff --git a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c deleted file mode 100644 index 1c586575fe1..00000000000 --- a/arch/mips/math-emu/kernel_linkage.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - *  Kevin D. Kissell, kevink@mips and Carsten Langgaard, carstenl@mips.com - *  Copyright (C) 2000 MIPS Technologies, Inc.	All rights reserved. - * - *  This program is free software; you can distribute it and/or modify it - *  under the terms of the GNU General Public License (Version 2) as - *  published by the Free Software Foundation. - * - *  This program is distributed in the hope it will be useful, but WITHOUT - *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License - *  for more details. - * - *  You should have received a copy of the GNU General Public License along - *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Routines corresponding to Linux kernel FP context - * manipulation primitives for the Algorithmics MIPS - * FPU Emulator - */ -#include <linux/sched.h> -#include <asm/processor.h> -#include <asm/signal.h> -#include <asm/uaccess.h> - -#include <asm/fpu.h> -#include <asm/fpu_emulator.h> - -#define SIGNALLING_NAN 0x7ff800007ff80000LL - -void fpu_emulator_init_fpu(void) -{ -	static int first = 1; -	int i; - -	if (first) { -		first = 0; -		printk("Algorithmics/MIPS FPU Emulator v1.5\n"); -	} - -	current->thread.fpu.fcr31 = 0; -	for (i = 0; i < 32; i++) { -		current->thread.fpu.fpr[i] = SIGNALLING_NAN; -	} -} - - -/* - * Emulator context save/restore to/from a signal context - * presumed to be on the user stack, and therefore accessed - * with appropriate macros from uaccess.h - */ - -int fpu_emulator_save_context(struct sigcontext __user *sc) -{ -	int i; -	int err = 0; - -	for (i = 0; i < 32; i++) { -		err |= -		    __put_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]); -	} -	err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr); - -	return err; -} - -int fpu_emulator_restore_context(struct sigcontext __user *sc) -{ -	int i; -	int err = 0; - -	for (i = 0; i < 32; i++) { -		err |= -		    __get_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]); -	} -	err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr); - -	return err; -} - -#ifdef CONFIG_64BIT -/* - * This is the o32 version - */ - -int fpu_emulator_save_context32(struct sigcontext32 __user *sc) -{ -	int i; -	int err = 0; - -	for (i = 0; i < 32; i+=2) { -		err |= -		    __put_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]); -	} -	err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr); - -	return err; -} - -int fpu_emulator_restore_context32(struct sigcontext32 __user *sc) -{ -	int i; -	int err = 0; - -	for (i = 0; i < 32; i+=2) { -		err |= -		    __get_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]); -	} -	err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr); - -	return err; -} -#endif diff --git a/arch/mips/math-emu/me-debugfs.c b/arch/mips/math-emu/me-debugfs.c new file mode 100644 index 00000000000..becdd63e14a --- /dev/null +++ b/arch/mips/math-emu/me-debugfs.c @@ -0,0 +1,67 @@ +#include <linux/cpumask.h> +#include <linux/debugfs.h> +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/percpu.h> +#include <linux/types.h> +#include <asm/fpu_emulator.h> +#include <asm/local.h> + +DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats); + +static int fpuemu_stat_get(void *data, u64 *val) +{ +	int cpu; +	unsigned long sum = 0; + +	for_each_online_cpu(cpu) { +		struct mips_fpu_emulator_stats *ps; +		local_t *pv; + +		ps = &per_cpu(fpuemustats, cpu); +		pv = (void *)ps + (unsigned long)data; +		sum += local_read(pv); +	} +	*val = sum; +	return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(fops_fpuemu_stat, fpuemu_stat_get, NULL, "%llu\n"); + +extern struct dentry *mips_debugfs_dir; +static int __init debugfs_fpuemu(void) +{ +	struct dentry *d, *dir; + +	if (!mips_debugfs_dir) +		return -ENODEV; +	dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir); +	if (!dir) +		return -ENOMEM; + +#define FPU_EMU_STAT_OFFSET(m)						\ +	offsetof(struct mips_fpu_emulator_stats, m) + +#define FPU_STAT_CREATE(m)						\ +do {									\ +	d = debugfs_create_file(#m , S_IRUGO, dir,			\ +				(void *)FPU_EMU_STAT_OFFSET(m),		\ +				&fops_fpuemu_stat);			\ +	if (!d)								\ +		return -ENOMEM;						\ +} while (0) + +	FPU_STAT_CREATE(emulated); +	FPU_STAT_CREATE(loads); +	FPU_STAT_CREATE(stores); +	FPU_STAT_CREATE(cp1ops); +	FPU_STAT_CREATE(cp1xops); +	FPU_STAT_CREATE(errors); +	FPU_STAT_CREATE(ieee754_inexact); +	FPU_STAT_CREATE(ieee754_underflow); +	FPU_STAT_CREATE(ieee754_overflow); +	FPU_STAT_CREATE(ieee754_zerodiv); +	FPU_STAT_CREATE(ieee754_invalidop); + +	return 0; +} +__initcall(debugfs_fpuemu); diff --git a/arch/mips/math-emu/sp_add.c b/arch/mips/math-emu/sp_add.c index c446e64637e..2d84d460cb6 100644 --- a/arch/mips/math-emu/sp_add.c +++ b/arch/mips/math-emu/sp_add.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,23 +16,22 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754sp.h" -ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y) +union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y)  { +	int s; +  	COMPXSP;  	COMPYSP;  	EXPLODEXSP;  	EXPLODEYSP; -	CLEARCX; +	ieee754_clearcx();  	FLUSHXSP;  	FLUSHYSP; @@ -51,8 +48,8 @@ ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754sp_nanxcpt(ieee754sp_indef(), "add", x, y); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754sp_nanxcpt(ieee754sp_indef());  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -68,14 +65,14 @@ ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)  		return x; -		/* Infinity handling -		 */ - +	/* +	 * Infinity handling +	 */  	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):  		if (xs == ys)  			return x; -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754sp_xcpt(ieee754sp_indef(), "add", x, y); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754sp_indef();  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): @@ -87,15 +84,14 @@ ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)  	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):  		return x; -		/* Zero handling -		 */ - +	/* +	 * Zero handling +	 */  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):  		if (xs == ys)  			return x;  		else -			return ieee754sp_zero(ieee754_csr.rm == -					      IEEE754_RD); +			return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):  	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): @@ -108,6 +104,8 @@ ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)  	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):  		SPDNORMX; +		/* FALL THROUGH */ +  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):  		SPDNORMY;  		break; @@ -122,33 +120,38 @@ ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)  	assert(xm & SP_HIDDEN_BIT);  	assert(ym & SP_HIDDEN_BIT); -	/* provide guard,round and stick bit space */ +	/* +	 * Provide guard, round and stick bit space. +	 */  	xm <<= 3;  	ym <<= 3;  	if (xe > ye) { -		/* have to shift y fraction right to align +		/* +		 * Have to shift y fraction right to align.  		 */ -		int s = xe - ye; +		s = xe - ye;  		SPXSRSYn(s);  	} else if (ye > xe) { -		/* have to shift x fraction right to align +		/* +		 * Have to shift x fraction right to align.  		 */ -		int s = ye - xe; +		s = ye - xe;  		SPXSRSXn(s);  	}  	assert(xe == ye);  	assert(xe <= SP_EMAX);  	if (xs == ys) { -		/* generate 28 bit result of adding two 27 bit numbers -		 * leaving result in xm,xs,xe +		/* +		 * Generate 28 bit result of adding two 27 bit numbers +		 * leaving result in xm, xs and xe.  		 */  		xm = xm + ym;  		xe = xe;  		xs = xs; -		if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */ +		if (xm >> (SP_FBITS + 1 + 3)) { /* carry out */  			SPXSRSX1();  		}  	} else { @@ -162,15 +165,16 @@ ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)  			xs = ys;  		}  		if (xm == 0) -			return ieee754sp_zero(ieee754_csr.rm == -					      IEEE754_RD); +			return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD); -		/* normalize in extended single precision */ -		while ((xm >> (SP_MBITS + 3)) == 0) { +		/* +		 * Normalize in extended single precision +		 */ +		while ((xm >> (SP_FBITS + 3)) == 0) {  			xm <<= 1;  			xe--;  		} -  	} -	SPNORMRET2(xs, xe, xm, "add", x, y); + +	return ieee754sp_format(xs, xe, xm);  } diff --git a/arch/mips/math-emu/sp_cmp.c b/arch/mips/math-emu/sp_cmp.c index 716cf37e246..addbccb2f55 100644 --- a/arch/mips/math-emu/sp_cmp.c +++ b/arch/mips/math-emu/sp_cmp.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,16 +16,16 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754sp.h" -int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cmp, int sig) +int ieee754sp_cmp(union ieee754sp x, union ieee754sp y, int cmp, int sig)  { +	int vx; +	int vy; +  	COMPXSP;  	COMPYSP; @@ -35,21 +33,21 @@ int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cmp, int sig)  	EXPLODEYSP;  	FLUSHXSP;  	FLUSHYSP; -	CLEARCX;	/* Even clear inexact flag here */ +	ieee754_clearcx();	/* Even clear inexact flag here */  	if (ieee754sp_isnan(x) || ieee754sp_isnan(y)) {  		if (sig || xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN) -			SETCX(IEEE754_INVALID_OPERATION); +			ieee754_setcx(IEEE754_INVALID_OPERATION);  		if (cmp & IEEE754_CUN)  			return 1;  		if (cmp & (IEEE754_CLT | IEEE754_CGT)) { -			if (sig && SETANDTESTCX(IEEE754_INVALID_OPERATION)) -				return ieee754si_xcpt(0, "fcmpf", x); +			if (sig && ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) +				return 0;  		}  		return 0;  	} else { -		int vx = x.bits; -		int vy = y.bits; +		vx = x.bits; +		vy = y.bits;  		if (vx < 0)  			vx = -vx ^ SP_SIGN_BIT; diff --git a/arch/mips/math-emu/sp_div.c b/arch/mips/math-emu/sp_div.c index d7747928c95..721f317aa87 100644 --- a/arch/mips/math-emu/sp_div.c +++ b/arch/mips/math-emu/sp_div.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,23 +16,24 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754sp.h" -ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y) +union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y)  { +	unsigned rm; +	int re; +	unsigned bm; +  	COMPXSP;  	COMPYSP;  	EXPLODEXSP;  	EXPLODEYSP; -	CLEARCX; +	ieee754_clearcx();  	FLUSHXSP;  	FLUSHYSP; @@ -51,8 +50,8 @@ ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y)  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754sp_nanxcpt(ieee754sp_indef(), "div", x, y); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754sp_nanxcpt(ieee754sp_indef());  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -68,12 +67,12 @@ ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y)  		return x; -		/* Infinity handling -		 */ - +	/* +	 * Infinity handling +	 */  	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754sp_indef();  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): @@ -85,17 +84,17 @@ ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y)  	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):  		return ieee754sp_inf(xs ^ ys); -		/* Zero handling -		 */ - +	/* +	 * Zero handling +	 */  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754sp_indef();  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):  	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): -		SETCX(IEEE754_ZERO_DIVIDE); -		return ieee754sp_xcpt(ieee754sp_inf(xs ^ ys), "div", x, y); +		ieee754_setcx(IEEE754_ZERO_DIVIDE); +		return ieee754sp_inf(xs ^ ys);  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): @@ -122,35 +121,33 @@ ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y)  	xm <<= 3;  	ym <<= 3; -	{ -		/* now the dirty work */ - -		unsigned rm = 0; -		int re = xe - ye; -		unsigned bm; - -		for (bm = SP_MBIT(SP_MBITS + 2); bm; bm >>= 1) { -			if (xm >= ym) { -				xm -= ym; -				rm |= bm; -				if (xm == 0) -					break; -			} -			xm <<= 1; -		} -		rm <<= 1; -		if (xm) -			rm |= 1;	/* have remainder, set sticky */ +	/* now the dirty work */ -		assert(rm); +	rm = 0; +	re = xe - ye; -		/* normalise rm to rounding precision ? -		 */ -		while ((rm >> (SP_MBITS + 3)) == 0) { -			rm <<= 1; -			re--; +	for (bm = SP_MBIT(SP_FBITS + 2); bm; bm >>= 1) { +		if (xm >= ym) { +			xm -= ym; +			rm |= bm; +			if (xm == 0) +				break;  		} +		xm <<= 1; +	} + +	rm <<= 1; +	if (xm) +		rm |= 1;	/* have remainder, set sticky */ -		SPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y); +	assert(rm); + +	/* normalise rm to rounding precision ? +	 */ +	while ((rm >> (SP_FBITS + 3)) == 0) { +		rm <<= 1; +		re--;  	} + +	return ieee754sp_format(xs == ys ? 0 : 1, re, rm);  } diff --git a/arch/mips/math-emu/sp_fdp.c b/arch/mips/math-emu/sp_fdp.c index e1515aae016..1b266fb1697 100644 --- a/arch/mips/math-emu/sp_fdp.c +++ b/arch/mips/math-emu/sp_fdp.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,59 +16,61 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754sp.h" +#include "ieee754dp.h" -ieee754sp ieee754sp_fdp(ieee754dp x) +union ieee754sp ieee754sp_fdp(union ieee754dp x)  { +	u32 rm; +  	COMPXDP; -	ieee754sp nan; +	union ieee754sp nan;  	EXPLODEXDP; -	CLEARCX; +	ieee754_clearcx();  	FLUSHXDP;  	switch (xc) {  	case IEEE754_CLASS_SNAN: -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754sp_nanxcpt(ieee754sp_indef(), "fdp"); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754sp_nanxcpt(ieee754sp_indef()); +  	case IEEE754_CLASS_QNAN:  		nan = buildsp(xs, SP_EMAX + 1 + SP_EBIAS, (u32) -				(xm >> (DP_MBITS - SP_MBITS))); +				(xm >> (DP_FBITS - SP_FBITS)));  		if (!ieee754sp_isnan(nan))  			nan = ieee754sp_indef(); -		return ieee754sp_nanxcpt(nan, "fdp", x); +		return ieee754sp_nanxcpt(nan); +  	case IEEE754_CLASS_INF:  		return ieee754sp_inf(xs); +  	case IEEE754_CLASS_ZERO:  		return ieee754sp_zero(xs); +  	case IEEE754_CLASS_DNORM:  		/* can't possibly be sp representable */ -		SETCX(IEEE754_UNDERFLOW); -		SETCX(IEEE754_INEXACT); -		if ((ieee754_csr.rm == IEEE754_RU && !xs) || -				(ieee754_csr.rm == IEEE754_RD && xs)) -			return ieee754sp_xcpt(ieee754sp_mind(xs), "fdp", x); -		return ieee754sp_xcpt(ieee754sp_zero(xs), "fdp", x); +		ieee754_setcx(IEEE754_UNDERFLOW); +		ieee754_setcx(IEEE754_INEXACT); +		if ((ieee754_csr.rm == FPU_CSR_RU && !xs) || +				(ieee754_csr.rm == FPU_CSR_RD && xs)) +			return ieee754sp_mind(xs); +		return ieee754sp_zero(xs); +  	case IEEE754_CLASS_NORM:  		break;  	} -	{ -		u32 rm; - -		/* convert from DP_MBITS to SP_MBITS+3 with sticky right shift -		 */ -		rm = (xm >> (DP_MBITS - (SP_MBITS + 3))) | -		    ((xm << (64 - (DP_MBITS - (SP_MBITS + 3)))) != 0); +	/* +	 * Convert from DP_FBITS to SP_FBITS+3 with sticky right shift. +	 */ +	rm = (xm >> (DP_FBITS - (SP_FBITS + 3))) | +	     ((xm << (64 - (DP_FBITS - (SP_FBITS + 3)))) != 0); -		SPNORMRET1(xs, xe, rm, "fdp", x); -	} +	return ieee754sp_format(xs, xe, rm);  } diff --git a/arch/mips/math-emu/sp_fint.c b/arch/mips/math-emu/sp_fint.c index 9694d6c016c..d5d8495b2cc 100644 --- a/arch/mips/math-emu/sp_fint.c +++ b/arch/mips/math-emu/sp_fint.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,21 +16,18 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754sp.h" -ieee754sp ieee754sp_fint(int x) +union ieee754sp ieee754sp_fint(int x)  {  	unsigned xm;  	int xe;  	int xs; -	CLEARCX; +	ieee754_clearcx();  	if (x == 0)  		return ieee754sp_zero(0); @@ -50,30 +45,21 @@ ieee754sp ieee754sp_fint(int x)  	} else {  		xm = x;  	} -	xe = SP_MBITS + 3; +	xe = SP_FBITS + 3; -	if (xm >> (SP_MBITS + 1 + 3)) { +	if (xm >> (SP_FBITS + 1 + 3)) {  		/* shunt out overflow bits  		 */ -		while (xm >> (SP_MBITS + 1 + 3)) { +		while (xm >> (SP_FBITS + 1 + 3)) {  			SPXSRSX1();  		}  	} else {  		/* normalize in grs extended single precision  		 */ -		while ((xm >> (SP_MBITS + 3)) == 0) { +		while ((xm >> (SP_FBITS + 3)) == 0) {  			xm <<= 1;  			xe--;  		}  	} -	SPNORMRET1(xs, xe, xm, "fint", x); -} - - -ieee754sp ieee754sp_funs(unsigned int u) -{ -	if ((int) u < 0) -		return ieee754sp_add(ieee754sp_1e31(), -				     ieee754sp_fint(u & ~(1 << 31))); -	return ieee754sp_fint(u); +	return ieee754sp_format(xs, xe, xm);  } diff --git a/arch/mips/math-emu/sp_flong.c b/arch/mips/math-emu/sp_flong.c index 16a651f2986..012e30ce758 100644 --- a/arch/mips/math-emu/sp_flong.c +++ b/arch/mips/math-emu/sp_flong.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,21 +16,18 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754sp.h" -ieee754sp ieee754sp_flong(s64 x) +union ieee754sp ieee754sp_flong(s64 x)  {  	u64 xm;		/* <--- need 64-bit mantissa temp */  	int xe;  	int xs; -	CLEARCX; +	ieee754_clearcx();  	if (x == 0)  		return ieee754sp_zero(0); @@ -50,29 +45,20 @@ ieee754sp ieee754sp_flong(s64 x)  	} else {  		xm = x;  	} -	xe = SP_MBITS + 3; +	xe = SP_FBITS + 3; -	if (xm >> (SP_MBITS + 1 + 3)) { +	if (xm >> (SP_FBITS + 1 + 3)) {  		/* shunt out overflow bits  		 */ -		while (xm >> (SP_MBITS + 1 + 3)) { +		while (xm >> (SP_FBITS + 1 + 3)) {  			SPXSRSX1();  		}  	} else {  		/* normalize in grs extended single precision */ -		while ((xm >> (SP_MBITS + 3)) == 0) { +		while ((xm >> (SP_FBITS + 3)) == 0) {  			xm <<= 1;  			xe--;  		}  	} -	SPNORMRET1(xs, xe, xm, "sp_flong", x); -} - - -ieee754sp ieee754sp_fulong(u64 u) -{ -	if ((s64) u < 0) -		return ieee754sp_add(ieee754sp_1e63(), -				     ieee754sp_flong(u & ~(1ULL << 63))); -	return ieee754sp_flong(u); +	return ieee754sp_format(xs, xe, xm);  } diff --git a/arch/mips/math-emu/sp_frexp.c b/arch/mips/math-emu/sp_frexp.c deleted file mode 100644 index 5bc993c3004..00000000000 --- a/arch/mips/math-emu/sp_frexp.c +++ /dev/null @@ -1,52 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. - * - * ######################################################################## - * - *  This program is free software; you can distribute it and/or modify it - *  under the terms of the GNU General Public License (Version 2) as - *  published by the Free Software Foundation. - * - *  This program is distributed in the hope it will be useful, but WITHOUT - *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License - *  for more details. - * - *  You should have received a copy of the GNU General Public License along - *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -/* close to ieeep754sp_logb -*/ -ieee754sp ieee754sp_frexp(ieee754sp x, int *eptr) -{ -	COMPXSP; -	CLEARCX; -	EXPLODEXSP; - -	switch (xc) { -	case IEEE754_CLASS_SNAN: -	case IEEE754_CLASS_QNAN: -	case IEEE754_CLASS_INF: -	case IEEE754_CLASS_ZERO: -		*eptr = 0; -		return x; -	case IEEE754_CLASS_DNORM: -		SPDNORMX; -		break; -	case IEEE754_CLASS_NORM: -		break; -	} -	*eptr = xe + 1; -	return buildsp(xs, -1 + SP_EBIAS, xm & ~SP_HIDDEN_BIT); -} diff --git a/arch/mips/math-emu/sp_logb.c b/arch/mips/math-emu/sp_logb.c deleted file mode 100644 index 9c14e0c75bd..00000000000 --- a/arch/mips/math-emu/sp_logb.c +++ /dev/null @@ -1,53 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. - * - * ######################################################################## - * - *  This program is free software; you can distribute it and/or modify it - *  under the terms of the GNU General Public License (Version 2) as - *  published by the Free Software Foundation. - * - *  This program is distributed in the hope it will be useful, but WITHOUT - *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License - *  for more details. - * - *  You should have received a copy of the GNU General Public License along - *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -ieee754sp ieee754sp_logb(ieee754sp x) -{ -	COMPXSP; - -	CLEARCX; - -	EXPLODEXSP; - -	switch (xc) { -	case IEEE754_CLASS_SNAN: -		return ieee754sp_nanxcpt(x, "logb", x); -	case IEEE754_CLASS_QNAN: -		return x; -	case IEEE754_CLASS_INF: -		return ieee754sp_inf(0); -	case IEEE754_CLASS_ZERO: -		return ieee754sp_inf(1); -	case IEEE754_CLASS_DNORM: -		SPDNORMX; -		break; -	case IEEE754_CLASS_NORM: -		break; -	} -	return ieee754sp_fint(xe); -} diff --git a/arch/mips/math-emu/sp_modf.c b/arch/mips/math-emu/sp_modf.c deleted file mode 100644 index 25a0fbaa055..00000000000 --- a/arch/mips/math-emu/sp_modf.c +++ /dev/null @@ -1,79 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. - * - * ######################################################################## - * - *  This program is free software; you can distribute it and/or modify it - *  under the terms of the GNU General Public License (Version 2) as - *  published by the Free Software Foundation. - * - *  This program is distributed in the hope it will be useful, but WITHOUT - *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License - *  for more details. - * - *  You should have received a copy of the GNU General Public License along - *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -/* modf function is always exact for a finite number -*/ -ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp *ip) -{ -	COMPXSP; - -	CLEARCX; - -	EXPLODEXSP; - -	switch (xc) { -	case IEEE754_CLASS_SNAN: -	case IEEE754_CLASS_QNAN: -	case IEEE754_CLASS_INF: -	case IEEE754_CLASS_ZERO: -		*ip = x; -		return x; -	case IEEE754_CLASS_DNORM: -		/* far to small */ -		*ip = ieee754sp_zero(xs); -		return x; -	case IEEE754_CLASS_NORM: -		break; -	} -	if (xe < 0) { -		*ip = ieee754sp_zero(xs); -		return x; -	} -	if (xe >= SP_MBITS) { -		*ip = x; -		return ieee754sp_zero(xs); -	} -	/* generate ipart mantissa by clearing bottom bits -	 */ -	*ip = buildsp(xs, xe + SP_EBIAS, -		      ((xm >> (SP_MBITS - xe)) << (SP_MBITS - xe)) & -		      ~SP_HIDDEN_BIT); - -	/* generate fpart mantissa by clearing top bits -	 * and normalizing (must be able to normalize) -	 */ -	xm = (xm << (32 - (SP_MBITS - xe))) >> (32 - (SP_MBITS - xe)); -	if (xm == 0) -		return ieee754sp_zero(xs); - -	while ((xm >> SP_MBITS) == 0) { -		xm <<= 1; -		xe--; -	} -	return buildsp(xs, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT); -} diff --git a/arch/mips/math-emu/sp_mul.c b/arch/mips/math-emu/sp_mul.c index fa4675cf2aa..890c13a2965 100644 --- a/arch/mips/math-emu/sp_mul.c +++ b/arch/mips/math-emu/sp_mul.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,23 +16,32 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754sp.h" -ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y) +union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y)  { +	int re; +	int rs; +	unsigned rm; +	unsigned short lxm; +	unsigned short hxm; +	unsigned short lym; +	unsigned short hym; +	unsigned lrm; +	unsigned hrm; +	unsigned t; +	unsigned at; +  	COMPXSP;  	COMPYSP;  	EXPLODEXSP;  	EXPLODEYSP; -	CLEARCX; +	ieee754_clearcx();  	FLUSHXSP;  	FLUSHYSP; @@ -51,8 +58,8 @@ ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y)  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754sp_nanxcpt(ieee754sp_indef(), "mul", x, y); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754sp_nanxcpt(ieee754sp_indef());  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -68,12 +75,13 @@ ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y)  		return x; -		/* Infinity handling */ - +	/* +	 * Infinity handling +	 */  	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754sp_xcpt(ieee754sp_indef(), "mul", x, y); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754sp_indef();  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):  	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): @@ -108,63 +116,50 @@ ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y)  	assert(xm & SP_HIDDEN_BIT);  	assert(ym & SP_HIDDEN_BIT); -	{ -		int re = xe + ye; -		int rs = xs ^ ys; -		unsigned rm; - -		/* shunt to top of word */ -		xm <<= 32 - (SP_MBITS + 1); -		ym <<= 32 - (SP_MBITS + 1); - -		/* multiply 32bits xm,ym to give high 32bits rm with stickness -		 */ -		{ -			unsigned short lxm = xm & 0xffff; -			unsigned short hxm = xm >> 16; -			unsigned short lym = ym & 0xffff; -			unsigned short hym = ym >> 16; -			unsigned lrm; -			unsigned hrm; - -			lrm = lxm * lym;	/* 16 * 16 => 32 */ -			hrm = hxm * hym;	/* 16 * 16 => 32 */ - -			{ -				unsigned t = lxm * hym; /* 16 * 16 => 32 */ -				{ -					unsigned at = lrm + (t << 16); -					hrm += at < lrm; -					lrm = at; -				} -				hrm = hrm + (t >> 16); -			} - -			{ -				unsigned t = hxm * lym; /* 16 * 16 => 32 */ -				{ -					unsigned at = lrm + (t << 16); -					hrm += at < lrm; -					lrm = at; -				} -				hrm = hrm + (t >> 16); -			} -			rm = hrm | (lrm != 0); -		} - -		/* -		 * sticky shift down to normal rounding precision -		 */ -		if ((int) rm < 0) { -			rm = (rm >> (32 - (SP_MBITS + 1 + 3))) | -			    ((rm << (SP_MBITS + 1 + 3)) != 0); -			re++; -		} else { -			rm = (rm >> (32 - (SP_MBITS + 1 + 3 + 1))) | -			    ((rm << (SP_MBITS + 1 + 3 + 1)) != 0); -		} -		assert(rm & (SP_HIDDEN_BIT << 3)); - -		SPNORMRET2(rs, re, rm, "mul", x, y); +	re = xe + ye; +	rs = xs ^ ys; + +	/* shunt to top of word */ +	xm <<= 32 - (SP_FBITS + 1); +	ym <<= 32 - (SP_FBITS + 1); + +	/* +	 * Multiply 32 bits xm, ym to give high 32 bits rm with stickness. +	 */ +	lxm = xm & 0xffff; +	hxm = xm >> 16; +	lym = ym & 0xffff; +	hym = ym >> 16; + +	lrm = lxm * lym;	/* 16 * 16 => 32 */ +	hrm = hxm * hym;	/* 16 * 16 => 32 */ + +	t = lxm * hym; /* 16 * 16 => 32 */ +	at = lrm + (t << 16); +	hrm += at < lrm; +	lrm = at; +	hrm = hrm + (t >> 16); + +	t = hxm * lym; /* 16 * 16 => 32 */ +	at = lrm + (t << 16); +	hrm += at < lrm; +	lrm = at; +	hrm = hrm + (t >> 16); + +	rm = hrm | (lrm != 0); + +	/* +	 * Sticky shift down to normal rounding precision. +	 */ +	if ((int) rm < 0) { +		rm = (rm >> (32 - (SP_FBITS + 1 + 3))) | +		    ((rm << (SP_FBITS + 1 + 3)) != 0); +		re++; +	} else { +		rm = (rm >> (32 - (SP_FBITS + 1 + 3 + 1))) | +		     ((rm << (SP_FBITS + 1 + 3 + 1)) != 0);  	} +	assert(rm & (SP_HIDDEN_BIT << 3)); + +	return ieee754sp_format(rs, re, rm);  } diff --git a/arch/mips/math-emu/sp_scalb.c b/arch/mips/math-emu/sp_scalb.c deleted file mode 100644 index dd76196984c..00000000000 --- a/arch/mips/math-emu/sp_scalb.c +++ /dev/null @@ -1,57 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. - * - * ######################################################################## - * - *  This program is free software; you can distribute it and/or modify it - *  under the terms of the GNU General Public License (Version 2) as - *  published by the Free Software Foundation. - * - *  This program is distributed in the hope it will be useful, but WITHOUT - *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License - *  for more details. - * - *  You should have received a copy of the GNU General Public License along - *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -ieee754sp ieee754sp_scalb(ieee754sp x, int n) -{ -	COMPXSP; - -	CLEARCX; - -	EXPLODEXSP; - -	switch (xc) { -	case IEEE754_CLASS_SNAN: -		return ieee754sp_nanxcpt(x, "scalb", x, n); -	case IEEE754_CLASS_QNAN: -	case IEEE754_CLASS_INF: -	case IEEE754_CLASS_ZERO: -		return x; -	case IEEE754_CLASS_DNORM: -		SPDNORMX; -		break; -	case IEEE754_CLASS_NORM: -		break; -	} -	SPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n); -} - - -ieee754sp ieee754sp_ldexp(ieee754sp x, int n) -{ -	return ieee754sp_scalb(x, n); -} diff --git a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c index ae4fcfafd85..f1ffaa9a17e 100644 --- a/arch/mips/math-emu/sp_simple.c +++ b/arch/mips/math-emu/sp_simple.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,33 +16,17 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754sp.h" -int ieee754sp_finite(ieee754sp x) -{ -	return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS; -} - -ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y) -{ -	CLEARCX; -	SPSIGN(x) = SPSIGN(y); -	return x; -} - - -ieee754sp ieee754sp_neg(ieee754sp x) +union ieee754sp ieee754sp_neg(union ieee754sp x)  {  	COMPXSP;  	EXPLODEXSP; -	CLEARCX; +	ieee754_clearcx();  	FLUSHXSP;  	/* @@ -55,30 +37,29 @@ ieee754sp ieee754sp_neg(ieee754sp x)  	SPSIGN(x) ^= 1;  	if (xc == IEEE754_CLASS_SNAN) { -		ieee754sp y = ieee754sp_indef(); -		SETCX(IEEE754_INVALID_OPERATION); +		union ieee754sp y = ieee754sp_indef(); +		ieee754_setcx(IEEE754_INVALID_OPERATION);  		SPSIGN(y) = SPSIGN(x); -		return ieee754sp_nanxcpt(y, "neg"); +		return ieee754sp_nanxcpt(y);  	}  	return x;  } - -ieee754sp ieee754sp_abs(ieee754sp x) +union ieee754sp ieee754sp_abs(union ieee754sp x)  {  	COMPXSP;  	EXPLODEXSP; -	CLEARCX; +	ieee754_clearcx();  	FLUSHXSP;  	/* Clear sign ALWAYS, irrespective of NaN */  	SPSIGN(x) = 0;  	if (xc == IEEE754_CLASS_SNAN) { -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754sp_nanxcpt(ieee754sp_indef(), "abs"); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754sp_nanxcpt(ieee754sp_indef());  	}  	return x; diff --git a/arch/mips/math-emu/sp_sqrt.c b/arch/mips/math-emu/sp_sqrt.c index fed20175f5f..b7c098a86f9 100644 --- a/arch/mips/math-emu/sp_sqrt.c +++ b/arch/mips/math-emu/sp_sqrt.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,15 +16,12 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754sp.h" -ieee754sp ieee754sp_sqrt(ieee754sp x) +union ieee754sp ieee754sp_sqrt(union ieee754sp x)  {  	int ix, s, q, m, t, i;  	unsigned int r; @@ -35,34 +30,38 @@ ieee754sp ieee754sp_sqrt(ieee754sp x)  	/* take care of Inf and NaN */  	EXPLODEXSP; -	CLEARCX; +	ieee754_clearcx();  	FLUSHXSP;  	/* x == INF or NAN? */  	switch (xc) {  	case IEEE754_CLASS_QNAN:  		/* sqrt(Nan) = Nan */ -		return ieee754sp_nanxcpt(x, "sqrt"); +		return ieee754sp_nanxcpt(x); +  	case IEEE754_CLASS_SNAN: -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt"); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754sp_nanxcpt(ieee754sp_indef()); +  	case IEEE754_CLASS_ZERO:  		/* sqrt(0) = 0 */  		return x; +  	case IEEE754_CLASS_INF:  		if (xs) {  			/* sqrt(-Inf) = Nan */ -			SETCX(IEEE754_INVALID_OPERATION); -			return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt"); +			ieee754_setcx(IEEE754_INVALID_OPERATION); +			return ieee754sp_nanxcpt(ieee754sp_indef());  		}  		/* sqrt(+Inf) = Inf */  		return x; +  	case IEEE754_CLASS_DNORM:  	case IEEE754_CLASS_NORM:  		if (xs) {  			/* sqrt(-x) = Nan */ -			SETCX(IEEE754_INVALID_OPERATION); -			return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt"); +			ieee754_setcx(IEEE754_INVALID_OPERATION); +			return ieee754sp_nanxcpt(ieee754sp_indef());  		}  		break;  	} @@ -99,12 +98,12 @@ ieee754sp ieee754sp_sqrt(ieee754sp x)  	}  	if (ix != 0) { -		SETCX(IEEE754_INEXACT); +		ieee754_setcx(IEEE754_INEXACT);  		switch (ieee754_csr.rm) { -		case IEEE754_RP: +		case FPU_CSR_RU:  			q += 2;  			break; -		case IEEE754_RN: +		case FPU_CSR_RN:  			q += (q & 1);  			break;  		} diff --git a/arch/mips/math-emu/sp_sub.c b/arch/mips/math-emu/sp_sub.c index e595c6f3d0b..8592e49032b 100644 --- a/arch/mips/math-emu/sp_sub.c +++ b/arch/mips/math-emu/sp_sub.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,23 +16,22 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754sp.h" -ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y) +union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y)  { +	int s; +  	COMPXSP;  	COMPYSP;  	EXPLODEXSP;  	EXPLODEYSP; -	CLEARCX; +	ieee754_clearcx();  	FLUSHXSP;  	FLUSHYSP; @@ -51,8 +48,8 @@ ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):  	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754sp_nanxcpt(ieee754sp_indef(), "sub", x, y); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754sp_nanxcpt(ieee754sp_indef());  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -68,14 +65,14 @@ ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)  		return x; -		/* Infinity handling -		 */ - +	/* +	 * Infinity handling +	 */  	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):  		if (xs != ys)  			return x; -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754sp_xcpt(ieee754sp_indef(), "sub", x, y); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754sp_indef();  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):  	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): @@ -87,15 +84,14 @@ ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)  	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):  		return x; -		/* Zero handling -		 */ - +	/* +	 * Zero handling +	 */  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):  		if (xs != ys)  			return x;  		else -			return ieee754sp_zero(ieee754_csr.rm == -					      IEEE754_RD); +			return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);  	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):  	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): @@ -104,7 +100,7 @@ ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):  	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):  		/* quick fix up */ -		DPSIGN(y) ^= 1; +		SPSIGN(y) ^= 1;  		return y;  	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): @@ -133,14 +129,16 @@ ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)  	ym <<= 3;  	if (xe > ye) { -		/* have to shift y fraction right to align +		/* +		 * have to shift y fraction right to align  		 */ -		int s = xe - ye; +		s = xe - ye;  		SPXSRSYn(s);  	} else if (ye > xe) { -		/* have to shift x fraction right to align +		/* +		 * have to shift x fraction right to align  		 */ -		int s = ye - xe; +		s = ye - xe;  		SPXSRSXn(s);  	}  	assert(xe == ye); @@ -153,7 +151,7 @@ ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)  		xe = xe;  		xs = xs; -		if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */ +		if (xm >> (SP_FBITS + 1 + 3)) { /* carry out */  			SPXSRSX1();	/* shift preserving sticky */  		}  	} else { @@ -167,17 +165,18 @@ ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)  			xs = ys;  		}  		if (xm == 0) { -			if (ieee754_csr.rm == IEEE754_RD) +			if (ieee754_csr.rm == FPU_CSR_RD)  				return ieee754sp_zero(1);	/* round negative inf. => sign = -1 */  			else  				return ieee754sp_zero(0);	/* other round modes   => sign = 1 */  		}  		/* normalize to rounding precision  		 */ -		while ((xm >> (SP_MBITS + 3)) == 0) { +		while ((xm >> (SP_FBITS + 3)) == 0) {  			xm <<= 1;  			xe--;  		}  	} -	SPNORMRET2(xs, xe, xm, "sub", x, y); + +	return ieee754sp_format(xs, xe, xm);  } diff --git a/arch/mips/math-emu/sp_tint.c b/arch/mips/math-emu/sp_tint.c index 0fe9acc7716..091299a3179 100644 --- a/arch/mips/math-emu/sp_tint.c +++ b/arch/mips/math-emu/sp_tint.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,20 +16,21 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ - -#include <linux/kernel.h>  #include "ieee754sp.h" -int ieee754sp_tint(ieee754sp x) +int ieee754sp_tint(union ieee754sp x)  { +	u32 residue; +	int round; +	int sticky; +	int odd; +  	COMPXSP; -	CLEARCX; +	ieee754_clearcx();  	EXPLODEXSP;  	FLUSHXSP; @@ -40,10 +39,12 @@ int ieee754sp_tint(ieee754sp x)  	case IEEE754_CLASS_SNAN:  	case IEEE754_CLASS_QNAN:  	case IEEE754_CLASS_INF: -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754si_indef(); +  	case IEEE754_CLASS_ZERO:  		return 0; +  	case IEEE754_CLASS_DNORM:  	case IEEE754_CLASS_NORM:  		break; @@ -54,18 +55,13 @@ int ieee754sp_tint(ieee754sp x)  			return -0x80000000;  		/* Set invalid. We will only use overflow for floating  		   point overflow */ -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754si_indef();  	}  	/* oh gawd */ -	if (xe > SP_MBITS) { -		xm <<= xe - SP_MBITS; +	if (xe > SP_FBITS) { +		xm <<= xe - SP_FBITS;  	} else { -		u32 residue; -		int round; -		int sticky; -		int odd; -  		if (xe < -1) {  			residue = xm;  			round = 0; @@ -76,51 +72,38 @@ int ieee754sp_tint(ieee754sp x)  			* so we do it in two steps. Be aware that xe  			* may be -1 */  			residue = xm << (xe + 1); -			residue <<= 31 - SP_MBITS; +			residue <<= 31 - SP_FBITS;  			round = (residue >> 31) != 0;  			sticky = (residue << 1) != 0; -			xm >>= SP_MBITS - xe; +			xm >>= SP_FBITS - xe;  		}  		odd = (xm & 0x1) != 0x0;  		switch (ieee754_csr.rm) { -		case IEEE754_RN: +		case FPU_CSR_RN:  			if (round && (sticky || odd))  				xm++;  			break; -		case IEEE754_RZ: +		case FPU_CSR_RZ:  			break; -		case IEEE754_RU:	/* toward +Infinity */ +		case FPU_CSR_RU:	/* toward +Infinity */  			if ((round || sticky) && !xs)  				xm++;  			break; -		case IEEE754_RD:	/* toward -Infinity */ +		case FPU_CSR_RD:	/* toward -Infinity */  			if ((round || sticky) && xs)  				xm++;  			break;  		}  		if ((xm >> 31) != 0) {  			/* This can happen after rounding */ -			SETCX(IEEE754_INVALID_OPERATION); -			return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x); +			ieee754_setcx(IEEE754_INVALID_OPERATION); +			return ieee754si_indef();  		}  		if (round || sticky) -			SETCX(IEEE754_INEXACT); +			ieee754_setcx(IEEE754_INEXACT);  	}  	if (xs)  		return -xm;  	else  		return xm;  } - - -unsigned int ieee754sp_tuns(ieee754sp x) -{ -	ieee754sp hb = ieee754sp_1e31(); - -	/* what if x < 0 ?? */ -	if (ieee754sp_lt(x, hb)) -		return (unsigned) ieee754sp_tint(x); - -	return (unsigned) ieee754sp_tint(ieee754sp_sub(x, hb)) | -	    ((unsigned) 1 << 31); -} diff --git a/arch/mips/math-emu/sp_tlong.c b/arch/mips/math-emu/sp_tlong.c index d0ca6e22be2..9f3c742c1ce 100644 --- a/arch/mips/math-emu/sp_tlong.c +++ b/arch/mips/math-emu/sp_tlong.c @@ -5,8 +5,6 @@   * MIPS floating point support   * Copyright (C) 1994-2000 Algorithmics Ltd.   * - * ######################################################################## - *   *  This program is free software; you can distribute it and/or modify it   *  under the terms of the GNU General Public License (Version 2) as   *  published by the Free Software Foundation. @@ -18,19 +16,22 @@   *   *  You should have received a copy of the GNU General Public License along   *  with this program; if not, write to the Free Software Foundation, Inc., - *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.   */ -  #include "ieee754sp.h" +#include "ieee754dp.h" -s64 ieee754sp_tlong(ieee754sp x) +s64 ieee754sp_tlong(union ieee754sp x)  { +	u32 residue; +	int round; +	int sticky; +	int odd; +  	COMPXDP;		/* <-- need 64-bit mantissa tmp */ -	CLEARCX; +	ieee754_clearcx();  	EXPLODEXSP;  	FLUSHXSP; @@ -39,10 +40,12 @@ s64 ieee754sp_tlong(ieee754sp x)  	case IEEE754_CLASS_SNAN:  	case IEEE754_CLASS_QNAN:  	case IEEE754_CLASS_INF: -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754di_indef(); +  	case IEEE754_CLASS_ZERO:  		return 0; +  	case IEEE754_CLASS_DNORM:  	case IEEE754_CLASS_NORM:  		break; @@ -53,69 +56,51 @@ s64 ieee754sp_tlong(ieee754sp x)  			return -0x8000000000000000LL;  		/* Set invalid. We will only use overflow for floating  		   point overflow */ -		SETCX(IEEE754_INVALID_OPERATION); -		return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); +		ieee754_setcx(IEEE754_INVALID_OPERATION); +		return ieee754di_indef();  	}  	/* oh gawd */ -	if (xe > SP_MBITS) { -		xm <<= xe - SP_MBITS; -	} else if (xe < SP_MBITS) { -		u32 residue; -		int round; -		int sticky; -		int odd; - +	if (xe > SP_FBITS) { +		xm <<= xe - SP_FBITS; +	} else if (xe < SP_FBITS) {  		if (xe < -1) {  			residue = xm;  			round = 0;  			sticky = residue != 0;  			xm = 0;  		} else { -			residue = xm << (32 - SP_MBITS + xe); +			residue = xm << (32 - SP_FBITS + xe);  			round = (residue >> 31) != 0;  			sticky = (residue << 1) != 0; -			xm >>= SP_MBITS - xe; +			xm >>= SP_FBITS - xe;  		}  		odd = (xm & 0x1) != 0x0;  		switch (ieee754_csr.rm) { -		case IEEE754_RN: +		case FPU_CSR_RN:  			if (round && (sticky || odd))  				xm++;  			break; -		case IEEE754_RZ: +		case FPU_CSR_RZ:  			break; -		case IEEE754_RU:	/* toward +Infinity */ +		case FPU_CSR_RU:	/* toward +Infinity */  			if ((round || sticky) && !xs)  				xm++;  			break; -		case IEEE754_RD:	/* toward -Infinity */ +		case FPU_CSR_RD:	/* toward -Infinity */  			if ((round || sticky) && xs)  				xm++;  			break;  		}  		if ((xm >> 63) != 0) {  			/* This can happen after rounding */ -			SETCX(IEEE754_INVALID_OPERATION); -			return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); +			ieee754_setcx(IEEE754_INVALID_OPERATION); +			return ieee754di_indef();  		}  		if (round || sticky) -			SETCX(IEEE754_INEXACT); +			ieee754_setcx(IEEE754_INEXACT);  	}  	if (xs)  		return -xm;  	else  		return xm;  } - - -u64 ieee754sp_tulong(ieee754sp x) -{ -	ieee754sp hb = ieee754sp_1e63(); - -	/* what if x < 0 ?? */ -	if (ieee754sp_lt(x, hb)) -		return (u64) ieee754sp_tlong(x); - -	return (u64) ieee754sp_tlong(ieee754sp_sub(x, hb)) | -	    (1ULL << 63); -}  | 
