--- ../linux-sharp-c1000+nwfpe/arch/arm/nwfpe/ARM-gcc.h 2005-05-03 22:49:08.000000000 +0900 +++ linux/arch/arm/nwfpe/ARM-gcc.h 2006-04-05 18:42:24.103364440 +0900 @@ -16,7 +16,7 @@ to the same as `int'. ------------------------------------------------------------------------------- */ -typedef char flag; +typedef int flag; typedef unsigned char uint8; typedef signed char int8; typedef int uint16; @@ -70,51 +70,3 @@ */ #define INLINE extern __inline__ - -/* For use as a GCC soft-float library we need some special function names. */ - -#ifdef __LIBFLOAT__ - -/* Some 32-bit ops can be mapped straight across by just changing the name. */ -#define float32_add __addsf3 -#define float32_sub __subsf3 -#define float32_mul __mulsf3 -#define float32_div __divsf3 -#define int32_to_float32 __floatsisf -#define float32_to_int32_round_to_zero __fixsfsi -#define float32_to_uint32_round_to_zero __fixunssfsi - -/* These ones go through the glue code. To avoid namespace pollution - we rename the internal functions too. */ -#define float32_eq ___float32_eq -#define float32_le ___float32_le -#define float32_lt ___float32_lt - -/* All the 64-bit ops have to go through the glue, so we pull the same - trick. */ -#define float64_add ___float64_add -#define float64_sub ___float64_sub -#define float64_mul ___float64_mul -#define float64_div ___float64_div -#define int32_to_float64 ___int32_to_float64 -#define float64_to_int32_round_to_zero ___float64_to_int32_round_to_zero -#define float64_to_uint32_round_to_zero ___float64_to_uint32_round_to_zero -#define float64_to_float32 ___float64_to_float32 -#define float32_to_float64 ___float32_to_float64 -#define float64_eq ___float64_eq -#define float64_le ___float64_le -#define float64_lt ___float64_lt - -#if 0 -#define float64_add __adddf3 -#define float64_sub __subdf3 -#define float64_mul __muldf3 -#define float64_div __divdf3 -#define int32_to_float64 __floatsidf -#define float64_to_int32_round_to_zero __fixdfsi -#define float64_to_uint32_round_to_zero __fixunsdfsi -#define float64_to_float32 __truncdfsf2 -#define float32_to_float64 __extendsfdf2 -#endif - -#endif --- ../linux-sharp-c1000+nwfpe/arch/arm/nwfpe/Makefile 2005-05-03 22:49:08.000000000 +0900 +++ linux/arch/arm/nwfpe/Makefile 2006-04-05 18:42:24.103364440 +0900 @@ -17,12 +17,13 @@ obj-$(CONFIG_FPE_NWFPE) += nwfpe.o nwfpe-objs := fpa11.o fpa11_cpdo.o fpa11_cpdt.o fpa11_cprt.o \ - fpmodule.o fpopcode.o softfloat.o \ - single_cpdo.o double_cpdo.o + fpmodule.o fpopcode.o softfloat.o -ifeq ($(CONFIG_FPE_NWFPE_XP),y) -nwfpe-objs += extended_cpdo.o -endif +CFLAGS_fpa11.o := -fomit-frame-pointer +CFLAGS_fpa11_cpdo.o := -fomit-frame-pointer +CFLAGS_fpa11_cpdt.o := -fomit-frame-pointer +CFLAGS_fpa11_cprt.o := -fomit-frame-pointer +CFLAGS_softfloat.o := -fomit-frame-pointer ifeq ($(CONFIG_CPU_26),y) nwfpe-objs += entry26.o --- ../linux-sharp-c1000+nwfpe/arch/arm/nwfpe/double_cpdo.c 2005-05-03 22:49:08.000000000 +0900 +++ linux/arch/arm/nwfpe/double_cpdo.c 2006-04-05 18:42:24.103364440 +0900 @@ -19,10 +19,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "fpa11.h" -#include "softfloat.h" -#include "fpopcode.h" - union float64_components { float64 f64; unsigned int i[2]; @@ -40,37 +36,22 @@ float64 float64_pow(float64 rFn, float64 rFm); float64 float64_pol(float64 rFn, float64 rFm); -static float64 float64_rsf(float64 rFn, float64 rFm) +static inline float64 float64_rsf(float64 rFn, float64 rFm) { return float64_sub(rFm, rFn); } -static float64 float64_rdv(float64 rFn, float64 rFm) +static inline float64 float64_rdv(float64 rFn, float64 rFm) { return float64_div(rFm, rFn); } -static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = { - [ADF_CODE >> 20] = float64_add, - [MUF_CODE >> 20] = float64_mul, - [SUF_CODE >> 20] = float64_sub, - [RSF_CODE >> 20] = float64_rsf, - [DVF_CODE >> 20] = float64_div, - [RDF_CODE >> 20] = float64_rdv, - [RMF_CODE >> 20] = float64_rem, - - /* strictly, these opcodes should not be implemented */ - [FML_CODE >> 20] = float64_mul, - [FDV_CODE >> 20] = float64_div, - [FRD_CODE >> 20] = float64_rdv, -}; - -static float64 float64_mvf(float64 rFm) +static inline float64 float64_mvf(float64 rFm) { return rFm; } -static float64 float64_mnf(float64 rFm) +static inline float64 float64_mnf(float64 rFm) { union float64_components u; @@ -80,7 +61,7 @@ return u.f64; } -static float64 float64_abs(float64 rFm) +static inline float64 float64_abs(float64 rFm) { union float64_components u; @@ -90,19 +71,8 @@ return u.f64; } -static float64 (*const monadic_double[16])(float64 rFm) = { - [MVF_CODE >> 20] = float64_mvf, - [MNF_CODE >> 20] = float64_mnf, - [ABS_CODE >> 20] = float64_abs, - [RND_CODE >> 20] = float64_round_to_int, - [URD_CODE >> 20] = float64_round_to_int, - [SQT_CODE >> 20] = float64_sqrt, - [NRM_CODE >> 20] = float64_mvf, -}; - -unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd) +static inline unsigned int DoubleCPDO(FPA11 *fpa11, const unsigned int opcode, FPREG * rFd, const unsigned int nDest) { - FPA11 *fpa11 = GET_FPA11(); float64 rFm; unsigned int Fm, opc_mask_shift; @@ -124,7 +94,7 @@ } } - opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20; + opc_mask_shift = (opcode >> 20) & (MASK_ARITHMETIC_OPCODE >> 20); if (!MONADIC_INSTRUCTION(opcode)) { unsigned int Fn = getFn(opcode); float64 rFn; @@ -142,18 +112,104 @@ return 0; } - if (dyadic_double[opc_mask_shift]) { - rFd->fDouble = dyadic_double[opc_mask_shift](rFn, rFm); - } else { + switch (opc_mask_shift) { + case ADF_CODE >> 20: + rFd->fDouble = float64_add(rFn, rFm); + break; + + case MUF_CODE >> 20: + rFd->fDouble = float64_mul(rFn, rFm); + break; + + case SUF_CODE >> 20: + rFd->fDouble = float64_sub(rFn, rFm); + break; + + case RSF_CODE >> 20: + rFd->fDouble = float64_rsf(rFn, rFm); + break; + + case DVF_CODE >> 20: + rFd->fDouble = float64_div(rFn, rFm); + break; + + case RDF_CODE >> 20: + rFd->fDouble = float64_rdv(rFn, rFm); + break; + + case RMF_CODE >> 20: + rFd->fDouble = float64_rem(rFn, rFm); + break; + + case FML_CODE >> 20: + rFd->fDouble = float64_mul(rFn, rFm); + break; + + case FDV_CODE >> 20: + rFd->fDouble = float64_div(rFn, rFm); + break; + + case FRD_CODE >> 20: + rFd->fDouble = float64_rdv(rFn, rFm); + break; + + default: return 0; } } else { - if (monadic_double[opc_mask_shift]) { - rFd->fDouble = monadic_double[opc_mask_shift](rFm); - } else { + switch (opc_mask_shift) { + case MVF_CODE >> 20: + rFd->fDouble = float64_mvf(rFm); + break; + + case MNF_CODE >> 20: + rFd->fDouble = float64_mnf(rFm); + break; + + case ABS_CODE >> 20: + rFd->fDouble = float64_abs(rFm); + break; + + case RND_CODE >> 20: + rFd->fDouble = float64_round_to_int(rFm); + break; + + case URD_CODE >> 20: + rFd->fDouble = float64_round_to_int(rFm); + break; + + case SQT_CODE >> 20: + rFd->fDouble = float64_sqrt(rFm); + break; + + case NRM_CODE >> 20: + rFd->fDouble = float64_mvf(rFm); + break; + + default: return 0; } } + /* The CPDO functions used to always set the destination type + to be the same as their working size. */ + + /* If the operation succeeded, check to see if the result in the + destination register is the correct size. If not force it + to be. */ + + fpa11->fType[getFd(opcode)] = nDest; + +#ifdef CONFIG_FPE_NWFPE_XP + if (nDest != typeDouble) { + if (nDest == typeSingle) + rFd->fSingle = float64_to_float32(rFd->fDouble); + else + rFd->fExtended = float64_to_floatx80(rFd->fDouble); + } +#else + if (nDest != typeDouble) + rFd->fSingle = float64_to_float32(rFd->fDouble); +#endif return 1; } --- ../linux-sharp-c1000+nwfpe/arch/arm/nwfpe/entry.S 2005-05-03 22:49:08.000000000 +0900 +++ linux/arch/arm/nwfpe/entry.S 2006-04-05 18:42:24.104364288 +0900 @@ -71,26 +71,38 @@ .globl nwfpe_enter nwfpe_enter: mov r4, lr @ save the failure-return addresses - ldr ip, [r10, #112] @ get init_flag mov sl, sp @ we access the registers via 'sl' ldr r5, [sp, #60] @ get contents of PC; - cmp ip, #0 - bleq nwfpe_init_fpa sub r8, r5, #4 .Lx1: ldrt r0, [r8] @ get actual instruction into r0 emulate: - bl EmulateAll @ emulate the instruction + and r3, r0, #0xF00 + cmp r3, #0x200 + cmpne r3, #0x100 + movne pc, r4 @ no, reurn failure + and r3, r0, #0x0E000000 + cmp r3, #0x0E000000 + bne emulate_cpdt + tst r0, #0x10 + adr lr, emulate_end + beq EmulateCPDO + b EmulateCPRT + +emulate_cpdt: + cmp r3, #0x0C000000 + movne pc, r4 @ no, return failure + bl EmulateCPDT + +emulate_end: cmp r0, #0 @ was emulation successful moveq pc, r4 @ no, return failure next: .Lx2: ldrt r6, [r5], #4 @ get the next instruction and @ increment PC - - and r2, r6, #0x0F000000 @ test for FP insns + and r2, r6, #0x0E000000 @ test for FP insns teq r2, #0x0C000000 - teqne r2, #0x0D000000 teqne r2, #0x0E000000 movne pc, r9 @ return ok if not a fp insn --- ../linux-sharp-c1000+nwfpe/arch/arm/nwfpe/extended_cpdo.c 2005-05-03 22:49:08.000000000 +0900 +++ linux/arch/arm/nwfpe/extended_cpdo.c 2006-04-05 18:42:24.104364288 +0900 @@ -19,10 +19,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "fpa11.h" -#include "softfloat.h" -#include "fpopcode.h" - floatx80 floatx80_exp(floatx80 Fm); floatx80 floatx80_ln(floatx80 Fm); floatx80 floatx80_sin(floatx80 rFm); @@ -87,9 +83,8 @@ [NRM_CODE >> 20] = floatx80_mvf, }; -unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd) +static inline unsigned int ExtendedCPDO(FPA11 *fpa11, const unsigned int opcode, FPREG * rFd, const unsigned int nDest) { - FPA11 *fpa11 = GET_FPA11(); floatx80 rFm; unsigned int Fm, opc_mask_shift; @@ -150,5 +145,21 @@ } } + /* The CPDO functions used to always set the destination type + to be the same as their working size. */ + + /* If the operation succeeded, check to see if the result in the + destination register is the correct size. If not force it + to be. */ + + fpa11->fType[getFd(opcode)] = nDest; + + if (nDest != typeExtended) { + if (nDest == typeSingle) + rFd->fSingle = floatx80_to_float32(rFd->fExtended); + else + rFd->fDouble = floatx80_to_float64(rFd->fExtended); + } + return 1; } --- ../linux-sharp-c1000+nwfpe/arch/arm/nwfpe/fpa11.c 2005-05-03 22:49:08.000000000 +0900 +++ linux/arch/arm/nwfpe/fpa11.c 2006-04-05 18:42:24.104364288 +0900 @@ -28,16 +28,10 @@ #include -/* forward declarations */ -unsigned int EmulateCPDO(const unsigned int); -unsigned int EmulateCPDT(const unsigned int); -unsigned int EmulateCPRT(const unsigned int); - /* Reset the FPA11 chip. Called to initialize and reset the emulator. */ -void resetFPA11(void) +static void resetFPA11(FPA11 *fpa11) { int i; - FPA11 *fpa11 = GET_FPA11(); /* initialize the register type array */ for (i = 0; i <= 7; i++) { @@ -92,40 +86,15 @@ #endif } -void nwfpe_init_fpa(void) +void nwfpe_init_fpa(union fp_state *fp) { - FPA11 *fpa11 = GET_FPA11(); + FPA11 *fpa11 = (FPA11 *)fp; #ifdef NWFPE_DEBUG printk("NWFPE: setting up state.\n"); #endif - resetFPA11(); + memset(fpa11, 0, sizeof(FPA11)); + resetFPA11(fpa11); SetRoundingMode(ROUND_TO_NEAREST); SetRoundingPrecision(ROUND_EXTENDED); fpa11->initflag = 1; } - -/* Emulate the instruction in the opcode. */ -unsigned int EmulateAll(const unsigned int opcode) -{ -#ifdef NWFPE_DEBUG - printk("NWFPE: emulating opcode %08x\n", opcode); -#endif - - if (TEST_OPCODE(opcode, MASK_CPRT)) { - /* Emulate conversion opcodes. */ - /* Emulate register transfer opcodes. */ - /* Emulate comparison opcodes. */ - return EmulateCPRT(opcode); - } else if (TEST_OPCODE(opcode, MASK_CPDO)) { - /* Emulate monadic arithmetic opcodes. */ - /* Emulate dyadic arithmetic opcodes. */ - return EmulateCPDO(opcode); - } else if (TEST_OPCODE(opcode, MASK_CPDT)) { - /* Emulate load/store opcodes. */ - /* Emulate load/store multiple opcodes. */ - return EmulateCPDT(opcode); - } - - /* Invalid instruction detected. Return FALSE. */ - return 0; -} --- ../linux-sharp-c1000+nwfpe/arch/arm/nwfpe/fpa11.h 2005-05-03 22:49:08.000000000 +0900 +++ linux/arch/arm/nwfpe/fpa11.h 2006-04-05 18:42:24.104364288 +0900 @@ -86,7 +86,6 @@ initialised. */ } FPA11; -extern void resetFPA11(void); extern void SetRoundingMode(const unsigned int); extern void SetRoundingPrecision(const unsigned int); --- ../linux-sharp-c1000+nwfpe/arch/arm/nwfpe/fpa11_cpdo.c 2005-05-03 22:49:08.000000000 +0900 +++ linux/arch/arm/nwfpe/fpa11_cpdo.c 2006-04-05 18:42:24.105364136 +0900 @@ -22,16 +22,19 @@ #include "fpa11.h" #include "fpopcode.h" +#include "softfloat.h" -unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd); -unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd); -unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd); +#include "single_cpdo.c" +#include "double_cpdo.c" +#ifdef CONFIG_FPE_NWFPE_XP +#include "extended_cpdo.c" +#endif unsigned int EmulateCPDO(const unsigned int opcode) { FPA11 *fpa11 = GET_FPA11(); FPREG *rFd; - unsigned int nType, nDest, nRc; + unsigned int nType, nDest, Fm; /* Get the destination size. If not valid let Linux perform an invalid instruction trap. */ @@ -52,7 +55,7 @@ nType = fpa11->fType[getFn(opcode)]; if (!CONSTANT_FM(opcode)) { - register unsigned int Fm = getFm(opcode); + Fm = getFm(opcode); if (nType < fpa11->fType[Fm]) { nType = fpa11->fType[Fm]; } @@ -62,70 +65,17 @@ switch (nType) { case typeSingle: - nRc = SingleCPDO(opcode, rFd); - break; + return SingleCPDO(fpa11, opcode, rFd, nDest); + case typeDouble: - nRc = DoubleCPDO(opcode, rFd); - break; + return DoubleCPDO(fpa11, opcode, rFd, nDest); + #ifdef CONFIG_FPE_NWFPE_XP case typeExtended: - nRc = ExtendedCPDO(opcode, rFd); - break; + return ExtendedCPDO(fpa11, opcode, rFd, nDest); #endif - default: - nRc = 0; - } - - /* The CPDO functions used to always set the destination type - to be the same as their working size. */ - - if (nRc != 0) { - /* If the operation succeeded, check to see if the result in the - destination register is the correct size. If not force it - to be. */ - fpa11->fType[getFd(opcode)] = nDest; - -#ifdef CONFIG_FPE_NWFPE_XP - if (nDest != nType) { - switch (nDest) { - case typeSingle: - { - if (typeDouble == nType) - rFd->fSingle = float64_to_float32(rFd->fDouble); - else - rFd->fSingle = floatx80_to_float32(rFd->fExtended); - } - break; - - case typeDouble: - { - if (typeSingle == nType) - rFd->fDouble = float32_to_float64(rFd->fSingle); - else - rFd->fDouble = floatx80_to_float64(rFd->fExtended); - } - break; - - case typeExtended: - { - if (typeSingle == nType) - rFd->fExtended = float32_to_floatx80(rFd->fSingle); - else - rFd->fExtended = float64_to_floatx80(rFd->fDouble); - } - break; - } - } -#else - if (nDest != nType) { - if (nDest == typeSingle) - rFd->fSingle = float64_to_float32(rFd->fDouble); - else - rFd->fDouble = float32_to_float64(rFd->fSingle); - } -#endif + default: + return 0; } - - return nRc; } --- ../linux-sharp-c1000+nwfpe/arch/arm/nwfpe/fpa11_cpdt.c 2005-05-03 22:49:08.000000000 +0900 +++ linux/arch/arm/nwfpe/fpa11_cpdt.c 2006-04-05 18:42:24.105364136 +0900 @@ -194,7 +194,7 @@ } } -unsigned int PerformLDF(const unsigned int opcode) +static inline unsigned int PerformLDF(const unsigned int opcode) { unsigned int *pBase, *pAddress, *pFinal, nRc = 1, write_back = WRITE_BACK(opcode); @@ -237,7 +237,7 @@ return nRc; } -unsigned int PerformSTF(const unsigned int opcode) +static inline unsigned int PerformSTF(const unsigned int opcode) { unsigned int *pBase, *pAddress, *pFinal, nRc = 1, write_back = WRITE_BACK(opcode); @@ -282,7 +282,7 @@ return nRc; } -unsigned int PerformLFM(const unsigned int opcode) +static inline unsigned int PerformLFM(const unsigned int opcode) { unsigned int i, Fd, *pBase, *pAddress, *pFinal, write_back = WRITE_BACK(opcode); @@ -318,7 +318,7 @@ return 1; } -unsigned int PerformSFM(const unsigned int opcode) +static inline unsigned int PerformSFM(const unsigned int opcode) { unsigned int i, Fd, *pBase, *pAddress, *pFinal, write_back = WRITE_BACK(opcode); --- ../linux-sharp-c1000+nwfpe/arch/arm/nwfpe/fpa11_cprt.c 2005-05-03 22:49:08.000000000 +0900 +++ linux/arch/arm/nwfpe/fpa11_cprt.c 2006-04-05 18:42:24.105364136 +0900 @@ -34,46 +34,12 @@ void SetRoundingMode(const unsigned int opcode); -unsigned int PerformFLT(const unsigned int opcode); -unsigned int PerformFIX(const unsigned int opcode); +static inline unsigned int PerformFLT(const unsigned int opcode); +static inline unsigned int PerformFIX(const unsigned int opcode); -static unsigned int PerformComparison(const unsigned int opcode); +static inline unsigned int PerformComparison(const unsigned int opcode); -unsigned int EmulateCPRT(const unsigned int opcode) -{ - - if (opcode & 0x800000) { - /* This is some variant of a comparison (PerformComparison - will sort out which one). Since most of the other CPRT - instructions are oddball cases of some sort or other it - makes sense to pull this out into a fast path. */ - return PerformComparison(opcode); - } - - /* Hint to GCC that we'd like a jump table rather than a load of CMPs */ - switch ((opcode & 0x700000) >> 20) { - case FLT_CODE >> 20: - return PerformFLT(opcode); - break; - case FIX_CODE >> 20: - return PerformFIX(opcode); - break; - - case WFS_CODE >> 20: - writeFPSR(readRegister(getRd(opcode))); - break; - case RFS_CODE >> 20: - writeRegister(getRd(opcode), readFPSR()); - break; - - default: - return 0; - } - - return 1; -} - -unsigned int PerformFLT(const unsigned int opcode) +static inline unsigned int PerformFLT(const unsigned int opcode) { FPA11 *fpa11 = GET_FPA11(); SetRoundingMode(opcode); @@ -110,7 +76,7 @@ return 1; } -unsigned int PerformFIX(const unsigned int opcode) +static inline unsigned int PerformFIX(const unsigned int opcode) { FPA11 *fpa11 = GET_FPA11(); unsigned int Fn = getFm(opcode); @@ -146,7 +112,7 @@ } /* This instruction sets the flags N, Z, C, V in the FPSR. */ -static unsigned int PerformComparison(const unsigned int opcode) +static inline unsigned int PerformComparison(const unsigned int opcode) { FPA11 *fpa11 = GET_FPA11(); unsigned int Fn = getFn(opcode), Fm = getFm(opcode); @@ -366,3 +332,37 @@ writeConditionCodes(flags); return 1; } + +unsigned int EmulateCPRT(const unsigned int opcode) +{ + + if (opcode & 0x800000) { + /* This is some variant of a comparison (PerformComparison + will sort out which one). Since most of the other CPRT + instructions are oddball cases of some sort or other it + makes sense to pull this out into a fast path. */ + return PerformComparison(opcode); + } + + /* Hint to GCC that we'd like a jump table rather than a load of CMPs */ + switch ((opcode & 0x700000) >> 20) { + case FLT_CODE >> 20: + return PerformFLT(opcode); + break; + case FIX_CODE >> 20: + return PerformFIX(opcode); + break; + + case WFS_CODE >> 20: + writeFPSR(readRegister(getRd(opcode))); + break; + case RFS_CODE >> 20: + writeRegister(getRd(opcode), readFPSR()); + break; + + default: + return 0; + } + + return 1; +} --- ../linux-sharp-c1000+nwfpe/arch/arm/nwfpe/fpmodule.c 2005-05-03 22:49:08.000000000 +0900 +++ linux/arch/arm/nwfpe/fpmodule.c 2006-04-05 18:42:24.105364136 +0900 @@ -68,12 +68,15 @@ /* external declarations for saved kernel symbols */ extern void (*kern_fp_enter)(void); +extern void (*fp_init)(union fp_state *); /* Original value of fp_enter from kernel before patched by fpe_init. */ static void (*orig_fp_enter)(void); +static void (*orig_fp_init)(union fp_state *); /* forward declarations */ extern void nwfpe_enter(void); +extern void nwfpe_init_fpa(union fp_state *fp); #ifdef MODULE /* @@ -112,7 +115,9 @@ /* Save pointer to the old FP handler and then patch ourselves in */ orig_fp_enter = kern_fp_enter; + orig_fp_init = fp_init; kern_fp_enter = nwfpe_enter; + fp_init = nwfpe_init_fpa; return 0; } @@ -121,6 +126,7 @@ { /* Restore the values we saved earlier. */ kern_fp_enter = orig_fp_enter; + fp_init = orig_fp_init; } /* --- ../linux-sharp-c1000+nwfpe/arch/arm/nwfpe/single_cpdo.c 2005-05-03 22:49:08.000000000 +0900 +++ linux/arch/arm/nwfpe/single_cpdo.c 2006-04-05 18:42:24.107363832 +0900 @@ -20,10 +20,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "fpa11.h" -#include "softfloat.h" -#include "fpopcode.h" - float32 float32_exp(float32 Fm); float32 float32_ln(float32 Fm); float32 float32_sin(float32 rFm); @@ -36,59 +32,34 @@ float32 float32_pow(float32 rFn, float32 rFm); float32 float32_pol(float32 rFn, float32 rFm); -static float32 float32_rsf(float32 rFn, float32 rFm) +static inline float32 float32_rsf(float32 rFn, float32 rFm) { return float32_sub(rFm, rFn); } -static float32 float32_rdv(float32 rFn, float32 rFm) +static inline float32 float32_rdv(float32 rFn, float32 rFm) { return float32_div(rFm, rFn); } -static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = { - [ADF_CODE >> 20] = float32_add, - [MUF_CODE >> 20] = float32_mul, - [SUF_CODE >> 20] = float32_sub, - [RSF_CODE >> 20] = float32_rsf, - [DVF_CODE >> 20] = float32_div, - [RDF_CODE >> 20] = float32_rdv, - [RMF_CODE >> 20] = float32_rem, - - [FML_CODE >> 20] = float32_mul, - [FDV_CODE >> 20] = float32_div, - [FRD_CODE >> 20] = float32_rdv, -}; - -static float32 float32_mvf(float32 rFm) +static inline float32 float32_mvf(float32 rFm) { return rFm; } -static float32 float32_mnf(float32 rFm) +static inline float32 float32_mnf(float32 rFm) { return rFm ^ 0x80000000; } -static float32 float32_abs(float32 rFm) +static inline float32 float32_abs(float32 rFm) { return rFm & 0x7fffffff; } -static float32 (*const monadic_single[16])(float32 rFm) = { - [MVF_CODE >> 20] = float32_mvf, - [MNF_CODE >> 20] = float32_mnf, - [ABS_CODE >> 20] = float32_abs, - [RND_CODE >> 20] = float32_round_to_int, - [URD_CODE >> 20] = float32_round_to_int, - [SQT_CODE >> 20] = float32_sqrt, - [NRM_CODE >> 20] = float32_mvf, -}; - -unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd) +static inline unsigned int SingleCPDO(FPA11 *fpa11, const unsigned int opcode, FPREG * rFd, const unsigned int nDest) { - FPA11 *fpa11 = GET_FPA11(); - float32 rFm; + float32 rFm, rFn; unsigned int Fm, opc_mask_shift; Fm = getFm(opcode); @@ -100,25 +71,114 @@ return 0; } - opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20; + opc_mask_shift = (opcode >> 20) & (MASK_ARITHMETIC_OPCODE >> 20); if (!MONADIC_INSTRUCTION(opcode)) { unsigned int Fn = getFn(opcode); - float32 rFn; - if (fpa11->fType[Fn] == typeSingle && - dyadic_single[opc_mask_shift]) { - rFn = fpa11->fpreg[Fn].fSingle; - rFd->fSingle = dyadic_single[opc_mask_shift](rFn, rFm); - } else { + if (fpa11->fType[Fn] != typeSingle) + return 0; + + rFn = fpa11->fpreg[Fn].fSingle; + + switch (opc_mask_shift) { + case ADF_CODE >> 20: + rFd->fSingle = float32_add(rFn, rFm); + break; + + case MUF_CODE >> 20: + rFd->fSingle = float32_mul(rFn, rFm); + break; + + case SUF_CODE >> 20: + rFd->fSingle = float32_sub(rFn, rFm); + break; + + case RSF_CODE >> 20: + rFd->fSingle = float32_rsf(rFn, rFm); + break; + + case DVF_CODE >> 20: + rFd->fSingle = float32_div(rFn, rFm); + break; + + case RDF_CODE >> 20: + rFd->fSingle = float32_rdv(rFn, rFm); + break; + + case RMF_CODE >> 20: + rFd->fSingle = float32_rem(rFn, rFm); + break; + + case FML_CODE >> 20: + rFd->fSingle = float32_mul(rFn, rFm); + break; + + case FDV_CODE >> 20: + rFd->fSingle = float32_div(rFn, rFm); + break; + + case FRD_CODE >> 20: + rFd->fSingle = float32_rdv(rFn, rFm); + break; + + default: return 0; } } else { - if (monadic_single[opc_mask_shift]) { - rFd->fSingle = monadic_single[opc_mask_shift](rFm); - } else { + switch (opc_mask_shift) { + case MVF_CODE >> 20: + rFd->fSingle = float32_mvf(rFm); + break; + + case MNF_CODE >> 20: + rFd->fSingle = float32_mnf(rFm); + break; + + case ABS_CODE >> 20: + rFd->fSingle = float32_abs(rFm); + break; + + case RND_CODE >> 20: + rFd->fSingle = float32_round_to_int(rFm); + break; + + case URD_CODE >> 20: + rFd->fSingle = float32_round_to_int(rFm); + break; + + case SQT_CODE >> 20: + rFd->fSingle = float32_sqrt(rFm); + break; + + case NRM_CODE >> 20: + rFd->fSingle = float32_mvf(rFm); + break; + + default: return 0; } } + /* The CPDO functions used to always set the destination type + to be the same as their working size. */ + + /* If the operation succeeded, check to see if the result in the + destination register is the correct size. If not force it + to be. */ + + fpa11->fType[getFd(opcode)] = nDest; + +#ifdef CONFIG_FPE_NWFPE_XP + if (nDest != typeSingle) { + if (nDest == typeDouble) + rFd->fDouble = float32_to_float64(rFd->fSingle); + else + rFd->fExtended = float32_to_floatx80(rFd->fSingle); + } +#else + if (nDest != typeSingle) + rFd->fDouble = float32_to_float64(rFd->fSingle); +#endif + return 1; } --- ../linux-sharp-c1000+nwfpe/arch/arm/nwfpe/softfloat-macros 2005-05-03 22:49:08.000000000 +0900 +++ linux/arch/arm/nwfpe/softfloat-macros 2006-04-05 18:42:24.108363680 +0900 @@ -41,17 +41,12 @@ */ INLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr ) { - bits32 z; - if ( count == 0 ) { - z = a; - } - else if ( count < 32 ) { - z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 ); - } - else { - z = ( a != 0 ); - } - *zPtr = z; + if ( count == 0 ) + *zPtr = a; + else if ( count < 32 ) + *zPtr = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 ); + else + *zPtr = ( a != 0 ); } /* @@ -66,20 +61,12 @@ */ INLINE void shift64RightJamming( bits64 a, int16 count, bits64 *zPtr ) { - bits64 z; - - __asm__("@shift64RightJamming -- start"); - if ( count == 0 ) { - z = a; - } - else if ( count < 64 ) { - z = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 ); - } - else { - z = ( a != 0 ); - } - __asm__("@shift64RightJamming -- end"); - *zPtr = z; + if ( count == 0 ) + *zPtr = a; + else if ( count < 64 ) + *zPtr = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 ); + else + *zPtr = ( a != 0 ); } /* @@ -104,29 +91,21 @@ shift64ExtraRightJamming( bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) { - bits64 z0, z1; int8 negCount = ( - count ) & 63; if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count; - } - else { - if ( count == 64 ) { - z1 = a0 | ( a1 != 0 ); - } - else { - z1 = ( ( a0 | a1 ) != 0 ); - } - z0 = 0; + *z1Ptr = a1; + *z0Ptr = a0; + } else if ( count < 64 ) { + *z1Ptr = ( a0<>count; + } else { + if ( count == 64 ) + *z1Ptr = a0 | ( a1 != 0 ); + else + *z1Ptr = ( ( a0 | a1 ) != 0 ); + *z0Ptr = 0; } - *z1Ptr = z1; - *z0Ptr = z0; - } /* @@ -142,24 +121,18 @@ shift128Right( bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) { - bits64 z0, z1; int8 negCount = ( - count ) & 63; if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count ); - z0 = a0>>count; - } - else { - z1 = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0; - z0 = 0; + *z1Ptr = a1; + *z0Ptr = a0; + } else if ( count < 64 ) { + *z1Ptr = ( a0<>count ); + *z0Ptr = a0>>count; + } else { + *z1Ptr = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0; + *z0Ptr = 0; } - *z1Ptr = z1; - *z0Ptr = z0; - } /* @@ -178,32 +151,23 @@ shift128RightJamming( bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) { - bits64 z0, z1; int8 negCount = ( - count ) & 63; if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count ) | ( ( a1<>count; - } - else { - if ( count == 64 ) { - z1 = a0 | ( a1 != 0 ); - } - else if ( count < 128 ) { - z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<>count ) | ( ( a1<>count; + } else { + if ( count == 64 ) + *z1Ptr = a0 | ( a1 != 0 ); + else if ( count < 128 ) + *z1Ptr = ( a0>>( count & 63 ) ) | ( ( ( a0<>24 ]; - return shiftCount; + asm("clz %0, %1" : "=r"(ret) : "r"(a) : "cc"); + return ret; } /* --- ../linux-sharp-c1000+nwfpe/arch/arm/nwfpe/softfloat-specialize 2005-05-03 22:49:08.000000000 +0900 +++ linux/arch/arm/nwfpe/softfloat-specialize 2006-04-05 18:42:24.108363680 +0900 @@ -39,25 +39,6 @@ /* ------------------------------------------------------------------------------- -Raises the exceptions specified by `flags'. Floating-point traps can be -defined here if desired. It is currently not possible for such a trap to -substitute a result value. If traps are not implemented, this routine -should be simply `float_exception_flags |= flags;'. - -ScottB: November 4, 1998 -Moved this function out of softfloat-specialize into fpmodule.c. -This effectively isolates all the changes required for integrating with the -Linux kernel into fpmodule.c. Porting to NetBSD should only require modifying -fpmodule.c to integrate with the NetBSD kernel (I hope!). -------------------------------------------------------------------------------- -void float_raise( int8 flags ) -{ - float_exception_flags |= flags; -} -*/ - -/* -------------------------------------------------------------------------------- Internal canonical NaN format. ------------------------------------------------------------------------------- */ @@ -68,45 +49,12 @@ /* ------------------------------------------------------------------------------- -The pattern for a default generated single-precision NaN. -------------------------------------------------------------------------------- -*/ -#define float32_default_nan 0xFFFFFFFF - -/* -------------------------------------------------------------------------------- -Returns 1 if the single-precision floating-point value `a' is a NaN; -otherwise returns 0. -------------------------------------------------------------------------------- -*/ -flag float32_is_nan( float32 a ) -{ - - return ( 0xFF000000 < (bits32) ( a<<1 ) ); - -} - -/* -------------------------------------------------------------------------------- -Returns 1 if the single-precision floating-point value `a' is a signaling -NaN; otherwise returns 0. -------------------------------------------------------------------------------- -*/ -flag float32_is_signaling_nan( float32 a ) -{ - - return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); - -} - -/* -------------------------------------------------------------------------------- Returns the result of converting the single-precision floating-point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid exception is raised. ------------------------------------------------------------------------------- */ -static commonNaNT float32ToCommonNaN( float32 a ) +static inline commonNaNT float32ToCommonNaN( float32 a ) { commonNaNT z; @@ -124,7 +72,7 @@ precision floating-point format. ------------------------------------------------------------------------------- */ -static float32 commonNaNToFloat32( commonNaNT a ) +static inline float32 commonNaNToFloat32( commonNaNT a ) { return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); @@ -138,7 +86,7 @@ signaling NaN, the invalid exception is raised. ------------------------------------------------------------------------------- */ -static float32 propagateFloat32NaN( float32 a, float32 b ) +static inline float32 propagateFloat32NaN( float32 a, float32 b ) { flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; @@ -200,7 +148,7 @@ exception is raised. ------------------------------------------------------------------------------- */ -static commonNaNT float64ToCommonNaN( float64 a ) +static inline commonNaNT float64ToCommonNaN( float64 a ) { commonNaNT z; @@ -218,7 +166,7 @@ precision floating-point format. ------------------------------------------------------------------------------- */ -static float64 commonNaNToFloat64( commonNaNT a ) +static inline float64 commonNaNToFloat64( commonNaNT a ) { return @@ -235,7 +183,7 @@ signaling NaN, the invalid exception is raised. ------------------------------------------------------------------------------- */ -static float64 propagateFloat64NaN( float64 a, float64 b ) +static inline float64 propagateFloat64NaN( float64 a, float64 b ) { flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; --- ../linux-sharp-c1000+nwfpe/arch/arm/nwfpe/softfloat.c 2005-05-03 22:49:08.000000000 +0900 +++ linux/arch/arm/nwfpe/softfloat.c 2006-04-05 18:42:24.110363376 +0900 @@ -29,8 +29,6 @@ */ #include "fpa11.h" -//#include "milieu.h" -//#include "softfloat.h" /* ------------------------------------------------------------------------------- @@ -75,7 +73,8 @@ positive or negative integer is returned. ------------------------------------------------------------------------------- */ -static int32 roundAndPackInt32( flag zSign, bits64 absZ ) +static inline int32 +roundAndPackInt32( flag zSign, bits64 absZ ) { int8 roundingMode; flag roundNearestEven; @@ -115,52 +114,14 @@ /* ------------------------------------------------------------------------------- -Returns the fraction bits of the single-precision floating-point value `a'. -------------------------------------------------------------------------------- -*/ -INLINE bits32 extractFloat32Frac( float32 a ) -{ - - return a & 0x007FFFFF; - -} - -/* -------------------------------------------------------------------------------- -Returns the exponent bits of the single-precision floating-point value `a'. -------------------------------------------------------------------------------- -*/ -INLINE int16 extractFloat32Exp( float32 a ) -{ - - return ( a>>23 ) & 0xFF; - -} - -/* -------------------------------------------------------------------------------- -Returns the sign bit of the single-precision floating-point value `a'. -------------------------------------------------------------------------------- -*/ -#if 0 /* in softfloat.h */ -INLINE flag extractFloat32Sign( float32 a ) -{ - - return a>>31; - -} -#endif - -/* -------------------------------------------------------------------------------- Normalizes the subnormal single-precision floating-point value represented by the denormalized significand `aSig'. The normalized exponent and significand are stored at the locations pointed to by `zExpPtr' and `zSigPtr', respectively. ------------------------------------------------------------------------------- */ -static void - normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr ) +static inline void +normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr ) { int8 shiftCount; @@ -172,35 +133,6 @@ /* ------------------------------------------------------------------------------- -Packs the sign `zSign', exponent `zExp', and significand `zSig' into a -single-precision floating-point value, returning the result. After being -shifted into the proper positions, the three fields are simply added -together to form the result. This means that any integer portion of `zSig' -will be added into the exponent. Since a properly normalized significand -will have an integer portion equal to 1, the `zExp' input should be 1 less -than the desired result exponent whenever `zSig' is a complete, normalized -significand. -------------------------------------------------------------------------------- -*/ -INLINE float32 packFloat32( flag zSign, int16 zExp, bits32 zSig ) -{ -#if 0 - float32 f; - __asm__("@ packFloat32 \n\ - mov %0, %1, asl #31 \n\ - orr %0, %2, asl #23 \n\ - orr %0, %3" - : /* no outputs */ - : "g" (f), "g" (zSign), "g" (zExp), "g" (zSig) - : "cc"); - return f; -#else - return ( ( (bits32) zSign )<<31 ) + ( ( (bits32) zExp )<<23 ) + zSig; -#endif -} - -/* -------------------------------------------------------------------------------- Takes an abstract floating-point value having sign `zSign', exponent `zExp', and significand `zSig', and returns the proper single-precision floating- point value corresponding to the abstract input. Ordinarily, the abstract @@ -222,7 +154,8 @@ Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) +static inline float32 +roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) { int8 roundingMode; flag roundNearestEven; @@ -284,8 +217,8 @@ point exponent. ------------------------------------------------------------------------------- */ -static float32 - normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) +static inline float32 +normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) { int8 shiftCount; @@ -296,52 +229,14 @@ /* ------------------------------------------------------------------------------- -Returns the fraction bits of the double-precision floating-point value `a'. -------------------------------------------------------------------------------- -*/ -INLINE bits64 extractFloat64Frac( float64 a ) -{ - - return a & LIT64( 0x000FFFFFFFFFFFFF ); - -} - -/* -------------------------------------------------------------------------------- -Returns the exponent bits of the double-precision floating-point value `a'. -------------------------------------------------------------------------------- -*/ -INLINE int16 extractFloat64Exp( float64 a ) -{ - - return ( a>>52 ) & 0x7FF; - -} - -/* -------------------------------------------------------------------------------- -Returns the sign bit of the double-precision floating-point value `a'. -------------------------------------------------------------------------------- -*/ -#if 0 /* in softfloat.h */ -INLINE flag extractFloat64Sign( float64 a ) -{ - - return a>>63; - -} -#endif - -/* -------------------------------------------------------------------------------- Normalizes the subnormal double-precision floating-point value represented by the denormalized significand `aSig'. The normalized exponent and significand are stored at the locations pointed to by `zExpPtr' and `zSigPtr', respectively. ------------------------------------------------------------------------------- */ -static void - normalizeFloat64Subnormal( bits64 aSig, int16 *zExpPtr, bits64 *zSigPtr ) +static inline void +normalizeFloat64Subnormal( bits64 aSig, int16 *zExpPtr, bits64 *zSigPtr ) { int8 shiftCount; @@ -353,25 +248,6 @@ /* ------------------------------------------------------------------------------- -Packs the sign `zSign', exponent `zExp', and significand `zSig' into a -double-precision floating-point value, returning the result. After being -shifted into the proper positions, the three fields are simply added -together to form the result. This means that any integer portion of `zSig' -will be added into the exponent. Since a properly normalized significand -will have an integer portion equal to 1, the `zExp' input should be 1 less -than the desired result exponent whenever `zSig' is a complete, normalized -significand. -------------------------------------------------------------------------------- -*/ -INLINE float64 packFloat64( flag zSign, int16 zExp, bits64 zSig ) -{ - - return ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<52 ) + zSig; - -} - -/* -------------------------------------------------------------------------------- Takes an abstract floating-point value having sign `zSign', exponent `zExp', and significand `zSig', and returns the proper double-precision floating- point value corresponding to the abstract input. Ordinarily, the abstract @@ -393,7 +269,8 @@ Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) +static inline float64 +roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) { int8 roundingMode; flag roundNearestEven; @@ -457,8 +334,8 @@ point exponent. ------------------------------------------------------------------------------- */ -static float64 - normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) +static inline float64 +normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) { int8 shiftCount; @@ -861,47 +738,6 @@ /* ------------------------------------------------------------------------------- Returns the result of converting the single-precision floating-point value -`a' to the 32-bit two's complement integer format. The conversion is -performed according to the IEC/IEEE Standard for Binary Floating-point -Arithmetic, except that the conversion is always rounded toward zero. If -`a' is a NaN, the largest positive integer is returned. Otherwise, if the -conversion overflows, the largest integer with the same sign as `a' is -returned. -------------------------------------------------------------------------------- -*/ -int32 float32_to_int32_round_to_zero( float32 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits32 aSig; - int32 z; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - shiftCount = aExp - 0x9E; - if ( 0 <= shiftCount ) { - if ( a == 0xCF000000 ) return 0x80000000; - float_raise( float_flag_invalid ); - if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) return 0x7FFFFFFF; - return 0x80000000; - } - else if ( aExp <= 0x7E ) { - if ( aExp | aSig ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig = ( aSig | 0x00800000 )<<8; - z = aSig>>( - shiftCount ); - if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - return aSign ? - z : z; - -} - -/* -------------------------------------------------------------------------------- -Returns the result of converting the single-precision floating-point value `a' to the double-precision floating-point format. The conversion is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. @@ -1032,7 +868,8 @@ Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static float32 addFloat32Sigs( float32 a, float32 b, flag zSign ) +static inline float32 +addFloat32Sigs( float32 a, float32 b, flag zSign ) { int16 aExp, bExp, zExp; bits32 aSig, bSig, zSig; @@ -1104,7 +941,8 @@ Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static float32 subFloat32Sigs( float32 a, float32 b, flag zSign ) +static inline float32 +subFloat32Sigs( float32 a, float32 b, flag zSign ) { int16 aExp, bExp, zExp; bits32 aSig, bSig, zSig; @@ -1568,82 +1406,6 @@ /* ------------------------------------------------------------------------------- -Returns 1 if the single-precision floating-point value `a' is equal to the -corresponding value `b', and 0 otherwise. The invalid exception is raised -if either operand is a NaN. Otherwise, the comparison is performed -according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. -------------------------------------------------------------------------------- -*/ -flag float32_eq_signaling( float32 a, float32 b ) -{ - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); - -} - -/* -------------------------------------------------------------------------------- -Returns 1 if the single-precision floating-point value `a' is less than or -equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -cause an exception. Otherwise, the comparison is performed according to the -IEC/IEEE Standard for Binary Floating-point Arithmetic. -------------------------------------------------------------------------------- -*/ -flag float32_le_quiet( float32 a, float32 b ) -{ - flag aSign, bSign; - //int16 aExp, bExp; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/* -------------------------------------------------------------------------------- -Returns 1 if the single-precision floating-point value `a' is less than -the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -exception. Otherwise, the comparison is performed according to the IEC/IEEE -Standard for Binary Floating-point Arithmetic. -------------------------------------------------------------------------------- -*/ -flag float32_lt_quiet( float32 a, float32 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -/* -------------------------------------------------------------------------------- Returns the result of converting the double-precision floating-point value `a' to the 32-bit two's complement integer format. The conversion is performed according to the IEC/IEEE Standard for Binary Floating-point @@ -1673,125 +1435,6 @@ /* ------------------------------------------------------------------------------- Returns the result of converting the double-precision floating-point value -`a' to the 32-bit two's complement integer format. The conversion is -performed according to the IEC/IEEE Standard for Binary Floating-point -Arithmetic, except that the conversion is always rounded toward zero. If -`a' is a NaN, the largest positive integer is returned. Otherwise, if the -conversion overflows, the largest integer with the same sign as `a' is -returned. -------------------------------------------------------------------------------- -*/ -int32 float64_to_int32_round_to_zero( float64 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits64 aSig, savedASig; - int32 z; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - shiftCount = 0x433 - aExp; - if ( shiftCount < 21 ) { - if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; - goto invalid; - } - else if ( 52 < shiftCount ) { - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig |= LIT64( 0x0010000000000000 ); - savedASig = aSig; - aSig >>= shiftCount; - z = aSig; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_exception_flags |= float_flag_invalid; - return aSign ? 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig<>= shiftCount; - z = aSig; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_exception_flags |= float_flag_invalid; - return aSign ? 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig<> 31; + return (0xFF000000 < (bits32)(a << 1)); +} + +/* +------------------------------------------------------------------------------- +Returns 1 if the single-precision floating-point value `a' is a signaling +NaN; otherwise returns 0. +------------------------------------------------------------------------------- +*/ +static inline flag float32_is_signaling_nan(float32 a) +{ + return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF); +} + +/* +------------------------------------------------------------------------------- +Returns the fraction bits of the single-precision floating-point value `a'. +------------------------------------------------------------------------------- +*/ +#define extractFloat32Frac(a) (bits32)(((float32)(a)) & 0x007FFFFF) + +/* +------------------------------------------------------------------------------- +Returns the exponent bits of the single-precision floating-point value `a'. +------------------------------------------------------------------------------- +*/ +#define extractFloat32Exp(a) (int16)((((float32)(a)) >> 23) & 0xFF) + +/* +------------------------------------------------------------------------------- +Returns the sign bit of the single-precision floating-point value `a'. +------------------------------------------------------------------------------- +*/ +#define extractFloat32Sign(a) (((float32)(a)) >> 31) + +/* +------------------------------------------------------------------------------- +Packs the sign `zSign', exponent `zExp', and significand `zSig' into a +single-precision floating-point value, returning the result. After being +shifted into the proper positions, the three fields are simply added +together to form the result. This means that any integer portion of `zSig' +will be added into the exponent. Since a properly normalized significand +will have an integer portion equal to 1, the `zExp' input should be 1 less +than the desired result exponent whenever `zSig' is a complete, normalized +significand. +------------------------------------------------------------------------------- +*/ +static inline float32 packFloat32(flag zSign, int16 zExp, bits32 zSig) +{ + return (((bits32)zSign) << 31) + (((bits32)zExp) << 23) + zSig; +} + +/* +------------------------------------------------------------------------------- +Returns the fraction bits of the double-precision floating-point value `a'. +------------------------------------------------------------------------------- +*/ +static inline bits64 extractFloat64Frac(float64 a) +{ + return a & LIT64(0x000FFFFFFFFFFFFF); +} + +/* +------------------------------------------------------------------------------- +Returns the exponent bits of the double-precision floating-point value `a'. +------------------------------------------------------------------------------- +*/ +static inline int16 extractFloat64Exp(float64 a) +{ + return (a >> 52) & 0x7FF; +} + +/* +------------------------------------------------------------------------------- +Returns the sign bit of the double-precision floating-point value `a'. +------------------------------------------------------------------------------- +*/ +static inline flag extractFloat64Sign(float64 a) +{ + return a >> 63; +} + +/* +------------------------------------------------------------------------------- +Packs the sign `zSign', exponent `zExp', and significand `zSig' into a +double-precision floating-point value, returning the result. After being +shifted into the proper positions, the three fields are simply added +together to form the result. This means that any integer portion of `zSig' +will be added into the exponent. Since a properly normalized significand +will have an integer portion equal to 1, the `zExp' input should be 1 less +than the desired result exponent whenever `zSig' is a complete, normalized +significand. +------------------------------------------------------------------------------- +*/ +static inline float64 packFloat64(flag zSign, int16 zExp, bits64 zSig) +{ + return (((bits64)zSign) << 63) + (((bits64)zExp) << 52) + zSig; } static inline flag float32_eq_nocheck(float32 a, float32 b) @@ -252,11 +352,6 @@ return (a != b) && (aSign ^ (a < b)); } -static inline flag extractFloat64Sign(float64 a) -{ - return a >> 63; -} - static inline flag float64_eq_nocheck(float64 a, float64 b) { return (a == b) || ((bits64) ((a | b) << 1) == 0);