aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-08-03 13:09:43 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2005-08-03 13:09:43 -0700
commit194d0710e1a7fe92dcf860ddd31fded8c3103b7a (patch)
treeda03b56fa4dee221c53af5770492d391f0d09459
parenta68d2ebc1581a3aec57bd032651e013fa609f530 (diff)
parent9bbd03758945858c9303f3258b418b94c4ffd735 (diff)
Merge master.kernel.org:/home/rmk/linux-2.6-arm
-rw-r--r--Documentation/dontdiff1
-rw-r--r--arch/arm/mach-ixp4xx/coyote-setup.c2
-rw-r--r--arch/arm/mach-ixp4xx/gtwx5715-setup.c2
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-setup.c4
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c16
-rw-r--r--arch/arm/mm/proc-xscale.S136
-rw-r--r--arch/arm/nwfpe/double_cpdo.c24
-rw-r--r--arch/arm/nwfpe/extended_cpdo.c24
-rw-r--r--arch/arm/nwfpe/fpa11.c30
-rw-r--r--arch/arm/nwfpe/fpa11.h11
-rw-r--r--arch/arm/nwfpe/fpa11_cpdo.c28
-rw-r--r--arch/arm/nwfpe/fpa11_cpdt.c22
-rw-r--r--arch/arm/nwfpe/fpa11_cprt.c28
-rw-r--r--arch/arm/nwfpe/fpmodule.c15
-rw-r--r--arch/arm/nwfpe/single_cpdo.c24
-rw-r--r--arch/arm/nwfpe/softfloat.c334
-rw-r--r--arch/arm/nwfpe/softfloat.h68
-rw-r--r--arch/arm/vfp/vfpdouble.c3
-rw-r--r--drivers/char/watchdog/sa1100_wdt.c49
19 files changed, 337 insertions, 484 deletions
diff --git a/Documentation/dontdiff b/Documentation/dontdiff
index b974cf595d0..96bea278bbf 100644
--- a/Documentation/dontdiff
+++ b/Documentation/dontdiff
@@ -104,6 +104,7 @@ logo_*.c
logo_*_clut224.c
logo_*_mono.c
lxdialog
+mach-types
mach-types.h
make_times_h
map
diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c
index 4ff4393ef0e..7f58afb27e7 100644
--- a/arch/arm/mach-ixp4xx/coyote-setup.c
+++ b/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,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = IXP4XX_UART_XTAL,
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
index 8ba1cd9406e..65e356bd10d 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c
+++ b/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,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = IXP4XX_UART_XTAL,
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index c2ba759e994..4633470a6a3 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/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,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = IXP4XX_UART_XTAL,
@@ -91,7 +91,7 @@ static struct plat_serial8250_port ixdp425_uart_data[] = {
.mapbase = IXP4XX_UART2_BASE_PHYS,
.membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
.irq = IRQ_IXP4XX_UART1,
- .flags = UPF_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = IXP4XX_UART_XTAL,
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index 1e7f343822d..e9182242da9 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -30,6 +30,7 @@
* 28-Jun-2005 BJD Moved pm functionality out to common code
* 17-Jul-2005 BJD Changed to platform device for SuperIO 16550s
* 25-Jul-2005 BJD Removed ASIX static mappings
+ * 27-Jul-2005 BJD Ensure maximum frequency of i2c bus
*/
#include <linux/kernel.h>
@@ -60,6 +61,7 @@
#include <asm/arch/regs-mem.h>
#include <asm/arch/regs-lcd.h>
#include <asm/arch/nand.h>
+#include <asm/arch/iic.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
@@ -304,7 +306,7 @@ static void bast_nand_select(struct s3c2410_nand_set *set, int slot)
}
static struct s3c2410_platform_nand bast_nand_info = {
- .tacls = 80,
+ .tacls = 40,
.twrph0 = 80,
.twrph1 = 80,
.nr_sets = ARRAY_SIZE(bast_nand_sets),
@@ -385,6 +387,17 @@ static struct platform_device bast_sio = {
},
};
+/* we have devices on the bus which cannot work much over the
+ * standard 100KHz i2c bus frequency
+*/
+
+static struct s3c2410_platform_i2c bast_i2c_info = {
+ .flags = 0,
+ .slave_addr = 0x10,
+ .bus_freq = 100*1000,
+ .max_freq = 130*1000,
+};
+
/* Standard BAST devices */
static struct platform_device *bast_devices[] __initdata = {
@@ -431,6 +444,7 @@ void __init bast_map_io(void)
s3c24xx_uclk.parent = &s3c24xx_clkout1;
s3c_device_nand.dev.platform_data = &bast_nand_info;
+ s3c_device_i2c.dev.platform_data = &bast_i2c_info;
s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
s3c24xx_init_clocks(0);
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index 2d977b4eeea..b88de270014 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -370,142 +370,6 @@ ENTRY(cpu_xscale_dcache_clean_area)
bhi 1b
mov pc, lr
-/* ================================ CACHE LOCKING============================
- *
- * The XScale MicroArchitecture implements support for locking entries into
- * the data and instruction cache. The following functions implement the core
- * low level instructions needed to accomplish the locking. The developer's
- * manual states that the code that performs the locking must be in non-cached
- * memory. To accomplish this, the code in xscale-cache-lock.c copies the
- * following functions from the cache into a non-cached memory region that
- * is allocated through consistent_alloc().
- *
- */
- .align 5
-/*
- * xscale_icache_lock
- *
- * r0: starting address to lock
- * r1: end address to lock
- */
-ENTRY(xscale_icache_lock)
-
-iLockLoop:
- bic r0, r0, #CACHELINESIZE - 1
- mcr p15, 0, r0, c9, c1, 0 @ lock into cache
- cmp r0, r1 @ are we done?
- add r0, r0, #CACHELINESIZE @ advance to next cache line
- bls iLockLoop
- mov pc, lr
-
-/*
- * xscale_icache_unlock
- */
-ENTRY(xscale_icache_unlock)
- mcr p15, 0, r0, c9, c1, 1 @ Unlock icache
- mov pc, lr
-
-/*
- * xscale_dcache_lock
- *
- * r0: starting address to lock
- * r1: end address to lock
- */
-ENTRY(xscale_dcache_lock)
- mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
- mov r2, #1
- mcr p15, 0, r2, c9, c2, 0 @ Put dcache in lock mode
- cpwait ip @ Wait for completion
-
- mrs r2, cpsr
- orr r3, r2, #PSR_F_BIT | PSR_I_BIT
-dLockLoop:
- msr cpsr_c, r3
- mcr p15, 0, r0, c7, c10, 1 @ Write back line if it is dirty
- mcr p15, 0, r0, c7, c6, 1 @ Flush/invalidate line
- msr cpsr_c, r2
- ldr ip, [r0], #CACHELINESIZE @ Preload 32 bytes into cache from
- @ location [r0]. Post-increment
- @ r3 to next cache line
- cmp r0, r1 @ Are we done?
- bls dLockLoop
-
- mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
- mov r2, #0
- mcr p15, 0, r2, c9, c2, 0 @ Get out of lock mode
- cpwait_ret lr, ip
-
-/*
- * xscale_dcache_unlock
- */
-ENTRY(xscale_dcache_unlock)
- mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
- mcr p15, 0, ip, c9, c2, 1 @ Unlock cache
- mov pc, lr
-
-/*
- * Needed to determine the length of the code that needs to be copied.
- */
- .align 5
-ENTRY(xscale_cache_dummy)
- mov pc, lr
-
-/* ================================ TLB LOCKING==============================
- *
- * The XScale MicroArchitecture implements support for locking entries into
- * the Instruction and Data TLBs. The following functions provide the
- * low level support for supporting these under Linux. xscale-lock.c
- * implements some higher level management code. Most of the following
- * is taken straight out of the Developer's Manual.
- */
-
-/*
- * Lock I-TLB entry
- *
- * r0: Virtual address to translate and lock
- */
- .align 5
-ENTRY(xscale_itlb_lock)
- mrs r2, cpsr
- orr r3, r2, #PSR_F_BIT | PSR_I_BIT
- msr cpsr_c, r3 @ Disable interrupts
- mcr p15, 0, r0, c8, c5, 1 @ Invalidate I-TLB entry
- mcr p15, 0, r0, c10, c4, 0 @ Translate and lock
- msr cpsr_c, r2 @ Restore interrupts
- cpwait_ret lr, ip
-
-/*
- * Lock D-TLB entry
- *
- * r0: Virtual address to translate and lock
- */
- .align 5
-ENTRY(xscale_dtlb_lock)
- mrs r2, cpsr
- orr r3, r2, #PSR_F_BIT | PSR_I_BIT
- msr cpsr_c, r3 @ Disable interrupts
- mcr p15, 0, r0, c8, c6, 1 @ Invalidate D-TLB entry
- mcr p15, 0, r0, c10, c8, 0 @ Translate and lock
- msr cpsr_c, r2 @ Restore interrupts
- cpwait_ret lr, ip
-
-/*
- * Unlock all I-TLB entries
- */
- .align 5
-ENTRY(xscale_itlb_unlock)
- mcr p15, 0, ip, c10, c4, 1 @ Unlock I-TLB
- mcr p15, 0, ip, c8, c5, 0 @ Invalidate I-TLB
- cpwait_ret lr, ip
-
-/*
- * Unlock all D-TLB entries
- */
-ENTRY(xscale_dtlb_unlock)
- mcr p15, 0, ip, c10, c8, 1 @ Unlock D-TBL
- mcr p15, 0, ip, c8, c6, 0 @ Invalidate D-TLB
- cpwait_ret lr, ip
-
/* =============================== PageTable ============================== */
#define PTE_CACHE_WRITE_ALLOCATE 0
diff --git a/arch/arm/nwfpe/double_cpdo.c b/arch/arm/nwfpe/double_cpdo.c
index 7ffd8cb9bc9..c51d1386a97 100644
--- a/arch/arm/nwfpe/double_cpdo.c
+++ b/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(float64 rFn, float64 rFm)
+static float64 float64_rsf(struct roundingData *roundData, float64 rFn, float64 rFm)
{
- return float64_sub(rFm, rFn);
+ return float64_sub(roundData, rFm, rFn);
}
-static float64 float64_rdv(float64 rFn, float64 rFm)
+static float64 float64_rdv(struct roundingData *roundData, float64 rFn, float64 rFm)
{
- return float64_div(rFm, rFn);
+ return float64_div(roundData, rFm, rFn);
}
-static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = {
+static float64 (*const dyadic_double[16])(struct roundingData*, float64 rFn, float64 rFm) = {
[ADF_CODE >> 20] = float64_add,
[MUF_CODE >> 20] = float64_mul,
[SUF_CODE >> 20] = float64_sub,
@@ -65,12 +65,12 @@ static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = {
[FRD_CODE >> 20] = float64_rdv,
};
-static float64 float64_mvf(float64 rFm)
+static float64 float64_mvf(struct roundingData *roundData,float64 rFm)
{
return rFm;
}
-static float64 float64_mnf(float64 rFm)
+static float64 float64_mnf(struct roundingData *roundData,float64 rFm)
{
union float64_components u;
@@ -84,7 +84,7 @@ static float64 float64_mnf(float64 rFm)
return u.f64;
}
-static float64 float64_abs(float64 rFm)
+static float64 float64_abs(struct roundingData *roundData,float64 rFm)
{
union float64_components u;
@@ -98,7 +98,7 @@ static float64 float64_abs(float64 rFm)
return u.f64;
}
-static float64 (*const monadic_double[16])(float64 rFm) = {
+static float64 (*const monadic_double[16])(struct roundingData *, float64 rFm) = {
[MVF_CODE >> 20] = float64_mvf,
[MNF_CODE >> 20] = float64_mnf,
[ABS_CODE >> 20] = float64_abs,
@@ -108,7 +108,7 @@ static float64 (*const monadic_double[16])(float64 rFm) = {
[NRM_CODE >> 20] = float64_mvf,
};
-unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd)
+unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
{
FPA11 *fpa11 = GET_FPA11();
float64 rFm;
@@ -151,13 +151,13 @@ unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd)
}
if (dyadic_double[opc_mask_shift]) {
- rFd->fDouble = dyadic_double[opc_mask_shift](rFn, rFm);
+ rFd->fDouble = dyadic_double[opc_mask_shift](roundData, rFn, rFm);
} else {
return 0;
}
} else {
if (monadic_double[opc_mask_shift]) {
- rFd->fDouble = monadic_double[opc_mask_shift](rFm);
+ rFd->fDouble = monadic_double[opc_mask_shift](roundData, rFm);
} else {
return 0;
}
diff --git a/arch/arm/nwfpe/extended_cpdo.c b/arch/arm/nwfpe/extended_cpdo.c
index c39f68a3449..65a279ba927 100644
--- a/arch/arm/nwfpe/extended_cpdo.c
+++ b/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(floatx80 rFn, floatx80 rFm)
+static floatx80 floatx80_rsf(struct roundingData *roundData, floatx80 rFn, floatx80 rFm)
{
- return floatx80_sub(rFm, rFn);
+ return floatx80_sub(roundData, rFm, rFn);
}
-static floatx80 floatx80_rdv(floatx80 rFn, floatx80 rFm)
+static floatx80 floatx80_rdv(struct roundingData *roundData, floatx80 rFn, floatx80 rFm)
{
- return floatx80_div(rFm, rFn);
+ return floatx80_div(roundData, rFm, rFn);
}
-static floatx80 (*const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) = {
+static floatx80 (*const dyadic_extended[16])(struct roundingData*, floatx80 rFn, floatx80 rFm) = {
[ADF_CODE >> 20] = floatx80_add,
[MUF_CODE >> 20] = floatx80_mul,
[SUF_CODE >> 20] = floatx80_sub,
@@ -60,24 +60,24 @@ static floatx80 (*const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) = {
[FRD_CODE >> 20] = floatx80_rdv,
};
-static floatx80 floatx80_mvf(floatx80 rFm)
+static floatx80 floatx80_mvf(struct roundingData *roundData, floatx80 rFm)
{
return rFm;
}
-static floatx80 floatx80_mnf(floatx80 rFm)
+static floatx80 floatx80_mnf(struct roundingData *roundData, floatx80 rFm)
{
rFm.high ^= 0x8000;
return rFm;
}
-static floatx80 floatx80_abs(floatx80 rFm)
+static floatx80 floatx80_abs(struct roundingData *roundData, floatx80 rFm)
{
rFm.high &= 0x7fff;
return rFm;
}
-static floatx80 (*const monadic_extended[16])(floatx80 rFm) = {
+static floatx80 (*const monadic_extended[16])(struct roundingData*, floatx80 rFm) = {
[MVF_CODE >> 20] = floatx80_mvf,
[MNF_CODE >> 20] = floatx80_mnf,
[ABS_CODE >> 20] = floatx80_abs,
@@ -87,7 +87,7 @@ static floatx80 (*const monadic_extended[16])(floatx80 rFm) = {
[NRM_CODE >> 20] = floatx80_mvf,
};
-unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd)
+unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
{
FPA11 *fpa11 = GET_FPA11();
floatx80 rFm;
@@ -138,13 +138,13 @@ unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd)
}
if (dyadic_extended[opc_mask_shift]) {
- rFd->fExtended = dyadic_extended[opc_mask_shift](rFn, rFm);
+ rFd->fExtended = dyadic_extended[opc_mask_shift](roundData, rFn, rFm);
} else {
return 0;
}
} else {
if (monadic_extended[opc_mask_shift]) {
- rFd->fExtended = monadic_extended[opc_mask_shift](rFm);
+ rFd->fExtended = monadic_extended[opc_mask_shift](roundData, rFm);
} else {
return 0;
}
diff --git a/arch/arm/nwfpe/fpa11.c b/arch/arm/nwfpe/fpa11.c
index bf61696865e..7690f731ee8 100644
--- a/arch/arm/nwfpe/fpa11.c
+++ b/arch/arm/nwfpe/fpa11.c
@@ -51,48 +51,42 @@ static void resetFPA11(void)
fpa11->fpsr = FP_EMULATOR | BIT_AC;
}
-void SetRoundingMode(const unsigned int opcode)
+int8 SetRoundingMode(const unsigned int opcode)
{
switch (opcode & MASK_ROUNDING_MODE) {
default:
case ROUND_TO_NEAREST:
- float_rounding_mode = float_round_nearest_even;
- break;
+ return float_round_nearest_even;
case ROUND_TO_PLUS_INFINITY:
- float_rounding_mode = float_round_up;
- break;
+ return float_round_up;
case ROUND_TO_MINUS_INFINITY:
- float_rounding_mode = float_round_down;
- break;
+ return float_round_down;
case ROUND_TO_ZERO:
- float_rounding_mode = float_round_to_zero;
- break;
+ return float_round_to_zero;
}
}
-void SetRoundingPrecision(const unsigned int opcode)
+int8 SetRoundingPrecision(const unsigned int opcode)
{
#ifdef CONFIG_FPE_NWFPE_XP
switch (opcode & MASK_ROUNDING_PRECISION) {
case ROUND_SINGLE:
- floatx80_rounding_precision = 32;
- break;
+ return 32;
case ROUND_DOUBLE:
- floatx80_rounding_precision = 64;
- break;
+ return 64;
case ROUND_EXTENDED:
- floatx80_rounding_precision = 80;
- break;
+ return 80;
default:
- floatx80_rounding_precision = 80;
+ return 80;
}
#endif
+ return 80;
}
void nwfpe_init_fpa(union fp_state *fp)
@@ -103,8 +97,6 @@ void nwfpe_init_fpa(union fp_state *fp)
#endif
memset(fpa11, 0, sizeof(FPA11));
resetFPA11();
- SetRoundingMode(ROUND_TO_NEAREST);
- SetRoundingPrecision(ROUND_EXTENDED);
fpa11->initflag = 1;
}
diff --git a/arch/arm/nwfpe/fpa11.h b/arch/arm/nwfpe/fpa11.h
index e4a61aea534..93523ae4b7a 100644
--- a/arch/arm/nwfpe/fpa11.h
+++ b/arch/arm/nwfpe/fpa11.h
@@ -37,6 +37,13 @@
/* includes */
#include "fpsr.h" /* FP control and status register definitions */
#include "milieu.h"
+
+struct roundingData {
+ int8 mode;
+ int8 precision;
+ signed char exception;
+};
+
#include "softfloat.h"
#define typeNone 0x00
@@ -84,8 +91,8 @@ typedef struct tagFPA11 {
initialised. */
} FPA11;
-extern void SetRoundingMode(const unsigned int);
-extern void SetRoundingPrecision(const unsigned int);
+extern int8 SetRoundingMode(const unsigned int);
+extern int8 SetRoundingPrecision(const unsigned int);
extern void nwfpe_init_fpa(union fp_state *fp);
#endif
diff --git a/arch/arm/nwfpe/fpa11_cpdo.c b/arch/arm/nwfpe/fpa11_cpdo.c
index 1bea67437b6..4a31dfd9406 100644
--- a/arch/arm/nwfpe/fpa11_cpdo.c
+++ b/arch/arm/nwfpe/fpa11_cpdo.c
@@ -24,15 +24,16 @@
#include "fpa11.h"
#include "fpopcode.h"
-unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd);
-unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd);
-unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd);
+unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
+unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
+unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
unsigned int EmulateCPDO(const unsigned int opcode)
{
FPA11 *fpa11 = GET_FPA11();
FPREG *rFd;
unsigned int nType, nDest, nRc;
+ struct roundingData roundData;
/* Get the destination size. If not valid let Linux perform
an invalid instruction trap. */
@@ -40,7 +41,9 @@ unsigned int EmulateCPDO(const unsigned int opcode)
if (typeNone == nDest)
return 0;
- SetRoundingMode(opcode);
+ roundData.mode = SetRoundingMode(opcode);
+ roundData.precision = SetRoundingPrecision(opcode);
+ roundData.exception = 0;
/* Compare the size of the operands in Fn and Fm.
Choose the largest size and perform operations in that size,
@@ -63,14 +66,14 @@ unsigned int EmulateCPDO(const unsigned int opcode)
switch (nType) {
case typeSingle:
- nRc = SingleCPDO(opcode, rFd);
+ nRc = SingleCPDO(&roundData, opcode, rFd);
break;
case typeDouble:
- nRc = DoubleCPDO(opcode, rFd);
+ nRc = DoubleCPDO(&roundData, opcode, rFd);
break;
#ifdef CONFIG_FPE_NWFPE_XP
case typeExtended:
- nRc = ExtendedCPDO(opcode, rFd);
+ nRc = ExtendedCPDO(&roundData, opcode, rFd);
break;
#endif
default:
@@ -93,9 +96,9 @@ unsigned int EmulateCPDO(const unsigned int opcode)
case typeSingle:
{
if (typeDouble == nType)
- rFd->fSingle = float64_to_float32(rFd->fDouble);
+ rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);
else
- rFd->fSingle = floatx80_to_float32(rFd->fExtended);
+ rFd->fSingle = floatx80_to_float32(&roundData, rFd->fExtended);
}
break;
@@ -104,7 +107,7 @@ unsigned int EmulateCPDO(const unsigned int opcode)
if (typeSingle == nType)
rFd->fDouble = float32_to_float64(rFd->fSingle);
else
- rFd->fDouble = floatx80_to_float64(rFd->fExtended);
+ rFd->fDouble = floatx80_to_float64(&roundData, rFd->fExtended);
}
break;
@@ -121,12 +124,15 @@ unsigned int EmulateCPDO(const unsigned int opcode)
#else
if (nDest != nType) {
if (nDest == typeSingle)
- rFd->fSingle = float64_to_float32(rFd->fDouble);
+ rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);
else
rFd->fDouble = float32_to_float64(rFd->fSingle);
}
#endif
}
+ if (roundData.exception)
+ float_raise(roundData.exception);
+
return nRc;
}
diff --git a/arch/arm/nwfpe/fpa11_cpdt.c b/arch/arm/nwfpe/fpa11_cpdt.c
index 95fb63fa9d1..b0db5cbcc3b 100644
--- a/arch/arm/nwfpe/fpa11_cpdt.c
+++ b/arch/arm/nwfpe/fpa11_cpdt.c
@@ -96,7 +96,7 @@ static inline void loadMultiple(const unsigned int Fn, const unsigned int __user
}
}
-static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem)
+static inline void storeSingle(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
{
FPA11 *fpa11 = GET_FPA11();
union {
@@ -106,12 +106,12 @@ static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem)
switch (fpa11->fType[Fn]) {
case typeDouble:
- val.f = float64_to_float32(fpa11->fpreg[Fn].fDouble);
+ val.f = float64_to_float32(roundData, fpa11->fpreg[Fn].fDouble);
break;
#ifdef CONFIG_FPE_NWFPE_XP
case typeExtended:
- val.f = floatx80_to_float32(fpa11->fpreg[Fn].fExtended);
+ val.f = floatx80_to_float32(roundData, fpa11->fpreg[Fn].fExtended);
break;
#endif
@@ -122,7 +122,7 @@ static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem)
put_user(val.i[0], pMem);
}
-static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem)
+static inline void storeDouble(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
{
FPA11 *fpa11 = GET_FPA11();
union {
@@ -137,7 +137,7 @@ static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem)
#ifdef CONFIG_FPE_NWFPE_XP
case typeExtended:
- val.f = floatx80_to_float64(fpa11->fpreg[Fn].fExtended);
+ val.f = floatx80_to_float64(roundData, fpa11->fpreg[Fn].fExtended);
break;
#endif
@@ -259,8 +259,11 @@ unsigned int PerformSTF(const unsigned int opcode)
{
unsigned int __user *pBase, *pAddress, *pFinal;
unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
+ struct roundingData roundData;
- SetRoundingMode(ROUND_TO_NEAREST);
+ roundData.mode = SetRoundingMode(opcode);
+ roundData.precision = SetRoundingPrecision(opcode);
+ roundData.exception = 0;
pBase = (unsigned int __user *) readRegister(getRn(opcode));
if (REG_PC == getRn(opcode)) {
@@ -281,10 +284,10 @@ unsigned int PerformSTF(const unsigned int opcode)
switch (opcode & MASK_TRANSFER_LENGTH) {
case TRANSFER_SINGLE:
- storeSingle(getFd(opcode), pAddress);
+ storeSingle(&roundData, getFd(opcode), pAddress);
break;
case TRANSFER_DOUBLE:
- storeDouble(getFd(opcode), pAddress);
+ storeDouble(&roundData, getFd(opcode), pAddress);
break;
#ifdef CONFIG_FPE_NWFPE_XP
case TRANSFER_EXTENDED:
@@ -295,6 +298,9 @@ unsigned int PerformSTF(const unsigned int opcode)
nRc = 0;
}
+ if (roundData.exception)
+ float_raise(roundData.exception);
+
if (write_back)
writeRegister(getRn(opcode), (unsigned long) pFinal);
return nRc;
diff --git a/arch/arm/nwfpe/fpa11_cprt.c b/arch/arm/nwfpe/fpa11_cprt.c
index db01fbc9721..adf8d300054 100644
--- a/arch/arm/nwfpe/fpa11_cprt.c
+++ b/arch/arm/nwfpe/fpa11_cprt.c
@@ -33,8 +33,6 @@ extern flag floatx80_is_nan(floatx80);
extern flag float64_is_nan(float64);
extern flag float32_is_nan(float32);
-void SetRoundingMode(const unsigned int opcode);
-
unsigned int PerformFLT(const unsigned int opcode);
unsigned int PerformFIX(const unsigned int opcode);
@@ -77,14 +75,17 @@ unsigned int EmulateCPRT(const unsigned int opcode)
unsigned int PerformFLT(const unsigned int opcode)
{
FPA11 *fpa11 = GET_FPA11();
- SetRoundingMode(opcode);
- SetRoundingPrecision(opcode);
+ struct roundingData roundData;
+
+ roundData.mode = SetRoundingMode(opcode);
+ roundData.precision = SetRoundingPrecision(opcode);
+ roundData.exception = 0;
switch (opcode & MASK_ROUNDING_PRECISION) {
case ROUND_SINGLE:
{
fpa11->fType[getFn(opcode)] = typeSingle;
- fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(readRegister(getRd(opcode)));
+ fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(&roundData, readRegister(getRd(opcode)));
}
break;
@@ -108,6 +109,9 @@ unsigned int PerformFLT(const unsigned int opcode)
return 0;
}
+ if (roundData.exception)
+ float_raise(roundData.exception);
+
return 1;
}
@@ -115,26 +119,29 @@ unsigned int PerformFIX(const unsigned int opcode)
{
FPA11 *fpa11 = GET_FPA11();
unsigned int Fn = getFm(opcode);
+ struct roundingData roundData;
- SetRoundingMode(opcode);
+ roundData.mode = SetRoundingMode(opcode);
+ roundData.precision = SetRoundingPrecision(opcode);
+ roundData.exception = 0;
switch (fpa11->fType[Fn]) {
case typeSingle:
{
- writeRegister(getRd(opcode), float32_to_int32(fpa11->fpreg[Fn].fSingle));
+ writeRegister(getRd(opcode), float32_to_int32(&roundData, fpa11->fpreg[Fn].fSingle));
}
break;
case typeDouble:
{
- writeRegister(getRd(opcode), float64_to_int32(fpa11->fpreg[Fn].fDouble));
+ writeRegister(getRd(opcode), float64_to_int32(&roundData, fpa11->fpreg[Fn].fDouble));
}
break;
#ifdef CONFIG_FPE_NWFPE_XP
case typeExtended:
{
- writeRegister(getRd(opcode), floatx80_to_int32(fpa11->fpreg[Fn].fExtended));
+ writeRegister(getRd(opcode), floatx80_to_int32(&roundData, fpa11->fpreg[Fn].fExtended));
}
break;
#endif
@@ -143,6 +150,9 @@ unsigned int PerformFIX(const unsigned int opcode)
return 0;
}
+ if (roundData.exception)
+ float_raise(roundData.exception);
+
return 1;
}
diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c
index 12885f31d34..2dfe1ac42ee 100644
--- a/arch/arm/nwfpe/fpmodule.c
+++ b/arch/arm/nwfpe/fpmodule.c
@@ -116,8 +116,6 @@ fpmodule.c to integrate with the NetBSD kernel (I hope!).
code to access data in user space in some other source files at the
moment (grep for get_user / put_user calls). --philb]
-float_exception_flags is a global variable in SoftFloat.
-
This function is called by the SoftFloat routines to raise a floating
point exception. We check the trap enable byte in the FPSR, and raise
a SIGFPE exception if necessary. If not the relevant bits in the
@@ -129,15 +127,14 @@ void float_raise(signed char flags)
register unsigned int fpsr, cumulativeTraps;
#ifdef CONFIG_DEBUG_USER
- printk(KERN_DEBUG
- "NWFPE: %s[%d] takes exception %08x at %p from %08lx\n",
- current->comm, current->pid, flags,
- __builtin_return_address(0), GET_USERREG()->ARM_pc);
+ /* Ignore inexact errors as there are far too many of them to log */
+ if (flags & ~BIT_IXC)
+ printk(KERN_DEBUG
+ "NWFPE: %s[%d] takes exception %08x at %p from %08lx\n",
+ current->comm, current->pid, flags,
+ __builtin_return_address(0), GET_USERREG()->ARM_pc);
#endif
- /* Keep SoftFloat exception flags up to date. */
- float_exception_flags |= flags;
-
/* Read fpsr and initialize the cumulativeTraps. */
fpsr = readFPSR();
cumulativeTraps = 0;
diff --git a/arch/arm/nwfpe/single_cpdo.c b/arch/arm/nwfpe/single_cpdo.c
index 705808e88d9..c66981d682c 100644
--- a/arch/arm/nwfpe/single_cpdo.c
+++ b/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(float32 rFn, float32 rFm)
+static float32 float32_rsf(struct roundingData *roundData, float32 rFn, float32 rFm)
{
- return float32_sub(rFm, rFn);
+ return float32_sub(roundData, rFm, rFn);
}
-static float32 float32_rdv(float32 rFn, float32 rFm)
+static float32 float32_rdv(struct roundingData *roundData, float32 rFn, float32 rFm)
{
- return float32_div(rFm, rFn);
+ return float32_div(roundData, rFm, rFn);
}
-static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = {
+static float32 (*const dyadic_single[16])(struct roundingData *, float32 rFn, float32 rFm) = {
[ADF_CODE >> 20] = float32_add,
[MUF_CODE >> 20] = float32_mul,
[SUF_CODE >> 20] = float32_sub,
@@ -60,22 +60,22 @@ static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = {
[FRD_CODE >> 20] = float32_rdv,
};
-static float32 float32_mvf(float32 rFm)
+static float32 float32_mvf(struct roundingData *roundData, float32 rFm)
{
return rFm;
}
-static float32 float32_mnf(float32 rFm)
+static float32 float32_mnf(struct roundingData *roundData, float32 rFm)
{
return rFm ^ 0x80000000;
}
-static float32 float32_abs(float32 rFm)
+static float32 float32_abs(struct roundingData *roundData, float32 rFm)
{
return rFm & 0x7fffffff;
}
-static float32 (*const monadic_single[16])(float32 rFm) = {
+static float32 (*const monadic_single[16])(struct roundingData*, float32 rFm) = {
[MVF_CODE >> 20] = float32_mvf,
[MNF_CODE >> 20] = float32_mnf,
[ABS_CODE >> 20] = float32_abs,
@@ -85,7 +85,7 @@ static float32 (*const monadic_single[16])(float32 rFm) = {
[NRM_CODE >> 20] = float32_mvf,
};
-unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd)
+unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
{
FPA11 *fpa11 = GET_FPA11();
float32 rFm;
@@ -108,13 +108,13 @@ unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd)
if (fpa11->fType[Fn] == typeSingle &&
dyadic_single[opc_mask_shift]) {
rFn = fpa11->fpreg[Fn].fSingle;
- rFd->fSingle = dyadic_single[opc_mask_shift](rFn, rFm);
+ rFd->fSingle = dyadic_single[opc_mask_shift](roundDat