Browse Source

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

Linus Torvalds 20 years ago
parent
commit
194d0710e1

+ 1 - 0
Documentation/dontdiff

@@ -104,6 +104,7 @@ logo_*.c
 logo_*_clut224.c
 logo_*_clut224.c
 logo_*_mono.c
 logo_*_mono.c
 lxdialog
 lxdialog
+mach-types
 mach-types.h
 mach-types.h
 make_times_h
 make_times_h
 map
 map

+ 1 - 1
arch/arm/mach-ixp4xx/coyote-setup.c

@@ -61,7 +61,7 @@ static struct plat_serial8250_port coyote_uart_data[] = {
 		.mapbase	= IXP4XX_UART2_BASE_PHYS,
 		.mapbase	= IXP4XX_UART2_BASE_PHYS,
 		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
 		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
 		.irq		= IRQ_IXP4XX_UART2,
 		.irq		= IRQ_IXP4XX_UART2,
-		.flags		= UPF_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
 		.iotype		= UPIO_MEM,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.regshift	= 2,
 		.uartclk	= IXP4XX_UART_XTAL,
 		.uartclk	= IXP4XX_UART_XTAL,

+ 1 - 1
arch/arm/mach-ixp4xx/gtwx5715-setup.c

@@ -83,7 +83,7 @@ static struct plat_serial8250_port gtwx5715_uart_platform_data[] = {
 	.mapbase	= IXP4XX_UART2_BASE_PHYS,
 	.mapbase	= IXP4XX_UART2_BASE_PHYS,
 	.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
 	.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
 	.irq		= IRQ_IXP4XX_UART2,
 	.irq		= IRQ_IXP4XX_UART2,
-	.flags		= UPF_BOOT_AUTOCONF,
+	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
 	.iotype		= UPIO_MEM,
 	.iotype		= UPIO_MEM,
 	.regshift	= 2,
 	.regshift	= 2,
 	.uartclk	= IXP4XX_UART_XTAL,
 	.uartclk	= IXP4XX_UART_XTAL,

+ 2 - 2
arch/arm/mach-ixp4xx/ixdp425-setup.c

@@ -82,7 +82,7 @@ static struct plat_serial8250_port ixdp425_uart_data[] = {
 		.mapbase	= IXP4XX_UART1_BASE_PHYS,
 		.mapbase	= IXP4XX_UART1_BASE_PHYS,
 		.membase	= (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
 		.membase	= (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
 		.irq		= IRQ_IXP4XX_UART1,
 		.irq		= IRQ_IXP4XX_UART1,
-		.flags		= UPF_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
 		.iotype		= UPIO_MEM,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.regshift	= 2,
 		.uartclk	= IXP4XX_UART_XTAL,
 		.uartclk	= IXP4XX_UART_XTAL,
@@ -91,7 +91,7 @@ static struct plat_serial8250_port ixdp425_uart_data[] = {
 		.mapbase	= IXP4XX_UART2_BASE_PHYS,
 		.mapbase	= IXP4XX_UART2_BASE_PHYS,
 		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
 		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
 		.irq		= IRQ_IXP4XX_UART1,
 		.irq		= IRQ_IXP4XX_UART1,
-		.flags		= UPF_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
 		.iotype		= UPIO_MEM,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.regshift	= 2,
 		.uartclk	= IXP4XX_UART_XTAL,
 		.uartclk	= IXP4XX_UART_XTAL,

+ 15 - 1
arch/arm/mach-s3c2410/mach-bast.c

@@ -30,6 +30,7 @@
  *     28-Jun-2005 BJD  Moved pm functionality out to common code
  *     28-Jun-2005 BJD  Moved pm functionality out to common code
  *     17-Jul-2005 BJD  Changed to platform device for SuperIO 16550s
  *     17-Jul-2005 BJD  Changed to platform device for SuperIO 16550s
  *     25-Jul-2005 BJD  Removed ASIX static mappings
  *     25-Jul-2005 BJD  Removed ASIX static mappings
+ *     27-Jul-2005 BJD  Ensure maximum frequency of i2c bus
 */
 */
 
 
 #include <linux/kernel.h>
 #include <linux/kernel.h>
@@ -60,6 +61,7 @@
 #include <asm/arch/regs-mem.h>
 #include <asm/arch/regs-mem.h>
 #include <asm/arch/regs-lcd.h>
 #include <asm/arch/regs-lcd.h>
 #include <asm/arch/nand.h>
 #include <asm/arch/nand.h>
+#include <asm/arch/iic.h>
 
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.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 = {
 static struct s3c2410_platform_nand bast_nand_info = {
-	.tacls		= 80,
+	.tacls		= 40,
 	.twrph0		= 80,
 	.twrph0		= 80,
 	.twrph1		= 80,
 	.twrph1		= 80,
 	.nr_sets	= ARRAY_SIZE(bast_nand_sets),
 	.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 */
 /* Standard BAST devices */
 
 
 static struct platform_device *bast_devices[] __initdata = {
 static struct platform_device *bast_devices[] __initdata = {
@@ -431,6 +444,7 @@ void __init bast_map_io(void)
 	s3c24xx_uclk.parent  = &s3c24xx_clkout1;
 	s3c24xx_uclk.parent  = &s3c24xx_clkout1;
 
 
 	s3c_device_nand.dev.platform_data = &bast_nand_info;
 	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_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_clocks(0);

+ 0 - 136
arch/arm/mm/proc-xscale.S

@@ -370,142 +370,6 @@ ENTRY(cpu_xscale_dcache_clean_area)
 	bhi	1b
 	bhi	1b
 	mov	pc, lr
 	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 ============================== */
 /* =============================== PageTable ============================== */
 
 
 #define PTE_CACHE_WRITE_ALLOCATE 0
 #define PTE_CACHE_WRITE_ALLOCATE 0

+ 12 - 12
arch/arm/nwfpe/double_cpdo.c

@@ -40,17 +40,17 @@ float64 float64_arccos(float64 rFm);
 float64 float64_pow(float64 rFn, float64 rFm);
 float64 float64_pow(float64 rFn, float64 rFm);
 float64 float64_pol(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,
 	[ADF_CODE >> 20] = float64_add,
 	[MUF_CODE >> 20] = float64_mul,
 	[MUF_CODE >> 20] = float64_mul,
 	[SUF_CODE >> 20] = float64_sub,
 	[SUF_CODE >> 20] = float64_sub,
@@ -65,12 +65,12 @@ static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = {
 	[FRD_CODE >> 20] = float64_rdv,
 	[FRD_CODE >> 20] = float64_rdv,
 };
 };
 
 
-static float64 float64_mvf(float64 rFm)
+static float64 float64_mvf(struct roundingData *roundData,float64 rFm)
 {
 {
 	return rFm;
 	return rFm;
 }
 }
 
 
-static float64 float64_mnf(float64 rFm)
+static float64 float64_mnf(struct roundingData *roundData,float64 rFm)
 {
 {
 	union float64_components u;
 	union float64_components u;
 
 
@@ -84,7 +84,7 @@ static float64 float64_mnf(float64 rFm)
 	return u.f64;
 	return u.f64;
 }
 }
 
 
-static float64 float64_abs(float64 rFm)
+static float64 float64_abs(struct roundingData *roundData,float64 rFm)
 {
 {
 	union float64_components u;
 	union float64_components u;
 
 
@@ -98,7 +98,7 @@ static float64 float64_abs(float64 rFm)
 	return u.f64;
 	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,
 	[MVF_CODE >> 20] = float64_mvf,
 	[MNF_CODE >> 20] = float64_mnf,
 	[MNF_CODE >> 20] = float64_mnf,
 	[ABS_CODE >> 20] = float64_abs,
 	[ABS_CODE >> 20] = float64_abs,
@@ -108,7 +108,7 @@ static float64 (*const monadic_double[16])(float64 rFm) = {
 	[NRM_CODE >> 20] = float64_mvf,
 	[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();
 	FPA11 *fpa11 = GET_FPA11();
 	float64 rFm;
 	float64 rFm;
@@ -151,13 +151,13 @@ unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd)
 		}
 		}
 
 
 		if (dyadic_double[opc_mask_shift]) {
 		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 {
 		} else {
 			return 0;
 			return 0;
 		}
 		}
 	} else {
 	} else {
 		if (monadic_double[opc_mask_shift]) {
 		if (monadic_double[opc_mask_shift]) {
-			rFd->fDouble = monadic_double[opc_mask_shift](rFm);
+			rFd->fDouble = monadic_double[opc_mask_shift](roundData, rFm);
 		} else {
 		} else {
 			return 0;
 			return 0;
 		}
 		}

+ 12 - 12
arch/arm/nwfpe/extended_cpdo.c

@@ -35,17 +35,17 @@ floatx80 floatx80_arccos(floatx80 rFm);
 floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm);
 floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm);
 floatx80 floatx80_pol(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,
 	[ADF_CODE >> 20] = floatx80_add,
 	[MUF_CODE >> 20] = floatx80_mul,
 	[MUF_CODE >> 20] = floatx80_mul,
 	[SUF_CODE >> 20] = floatx80_sub,
 	[SUF_CODE >> 20] = floatx80_sub,
@@ -60,24 +60,24 @@ static floatx80 (*const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) = {
 	[FRD_CODE >> 20] = floatx80_rdv,
 	[FRD_CODE >> 20] = floatx80_rdv,
 };
 };
 
 
-static floatx80 floatx80_mvf(floatx80 rFm)
+static floatx80 floatx80_mvf(struct roundingData *roundData, floatx80 rFm)
 {
 {
 	return rFm;
 	return rFm;
 }
 }
 
 
-static floatx80 floatx80_mnf(floatx80 rFm)
+static floatx80 floatx80_mnf(struct roundingData *roundData, floatx80 rFm)
 {
 {
 	rFm.high ^= 0x8000;
 	rFm.high ^= 0x8000;
 	return rFm;
 	return rFm;
 }
 }
 
 
-static floatx80 floatx80_abs(floatx80 rFm)
+static floatx80 floatx80_abs(struct roundingData *roundData, floatx80 rFm)
 {
 {
 	rFm.high &= 0x7fff;
 	rFm.high &= 0x7fff;
 	return rFm;
 	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,
 	[MVF_CODE >> 20] = floatx80_mvf,
 	[MNF_CODE >> 20] = floatx80_mnf,
 	[MNF_CODE >> 20] = floatx80_mnf,
 	[ABS_CODE >> 20] = floatx80_abs,
 	[ABS_CODE >> 20] = floatx80_abs,
@@ -87,7 +87,7 @@ static floatx80 (*const monadic_extended[16])(floatx80 rFm) = {
 	[NRM_CODE >> 20] = floatx80_mvf,
 	[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();
 	FPA11 *fpa11 = GET_FPA11();
 	floatx80 rFm;
 	floatx80 rFm;
@@ -138,13 +138,13 @@ unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd)
 		}
 		}
 
 
 		if (dyadic_extended[opc_mask_shift]) {
 		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 {
 		} else {
 			return 0;
 			return 0;
 		}
 		}
 	} else {
 	} else {
 		if (monadic_extended[opc_mask_shift]) {
 		if (monadic_extended[opc_mask_shift]) {
-			rFd->fExtended = monadic_extended[opc_mask_shift](rFm);
+			rFd->fExtended = monadic_extended[opc_mask_shift](roundData, rFm);
 		} else {
 		} else {
 			return 0;
 			return 0;
 		}
 		}

+ 11 - 19
arch/arm/nwfpe/fpa11.c

@@ -51,48 +51,42 @@ static void resetFPA11(void)
 	fpa11->fpsr = FP_EMULATOR | BIT_AC;
 	fpa11->fpsr = FP_EMULATOR | BIT_AC;
 }
 }
 
 
-void SetRoundingMode(const unsigned int opcode)
+int8 SetRoundingMode(const unsigned int opcode)
 {
 {
 	switch (opcode & MASK_ROUNDING_MODE) {
 	switch (opcode & MASK_ROUNDING_MODE) {
 	default:
 	default:
 	case ROUND_TO_NEAREST:
 	case ROUND_TO_NEAREST:
-		float_rounding_mode = float_round_nearest_even;
-		break;
+		return float_round_nearest_even;
 
 
 	case ROUND_TO_PLUS_INFINITY:
 	case ROUND_TO_PLUS_INFINITY:
-		float_rounding_mode = float_round_up;
-		break;
+		return float_round_up;
 
 
 	case ROUND_TO_MINUS_INFINITY:
 	case ROUND_TO_MINUS_INFINITY:
-		float_rounding_mode = float_round_down;
-		break;
+		return float_round_down;
 
 
 	case ROUND_TO_ZERO:
 	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
 #ifdef CONFIG_FPE_NWFPE_XP
 	switch (opcode & MASK_ROUNDING_PRECISION) {
 	switch (opcode & MASK_ROUNDING_PRECISION) {
 	case ROUND_SINGLE:
 	case ROUND_SINGLE:
-		floatx80_rounding_precision = 32;
-		break;
+		return 32;
 
 
 	case ROUND_DOUBLE:
 	case ROUND_DOUBLE:
-		floatx80_rounding_precision = 64;
-		break;
+		return 64;
 
 
 	case ROUND_EXTENDED:
 	case ROUND_EXTENDED:
-		floatx80_rounding_precision = 80;
-		break;
+		return 80;
 
 
 	default:
 	default:
-		floatx80_rounding_precision = 80;
+		return 80;
 	}
 	}
 #endif
 #endif
+	return 80;
 }
 }
 
 
 void nwfpe_init_fpa(union fp_state *fp)
 void nwfpe_init_fpa(union fp_state *fp)
@@ -103,8 +97,6 @@ void nwfpe_init_fpa(union fp_state *fp)
 #endif
 #endif
  	memset(fpa11, 0, sizeof(FPA11));
  	memset(fpa11, 0, sizeof(FPA11));
 	resetFPA11();
 	resetFPA11();
-	SetRoundingMode(ROUND_TO_NEAREST);
-	SetRoundingPrecision(ROUND_EXTENDED);
 	fpa11->initflag = 1;
 	fpa11->initflag = 1;
 }
 }
 
 

+ 9 - 2
arch/arm/nwfpe/fpa11.h

@@ -37,6 +37,13 @@
 /* includes */
 /* includes */
 #include "fpsr.h"		/* FP control and status register definitions */
 #include "fpsr.h"		/* FP control and status register definitions */
 #include "milieu.h"
 #include "milieu.h"
+
+struct roundingData {
+    int8 mode;
+    int8 precision;
+    signed char exception;
+};
+
 #include "softfloat.h"
 #include "softfloat.h"
 
 
 #define		typeNone		0x00
 #define		typeNone		0x00
@@ -84,8 +91,8 @@ typedef struct tagFPA11 {
 				   initialised. */
 				   initialised. */
 } FPA11;
 } 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);
 extern void nwfpe_init_fpa(union fp_state *fp);
 
 
 #endif
 #endif

+ 17 - 11
arch/arm/nwfpe/fpa11_cpdo.c

@@ -24,15 +24,16 @@
 #include "fpa11.h"
 #include "fpa11.h"
 #include "fpopcode.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)
 unsigned int EmulateCPDO(const unsigned int opcode)
 {
 {
 	FPA11 *fpa11 = GET_FPA11();
 	FPA11 *fpa11 = GET_FPA11();
 	FPREG *rFd;
 	FPREG *rFd;
 	unsigned int nType, nDest, nRc;
 	unsigned int nType, nDest, nRc;
+	struct roundingData roundData;
 
 
 	/* Get the destination size.  If not valid let Linux perform
 	/* Get the destination size.  If not valid let Linux perform
 	   an invalid instruction trap. */
 	   an invalid instruction trap. */
@@ -40,7 +41,9 @@ unsigned int EmulateCPDO(const unsigned int opcode)
 	if (typeNone == nDest)
 	if (typeNone == nDest)
 		return 0;
 		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.
 	/* Compare the size of the operands in Fn and Fm.
 	   Choose the largest size and perform operations in that size,
 	   Choose the largest size and perform operations in that size,
@@ -63,14 +66,14 @@ unsigned int EmulateCPDO(const unsigned int opcode)
 
 
 	switch (nType) {
 	switch (nType) {
 	case typeSingle:
 	case typeSingle:
-		nRc = SingleCPDO(opcode, rFd);
+		nRc = SingleCPDO(&roundData, opcode, rFd);
 		break;
 		break;
 	case typeDouble:
 	case typeDouble:
-		nRc = DoubleCPDO(opcode, rFd);
+		nRc = DoubleCPDO(&roundData, opcode, rFd);
 		break;
 		break;
 #ifdef CONFIG_FPE_NWFPE_XP
 #ifdef CONFIG_FPE_NWFPE_XP
 	case typeExtended:
 	case typeExtended:
-		nRc = ExtendedCPDO(opcode, rFd);
+		nRc = ExtendedCPDO(&roundData, opcode, rFd);
 		break;
 		break;
 #endif
 #endif
 	default:
 	default:
@@ -93,9 +96,9 @@ unsigned int EmulateCPDO(const unsigned int opcode)
 			case typeSingle:
 			case typeSingle:
 				{
 				{
 					if (typeDouble == nType)
 					if (typeDouble == nType)
-						rFd->fSingle = float64_to_float32(rFd->fDouble);
+						rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);
 					else
 					else
-						rFd->fSingle = floatx80_to_float32(rFd->fExtended);
+						rFd->fSingle = floatx80_to_float32(&roundData, rFd->fExtended);
 				}
 				}
 				break;
 				break;
 
 
@@ -104,7 +107,7 @@ unsigned int EmulateCPDO(const unsigned int opcode)
 					if (typeSingle == nType)
 					if (typeSingle == nType)
 						rFd->fDouble = float32_to_float64(rFd->fSingle);
 						rFd->fDouble = float32_to_float64(rFd->fSingle);
 					else
 					else
-						rFd->fDouble = floatx80_to_float64(rFd->fExtended);
+						rFd->fDouble = floatx80_to_float64(&roundData, rFd->fExtended);
 				}
 				}
 				break;
 				break;
 
 
@@ -121,12 +124,15 @@ unsigned int EmulateCPDO(const unsigned int opcode)
 #else
 #else
 		if (nDest != nType) {
 		if (nDest != nType) {
 			if (nDest == typeSingle)
 			if (nDest == typeSingle)
-				rFd->fSingle = float64_to_float32(rFd->fDouble);
+				rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);
 			else
 			else
 				rFd->fDouble = float32_to_float64(rFd->fSingle);
 				rFd->fDouble = float32_to_float64(rFd->fSingle);
 		}
 		}
 #endif
 #endif
 	}
 	}
 
 
+	if (roundData.exception)
+		float_raise(roundData.exception);
+
 	return nRc;
 	return nRc;
 }
 }

+ 14 - 8
arch/arm/nwfpe/fpa11_cpdt.c

@@ -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();
 	FPA11 *fpa11 = GET_FPA11();
 	union {
 	union {
@@ -106,12 +106,12 @@ static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem)
 
 
 	switch (fpa11->fType[Fn]) {
 	switch (fpa11->fType[Fn]) {
 	case typeDouble:
 	case typeDouble:
-		val.f = float64_to_float32(fpa11->fpreg[Fn].fDouble);
+		val.f = float64_to_float32(roundData, fpa11->fpreg[Fn].fDouble);
 		break;
 		break;
 
 
 #ifdef CONFIG_FPE_NWFPE_XP
 #ifdef CONFIG_FPE_NWFPE_XP
 	case typeExtended:
 	case typeExtended:
-		val.f = floatx80_to_float32(fpa11->fpreg[Fn].fExtended);
+		val.f = floatx80_to_float32(roundData, fpa11->fpreg[Fn].fExtended);
 		break;
 		break;
 #endif
 #endif
 
 
@@ -122,7 +122,7 @@ static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem)
 	put_user(val.i[0], 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();
 	FPA11 *fpa11 = GET_FPA11();
 	union {
 	union {
@@ -137,7 +137,7 @@ static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem)
 
 
 #ifdef CONFIG_FPE_NWFPE_XP
 #ifdef CONFIG_FPE_NWFPE_XP
 	case typeExtended:
 	case typeExtended:
-		val.f = floatx80_to_float64(fpa11->fpreg[Fn].fExtended);
+		val.f = floatx80_to_float64(roundData, fpa11->fpreg[Fn].fExtended);
 		break;
 		break;
 #endif
 #endif
 
 
@@ -259,8 +259,11 @@ unsigned int PerformSTF(const unsigned int opcode)
 {
 {
 	unsigned int __user *pBase, *pAddress, *pFinal;
 	unsigned int __user *pBase, *pAddress, *pFinal;
 	unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
 	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));
 	pBase = (unsigned int __user *) readRegister(getRn(opcode));
 	if (REG_PC == getRn(opcode)) {
 	if (REG_PC == getRn(opcode)) {
@@ -281,10 +284,10 @@ unsigned int PerformSTF(const unsigned int opcode)
 
 
 	switch (opcode & MASK_TRANSFER_LENGTH) {
 	switch (opcode & MASK_TRANSFER_LENGTH) {
 	case TRANSFER_SINGLE:
 	case TRANSFER_SINGLE:
-		storeSingle(getFd(opcode), pAddress);
+		storeSingle(&roundData, getFd(opcode), pAddress);
 		break;
 		break;
 	case TRANSFER_DOUBLE:
 	case TRANSFER_DOUBLE:
-		storeDouble(getFd(opcode), pAddress);
+		storeDouble(&roundData, getFd(opcode), pAddress);
 		break;
 		break;
 #ifdef CONFIG_FPE_NWFPE_XP
 #ifdef CONFIG_FPE_NWFPE_XP
 	case TRANSFER_EXTENDED:
 	case TRANSFER_EXTENDED:
@@ -295,6 +298,9 @@ unsigned int PerformSTF(const unsigned int opcode)
 		nRc = 0;
 		nRc = 0;
 	}
 	}
 
 
+	if (roundData.exception)
+		float_raise(roundData.exception);
+
 	if (write_back)
 	if (write_back)
 		writeRegister(getRn(opcode), (unsigned long) pFinal);
 		writeRegister(getRn(opcode), (unsigned long) pFinal);
 	return nRc;
 	return nRc;

+ 19 - 9
arch/arm/nwfpe/fpa11_cprt.c

@@ -33,8 +33,6 @@ extern flag floatx80_is_nan(floatx80);
 extern flag float64_is_nan(float64);
 extern flag float64_is_nan(float64);
 extern flag float32_is_nan(float32);
 extern flag float32_is_nan(float32);
 
 
-void SetRoundingMode(const unsigned int opcode);
-
 unsigned int PerformFLT(const unsigned int opcode);
 unsigned int PerformFLT(const unsigned int opcode);
 unsigned int PerformFIX(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)
 unsigned int PerformFLT(const unsigned int opcode)
 {
 {
 	FPA11 *fpa11 = GET_FPA11();
 	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) {
 	switch (opcode & MASK_ROUNDING_PRECISION) {
 	case ROUND_SINGLE:
 	case ROUND_SINGLE:
 		{
 		{
 			fpa11->fType[getFn(opcode)] = typeSingle;
 			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;
 		break;
 
 
@@ -108,6 +109,9 @@ unsigned int PerformFLT(const unsigned int opcode)
 		return 0;
 		return 0;
 	}
 	}
 
 
+	if (roundData.exception)
+		float_raise(roundData.exception);
+
 	return 1;
 	return 1;
 }
 }
 
 
@@ -115,26 +119,29 @@ unsigned int PerformFIX(const unsigned int opcode)
 {
 {
 	FPA11 *fpa11 = GET_FPA11();
 	FPA11 *fpa11 = GET_FPA11();
 	unsigned int Fn = getFm(opcode);
 	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]) {
 	switch (fpa11->fType[Fn]) {
 	case typeSingle:
 	case typeSingle:
 		{
 		{
-			writeRegister(getRd(opcode), float32_to_int32(fpa11->fpreg[Fn].fSingle));
+			writeRegister(getRd(opcode), float32_to_int32(&roundData, fpa11->fpreg[Fn].fSingle));
 		}
 		}
 		break;
 		break;
 
 
 	case typeDouble:
 	case typeDouble:
 		{
 		{
-			writeRegister(getRd(opcode), float64_to_int32(fpa11->fpreg[Fn].fDouble));
+			writeRegister(getRd(opcode), float64_to_int32(&roundData, fpa11->fpreg[Fn].fDouble));
 		}
 		}
 		break;
 		break;
 
 
 #ifdef CONFIG_FPE_NWFPE_XP
 #ifdef CONFIG_FPE_NWFPE_XP
 	case typeExtended:
 	case typeExtended:
 		{
 		{
-			writeRegister(getRd(opcode), floatx80_to_int32(fpa11->fpreg[Fn].fExtended));
+			writeRegister(getRd(opcode), floatx80_to_int32(&roundData, fpa11->fpreg[Fn].fExtended));
 		}
 		}
 		break;
 		break;
 #endif
 #endif
@@ -143,6 +150,9 @@ unsigned int PerformFIX(const unsigned int opcode)
 		return 0;
 		return 0;
 	}
 	}
 
 
+	if (roundData.exception)
+		float_raise(roundData.exception);
+
 	return 1;
 	return 1;
 }
 }
 
 

+ 6 - 9
arch/arm/nwfpe/fpmodule.c

@@ -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 
 code to access data in user space in some other source files at the 
 moment (grep for get_user / put_user calls).  --philb]
 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
 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
 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 
 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;
 	register unsigned int fpsr, cumulativeTraps;
 
 
 #ifdef CONFIG_DEBUG_USER
 #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
 #endif
 
 
-	/* Keep SoftFloat exception flags up to date.  */
-	float_exception_flags |= flags;
-
 	/* Read fpsr and initialize the cumulativeTraps.  */
 	/* Read fpsr and initialize the cumulativeTraps.  */
 	fpsr = readFPSR();
 	fpsr = readFPSR();
 	cumulativeTraps = 0;
 	cumulativeTraps = 0;

+ 12 - 12
arch/arm/nwfpe/single_cpdo.c

@@ -36,17 +36,17 @@ float32 float32_arccos(float32 rFm);
 float32 float32_pow(float32 rFn, float32 rFm);
 float32 float32_pow(float32 rFn, float32 rFm);
 float32 float32_pol(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,
 	[ADF_CODE >> 20] = float32_add,
 	[MUF_CODE >> 20] = float32_mul,
 	[MUF_CODE >> 20] = float32_mul,
 	[SUF_CODE >> 20] = float32_sub,
 	[SUF_CODE >> 20] = float32_sub,
@@ -60,22 +60,22 @@ static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = {
 	[FRD_CODE >> 20] = float32_rdv,
 	[FRD_CODE >> 20] = float32_rdv,
 };
 };
 
 
-static float32 float32_mvf(float32 rFm)
+static float32 float32_mvf(struct roundingData *roundData, float32 rFm)
 {
 {
 	return rFm;
 	return rFm;
 }
 }
 
 
-static float32 float32_mnf(float32 rFm)
+static float32 float32_mnf(struct roundingData *roundData, float32 rFm)
 {
 {
 	return rFm ^ 0x80000000;
 	return rFm ^ 0x80000000;
 }
 }
 
 
-static float32 float32_abs(float32 rFm)
+static float32 float32_abs(struct roundingData *roundData, float32 rFm)
 {
 {
 	return rFm & 0x7fffffff;
 	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,
 	[MVF_CODE >> 20] = float32_mvf,
 	[MNF_CODE >> 20] = float32_mnf,
 	[MNF_CODE >> 20] = float32_mnf,
 	[ABS_CODE >> 20] = float32_abs,
 	[ABS_CODE >> 20] = float32_abs,
@@ -85,7 +85,7 @@ static float32 (*const monadic_single[16])(float32 rFm) = {
 	[NRM_CODE >> 20] = float32_mvf,
 	[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();
 	FPA11 *fpa11 = GET_FPA11();
 	float32 rFm;
 	float32 rFm;
@@ -108,13 +108,13 @@ unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd)
 		if (fpa11->fType[Fn] == typeSingle &&
 		if (fpa11->fType[Fn] == typeSingle &&
 		    dyadic_single[opc_mask_shift]) {
 		    dyadic_single[opc_mask_shift]) {
 			rFn = fpa11->fpreg[Fn].fSingle;
 			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 {
 		} else {
 			return 0;
 			return 0;
 		}
 		}
 	} else {
 	} else {
 		if (monadic_single[opc_mask_shift]) {
 		if (monadic_single[opc_mask_shift]) {
-			rFd->fSingle = monadic_single[opc_mask_shift](rFm);
+			rFd->fSingle = monadic_single[opc_mask_shift](roundData, rFm);
 		} else {
 		} else {
 			return 0;
 			return 0;
 		}
 		}

+ 163 - 171
arch/arm/nwfpe/softfloat.c

@@ -34,16 +34,6 @@ this code that are retained.
 //#include "milieu.h"
 //#include "milieu.h"
 //#include "softfloat.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
 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.
 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;
     int8 roundingMode;
     flag roundNearestEven;
     flag roundNearestEven;
     int8 roundIncrement, roundBits;
     int8 roundIncrement, roundBits;
     int32 z;
     int32 z;
 
 
-    roundingMode = float_rounding_mode;
+    roundingMode = roundData->mode;
     roundNearestEven = ( roundingMode == float_round_nearest_even );
     roundNearestEven = ( roundingMode == float_round_nearest_even );
     roundIncrement = 0x40;
     roundIncrement = 0x40;
     if ( ! roundNearestEven ) {
     if ( ! roundNearestEven ) {
@@ -107,10 +97,10 @@ static int32 roundAndPackInt32( flag zSign, bits64 absZ )
     z = absZ;
     z = absZ;
     if ( zSign ) z = - z;
     if ( zSign ) z = - z;
     if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) {
     if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) {
-        float_exception_flags |= float_flag_invalid;
+        roundData->exception |= float_flag_invalid;
         return zSign ? 0x80000000 : 0x7FFFFFFF;
         return zSign ? 0x80000000 : 0x7FFFFFFF;
     }
     }
-    if ( roundBits ) float_exception_flags |= float_flag_inexact;
+    if ( roundBits ) roundData->exception |= float_flag_inexact;
     return z;
     return z;
 
 
 }
 }
@@ -224,14 +214,14 @@ The handling of underflow and overflow follows the IEC/IEEE Standard for
 Binary Floating-point Arithmetic.
 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;
     int8 roundingMode;
     flag roundNearestEven;
     flag roundNearestEven;
     int8 roundIncrement, roundBits;
     int8 roundIncrement, roundBits;
     flag isTiny;
     flag isTiny;
 
 
-    roundingMode = float_rounding_mode;
+    roundingMode = roundData->mode;
     roundNearestEven = ( roundingMode == float_round_nearest_even );
     roundNearestEven = ( roundingMode == float_round_nearest_even );
     roundIncrement = 0x40;
     roundIncrement = 0x40;
     if ( ! roundNearestEven ) {
     if ( ! roundNearestEven ) {
@@ -254,7 +244,7 @@ static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
              || (    ( zExp == 0xFD )
              || (    ( zExp == 0xFD )
                   && ( (sbits32) ( zSig + roundIncrement ) < 0 ) )
                   && ( (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 );
             return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 );
         }
         }
         if ( zExp < 0 ) {
         if ( zExp < 0 ) {
@@ -265,10 +255,10 @@ static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
             shift32RightJamming( zSig, - zExp, &zSig );
             shift32RightJamming( zSig, - zExp, &zSig );
             zExp = 0;
             zExp = 0;
             roundBits = zSig & 0x7F;
             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 = ( zSig + roundIncrement )>>7;
     zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
     zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
     if ( zSig == 0 ) zExp = 0;
     if ( zSig == 0 ) zExp = 0;
@@ -287,12 +277,12 @@ point exponent.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 */
 */
 static float32
 static float32
- normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
+ normalizeRoundAndPackFloat32( struct roundingData *roundData, flag zSign, int16 zExp, bits32 zSig )
 {
 {
     int8 shiftCount;
     int8 shiftCount;
 
 
     shiftCount = countLeadingZeros32( zSig ) - 1;
     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.
 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;
     int8 roundingMode;
     flag roundNearestEven;
     flag roundNearestEven;
     int16 roundIncrement, roundBits;
     int16 roundIncrement, roundBits;
     flag isTiny;
     flag isTiny;
 
 
-    roundingMode = float_rounding_mode;
+    roundingMode = roundData->mode;
     roundNearestEven = ( roundingMode == float_round_nearest_even );
     roundNearestEven = ( roundingMode == float_round_nearest_even );
     roundIncrement = 0x200;
     roundIncrement = 0x200;
     if ( ! roundNearestEven ) {
     if ( ! roundNearestEven ) {
@@ -427,7 +417,7 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig )
            ) {
            ) {
             //register int lr = __builtin_return_address(0);
             //register int lr = __builtin_return_address(0);
             //printk("roundAndPackFloat64 called from 0x%08x\n",lr);
             //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 );
             return packFloat64( zSign, 0x7FF, 0 ) - ( roundIncrement == 0 );
         }
         }
         if ( zExp < 0 ) {
         if ( zExp < 0 ) {
@@ -438,10 +428,10 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig )
             shift64RightJamming( zSig, - zExp, &zSig );
             shift64RightJamming( zSig, - zExp, &zSig );
             zExp = 0;
             zExp = 0;
             roundBits = zSig & 0x3FF;
             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 = ( zSig + roundIncrement )>>10;
     zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven );
     zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven );
     if ( zSig == 0 ) zExp = 0;
     if ( zSig == 0 ) zExp = 0;
@@ -460,12 +450,12 @@ point exponent.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 */
 */
 static float64
 static float64
- normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig )
+ normalizeRoundAndPackFloat64( struct roundingData *roundData, flag zSign, int16 zExp, bits64 zSig )
 {
 {
     int8 shiftCount;
     int8 shiftCount;
 
 
     shiftCount = countLeadingZeros64( zSig ) - 1;
     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
 static floatx80
  roundAndPackFloatx80(
  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;
     flag roundNearestEven, increment, isTiny;
     int64 roundIncrement, roundMask, roundBits;
     int64 roundIncrement, roundMask, roundBits;
 
 
-    roundingMode = float_rounding_mode;
+    roundingMode = roundData->mode;
+    roundingPrecision = roundData->precision;
     roundNearestEven = ( roundingMode == float_round_nearest_even );
     roundNearestEven = ( roundingMode == float_round_nearest_even );
     if ( roundingPrecision == 80 ) goto precision80;
     if ( roundingPrecision == 80 ) goto precision80;
     if ( roundingPrecision == 64 ) {
     if ( roundingPrecision == 64 ) {
@@ -623,8 +614,8 @@ static floatx80
             shift64RightJamming( zSig0, 1 - zExp, &zSig0 );
             shift64RightJamming( zSig0, 1 - zExp, &zSig0 );
             zExp = 0;
             zExp = 0;
             roundBits = zSig0 & roundMask;
             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;
             zSig0 += roundIncrement;
             if ( (sbits64) zSig0 < 0 ) zExp = 1;
             if ( (sbits64) zSig0 < 0 ) zExp = 1;
             roundIncrement = roundMask + 1;
             roundIncrement = roundMask + 1;
@@ -635,7 +626,7 @@ static floatx80
             return packFloatx80( zSign, zExp, zSig0 );
             return packFloatx80( zSign, zExp, zSig0 );
         }
         }
     }
     }
-    if ( roundBits ) float_exception_flags |= float_flag_inexact;
+    if ( roundBits ) roundData->exception |= float_flag_inexact;
     zSig0 += roundIncrement;
     zSig0 += roundIncrement;
     if ( zSig0 < roundIncrement ) {
     if ( zSig0 < roundIncrement ) {
         ++zExp;
         ++zExp;
@@ -672,7 +663,7 @@ static floatx80
            ) {
            ) {
             roundMask = 0;
             roundMask = 0;
  overflow:
  overflow:
-            float_raise( float_flag_overflow | float_flag_inexact );
+            roundData->exception |= float_flag_overflow | float_flag_inexact;
             if (    ( roundingMode == float_round_to_zero )
             if (    ( roundingMode == float_round_to_zero )
                  || ( zSign && ( roundingMode == float_round_up ) )
                  || ( zSign && ( roundingMode == float_round_up ) )
                  || ( ! zSign && ( roundingMode == float_round_down ) )
                  || ( ! zSign && ( roundingMode == float_round_down ) )
@@ -689,8 +680,8 @@ static floatx80
                 || ( zSig0 < LIT64( 0xFFFFFFFFFFFFFFFF ) );
                 || ( zSig0 < LIT64( 0xFFFFFFFFFFFFFFFF ) );
             shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 );
             shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 );
             zExp = 0;
             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 ) {
             if ( roundNearestEven ) {
                 increment = ( (sbits64) zSig1 < 0 );
                 increment = ( (sbits64) zSig1 < 0 );
             }
             }
@@ -710,7 +701,7 @@ static floatx80
             return packFloatx80( zSign, zExp, zSig0 );
             return packFloatx80( zSign, zExp, zSig0 );
         }
         }
     }
     }
-    if ( zSig1 ) float_exception_flags |= float_flag_inexact;
+    if ( zSig1 ) roundData->exception |= float_flag_inexact;
     if ( increment ) {
     if ( increment ) {
         ++zSig0;
         ++zSig0;
         if ( zSig0 == 0 ) {
         if ( zSig0 == 0 ) {
@@ -740,7 +731,7 @@ normalized.
 */
 */
 static floatx80
 static floatx80
  normalizeRoundAndPackFloatx80(
  normalizeRoundAndPackFloatx80(
-     int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
+     struct roundingData *roundData, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
  )
  )
 {
 {
     int8 shiftCount;
     int8 shiftCount;
@@ -754,7 +745,7 @@ static floatx80
     shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
     shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
     zExp -= shiftCount;
     zExp -= shiftCount;
     return
     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.
 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;
     flag zSign;
 
 
     if ( a == 0 ) return 0;
     if ( a == 0 ) return 0;
     if ( a == 0x80000000 ) return packFloat32( 1, 0x9E, 0 );
     if ( a == 0x80000000 ) return packFloat32( 1, 0x9E, 0 );
     zSign = ( a < 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.
 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;
     flag aSign;
     int16 aExp, shiftCount;
     int16 aExp, shiftCount;
@@ -856,7 +847,7 @@ int32 float32_to_int32( float32 a )
     zSig = aSig;
     zSig = aSig;
     zSig <<= 32;
     zSig <<= 32;
     if ( 0 < shiftCount ) shift64RightJamming( zSig, shiftCount, &zSig );
     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;
         return 0x80000000;
     }
     }
     else if ( aExp <= 0x7E ) {
     else if ( aExp <= 0x7E ) {
-        if ( aExp | aSig ) float_exception_flags |= float_flag_inexact;
+        if ( aExp | aSig ) float_raise( float_flag_inexact );
         return 0;
         return 0;
     }
     }
     aSig = ( aSig | 0x00800000 )<<8;
     aSig = ( aSig | 0x00800000 )<<8;
     z = aSig>>( - shiftCount );
     z = aSig>>( - shiftCount );
     if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) {
     if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) {
-        float_exception_flags |= float_flag_inexact;
+        float_raise( float_flag_inexact );
     }
     }
     return aSign ? - z : z;
     return aSign ? - z : z;
 
 
@@ -973,7 +964,7 @@ operation is performed according to the IEC/IEEE Standard for Binary
 Floating-point Arithmetic.
 Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 */
 */
-float32 float32_round_to_int( float32 a )
+float32 float32_round_to_int( struct roundingData *roundData, float32 a )
 {
 {
     flag aSign;
     flag aSign;
     int16 aExp;
     int16 aExp;
@@ -988,11 +979,12 @@ float32 float32_round_to_int( float32 a )
         }
         }
         return a;
         return a;
     }
     }
+    roundingMode = roundData->mode;
     if ( aExp <= 0x7E ) {
     if ( aExp <= 0x7E ) {
         if ( (bits32) ( a<<1 ) == 0 ) return a;
         if ( (bits32) ( a<<1 ) == 0 ) return a;
-        float_exception_flags |= float_flag_inexact;
+        roundData->exception |= float_flag_inexact;
         aSign = extractFloat32Sign( a );
         aSign = extractFloat32Sign( a );
-        switch ( float_rounding_mode ) {
+        switch ( roundingMode ) {
          case float_round_nearest_even:
          case float_round_nearest_even:
             if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) {
             if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) {
                 return packFloat32( aSign, 0x7F, 0 );
                 return packFloat32( aSign, 0x7F, 0 );
@@ -1009,7 +1001,6 @@ float32 float32_round_to_int( float32 a )
     lastBitMask <<= 0x96 - aExp;
     lastBitMask <<= 0x96 - aExp;
     roundBitsMask = lastBitMask - 1;
     roundBitsMask = lastBitMask - 1;
     z = a;
     z = a;
-    roundingMode = float_rounding_mode;
     if ( roundingMode == float_round_nearest_even ) {
     if ( roundingMode == float_round_nearest_even ) {
         z += lastBitMask>>1;
         z += lastBitMask>>1;
         if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
         if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
@@ -1020,7 +1011,7 @@ float32 float32_round_to_int( float32 a )
         }
         }
     }
     }
     z &= ~ roundBitsMask;
     z &= ~ roundBitsMask;
-    if ( z != a ) float_exception_flags |= float_flag_inexact;
+    if ( z != a ) roundData->exception |= float_flag_inexact;
     return z;
     return z;
 
 
 }
 }
@@ -1034,7 +1025,7 @@ addition is performed according to the IEC/IEEE Standard for Binary
 Floating-point Arithmetic.
 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;
     int16 aExp, bExp, zExp;
     bits32 aSig, bSig, zSig;
     bits32 aSig, bSig, zSig;
@@ -1093,7 +1084,7 @@ static float32 addFloat32Sigs( float32 a, float32 b, flag zSign )
         ++zExp;
         ++zExp;
     }
     }
  roundAndPack:
  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.
 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;
     int16 aExp, bExp, zExp;
     bits32 aSig, bSig, zSig;
     bits32 aSig, bSig, zSig;
@@ -1123,7 +1114,7 @@ static float32 subFloat32Sigs( float32 a, float32 b, flag zSign )
     if ( expDiff < 0 ) goto bExpBigger;
     if ( expDiff < 0 ) goto bExpBigger;
     if ( aExp == 0xFF ) {
     if ( aExp == 0xFF ) {
         if ( aSig | bSig ) return propagateFloat32NaN( a, b );
         if ( aSig | bSig ) return propagateFloat32NaN( a, b );
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         return float32_default_nan;
         return float32_default_nan;
     }
     }
     if ( aExp == 0 ) {
     if ( aExp == 0 ) {
@@ -1132,7 +1123,7 @@ static float32 subFloat32Sigs( float32 a, float32 b, flag zSign )
     }
     }
     if ( bSig < aSig ) goto aBigger;
     if ( bSig < aSig ) goto aBigger;
     if ( aSig < bSig ) goto bBigger;
     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:
  bExpBigger:
     if ( bExp == 0xFF ) {
     if ( bExp == 0xFF ) {
         if ( bSig ) return propagateFloat32NaN( a, b );
         if ( bSig ) return propagateFloat32NaN( a, b );
@@ -1169,7 +1160,7 @@ static float32 subFloat32Sigs( float32 a, float32 b, flag zSign )
     zExp = aExp;
     zExp = aExp;
  normalizeRoundAndPack:
  normalizeRoundAndPack:
     --zExp;
     --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.
 Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 */
 */
-float32 float32_add( float32 a, float32 b )
+float32 float32_add( struct roundingData *roundData, float32 a, float32 b )
 {
 {
     flag aSign, bSign;
     flag aSign, bSign;
 
 
     aSign = extractFloat32Sign( a );
     aSign = extractFloat32Sign( a );
     bSign = extractFloat32Sign( b );
     bSign = extractFloat32Sign( b );
     if ( aSign == bSign ) {
     if ( aSign == bSign ) {
-        return addFloat32Sigs( a, b, aSign );
+        return addFloat32Sigs( roundData, a, b, aSign );
     }
     }
     else {
     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.
 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;
     flag aSign, bSign;
 
 
     aSign = extractFloat32Sign( a );
     aSign = extractFloat32Sign( a );
     bSign = extractFloat32Sign( b );
     bSign = extractFloat32Sign( b );
     if ( aSign == bSign ) {
     if ( aSign == bSign ) {
-        return subFloat32Sigs( a, b, aSign );
+        return subFloat32Sigs( roundData, a, b, aSign );
     }
     }
     else {
     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.
 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;
     flag aSign, bSign, zSign;
     int16 aExp, bExp, zExp;
     int16 aExp, bExp, zExp;
@@ -1244,7 +1235,7 @@ float32 float32_mul( float32 a, float32 b )
             return propagateFloat32NaN( a, b );
             return propagateFloat32NaN( a, b );
         }
         }
         if ( ( bExp | bSig ) == 0 ) {
         if ( ( bExp | bSig ) == 0 ) {
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
             return float32_default_nan;
             return float32_default_nan;
         }
         }
         return packFloat32( zSign, 0xFF, 0 );
         return packFloat32( zSign, 0xFF, 0 );
@@ -1252,7 +1243,7 @@ float32 float32_mul( float32 a, float32 b )
     if ( bExp == 0xFF ) {
     if ( bExp == 0xFF ) {
         if ( bSig ) return propagateFloat32NaN( a, b );
         if ( bSig ) return propagateFloat32NaN( a, b );
         if ( ( aExp | aSig ) == 0 ) {
         if ( ( aExp | aSig ) == 0 ) {
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
             return float32_default_nan;
             return float32_default_nan;
         }
         }
         return packFloat32( zSign, 0xFF, 0 );
         return packFloat32( zSign, 0xFF, 0 );
@@ -1274,7 +1265,7 @@ float32 float32_mul( float32 a, float32 b )
         zSig <<= 1;
         zSig <<= 1;
         --zExp;
         --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.
 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;
     flag aSign, bSign, zSign;
     int16 aExp, bExp, zExp;
     int16 aExp, bExp, zExp;
@@ -1302,7 +1293,7 @@ float32 float32_div( float32 a, float32 b )
         if ( aSig ) return propagateFloat32NaN( a, b );
         if ( aSig ) return propagateFloat32NaN( a, b );
         if ( bExp == 0xFF ) {
         if ( bExp == 0xFF ) {
             if ( bSig ) return propagateFloat32NaN( a, b );
             if ( bSig ) return propagateFloat32NaN( a, b );
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
             return float32_default_nan;
             return float32_default_nan;
         }
         }
         return packFloat32( zSign, 0xFF, 0 );
         return packFloat32( zSign, 0xFF, 0 );
@@ -1314,10 +1305,10 @@ float32 float32_div( float32 a, float32 b )
     if ( bExp == 0 ) {
     if ( bExp == 0 ) {
         if ( bSig == 0 ) {
         if ( bSig == 0 ) {
             if ( ( aExp | aSig ) == 0 ) {
             if ( ( aExp | aSig ) == 0 ) {
-                float_raise( float_flag_invalid );
+                roundData->exception |= float_flag_invalid;
                 return float32_default_nan;
                 return float32_default_nan;
             }
             }
-            float_raise( float_flag_divbyzero );
+            roundData->exception |= float_flag_divbyzero;
             return packFloat32( zSign, 0xFF, 0 );
             return packFloat32( zSign, 0xFF, 0 );
         }
         }
         normalizeFloat32Subnormal( bSig, &bExp, &bSig );
         normalizeFloat32Subnormal( bSig, &bExp, &bSig );
@@ -1341,7 +1332,7 @@ float32 float32_div( float32 a, float32 b )
     if ( ( zSig & 0x3F ) == 0 ) {
     if ( ( zSig & 0x3F ) == 0 ) {
         zSig |= ( ( (bits64) bSig ) * zSig != ( (bits64) aSig )<<32 );
         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.
 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;
     flag aSign, bSign, zSign;
     int16 aExp, bExp, expDiff;
     int16 aExp, bExp, expDiff;
@@ -1372,7 +1363,7 @@ float32 float32_rem( float32 a, float32 b )
         if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
         if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
             return propagateFloat32NaN( a, b );
             return propagateFloat32NaN( a, b );
         }
         }
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         return float32_default_nan;
         return float32_default_nan;
     }
     }
     if ( bExp == 0xFF ) {
     if ( bExp == 0xFF ) {
@@ -1381,7 +1372,7 @@ float32 float32_rem( float32 a, float32 b )
     }
     }
     if ( bExp == 0 ) {
     if ( bExp == 0 ) {
         if ( bSig == 0 ) {
         if ( bSig == 0 ) {
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
             return float32_default_nan;
             return float32_default_nan;
         }
         }
         normalizeFloat32Subnormal( bSig, &bExp, &bSig );
         normalizeFloat32Subnormal( bSig, &bExp, &bSig );
@@ -1444,7 +1435,7 @@ float32 float32_rem( float32 a, float32 b )
     }
     }
     zSign = ( (sbits32) aSig < 0 );
     zSign = ( (sbits32) aSig < 0 );
     if ( zSign ) aSig = - aSig;
     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.
 Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 */
 */
-float32 float32_sqrt( float32 a )
+float32 float32_sqrt( struct roundingData *roundData, float32 a )
 {
 {
     flag aSign;
     flag aSign;
     int16 aExp, zExp;
     int16 aExp, zExp;
@@ -1468,12 +1459,12 @@ float32 float32_sqrt( float32 a )
     if ( aExp == 0xFF ) {
     if ( aExp == 0xFF ) {
         if ( aSig ) return propagateFloat32NaN( a, 0 );
         if ( aSig ) return propagateFloat32NaN( a, 0 );
         if ( ! aSign ) return a;
         if ( ! aSign ) return a;
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         return float32_default_nan;
         return float32_default_nan;
     }
     }
     if ( aSign ) {
     if ( aSign ) {
         if ( ( aExp | aSig ) == 0 ) return a;
         if ( ( aExp | aSig ) == 0 ) return a;
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         return float32_default_nan;
         return float32_default_nan;
     }
     }
     if ( aExp == 0 ) {
     if ( aExp == 0 ) {
@@ -1499,7 +1490,7 @@ float32 float32_sqrt( float32 a )
         }
         }
     }
     }
     shift32RightJamming( zSig, 1, &zSig );
     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.
 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;
     flag aSign;
     int16 aExp, shiftCount;
     int16 aExp, shiftCount;
@@ -1674,7 +1665,7 @@ int32 float64_to_int32( float64 a )
     if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
     if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
     shiftCount = 0x42C - aExp;
     shiftCount = 0x42C - aExp;
     if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig );
     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;
         goto invalid;
     }
     }
     else if ( 52 < shiftCount ) {
     else if ( 52 < shiftCount ) {
-        if ( aExp || aSig ) float_exception_flags |= float_flag_inexact;
+        if ( aExp || aSig ) float_raise( float_flag_inexact );
         return 0;
         return 0;
     }
     }
     aSig |= LIT64( 0x0010000000000000 );
     aSig |= LIT64( 0x0010000000000000 );
@@ -1715,11 +1706,11 @@ int32 float64_to_int32_round_to_zero( float64 a )
     if ( aSign ) z = - z;
     if ( aSign ) z = - z;
     if ( ( z < 0 ) ^ aSign ) {
     if ( ( z < 0 ) ^ aSign ) {
  invalid:
  invalid:
-        float_exception_flags |= float_flag_invalid;
+        float_raise( float_flag_invalid );
         return aSign ? 0x80000000 : 0x7FFFFFFF;
         return aSign ? 0x80000000 : 0x7FFFFFFF;
     }
     }
     if ( ( aSig<<shiftCount ) != savedASig ) {
     if ( ( aSig<<shiftCount ) != savedASig ) {
-        float_exception_flags |= float_flag_inexact;
+        float_raise( float_flag_inexact );
     }
     }
     return z;
     return z;
 
 
@@ -1736,7 +1727,7 @@ positive integer is returned.  Otherwise, if the conversion overflows, the
 largest positive integer is returned.
 largest positive integer is returned.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 */
 */
-int32 float64_to_uint32( float64 a )
+int32 float64_to_uint32( struct roundingData *roundData, float64 a )
 {
 {
     flag aSign;
     flag aSign;
     int16 aExp, shiftCount;
     int16 aExp, shiftCount;
@@ -1749,7 +1740,7 @@ int32 float64_to_uint32( float64 a )
     if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
     if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
     shiftCount = 0x42C - aExp;
     shiftCount = 0x42C - aExp;
     if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig );
     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;
         goto invalid;
     }
     }
     else if ( 52 < shiftCount ) {
     else if ( 52 < shiftCount ) {
-        if ( aExp || aSig ) float_exception_flags |= float_flag_inexact;
+        if ( aExp || aSig ) float_raise( float_flag_inexact );
         return 0;
         return 0;
     }
     }
     aSig |= LIT64( 0x0010000000000000 );
     aSig |= LIT64( 0x0010000000000000 );
@@ -1788,11 +1779,11 @@ int32 float64_to_uint32_round_to_zero( float64 a )
     if ( aSign ) z = - z;
     if ( aSign ) z = - z;
     if ( ( z < 0 ) ^ aSign ) {
     if ( ( z < 0 ) ^ aSign ) {
  invalid:
  invalid:
-        float_exception_flags |= float_flag_invalid;
+        float_raise( float_flag_invalid );
         return aSign ? 0x80000000 : 0x7FFFFFFF;
         return aSign ? 0x80000000 : 0x7FFFFFFF;
     }
     }
     if ( ( aSig<<shiftCount ) != savedASig ) {
     if ( ( aSig<<shiftCount ) != savedASig ) {
-        float_exception_flags |= float_flag_inexact;
+        float_raise( float_flag_inexact );
     }
     }
     return z;
     return z;
 }
 }
@@ -1805,7 +1796,7 @@ performed according to the IEC/IEEE Standard for Binary Floating-point
 Arithmetic.
 Arithmetic.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 */
 */
-float32 float64_to_float32( float64 a )
+float32 float64_to_float32( struct roundingData *roundData, float64 a )
 {
 {
     flag aSign;
     flag aSign;
     int16 aExp;
     int16 aExp;
@@ -1825,7 +1816,7 @@ float32 float64_to_float32( float64 a )
         zSig |= 0x40000000;
         zSig |= 0x40000000;
         aExp -= 0x381;
         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.
 Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 */
 */
-float64 float64_round_to_int( float64 a )
+float64 float64_round_to_int( struct roundingData *roundData, float64 a )
 {
 {
     flag aSign;
     flag aSign;
     int16 aExp;
     int16 aExp;
@@ -1889,9 +1880,9 @@ float64 float64_round_to_int( float64 a )
     }
     }
     if ( aExp <= 0x3FE ) {
     if ( aExp <= 0x3FE ) {
         if ( (bits64) ( a<<1 ) == 0 ) return a;
         if ( (bits64) ( a<<1 ) == 0 ) return a;
-        float_exception_flags |= float_flag_inexact;
+        roundData->exception |= float_flag_inexact;
         aSign = extractFloat64Sign( a );
         aSign = extractFloat64Sign( a );
-        switch ( float_rounding_mode ) {
+        switch ( roundData->mode ) {
          case float_round_nearest_even:
          case float_round_nearest_even:
             if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) {
             if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) {
                 return packFloat64( aSign, 0x3FF, 0 );
                 return packFloat64( aSign, 0x3FF, 0 );
@@ -1909,7 +1900,7 @@ float64 float64_round_to_int( float64 a )
     lastBitMask <<= 0x433 - aExp;
     lastBitMask <<= 0x433 - aExp;
     roundBitsMask = lastBitMask - 1;
     roundBitsMask = lastBitMask - 1;
     z = a;
     z = a;
-    roundingMode = float_rounding_mode;
+    roundingMode = roundData->mode;
     if ( roundingMode == float_round_nearest_even ) {
     if ( roundingMode == float_round_nearest_even ) {
         z += lastBitMask>>1;
         z += lastBitMask>>1;
         if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
         if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
@@ -1920,7 +1911,7 @@ float64 float64_round_to_int( float64 a )
         }
         }
     }
     }
     z &= ~ roundBitsMask;
     z &= ~ roundBitsMask;
-    if ( z != a ) float_exception_flags |= float_flag_inexact;
+    if ( z != a ) roundData->exception |= float_flag_inexact;
     return z;
     return z;
 
 
 }
 }
@@ -1934,7 +1925,7 @@ addition is performed according to the IEC/IEEE Standard for Binary
 Floating-point Arithmetic.
 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;
     int16 aExp, bExp, zExp;
     bits64 aSig, bSig, zSig;
     bits64 aSig, bSig, zSig;
@@ -1993,7 +1984,7 @@ static float64 addFloat64Sigs( float64 a, float64 b, flag zSign )
         ++zExp;
         ++zExp;
     }
     }
  roundAndPack:
  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.
 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;
     int16 aExp, bExp, zExp;
     bits64 aSig, bSig, zSig;
     bits64 aSig, bSig, zSig;
@@ -2023,7 +2014,7 @@ static float64 subFloat64Sigs( float64 a, float64 b, flag zSign )
     if ( expDiff < 0 ) goto bExpBigger;
     if ( expDiff < 0 ) goto bExpBigger;
     if ( aExp == 0x7FF ) {
     if ( aExp == 0x7FF ) {
         if ( aSig | bSig ) return propagateFloat64NaN( a, b );
         if ( aSig | bSig ) return propagateFloat64NaN( a, b );
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         return float64_default_nan;
         return float64_default_nan;
     }
     }
     if ( aExp == 0 ) {
     if ( aExp == 0 ) {
@@ -2032,7 +2023,7 @@ static float64 subFloat64Sigs( float64 a, float64 b, flag zSign )
     }
     }
     if ( bSig < aSig ) goto aBigger;
     if ( bSig < aSig ) goto aBigger;
     if ( aSig < bSig ) goto bBigger;
     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:
  bExpBigger:
     if ( bExp == 0x7FF ) {
     if ( bExp == 0x7FF ) {
         if ( bSig ) return propagateFloat64NaN( a, b );
         if ( bSig ) return propagateFloat64NaN( a, b );
@@ -2069,7 +2060,7 @@ static float64 subFloat64Sigs( float64 a, float64 b, flag zSign )
     zExp = aExp;
     zExp = aExp;
  normalizeRoundAndPack:
  normalizeRoundAndPack:
     --zExp;
     --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.
 Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 */
 */
-float64 float64_add( float64 a, float64 b )
+float64 float64_add( struct roundingData *roundData, float64 a, float64 b )
 {
 {
     flag aSign, bSign;
     flag aSign, bSign;
 
 
     aSign = extractFloat64Sign( a );
     aSign = extractFloat64Sign( a );
     bSign = extractFloat64Sign( b );
     bSign = extractFloat64Sign( b );
     if ( aSign == bSign ) {
     if ( aSign == bSign ) {
-        return addFloat64Sigs( a, b, aSign );
+        return addFloat64Sigs( roundData, a, b, aSign );
     }
     }
     else {
     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.
 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;
     flag aSign, bSign;
 
 
     aSign = extractFloat64Sign( a );
     aSign = extractFloat64Sign( a );
     bSign = extractFloat64Sign( b );
     bSign = extractFloat64Sign( b );
     if ( aSign == bSign ) {
     if ( aSign == bSign ) {
-        return subFloat64Sigs( a, b, aSign );
+        return subFloat64Sigs( roundData, a, b, aSign );
     }
     }
     else {
     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.
 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;
     flag aSign, bSign, zSign;
     int16 aExp, bExp, zExp;
     int16 aExp, bExp, zExp;
@@ -2142,7 +2133,7 @@ float64 float64_mul( float64 a, float64 b )
             return propagateFloat64NaN( a, b );
             return propagateFloat64NaN( a, b );
         }
         }
         if ( ( bExp | bSig ) == 0 ) {
         if ( ( bExp | bSig ) == 0 ) {
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
             return float64_default_nan;
             return float64_default_nan;
         }
         }
         return packFloat64( zSign, 0x7FF, 0 );
         return packFloat64( zSign, 0x7FF, 0 );
@@ -2150,7 +2141,7 @@ float64 float64_mul( float64 a, float64 b )
     if ( bExp == 0x7FF ) {
     if ( bExp == 0x7FF ) {
         if ( bSig ) return propagateFloat64NaN( a, b );
         if ( bSig ) return propagateFloat64NaN( a, b );
         if ( ( aExp | aSig ) == 0 ) {
         if ( ( aExp | aSig ) == 0 ) {
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
             return float64_default_nan;
             return float64_default_nan;
         }
         }
         return packFloat64( zSign, 0x7FF, 0 );
         return packFloat64( zSign, 0x7FF, 0 );
@@ -2172,7 +2163,7 @@ float64 float64_mul( float64 a, float64 b )
         zSig0 <<= 1;
         zSig0 <<= 1;
         --zExp;
         --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.
 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;
     flag aSign, bSign, zSign;
     int16 aExp, bExp, zExp;
     int16 aExp, bExp, zExp;
@@ -2202,7 +2193,7 @@ float64 float64_div( float64 a, float64 b )
         if ( aSig ) return propagateFloat64NaN( a, b );
         if ( aSig ) return propagateFloat64NaN( a, b );
         if ( bExp == 0x7FF ) {
         if ( bExp == 0x7FF ) {
             if ( bSig ) return propagateFloat64NaN( a, b );
             if ( bSig ) return propagateFloat64NaN( a, b );
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
             return float64_default_nan;
             return float64_default_nan;
         }
         }
         return packFloat64( zSign, 0x7FF, 0 );
         return packFloat64( zSign, 0x7FF, 0 );
@@ -2214,10 +2205,10 @@ float64 float64_div( float64 a, float64 b )
     if ( bExp == 0 ) {
     if ( bExp == 0 ) {
         if ( bSig == 0 ) {
         if ( bSig == 0 ) {
             if ( ( aExp | aSig ) == 0 ) {
             if ( ( aExp | aSig ) == 0 ) {
-                float_raise( float_flag_invalid );
+                roundData->exception |= float_flag_invalid;
                 return float64_default_nan;
                 return float64_default_nan;
             }
             }
-            float_raise( float_flag_divbyzero );
+            roundData->exception |= float_flag_divbyzero;
             return packFloat64( zSign, 0x7FF, 0 );
             return packFloat64( zSign, 0x7FF, 0 );
         }
         }
         normalizeFloat64Subnormal( bSig, &bExp, &bSig );
         normalizeFloat64Subnormal( bSig, &bExp, &bSig );
@@ -2243,7 +2234,7 @@ float64 float64_div( float64 a, float64 b )
         }
         }
         zSig |= ( rem1 != 0 );
         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.
 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;
     flag aSign, bSign, zSign;
     int16 aExp, bExp, expDiff;
     int16 aExp, bExp, expDiff;
@@ -2272,7 +2263,7 @@ float64 float64_rem( float64 a, float64 b )
         if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) {
         if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) {
             return propagateFloat64NaN( a, b );
             return propagateFloat64NaN( a, b );
         }
         }
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         return float64_default_nan;
         return float64_default_nan;
     }
     }
     if ( bExp == 0x7FF ) {
     if ( bExp == 0x7FF ) {
@@ -2281,7 +2272,7 @@ float64 float64_rem( float64 a, float64 b )
     }
     }
     if ( bExp == 0 ) {
     if ( bExp == 0 ) {
         if ( bSig == 0 ) {
         if ( bSig == 0 ) {
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
             return float64_default_nan;
             return float64_default_nan;
         }
         }
         normalizeFloat64Subnormal( bSig, &bExp, &bSig );
         normalizeFloat64Subnormal( bSig, &bExp, &bSig );
@@ -2329,7 +2320,7 @@ float64 float64_rem( float64 a, float64 b )
     }
     }
     zSign = ( (sbits64) aSig < 0 );
     zSign = ( (sbits64) aSig < 0 );
     if ( zSign ) aSig = - aSig;
     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.
 Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 */
 */
-float64 float64_sqrt( float64 a )
+float64 float64_sqrt( struct roundingData *roundData, float64 a )
 {
 {
     flag aSign;
     flag aSign;
     int16 aExp, zExp;
     int16 aExp, zExp;
@@ -2354,12 +2345,12 @@ float64 float64_sqrt( float64 a )
     if ( aExp == 0x7FF ) {
     if ( aExp == 0x7FF ) {
         if ( aSig ) return propagateFloat64NaN( a, a );
         if ( aSig ) return propagateFloat64NaN( a, a );
         if ( ! aSign ) return a;
         if ( ! aSign ) return a;
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         return float64_default_nan;
         return float64_default_nan;
     }
     }
     if ( aSign ) {
     if ( aSign ) {
         if ( ( aExp | aSig ) == 0 ) return a;
         if ( ( aExp | aSig ) == 0 ) return a;
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         return float64_default_nan;
         return float64_default_nan;
     }
     }
     if ( aExp == 0 ) {
     if ( aExp == 0 ) {
@@ -2390,7 +2381,7 @@ float64 float64_sqrt( float64 a )
         }
         }
     }
     }
     shift64RightJamming( zSig, 1, &zSig );
     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.
 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;
     flag aSign;
     int32 aExp, shiftCount;
     int32 aExp, shiftCount;
@@ -2567,7 +2558,7 @@ int32 floatx80_to_int32( floatx80 a )
     shiftCount = 0x4037 - aExp;
     shiftCount = 0x4037 - aExp;
     if ( shiftCount <= 0 ) shiftCount = 1;
     if ( shiftCount <= 0 ) shiftCount = 1;
     shift64RightJamming( aSig, shiftCount, &aSig );
     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;
         goto invalid;
     }
     }
     else if ( 63 < shiftCount ) {
     else if ( 63 < shiftCount ) {
-        if ( aExp || aSig ) float_exception_flags |= float_flag_inexact;
+        if ( aExp || aSig ) float_raise( float_flag_inexact );
         return 0;
         return 0;
     }
     }
     savedASig = aSig;
     savedASig = aSig;
@@ -2607,11 +2598,11 @@ int32 floatx80_to_int32_round_to_zero( floatx80 a )
     if ( aSign ) z = - z;
     if ( aSign ) z = - z;
     if ( ( z < 0 ) ^ aSign ) {
     if ( ( z < 0 ) ^ aSign ) {
  invalid:
  invalid:
-        float_exception_flags |= float_flag_invalid;
+        float_raise( float_flag_invalid );
         return aSign ? 0x80000000 : 0x7FFFFFFF;
         return aSign ? 0x80000000 : 0x7FFFFFFF;
     }
     }
     if ( ( aSig<<shiftCount ) != savedASig ) {
     if ( ( aSig<<shiftCount ) != savedASig ) {
-        float_exception_flags |= float_flag_inexact;
+        float_raise( float_flag_inexact );
     }
     }
     return z;
     return z;
 
 
@@ -2625,7 +2616,7 @@ conversion is performed according to the IEC/IEEE Standard for Binary
 Floating-point Arithmetic.
 Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 */
 */
-float32 floatx80_to_float32( floatx80 a )
+float32 floatx80_to_float32( struct roundingData *roundData, floatx80 a )
 {
 {
     flag aSign;
     flag aSign;
     int32 aExp;
     int32 aExp;
@@ -2642,7 +2633,7 @@ float32 floatx80_to_float32( floatx80 a )
     }
     }
     shift64RightJamming( aSig, 33, &aSig );
     shift64RightJamming( aSig, 33, &aSig );
     if ( aExp || aSig ) aExp -= 0x3F81;
     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.
 Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 */
 */
-float64 floatx80_to_float64( floatx80 a )
+float64 floatx80_to_float64( struct roundingData *roundData, floatx80 a )
 {
 {
     flag aSign;
     flag aSign;
     int32 aExp;
     int32 aExp;
@@ -2671,7 +2662,7 @@ float64 floatx80_to_float64( floatx80 a )
     }
     }
     shift64RightJamming( aSig, 1, &zSig );
     shift64RightJamming( aSig, 1, &zSig );
     if ( aExp || aSig ) aExp -= 0x3C01;
     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.
 Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 */
 */
-floatx80 floatx80_round_to_int( floatx80 a )
+floatx80 floatx80_round_to_int( struct roundingData *roundData, floatx80 a )
 {
 {
     flag aSign;
     flag aSign;
     int32 aExp;
     int32 aExp;
@@ -2703,9 +2694,9 @@ floatx80 floatx80_round_to_int( floatx80 a )
              && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) {
              && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) {
             return a;
             return a;
         }
         }
-        float_exception_flags |= float_flag_inexact;
+        roundData->exception |= float_flag_inexact;
         aSign = extractFloatx80Sign( a );
         aSign = extractFloatx80Sign( a );
-        switch ( float_rounding_mode ) {
+        switch ( roundData->mode ) {
          case float_round_nearest_even:
          case float_round_nearest_even:
             if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 )
             if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 )
                ) {
                ) {
@@ -2729,7 +2720,7 @@ floatx80 floatx80_round_to_int( floatx80 a )
     lastBitMask <<= 0x403E - aExp;
     lastBitMask <<= 0x403E - aExp;
     roundBitsMask = lastBitMask - 1;
     roundBitsMask = lastBitMask - 1;
     z = a;
     z = a;
-    roundingMode = float_rounding_mode;
+    roundingMode = roundData->mode;
     if ( roundingMode == float_round_nearest_even ) {
     if ( roundingMode == float_round_nearest_even ) {
         z.low += lastBitMask>>1;
         z.low += lastBitMask>>1;
         if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
         if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
@@ -2744,7 +2735,7 @@ floatx80 floatx80_round_to_int( floatx80 a )
         ++z.high;
         ++z.high;
         z.low = LIT64( 0x8000000000000000 );
         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;
     return z;
 
 
 }
 }
@@ -2758,7 +2749,7 @@ The addition is performed according to the IEC/IEEE Standard for Binary
 Floating-point Arithmetic.
 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;
     int32 aExp, bExp, zExp;
     bits64 aSig, bSig, zSig0, zSig1;
     bits64 aSig, bSig, zSig0, zSig1;
@@ -2814,7 +2805,7 @@ static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
  roundAndPack:
  roundAndPack:
     return
     return
         roundAndPackFloatx80(
         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.
 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;
     int32 aExp, bExp, zExp;
     bits64 aSig, bSig, zSig0, zSig1;
     bits64 aSig, bSig, zSig0, zSig1;
@@ -2845,7 +2836,7 @@ static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
         if ( (bits64) ( ( aSig | bSig )<<1 ) ) {
         if ( (bits64) ( ( aSig | bSig )<<1 ) ) {
             return propagateFloatx80NaN( a, b );
             return propagateFloatx80NaN( a, b );
         }
         }
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         z.low = floatx80_default_nan_low;
         z.low = floatx80_default_nan_low;
         z.high = floatx80_default_nan_high;
         z.high = floatx80_default_nan_high;
         return z;
         return z;
@@ -2857,7 +2848,7 @@ static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
     zSig1 = 0;
     zSig1 = 0;
     if ( bSig < aSig ) goto aBigger;
     if ( bSig < aSig ) goto aBigger;
     if ( aSig < bSig ) goto bBigger;
     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:
  bExpBigger:
     if ( bExp == 0x7FFF ) {
     if ( bExp == 0x7FFF ) {
         if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
         if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
@@ -2883,7 +2874,7 @@ static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
  normalizeRoundAndPack:
  normalizeRoundAndPack:
     return
     return
         normalizeRoundAndPackFloatx80(
         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.
 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;
     flag aSign, bSign;
     
     
     aSign = extractFloatx80Sign( a );
     aSign = extractFloatx80Sign( a );
     bSign = extractFloatx80Sign( b );
     bSign = extractFloatx80Sign( b );
     if ( aSign == bSign ) {
     if ( aSign == bSign ) {
-        return addFloatx80Sigs( a, b, aSign );
+        return addFloatx80Sigs( roundData, a, b, aSign );
     }
     }
     else {
     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.
 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;
     flag aSign, bSign;
 
 
     aSign = extractFloatx80Sign( a );
     aSign = extractFloatx80Sign( a );
     bSign = extractFloatx80Sign( b );
     bSign = extractFloatx80Sign( b );
     if ( aSign == bSign ) {
     if ( aSign == bSign ) {
-        return subFloatx80Sigs( a, b, aSign );
+        return subFloatx80Sigs( roundData, a, b, aSign );
     }
     }
     else {
     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.
 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;
     flag aSign, bSign, zSign;
     int32 aExp, bExp, zExp;
     int32 aExp, bExp, zExp;
@@ -2964,7 +2955,7 @@ floatx80 floatx80_mul( floatx80 a, floatx80 b )
         if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
         if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
         if ( ( aExp | aSig ) == 0 ) {
         if ( ( aExp | aSig ) == 0 ) {
  invalid:
  invalid:
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
             z.low = floatx80_default_nan_low;
             z.low = floatx80_default_nan_low;
             z.high = floatx80_default_nan_high;
             z.high = floatx80_default_nan_high;
             return z;
             return z;
@@ -2987,7 +2978,7 @@ floatx80 floatx80_mul( floatx80 a, floatx80 b )
     }
     }
     return
     return
         roundAndPackFloatx80(
         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.
 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;
     flag aSign, bSign, zSign;
     int32 aExp, bExp, zExp;
     int32 aExp, bExp, zExp;
@@ -3029,12 +3020,12 @@ floatx80 floatx80_div( floatx80 a, floatx80 b )
         if ( bSig == 0 ) {
         if ( bSig == 0 ) {
             if ( ( aExp | aSig ) == 0 ) {
             if ( ( aExp | aSig ) == 0 ) {
  invalid:
  invalid:
-                float_raise( float_flag_invalid );
+                roundData->exception |= float_flag_invalid;
                 z.low = floatx80_default_nan_low;
                 z.low = floatx80_default_nan_low;
                 z.high = floatx80_default_nan_high;
                 z.high = floatx80_default_nan_high;
                 return z;
                 return z;
             }
             }
-            float_raise( float_flag_divbyzero );
+            roundData->exception |= float_flag_divbyzero;
             return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
             return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
         }
         }
         normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
         normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
@@ -3068,7 +3059,7 @@ floatx80 floatx80_div( floatx80 a, floatx80 b )
     }
     }
     return
     return
         roundAndPackFloatx80(
         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.
 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;
     flag aSign, bSign, zSign;
     int32 aExp, bExp, expDiff;
     int32 aExp, bExp, expDiff;
@@ -3107,7 +3098,7 @@ floatx80 floatx80_rem( floatx80 a, floatx80 b )
     if ( bExp == 0 ) {
     if ( bExp == 0 ) {
         if ( bSig == 0 ) {
         if ( bSig == 0 ) {
  invalid:
  invalid:
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
             z.low = floatx80_default_nan_low;
             z.low = floatx80_default_nan_low;
             z.high = floatx80_default_nan_high;
             z.high = floatx80_default_nan_high;
             return z;
             return z;
@@ -3164,9 +3155,10 @@ floatx80 floatx80_rem( floatx80 a, floatx80 b )
         aSig1 = alternateASig1;
         aSig1 = alternateASig1;
         zSign = ! zSign;
         zSign = ! zSign;
     }
     }
+
     return
     return
         normalizeRoundAndPackFloatx80(
         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.
 for Binary Floating-point Arithmetic.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 */
 */
-floatx80 floatx80_sqrt( floatx80 a )
+floatx80 floatx80_sqrt( struct roundingData *roundData, floatx80 a )
 {
 {
     flag aSign;
     flag aSign;
     int32 aExp, zExp;
     int32 aExp, zExp;
@@ -3197,7 +3189,7 @@ floatx80 floatx80_sqrt( floatx80 a )
     if ( aSign ) {
     if ( aSign ) {
         if ( ( aExp | aSig0 ) == 0 ) return a;
         if ( ( aExp | aSig0 ) == 0 ) return a;
  invalid:
  invalid:
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         z.low = floatx80_default_nan_low;
         z.low = floatx80_default_nan_low;
         z.high = floatx80_default_nan_high;
         z.high = floatx80_default_nan_high;
         return z;
         return z;
@@ -3242,7 +3234,7 @@ floatx80 floatx80_sqrt( floatx80 a )
     }
     }
     return
     return
         roundAndPackFloatx80(
         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 )
         if (    floatx80_is_signaling_nan( a )
              || floatx80_is_signaling_nan( b ) ) {
              || floatx80_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
         }
         }
         return 0;
         return 0;
     }
     }
@@ -3294,7 +3286,7 @@ flag floatx80_le( floatx80 a, floatx80 b )
          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
               && (bits64) ( extractFloatx80Frac( b )<<1 ) )
               && (bits64) ( extractFloatx80Frac( b )<<1 ) )
        ) {
        ) {
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         return 0;
         return 0;
     }
     }
     aSign = extractFloatx80Sign( a );
     aSign = extractFloatx80Sign( a );
@@ -3328,7 +3320,7 @@ flag floatx80_lt( floatx80 a, floatx80 b )
          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
               && (bits64) ( extractFloatx80Frac( b )<<1 ) )
               && (bits64) ( extractFloatx80Frac( b )<<1 ) )
        ) {
        ) {
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         return 0;
         return 0;
     }
     }
     aSign = extractFloatx80Sign( a );
     aSign = extractFloatx80Sign( a );
@@ -3361,7 +3353,7 @@ flag floatx80_eq_signaling( floatx80 a, floatx80 b )
          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
               && (bits64) ( extractFloatx80Frac( b )<<1 ) )
               && (bits64) ( extractFloatx80Frac( b )<<1 ) )
        ) {
        ) {
-        float_raise( float_flag_invalid );
+        roundData->exception |= float_flag_invalid;
         return 0;
         return 0;
     }
     }
     return
     return
@@ -3392,7 +3384,7 @@ flag floatx80_le_quiet( floatx80 a, floatx80 b )
        ) {
        ) {
         if (    floatx80_is_signaling_nan( a )
         if (    floatx80_is_signaling_nan( a )
              || floatx80_is_signaling_nan( b ) ) {
              || floatx80_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
         }
         }
         return 0;
         return 0;
     }
     }
@@ -3429,7 +3421,7 @@ flag floatx80_lt_quiet( floatx80 a, floatx80 b )
        ) {
        ) {
         if (    floatx80_is_signaling_nan( a )
         if (    floatx80_is_signaling_nan( a )
              || floatx80_is_signaling_nan( b ) ) {
              || floatx80_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid );
+            roundData->exception |= float_flag_invalid;
         }
         }
         return 0;
         return 0;
     }
     }

+ 29 - 39
arch/arm/nwfpe/softfloat.h

@@ -74,7 +74,7 @@ enum {
 Software IEC/IEEE floating-point rounding mode.
 Software IEC/IEEE floating-point rounding mode.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 */
 */
-extern signed char float_rounding_mode;
+//extern int8 float_rounding_mode;
 enum {
 enum {
     float_round_nearest_even = 0,
     float_round_nearest_even = 0,
     float_round_to_zero      = 1,
     float_round_to_zero      = 1,
@@ -86,7 +86,6 @@ enum {
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Software IEC/IEEE floating-point exception flags.
 Software IEC/IEEE floating-point exception flags.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
-extern signed char float_exception_flags;
 enum {
 enum {
     float_flag_inexact   =  1,
     float_flag_inexact   =  1,
     float_flag_underflow =  2,
     float_flag_underflow =  2,
@@ -99,7 +98,6 @@ ScottB: November 4, 1998
 Changed the enumeration to match the bit order in the FPA11.
 Changed the enumeration to match the bit order in the FPA11.
 */
 */
 
 
-extern signed char float_exception_flags;
 enum {
 enum {
     float_flag_invalid   =  1,
     float_flag_invalid   =  1,
     float_flag_divbyzero =  2,
     float_flag_divbyzero =  2,
@@ -121,7 +119,7 @@ void float_raise( signed char );
 Software IEC/IEEE integer-to-floating-point conversion routines.
 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 );
 float64 int32_to_float64( signed int );
 #ifdef FLOATX80
 #ifdef FLOATX80
 floatx80 int32_to_floatx80( signed int );
 floatx80 int32_to_floatx80( signed int );
@@ -132,7 +130,7 @@ floatx80 int32_to_floatx80( signed int );
 Software IEC/IEEE single-precision conversion routines.
 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 );
 signed int float32_to_int32_round_to_zero( float32 );
 float64 float32_to_float64( float32 );
 float64 float32_to_float64( float32 );
 #ifdef FLOATX80
 #ifdef FLOATX80
@@ -144,13 +142,13 @@ floatx80 float32_to_floatx80( float32 );
 Software IEC/IEEE single-precision operations.
 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_eq( float32, float32 );
 char float32_le( float32, float32 );
 char float32_le( float32, float32 );
 char float32_lt( float32, float32 );
 char float32_lt( float32, float32 );
@@ -164,9 +162,9 @@ char float32_is_signaling_nan( float32 );
 Software IEC/IEEE double-precision conversion routines.
 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 );
 signed int float64_to_int32_round_to_zero( float64 );
-float32 float64_to_float32( float64 );
+float32 float64_to_float32( struct roundingData *, float64 );
 #ifdef FLOATX80
 #ifdef FLOATX80
 floatx80 float64_to_floatx80( float64 );
 floatx80 float64_to_floatx80( float64 );
 #endif
 #endif
@@ -176,13 +174,13 @@ floatx80 float64_to_floatx80( float64 );
 Software IEC/IEEE double-precision operations.
 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_eq( float64, float64 );
 char float64_le( float64, float64 );
 char float64_le( float64, float64 );
 char float64_lt( 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.
 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 );
 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.
 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_eq( floatx80, floatx80 );
 char floatx80_le( floatx80, floatx80 );
 char floatx80_le( floatx80, floatx80 );
 char floatx80_lt( floatx80, floatx80 );
 char floatx80_lt( floatx80, floatx80 );

+ 3 - 0
arch/arm/vfp/vfpdouble.c

@@ -770,6 +770,9 @@ vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,
 		if ((s64)m_sig < 0) {
 		if ((s64)m_sig < 0) {
 			vdd->sign = vfp_sign_negate(vdd->sign);
 			vdd->sign = vfp_sign_negate(vdd->sign);
 			m_sig = -m_sig;
 			m_sig = -m_sig;
+		} else if (m_sig == 0) {
+			vdd->sign = (fpscr & FPSCR_RMODE_MASK) ==
+				      FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
 		}
 		}
 	} else {
 	} else {
 		m_sig += vdn->significand;
 		m_sig += vdn->significand;

+ 10 - 39
drivers/char/watchdog/sa1100_wdt.c

@@ -36,13 +36,10 @@
 #include <asm/uaccess.h>
 #include <asm/uaccess.h>
 
 
 #define OSCR_FREQ		CLOCK_TICK_RATE
 #define OSCR_FREQ		CLOCK_TICK_RATE
-#define SA1100_CLOSE_MAGIC	(0x5afc4453)
 
 
 static unsigned long sa1100wdt_users;
 static unsigned long sa1100wdt_users;
-static int expect_close;
 static int pre_margin;
 static int pre_margin;
 static int boot_status;
 static int boot_status;
-static int nowayout = WATCHDOG_NOWAYOUT;
 
 
 /*
 /*
  *	Allow only one person to hold it open
  *	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)
 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);
 	clear_bit(1, &sa1100wdt_users);
-	expect_close = 0;
 
 
 	return 0;
 	return 0;
 }
 }
 
 
 static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
 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. */
 		/* Refresh OSMR3 timer. */
 		OSMR3 = OSCR + pre_margin;
 		OSMR3 = OSCR + pre_margin;
-	}
 
 
 	return len;
 	return len;
 }
 }
 
 
 static struct watchdog_info ident = {
 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,
 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 =
 static struct miscdevice sa1100dog_miscdev =
 {
 {
 	.minor		= WATCHDOG_MINOR,
 	.minor		= WATCHDOG_MINOR,
-	.name		= "SA1100/PXA2xx watchdog",
+	.name		= "watchdog",
 	.fops		= &sa1100dog_fops,
 	.fops		= &sa1100dog_fops,
 };
 };
 
 
@@ -194,7 +169,6 @@ static int __init sa1100dog_init(void)
 	if (ret == 0)
 	if (ret == 0)
 		printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n",
 		printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n",
 		       margin);
 		       margin);
-
 	return ret;
 	return ret;
 }
 }
 
 
@@ -212,8 +186,5 @@ MODULE_DESCRIPTION("SA1100/PXA2xx Watchdog");
 module_param(margin, int, 0);
 module_param(margin, int, 0);
 MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)");
 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_LICENSE("GPL");
 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);