Commit 194d0710 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/home/rmk/linux-2.6-arm

parents a68d2ebc 9bbd0375
......@@ -104,6 +104,7 @@ logo_*.c
logo_*_clut224.c
logo_*_mono.c
lxdialog
mach-types
mach-types.h
make_times_h
map
......
......@@ -61,7 +61,7 @@ static struct plat_serial8250_port coyote_uart_data[] = {
.mapbase = IXP4XX_UART2_BASE_PHYS,
.membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
.irq = IRQ_IXP4XX_UART2,
.flags = UPF_BOOT_AUTOCONF,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = IXP4XX_UART_XTAL,
......
......@@ -83,7 +83,7 @@ static struct plat_serial8250_port gtwx5715_uart_platform_data[] = {
.mapbase = IXP4XX_UART2_BASE_PHYS,
.membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
.irq = IRQ_IXP4XX_UART2,
.flags = UPF_BOOT_AUTOCONF,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = IXP4XX_UART_XTAL,
......
......@@ -82,7 +82,7 @@ static struct plat_serial8250_port ixdp425_uart_data[] = {
.mapbase = IXP4XX_UART1_BASE_PHYS,
.membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
.irq = IRQ_IXP4XX_UART1,
.flags = UPF_BOOT_AUTOCONF,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = IXP4XX_UART_XTAL,
......@@ -91,7 +91,7 @@ static struct plat_serial8250_port ixdp425_uart_data[] = {
.mapbase = IXP4XX_UART2_BASE_PHYS,
.membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
.irq = IRQ_IXP4XX_UART1,
.flags = UPF_BOOT_AUTOCONF,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = IXP4XX_UART_XTAL,
......
......@@ -30,6 +30,7 @@
* 28-Jun-2005 BJD Moved pm functionality out to common code
* 17-Jul-2005 BJD Changed to platform device for SuperIO 16550s
* 25-Jul-2005 BJD Removed ASIX static mappings
* 27-Jul-2005 BJD Ensure maximum frequency of i2c bus
*/
#include <linux/kernel.h>
......@@ -60,6 +61,7 @@
#include <asm/arch/regs-mem.h>
#include <asm/arch/regs-lcd.h>
#include <asm/arch/nand.h>
#include <asm/arch/iic.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
......@@ -304,7 +306,7 @@ static void bast_nand_select(struct s3c2410_nand_set *set, int slot)
}
static struct s3c2410_platform_nand bast_nand_info = {
.tacls = 80,
.tacls = 40,
.twrph0 = 80,
.twrph1 = 80,
.nr_sets = ARRAY_SIZE(bast_nand_sets),
......@@ -385,6 +387,17 @@ static struct platform_device bast_sio = {
},
};
/* we have devices on the bus which cannot work much over the
* standard 100KHz i2c bus frequency
*/
static struct s3c2410_platform_i2c bast_i2c_info = {
.flags = 0,
.slave_addr = 0x10,
.bus_freq = 100*1000,
.max_freq = 130*1000,
};
/* Standard BAST devices */
static struct platform_device *bast_devices[] __initdata = {
......@@ -431,6 +444,7 @@ void __init bast_map_io(void)
s3c24xx_uclk.parent = &s3c24xx_clkout1;
s3c_device_nand.dev.platform_data = &bast_nand_info;
s3c_device_i2c.dev.platform_data = &bast_i2c_info;
s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
s3c24xx_init_clocks(0);
......
......@@ -370,142 +370,6 @@ ENTRY(cpu_xscale_dcache_clean_area)
bhi 1b
mov pc, lr
/* ================================ CACHE LOCKING============================
*
* The XScale MicroArchitecture implements support for locking entries into
* the data and instruction cache. The following functions implement the core
* low level instructions needed to accomplish the locking. The developer's
* manual states that the code that performs the locking must be in non-cached
* memory. To accomplish this, the code in xscale-cache-lock.c copies the
* following functions from the cache into a non-cached memory region that
* is allocated through consistent_alloc().
*
*/
.align 5
/*
* xscale_icache_lock
*
* r0: starting address to lock
* r1: end address to lock
*/
ENTRY(xscale_icache_lock)
iLockLoop:
bic r0, r0, #CACHELINESIZE - 1
mcr p15, 0, r0, c9, c1, 0 @ lock into cache
cmp r0, r1 @ are we done?
add r0, r0, #CACHELINESIZE @ advance to next cache line
bls iLockLoop
mov pc, lr
/*
* xscale_icache_unlock
*/
ENTRY(xscale_icache_unlock)
mcr p15, 0, r0, c9, c1, 1 @ Unlock icache
mov pc, lr
/*
* xscale_dcache_lock
*
* r0: starting address to lock
* r1: end address to lock
*/
ENTRY(xscale_dcache_lock)
mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
mov r2, #1
mcr p15, 0, r2, c9, c2, 0 @ Put dcache in lock mode
cpwait ip @ Wait for completion
mrs r2, cpsr
orr r3, r2, #PSR_F_BIT | PSR_I_BIT
dLockLoop:
msr cpsr_c, r3
mcr p15, 0, r0, c7, c10, 1 @ Write back line if it is dirty
mcr p15, 0, r0, c7, c6, 1 @ Flush/invalidate line
msr cpsr_c, r2
ldr ip, [r0], #CACHELINESIZE @ Preload 32 bytes into cache from
@ location [r0]. Post-increment
@ r3 to next cache line
cmp r0, r1 @ Are we done?
bls dLockLoop
mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
mov r2, #0
mcr p15, 0, r2, c9, c2, 0 @ Get out of lock mode
cpwait_ret lr, ip
/*
* xscale_dcache_unlock
*/
ENTRY(xscale_dcache_unlock)
mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
mcr p15, 0, ip, c9, c2, 1 @ Unlock cache
mov pc, lr
/*
* Needed to determine the length of the code that needs to be copied.
*/
.align 5
ENTRY(xscale_cache_dummy)
mov pc, lr
/* ================================ TLB LOCKING==============================
*
* The XScale MicroArchitecture implements support for locking entries into
* the Instruction and Data TLBs. The following functions provide the
* low level support for supporting these under Linux. xscale-lock.c
* implements some higher level management code. Most of the following
* is taken straight out of the Developer's Manual.
*/
/*
* Lock I-TLB entry
*
* r0: Virtual address to translate and lock
*/
.align 5
ENTRY(xscale_itlb_lock)
mrs r2, cpsr
orr r3, r2, #PSR_F_BIT | PSR_I_BIT
msr cpsr_c, r3 @ Disable interrupts
mcr p15, 0, r0, c8, c5, 1 @ Invalidate I-TLB entry
mcr p15, 0, r0, c10, c4, 0 @ Translate and lock
msr cpsr_c, r2 @ Restore interrupts
cpwait_ret lr, ip
/*
* Lock D-TLB entry
*
* r0: Virtual address to translate and lock
*/
.align 5
ENTRY(xscale_dtlb_lock)
mrs r2, cpsr
orr r3, r2, #PSR_F_BIT | PSR_I_BIT
msr cpsr_c, r3 @ Disable interrupts
mcr p15, 0, r0, c8, c6, 1 @ Invalidate D-TLB entry
mcr p15, 0, r0, c10, c8, 0 @ Translate and lock
msr cpsr_c, r2 @ Restore interrupts
cpwait_ret lr, ip
/*
* Unlock all I-TLB entries
*/
.align 5
ENTRY(xscale_itlb_unlock)
mcr p15, 0, ip, c10, c4, 1 @ Unlock I-TLB
mcr p15, 0, ip, c8, c5, 0 @ Invalidate I-TLB
cpwait_ret lr, ip
/*
* Unlock all D-TLB entries
*/
ENTRY(xscale_dtlb_unlock)
mcr p15, 0, ip, c10, c8, 1 @ Unlock D-TBL
mcr p15, 0, ip, c8, c6, 0 @ Invalidate D-TLB
cpwait_ret lr, ip
/* =============================== PageTable ============================== */
#define PTE_CACHE_WRITE_ALLOCATE 0
......
......@@ -40,17 +40,17 @@ float64 float64_arccos(float64 rFm);
float64 float64_pow(float64 rFn, float64 rFm);
float64 float64_pol(float64 rFn, float64 rFm);
static float64 float64_rsf(float64 rFn, float64 rFm)
static float64 float64_rsf(struct roundingData *roundData, float64 rFn, float64 rFm)
{
return float64_sub(rFm, rFn);
return float64_sub(roundData, rFm, rFn);
}
static float64 float64_rdv(float64 rFn, float64 rFm)
static float64 float64_rdv(struct roundingData *roundData, float64 rFn, float64 rFm)
{
return float64_div(rFm, rFn);
return float64_div(roundData, rFm, rFn);
}
static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = {
static float64 (*const dyadic_double[16])(struct roundingData*, float64 rFn, float64 rFm) = {
[ADF_CODE >> 20] = float64_add,
[MUF_CODE >> 20] = float64_mul,
[SUF_CODE >> 20] = float64_sub,
......@@ -65,12 +65,12 @@ static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = {
[FRD_CODE >> 20] = float64_rdv,
};
static float64 float64_mvf(float64 rFm)
static float64 float64_mvf(struct roundingData *roundData,float64 rFm)
{
return rFm;
}
static float64 float64_mnf(float64 rFm)
static float64 float64_mnf(struct roundingData *roundData,float64 rFm)
{
union float64_components u;
......@@ -84,7 +84,7 @@ static float64 float64_mnf(float64 rFm)
return u.f64;
}
static float64 float64_abs(float64 rFm)
static float64 float64_abs(struct roundingData *roundData,float64 rFm)
{
union float64_components u;
......@@ -98,7 +98,7 @@ static float64 float64_abs(float64 rFm)
return u.f64;
}
static float64 (*const monadic_double[16])(float64 rFm) = {
static float64 (*const monadic_double[16])(struct roundingData *, float64 rFm) = {
[MVF_CODE >> 20] = float64_mvf,
[MNF_CODE >> 20] = float64_mnf,
[ABS_CODE >> 20] = float64_abs,
......@@ -108,7 +108,7 @@ static float64 (*const monadic_double[16])(float64 rFm) = {
[NRM_CODE >> 20] = float64_mvf,
};
unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd)
unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
{
FPA11 *fpa11 = GET_FPA11();
float64 rFm;
......@@ -151,13 +151,13 @@ unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd)
}
if (dyadic_double[opc_mask_shift]) {
rFd->fDouble = dyadic_double[opc_mask_shift](rFn, rFm);
rFd->fDouble = dyadic_double[opc_mask_shift](roundData, rFn, rFm);
} else {
return 0;
}
} else {
if (monadic_double[opc_mask_shift]) {
rFd->fDouble = monadic_double[opc_mask_shift](rFm);
rFd->fDouble = monadic_double[opc_mask_shift](roundData, rFm);
} else {
return 0;
}
......
......@@ -35,17 +35,17 @@ floatx80 floatx80_arccos(floatx80 rFm);
floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm);
floatx80 floatx80_pol(floatx80 rFn, floatx80 rFm);
static floatx80 floatx80_rsf(floatx80 rFn, floatx80 rFm)
static floatx80 floatx80_rsf(struct roundingData *roundData, floatx80 rFn, floatx80 rFm)
{
return floatx80_sub(rFm, rFn);
return floatx80_sub(roundData, rFm, rFn);
}
static floatx80 floatx80_rdv(floatx80 rFn, floatx80 rFm)
static floatx80 floatx80_rdv(struct roundingData *roundData, floatx80 rFn, floatx80 rFm)
{
return floatx80_div(rFm, rFn);
return floatx80_div(roundData, rFm, rFn);
}
static floatx80 (*const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) = {
static floatx80 (*const dyadic_extended[16])(struct roundingData*, floatx80 rFn, floatx80 rFm) = {
[ADF_CODE >> 20] = floatx80_add,
[MUF_CODE >> 20] = floatx80_mul,
[SUF_CODE >> 20] = floatx80_sub,
......@@ -60,24 +60,24 @@ static floatx80 (*const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) = {
[FRD_CODE >> 20] = floatx80_rdv,
};
static floatx80 floatx80_mvf(floatx80 rFm)
static floatx80 floatx80_mvf(struct roundingData *roundData, floatx80 rFm)
{
return rFm;
}
static floatx80 floatx80_mnf(floatx80 rFm)
static floatx80 floatx80_mnf(struct roundingData *roundData, floatx80 rFm)
{
rFm.high ^= 0x8000;
return rFm;
}
static floatx80 floatx80_abs(floatx80 rFm)
static floatx80 floatx80_abs(struct roundingData *roundData, floatx80 rFm)
{
rFm.high &= 0x7fff;
return rFm;
}
static floatx80 (*const monadic_extended[16])(floatx80 rFm) = {
static floatx80 (*const monadic_extended[16])(struct roundingData*, floatx80 rFm) = {
[MVF_CODE >> 20] = floatx80_mvf,
[MNF_CODE >> 20] = floatx80_mnf,
[ABS_CODE >> 20] = floatx80_abs,
......@@ -87,7 +87,7 @@ static floatx80 (*const monadic_extended[16])(floatx80 rFm) = {
[NRM_CODE >> 20] = floatx80_mvf,
};
unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd)
unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
{
FPA11 *fpa11 = GET_FPA11();
floatx80 rFm;
......@@ -138,13 +138,13 @@ unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd)
}
if (dyadic_extended[opc_mask_shift]) {
rFd->fExtended = dyadic_extended[opc_mask_shift](rFn, rFm);
rFd->fExtended = dyadic_extended[opc_mask_shift](roundData, rFn, rFm);
} else {
return 0;
}
} else {
if (monadic_extended[opc_mask_shift]) {
rFd->fExtended = monadic_extended[opc_mask_shift](rFm);
rFd->fExtended = monadic_extended[opc_mask_shift](roundData, rFm);
} else {
return 0;
}
......
......@@ -51,48 +51,42 @@ static void resetFPA11(void)
fpa11->fpsr = FP_EMULATOR | BIT_AC;
}
void SetRoundingMode(const unsigned int opcode)
int8 SetRoundingMode(const unsigned int opcode)
{
switch (opcode & MASK_ROUNDING_MODE) {
default:
case ROUND_TO_NEAREST:
float_rounding_mode = float_round_nearest_even;
break;
return float_round_nearest_even;
case ROUND_TO_PLUS_INFINITY:
float_rounding_mode = float_round_up;
break;
return float_round_up;
case ROUND_TO_MINUS_INFINITY:
float_rounding_mode = float_round_down;
break;
return float_round_down;
case ROUND_TO_ZERO:
float_rounding_mode = float_round_to_zero;
break;
return float_round_to_zero;
}
}
void SetRoundingPrecision(const unsigned int opcode)
int8 SetRoundingPrecision(const unsigned int opcode)
{
#ifdef CONFIG_FPE_NWFPE_XP
switch (opcode & MASK_ROUNDING_PRECISION) {
case ROUND_SINGLE:
floatx80_rounding_precision = 32;
break;
return 32;
case ROUND_DOUBLE:
floatx80_rounding_precision = 64;
break;
return 64;
case ROUND_EXTENDED:
floatx80_rounding_precision = 80;
break;
return 80;
default:
floatx80_rounding_precision = 80;
return 80;
}
#endif
return 80;
}
void nwfpe_init_fpa(union fp_state *fp)
......@@ -103,8 +97,6 @@ void nwfpe_init_fpa(union fp_state *fp)
#endif
memset(fpa11, 0, sizeof(FPA11));
resetFPA11();
SetRoundingMode(ROUND_TO_NEAREST);
SetRoundingPrecision(ROUND_EXTENDED);
fpa11->initflag = 1;
}
......
......@@ -37,6 +37,13 @@
/* includes */
#include "fpsr.h" /* FP control and status register definitions */
#include "milieu.h"
struct roundingData {
int8 mode;
int8 precision;
signed char exception;
};
#include "softfloat.h"
#define typeNone 0x00
......@@ -84,8 +91,8 @@ typedef struct tagFPA11 {
initialised. */
} FPA11;
extern void SetRoundingMode(const unsigned int);
extern void SetRoundingPrecision(const unsigned int);
extern int8 SetRoundingMode(const unsigned int);
extern int8 SetRoundingPrecision(const unsigned int);
extern void nwfpe_init_fpa(union fp_state *fp);
#endif
......@@ -24,15 +24,16 @@
#include "fpa11.h"
#include "fpopcode.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);
unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
unsigned int EmulateCPDO(const unsigned int opcode)
{
FPA11 *fpa11 = GET_FPA11();
FPREG *rFd;
unsigned int nType, nDest, nRc;
struct roundingData roundData;
/* Get the destination size. If not valid let Linux perform
an invalid instruction trap. */
......@@ -40,7 +41,9 @@ unsigned int EmulateCPDO(const unsigned int opcode)
if (typeNone == nDest)
return 0;
SetRoundingMode(opcode);
roundData.mode = SetRoundingMode(opcode);
roundData.precision = SetRoundingPrecision(opcode);
roundData.exception = 0;
/* Compare the size of the operands in Fn and Fm.
Choose the largest size and perform operations in that size,
......@@ -63,14 +66,14 @@ unsigned int EmulateCPDO(const unsigned int opcode)
switch (nType) {
case typeSingle:
nRc = SingleCPDO(opcode, rFd);
nRc = SingleCPDO(&roundData, opcode, rFd);
break;
case typeDouble:
nRc = DoubleCPDO(opcode, rFd);
nRc = DoubleCPDO(&roundData, opcode, rFd);
break;
#ifdef CONFIG_FPE_NWFPE_XP
case typeExtended:
nRc = ExtendedCPDO(opcode, rFd);
nRc = ExtendedCPDO(&roundData, opcode, rFd);
break;
#endif
default:
......@@ -93,9 +96,9 @@ unsigned int EmulateCPDO(const unsigned int opcode)
case typeSingle:
{
if (typeDouble == nType)
rFd->fSingle = float64_to_float32(rFd->fDouble);
rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);
else
rFd->fSingle = floatx80_to_float32(rFd->fExtended);
rFd->fSingle = floatx80_to_float32(&roundData, rFd->fExtended);
}
break;
......@@ -104,7 +107,7 @@ unsigned int EmulateCPDO(const unsigned int opcode)
if (typeSingle == nType)
rFd->fDouble = float32_to_float64(rFd->fSingle);
else
rFd->fDouble = floatx80_to_float64(rFd->fExtended);
rFd->fDouble = floatx80_to_float64(&roundData, rFd->fExtended);
}
break;
......@@ -121,12 +124,15 @@ unsigned int EmulateCPDO(const unsigned int opcode)
#else
if (nDest != nType) {
if (nDest == typeSingle)
rFd->fSingle = float64_to_float32(rFd->fDouble);
rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);
else
rFd->fDouble = float32_to_float64(rFd->fSingle);
}
#endif
}
if (roundData.exception)
float_raise(roundData.exception);
return nRc;
}
......@@ -96,7 +96,7 @@ static inline void loadMultiple(const unsigned int Fn, const unsigned int __user
}
}
static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem)
static inline void storeSingle(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
{
FPA11 *fpa11 = GET_FPA11();
union {
......@@ -106,12 +106,12 @@ static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem)
switch (fpa11->fType[Fn]) {
case typeDouble:
val.f = float64_to_float32(fpa11->fpreg[Fn].fDouble);
val.f = float64_to_float32(roundData, fpa11->fpreg[Fn].fDouble);
break;
#ifdef CONFIG_FPE_NWFPE_XP
case typeExtended:
val.f = floatx80_to_float32(fpa11->fpreg[Fn].fExtended);
val.f = floatx80_to_float32(roundData, fpa11->fpreg[Fn].fExtended);
break;
#endif
......@@ -122,7 +122,7 @@ static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem)
put_user(val.i[0], pMem);
}
static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem)
static inline void storeDouble(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
{
FPA11 *fpa11 = GET_FPA11();
union {
......@@ -137,7 +137,7 @@ static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem)
#ifdef CONFIG_FPE_NWFPE_XP
case typeExtended:
val.f = floatx80_to_float64(fpa11->fpreg[Fn].fExtended);
val.f = floatx80_to_float64(roundData, fpa11->fpreg[Fn].fExtended);
break;
#endif
......@@ -259,8 +259,11 @@ unsigned int PerformSTF(const unsigned int opcode)
{
unsigned int __user *pBase, *pAddress, *pFinal;
unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
struct roundingData roundData;
SetRoundingMode(ROUND_TO_NEAREST);
roundData.mode = SetRoundingMode(opcode);
roundData.precision = SetRoundingPrecision(opcode);
roundData.exception = 0;
pBase = (unsigned int __user *) readRegister(getRn(opcode));
if (REG_PC == getRn(opcode)) {
......@@ -281,10 +284,10 @@ unsigned int PerformSTF(const unsigned int opcode)
switch (opcode & MASK_TRANSFER_LENGTH) {
case TRANSFER_SINGLE:
storeSingle(getFd(opcode), pAddress);
storeSingle(&roundData, getFd(opcode), pAddress);
break;
case TRANSFER_DOUBLE:
storeDouble(getFd(opcode), pAddress);
storeDouble(&roundData, getFd(opcode), pAddress);
break;
#ifdef CONFIG_FPE_NWFPE_XP
case TRANSFER_EXTENDED:
......@@ -295,6 +298,9 @@ unsigned int PerformSTF(const unsigned int opcode)
nRc = 0;
}
if (roundData.exception)
float_raise(roundData.exception);
if (write_back)
writeRegister(getRn(opcode), (unsigned long) pFinal);
return nRc;
......
......@@ -33,8 +33,6 @@ extern flag floatx80_is_nan(floatx80);
extern flag float64_is_nan(float64);
extern flag float32_is_nan(float32);
void SetRoundingMode(const unsigned int opcode);
unsigned int PerformFLT(const unsigned int opcode);
unsigned int PerformFIX(const unsigned int opcode);
......@@ -77,14 +75,17 @@ unsigned int EmulateCPRT(const unsigned int opcode)
unsigned int PerformFLT(const unsigned int opcode)
{
FPA11 *fpa11 = GET_FPA11();
SetRoundingMode(opcode);
SetRoundingPrecision(opcode);
struct roundingData roundData;
roundData.mode = SetRoundingMode(opcode);
roundData.precision = SetRoundingPrecision(opcode);
roundData.exception = 0;
switch (opcode & MASK_ROUNDING_PRECISION) {
case ROUND_SINGLE:
{
fpa11->fType[getFn(opcode)] = typeSingle;
fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(readRegister(getRd(opcode)));
fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(&roundData, readRegister(getRd(opcode)));
}
break;
......@@ -108,6 +109,9 @@ unsigned int PerformFLT(const unsigned int opcode)
return 0;
}
if (roundData.exception)
float_raise(roundData.exception);
return 1;
}
......@@ -115,26 +119,29 @@ unsigned int PerformFIX(const unsigned int opcode)
{
FPA11 *fpa11 = GET_FPA11();
unsigned int Fn = getFm(opcode);
struct roundingData roundData;
SetRoundingMode(opcode);
roundData.mode = SetRoundingMode(opcode);
roundData.precision = SetRoundingPrecision(opcode);
roundData.exception = 0;
switch (fpa11->fType[Fn]) {
case typeSingle:
{
writeRegister(getRd(opcode), float32_to_int32(fpa11->fpreg[Fn].fSingle));
writeRegister(getRd(opcode), float32_to_int32(&roundData, fpa11->fpreg[Fn].fSingle));
}
break;
case typeDouble:
{
writeRegister(getRd(opcode), float64_to_int32(fpa11->fpreg[Fn].fDouble));
writeRegister(getRd(opcode), float64_to_int32(&roundData, fpa11->fpreg[Fn].fDouble));
}
break;
#ifdef CONFIG_FPE_NWFPE_XP
case typeExtended:
{
writeRegister(getRd(opcode), floatx80_to_int32(fpa11->fpreg[Fn].fExtended));
writeRegister(getRd(opcode), floatx80_to_int32(&roundData, fpa11->fpreg[Fn].fExtended));
}
break;
#endif
......@@ -143,6 +150,9 @@ unsigned int PerformFIX(const unsigned int opcode)
return 0;
}
if (roundData.exception)
float_raise(roundData.exception);
return 1;
}
......
......@@ -116,8 +116,6 @@ fpmodule.c to integrate with the NetBSD kernel (I hope!).
code to access data in user space in some other source files at the
moment (grep for get_user / put_user calls). --philb]
float_exception_flags is a global variable in SoftFloat.
This function is called by the SoftFloat routines to raise a floating
point exception. We check the trap enable byte in the FPSR, and raise
a SIGFPE exception if necessary. If not the relevant bits in the
......@@ -129,15 +127,14 @@ void float_raise(signed char flags)
register unsigned int fpsr, cumulativeTraps;
#ifdef CONFIG_DEBUG_USER
printk(KERN_DEBUG
"NWFPE: %s[%d] takes exception %08x at %p from %08lx\n",
current->comm, current->pid, flags,
__builtin_return_address(0), GET_USERREG()->ARM_pc);
/* Ignore inexact errors as there are far too many of them to log */
if (flags & ~BIT_IXC)
printk(KERN_DEBUG
"NWFPE: %s[%d] takes exception %08x at %p from %08lx\n",
current->comm, current->pid, flags,
__builtin_return_address(0), GET_USERREG()->ARM_pc);
#endif
/* Keep SoftFloat exception flags up to date. */
float_exception_flags |= flags;
/* Read fpsr and initialize the cumulativeTraps. */
fpsr = readFPSR();
cumulativeTraps = 0;
......
......@@ -36,17 +36,17 @@ float32 float32_arccos(float32 rFm);
float32 float32_pow(float32 rFn, float32 rFm);
float32 float32_pol(float32 rFn, float32 rFm);
static float32 float32_rsf(float32 rFn, float32 rFm)
static float32 float32_rsf(struct roundingData *roundData, float32 rFn, float32 rFm)
{
return float32_sub(rFm, rFn);
return float32_sub(roundData, rFm, rFn);
}
static float32 float32_rdv(float32 rFn, float32 rFm)
static float32 float32_rdv(struct roundingData *roundData, float32 rFn, float32 rFm)
{
return float32_div(rFm, rFn);
return float32_div(roundData, rFm, rFn);
}
static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = {
static float32 (*const dyadic_single[16])(struct roundingData *, float32 rFn, float32 rFm) = {
[ADF_CODE >> 20] = float32_add,
[MUF_CODE >> 20] = float32_mul,
[SUF_CODE >> 20] = float32_sub,
......@@ -60,22 +60,22 @@ static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = {
[FRD_CODE >> 20] = float32_rdv,
};
static float32 float32_mvf(float32 rFm)
static float32 float32_mvf(struct roundingData *roundData, float32 rFm)
{
return rFm;
}
static float32 float32_mnf(float32 rFm)
static float32 float32_mnf(struct roundingData *roundData, float32 rFm)
{
return rFm ^ 0x80000000;
}
static float32 float32_abs(float32 rFm)
static float32 float32_abs(struct roundingData *roundData, float32 rFm)
{
return rFm & 0x7fffffff;
}
static float32 (*const monadic_single[16])(float32 rFm) = {
static float32 (*const monadic_single[16])(struct roundingData*, float32 rFm) = {
[MVF_CODE >> 20] = float32_mvf,
[MNF_CODE >> 20] = float32_mnf,
[ABS_CODE >> 20] = float32_abs,
......@@ -85,7 +85,7 @@ static float32 (*const monadic_single[16])(float32 rFm) = {
[NRM_CODE >> 20] = float32_mvf,
};
unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd)
unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
{
FPA11 *fpa11 = GET_FPA11();
float32 rFm;
......@@ -108,13 +108,13 @@ unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd)
if (fpa11->fType[Fn] == typeSingle &&
dyadic_single[opc_mask_shift]) {
rFn = fpa11->fpreg[Fn].fSingle;
rFd->fSingle = dyadic_single[opc_mask_shift](rFn, rFm);
rFd->fSingle = dyadic_single[opc_mask_shift](roundData, rFn, rFm);
} else {
return 0;
}
} else {
if (monadic_single[opc_mask_shift]) {
rFd->fSingle = monadic_single[opc_mask_shift](rFm);
rFd->fSingle = monadic_single[opc_mask_shift](roundData, rFm);
} else {
return 0;
}
......
......@@ -34,16 +34,6 @@ this code that are retained.
//#include "milieu.h"
//#include "softfloat.h"
/*
-------------------------------------------------------------------------------
Floating-point rounding mode, extended double-precision rounding precision,
and exception flags.
-------------------------------------------------------------------------------
*/
int8 float_rounding_mode = float_round_nearest_even;
int8 floatx80_rounding_precision = 80;
int8 float_exception_flags;
/*
-------------------------------------------------------------------------------
Primitive arithmetic functions, including multi-word arithmetic, and
......@@ -77,14 +67,14 @@ input is too large, however, the invalid exception is raised and the largest
positive or negative integer is returned.
-------------------------------------------------------------------------------
*/
static int32 roundAndPackInt32( flag zSign, bits64 absZ )
static int32 roundAndPackInt32( struct roundingData *roundData, flag zSign, bits64 absZ )
{
int8 roundingMode;
flag roundNearestEven;
int8 roundIncrement, roundBits;
int32 z;
roundingMode = float_rounding_mode;
roundingMode = roundData->mode;
roundNearestEven = ( roundingMode == float_round_nearest_even );
roundIncrement = 0x40;
if ( ! roundNearestEven ) {
......@@ -107,10 +97,10 @@ static int32 roundAndPackInt32( flag zSign, bits64 absZ )
z = absZ;
if ( zSign ) z = - z;
if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) {
float_exception_flags |= float_flag_invalid;
roundData->exception |= float_flag_invalid;
return zSign ? 0x80000000 : 0x7FFFFFFF;
}
if ( roundBits ) float_exception_flags |= float_flag_inexact;
if ( roundBits ) roundData->exception |= float_flag_inexact;
return z;
}
......@@ -224,14 +214,14 @@ The handling of underflow and overflow follows the IEC/IEEE Standard for
Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
static float32 roundAndPackFloat32( struct roundingData *roundData, flag zSign, int16 zExp, bits32 zSig )
{
int8 roundingMode;
flag roundNearestEven;
int8 roundIncrement, roundBits;
flag isTiny;
roundingMode = float_rounding_mode;
roundingMode = roundData->mode;
roundNearestEven = ( roundingMode == float_round_nearest_even );
roundIncrement = 0x40;
if ( ! roundNearestEven ) {
......@@ -254,7 +244,7 @@ static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
|| ( ( zExp == 0xFD )
&& ( (sbits32) ( zSig + roundIncrement ) < 0 ) )
) {
float_raise( float_flag_overflow | float_flag_inexact );
roundData->exception |= float_flag_overflow | float_flag_inexact;
return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 );
}
if ( zExp < 0 ) {
......@@ -265,10 +255,10 @@ static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
shift32RightJamming( zSig, - zExp, &zSig );
zExp = 0;
roundBits = zSig & 0x7F;
if ( isTiny && roundBits ) float_raise( float_flag_underflow );
if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow;
}
}
if ( roundBits ) float_exception_flags |= float_flag_inexact;
if ( roundBits ) roundData->exception |= float_flag_inexact;
zSig = ( zSig + roundIncrement )>>7;
zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
if ( zSig == 0 ) zExp = 0;
......@@ -287,12 +277,12 @@ point exponent.
-------------------------------------------------------------------------------
*/
static float32
normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
normalizeRoundAndPackFloat32( struct roundingData *roundData, flag zSign, int16 zExp, bits32 zSig )
{
int8 shiftCount;
shiftCount = countLeadingZeros32( zSig ) - 1;
return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<<shiftCount );
return roundAndPackFloat32( roundData, zSign, zExp - shiftCount, zSig<<shiftCount );
}
......@@ -395,14 +385,14 @@ The handling of underflow and overflow follows the IEC/IEEE Standard for
Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig )
static float64 roundAndPackFloat64( struct roundingData *roundData, flag zSign, int16 zExp, bits64 zSig )
{
int8 roundingMode;
flag roundNearestEven;
int16 roundIncrement, roundBits;
flag isTiny;
roundingMode = float_rounding_mode;
roundingMode = roundData->mode;
roundNearestEven = ( roundingMode == float_round_nearest_even );
roundIncrement = 0x200;
if ( ! roundNearestEven ) {
......@@ -427,7 +417,7 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig )
) {
//register int lr = __builtin_return_address(0);
//printk("roundAndPackFloat64 called from 0x%08x\n",lr);
float_raise( float_flag_overflow | float_flag_inexact );
roundData->exception |= float_flag_overflow | float_flag_inexact;
return packFloat64( zSign, 0x7FF, 0 ) - ( roundIncrement == 0 );
}
if ( zExp < 0 ) {
......@@ -438,10 +428,10 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig )
shift64RightJamming( zSig, - zExp, &zSig );
zExp = 0;
roundBits = zSig & 0x3FF;
if ( isTiny && roundBits ) float_raise( float_flag_underflow );
if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow;
}
}
if ( roundBits ) float_exception_flags |= float_flag_inexact;
if ( roundBits ) roundData->exception |= float_flag_inexact;
zSig = ( zSig + roundIncrement )>>10;
zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven );
if ( zSig == 0 ) zExp = 0;
......@@ -460,12 +450,12 @@ point exponent.
-------------------------------------------------------------------------------
*/
static float64
normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig )
normalizeRoundAndPackFloat64( struct roundingData *roundData, flag zSign, int16 zExp, bits64 zSig )
{
int8 shiftCount;
shiftCount = countLeadingZeros64( zSig ) - 1;
return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<<shiftCount );
return roundAndPackFloat64( roundData, zSign, zExp - shiftCount, zSig<<shiftCount );
}
......@@ -572,14 +562,15 @@ Floating-point Arithmetic.
*/
static floatx80
roundAndPackFloatx80(
int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
struct roundingData *roundData, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
)
{
int8 roundingMode;
int8 roundingMode, roundingPrecision;
flag roundNearestEven, increment, isTiny;
int64 roundIncrement, roundMask, roundBits;
roundingMode = float_rounding_mode;
roundingMode = roundData->mode;
roundingPrecision = roundData->precision;
roundNearestEven = ( roundingMode == float_round_nearest_even );
if ( roundingPrecision == 80 ) goto precision80;
if ( roundingPrecision == 64 ) {
......@@ -623,8 +614,8 @@ static floatx80
shift64RightJamming( zSig0, 1 - zExp, &zSig0 );
zExp = 0;
roundBits = zSig0 & roundMask;
if ( isTiny && roundBits ) float_raise( float_flag_underflow );
if ( roundBits ) float_exception_flags |= float_flag_inexact;
if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow;
if ( roundBits ) roundData->exception |= float_flag_inexact;
zSig0 += roundIncrement;
if ( (sbits64) zSig0 < 0 ) zExp = 1;
roundIncrement = roundMask + 1;
......@@ -635,7 +626,7 @@ static floatx80
return packFloatx80( zSign, zExp, zSig0 );
}
}
if ( roundBits ) float_exception_flags |= float_flag_inexact;
if ( roundBits ) roundData->exception |= float_flag_inexact;
zSig0 += roundIncrement;
if ( zSig0 < roundIncrement ) {
++zExp;
......@@ -672,7 +663,7 @@ static floatx80
) {
roundMask = 0;
overflow:
float_raise( float_flag_overflow | float_flag_inexact );
roundData->exception |= float_flag_overflow | float_flag_inexact;
if ( ( roundingMode == float_round_to_zero )
|| ( zSign && ( roundingMode == float_round_up ) )
|| ( ! zSign && ( roundingMode == float_round_down ) )
......@@ -689,8 +680,8 @@ static floatx80
|| ( zSig0 < LIT64( 0xFFFFFFFFFFFFFFFF ) );
shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 );
zExp = 0;
if ( isTiny && zSig1 ) float_raise( float_flag_underflow );
if ( zSig1 ) float_exception_flags |= float_flag_inexact;
if ( isTiny && zSig1 ) roundData->exception |= float_flag_underflow;
if ( zSig1 ) roundData->exception |= float_flag_inexact;
if ( roundNearestEven ) {
increment = ( (sbits64) zSig1 < 0 );
}
......@@ -710,7 +701,7 @@ static floatx80
return packFloatx80( zSign, zExp, zSig0 );
}
}
if ( zSig1 ) float_exception_flags |= float_flag_inexact;
if ( zSig1 ) roundData->exception |= float_flag_inexact;
if ( increment ) {
++zSig0;
if ( zSig0 == 0 ) {
......@@ -740,7 +731,7 @@ normalized.
*/
static floatx80
normalizeRoundAndPackFloatx80(
int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
struct roundingData *roundData, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
)
{
int8 shiftCount;
......@@ -754,7 +745,7 @@ static floatx80
shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
zExp -= shiftCount;
return
roundAndPackFloatx80( roundingPrecision, zSign, zExp, zSig0, zSig1 );
roundAndPackFloatx80( roundData, zSign, zExp, zSig0, zSig1 );
}
......@@ -767,14 +758,14 @@ the single-precision floating-point format. The conversion is performed
according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
float32 int32_to_float32( int32 a )
float32 int32_to_float32(struct roundingData *roundData, int32 a)
{
flag zSign;
if ( a == 0 ) return 0;
if ( a == 0x80000000 ) return packFloat32( 1, 0x9E, 0 );
zSign = ( a < 0 );
return normalizeRoundAndPackFloat32( zSign, 0x9C, zSign ? - a : a );
return normalizeRoundAndPackFloat32( roundData, zSign, 0x9C, zSign ? - a : a );
}
......@@ -840,7 +831,7 @@ positive integer is returned. Otherwise, if the conversion overflows, the
largest integer with the same sign as `a' is returned.
-------------------------------------------------------------------------------
*/
int32 float32_to_int32( float32 a )
int32 float32_to_int32( struct roundingData *roundData, float32 a )
{
flag aSign;
int16 aExp, shiftCount;
......@@ -856,7 +847,7 @@ int32 float32_to_int32( float32 a )
zSig = aSig;
zSig <<= 32;
if ( 0 < shiftCount ) shift64RightJamming( zSig, shiftCount, &zSig );
return roundAndPackInt32( aSign, zSig );
return roundAndPackInt32( roundData, aSign, zSig );
}
......@@ -889,13 +880,13 @@ int32 float32_to_int32_round_to_zero( float32 a )
return 0x80000000;
}
else if ( aExp <= 0x7E ) {
if ( aExp | aSig ) float_exception_flags |= float_flag_inexact;
if ( aExp | aSig ) float_raise( float_flag_inexact );
return 0;
}
aSig = ( aSig | 0x00800000 )<<8;
z = aSig>>( - shiftCount );
if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) {
float_exception_flags |= float_flag_inexact;
float_raise( float_flag_inexact );
}
return aSign ? - z : z;
......@@ -973,7 +964,7 @@ operation is performed according to the IEC/IEEE Standard for Binary
Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
float32 float32_round_to_int( float32 a )
float32 float32_round_to_int( struct roundingData *roundData, float32 a )
{
flag aSign;
int16 aExp;
......@@ -988,11 +979,12 @@ float32 float32_round_to_int( float32 a )
}
return a;
}
roundingMode = roundData->mode;
if ( aExp <= 0x7E ) {
if ( (bits32) ( a<<1 ) == 0 ) return a;
float_exception_flags |= float_flag_inexact;
roundData->exception |= float_flag_inexact;
aSign = extractFloat32Sign( a );
switch ( float_rounding_mode ) {
switch ( roundingMode ) {
case float_round_nearest_even:
if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) {
return packFloat32( aSign, 0x7F, 0 );
......@@ -1009,7 +1001,6 @@ float32 float32_round_to_int( float32 a )
lastBitMask <<= 0x96 - aExp;
roundBitsMask = lastBitMask - 1;
z = a;
roundingMode = float_rounding_mode;
if ( roundingMode == float_round_nearest_even ) {
z += lastBitMask>>1;
if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
......@@ -1020,7 +1011,7 @@ float32 float32_round_to_int( float32 a )
}
}
z &= ~ roundBitsMask;
if ( z != a ) float_exception_flags |= float_flag_inexact;
if ( z != a ) roundData->exception |= float_flag_inexact;
return z;
}
......@@ -1034,7 +1025,7 @@ addition is performed according to the IEC/IEEE Standard for Binary
Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
static float32 addFloat32Sigs( float32 a, float32 b, flag zSign )
static float32 addFloat32Sigs( struct roundingData *roundData, float32 a, float32 b, flag zSign )
{
int16 aExp, bExp, zExp;
bits32 aSig, bSig, zSig;
......@@ -1093,7 +1084,7 @@ static float32 addFloat32Sigs( float32 a, float32 b, flag zSign )
++zExp;
}
roundAndPack:
return roundAndPackFloat32( zSign, zExp, zSig );
return roundAndPackFloat32( roundData, zSign, zExp, zSig );
}
......@@ -1106,7 +1097,7 @@ result is a NaN. The subtraction is performed according to the IEC/IEEE
Standard for Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
static float32 subFloat32Sigs( float32 a, float32 b, flag zSign )
static float32 subFloat32Sigs( struct roundingData *roundData, float32 a, float32 b, flag zSign )
{
int16 aExp, bExp, zExp;
bits32 aSig, bSig, zSig;
......@@ -1123,7 +1114,7 @@ static float32 subFloat32Sigs( float32 a, float32 b, flag zSign )
if ( expDiff < 0 ) goto bExpBigger;
if ( aExp == 0xFF ) {
if ( aSig | bSig ) return propagateFloat32NaN( a, b );
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return float32_default_nan;
}
if ( aExp == 0 ) {
......@@ -1132,7 +1123,7 @@ static float32 subFloat32Sigs( float32 a, float32 b, flag zSign )
}
if ( bSig < aSig ) goto aBigger;
if ( aSig < bSig ) goto bBigger;
return packFloat32( float_rounding_mode == float_round_down, 0, 0 );
return packFloat32( roundData->mode == float_round_down, 0, 0 );
bExpBigger:
if ( bExp == 0xFF ) {
if ( bSig ) return propagateFloat32NaN( a, b );
......@@ -1169,7 +1160,7 @@ static float32 subFloat32Sigs( float32 a, float32 b, flag zSign )
zExp = aExp;
normalizeRoundAndPack:
--zExp;
return normalizeRoundAndPackFloat32( zSign, zExp, zSig );
return normalizeRoundAndPackFloat32( roundData, zSign, zExp, zSig );
}
......@@ -1180,17 +1171,17 @@ and `b'. The operation is performed according to the IEC/IEEE Standard for
Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
float32 float32_add( float32 a, float32 b )
float32 float32_add( struct roundingData *roundData, float32 a, float32 b )
{
flag aSign, bSign;
aSign = extractFloat32Sign( a );
bSign = extractFloat32Sign( b );
if ( aSign == bSign ) {
return addFloat32Sigs( a, b, aSign );
return addFloat32Sigs( roundData, a, b, aSign );
}
else {
return subFloat32Sigs( a, b, aSign );
return subFloat32Sigs( roundData, a, b, aSign );
}
}
......@@ -1202,17 +1193,17 @@ Returns the result of subtracting the single-precision floating-point values
for Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
float32 float32_sub( float32 a, float32 b )
float32 float32_sub( struct roundingData *roundData, float32 a, float32 b )
{
flag aSign, bSign;
aSign = extractFloat32Sign( a );
bSign = extractFloat32Sign( b );
if ( aSign == bSign ) {
return subFloat32Sigs( a, b, aSign );
return subFloat32Sigs( roundData, a, b, aSign );
}
else {
return addFloat32Sigs( a, b, aSign );
return addFloat32Sigs( roundData, a, b, aSign );
}
}
......@@ -1224,7 +1215,7 @@ Returns the result of multiplying the single-precision floating-point values
for Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
float32 float32_mul( float32 a, float32 b )
float32 float32_mul( struct roundingData *roundData, float32 a, float32 b )
{
flag aSign, bSign, zSign;
int16 aExp, bExp, zExp;
......@@ -1244,7 +1235,7 @@ float32 float32_mul( float32 a, float32 b )
return propagateFloat32NaN( a, b );
}
if ( ( bExp | bSig ) == 0 ) {
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return float32_default_nan;
}
return packFloat32( zSign, 0xFF, 0 );
......@@ -1252,7 +1243,7 @@ float32 float32_mul( float32 a, float32 b )
if ( bExp == 0xFF ) {
if ( bSig ) return propagateFloat32NaN( a, b );
if ( ( aExp | aSig ) == 0 ) {
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return float32_default_nan;
}
return packFloat32( zSign, 0xFF, 0 );
......@@ -1274,7 +1265,7 @@ float32 float32_mul( float32 a, float32 b )
zSig <<= 1;
--zExp;
}
return roundAndPackFloat32( zSign, zExp, zSig );
return roundAndPackFloat32( roundData, zSign, zExp, zSig );
}
......@@ -1285,7 +1276,7 @@ by the corresponding value `b'. The operation is performed according to the
IEC/IEEE Standard for Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
float32 float32_div( float32 a, float32 b )
float32 float32_div( struct roundingData *roundData, float32 a, float32 b )
{
flag aSign, bSign, zSign;
int16 aExp, bExp, zExp;
......@@ -1302,7 +1293,7 @@ float32 float32_div( float32 a, float32 b )
if ( aSig ) return propagateFloat32NaN( a, b );
if ( bExp == 0xFF ) {
if ( bSig ) return propagateFloat32NaN( a, b );
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return float32_default_nan;
}
return packFloat32( zSign, 0xFF, 0 );
......@@ -1314,10 +1305,10 @@ float32 float32_div( float32 a, float32 b )
if ( bExp == 0 ) {
if ( bSig == 0 ) {
if ( ( aExp | aSig ) == 0 ) {
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return float32_default_nan;
}
float_raise( float_flag_divbyzero );
roundData->exception |= float_flag_divbyzero;
return packFloat32( zSign, 0xFF, 0 );
}
normalizeFloat32Subnormal( bSig, &bExp, &bSig );
......@@ -1341,7 +1332,7 @@ float32 float32_div( float32 a, float32 b )
if ( ( zSig & 0x3F ) == 0 ) {
zSig |= ( ( (bits64) bSig ) * zSig != ( (bits64) aSig )<<32 );
}
return roundAndPackFloat32( zSign, zExp, zSig );
return roundAndPackFloat32( roundData, zSign, zExp, zSig );
}
......@@ -1352,7 +1343,7 @@ with respect to the corresponding value `b'. The operation is performed
according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
float32 float32_rem( float32 a, float32 b )
float32 float32_rem( struct roundingData *roundData, float32 a, float32 b )
{
flag aSign, bSign, zSign;
int16 aExp, bExp, expDiff;
......@@ -1372,7 +1363,7 @@ float32 float32_rem( float32 a, float32 b )
if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
return propagateFloat32NaN( a, b );
}
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return float32_default_nan;
}
if ( bExp == 0xFF ) {
......@@ -1381,7 +1372,7 @@ float32 float32_rem( float32 a, float32 b )
}
if ( bExp == 0 ) {
if ( bSig == 0 ) {
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return float32_default_nan;
}
normalizeFloat32Subnormal( bSig, &bExp, &bSig );
......@@ -1444,7 +1435,7 @@ float32 float32_rem( float32 a, float32 b )
}
zSign = ( (sbits32) aSig < 0 );
if ( zSign ) aSig = - aSig;
return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig );
return normalizeRoundAndPackFloat32( roundData, aSign ^ zSign, bExp, aSig );
}
......@@ -1455,7 +1446,7 @@ The operation is performed according to the IEC/IEEE Standard for Binary
Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
float32 float32_sqrt( float32 a )
float32 float32_sqrt( struct roundingData *roundData, float32 a )
{
flag aSign;
int16 aExp, zExp;
......@@ -1468,12 +1459,12 @@ float32 float32_sqrt( float32 a )
if ( aExp == 0xFF ) {
if ( aSig ) return propagateFloat32NaN( a, 0 );
if ( ! aSign ) return a;
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return float32_default_nan;
}
if ( aSign ) {
if ( ( aExp | aSig ) == 0 ) return a;
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return float32_default_nan;
}
if ( aExp == 0 ) {
......@@ -1499,7 +1490,7 @@ float32 float32_sqrt( float32 a )
}
}
shift32RightJamming( zSig, 1, &zSig );
return roundAndPackFloat32( 0, zExp, zSig );
return roundAndPackFloat32( roundData, 0, zExp, zSig );
}
......@@ -1661,7 +1652,7 @@ positive integer is returned. Otherwise, if the conversion overflows, the
largest integer with the same sign as `a' is returned.
-------------------------------------------------------------------------------
*/
int32 float64_to_int32( float64 a )
int32 float64_to_int32( struct roundingData *roundData, float64 a )
{
flag aSign;
int16 aExp, shiftCount;
......@@ -1674,7 +1665,7 @@ int32 float64_to_int32( float64 a )
if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
shiftCount = 0x42C - aExp;
if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig );
return roundAndPackInt32( aSign, aSig );
return roundAndPackInt32( roundData, aSign, aSig );
}
......@@ -1705,7 +1696,7 @@ int32 float64_to_int32_round_to_zero( float64 a )
goto invalid;
}
else if ( 52 < shiftCount ) {
if ( aExp || aSig ) float_exception_flags |= float_flag_inexact;
if ( aExp || aSig ) float_raise( float_flag_inexact );
return 0;
}
aSig |= LIT64( 0x0010000000000000 );
......@@ -1715,11 +1706,11 @@ int32 float64_to_int32_round_to_zero( float64 a )
if ( aSign ) z = - z;
if ( ( z < 0 ) ^ aSign ) {
invalid:
float_exception_flags |= float_flag_invalid;
float_raise( float_flag_invalid );
return aSign ? 0x80000000 : 0x7FFFFFFF;
}
if ( ( aSig<<shiftCount ) != savedASig ) {
float_exception_flags |= float_flag_inexact;
float_raise( float_flag_inexact );
}
return z;
......@@ -1736,7 +1727,7 @@ positive integer is returned. Otherwise, if the conversion overflows, the
largest positive integer is returned.
-------------------------------------------------------------------------------
*/
int32 float64_to_uint32( float64 a )
int32 float64_to_uint32( struct roundingData *roundData, float64 a )
{
flag aSign;
int16 aExp, shiftCount;
......@@ -1749,7 +1740,7 @@ int32 float64_to_uint32( float64 a )
if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
shiftCount = 0x42C - aExp;
if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig );
return roundAndPackInt32( aSign, aSig );
return roundAndPackInt32( roundData, aSign, aSig );
}
/*
......@@ -1778,7 +1769,7 @@ int32 float64_to_uint32_round_to_zero( float64 a )
goto invalid;
}
else if ( 52 < shiftCount ) {
if ( aExp || aSig ) float_exception_flags |= float_flag_inexact;
if ( aExp || aSig ) float_raise( float_flag_inexact );
return 0;
}
aSig |= LIT64( 0x0010000000000000 );
......@@ -1788,11 +1779,11 @@ int32 float64_to_uint32_round_to_zero( float64 a )
if ( aSign ) z = - z;
if ( ( z < 0 ) ^ aSign ) {
invalid:
float_exception_flags |= float_flag_invalid;
float_raise( float_flag_invalid );
return aSign ? 0x80000000 : 0x7FFFFFFF;
}
if ( ( aSig<<shiftCount ) != savedASig ) {
float_exception_flags |= float_flag_inexact;
float_raise( float_flag_inexact );
}
return z;
}
......@@ -1805,7 +1796,7 @@ performed according to the IEC/IEEE Standard for Binary Floating-point
Arithmetic.
-------------------------------------------------------------------------------
*/
float32 float64_to_float32( float64 a )
float32 float64_to_float32( struct roundingData *roundData, float64 a )
{
flag aSign;
int16 aExp;
......@@ -1825,7 +1816,7 @@ float32 float64_to_float32( float64 a )
zSig |= 0x40000000;
aExp -= 0x381;
}
return roundAndPackFloat32( aSign, aExp, zSig );
return roundAndPackFloat32( roundData, aSign, aExp, zSig );
}
......@@ -1872,7 +1863,7 @@ operation is performed according to the IEC/IEEE Standard for Binary
Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
float64 float64_round_to_int( float64 a )
float64 float64_round_to_int( struct roundingData *roundData, float64 a )
{
flag aSign;
int16 aExp;
......@@ -1889,9 +1880,9 @@ float64 float64_round_to_int( float64 a )
}
if ( aExp <= 0x3FE ) {
if ( (bits64) ( a<<1 ) == 0 ) return a;
float_exception_flags |= float_flag_inexact;
roundData->exception |= float_flag_inexact;
aSign = extractFloat64Sign( a );
switch ( float_rounding_mode ) {
switch ( roundData->mode ) {
case float_round_nearest_even:
if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) {
return packFloat64( aSign, 0x3FF, 0 );
......@@ -1909,7 +1900,7 @@ float64 float64_round_to_int( float64 a )
lastBitMask <<= 0x433 - aExp;
roundBitsMask = lastBitMask - 1;
z = a;
roundingMode = float_rounding_mode;
roundingMode = roundData->mode;
if ( roundingMode == float_round_nearest_even ) {
z += lastBitMask>>1;
if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
......@@ -1920,7 +1911,7 @@ float64 float64_round_to_int( float64 a )
}
}
z &= ~ roundBitsMask;
if ( z != a ) float_exception_flags |= float_flag_inexact;
if ( z != a ) roundData->exception |= float_flag_inexact;
return z;
}
......@@ -1934,7 +1925,7 @@ addition is performed according to the IEC/IEEE Standard for Binary
Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
static float64 addFloat64Sigs( float64 a, float64 b, flag zSign )
static float64 addFloat64Sigs( struct roundingData *roundData, float64 a, float64 b, flag zSign )
{
int16 aExp, bExp, zExp;
bits64 aSig, bSig, zSig;
......@@ -1993,7 +1984,7 @@ static float64 addFloat64Sigs( float64 a, float64 b, flag zSign )
++zExp;
}
roundAndPack:
return roundAndPackFloat64( zSign, zExp, zSig );
return roundAndPackFloat64( roundData, zSign, zExp, zSig );
}
......@@ -2006,7 +1997,7 @@ result is a NaN. The subtraction is performed according to the IEC/IEEE
Standard for Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
static float64 subFloat64Sigs( float64 a, float64 b, flag zSign )
static float64 subFloat64Sigs( struct roundingData *roundData, float64 a, float64 b, flag zSign )
{
int16 aExp, bExp, zExp;
bits64 aSig, bSig, zSig;
......@@ -2023,7 +2014,7 @@ static float64 subFloat64Sigs( float64 a, float64 b, flag zSign )
if ( expDiff < 0 ) goto bExpBigger;
if ( aExp == 0x7FF ) {
if ( aSig | bSig ) return propagateFloat64NaN( a, b );
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return float64_default_nan;
}
if ( aExp == 0 ) {
......@@ -2032,7 +2023,7 @@ static float64 subFloat64Sigs( float64 a, float64 b, flag zSign )
}
if ( bSig < aSig ) goto aBigger;
if ( aSig < bSig ) goto bBigger;
return packFloat64( float_rounding_mode == float_round_down, 0, 0 );
return packFloat64( roundData->mode == float_round_down, 0, 0 );
bExpBigger:
if ( bExp == 0x7FF ) {
if ( bSig ) return propagateFloat64NaN( a, b );
......@@ -2069,7 +2060,7 @@ static float64 subFloat64Sigs( float64 a, float64 b, flag zSign )
zExp = aExp;
normalizeRoundAndPack:
--zExp;
return normalizeRoundAndPackFloat64( zSign, zExp, zSig );
return normalizeRoundAndPackFloat64( roundData, zSign, zExp, zSig );
}
......@@ -2080,17 +2071,17 @@ and `b'. The operation is performed according to the IEC/IEEE Standard for
Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
float64 float64_add( float64 a, float64 b )
float64 float64_add( struct roundingData *roundData, float64 a, float64 b )
{
flag aSign, bSign;
aSign = extractFloat64Sign( a );
bSign = extractFloat64Sign( b );
if ( aSign == bSign ) {
return addFloat64Sigs( a, b, aSign );
return addFloat64Sigs( roundData, a, b, aSign );
}
else {
return subFloat64Sigs( a, b, aSign );
return subFloat64Sigs( roundData, a, b, aSign );
}
}
......@@ -2102,17 +2093,17 @@ Returns the result of subtracting the double-precision floating-point values
for Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
float64 float64_sub( float64 a, float64 b )
float64 float64_sub( struct roundingData *roundData, float64 a, float64 b )
{
flag aSign, bSign;
aSign = extractFloat64Sign( a );
bSign = extractFloat64Sign( b );
if ( aSign == bSign ) {
return subFloat64Sigs( a, b, aSign );
return subFloat64Sigs( roundData, a, b, aSign );
}
else {
return addFloat64Sigs( a, b, aSign );
return addFloat64Sigs( roundData, a, b, aSign );
}
}
......@@ -2124,7 +2115,7 @@ Returns the result of multiplying the double-precision floating-point values
for Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
float64 float64_mul( float64 a, float64 b )
float64 float64_mul( struct roundingData *roundData, float64 a, float64 b )
{
flag aSign, bSign, zSign;
int16 aExp, bExp, zExp;
......@@ -2142,7 +2133,7 @@ float64 float64_mul( float64 a, float64 b )
return propagateFloat64NaN( a, b );
}
if ( ( bExp | bSig ) == 0 ) {
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return float64_default_nan;
}
return packFloat64( zSign, 0x7FF, 0 );
......@@ -2150,7 +2141,7 @@ float64 float64_mul( float64 a, float64 b )
if ( bExp == 0x7FF ) {
if ( bSig ) return propagateFloat64NaN( a, b );
if ( ( aExp | aSig ) == 0 ) {
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return float64_default_nan;
}
return packFloat64( zSign, 0x7FF, 0 );
......@@ -2172,7 +2163,7 @@ float64 float64_mul( float64 a, float64 b )
zSig0 <<= 1;
--zExp;
}
return roundAndPackFloat64( zSign, zExp, zSig0 );
return roundAndPackFloat64( roundData, zSign, zExp, zSig0 );
}
......@@ -2183,7 +2174,7 @@ by the corresponding value `b'. The operation is performed according to
the IEC/IEEE Standard for Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
float64 float64_div( float64 a, float64 b )
float64 float64_div( struct roundingData *roundData, float64 a, float64 b )
{
flag aSign, bSign, zSign;
int16 aExp, bExp, zExp;
......@@ -2202,7 +2193,7 @@ float64 float64_div( float64 a, float64 b )
if ( aSig ) return propagateFloat64NaN( a, b );
if ( bExp == 0x7FF ) {
if ( bSig ) return propagateFloat64NaN( a, b );
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return float64_default_nan;
}
return packFloat64( zSign, 0x7FF, 0 );
......@@ -2214,10 +2205,10 @@ float64 float64_div( float64 a, float64 b )
if ( bExp == 0 ) {
if ( bSig == 0 ) {
if ( ( aExp | aSig ) == 0 ) {
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return float64_default_nan;
}
float_raise( float_flag_divbyzero );
roundData->exception |= float_flag_divbyzero;
return packFloat64( zSign, 0x7FF, 0 );
}
normalizeFloat64Subnormal( bSig, &bExp, &bSig );
......@@ -2243,7 +2234,7 @@ float64 float64_div( float64 a, float64 b )
}
zSig |= ( rem1 != 0 );
}
return roundAndPackFloat64( zSign, zExp, zSig );
return roundAndPackFloat64( roundData, zSign, zExp, zSig );
}
......@@ -2254,7 +2245,7 @@ with respect to the corresponding value `b'. The operation is performed
according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
float64 float64_rem( float64 a, float64 b )
float64 float64_rem( struct roundingData *roundData, float64 a, float64 b )
{
flag aSign, bSign, zSign;
int16 aExp, bExp, expDiff;
......@@ -2272,7 +2263,7 @@ float64 float64_rem( float64 a, float64 b )
if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) {
return propagateFloat64NaN( a, b );
}
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return float64_default_nan;
}
if ( bExp == 0x7FF ) {
......@@ -2281,7 +2272,7 @@ float64 float64_rem( float64 a, float64 b )
}
if ( bExp == 0 ) {
if ( bSig == 0 ) {
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return float64_default_nan;
}
normalizeFloat64Subnormal( bSig, &bExp, &bSig );
......@@ -2329,7 +2320,7 @@ float64 float64_rem( float64 a, float64 b )
}
zSign = ( (sbits64) aSig < 0 );
if ( zSign ) aSig = - aSig;
return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig );
return normalizeRoundAndPackFloat64( roundData, aSign ^ zSign, bExp, aSig );
}
......@@ -2340,7 +2331,7 @@ The operation is performed according to the IEC/IEEE Standard for Binary
Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
float64 float64_sqrt( float64 a )
float64 float64_sqrt( struct roundingData *roundData, float64 a )
{
flag aSign;
int16 aExp, zExp;
......@@ -2354,12 +2345,12 @@ float64 float64_sqrt( float64 a )
if ( aExp == 0x7FF ) {
if ( aSig ) return propagateFloat64NaN( a, a );
if ( ! aSign ) return a;
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return float64_default_nan;
}
if ( aSign ) {
if ( ( aExp | aSig ) == 0 ) return a;
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return float64_default_nan;
}
if ( aExp == 0 ) {
......@@ -2390,7 +2381,7 @@ float64 float64_sqrt( float64 a )
}
}
shift64RightJamming( zSig, 1, &zSig );
return roundAndPackFloat64( 0, zExp, zSig );
return roundAndPackFloat64( roundData, 0, zExp, zSig );
}
......@@ -2554,7 +2545,7 @@ largest positive integer is returned. Otherwise, if the conversion
overflows, the largest integer with the same sign as `a' is returned.
-------------------------------------------------------------------------------
*/
int32 floatx80_to_int32( floatx80 a )
int32 floatx80_to_int32( struct roundingData *roundData, floatx80 a )
{
flag aSign;
int32 aExp, shiftCount;
......@@ -2567,7 +2558,7 @@ int32 floatx80_to_int32( floatx80 a )
shiftCount = 0x4037 - aExp;
if ( shiftCount <= 0 ) shiftCount = 1;
shift64RightJamming( aSig, shiftCount, &aSig );
return roundAndPackInt32( aSign, aSig );
return roundAndPackInt32( roundData, aSign, aSig );
}
......@@ -2598,7 +2589,7 @@ int32 floatx80_to_int32_round_to_zero( floatx80 a )
goto invalid;
}
else if ( 63 < shiftCount ) {
if ( aExp || aSig ) float_exception_flags |= float_flag_inexact;
if ( aExp || aSig ) float_raise( float_flag_inexact );
return 0;
}
savedASig = aSig;
......@@ -2607,11 +2598,11 @@ int32 floatx80_to_int32_round_to_zero( floatx80 a )
if ( aSign ) z = - z;
if ( ( z < 0 ) ^ aSign ) {
invalid:
float_exception_flags |= float_flag_invalid;
float_raise( float_flag_invalid );
return aSign ? 0x80000000 : 0x7FFFFFFF;
}
if ( ( aSig<<shiftCount ) != savedASig ) {
float_exception_flags |= float_flag_inexact;
float_raise( float_flag_inexact );
}
return z;
......@@ -2625,7 +2616,7 @@ conversion is performed according to the IEC/IEEE Standard for Binary
Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
float32 floatx80_to_float32( floatx80 a )
float32 floatx80_to_float32( struct roundingData *roundData, floatx80 a )
{
flag aSign;
int32 aExp;
......@@ -2642,7 +2633,7 @@ float32 floatx80_to_float32( floatx80 a )
}
shift64RightJamming( aSig, 33, &aSig );
if ( aExp || aSig ) aExp -= 0x3F81;
return roundAndPackFloat32( aSign, aExp, aSig );
return roundAndPackFloat32( roundData, aSign, aExp, aSig );
}
......@@ -2654,7 +2645,7 @@ conversion is performed according to the IEC/IEEE Standard for Binary
Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
float64 floatx80_to_float64( floatx80 a )
float64 floatx80_to_float64( struct roundingData *roundData, floatx80 a )
{
flag aSign;
int32 aExp;
......@@ -2671,7 +2662,7 @@ float64 floatx80_to_float64( floatx80 a )
}
shift64RightJamming( aSig, 1, &zSig );
if ( aExp || aSig ) aExp -= 0x3C01;
return roundAndPackFloat64( aSign, aExp, zSig );
return roundAndPackFloat64( roundData, aSign, aExp, zSig );
}
......@@ -2683,7 +2674,7 @@ value. The operation is performed according to the IEC/IEEE Standard for
Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
floatx80 floatx80_round_to_int( floatx80 a )
floatx80 floatx80_round_to_int( struct roundingData *roundData, floatx80 a )
{
flag aSign;
int32 aExp;
......@@ -2703,9 +2694,9 @@ floatx80 floatx80_round_to_int( floatx80 a )
&& ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) {
return a;
}
float_exception_flags |= float_flag_inexact;
roundData->exception |= float_flag_inexact;
aSign = extractFloatx80Sign( a );
switch ( float_rounding_mode ) {
switch ( roundData->mode ) {
case float_round_nearest_even:
if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 )
) {
......@@ -2729,7 +2720,7 @@ floatx80 floatx80_round_to_int( floatx80 a )
lastBitMask <<= 0x403E - aExp;
roundBitsMask = lastBitMask - 1;
z = a;
roundingMode = float_rounding_mode;
roundingMode = roundData->mode;
if ( roundingMode == float_round_nearest_even ) {
z.low += lastBitMask>>1;
if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
......@@ -2744,7 +2735,7 @@ floatx80 floatx80_round_to_int( floatx80 a )
++z.high;
z.low = LIT64( 0x8000000000000000 );
}
if ( z.low != a.low ) float_exception_flags |= float_flag_inexact;
if ( z.low != a.low ) roundData->exception |= float_flag_inexact;
return z;
}
......@@ -2758,7 +2749,7 @@ The addition is performed according to the IEC/IEEE Standard for Binary
Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
static floatx80 addFloatx80Sigs( struct roundingData *roundData, floatx80 a, floatx80 b, flag zSign )
{
int32 aExp, bExp, zExp;
bits64 aSig, bSig, zSig0, zSig1;
......@@ -2814,7 +2805,7 @@ static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
roundAndPack:
return
roundAndPackFloatx80(
floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
roundData, zSign, zExp, zSig0, zSig1 );
}
......@@ -2827,7 +2818,7 @@ result is a NaN. The subtraction is performed according to the IEC/IEEE
Standard for Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
static floatx80 subFloatx80Sigs( struct roundingData *roundData, floatx80 a, floatx80 b, flag zSign )
{
int32 aExp, bExp, zExp;
bits64 aSig, bSig, zSig0, zSig1;
......@@ -2845,7 +2836,7 @@ static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
if ( (bits64) ( ( aSig | bSig )<<1 ) ) {
return propagateFloatx80NaN( a, b );
}
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
z.low = floatx80_default_nan_low;
z.high = floatx80_default_nan_high;
return z;
......@@ -2857,7 +2848,7 @@ static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
zSig1 = 0;
if ( bSig < aSig ) goto aBigger;
if ( aSig < bSig ) goto bBigger;
return packFloatx80( float_rounding_mode == float_round_down, 0, 0 );
return packFloatx80( roundData->mode == float_round_down, 0, 0 );
bExpBigger:
if ( bExp == 0x7FFF ) {
if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
......@@ -2883,7 +2874,7 @@ static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
normalizeRoundAndPack:
return
normalizeRoundAndPackFloatx80(
floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
roundData, zSign, zExp, zSig0, zSig1 );
}
......@@ -2894,17 +2885,17 @@ values `a' and `b'. The operation is performed according to the IEC/IEEE
Standard for Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
floatx80 floatx80_add( floatx80 a, floatx80 b )
floatx80 floatx80_add( struct roundingData *roundData, floatx80 a, floatx80 b )
{
flag aSign, bSign;
aSign = extractFloatx80Sign( a );
bSign = extractFloatx80Sign( b );
if ( aSign == bSign ) {
return addFloatx80Sigs( a, b, aSign );
return addFloatx80Sigs( roundData, a, b, aSign );
}
else {
return subFloatx80Sigs( a, b, aSign );
return subFloatx80Sigs( roundData, a, b, aSign );
}
}
......@@ -2916,17 +2907,17 @@ point values `a' and `b'. The operation is performed according to the
IEC/IEEE Standard for Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
floatx80 floatx80_sub( floatx80 a, floatx80 b )
floatx80 floatx80_sub( struct roundingData *roundData, floatx80 a, floatx80 b )
{
flag aSign, bSign;
aSign = extractFloatx80Sign( a );
bSign = extractFloatx80Sign( b );
if ( aSign == bSign ) {
return subFloatx80Sigs( a, b, aSign );
return subFloatx80Sigs( roundData, a, b, aSign );
}
else {
return addFloatx80Sigs( a, b, aSign );
return addFloatx80Sigs( roundData, a, b, aSign );
}
}
......@@ -2938,7 +2929,7 @@ point values `a' and `b'. The operation is performed according to the
IEC/IEEE Standard for Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
floatx80 floatx80_mul( floatx80 a, floatx80 b )
floatx80 floatx80_mul( struct roundingData *roundData, floatx80 a, floatx80 b )
{
flag aSign, bSign, zSign;
int32 aExp, bExp, zExp;
......@@ -2964,7 +2955,7 @@ floatx80 floatx80_mul( floatx80 a, floatx80 b )
if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
if ( ( aExp | aSig ) == 0 ) {
invalid:
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
z.low = floatx80_default_nan_low;
z.high = floatx80_default_nan_high;
return z;
......@@ -2987,7 +2978,7 @@ floatx80 floatx80_mul( floatx80 a, floatx80 b )
}
return
roundAndPackFloatx80(
floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
roundData, zSign, zExp, zSig0, zSig1 );
}
......@@ -2998,7 +2989,7 @@ value `a' by the corresponding value `b'. The operation is performed
according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
floatx80 floatx80_div( floatx80 a, floatx80 b )
floatx80 floatx80_div( struct roundingData *roundData, floatx80 a, floatx80 b )
{
flag aSign, bSign, zSign;
int32 aExp, bExp, zExp;
......@@ -3029,12 +3020,12 @@ floatx80 floatx80_div( floatx80 a, floatx80 b )
if ( bSig == 0 ) {
if ( ( aExp | aSig ) == 0 ) {
invalid:
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
z.low = floatx80_default_nan_low;
z.high = floatx80_default_nan_high;
return z;
}
float_raise( float_flag_divbyzero );
roundData->exception |= float_flag_divbyzero;
return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
}
normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
......@@ -3068,7 +3059,7 @@ floatx80 floatx80_div( floatx80 a, floatx80 b )
}
return
roundAndPackFloatx80(
floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
roundData, zSign, zExp, zSig0, zSig1 );
}
......@@ -3079,7 +3070,7 @@ Returns the remainder of the extended double-precision floating-point value
according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
floatx80 floatx80_rem( floatx80 a, floatx80 b )
floatx80 floatx80_rem( struct roundingData *roundData, floatx80 a, floatx80 b )
{
flag aSign, bSign, zSign;
int32 aExp, bExp, expDiff;
......@@ -3107,7 +3098,7 @@ floatx80 floatx80_rem( floatx80 a, floatx80 b )
if ( bExp == 0 ) {
if ( bSig == 0 ) {
invalid:
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
z.low = floatx80_default_nan_low;
z.high = floatx80_default_nan_high;
return z;
......@@ -3164,9 +3155,10 @@ floatx80 floatx80_rem( floatx80 a, floatx80 b )
aSig1 = alternateASig1;
zSign = ! zSign;
}
return
normalizeRoundAndPackFloatx80(
80, zSign, bExp + expDiff, aSig0, aSig1 );
roundData, zSign, bExp + expDiff, aSig0, aSig1 );
}
......@@ -3177,7 +3169,7 @@ value `a'. The operation is performed according to the IEC/IEEE Standard
for Binary Floating-point Arithmetic.
-------------------------------------------------------------------------------
*/
floatx80 floatx80_sqrt( floatx80 a )
floatx80 floatx80_sqrt( struct roundingData *roundData, floatx80 a )
{
flag aSign;
int32 aExp, zExp;
......@@ -3197,7 +3189,7 @@ floatx80 floatx80_sqrt( floatx80 a )
if ( aSign ) {
if ( ( aExp | aSig0 ) == 0 ) return a;
invalid:
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
z.low = floatx80_default_nan_low;
z.high = floatx80_default_nan_high;
return z;
......@@ -3242,7 +3234,7 @@ floatx80 floatx80_sqrt( floatx80 a )
}
return
roundAndPackFloatx80(
floatx80_rounding_precision, 0, zExp, zSig0, zSig1 );
roundData, 0, zExp, zSig0, zSig1 );
}
......@@ -3264,7 +3256,7 @@ flag floatx80_eq( floatx80 a, floatx80 b )
) {
if ( floatx80_is_signaling_nan( a )
|| floatx80_is_signaling_nan( b ) ) {
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
}
return 0;
}
......@@ -3294,7 +3286,7 @@ flag floatx80_le( floatx80 a, floatx80 b )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
&& (bits64) ( extractFloatx80Frac( b )<<1 ) )
) {
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return 0;
}
aSign = extractFloatx80Sign( a );
......@@ -3328,7 +3320,7 @@ flag floatx80_lt( floatx80 a, floatx80 b )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
&& (bits64) ( extractFloatx80Frac( b )<<1 ) )
) {
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return 0;
}
aSign = extractFloatx80Sign( a );
......@@ -3361,7 +3353,7 @@ flag floatx80_eq_signaling( floatx80 a, floatx80 b )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
&& (bits64) ( extractFloatx80Frac( b )<<1 ) )
) {
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
return 0;
}
return
......@@ -3392,7 +3384,7 @@ flag floatx80_le_quiet( floatx80 a, floatx80 b )
) {
if ( floatx80_is_signaling_nan( a )
|| floatx80_is_signaling_nan( b ) ) {
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
}
return 0;
}
......@@ -3429,7 +3421,7 @@ flag floatx80_lt_quiet( floatx80 a, floatx80 b )
) {
if ( floatx80_is_signaling_nan( a )
|| floatx80_is_signaling_nan( b ) ) {
float_raise( float_flag_invalid );
roundData->exception |= float_flag_invalid;
}
return 0;
}
......
......@@ -74,7 +74,7 @@ enum {
Software IEC/IEEE floating-point rounding mode.
-------------------------------------------------------------------------------
*/
extern signed char float_rounding_mode;
//extern int8 float_rounding_mode;
enum {
float_round_nearest_even = 0,
float_round_to_zero = 1,
......@@ -86,7 +86,6 @@ enum {
-------------------------------------------------------------------------------
Software IEC/IEEE floating-point exception flags.
-------------------------------------------------------------------------------
extern signed char float_exception_flags;
enum {
float_flag_inexact = 1,
float_flag_underflow = 2,
......@@ -99,7 +98,6 @@ ScottB: November 4, 1998
Changed the enumeration to match the bit order in the FPA11.
*/
extern signed char float_exception_flags;
enum {
float_flag_invalid = 1,
float_flag_divbyzero = 2,
......@@ -121,7 +119,7 @@ void float_raise( signed char );
Software IEC/IEEE integer-to-floating-point conversion routines.
-------------------------------------------------------------------------------
*/
float32 int32_to_float32( signed int );
float32 int32_to_float32( struct roundingData *, signed int );
float64 int32_to_float64( signed int );
#ifdef FLOATX80
floatx80 int32_to_floatx80( signed int );
......@@ -132,7 +130,7 @@ floatx80 int32_to_floatx80( signed int );
Software IEC/IEEE single-precision conversion routines.
-------------------------------------------------------------------------------
*/
signed int float32_to_int32( float32 );
signed int float32_to_int32( struct roundingData *, float32 );
signed int float32_to_int32_round_to_zero( float32 );
float64 float32_to_float64( float32 );
#ifdef FLOATX80
......@@ -144,13 +142,13 @@ floatx80 float32_to_floatx80( float32 );
Software IEC/IEEE single-precision operations.
-------------------------------------------------------------------------------
*/
float32 float32_round_to_int( float32 );
float32 float32_add( float32, float32 );
float32 float32_sub( float32, float32 );
float32 float32_mul( float32, float32 );
float32 float32_div( float32, float32 );
float32 float32_rem( float32, float32 );
float32 float32_sqrt( float32 );
float32 float32_round_to_int( struct roundingData*, float32 );
float32 float32_add( struct roundingData *, float32, float32 );
float32 float32_sub( struct roundingData *, float32, float32 );
float32 float32_mul( struct roundingData *, float32, float32 );
float32 float32_div( struct roundingData *, float32, float32 );
float32 float32_rem( struct roundingData *, float32, float32 );
float32 float32_sqrt( struct roundingData*, float32 );
char float32_eq( float32, float32 );
char float32_le( float32, float32 );
char float32_lt( float32, float32 );
......@@ -164,9 +162,9 @@ char float32_is_signaling_nan( float32 );
Software IEC/IEEE double-precision conversion routines.
-------------------------------------------------------------------------------
*/
signed int float64_to_int32( float64 );
signed int float64_to_int32( struct roundingData *, float64 );
signed int float64_to_int32_round_to_zero( float64 );
float32 float64_to_float32( float64 );
float32 float64_to_float32( struct roundingData *, float64 );
#ifdef FLOATX80
floatx80 float64_to_floatx80( float64 );
#endif
......@@ -176,13 +174,13 @@ floatx80 float64_to_floatx80( float64 );
Software IEC/IEEE double-precision operations.
-------------------------------------------------------------------------------
*/
float64 float64_round_to_int( float64 );
float64 float64_add( float64, float64 );
float64 float64_sub( float64, float64 );
float64 float64_mul( float64, float64 );
float64 float64_div( float64, float64 );
float64 float64_rem( float64, float64 );
float64 float64_sqrt( float64 );
float64 float64_round_to_int( struct roundingData *, float64 );
float64 float64_add( struct roundingData *, float64, float64 );
float64 float64_sub( struct roundingData *, float64, float64 );
float64 float64_mul( struct roundingData *, float64, float64 );
float64 float64_div( struct roundingData *, float64, float64 );
float64 float64_rem( struct roundingData *, float64, float64 );
float64 float64_sqrt( struct roundingData *, float64 );
char float64_eq( float64, float64 );
char float64_le( float64, float64 );
char float64_lt( float64, float64 );
......@@ -198,31 +196,23 @@ char float64_is_signaling_nan( float64 );
Software IEC/IEEE extended double-precision conversion routines.
-------------------------------------------------------------------------------
*/
signed int floatx80_to_int32( floatx80 );
signed int floatx80_to_int32( struct roundingData *, floatx80 );
signed int floatx80_to_int32_round_to_zero( floatx80 );
float32 floatx80_to_float32( floatx80 );
float64 floatx80_to_float64( floatx80 );
/*
-------------------------------------------------------------------------------
Software IEC/IEEE extended double-precision rounding precision. Valid
values are 32, 64, and 80.
-------------------------------------------------------------------------------
*/
extern signed char floatx80_rounding_precision;
float32 floatx80_to_float32( struct roundingData *, floatx80 );
float64 floatx80_to_float64( struct roundingData *, floatx80 );
/*
-------------------------------------------------------------------------------
Software IEC/IEEE extended double-precision operations.
-------------------------------------------------------------------------------
*/
floatx80 floatx80_round_to_int( floatx80 );
floatx80 floatx80_add( floatx80, floatx80 );
floatx80 floatx80_sub( floatx80, floatx80 );
floatx80 floatx80_mul( floatx80, floatx80 );
floatx80 floatx80_div( floatx80, floatx80 );
floatx80 floatx80_rem( floatx80, floatx80 );
floatx80 floatx80_sqrt( floatx80 );
floatx80 floatx80_round_to_int( struct roundingData *, floatx80 );
floatx80 floatx80_add( struct roundingData *, floatx80, floatx80 );
floatx80 floatx80_sub( struct roundingData *, floatx80, floatx80 );
floatx80 floatx80_mul( struct roundingData *, floatx80, floatx80 );
floatx80 floatx80_div( struct roundingData *, floatx80, floatx80 );
floatx80 floatx80_rem( struct roundingData *, floatx80, floatx80 );
floatx80 floatx80_sqrt( struct roundingData *, floatx80 );
char floatx80_eq( floatx80, floatx80 );
char floatx80_le( floatx80, floatx80 );
char floatx80_lt( floatx80, floatx80 );
......
......@@ -770,6 +770,9 @@ vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,
if ((s64)m_sig < 0) {
vdd->sign = vfp_sign_negate(vdd->sign);
m_sig = -m_sig;
} else if (m_sig == 0) {
vdd->sign = (fpscr & FPSCR_RMODE_MASK) ==
FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
}
} else {
m_sig += vdn->significand;
......
......@@ -36,13 +36,10 @@
#include <asm/uaccess.h>
#define OSCR_FREQ CLOCK_TICK_RATE
#define SA1100_CLOSE_MAGIC (0x5afc4453)
static unsigned long sa1100wdt_users;
static int expect_close;
static int pre_margin;
static int boot_status;
static int nowayout = WATCHDOG_NOWAYOUT;
/*
* Allow only one person to hold it open
......@@ -62,55 +59,33 @@ static int sa1100dog_open(struct inode *inode, struct file *file)
}
/*
* Shut off the timer.
* Lock it in if it's a module and we defined ...NOWAYOUT
* Oddly, the watchdog can only be enabled, but we can turn off
* the interrupt, which appears to prevent the watchdog timing out.
* The watchdog cannot be disabled.
*
* Previous comments suggested that turning off the interrupt by
* clearing OIER[E3] would prevent the watchdog timing out but this
* does not appear to be true (at least on the PXA255).
*/
static int sa1100dog_release(struct inode *inode, struct file *file)
{
OSMR3 = OSCR + pre_margin;
if (expect_close == SA1100_CLOSE_MAGIC) {
OIER &= ~OIER_E3;
} else {
printk(KERN_CRIT "WATCHDOG: WDT device closed unexpectedly. WDT will not stop!\n");
}
printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n");
clear_bit(1, &sa1100wdt_users);
expect_close = 0;
return 0;
}
static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
{
if (len) {
if (!nowayout) {
size_t i;
expect_close = 0;
for (i = 0; i != len; i++) {
char c;
if (get_user(c, data + i))
return -EFAULT;
if (c == 'V')
expect_close = SA1100_CLOSE_MAGIC;
}
}
if (len)
/* Refresh OSMR3 timer. */
OSMR3 = OSCR + pre_margin;
}
return len;
}
static struct watchdog_info ident = {
.options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE |
WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
.identity = "SA1100 Watchdog",
.options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
.identity = "SA1100/PXA255 Watchdog",
};
static int sa1100dog_ioctl(struct inode *inode, struct file *file,
......@@ -172,7 +147,7 @@ static struct file_operations sa1100dog_fops =
static struct miscdevice sa1100dog_miscdev =
{
.minor = WATCHDOG_MINOR,
.name = "SA1100/PXA2xx watchdog",
.name = "watchdog",
.fops = &sa1100dog_fops,
};
......@@ -194,7 +169,6 @@ static int __init sa1100dog_init(void)
if (ret == 0)
printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n",
margin);
return ret;
}
......@@ -212,8 +186,5 @@ MODULE_DESCRIPTION("SA1100/PXA2xx Watchdog");
module_param(margin, int, 0);
MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)");
module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment