diff --git a/[refs] b/[refs] index 7e5cba9740e5..330699c3f001 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 9d343219e33e8b49d754ea9b2e45f6c7da87f4fb +refs/heads/master: 11e981f1e02c2a36465cbb208b21cb8b6480f399 diff --git a/trunk/Documentation/dontdiff b/trunk/Documentation/dontdiff index 96bea278bbf6..b974cf595d01 100644 --- a/trunk/Documentation/dontdiff +++ b/trunk/Documentation/dontdiff @@ -104,7 +104,6 @@ logo_*.c logo_*_clut224.c logo_*_mono.c lxdialog -mach-types mach-types.h make_times_h map diff --git a/trunk/arch/arm/mach-ixp4xx/coyote-setup.c b/trunk/arch/arm/mach-ixp4xx/coyote-setup.c index 7f58afb27e71..4ff4393ef0ea 100644 --- a/trunk/arch/arm/mach-ixp4xx/coyote-setup.c +++ b/trunk/arch/arm/mach-ixp4xx/coyote-setup.c @@ -61,7 +61,7 @@ static struct plat_serial8250_port coyote_uart_data[] = { .mapbase = IXP4XX_UART2_BASE_PHYS, .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, .irq = IRQ_IXP4XX_UART2, - .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + .flags = UPF_BOOT_AUTOCONF, .iotype = UPIO_MEM, .regshift = 2, .uartclk = IXP4XX_UART_XTAL, diff --git a/trunk/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/trunk/arch/arm/mach-ixp4xx/gtwx5715-setup.c index 65e356bd10d6..8ba1cd9406e7 100644 --- a/trunk/arch/arm/mach-ixp4xx/gtwx5715-setup.c +++ b/trunk/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, .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, .irq = IRQ_IXP4XX_UART2, - .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + .flags = UPF_BOOT_AUTOCONF, .iotype = UPIO_MEM, .regshift = 2, .uartclk = IXP4XX_UART_XTAL, diff --git a/trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c b/trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c index 4633470a6a37..c2ba759e9946 100644 --- a/trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -82,7 +82,7 @@ static struct plat_serial8250_port ixdp425_uart_data[] = { .mapbase = IXP4XX_UART1_BASE_PHYS, .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, .irq = IRQ_IXP4XX_UART1, - .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + .flags = UPF_BOOT_AUTOCONF, .iotype = UPIO_MEM, .regshift = 2, .uartclk = IXP4XX_UART_XTAL, @@ -91,7 +91,7 @@ static struct plat_serial8250_port ixdp425_uart_data[] = { .mapbase = IXP4XX_UART2_BASE_PHYS, .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, .irq = IRQ_IXP4XX_UART1, - .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + .flags = UPF_BOOT_AUTOCONF, .iotype = UPIO_MEM, .regshift = 2, .uartclk = IXP4XX_UART_XTAL, diff --git a/trunk/arch/arm/mach-s3c2410/mach-bast.c b/trunk/arch/arm/mach-s3c2410/mach-bast.c index e9182242da95..1e7f343822d0 100644 --- a/trunk/arch/arm/mach-s3c2410/mach-bast.c +++ b/trunk/arch/arm/mach-s3c2410/mach-bast.c @@ -30,7 +30,6 @@ * 28-Jun-2005 BJD Moved pm functionality out to common code * 17-Jul-2005 BJD Changed to platform device for SuperIO 16550s * 25-Jul-2005 BJD Removed ASIX static mappings - * 27-Jul-2005 BJD Ensure maximum frequency of i2c bus */ #include @@ -61,7 +60,6 @@ #include #include #include -#include #include #include @@ -306,7 +304,7 @@ static void bast_nand_select(struct s3c2410_nand_set *set, int slot) } static struct s3c2410_platform_nand bast_nand_info = { - .tacls = 40, + .tacls = 80, .twrph0 = 80, .twrph1 = 80, .nr_sets = ARRAY_SIZE(bast_nand_sets), @@ -387,17 +385,6 @@ static struct platform_device bast_sio = { }, }; -/* we have devices on the bus which cannot work much over the - * standard 100KHz i2c bus frequency -*/ - -static struct s3c2410_platform_i2c bast_i2c_info = { - .flags = 0, - .slave_addr = 0x10, - .bus_freq = 100*1000, - .max_freq = 130*1000, -}; - /* Standard BAST devices */ static struct platform_device *bast_devices[] __initdata = { @@ -444,7 +431,6 @@ void __init bast_map_io(void) s3c24xx_uclk.parent = &s3c24xx_clkout1; s3c_device_nand.dev.platform_data = &bast_nand_info; - s3c_device_i2c.dev.platform_data = &bast_i2c_info; s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc)); s3c24xx_init_clocks(0); diff --git a/trunk/arch/arm/mm/fault.c b/trunk/arch/arm/mm/fault.c index 0b6c4db44e08..65bfe84b6d67 100644 --- a/trunk/arch/arm/mm/fault.c +++ b/trunk/arch/arm/mm/fault.c @@ -238,9 +238,9 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) up_read(&mm->mmap_sem); /* - * Handle the "normal" case first - VM_FAULT_MAJOR / VM_FAULT_MINOR + * Handle the "normal" case first */ - if (fault >= VM_FAULT_MINOR) + if (fault > 0) return 0; /* @@ -261,7 +261,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) do_exit(SIGKILL); return 0; - case VM_FAULT_SIGBUS: + case 0: /* * We had some memory, but were unable to * successfully fix up this page fault. diff --git a/trunk/arch/arm/mm/proc-xscale.S b/trunk/arch/arm/mm/proc-xscale.S index b88de2700146..2d977b4eeeab 100644 --- a/trunk/arch/arm/mm/proc-xscale.S +++ b/trunk/arch/arm/mm/proc-xscale.S @@ -370,6 +370,142 @@ ENTRY(cpu_xscale_dcache_clean_area) bhi 1b mov pc, lr +/* ================================ CACHE LOCKING============================ + * + * The XScale MicroArchitecture implements support for locking entries into + * the data and instruction cache. The following functions implement the core + * low level instructions needed to accomplish the locking. The developer's + * manual states that the code that performs the locking must be in non-cached + * memory. To accomplish this, the code in xscale-cache-lock.c copies the + * following functions from the cache into a non-cached memory region that + * is allocated through consistent_alloc(). + * + */ + .align 5 +/* + * xscale_icache_lock + * + * r0: starting address to lock + * r1: end address to lock + */ +ENTRY(xscale_icache_lock) + +iLockLoop: + bic r0, r0, #CACHELINESIZE - 1 + mcr p15, 0, r0, c9, c1, 0 @ lock into cache + cmp r0, r1 @ are we done? + add r0, r0, #CACHELINESIZE @ advance to next cache line + bls iLockLoop + mov pc, lr + +/* + * xscale_icache_unlock + */ +ENTRY(xscale_icache_unlock) + mcr p15, 0, r0, c9, c1, 1 @ Unlock icache + mov pc, lr + +/* + * xscale_dcache_lock + * + * r0: starting address to lock + * r1: end address to lock + */ +ENTRY(xscale_dcache_lock) + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mov r2, #1 + mcr p15, 0, r2, c9, c2, 0 @ Put dcache in lock mode + cpwait ip @ Wait for completion + + mrs r2, cpsr + orr r3, r2, #PSR_F_BIT | PSR_I_BIT +dLockLoop: + msr cpsr_c, r3 + mcr p15, 0, r0, c7, c10, 1 @ Write back line if it is dirty + mcr p15, 0, r0, c7, c6, 1 @ Flush/invalidate line + msr cpsr_c, r2 + ldr ip, [r0], #CACHELINESIZE @ Preload 32 bytes into cache from + @ location [r0]. Post-increment + @ r3 to next cache line + cmp r0, r1 @ Are we done? + bls dLockLoop + + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mov r2, #0 + mcr p15, 0, r2, c9, c2, 0 @ Get out of lock mode + cpwait_ret lr, ip + +/* + * xscale_dcache_unlock + */ +ENTRY(xscale_dcache_unlock) + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mcr p15, 0, ip, c9, c2, 1 @ Unlock cache + mov pc, lr + +/* + * Needed to determine the length of the code that needs to be copied. + */ + .align 5 +ENTRY(xscale_cache_dummy) + mov pc, lr + +/* ================================ TLB LOCKING============================== + * + * The XScale MicroArchitecture implements support for locking entries into + * the Instruction and Data TLBs. The following functions provide the + * low level support for supporting these under Linux. xscale-lock.c + * implements some higher level management code. Most of the following + * is taken straight out of the Developer's Manual. + */ + +/* + * Lock I-TLB entry + * + * r0: Virtual address to translate and lock + */ + .align 5 +ENTRY(xscale_itlb_lock) + mrs r2, cpsr + orr r3, r2, #PSR_F_BIT | PSR_I_BIT + msr cpsr_c, r3 @ Disable interrupts + mcr p15, 0, r0, c8, c5, 1 @ Invalidate I-TLB entry + mcr p15, 0, r0, c10, c4, 0 @ Translate and lock + msr cpsr_c, r2 @ Restore interrupts + cpwait_ret lr, ip + +/* + * Lock D-TLB entry + * + * r0: Virtual address to translate and lock + */ + .align 5 +ENTRY(xscale_dtlb_lock) + mrs r2, cpsr + orr r3, r2, #PSR_F_BIT | PSR_I_BIT + msr cpsr_c, r3 @ Disable interrupts + mcr p15, 0, r0, c8, c6, 1 @ Invalidate D-TLB entry + mcr p15, 0, r0, c10, c8, 0 @ Translate and lock + msr cpsr_c, r2 @ Restore interrupts + cpwait_ret lr, ip + +/* + * Unlock all I-TLB entries + */ + .align 5 +ENTRY(xscale_itlb_unlock) + mcr p15, 0, ip, c10, c4, 1 @ Unlock I-TLB + mcr p15, 0, ip, c8, c5, 0 @ Invalidate I-TLB + cpwait_ret lr, ip + +/* + * Unlock all D-TLB entries + */ +ENTRY(xscale_dtlb_unlock) + mcr p15, 0, ip, c10, c8, 1 @ Unlock D-TBL + mcr p15, 0, ip, c8, c6, 0 @ Invalidate D-TLB + cpwait_ret lr, ip + /* =============================== PageTable ============================== */ #define PTE_CACHE_WRITE_ALLOCATE 0 diff --git a/trunk/arch/arm/nwfpe/double_cpdo.c b/trunk/arch/arm/nwfpe/double_cpdo.c index c51d1386a97c..7ffd8cb9bc96 100644 --- a/trunk/arch/arm/nwfpe/double_cpdo.c +++ b/trunk/arch/arm/nwfpe/double_cpdo.c @@ -40,17 +40,17 @@ float64 float64_arccos(float64 rFm); float64 float64_pow(float64 rFn, float64 rFm); float64 float64_pol(float64 rFn, float64 rFm); -static float64 float64_rsf(struct roundingData *roundData, float64 rFn, float64 rFm) +static float64 float64_rsf(float64 rFn, float64 rFm) { - return float64_sub(roundData, rFm, rFn); + return float64_sub(rFm, rFn); } -static float64 float64_rdv(struct roundingData *roundData, float64 rFn, float64 rFm) +static float64 float64_rdv(float64 rFn, float64 rFm) { - return float64_div(roundData, rFm, rFn); + return float64_div(rFm, rFn); } -static float64 (*const dyadic_double[16])(struct roundingData*, float64 rFn, float64 rFm) = { +static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = { [ADF_CODE >> 20] = float64_add, [MUF_CODE >> 20] = float64_mul, [SUF_CODE >> 20] = float64_sub, @@ -65,12 +65,12 @@ static float64 (*const dyadic_double[16])(struct roundingData*, float64 rFn, flo [FRD_CODE >> 20] = float64_rdv, }; -static float64 float64_mvf(struct roundingData *roundData,float64 rFm) +static float64 float64_mvf(float64 rFm) { return rFm; } -static float64 float64_mnf(struct roundingData *roundData,float64 rFm) +static float64 float64_mnf(float64 rFm) { union float64_components u; @@ -84,7 +84,7 @@ static float64 float64_mnf(struct roundingData *roundData,float64 rFm) return u.f64; } -static float64 float64_abs(struct roundingData *roundData,float64 rFm) +static float64 float64_abs(float64 rFm) { union float64_components u; @@ -98,7 +98,7 @@ static float64 float64_abs(struct roundingData *roundData,float64 rFm) return u.f64; } -static float64 (*const monadic_double[16])(struct roundingData *, float64 rFm) = { +static float64 (*const monadic_double[16])(float64 rFm) = { [MVF_CODE >> 20] = float64_mvf, [MNF_CODE >> 20] = float64_mnf, [ABS_CODE >> 20] = float64_abs, @@ -108,7 +108,7 @@ static float64 (*const monadic_double[16])(struct roundingData *, float64 rFm) = [NRM_CODE >> 20] = float64_mvf, }; -unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd) +unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd) { FPA11 *fpa11 = GET_FPA11(); float64 rFm; @@ -151,13 +151,13 @@ unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcod } if (dyadic_double[opc_mask_shift]) { - rFd->fDouble = dyadic_double[opc_mask_shift](roundData, rFn, rFm); + rFd->fDouble = dyadic_double[opc_mask_shift](rFn, rFm); } else { return 0; } } else { if (monadic_double[opc_mask_shift]) { - rFd->fDouble = monadic_double[opc_mask_shift](roundData, rFm); + rFd->fDouble = monadic_double[opc_mask_shift](rFm); } else { return 0; } diff --git a/trunk/arch/arm/nwfpe/extended_cpdo.c b/trunk/arch/arm/nwfpe/extended_cpdo.c index 65a279ba927f..c39f68a3449e 100644 --- a/trunk/arch/arm/nwfpe/extended_cpdo.c +++ b/trunk/arch/arm/nwfpe/extended_cpdo.c @@ -35,17 +35,17 @@ floatx80 floatx80_arccos(floatx80 rFm); floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm); floatx80 floatx80_pol(floatx80 rFn, floatx80 rFm); -static floatx80 floatx80_rsf(struct roundingData *roundData, floatx80 rFn, floatx80 rFm) +static floatx80 floatx80_rsf(floatx80 rFn, floatx80 rFm) { - return floatx80_sub(roundData, rFm, rFn); + return floatx80_sub(rFm, rFn); } -static floatx80 floatx80_rdv(struct roundingData *roundData, floatx80 rFn, floatx80 rFm) +static floatx80 floatx80_rdv(floatx80 rFn, floatx80 rFm) { - return floatx80_div(roundData, rFm, rFn); + return floatx80_div(rFm, rFn); } -static floatx80 (*const dyadic_extended[16])(struct roundingData*, floatx80 rFn, floatx80 rFm) = { +static floatx80 (*const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) = { [ADF_CODE >> 20] = floatx80_add, [MUF_CODE >> 20] = floatx80_mul, [SUF_CODE >> 20] = floatx80_sub, @@ -60,24 +60,24 @@ static floatx80 (*const dyadic_extended[16])(struct roundingData*, floatx80 rFn, [FRD_CODE >> 20] = floatx80_rdv, }; -static floatx80 floatx80_mvf(struct roundingData *roundData, floatx80 rFm) +static floatx80 floatx80_mvf(floatx80 rFm) { return rFm; } -static floatx80 floatx80_mnf(struct roundingData *roundData, floatx80 rFm) +static floatx80 floatx80_mnf(floatx80 rFm) { rFm.high ^= 0x8000; return rFm; } -static floatx80 floatx80_abs(struct roundingData *roundData, floatx80 rFm) +static floatx80 floatx80_abs(floatx80 rFm) { rFm.high &= 0x7fff; return rFm; } -static floatx80 (*const monadic_extended[16])(struct roundingData*, floatx80 rFm) = { +static floatx80 (*const monadic_extended[16])(floatx80 rFm) = { [MVF_CODE >> 20] = floatx80_mvf, [MNF_CODE >> 20] = floatx80_mnf, [ABS_CODE >> 20] = floatx80_abs, @@ -87,7 +87,7 @@ static floatx80 (*const monadic_extended[16])(struct roundingData*, floatx80 rFm [NRM_CODE >> 20] = floatx80_mvf, }; -unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd) +unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd) { FPA11 *fpa11 = GET_FPA11(); floatx80 rFm; @@ -138,13 +138,13 @@ unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opc } if (dyadic_extended[opc_mask_shift]) { - rFd->fExtended = dyadic_extended[opc_mask_shift](roundData, rFn, rFm); + rFd->fExtended = dyadic_extended[opc_mask_shift](rFn, rFm); } else { return 0; } } else { if (monadic_extended[opc_mask_shift]) { - rFd->fExtended = monadic_extended[opc_mask_shift](roundData, rFm); + rFd->fExtended = monadic_extended[opc_mask_shift](rFm); } else { return 0; } diff --git a/trunk/arch/arm/nwfpe/fpa11.c b/trunk/arch/arm/nwfpe/fpa11.c index 7690f731ee87..bf61696865ec 100644 --- a/trunk/arch/arm/nwfpe/fpa11.c +++ b/trunk/arch/arm/nwfpe/fpa11.c @@ -51,42 +51,48 @@ static void resetFPA11(void) fpa11->fpsr = FP_EMULATOR | BIT_AC; } -int8 SetRoundingMode(const unsigned int opcode) +void SetRoundingMode(const unsigned int opcode) { switch (opcode & MASK_ROUNDING_MODE) { default: case ROUND_TO_NEAREST: - return float_round_nearest_even; + float_rounding_mode = float_round_nearest_even; + break; case ROUND_TO_PLUS_INFINITY: - return float_round_up; + float_rounding_mode = float_round_up; + break; case ROUND_TO_MINUS_INFINITY: - return float_round_down; + float_rounding_mode = float_round_down; + break; case ROUND_TO_ZERO: - return float_round_to_zero; + float_rounding_mode = float_round_to_zero; + break; } } -int8 SetRoundingPrecision(const unsigned int opcode) +void SetRoundingPrecision(const unsigned int opcode) { #ifdef CONFIG_FPE_NWFPE_XP switch (opcode & MASK_ROUNDING_PRECISION) { case ROUND_SINGLE: - return 32; + floatx80_rounding_precision = 32; + break; case ROUND_DOUBLE: - return 64; + floatx80_rounding_precision = 64; + break; case ROUND_EXTENDED: - return 80; + floatx80_rounding_precision = 80; + break; default: - return 80; + floatx80_rounding_precision = 80; } #endif - return 80; } void nwfpe_init_fpa(union fp_state *fp) @@ -97,6 +103,8 @@ void nwfpe_init_fpa(union fp_state *fp) #endif memset(fpa11, 0, sizeof(FPA11)); resetFPA11(); + SetRoundingMode(ROUND_TO_NEAREST); + SetRoundingPrecision(ROUND_EXTENDED); fpa11->initflag = 1; } diff --git a/trunk/arch/arm/nwfpe/fpa11.h b/trunk/arch/arm/nwfpe/fpa11.h index 93523ae4b7a1..e4a61aea534b 100644 --- a/trunk/arch/arm/nwfpe/fpa11.h +++ b/trunk/arch/arm/nwfpe/fpa11.h @@ -37,13 +37,6 @@ /* includes */ #include "fpsr.h" /* FP control and status register definitions */ #include "milieu.h" - -struct roundingData { - int8 mode; - int8 precision; - signed char exception; -}; - #include "softfloat.h" #define typeNone 0x00 @@ -91,8 +84,8 @@ typedef struct tagFPA11 { initialised. */ } FPA11; -extern int8 SetRoundingMode(const unsigned int); -extern int8 SetRoundingPrecision(const unsigned int); +extern void SetRoundingMode(const unsigned int); +extern void SetRoundingPrecision(const unsigned int); extern void nwfpe_init_fpa(union fp_state *fp); #endif diff --git a/trunk/arch/arm/nwfpe/fpa11_cpdo.c b/trunk/arch/arm/nwfpe/fpa11_cpdo.c index 4a31dfd94068..1bea67437b6f 100644 --- a/trunk/arch/arm/nwfpe/fpa11_cpdo.c +++ b/trunk/arch/arm/nwfpe/fpa11_cpdo.c @@ -24,16 +24,15 @@ #include "fpa11.h" #include "fpopcode.h" -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 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 EmulateCPDO(const unsigned int opcode) { FPA11 *fpa11 = GET_FPA11(); FPREG *rFd; unsigned int nType, nDest, nRc; - struct roundingData roundData; /* Get the destination size. If not valid let Linux perform an invalid instruction trap. */ @@ -41,9 +40,7 @@ unsigned int EmulateCPDO(const unsigned int opcode) if (typeNone == nDest) return 0; - roundData.mode = SetRoundingMode(opcode); - roundData.precision = SetRoundingPrecision(opcode); - roundData.exception = 0; + SetRoundingMode(opcode); /* Compare the size of the operands in Fn and Fm. Choose the largest size and perform operations in that size, @@ -66,14 +63,14 @@ unsigned int EmulateCPDO(const unsigned int opcode) switch (nType) { case typeSingle: - nRc = SingleCPDO(&roundData, opcode, rFd); + nRc = SingleCPDO(opcode, rFd); break; case typeDouble: - nRc = DoubleCPDO(&roundData, opcode, rFd); + nRc = DoubleCPDO(opcode, rFd); break; #ifdef CONFIG_FPE_NWFPE_XP case typeExtended: - nRc = ExtendedCPDO(&roundData, opcode, rFd); + nRc = ExtendedCPDO(opcode, rFd); break; #endif default: @@ -96,9 +93,9 @@ unsigned int EmulateCPDO(const unsigned int opcode) case typeSingle: { if (typeDouble == nType) - rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble); + rFd->fSingle = float64_to_float32(rFd->fDouble); else - rFd->fSingle = floatx80_to_float32(&roundData, rFd->fExtended); + rFd->fSingle = floatx80_to_float32(rFd->fExtended); } break; @@ -107,7 +104,7 @@ unsigned int EmulateCPDO(const unsigned int opcode) if (typeSingle == nType) rFd->fDouble = float32_to_float64(rFd->fSingle); else - rFd->fDouble = floatx80_to_float64(&roundData, rFd->fExtended); + rFd->fDouble = floatx80_to_float64(rFd->fExtended); } break; @@ -124,15 +121,12 @@ unsigned int EmulateCPDO(const unsigned int opcode) #else if (nDest != nType) { if (nDest == typeSingle) - rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble); + rFd->fSingle = float64_to_float32(rFd->fDouble); else rFd->fDouble = float32_to_float64(rFd->fSingle); } #endif } - if (roundData.exception) - float_raise(roundData.exception); - return nRc; } diff --git a/trunk/arch/arm/nwfpe/fpa11_cpdt.c b/trunk/arch/arm/nwfpe/fpa11_cpdt.c index b0db5cbcc3b1..95fb63fa9d18 100644 --- a/trunk/arch/arm/nwfpe/fpa11_cpdt.c +++ b/trunk/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(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem) +static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem) { FPA11 *fpa11 = GET_FPA11(); union { @@ -106,12 +106,12 @@ static inline void storeSingle(struct roundingData *roundData, const unsigned in switch (fpa11->fType[Fn]) { case typeDouble: - val.f = float64_to_float32(roundData, fpa11->fpreg[Fn].fDouble); + val.f = float64_to_float32(fpa11->fpreg[Fn].fDouble); break; #ifdef CONFIG_FPE_NWFPE_XP case typeExtended: - val.f = floatx80_to_float32(roundData, fpa11->fpreg[Fn].fExtended); + val.f = floatx80_to_float32(fpa11->fpreg[Fn].fExtended); break; #endif @@ -122,7 +122,7 @@ static inline void storeSingle(struct roundingData *roundData, const unsigned in put_user(val.i[0], pMem); } -static inline void storeDouble(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem) +static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem) { FPA11 *fpa11 = GET_FPA11(); union { @@ -137,7 +137,7 @@ static inline void storeDouble(struct roundingData *roundData, const unsigned in #ifdef CONFIG_FPE_NWFPE_XP case typeExtended: - val.f = floatx80_to_float64(roundData, fpa11->fpreg[Fn].fExtended); + val.f = floatx80_to_float64(fpa11->fpreg[Fn].fExtended); break; #endif @@ -259,11 +259,8 @@ unsigned int PerformSTF(const unsigned int opcode) { unsigned int __user *pBase, *pAddress, *pFinal; unsigned int nRc = 1, write_back = WRITE_BACK(opcode); - struct roundingData roundData; - roundData.mode = SetRoundingMode(opcode); - roundData.precision = SetRoundingPrecision(opcode); - roundData.exception = 0; + SetRoundingMode(ROUND_TO_NEAREST); pBase = (unsigned int __user *) readRegister(getRn(opcode)); if (REG_PC == getRn(opcode)) { @@ -284,10 +281,10 @@ unsigned int PerformSTF(const unsigned int opcode) switch (opcode & MASK_TRANSFER_LENGTH) { case TRANSFER_SINGLE: - storeSingle(&roundData, getFd(opcode), pAddress); + storeSingle(getFd(opcode), pAddress); break; case TRANSFER_DOUBLE: - storeDouble(&roundData, getFd(opcode), pAddress); + storeDouble(getFd(opcode), pAddress); break; #ifdef CONFIG_FPE_NWFPE_XP case TRANSFER_EXTENDED: @@ -298,9 +295,6 @@ unsigned int PerformSTF(const unsigned int opcode) nRc = 0; } - if (roundData.exception) - float_raise(roundData.exception); - if (write_back) writeRegister(getRn(opcode), (unsigned long) pFinal); return nRc; diff --git a/trunk/arch/arm/nwfpe/fpa11_cprt.c b/trunk/arch/arm/nwfpe/fpa11_cprt.c index adf8d3000540..db01fbc97216 100644 --- a/trunk/arch/arm/nwfpe/fpa11_cprt.c +++ b/trunk/arch/arm/nwfpe/fpa11_cprt.c @@ -33,6 +33,8 @@ extern flag floatx80_is_nan(floatx80); extern flag float64_is_nan(float64); extern flag float32_is_nan(float32); +void SetRoundingMode(const unsigned int opcode); + unsigned int PerformFLT(const unsigned int opcode); unsigned int PerformFIX(const unsigned int opcode); @@ -75,17 +77,14 @@ unsigned int EmulateCPRT(const unsigned int opcode) unsigned int PerformFLT(const unsigned int opcode) { FPA11 *fpa11 = GET_FPA11(); - struct roundingData roundData; - - roundData.mode = SetRoundingMode(opcode); - roundData.precision = SetRoundingPrecision(opcode); - roundData.exception = 0; + SetRoundingMode(opcode); + SetRoundingPrecision(opcode); switch (opcode & MASK_ROUNDING_PRECISION) { case ROUND_SINGLE: { fpa11->fType[getFn(opcode)] = typeSingle; - fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(&roundData, readRegister(getRd(opcode))); + fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(readRegister(getRd(opcode))); } break; @@ -109,9 +108,6 @@ unsigned int PerformFLT(const unsigned int opcode) return 0; } - if (roundData.exception) - float_raise(roundData.exception); - return 1; } @@ -119,29 +115,26 @@ unsigned int PerformFIX(const unsigned int opcode) { FPA11 *fpa11 = GET_FPA11(); unsigned int Fn = getFm(opcode); - struct roundingData roundData; - roundData.mode = SetRoundingMode(opcode); - roundData.precision = SetRoundingPrecision(opcode); - roundData.exception = 0; + SetRoundingMode(opcode); switch (fpa11->fType[Fn]) { case typeSingle: { - writeRegister(getRd(opcode), float32_to_int32(&roundData, fpa11->fpreg[Fn].fSingle)); + writeRegister(getRd(opcode), float32_to_int32(fpa11->fpreg[Fn].fSingle)); } break; case typeDouble: { - writeRegister(getRd(opcode), float64_to_int32(&roundData, fpa11->fpreg[Fn].fDouble)); + writeRegister(getRd(opcode), float64_to_int32(fpa11->fpreg[Fn].fDouble)); } break; #ifdef CONFIG_FPE_NWFPE_XP case typeExtended: { - writeRegister(getRd(opcode), floatx80_to_int32(&roundData, fpa11->fpreg[Fn].fExtended)); + writeRegister(getRd(opcode), floatx80_to_int32(fpa11->fpreg[Fn].fExtended)); } break; #endif @@ -150,9 +143,6 @@ unsigned int PerformFIX(const unsigned int opcode) return 0; } - if (roundData.exception) - float_raise(roundData.exception); - return 1; } diff --git a/trunk/arch/arm/nwfpe/fpmodule.c b/trunk/arch/arm/nwfpe/fpmodule.c index 2dfe1ac42ee8..12885f31d347 100644 --- a/trunk/arch/arm/nwfpe/fpmodule.c +++ b/trunk/arch/arm/nwfpe/fpmodule.c @@ -116,6 +116,8 @@ fpmodule.c to integrate with the NetBSD kernel (I hope!). code to access data in user space in some other source files at the moment (grep for get_user / put_user calls). --philb] +float_exception_flags is a global variable in SoftFloat. + This function is called by the SoftFloat routines to raise a floating point exception. We check the trap enable byte in the FPSR, and raise a SIGFPE exception if necessary. If not the relevant bits in the @@ -127,14 +129,15 @@ void float_raise(signed char flags) register unsigned int fpsr, cumulativeTraps; #ifdef CONFIG_DEBUG_USER - /* 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); + printk(KERN_DEBUG + "NWFPE: %s[%d] takes exception %08x at %p from %08lx\n", + current->comm, current->pid, flags, + __builtin_return_address(0), GET_USERREG()->ARM_pc); #endif + /* Keep SoftFloat exception flags up to date. */ + float_exception_flags |= flags; + /* Read fpsr and initialize the cumulativeTraps. */ fpsr = readFPSR(); cumulativeTraps = 0; diff --git a/trunk/arch/arm/nwfpe/single_cpdo.c b/trunk/arch/arm/nwfpe/single_cpdo.c index c66981d682cf..705808e88d9d 100644 --- a/trunk/arch/arm/nwfpe/single_cpdo.c +++ b/trunk/arch/arm/nwfpe/single_cpdo.c @@ -36,17 +36,17 @@ float32 float32_arccos(float32 rFm); float32 float32_pow(float32 rFn, float32 rFm); float32 float32_pol(float32 rFn, float32 rFm); -static float32 float32_rsf(struct roundingData *roundData, float32 rFn, float32 rFm) +static float32 float32_rsf(float32 rFn, float32 rFm) { - return float32_sub(roundData, rFm, rFn); + return float32_sub(rFm, rFn); } -static float32 float32_rdv(struct roundingData *roundData, float32 rFn, float32 rFm) +static float32 float32_rdv(float32 rFn, float32 rFm) { - return float32_div(roundData, rFm, rFn); + return float32_div(rFm, rFn); } -static float32 (*const dyadic_single[16])(struct roundingData *, float32 rFn, float32 rFm) = { +static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = { [ADF_CODE >> 20] = float32_add, [MUF_CODE >> 20] = float32_mul, [SUF_CODE >> 20] = float32_sub, @@ -60,22 +60,22 @@ static float32 (*const dyadic_single[16])(struct roundingData *, float32 rFn, fl [FRD_CODE >> 20] = float32_rdv, }; -static float32 float32_mvf(struct roundingData *roundData, float32 rFm) +static float32 float32_mvf(float32 rFm) { return rFm; } -static float32 float32_mnf(struct roundingData *roundData, float32 rFm) +static float32 float32_mnf(float32 rFm) { return rFm ^ 0x80000000; } -static float32 float32_abs(struct roundingData *roundData, float32 rFm) +static float32 float32_abs(float32 rFm) { return rFm & 0x7fffffff; } -static float32 (*const monadic_single[16])(struct roundingData*, float32 rFm) = { +static float32 (*const monadic_single[16])(float32 rFm) = { [MVF_CODE >> 20] = float32_mvf, [MNF_CODE >> 20] = float32_mnf, [ABS_CODE >> 20] = float32_abs, @@ -85,7 +85,7 @@ static float32 (*const monadic_single[16])(struct roundingData*, float32 rFm) = [NRM_CODE >> 20] = float32_mvf, }; -unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd) +unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd) { FPA11 *fpa11 = GET_FPA11(); float32 rFm; @@ -108,13 +108,13 @@ unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcod if (fpa11->fType[Fn] == typeSingle && dyadic_single[opc_mask_shift]) { rFn = fpa11->fpreg[Fn].fSingle; - rFd->fSingle = dyadic_single[opc_mask_shift](roundData, rFn, rFm); + rFd->fSingle = dyadic_single[opc_mask_shift](rFn, rFm); } else { return 0; } } else { if (monadic_single[opc_mask_shift]) { - rFd->fSingle = monadic_single[opc_mask_shift](roundData, rFm); + rFd->fSingle = monadic_single[opc_mask_shift](rFm); } else { return 0; } diff --git a/trunk/arch/arm/nwfpe/softfloat.c b/trunk/arch/arm/nwfpe/softfloat.c index 8b75a6e7cb3a..e038dd3be9b3 100644 --- a/trunk/arch/arm/nwfpe/softfloat.c +++ b/trunk/arch/arm/nwfpe/softfloat.c @@ -34,6 +34,16 @@ this code that are retained. //#include "milieu.h" //#include "softfloat.h" +/* +------------------------------------------------------------------------------- +Floating-point rounding mode, extended double-precision rounding precision, +and exception flags. +------------------------------------------------------------------------------- +*/ +int8 float_rounding_mode = float_round_nearest_even; +int8 floatx80_rounding_precision = 80; +int8 float_exception_flags; + /* ------------------------------------------------------------------------------- Primitive arithmetic functions, including multi-word arithmetic, and @@ -67,14 +77,14 @@ input is too large, however, the invalid exception is raised and the largest positive or negative integer is returned. ------------------------------------------------------------------------------- */ -static int32 roundAndPackInt32( struct roundingData *roundData, flag zSign, bits64 absZ ) +static int32 roundAndPackInt32( flag zSign, bits64 absZ ) { int8 roundingMode; flag roundNearestEven; int8 roundIncrement, roundBits; int32 z; - roundingMode = roundData->mode; + roundingMode = float_rounding_mode; roundNearestEven = ( roundingMode == float_round_nearest_even ); roundIncrement = 0x40; if ( ! roundNearestEven ) { @@ -97,10 +107,10 @@ static int32 roundAndPackInt32( struct roundingData *roundData, flag zSign, bits z = absZ; if ( zSign ) z = - z; if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { - roundData->exception |= float_flag_invalid; + float_exception_flags |= float_flag_invalid; return zSign ? 0x80000000 : 0x7FFFFFFF; } - if ( roundBits ) roundData->exception |= float_flag_inexact; + if ( roundBits ) float_exception_flags |= float_flag_inexact; return z; } @@ -214,14 +224,14 @@ The handling of underflow and overflow follows the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static float32 roundAndPackFloat32( struct roundingData *roundData, flag zSign, int16 zExp, bits32 zSig ) +static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) { int8 roundingMode; flag roundNearestEven; int8 roundIncrement, roundBits; flag isTiny; - roundingMode = roundData->mode; + roundingMode = float_rounding_mode; roundNearestEven = ( roundingMode == float_round_nearest_even ); roundIncrement = 0x40; if ( ! roundNearestEven ) { @@ -244,7 +254,7 @@ static float32 roundAndPackFloat32( struct roundingData *roundData, flag zSign, || ( ( zExp == 0xFD ) && ( (sbits32) ( zSig + roundIncrement ) < 0 ) ) ) { - roundData->exception |= float_flag_overflow | float_flag_inexact; + float_raise( float_flag_overflow | float_flag_inexact ); return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 ); } if ( zExp < 0 ) { @@ -255,10 +265,10 @@ static float32 roundAndPackFloat32( struct roundingData *roundData, flag zSign, shift32RightJamming( zSig, - zExp, &zSig ); zExp = 0; roundBits = zSig & 0x7F; - if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow; + if ( isTiny && roundBits ) float_raise( float_flag_underflow ); } } - if ( roundBits ) roundData->exception |= float_flag_inexact; + if ( roundBits ) float_exception_flags |= float_flag_inexact; zSig = ( zSig + roundIncrement )>>7; zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); if ( zSig == 0 ) zExp = 0; @@ -277,12 +287,12 @@ point exponent. ------------------------------------------------------------------------------- */ static float32 - normalizeRoundAndPackFloat32( struct roundingData *roundData, flag zSign, int16 zExp, bits32 zSig ) + normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) { int8 shiftCount; shiftCount = countLeadingZeros32( zSig ) - 1; - return roundAndPackFloat32( roundData, zSign, zExp - shiftCount, zSig<mode; + roundingMode = float_rounding_mode; roundNearestEven = ( roundingMode == float_round_nearest_even ); roundIncrement = 0x200; if ( ! roundNearestEven ) { @@ -417,7 +427,7 @@ static float64 roundAndPackFloat64( struct roundingData *roundData, flag zSign, ) { //register int lr = __builtin_return_address(0); //printk("roundAndPackFloat64 called from 0x%08x\n",lr); - roundData->exception |= float_flag_overflow | float_flag_inexact; + float_raise( float_flag_overflow | float_flag_inexact ); return packFloat64( zSign, 0x7FF, 0 ) - ( roundIncrement == 0 ); } if ( zExp < 0 ) { @@ -428,10 +438,10 @@ static float64 roundAndPackFloat64( struct roundingData *roundData, flag zSign, shift64RightJamming( zSig, - zExp, &zSig ); zExp = 0; roundBits = zSig & 0x3FF; - if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow; + if ( isTiny && roundBits ) float_raise( float_flag_underflow ); } } - if ( roundBits ) roundData->exception |= float_flag_inexact; + if ( roundBits ) float_exception_flags |= float_flag_inexact; zSig = ( zSig + roundIncrement )>>10; zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven ); if ( zSig == 0 ) zExp = 0; @@ -450,12 +460,12 @@ point exponent. ------------------------------------------------------------------------------- */ static float64 - normalizeRoundAndPackFloat64( struct roundingData *roundData, flag zSign, int16 zExp, bits64 zSig ) + normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) { int8 shiftCount; shiftCount = countLeadingZeros64( zSig ) - 1; - return roundAndPackFloat64( roundData, zSign, zExp - shiftCount, zSig<mode; - roundingPrecision = roundData->precision; + roundingMode = float_rounding_mode; roundNearestEven = ( roundingMode == float_round_nearest_even ); if ( roundingPrecision == 80 ) goto precision80; if ( roundingPrecision == 64 ) { @@ -614,8 +623,8 @@ static floatx80 shift64RightJamming( zSig0, 1 - zExp, &zSig0 ); zExp = 0; roundBits = zSig0 & roundMask; - if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow; - if ( roundBits ) roundData->exception |= float_flag_inexact; + if ( isTiny && roundBits ) float_raise( float_flag_underflow ); + if ( roundBits ) float_exception_flags |= float_flag_inexact; zSig0 += roundIncrement; if ( (sbits64) zSig0 < 0 ) zExp = 1; roundIncrement = roundMask + 1; @@ -626,7 +635,7 @@ static floatx80 return packFloatx80( zSign, zExp, zSig0 ); } } - if ( roundBits ) roundData->exception |= float_flag_inexact; + if ( roundBits ) float_exception_flags |= float_flag_inexact; zSig0 += roundIncrement; if ( zSig0 < roundIncrement ) { ++zExp; @@ -663,7 +672,7 @@ static floatx80 ) { roundMask = 0; overflow: - roundData->exception |= float_flag_overflow | float_flag_inexact; + float_raise( float_flag_overflow | float_flag_inexact ); if ( ( roundingMode == float_round_to_zero ) || ( zSign && ( roundingMode == float_round_up ) ) || ( ! zSign && ( roundingMode == float_round_down ) ) @@ -680,8 +689,8 @@ static floatx80 || ( zSig0 < LIT64( 0xFFFFFFFFFFFFFFFF ) ); shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 ); zExp = 0; - if ( isTiny && zSig1 ) roundData->exception |= float_flag_underflow; - if ( zSig1 ) roundData->exception |= float_flag_inexact; + if ( isTiny && zSig1 ) float_raise( float_flag_underflow ); + if ( zSig1 ) float_exception_flags |= float_flag_inexact; if ( roundNearestEven ) { increment = ( (sbits64) zSig1 < 0 ); } @@ -701,7 +710,7 @@ static floatx80 return packFloatx80( zSign, zExp, zSig0 ); } } - if ( zSig1 ) roundData->exception |= float_flag_inexact; + if ( zSig1 ) float_exception_flags |= float_flag_inexact; if ( increment ) { ++zSig0; if ( zSig0 == 0 ) { @@ -731,7 +740,7 @@ normalized. */ static floatx80 normalizeRoundAndPackFloatx80( - struct roundingData *roundData, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 + int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ) { int8 shiftCount; @@ -745,7 +754,7 @@ static floatx80 shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 ); zExp -= shiftCount; return - roundAndPackFloatx80( roundData, zSign, zExp, zSig0, zSig1 ); + roundAndPackFloatx80( roundingPrecision, zSign, zExp, zSig0, zSig1 ); } @@ -758,14 +767,14 @@ the single-precision floating-point format. The conversion is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 int32_to_float32(struct roundingData *roundData, int32 a) +float32 int32_to_float32( int32 a ) { flag zSign; if ( a == 0 ) return 0; if ( a == 0x80000000 ) return packFloat32( 1, 0x9E, 0 ); zSign = ( a < 0 ); - return normalizeRoundAndPackFloat32( roundData, zSign, 0x9C, zSign ? - a : a ); + return normalizeRoundAndPackFloat32( zSign, 0x9C, zSign ? - a : a ); } @@ -831,7 +840,7 @@ positive integer is returned. Otherwise, if the conversion overflows, the largest integer with the same sign as `a' is returned. ------------------------------------------------------------------------------- */ -int32 float32_to_int32( struct roundingData *roundData, float32 a ) +int32 float32_to_int32( float32 a ) { flag aSign; int16 aExp, shiftCount; @@ -847,7 +856,7 @@ int32 float32_to_int32( struct roundingData *roundData, float32 a ) zSig = aSig; zSig <<= 32; if ( 0 < shiftCount ) shift64RightJamming( zSig, shiftCount, &zSig ); - return roundAndPackInt32( roundData, aSign, zSig ); + return roundAndPackInt32( aSign, zSig ); } @@ -880,13 +889,13 @@ int32 float32_to_int32_round_to_zero( float32 a ) return 0x80000000; } else if ( aExp <= 0x7E ) { - if ( aExp | aSig ) float_raise( float_flag_inexact ); + if ( aExp | aSig ) float_exception_flags |= float_flag_inexact; return 0; } aSig = ( aSig | 0x00800000 )<<8; z = aSig>>( - shiftCount ); if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) { - float_raise( float_flag_inexact ); + float_exception_flags |= float_flag_inexact; } return aSign ? - z : z; @@ -964,7 +973,7 @@ operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_round_to_int( struct roundingData *roundData, float32 a ) +float32 float32_round_to_int( float32 a ) { flag aSign; int16 aExp; @@ -979,12 +988,11 @@ float32 float32_round_to_int( struct roundingData *roundData, float32 a ) } return a; } - roundingMode = roundData->mode; if ( aExp <= 0x7E ) { if ( (bits32) ( a<<1 ) == 0 ) return a; - roundData->exception |= float_flag_inexact; + float_exception_flags |= float_flag_inexact; aSign = extractFloat32Sign( a ); - switch ( roundingMode ) { + switch ( float_rounding_mode ) { case float_round_nearest_even: if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) { return packFloat32( aSign, 0x7F, 0 ); @@ -1001,6 +1009,7 @@ float32 float32_round_to_int( struct roundingData *roundData, float32 a ) lastBitMask <<= 0x96 - aExp; roundBitsMask = lastBitMask - 1; z = a; + roundingMode = float_rounding_mode; if ( roundingMode == float_round_nearest_even ) { z += lastBitMask>>1; if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; @@ -1011,7 +1020,7 @@ float32 float32_round_to_int( struct roundingData *roundData, float32 a ) } } z &= ~ roundBitsMask; - if ( z != a ) roundData->exception |= float_flag_inexact; + if ( z != a ) float_exception_flags |= float_flag_inexact; return z; } @@ -1025,7 +1034,7 @@ addition is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static float32 addFloat32Sigs( struct roundingData *roundData, float32 a, float32 b, flag zSign ) +static float32 addFloat32Sigs( float32 a, float32 b, flag zSign ) { int16 aExp, bExp, zExp; bits32 aSig, bSig, zSig; @@ -1084,7 +1093,7 @@ static float32 addFloat32Sigs( struct roundingData *roundData, float32 a, float3 ++zExp; } roundAndPack: - return roundAndPackFloat32( roundData, zSign, zExp, zSig ); + return roundAndPackFloat32( zSign, zExp, zSig ); } @@ -1097,7 +1106,7 @@ result is a NaN. The subtraction is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static float32 subFloat32Sigs( struct roundingData *roundData, float32 a, float32 b, flag zSign ) +static float32 subFloat32Sigs( float32 a, float32 b, flag zSign ) { int16 aExp, bExp, zExp; bits32 aSig, bSig, zSig; @@ -1114,7 +1123,7 @@ static float32 subFloat32Sigs( struct roundingData *roundData, float32 a, float3 if ( expDiff < 0 ) goto bExpBigger; if ( aExp == 0xFF ) { if ( aSig | bSig ) return propagateFloat32NaN( a, b ); - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return float32_default_nan; } if ( aExp == 0 ) { @@ -1123,7 +1132,7 @@ static float32 subFloat32Sigs( struct roundingData *roundData, float32 a, float3 } if ( bSig < aSig ) goto aBigger; if ( aSig < bSig ) goto bBigger; - return packFloat32( roundData->mode == float_round_down, 0, 0 ); + return packFloat32( float_rounding_mode == float_round_down, 0, 0 ); bExpBigger: if ( bExp == 0xFF ) { if ( bSig ) return propagateFloat32NaN( a, b ); @@ -1160,7 +1169,7 @@ static float32 subFloat32Sigs( struct roundingData *roundData, float32 a, float3 zExp = aExp; normalizeRoundAndPack: --zExp; - return normalizeRoundAndPackFloat32( roundData, zSign, zExp, zSig ); + return normalizeRoundAndPackFloat32( zSign, zExp, zSig ); } @@ -1171,17 +1180,17 @@ and `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_add( struct roundingData *roundData, float32 a, float32 b ) +float32 float32_add( float32 a, float32 b ) { flag aSign, bSign; aSign = extractFloat32Sign( a ); bSign = extractFloat32Sign( b ); if ( aSign == bSign ) { - return addFloat32Sigs( roundData, a, b, aSign ); + return addFloat32Sigs( a, b, aSign ); } else { - return subFloat32Sigs( roundData, a, b, aSign ); + return subFloat32Sigs( a, b, aSign ); } } @@ -1193,17 +1202,17 @@ Returns the result of subtracting the single-precision floating-point values for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_sub( struct roundingData *roundData, float32 a, float32 b ) +float32 float32_sub( float32 a, float32 b ) { flag aSign, bSign; aSign = extractFloat32Sign( a ); bSign = extractFloat32Sign( b ); if ( aSign == bSign ) { - return subFloat32Sigs( roundData, a, b, aSign ); + return subFloat32Sigs( a, b, aSign ); } else { - return addFloat32Sigs( roundData, a, b, aSign ); + return addFloat32Sigs( a, b, aSign ); } } @@ -1215,7 +1224,7 @@ Returns the result of multiplying the single-precision floating-point values for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_mul( struct roundingData *roundData, float32 a, float32 b ) +float32 float32_mul( float32 a, float32 b ) { flag aSign, bSign, zSign; int16 aExp, bExp, zExp; @@ -1235,7 +1244,7 @@ float32 float32_mul( struct roundingData *roundData, float32 a, float32 b ) return propagateFloat32NaN( a, b ); } if ( ( bExp | bSig ) == 0 ) { - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return float32_default_nan; } return packFloat32( zSign, 0xFF, 0 ); @@ -1243,7 +1252,7 @@ float32 float32_mul( struct roundingData *roundData, float32 a, float32 b ) if ( bExp == 0xFF ) { if ( bSig ) return propagateFloat32NaN( a, b ); if ( ( aExp | aSig ) == 0 ) { - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return float32_default_nan; } return packFloat32( zSign, 0xFF, 0 ); @@ -1265,7 +1274,7 @@ float32 float32_mul( struct roundingData *roundData, float32 a, float32 b ) zSig <<= 1; --zExp; } - return roundAndPackFloat32( roundData, zSign, zExp, zSig ); + return roundAndPackFloat32( zSign, zExp, zSig ); } @@ -1276,7 +1285,7 @@ by the corresponding value `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_div( struct roundingData *roundData, float32 a, float32 b ) +float32 float32_div( float32 a, float32 b ) { flag aSign, bSign, zSign; int16 aExp, bExp, zExp; @@ -1293,7 +1302,7 @@ float32 float32_div( struct roundingData *roundData, float32 a, float32 b ) if ( aSig ) return propagateFloat32NaN( a, b ); if ( bExp == 0xFF ) { if ( bSig ) return propagateFloat32NaN( a, b ); - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return float32_default_nan; } return packFloat32( zSign, 0xFF, 0 ); @@ -1305,10 +1314,10 @@ float32 float32_div( struct roundingData *roundData, float32 a, float32 b ) if ( bExp == 0 ) { if ( bSig == 0 ) { if ( ( aExp | aSig ) == 0 ) { - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return float32_default_nan; } - roundData->exception |= float_flag_divbyzero; + float_raise( float_flag_divbyzero ); return packFloat32( zSign, 0xFF, 0 ); } normalizeFloat32Subnormal( bSig, &bExp, &bSig ); @@ -1332,7 +1341,7 @@ float32 float32_div( struct roundingData *roundData, float32 a, float32 b ) if ( ( zSig & 0x3F ) == 0 ) { zSig |= ( ( (bits64) bSig ) * zSig != ( (bits64) aSig )<<32 ); } - return roundAndPackFloat32( roundData, zSign, zExp, zSig ); + return roundAndPackFloat32( zSign, zExp, zSig ); } @@ -1343,7 +1352,7 @@ with respect to the corresponding value `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_rem( struct roundingData *roundData, float32 a, float32 b ) +float32 float32_rem( float32 a, float32 b ) { flag aSign, bSign, zSign; int16 aExp, bExp, expDiff; @@ -1363,7 +1372,7 @@ float32 float32_rem( struct roundingData *roundData, float32 a, float32 b ) if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { return propagateFloat32NaN( a, b ); } - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return float32_default_nan; } if ( bExp == 0xFF ) { @@ -1372,7 +1381,7 @@ float32 float32_rem( struct roundingData *roundData, float32 a, float32 b ) } if ( bExp == 0 ) { if ( bSig == 0 ) { - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return float32_default_nan; } normalizeFloat32Subnormal( bSig, &bExp, &bSig ); @@ -1435,7 +1444,7 @@ float32 float32_rem( struct roundingData *roundData, float32 a, float32 b ) } zSign = ( (sbits32) aSig < 0 ); if ( zSign ) aSig = - aSig; - return normalizeRoundAndPackFloat32( roundData, aSign ^ zSign, bExp, aSig ); + return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig ); } @@ -1446,7 +1455,7 @@ The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_sqrt( struct roundingData *roundData, float32 a ) +float32 float32_sqrt( float32 a ) { flag aSign; int16 aExp, zExp; @@ -1459,12 +1468,12 @@ float32 float32_sqrt( struct roundingData *roundData, float32 a ) if ( aExp == 0xFF ) { if ( aSig ) return propagateFloat32NaN( a, 0 ); if ( ! aSign ) return a; - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return float32_default_nan; } if ( aSign ) { if ( ( aExp | aSig ) == 0 ) return a; - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return float32_default_nan; } if ( aExp == 0 ) { @@ -1490,7 +1499,7 @@ float32 float32_sqrt( struct roundingData *roundData, float32 a ) } } shift32RightJamming( zSig, 1, &zSig ); - return roundAndPackFloat32( roundData, 0, zExp, zSig ); + return roundAndPackFloat32( 0, zExp, zSig ); } @@ -1652,7 +1661,7 @@ positive integer is returned. Otherwise, if the conversion overflows, the largest integer with the same sign as `a' is returned. ------------------------------------------------------------------------------- */ -int32 float64_to_int32( struct roundingData *roundData, float64 a ) +int32 float64_to_int32( float64 a ) { flag aSign; int16 aExp, shiftCount; @@ -1665,7 +1674,7 @@ int32 float64_to_int32( struct roundingData *roundData, float64 a ) if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); shiftCount = 0x42C - aExp; if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); - return roundAndPackInt32( roundData, aSign, aSig ); + return roundAndPackInt32( aSign, aSig ); } @@ -1696,7 +1705,7 @@ int32 float64_to_int32_round_to_zero( float64 a ) goto invalid; } else if ( 52 < shiftCount ) { - if ( aExp || aSig ) float_raise( float_flag_inexact ); + if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; return 0; } aSig |= LIT64( 0x0010000000000000 ); @@ -1706,11 +1715,11 @@ int32 float64_to_int32_round_to_zero( float64 a ) if ( aSign ) z = - z; if ( ( z < 0 ) ^ aSign ) { invalid: - float_raise( float_flag_invalid ); + float_exception_flags |= float_flag_invalid; return aSign ? 0x80000000 : 0x7FFFFFFF; } if ( ( aSig<exception |= float_flag_inexact; + float_exception_flags |= float_flag_inexact; aSign = extractFloat64Sign( a ); - switch ( roundData->mode ) { + switch ( float_rounding_mode ) { case float_round_nearest_even: if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) { return packFloat64( aSign, 0x3FF, 0 ); @@ -1900,7 +1909,7 @@ float64 float64_round_to_int( struct roundingData *roundData, float64 a ) lastBitMask <<= 0x433 - aExp; roundBitsMask = lastBitMask - 1; z = a; - roundingMode = roundData->mode; + roundingMode = float_rounding_mode; if ( roundingMode == float_round_nearest_even ) { z += lastBitMask>>1; if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; @@ -1911,7 +1920,7 @@ float64 float64_round_to_int( struct roundingData *roundData, float64 a ) } } z &= ~ roundBitsMask; - if ( z != a ) roundData->exception |= float_flag_inexact; + if ( z != a ) float_exception_flags |= float_flag_inexact; return z; } @@ -1925,7 +1934,7 @@ addition is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static float64 addFloat64Sigs( struct roundingData *roundData, float64 a, float64 b, flag zSign ) +static float64 addFloat64Sigs( float64 a, float64 b, flag zSign ) { int16 aExp, bExp, zExp; bits64 aSig, bSig, zSig; @@ -1984,7 +1993,7 @@ static float64 addFloat64Sigs( struct roundingData *roundData, float64 a, float6 ++zExp; } roundAndPack: - return roundAndPackFloat64( roundData, zSign, zExp, zSig ); + return roundAndPackFloat64( zSign, zExp, zSig ); } @@ -1997,7 +2006,7 @@ result is a NaN. The subtraction is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static float64 subFloat64Sigs( struct roundingData *roundData, float64 a, float64 b, flag zSign ) +static float64 subFloat64Sigs( float64 a, float64 b, flag zSign ) { int16 aExp, bExp, zExp; bits64 aSig, bSig, zSig; @@ -2014,7 +2023,7 @@ static float64 subFloat64Sigs( struct roundingData *roundData, float64 a, float6 if ( expDiff < 0 ) goto bExpBigger; if ( aExp == 0x7FF ) { if ( aSig | bSig ) return propagateFloat64NaN( a, b ); - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return float64_default_nan; } if ( aExp == 0 ) { @@ -2023,7 +2032,7 @@ static float64 subFloat64Sigs( struct roundingData *roundData, float64 a, float6 } if ( bSig < aSig ) goto aBigger; if ( aSig < bSig ) goto bBigger; - return packFloat64( roundData->mode == float_round_down, 0, 0 ); + return packFloat64( float_rounding_mode == float_round_down, 0, 0 ); bExpBigger: if ( bExp == 0x7FF ) { if ( bSig ) return propagateFloat64NaN( a, b ); @@ -2060,7 +2069,7 @@ static float64 subFloat64Sigs( struct roundingData *roundData, float64 a, float6 zExp = aExp; normalizeRoundAndPack: --zExp; - return normalizeRoundAndPackFloat64( roundData, zSign, zExp, zSig ); + return normalizeRoundAndPackFloat64( zSign, zExp, zSig ); } @@ -2071,17 +2080,17 @@ and `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float64 float64_add( struct roundingData *roundData, float64 a, float64 b ) +float64 float64_add( float64 a, float64 b ) { flag aSign, bSign; aSign = extractFloat64Sign( a ); bSign = extractFloat64Sign( b ); if ( aSign == bSign ) { - return addFloat64Sigs( roundData, a, b, aSign ); + return addFloat64Sigs( a, b, aSign ); } else { - return subFloat64Sigs( roundData, a, b, aSign ); + return subFloat64Sigs( a, b, aSign ); } } @@ -2093,17 +2102,17 @@ Returns the result of subtracting the double-precision floating-point values for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float64 float64_sub( struct roundingData *roundData, float64 a, float64 b ) +float64 float64_sub( float64 a, float64 b ) { flag aSign, bSign; aSign = extractFloat64Sign( a ); bSign = extractFloat64Sign( b ); if ( aSign == bSign ) { - return subFloat64Sigs( roundData, a, b, aSign ); + return subFloat64Sigs( a, b, aSign ); } else { - return addFloat64Sigs( roundData, a, b, aSign ); + return addFloat64Sigs( a, b, aSign ); } } @@ -2115,7 +2124,7 @@ Returns the result of multiplying the double-precision floating-point values for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float64 float64_mul( struct roundingData *roundData, float64 a, float64 b ) +float64 float64_mul( float64 a, float64 b ) { flag aSign, bSign, zSign; int16 aExp, bExp, zExp; @@ -2133,7 +2142,7 @@ float64 float64_mul( struct roundingData *roundData, float64 a, float64 b ) return propagateFloat64NaN( a, b ); } if ( ( bExp | bSig ) == 0 ) { - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return float64_default_nan; } return packFloat64( zSign, 0x7FF, 0 ); @@ -2141,7 +2150,7 @@ float64 float64_mul( struct roundingData *roundData, float64 a, float64 b ) if ( bExp == 0x7FF ) { if ( bSig ) return propagateFloat64NaN( a, b ); if ( ( aExp | aSig ) == 0 ) { - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return float64_default_nan; } return packFloat64( zSign, 0x7FF, 0 ); @@ -2163,7 +2172,7 @@ float64 float64_mul( struct roundingData *roundData, float64 a, float64 b ) zSig0 <<= 1; --zExp; } - return roundAndPackFloat64( roundData, zSign, zExp, zSig0 ); + return roundAndPackFloat64( zSign, zExp, zSig0 ); } @@ -2174,7 +2183,7 @@ by the corresponding value `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float64 float64_div( struct roundingData *roundData, float64 a, float64 b ) +float64 float64_div( float64 a, float64 b ) { flag aSign, bSign, zSign; int16 aExp, bExp, zExp; @@ -2193,7 +2202,7 @@ float64 float64_div( struct roundingData *roundData, float64 a, float64 b ) if ( aSig ) return propagateFloat64NaN( a, b ); if ( bExp == 0x7FF ) { if ( bSig ) return propagateFloat64NaN( a, b ); - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return float64_default_nan; } return packFloat64( zSign, 0x7FF, 0 ); @@ -2205,10 +2214,10 @@ float64 float64_div( struct roundingData *roundData, float64 a, float64 b ) if ( bExp == 0 ) { if ( bSig == 0 ) { if ( ( aExp | aSig ) == 0 ) { - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return float64_default_nan; } - roundData->exception |= float_flag_divbyzero; + float_raise( float_flag_divbyzero ); return packFloat64( zSign, 0x7FF, 0 ); } normalizeFloat64Subnormal( bSig, &bExp, &bSig ); @@ -2234,7 +2243,7 @@ float64 float64_div( struct roundingData *roundData, float64 a, float64 b ) } zSig |= ( rem1 != 0 ); } - return roundAndPackFloat64( roundData, zSign, zExp, zSig ); + return roundAndPackFloat64( zSign, zExp, zSig ); } @@ -2245,7 +2254,7 @@ with respect to the corresponding value `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float64 float64_rem( struct roundingData *roundData, float64 a, float64 b ) +float64 float64_rem( float64 a, float64 b ) { flag aSign, bSign, zSign; int16 aExp, bExp, expDiff; @@ -2263,7 +2272,7 @@ float64 float64_rem( struct roundingData *roundData, float64 a, float64 b ) if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { return propagateFloat64NaN( a, b ); } - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return float64_default_nan; } if ( bExp == 0x7FF ) { @@ -2272,7 +2281,7 @@ float64 float64_rem( struct roundingData *roundData, float64 a, float64 b ) } if ( bExp == 0 ) { if ( bSig == 0 ) { - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return float64_default_nan; } normalizeFloat64Subnormal( bSig, &bExp, &bSig ); @@ -2320,7 +2329,7 @@ float64 float64_rem( struct roundingData *roundData, float64 a, float64 b ) } zSign = ( (sbits64) aSig < 0 ); if ( zSign ) aSig = - aSig; - return normalizeRoundAndPackFloat64( roundData, aSign ^ zSign, bExp, aSig ); + return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig ); } @@ -2331,7 +2340,7 @@ The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float64 float64_sqrt( struct roundingData *roundData, float64 a ) +float64 float64_sqrt( float64 a ) { flag aSign; int16 aExp, zExp; @@ -2345,12 +2354,12 @@ float64 float64_sqrt( struct roundingData *roundData, float64 a ) if ( aExp == 0x7FF ) { if ( aSig ) return propagateFloat64NaN( a, a ); if ( ! aSign ) return a; - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return float64_default_nan; } if ( aSign ) { if ( ( aExp | aSig ) == 0 ) return a; - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return float64_default_nan; } if ( aExp == 0 ) { @@ -2381,7 +2390,7 @@ float64 float64_sqrt( struct roundingData *roundData, float64 a ) } } shift64RightJamming( zSig, 1, &zSig ); - return roundAndPackFloat64( roundData, 0, zExp, zSig ); + return roundAndPackFloat64( 0, zExp, zSig ); } @@ -2545,7 +2554,7 @@ largest positive integer is returned. Otherwise, if the conversion overflows, the largest integer with the same sign as `a' is returned. ------------------------------------------------------------------------------- */ -int32 floatx80_to_int32( struct roundingData *roundData, floatx80 a ) +int32 floatx80_to_int32( floatx80 a ) { flag aSign; int32 aExp, shiftCount; @@ -2558,7 +2567,7 @@ int32 floatx80_to_int32( struct roundingData *roundData, floatx80 a ) shiftCount = 0x4037 - aExp; if ( shiftCount <= 0 ) shiftCount = 1; shift64RightJamming( aSig, shiftCount, &aSig ); - return roundAndPackInt32( roundData, aSign, aSig ); + return roundAndPackInt32( aSign, aSig ); } @@ -2589,7 +2598,7 @@ int32 floatx80_to_int32_round_to_zero( floatx80 a ) goto invalid; } else if ( 63 < shiftCount ) { - if ( aExp || aSig ) float_raise( float_flag_inexact ); + if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; return 0; } savedASig = aSig; @@ -2598,11 +2607,11 @@ int32 floatx80_to_int32_round_to_zero( floatx80 a ) if ( aSign ) z = - z; if ( ( z < 0 ) ^ aSign ) { invalid: - float_raise( float_flag_invalid ); + float_exception_flags |= float_flag_invalid; return aSign ? 0x80000000 : 0x7FFFFFFF; } if ( ( aSig<exception |= float_flag_inexact; + float_exception_flags |= float_flag_inexact; aSign = extractFloatx80Sign( a ); - switch ( roundData->mode ) { + switch ( float_rounding_mode ) { case float_round_nearest_even: if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) { @@ -2720,7 +2729,7 @@ floatx80 floatx80_round_to_int( struct roundingData *roundData, floatx80 a ) lastBitMask <<= 0x403E - aExp; roundBitsMask = lastBitMask - 1; z = a; - roundingMode = roundData->mode; + roundingMode = float_rounding_mode; if ( roundingMode == float_round_nearest_even ) { z.low += lastBitMask>>1; if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; @@ -2735,7 +2744,7 @@ floatx80 floatx80_round_to_int( struct roundingData *roundData, floatx80 a ) ++z.high; z.low = LIT64( 0x8000000000000000 ); } - if ( z.low != a.low ) roundData->exception |= float_flag_inexact; + if ( z.low != a.low ) float_exception_flags |= float_flag_inexact; return z; } @@ -2749,7 +2758,7 @@ The addition is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static floatx80 addFloatx80Sigs( struct roundingData *roundData, floatx80 a, floatx80 b, flag zSign ) +static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) { int32 aExp, bExp, zExp; bits64 aSig, bSig, zSig0, zSig1; @@ -2805,7 +2814,7 @@ static floatx80 addFloatx80Sigs( struct roundingData *roundData, floatx80 a, flo roundAndPack: return roundAndPackFloatx80( - roundData, zSign, zExp, zSig0, zSig1 ); + floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); } @@ -2818,7 +2827,7 @@ result is a NaN. The subtraction is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static floatx80 subFloatx80Sigs( struct roundingData *roundData, floatx80 a, floatx80 b, flag zSign ) +static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) { int32 aExp, bExp, zExp; bits64 aSig, bSig, zSig0, zSig1; @@ -2836,7 +2845,7 @@ static floatx80 subFloatx80Sigs( struct roundingData *roundData, floatx80 a, flo if ( (bits64) ( ( aSig | bSig )<<1 ) ) { return propagateFloatx80NaN( a, b ); } - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; return z; @@ -2848,7 +2857,7 @@ static floatx80 subFloatx80Sigs( struct roundingData *roundData, floatx80 a, flo zSig1 = 0; if ( bSig < aSig ) goto aBigger; if ( aSig < bSig ) goto bBigger; - return packFloatx80( roundData->mode == float_round_down, 0, 0 ); + return packFloatx80( float_rounding_mode == float_round_down, 0, 0 ); bExpBigger: if ( bExp == 0x7FFF ) { if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); @@ -2874,7 +2883,7 @@ static floatx80 subFloatx80Sigs( struct roundingData *roundData, floatx80 a, flo normalizeRoundAndPack: return normalizeRoundAndPackFloatx80( - roundData, zSign, zExp, zSig0, zSig1 ); + floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); } @@ -2885,17 +2894,17 @@ values `a' and `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -floatx80 floatx80_add( struct roundingData *roundData, floatx80 a, floatx80 b ) +floatx80 floatx80_add( floatx80 a, floatx80 b ) { flag aSign, bSign; aSign = extractFloatx80Sign( a ); bSign = extractFloatx80Sign( b ); if ( aSign == bSign ) { - return addFloatx80Sigs( roundData, a, b, aSign ); + return addFloatx80Sigs( a, b, aSign ); } else { - return subFloatx80Sigs( roundData, a, b, aSign ); + return subFloatx80Sigs( a, b, aSign ); } } @@ -2907,17 +2916,17 @@ point values `a' and `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -floatx80 floatx80_sub( struct roundingData *roundData, floatx80 a, floatx80 b ) +floatx80 floatx80_sub( floatx80 a, floatx80 b ) { flag aSign, bSign; aSign = extractFloatx80Sign( a ); bSign = extractFloatx80Sign( b ); if ( aSign == bSign ) { - return subFloatx80Sigs( roundData, a, b, aSign ); + return subFloatx80Sigs( a, b, aSign ); } else { - return addFloatx80Sigs( roundData, a, b, aSign ); + return addFloatx80Sigs( a, b, aSign ); } } @@ -2929,7 +2938,7 @@ point values `a' and `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -floatx80 floatx80_mul( struct roundingData *roundData, floatx80 a, floatx80 b ) +floatx80 floatx80_mul( floatx80 a, floatx80 b ) { flag aSign, bSign, zSign; int32 aExp, bExp, zExp; @@ -2955,7 +2964,7 @@ floatx80 floatx80_mul( struct roundingData *roundData, floatx80 a, floatx80 b ) if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); if ( ( aExp | aSig ) == 0 ) { invalid: - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; return z; @@ -2978,7 +2987,7 @@ floatx80 floatx80_mul( struct roundingData *roundData, floatx80 a, floatx80 b ) } return roundAndPackFloatx80( - roundData, zSign, zExp, zSig0, zSig1 ); + floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); } @@ -2989,7 +2998,7 @@ value `a' by the corresponding value `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -floatx80 floatx80_div( struct roundingData *roundData, floatx80 a, floatx80 b ) +floatx80 floatx80_div( floatx80 a, floatx80 b ) { flag aSign, bSign, zSign; int32 aExp, bExp, zExp; @@ -3020,12 +3029,12 @@ floatx80 floatx80_div( struct roundingData *roundData, floatx80 a, floatx80 b ) if ( bSig == 0 ) { if ( ( aExp | aSig ) == 0 ) { invalid: - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; return z; } - roundData->exception |= float_flag_divbyzero; + float_raise( float_flag_divbyzero ); return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); } normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); @@ -3059,7 +3068,7 @@ floatx80 floatx80_div( struct roundingData *roundData, floatx80 a, floatx80 b ) } return roundAndPackFloatx80( - roundData, zSign, zExp, zSig0, zSig1 ); + floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); } @@ -3070,7 +3079,7 @@ Returns the remainder of the extended double-precision floating-point value according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -floatx80 floatx80_rem( struct roundingData *roundData, floatx80 a, floatx80 b ) +floatx80 floatx80_rem( floatx80 a, floatx80 b ) { flag aSign, bSign, zSign; int32 aExp, bExp, expDiff; @@ -3098,7 +3107,7 @@ floatx80 floatx80_rem( struct roundingData *roundData, floatx80 a, floatx80 b ) if ( bExp == 0 ) { if ( bSig == 0 ) { invalid: - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; return z; @@ -3155,10 +3164,9 @@ floatx80 floatx80_rem( struct roundingData *roundData, floatx80 a, floatx80 b ) aSig1 = alternateASig1; zSign = ! zSign; } - return normalizeRoundAndPackFloatx80( - roundData, zSign, bExp + expDiff, aSig0, aSig1 ); + 80, zSign, bExp + expDiff, aSig0, aSig1 ); } @@ -3169,7 +3177,7 @@ value `a'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -floatx80 floatx80_sqrt( struct roundingData *roundData, floatx80 a ) +floatx80 floatx80_sqrt( floatx80 a ) { flag aSign; int32 aExp, zExp; @@ -3189,7 +3197,7 @@ floatx80 floatx80_sqrt( struct roundingData *roundData, floatx80 a ) if ( aSign ) { if ( ( aExp | aSig0 ) == 0 ) return a; invalid: - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; return z; @@ -3234,7 +3242,7 @@ floatx80 floatx80_sqrt( struct roundingData *roundData, floatx80 a ) } return roundAndPackFloatx80( - roundData, 0, zExp, zSig0, zSig1 ); + floatx80_rounding_precision, 0, zExp, zSig0, zSig1 ); } @@ -3256,7 +3264,7 @@ flag floatx80_eq( floatx80 a, floatx80 b ) ) { if ( floatx80_is_signaling_nan( a ) || floatx80_is_signaling_nan( b ) ) { - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); } return 0; } @@ -3286,7 +3294,7 @@ flag floatx80_le( floatx80 a, floatx80 b ) || ( ( extractFloatx80Exp( b ) == 0x7FFF ) && (bits64) ( extractFloatx80Frac( b )<<1 ) ) ) { - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return 0; } aSign = extractFloatx80Sign( a ); @@ -3320,7 +3328,7 @@ flag floatx80_lt( floatx80 a, floatx80 b ) || ( ( extractFloatx80Exp( b ) == 0x7FFF ) && (bits64) ( extractFloatx80Frac( b )<<1 ) ) ) { - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return 0; } aSign = extractFloatx80Sign( a ); @@ -3353,7 +3361,7 @@ flag floatx80_eq_signaling( floatx80 a, floatx80 b ) || ( ( extractFloatx80Exp( b ) == 0x7FFF ) && (bits64) ( extractFloatx80Frac( b )<<1 ) ) ) { - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); return 0; } return @@ -3384,7 +3392,7 @@ flag floatx80_le_quiet( floatx80 a, floatx80 b ) ) { if ( floatx80_is_signaling_nan( a ) || floatx80_is_signaling_nan( b ) ) { - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); } return 0; } @@ -3421,7 +3429,7 @@ flag floatx80_lt_quiet( floatx80 a, floatx80 b ) ) { if ( floatx80_is_signaling_nan( a ) || floatx80_is_signaling_nan( b ) ) { - roundData->exception |= float_flag_invalid; + float_raise( float_flag_invalid ); } return 0; } diff --git a/trunk/arch/arm/nwfpe/softfloat.h b/trunk/arch/arm/nwfpe/softfloat.h index 1c8799b9ee4d..1e1743173899 100644 --- a/trunk/arch/arm/nwfpe/softfloat.h +++ b/trunk/arch/arm/nwfpe/softfloat.h @@ -74,7 +74,7 @@ enum { Software IEC/IEEE floating-point rounding mode. ------------------------------------------------------------------------------- */ -//extern int8 float_rounding_mode; +extern signed char float_rounding_mode; enum { float_round_nearest_even = 0, float_round_to_zero = 1, @@ -86,6 +86,7 @@ enum { ------------------------------------------------------------------------------- Software IEC/IEEE floating-point exception flags. ------------------------------------------------------------------------------- +extern signed char float_exception_flags; enum { float_flag_inexact = 1, float_flag_underflow = 2, @@ -98,6 +99,7 @@ ScottB: November 4, 1998 Changed the enumeration to match the bit order in the FPA11. */ +extern signed char float_exception_flags; enum { float_flag_invalid = 1, float_flag_divbyzero = 2, @@ -119,7 +121,7 @@ void float_raise( signed char ); Software IEC/IEEE integer-to-floating-point conversion routines. ------------------------------------------------------------------------------- */ -float32 int32_to_float32( struct roundingData *, signed int ); +float32 int32_to_float32( signed int ); float64 int32_to_float64( signed int ); #ifdef FLOATX80 floatx80 int32_to_floatx80( signed int ); @@ -130,7 +132,7 @@ floatx80 int32_to_floatx80( signed int ); Software IEC/IEEE single-precision conversion routines. ------------------------------------------------------------------------------- */ -signed int float32_to_int32( struct roundingData *, float32 ); +signed int float32_to_int32( float32 ); signed int float32_to_int32_round_to_zero( float32 ); float64 float32_to_float64( float32 ); #ifdef FLOATX80 @@ -142,13 +144,13 @@ floatx80 float32_to_floatx80( float32 ); Software IEC/IEEE single-precision operations. ------------------------------------------------------------------------------- */ -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 ); +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 ); char float32_eq( float32, float32 ); char float32_le( float32, float32 ); char float32_lt( float32, float32 ); @@ -162,9 +164,9 @@ char float32_is_signaling_nan( float32 ); Software IEC/IEEE double-precision conversion routines. ------------------------------------------------------------------------------- */ -signed int float64_to_int32( struct roundingData *, float64 ); +signed int float64_to_int32( float64 ); signed int float64_to_int32_round_to_zero( float64 ); -float32 float64_to_float32( struct roundingData *, float64 ); +float32 float64_to_float32( float64 ); #ifdef FLOATX80 floatx80 float64_to_floatx80( float64 ); #endif @@ -174,13 +176,13 @@ floatx80 float64_to_floatx80( float64 ); Software IEC/IEEE double-precision operations. ------------------------------------------------------------------------------- */ -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 ); +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 ); char float64_eq( float64, float64 ); char float64_le( float64, float64 ); char float64_lt( float64, float64 ); @@ -196,23 +198,31 @@ char float64_is_signaling_nan( float64 ); Software IEC/IEEE extended double-precision conversion routines. ------------------------------------------------------------------------------- */ -signed int floatx80_to_int32( struct roundingData *, floatx80 ); +signed int floatx80_to_int32( floatx80 ); signed int floatx80_to_int32_round_to_zero( floatx80 ); -float32 floatx80_to_float32( struct roundingData *, floatx80 ); -float64 floatx80_to_float64( struct roundingData *, 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; /* ------------------------------------------------------------------------------- Software IEC/IEEE extended double-precision operations. ------------------------------------------------------------------------------- */ -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 ); +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 ); char floatx80_eq( floatx80, floatx80 ); char floatx80_le( floatx80, floatx80 ); char floatx80_lt( floatx80, floatx80 ); diff --git a/trunk/arch/arm/vfp/vfpdouble.c b/trunk/arch/arm/vfp/vfpdouble.c index 9b367a65cb4d..b801cd66b6ea 100644 --- a/trunk/arch/arm/vfp/vfpdouble.c +++ b/trunk/arch/arm/vfp/vfpdouble.c @@ -770,9 +770,6 @@ vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn, if ((s64)m_sig < 0) { vdd->sign = vfp_sign_negate(vdd->sign); m_sig = -m_sig; - } else if (m_sig == 0) { - vdd->sign = (fpscr & FPSCR_RMODE_MASK) == - FPSCR_ROUND_MINUSINF ? 0x8000 : 0; } } else { m_sig += vdn->significand; diff --git a/trunk/arch/arm26/mm/fault.c b/trunk/arch/arm26/mm/fault.c index bd6f2db608b7..dacca8bb7744 100644 --- a/trunk/arch/arm26/mm/fault.c +++ b/trunk/arch/arm26/mm/fault.c @@ -176,12 +176,12 @@ __do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr, * Handle the "normal" cases first - successful and sigbus */ switch (fault) { - case VM_FAULT_MAJOR: + case 2: tsk->maj_flt++; return fault; - case VM_FAULT_MINOR: + case 1: tsk->min_flt++; - case VM_FAULT_SIGBUS: + case 0: return fault; } @@ -226,11 +226,14 @@ int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) /* * Handle the "normal" case first */ - switch (fault) { - case VM_FAULT_MINOR: - case VM_FAULT_MAJOR: + if (fault > 0) return 0; - case VM_FAULT_SIGBUS: + + /* + * We had some memory, but were unable to + * successfully fix up this page fault. + */ + if (fault == 0){ goto do_sigbus; } diff --git a/trunk/arch/cris/mm/fault.c b/trunk/arch/cris/mm/fault.c index 934c51078cce..fe1cc36b5aca 100644 --- a/trunk/arch/cris/mm/fault.c +++ b/trunk/arch/cris/mm/fault.c @@ -284,13 +284,13 @@ do_page_fault(unsigned long address, struct pt_regs *regs, */ switch (handle_mm_fault(mm, vma, address, writeaccess & 1)) { - case VM_FAULT_MINOR: + case 1: tsk->min_flt++; break; - case VM_FAULT_MAJOR: + case 2: tsk->maj_flt++; break; - case VM_FAULT_SIGBUS: + case 0: goto do_sigbus; default: goto out_of_memory; diff --git a/trunk/arch/frv/mm/fault.c b/trunk/arch/frv/mm/fault.c index 8b3eb50c5105..41d02ac48233 100644 --- a/trunk/arch/frv/mm/fault.c +++ b/trunk/arch/frv/mm/fault.c @@ -163,13 +163,13 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear * the fault. */ switch (handle_mm_fault(mm, vma, ear0, write)) { - case VM_FAULT_MINOR: + case 1: current->min_flt++; break; - case VM_FAULT_MAJOR: + case 2: current->maj_flt++; break; - case VM_FAULT_SIGBUS: + case 0: goto do_sigbus; default: goto out_of_memory; diff --git a/trunk/arch/m68k/mm/fault.c b/trunk/arch/m68k/mm/fault.c index aec15270d334..ac48b6d2aff6 100644 --- a/trunk/arch/m68k/mm/fault.c +++ b/trunk/arch/m68k/mm/fault.c @@ -160,13 +160,13 @@ int do_page_fault(struct pt_regs *regs, unsigned long address, printk("handle_mm_fault returns %d\n",fault); #endif switch (fault) { - case VM_FAULT_MINOR: + case 1: current->min_flt++; break; - case VM_FAULT_MAJOR: + case 2: current->maj_flt++; break; - case VM_FAULT_SIGBUS: + case 0: goto bus_err; default: goto out_of_memory; diff --git a/trunk/arch/parisc/mm/fault.c b/trunk/arch/parisc/mm/fault.c index 0ad945d4c0a4..eaa701479f5f 100644 --- a/trunk/arch/parisc/mm/fault.c +++ b/trunk/arch/parisc/mm/fault.c @@ -178,17 +178,17 @@ void do_page_fault(struct pt_regs *regs, unsigned long code, */ switch (handle_mm_fault(mm, vma, address, (acc_type & VM_WRITE) != 0)) { - case VM_FAULT_MINOR: + case 1: ++current->min_flt; break; - case VM_FAULT_MAJOR: + case 2: ++current->maj_flt; break; - case VM_FAULT_SIGBUS: + case 0: /* - * We hit a hared mapping outside of the file, or some - * other thing happened to us that made us unable to - * handle the page fault gracefully. + * We ran out of memory, or some other thing happened + * to us that made us unable to handle the page fault + * gracefully. */ goto bad_area; default: diff --git a/trunk/arch/ppc64/xmon/xmon.c b/trunk/arch/ppc64/xmon/xmon.c index 05539439e6bc..7f6e13a4b71e 100644 --- a/trunk/arch/ppc64/xmon/xmon.c +++ b/trunk/arch/ppc64/xmon/xmon.c @@ -329,16 +329,13 @@ int xmon_core(struct pt_regs *regs, int fromipi) printf("cpu 0x%x: Exception %lx %s in xmon, " "returning to main loop\n", cpu, regs->trap, getvecname(TRAP(regs))); - release_output_lock(); longjmp(xmon_fault_jmp[cpu], 1); } if (setjmp(recurse_jmp) != 0) { if (!in_xmon || !xmon_gate) { - get_output_lock(); printf("xmon: WARNING: bad recursive fault " "on cpu 0x%x\n", cpu); - release_output_lock(); goto waiting; } secondary = !(xmon_taken && cpu == xmon_owner); diff --git a/trunk/arch/sh64/mm/fault.c b/trunk/arch/sh64/mm/fault.c index f08d0eaf6497..a24932881dbb 100644 --- a/trunk/arch/sh64/mm/fault.c +++ b/trunk/arch/sh64/mm/fault.c @@ -223,13 +223,13 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, */ survive: switch (handle_mm_fault(mm, vma, address, writeaccess)) { - case VM_FAULT_MINOR: + case 1: tsk->min_flt++; break; - case VM_FAULT_MAJOR: + case 2: tsk->maj_flt++; break; - case VM_FAULT_SIGBUS: + case 0: goto do_sigbus; default: goto out_of_memory; diff --git a/trunk/arch/x86_64/mm/fault.c b/trunk/arch/x86_64/mm/fault.c index 493819e543a5..13792721037e 100644 --- a/trunk/arch/x86_64/mm/fault.c +++ b/trunk/arch/x86_64/mm/fault.c @@ -439,13 +439,13 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) * the fault. */ switch (handle_mm_fault(mm, vma, address, write)) { - case VM_FAULT_MINOR: + case 1: tsk->min_flt++; break; - case VM_FAULT_MAJOR: + case 2: tsk->maj_flt++; break; - case VM_FAULT_SIGBUS: + case 0: goto do_sigbus; default: goto out_of_memory; diff --git a/trunk/drivers/acpi/motherboard.c b/trunk/drivers/acpi/motherboard.c index 2934475d67d6..61ea70742d49 100644 --- a/trunk/drivers/acpi/motherboard.c +++ b/trunk/drivers/acpi/motherboard.c @@ -43,7 +43,7 @@ ACPI_MODULE_NAME ("acpi_motherboard") */ #define IS_RESERVED_ADDR(base, len) \ (((len) > 0) && ((base) > 0) && ((base) + (len) < IO_SPACE_LIMIT) \ - && ((base) + (len) > 0x1000)) + && ((base) + (len) > PCIBIOS_MIN_IO)) /* * Clearing the flag (IORESOURCE_BUSY) allows drivers to use diff --git a/trunk/drivers/acpi/osl.c b/trunk/drivers/acpi/osl.c index bdd9f37f8101..7289da3c4db6 100644 --- a/trunk/drivers/acpi/osl.c +++ b/trunk/drivers/acpi/osl.c @@ -145,10 +145,14 @@ acpi_os_vprintf(const char *fmt, va_list args) #endif } +extern int acpi_in_resume; void * acpi_os_allocate(acpi_size size) { - return kmalloc(size, GFP_KERNEL); + if (acpi_in_resume) + return kmalloc(size, GFP_ATOMIC); + else + return kmalloc(size, GFP_KERNEL); } void diff --git a/trunk/drivers/acpi/pci_link.c b/trunk/drivers/acpi/pci_link.c index 65cea07abbc3..834c2ceff1aa 100644 --- a/trunk/drivers/acpi/pci_link.c +++ b/trunk/drivers/acpi/pci_link.c @@ -798,6 +798,11 @@ acpi_pci_link_resume( return_VALUE(0); } +/* + * FIXME: this is a workaround to avoid nasty warning. It will be removed + * after every device calls pci_disable_device in .resume. + */ +int acpi_in_resume; static int irqrouter_resume( struct sys_device *dev) @@ -807,6 +812,7 @@ irqrouter_resume( ACPI_FUNCTION_TRACE("irqrouter_resume"); + acpi_in_resume = 1; list_for_each(node, &acpi_link.entries) { link = list_entry(node, struct acpi_pci_link, node); if (!link) { @@ -816,6 +822,7 @@ irqrouter_resume( } acpi_pci_link_resume(link); } + acpi_in_resume = 0; return_VALUE(0); } diff --git a/trunk/drivers/block/cfq-iosched.c b/trunk/drivers/block/cfq-iosched.c index 2435a7c99b2b..de5746e38af9 100644 --- a/trunk/drivers/block/cfq-iosched.c +++ b/trunk/drivers/block/cfq-iosched.c @@ -1281,7 +1281,6 @@ static struct request *cfq_next_request(request_queue_t *q) */ if (!cfq_crq_in_driver(crq) && !cfq_cfqq_idle_window(cfqq) && - !blk_barrier_rq(rq) && cfqd->rq_in_driver >= cfqd->cfq_max_depth) return NULL; diff --git a/trunk/drivers/char/watchdog/sa1100_wdt.c b/trunk/drivers/char/watchdog/sa1100_wdt.c index fb88b4041dca..1b2132617dc3 100644 --- a/trunk/drivers/char/watchdog/sa1100_wdt.c +++ b/trunk/drivers/char/watchdog/sa1100_wdt.c @@ -36,10 +36,13 @@ #include #define OSCR_FREQ CLOCK_TICK_RATE +#define SA1100_CLOSE_MAGIC (0x5afc4453) static unsigned long sa1100wdt_users; +static int expect_close; static int pre_margin; static int boot_status; +static int nowayout = WATCHDOG_NOWAYOUT; /* * Allow only one person to hold it open @@ -59,33 +62,55 @@ static int sa1100dog_open(struct inode *inode, struct file *file) } /* - * 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). + * 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. */ static int sa1100dog_release(struct inode *inode, struct file *file) { - printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n"); + 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"); + } clear_bit(1, &sa1100wdt_users); + expect_close = 0; return 0; } static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos) { - if (len) + if (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; + } + } /* Refresh OSMR3 timer. */ OSMR3 = OSCR + pre_margin; + } return len; } static struct watchdog_info ident = { - .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, - .identity = "SA1100/PXA255 Watchdog", + .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | + WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, + .identity = "SA1100 Watchdog", }; static int sa1100dog_ioctl(struct inode *inode, struct file *file, @@ -147,7 +172,7 @@ static struct file_operations sa1100dog_fops = static struct miscdevice sa1100dog_miscdev = { .minor = WATCHDOG_MINOR, - .name = "watchdog", + .name = "SA1100/PXA2xx watchdog", .fops = &sa1100dog_fops, }; @@ -169,6 +194,7 @@ static int __init sa1100dog_init(void) if (ret == 0) printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n", margin); + return ret; } @@ -186,5 +212,8 @@ MODULE_DESCRIPTION("SA1100/PXA2xx Watchdog"); module_param(margin, int, 0); MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); + MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/trunk/drivers/infiniband/include/ib_cm.h b/trunk/drivers/infiniband/include/ib_cm.h index da650115e79a..e5d74a730a70 100644 --- a/trunk/drivers/infiniband/include/ib_cm.h +++ b/trunk/drivers/infiniband/include/ib_cm.h @@ -169,8 +169,7 @@ enum ib_cm_rej_reason { IB_CM_REJ_INVALID_ALT_TRAFFIC_CLASS = __constant_htons(21), IB_CM_REJ_INVALID_ALT_HOP_LIMIT = __constant_htons(22), IB_CM_REJ_INVALID_ALT_PACKET_RATE = __constant_htons(23), - IB_CM_REJ_PORT_CM_REDIRECT = __constant_htons(24), - IB_CM_REJ_PORT_REDIRECT = __constant_htons(25), + IB_CM_REJ_PORT_REDIRECT = __constant_htons(24), IB_CM_REJ_INVALID_MTU = __constant_htons(26), IB_CM_REJ_INSUFFICIENT_RESP_RESOURCES = __constant_htons(27), IB_CM_REJ_CONSUMER_DEFINED = __constant_htons(28), diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c index fa00816a3cf7..6f60abbaebd5 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -600,10 +600,9 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) ipoib_mcast_send(dev, (union ib_gid *) (phdr->hwaddr + 4), skb); } else { - /* unicast GID -- should be ARP or RARP reply */ + /* unicast GID -- should be ARP reply */ - if ((be16_to_cpup((__be16 *) skb->data) != ETH_P_ARP) && - (be16_to_cpup((__be16 *) skb->data) != ETH_P_RARP)) { + if (be16_to_cpup((u16 *) skb->data) != ETH_P_ARP) { ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x " IPOIB_GID_FMT "\n", skb->dst ? "neigh" : "dst", diff --git a/trunk/drivers/pci/bus.c b/trunk/drivers/pci/bus.c index fb9a11243d2a..fedae89d8f7d 100644 --- a/trunk/drivers/pci/bus.c +++ b/trunk/drivers/pci/bus.c @@ -60,9 +60,7 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, continue; /* Ok, try it out.. */ - ret = allocate_resource(r, res, size, - r->start ? : min, - -1, align, + ret = allocate_resource(r, res, size, min, -1, align, alignf, alignf_data); if (ret == 0) break; diff --git a/trunk/drivers/pcmcia/yenta_socket.c b/trunk/drivers/pcmcia/yenta_socket.c index 91e7457d5b04..6837491f021c 100644 --- a/trunk/drivers/pcmcia/yenta_socket.c +++ b/trunk/drivers/pcmcia/yenta_socket.c @@ -642,7 +642,6 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ (yenta_search_res(socket, res, BRIDGE_IO_MIN))) { config_writel(socket, addr_start, res->start); config_writel(socket, addr_end, res->end); - return; } } else { if (type & IORESOURCE_PREFETCH) { @@ -651,7 +650,6 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) { config_writel(socket, addr_start, res->start); config_writel(socket, addr_end, res->end); - return; } /* Approximating prefetchable by non-prefetchable */ res->flags = IORESOURCE_MEM; @@ -661,7 +659,6 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) { config_writel(socket, addr_start, res->start); config_writel(socket, addr_end, res->end); - return; } } diff --git a/trunk/drivers/scsi/aic7xxx/aicasm/aicasm.c b/trunk/drivers/scsi/aic7xxx/aicasm/aicasm.c index f936b691232f..c34639481904 100644 --- a/trunk/drivers/scsi/aic7xxx/aicasm/aicasm.c +++ b/trunk/drivers/scsi/aic7xxx/aicasm/aicasm.c @@ -369,7 +369,7 @@ output_code() fprintf(ofile, "%s\t0x%02x, 0x%02x, 0x%02x, 0x%02x", cur_instr == STAILQ_FIRST(&seq_program) ? "" : ",\n", -#ifdef __LITTLE_ENDIAN +#if BYTE_ORDER == LITTLE_ENDIAN cur_instr->format.bytes[0], cur_instr->format.bytes[1], cur_instr->format.bytes[2], @@ -613,7 +613,7 @@ output_listing(char *ifilename) line++; } fprintf(listfile, "%03x %02x%02x%02x%02x", instrptr, -#ifdef __LITTLE_ENDIAN +#if BYTE_ORDER == LITTLE_ENDIAN cur_instr->format.bytes[0], cur_instr->format.bytes[1], cur_instr->format.bytes[2], diff --git a/trunk/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h b/trunk/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h index e64f802bbaaa..3e80f07df49c 100644 --- a/trunk/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h +++ b/trunk/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h @@ -42,10 +42,8 @@ * $FreeBSD$ */ -#include - struct ins_format1 { -#ifdef __LITTLE_ENDIAN +#if BYTE_ORDER == LITTLE_ENDIAN uint32_t immediate : 8, source : 9, destination : 9, @@ -63,7 +61,7 @@ struct ins_format1 { }; struct ins_format2 { -#ifdef __LITTLE_ENDIAN +#if BYTE_ORDER == LITTLE_ENDIAN uint32_t shift_control : 8, source : 9, destination : 9, @@ -81,7 +79,7 @@ struct ins_format2 { }; struct ins_format3 { -#ifdef __LITTLE_ENDIAN +#if BYTE_ORDER == LITTLE_ENDIAN uint32_t immediate : 8, source : 9, address : 10, diff --git a/trunk/include/asm-i386/pci.h b/trunk/include/asm-i386/pci.h index 2cbab30734d6..78c85985aee3 100644 --- a/trunk/include/asm-i386/pci.h +++ b/trunk/include/asm-i386/pci.h @@ -18,9 +18,11 @@ extern unsigned int pcibios_assign_all_busses(void); #define pcibios_scan_all_fns(a, b) 0 extern unsigned long pci_mem_start; -#define PCIBIOS_MIN_IO 0x4000 +#define PCIBIOS_MIN_IO 0x1000 #define PCIBIOS_MIN_MEM (pci_mem_start) +#define PCIBIOS_MIN_CARDBUS_IO 0x4000 + void pcibios_config_init(void); struct pci_bus * pcibios_scan_root(int bus); diff --git a/trunk/include/asm-x86_64/pci.h b/trunk/include/asm-x86_64/pci.h index 9c4527eb55e2..eeb3088a1c9e 100644 --- a/trunk/include/asm-x86_64/pci.h +++ b/trunk/include/asm-x86_64/pci.h @@ -22,9 +22,11 @@ extern unsigned int pcibios_assign_all_busses(void); extern int no_iommu, force_iommu; extern unsigned long pci_mem_start; -#define PCIBIOS_MIN_IO 0x4000 +#define PCIBIOS_MIN_IO 0x1000 #define PCIBIOS_MIN_MEM (pci_mem_start) +#define PCIBIOS_MIN_CARDBUS_IO 0x4000 + void pcibios_config_init(void); struct pci_bus * pcibios_scan_root(int bus); extern int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value); diff --git a/trunk/include/linux/mm.h b/trunk/include/linux/mm.h index 82d7024f0765..6eb7f48317f8 100644 --- a/trunk/include/linux/mm.h +++ b/trunk/include/linux/mm.h @@ -625,16 +625,10 @@ static inline int page_mapped(struct page *page) * Used to decide whether a process gets delivered SIGBUS or * just gets major/minor fault counters bumped up. */ -#define VM_FAULT_OOM 0x00 -#define VM_FAULT_SIGBUS 0x01 -#define VM_FAULT_MINOR 0x02 -#define VM_FAULT_MAJOR 0x03 - -/* - * Special case for get_user_pages. - * Must be in a distinct bit from the above VM_FAULT_ flags. - */ -#define VM_FAULT_WRITE 0x10 +#define VM_FAULT_OOM (-1) +#define VM_FAULT_SIGBUS 0 +#define VM_FAULT_MINOR 1 +#define VM_FAULT_MAJOR 2 #define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK) @@ -710,13 +704,7 @@ extern pte_t *FASTCALL(pte_alloc_kernel(struct mm_struct *mm, pmd_t *pmd, unsign extern pte_t *FASTCALL(pte_alloc_map(struct mm_struct *mm, pmd_t *pmd, unsigned long address)); extern int install_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, struct page *page, pgprot_t prot); extern int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, unsigned long pgoff, pgprot_t prot); -extern int __handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma, unsigned long address, int write_access); - -static inline int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long address, int write_access) -{ - return __handle_mm_fault(mm, vma, address, write_access) & (~VM_FAULT_WRITE); -} - +extern int handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma, unsigned long address, int write_access); extern int make_pages_present(unsigned long addr, unsigned long end); extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write); void install_arg_page(struct vm_area_struct *, struct page *, unsigned long); diff --git a/trunk/kernel/sys.c b/trunk/kernel/sys.c index 0bcaed6560ac..000e81ad2c1d 100644 --- a/trunk/kernel/sys.c +++ b/trunk/kernel/sys.c @@ -404,6 +404,7 @@ void kernel_halt(void) { notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL); system_state = SYSTEM_HALT; + device_suspend(PMSG_SUSPEND); device_shutdown(); printk(KERN_EMERG "System halted.\n"); machine_halt(); @@ -414,6 +415,7 @@ void kernel_power_off(void) { notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL); system_state = SYSTEM_POWER_OFF; + device_suspend(PMSG_SUSPEND); device_shutdown(); printk(KERN_EMERG "Power down.\n"); machine_power_off(); diff --git a/trunk/mm/memory.c b/trunk/mm/memory.c index e046b7e4b530..2405289dfdf8 100644 --- a/trunk/mm/memory.c +++ b/trunk/mm/memory.c @@ -811,18 +811,15 @@ static struct page *__follow_page(struct mm_struct *mm, unsigned long address, pte = *ptep; pte_unmap(ptep); if (pte_present(pte)) { - if (write && !pte_write(pte)) + if (write && !pte_dirty(pte)) goto out; if (read && !pte_read(pte)) goto out; pfn = pte_pfn(pte); if (pfn_valid(pfn)) { page = pfn_to_page(pfn); - if (accessed) { - if (write && !pte_dirty(pte) &&!PageDirty(page)) - set_page_dirty(page); + if (accessed) mark_page_accessed(page); - } return page; } } @@ -944,13 +941,10 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, } spin_lock(&mm->page_table_lock); do { - int write_access = write; struct page *page; cond_resched_lock(&mm->page_table_lock); - while (!(page = follow_page(mm, start, write_access))) { - int ret; - + while (!(page = follow_page(mm, start, write))) { /* * Shortcut for anonymous pages. We don't want * to force the creation of pages tables for @@ -963,18 +957,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, break; } spin_unlock(&mm->page_table_lock); - ret = __handle_mm_fault(mm, vma, start, write_access); - - /* - * The VM_FAULT_WRITE bit tells us that do_wp_page has - * broken COW when necessary, even if maybe_mkwrite - * decided not to set pte_write. We can thus safely do - * subsequent page lookups as if they were reads. - */ - if (ret & VM_FAULT_WRITE) - write_access = 0; - - switch (ret & ~VM_FAULT_WRITE) { + switch (handle_mm_fault(mm,vma,start,write)) { case VM_FAULT_MINOR: tsk->min_flt++; break; @@ -1237,7 +1220,6 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma, struct page *old_page, *new_page; unsigned long pfn = pte_pfn(pte); pte_t entry; - int ret; if (unlikely(!pfn_valid(pfn))) { /* @@ -1265,7 +1247,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma, lazy_mmu_prot_update(entry); pte_unmap(page_table); spin_unlock(&mm->page_table_lock); - return VM_FAULT_MINOR|VM_FAULT_WRITE; + return VM_FAULT_MINOR; } } pte_unmap(page_table); @@ -1292,7 +1274,6 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma, /* * Re-check the pte - we dropped the lock */ - ret = VM_FAULT_MINOR; spin_lock(&mm->page_table_lock); page_table = pte_offset_map(pmd, address); if (likely(pte_same(*page_table, pte))) { @@ -1309,13 +1290,12 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma, /* Free the old page.. */ new_page = old_page; - ret |= VM_FAULT_WRITE; } pte_unmap(page_table); page_cache_release(new_page); page_cache_release(old_page); spin_unlock(&mm->page_table_lock); - return ret; + return VM_FAULT_MINOR; no_new_page: page_cache_release(old_page); @@ -2007,6 +1987,7 @@ static inline int handle_pte_fault(struct mm_struct *mm, if (write_access) { if (!pte_write(entry)) return do_wp_page(mm, vma, address, pte, pmd, entry); + entry = pte_mkdirty(entry); } entry = pte_mkyoung(entry); @@ -2021,7 +2002,7 @@ static inline int handle_pte_fault(struct mm_struct *mm, /* * By the time we get here, we already hold the mm semaphore */ -int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma, +int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma, unsigned long address, int write_access) { pgd_t *pgd; diff --git a/trunk/security/keys/keyctl.c b/trunk/security/keys/keyctl.c index a6516a64b297..fea262860ea0 100644 --- a/trunk/security/keys/keyctl.c +++ b/trunk/security/keys/keyctl.c @@ -49,6 +49,9 @@ asmlinkage long sys_add_key(const char __user *_type, goto error; type[31] = '\0'; + if (!type[0]) + goto error; + ret = -EPERM; if (type[0] == '.') goto error; @@ -141,10 +144,6 @@ asmlinkage long sys_request_key(const char __user *_type, goto error; type[31] = '\0'; - ret = -EPERM; - if (type[0] == '.') - goto error; - /* pull the description into kernel space */ ret = -EFAULT; dlen = strnlen_user(_description, PAGE_SIZE - 1); @@ -363,7 +362,7 @@ long keyctl_revoke_key(key_serial_t id) key_put(key); error: - return ret; + return 0; } /* end keyctl_revoke_key() */ @@ -686,8 +685,6 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) goto can_read_key2; ret = PTR_ERR(skey); - if (ret == -EAGAIN) - ret = -EACCES; goto error2; } diff --git a/trunk/security/keys/request_key.c b/trunk/security/keys/request_key.c index 90c1506d007c..dfcd983af1fd 100644 --- a/trunk/security/keys/request_key.c +++ b/trunk/security/keys/request_key.c @@ -405,7 +405,7 @@ struct key *request_key_and_link(struct key_type *type, key_user_put(user); /* link the new key into the appropriate keyring */ - if (!IS_ERR(key)) + if (!PTR_ERR(key)) request_key_link(key, dest_keyring); }