diff --git a/[refs] b/[refs] index deef992e2e70..c5c13f2897a0 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 09f3eca2b7e2762e223fdd359f9d0f6303a85f6c +refs/heads/master: 561d9a969455cb009bb15b63e1d925dc527e7a9d diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index f3d7256bc74e..2bbe40ea4d10 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -1681,7 +1681,8 @@ S: Maintained HARMONY SOUND DRIVER P: Kyle McMartin M: kyle@parisc-linux.org -L: linux-parisc@vger.kernel.org +W: http://www.parisc-linux.org/~kyle/harmony/ +L: parisc-linux@lists.parisc-linux.org S: Maintained HAYES ESP SERIAL DRIVER @@ -2597,6 +2598,13 @@ L: https://tango.0pointer.de/mailman/listinfo/s270-linux W: http://0pointer.de/lennart/tchibo.html S: Maintained +MTRR AND SIMILAR SUPPORT [i386] +P: Richard Gooch +M: rgooch@atnf.csiro.au +L: linux-kernel@vger.kernel.org +W: http://www.atnf.csiro.au/~rgooch/linux/kernel-patches.html +S: Maintained + MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM P: Pierre Ossman M: drzeus-mmc@drzeus.cx @@ -2889,15 +2897,16 @@ W: http://www.torque.net/linux-pp.html S: Maintained PARISC ARCHITECTURE -P: Kyle McMartin -M: kyle@parisc-linux.org P: Matthew Wilcox M: matthew@wil.cx P: Grant Grundler M: grundler@parisc-linux.org -L: linux-parisc@vger.kernel.org +P: Kyle McMartin +M: kyle@parisc-linux.org +L: parisc-linux@parisc-linux.org W: http://www.parisc-linux.org/ T: git kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6.git +T: cvs cvs.parisc-linux.org:/var/cvs/linux-2.6 S: Maintained PARAVIRT_OPS INTERFACE diff --git a/trunk/arch/mips/Kconfig b/trunk/arch/mips/Kconfig index c6fc405a6c8e..455bd1f560aa 100644 --- a/trunk/arch/mips/Kconfig +++ b/trunk/arch/mips/Kconfig @@ -714,10 +714,6 @@ config ARCH_HAS_ILOG2_U64 bool default n -config ARCH_SUPPORTS_OPROFILE - bool - default y if !MIPS_MT_SMTC - config GENERIC_FIND_NEXT_BIT bool default y diff --git a/trunk/arch/mips/au1000/common/dbdma.c b/trunk/arch/mips/au1000/common/dbdma.c index edf91f41a786..9d6ad43fded6 100644 --- a/trunk/arch/mips/au1000/common/dbdma.c +++ b/trunk/arch/mips/au1000/common/dbdma.c @@ -859,7 +859,7 @@ dbdma_interrupt(int irq, void *dev_id) intstat = dbdma_gptr->ddma_intstat; au_sync(); - chan_index = __ffs(intstat); + chan_index = ffs(intstat); ctp = chan_tab_ptr[chan_index]; cp = ctp->chan_ptr; diff --git a/trunk/arch/mips/au1000/common/irq.c b/trunk/arch/mips/au1000/common/irq.c index 3c7714f057ac..ddfb7f0a17a6 100644 --- a/trunk/arch/mips/au1000/common/irq.c +++ b/trunk/arch/mips/au1000/common/irq.c @@ -462,9 +462,9 @@ static void intc0_req0_irqdispatch(void) return; } #endif - bit = __ffs(intc0_req0); + bit = ffs(intc0_req0); intc0_req0 &= ~(1 << bit); - do_IRQ(AU1000_INTC0_INT_BASE + bit); + do_IRQ(MIPS_CPU_IRQ_BASE + bit); } @@ -478,9 +478,9 @@ static void intc0_req1_irqdispatch(void) if (!intc0_req1) return; - bit = __ffs(intc0_req1); + bit = ffs(intc0_req1); intc0_req1 &= ~(1 << bit); - do_IRQ(AU1000_INTC0_INT_BASE + bit); + do_IRQ(bit); } @@ -498,9 +498,9 @@ static void intc1_req0_irqdispatch(void) if (!intc1_req0) return; - bit = __ffs(intc1_req0); + bit = ffs(intc1_req0); intc1_req0 &= ~(1 << bit); - do_IRQ(AU1000_INTC1_INT_BASE + bit); + do_IRQ(MIPS_CPU_IRQ_BASE + 32 + bit); } @@ -514,9 +514,9 @@ static void intc1_req1_irqdispatch(void) if (!intc1_req1) return; - bit = __ffs(intc1_req1); + bit = ffs(intc1_req1); intc1_req1 &= ~(1 << bit); - do_IRQ(AU1000_INTC1_INT_BASE + bit); + do_IRQ(MIPS_CPU_IRQ_BASE + 32 + bit); } asmlinkage void plat_irq_dispatch(void) diff --git a/trunk/arch/mips/au1000/pb1200/irqmap.c b/trunk/arch/mips/au1000/pb1200/irqmap.c index 8fcd0df86f93..c096be4ed4e7 100644 --- a/trunk/arch/mips/au1000/pb1200/irqmap.c +++ b/trunk/arch/mips/au1000/pb1200/irqmap.c @@ -74,7 +74,7 @@ irqreturn_t pb1200_cascade_handler( int irq, void *dev_id) bcsr->int_status = bisr; for( ; bisr; bisr &= (bisr-1) ) { - extirq_nr = PB1200_INT_BEGIN + __ffs(bisr); + extirq_nr = PB1200_INT_BEGIN + ffs(bisr); /* Ack and dispatch IRQ */ do_IRQ(extirq_nr); } diff --git a/trunk/arch/mips/oprofile/op_model_mipsxx.c b/trunk/arch/mips/oprofile/op_model_mipsxx.c index bdfa07aecd97..423bc2c473df 100644 --- a/trunk/arch/mips/oprofile/op_model_mipsxx.c +++ b/trunk/arch/mips/oprofile/op_model_mipsxx.c @@ -6,7 +6,6 @@ * Copyright (C) 2004, 05, 06 by Ralf Baechle * Copyright (C) 2005 by MIPS Technologies, Inc. */ -#include #include #include #include @@ -34,45 +33,11 @@ #ifdef CONFIG_MIPS_MT_SMP #define WHAT (M_TC_EN_VPE | M_PERFCTL_VPEID(smp_processor_id())) #define vpe_id() smp_processor_id() - -/* - * The number of bits to shift to convert between counters per core and - * counters per VPE. There is no reasonable interface atm to obtain the - * number of VPEs used by Linux and in the 34K this number is fixed to two - * anyways so we hardcore a few things here for the moment. The way it's - * done here will ensure that oprofile VSMP kernel will run right on a lesser - * core like a 24K also or with maxcpus=1. - */ -static inline unsigned int vpe_shift(void) -{ - if (num_possible_cpus() > 1) - return 1; - - return 0; -} - #else - #define WHAT 0 #define vpe_id() 0 - -static inline unsigned int vpe_shift(void) -{ - return 0; -} - #endif -static inline unsigned int counters_total_to_per_cpu(unsigned int counters) -{ - return counters >> vpe_shift(); -} - -static inline unsigned int counters_per_cpu_to_total(unsigned int counters) -{ - return counters << vpe_shift(); -} - #define __define_perf_accessors(r, n, np) \ \ static inline unsigned int r_c0_ ## r ## n(void) \ @@ -304,7 +269,9 @@ static int __init mipsxx_init(void) reset_counters(counters); - counters = counters_total_to_per_cpu(counters); +#ifdef CONFIG_MIPS_MT_SMP + counters >>= 1; +#endif op_model_mipsxx_ops.num_counters = counters; switch (current_cpu_type()) { @@ -363,8 +330,9 @@ static int __init mipsxx_init(void) static void mipsxx_exit(void) { int counters = op_model_mipsxx_ops.num_counters; - - counters = counters_per_cpu_to_total(counters); +#ifdef CONFIG_MIPS_MT_SMP + counters <<= 1; +#endif reset_counters(counters); perf_irq = null_perf_irq; diff --git a/trunk/arch/mips/pci/pci-bcm1480.c b/trunk/arch/mips/pci/pci-bcm1480.c index 47f316c86ab1..bc647cb77298 100644 --- a/trunk/arch/mips/pci/pci-bcm1480.c +++ b/trunk/arch/mips/pci/pci-bcm1480.c @@ -76,10 +76,7 @@ static inline void WRITECFG32(u32 addr, u32 data) int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { - if (pin == 0) - return -1; - - return K_BCM1480_INT_PCI_INTA - 1 + pin; + return K_BCM1480_INT_PCI_INTA + pin; } /* Do platform specific device initialization at pci_enable_device() time */ diff --git a/trunk/arch/parisc/Makefile b/trunk/arch/parisc/Makefile index e574de4efb36..ae4a9b3d4fd6 100644 --- a/trunk/arch/parisc/Makefile +++ b/trunk/arch/parisc/Makefile @@ -70,7 +70,7 @@ kernel-y := mm/ kernel/ math-emu/ kernel/init_task.o kernel-$(CONFIG_HPUX) += hpux/ core-y += $(addprefix arch/parisc/, $(kernel-y)) -libs-y += arch/parisc/lib/ `$(CC) -print-libgcc-file-name` +libs-y += arch/parisc/lib/ drivers-$(CONFIG_OPROFILE) += arch/parisc/oprofile/ diff --git a/trunk/arch/parisc/kernel/firmware.c b/trunk/arch/parisc/kernel/firmware.c index 4ab83d56974d..fd6552c4c08c 100644 --- a/trunk/arch/parisc/kernel/firmware.c +++ b/trunk/arch/parisc/kernel/firmware.c @@ -1082,56 +1082,76 @@ void pdc_io_reset_devices(void) /** - * pdc_iodc_print - Console print using IODC. - * @str: the string to output. - * @count: length of str + * pdc_iodc_putc - Console character print using IODC. + * @c: the character to output. * * Note that only these special chars are architected for console IODC io: * BEL, BS, CR, and LF. Others are passed through. * Since the HP console requires CR+LF to perform a 'newline', we translate * "\n" to "\r\n". */ -int pdc_iodc_print(unsigned char *str, unsigned count) +void pdc_iodc_putc(unsigned char c) { - /* XXX Should we spinlock posx usage */ - static int posx; /* for simple TAB-Simulation... */ - int __attribute__((aligned(8))) iodc_retbuf[32]; - char __attribute__((aligned(64))) iodc_dbuf[4096]; - unsigned int i; + /* XXX Should we spinlock posx usage */ + static int posx; /* for simple TAB-Simulation... */ + static int __attribute__((aligned(8))) iodc_retbuf[32]; + static char __attribute__((aligned(64))) iodc_dbuf[4096]; + unsigned int n; unsigned long flags; - memset(iodc_dbuf, 0, 4096); - for (i = 0; i < count && i < 2048;) { - switch(str[i]) { - case '\n': - iodc_dbuf[i+0] = '\r'; - iodc_dbuf[i+1] = '\n'; - i += 2; - posx = 0; - break; - case '\t': - while (posx & 7) { - iodc_dbuf[i] = ' '; - i++, posx++; - } - break; - case '\b': /* BS */ - posx -= 2; - default: - iodc_dbuf[i] = str[i]; - i++, posx++; - break; - } - } + switch (c) { + case '\n': + iodc_dbuf[0] = '\r'; + iodc_dbuf[1] = '\n'; + n = 2; + posx = 0; + break; + case '\t': + pdc_iodc_putc(' '); + while (posx & 7) /* expand TAB */ + pdc_iodc_putc(' '); + return; /* return since IODC can't handle this */ + case '\b': + posx-=2; /* BS */ + default: + iodc_dbuf[0] = c; + n = 1; + posx++; + break; + } spin_lock_irqsave(&pdc_lock, flags); real32_call(PAGE0->mem_cons.iodc_io, (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT, PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers), - __pa(iodc_retbuf), 0, __pa(iodc_dbuf), i, 0); + __pa(iodc_retbuf), 0, __pa(iodc_dbuf), n, 0); spin_unlock_irqrestore(&pdc_lock, flags); +} - return i; +/** + * pdc_iodc_outc - Console character print using IODC (without conversions). + * @c: the character to output. + * + * Write the character directly to the IODC console. + */ +void pdc_iodc_outc(unsigned char c) +{ + unsigned int n; + unsigned long flags; + + /* fill buffer with one caracter and print it */ + static int __attribute__((aligned(8))) iodc_retbuf[32]; + static char __attribute__((aligned(64))) iodc_dbuf[4096]; + + n = 1; + iodc_dbuf[0] = c; + + spin_lock_irqsave(&pdc_lock, flags); + real32_call(PAGE0->mem_cons.iodc_io, + (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT, + PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers), + __pa(iodc_retbuf), 0, __pa(iodc_dbuf), n, 0); + spin_unlock_irqrestore(&pdc_lock, flags); } /** diff --git a/trunk/arch/parisc/kernel/irq.c b/trunk/arch/parisc/kernel/irq.c index 23ef950df008..76ce5e3b0050 100644 --- a/trunk/arch/parisc/kernel/irq.c +++ b/trunk/arch/parisc/kernel/irq.c @@ -397,7 +397,7 @@ static void claim_cpu_irqs(void) } irq_desc[TIMER_IRQ].action = &timer_action; - irq_desc[TIMER_IRQ].status = IRQ_PER_CPU; + irq_desc[TIMER_IRQ].status |= IRQ_PER_CPU; #ifdef CONFIG_SMP irq_desc[IPI_IRQ].action = &ipi_action; irq_desc[IPI_IRQ].status = IRQ_PER_CPU; diff --git a/trunk/arch/parisc/kernel/parisc_ksyms.c b/trunk/arch/parisc/kernel/parisc_ksyms.c index 7aca704e96f0..671ee5b9950c 100644 --- a/trunk/arch/parisc/kernel/parisc_ksyms.c +++ b/trunk/arch/parisc/kernel/parisc_ksyms.c @@ -122,31 +122,9 @@ EXPORT_SYMBOL($$divI_12); EXPORT_SYMBOL($$divI_14); EXPORT_SYMBOL($$divI_15); -extern void __ashrdi3(void); -extern void __ashldi3(void); -extern void __lshrdi3(void); -extern void __muldi3(void); - -EXPORT_SYMBOL(__ashrdi3); -EXPORT_SYMBOL(__ashldi3); -EXPORT_SYMBOL(__lshrdi3); -EXPORT_SYMBOL(__muldi3); - asmlinkage void * __canonicalize_funcptr_for_compare(void *); EXPORT_SYMBOL(__canonicalize_funcptr_for_compare); -#ifdef CONFIG_64BIT -extern void __divdi3(void); -extern void __udivdi3(void); -extern void __umoddi3(void); -extern void __moddi3(void); - -EXPORT_SYMBOL(__divdi3); -EXPORT_SYMBOL(__udivdi3); -EXPORT_SYMBOL(__umoddi3); -EXPORT_SYMBOL(__moddi3); -#endif - #ifndef CONFIG_64BIT extern void $$dyncall(void); EXPORT_SYMBOL($$dyncall); diff --git a/trunk/arch/parisc/kernel/pdc_cons.c b/trunk/arch/parisc/kernel/pdc_cons.c index 33b1f84441b1..aab05767427c 100644 --- a/trunk/arch/parisc/kernel/pdc_cons.c +++ b/trunk/arch/parisc/kernel/pdc_cons.c @@ -55,7 +55,13 @@ static void pdc_console_write(struct console *co, const char *s, unsigned count) { - pdc_iodc_print(s, count); + while(count--) + pdc_iodc_putc(*s++); +} + +void pdc_outc(unsigned char c) +{ + pdc_iodc_outc(c); } void pdc_printf(const char *fmt, ...) @@ -68,7 +74,8 @@ void pdc_printf(const char *fmt, ...) len = vscnprintf(buf, sizeof(buf), fmt, args); va_end(args); - pdc_iodc_print(buf, len); + for (i = 0; i < len; i++) + pdc_iodc_outc(buf[i]); } int pdc_console_poll_key(struct console *co) diff --git a/trunk/arch/parisc/lib/Makefile b/trunk/arch/parisc/lib/Makefile index 5f2e6904d14a..7ce406c7daf5 100644 --- a/trunk/arch/parisc/lib/Makefile +++ b/trunk/arch/parisc/lib/Makefile @@ -4,4 +4,4 @@ lib-y := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o memcpy.o -obj-y := iomap.o +obj-y := libgcc/ milli/ iomap.o diff --git a/trunk/arch/parisc/lib/libgcc/Makefile b/trunk/arch/parisc/lib/libgcc/Makefile new file mode 100644 index 000000000000..b67a85ad9c87 --- /dev/null +++ b/trunk/arch/parisc/lib/libgcc/Makefile @@ -0,0 +1,4 @@ +obj-y := __ashldi3.o __ashrdi3.o __clzsi2.o __divdi3.o __divsi3.o \ + __lshrdi3.o __moddi3.o __modsi3.o __udivdi3.o \ + __udivmoddi4.o __udivmodsi4.o __udivsi3.o \ + __umoddi3.o __umodsi3.o __muldi3.o __umulsidi3.o diff --git a/trunk/arch/parisc/lib/libgcc/__ashldi3.c b/trunk/arch/parisc/lib/libgcc/__ashldi3.c new file mode 100644 index 000000000000..a14a257abb2b --- /dev/null +++ b/trunk/arch/parisc/lib/libgcc/__ashldi3.c @@ -0,0 +1,19 @@ +#include "libgcc.h" + +u64 __ashldi3(u64 v, int cnt) +{ + int c = cnt & 31; + u32 vl = (u32) v; + u32 vh = (u32) (v >> 32); + + if (cnt & 32) { + vh = (vl << c); + vl = 0; + } else { + vh = (vh << c) + (vl >> (32 - c)); + vl = (vl << c); + } + + return ((u64) vh << 32) + vl; +} +EXPORT_SYMBOL(__ashldi3); diff --git a/trunk/arch/parisc/lib/libgcc/__ashrdi3.c b/trunk/arch/parisc/lib/libgcc/__ashrdi3.c new file mode 100644 index 000000000000..8636a5aa4f77 --- /dev/null +++ b/trunk/arch/parisc/lib/libgcc/__ashrdi3.c @@ -0,0 +1,19 @@ +#include "libgcc.h" + +u64 __ashrdi3(u64 v, int cnt) +{ + int c = cnt & 31; + u32 vl = (u32) v; + u32 vh = (u32) (v >> 32); + + if (cnt & 32) { + vl = ((s32) vh >> c); + vh = (s32) vh >> 31; + } else { + vl = (vl >> c) + (vh << (32 - c)); + vh = ((s32) vh >> c); + } + + return ((u64) vh << 32) + vl; +} +EXPORT_SYMBOL(__ashrdi3); diff --git a/trunk/arch/parisc/lib/libgcc/__clzsi2.c b/trunk/arch/parisc/lib/libgcc/__clzsi2.c new file mode 100644 index 000000000000..a7aa2f55a9c6 --- /dev/null +++ b/trunk/arch/parisc/lib/libgcc/__clzsi2.c @@ -0,0 +1,30 @@ +#include "libgcc.h" + +u32 __clzsi2(u32 v) +{ + int p = 31; + + if (v & 0xffff0000) { + p -= 16; + v >>= 16; + } + if (v & 0xff00) { + p -= 8; + v >>= 8; + } + if (v & 0xf0) { + p -= 4; + v >>= 4; + } + if (v & 0xc) { + p -= 2; + v >>= 2; + } + if (v & 0x2) { + p -= 1; + v >>= 1; + } + + return p; +} +EXPORT_SYMBOL(__clzsi2); diff --git a/trunk/arch/parisc/lib/libgcc/__divdi3.c b/trunk/arch/parisc/lib/libgcc/__divdi3.c new file mode 100644 index 000000000000..f23c6fe2838b --- /dev/null +++ b/trunk/arch/parisc/lib/libgcc/__divdi3.c @@ -0,0 +1,23 @@ +#include "libgcc.h" + +s64 __divdi3(s64 num, s64 den) +{ + int minus = 0; + s64 v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + v = __udivmoddi4(num, den, NULL); + if (minus) + v = -v; + + return v; +} +EXPORT_SYMBOL(__divdi3); diff --git a/trunk/arch/parisc/lib/libgcc/__divsi3.c b/trunk/arch/parisc/lib/libgcc/__divsi3.c new file mode 100644 index 000000000000..730fb530680d --- /dev/null +++ b/trunk/arch/parisc/lib/libgcc/__divsi3.c @@ -0,0 +1,23 @@ +#include "libgcc.h" + +s32 __divsi3(s32 num, s32 den) +{ + int minus = 0; + s32 v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + v = __udivmodsi4(num, den, NULL); + if (minus) + v = -v; + + return v; +} +EXPORT_SYMBOL(__divsi3); diff --git a/trunk/arch/parisc/lib/libgcc/__lshrdi3.c b/trunk/arch/parisc/lib/libgcc/__lshrdi3.c new file mode 100644 index 000000000000..4a820708ec57 --- /dev/null +++ b/trunk/arch/parisc/lib/libgcc/__lshrdi3.c @@ -0,0 +1,19 @@ +#include "libgcc.h" + +u64 __lshrdi3(u64 v, int cnt) +{ + int c = cnt & 31; + u32 vl = (u32) v; + u32 vh = (u32) (v >> 32); + + if (cnt & 32) { + vl = (vh >> c); + vh = 0; + } else { + vl = (vl >> c) + (vh << (32 - c)); + vh = (vh >> c); + } + + return ((u64) vh << 32) + vl; +} +EXPORT_SYMBOL(__lshrdi3); diff --git a/trunk/arch/parisc/lib/libgcc/__moddi3.c b/trunk/arch/parisc/lib/libgcc/__moddi3.c new file mode 100644 index 000000000000..ed64bbafc989 --- /dev/null +++ b/trunk/arch/parisc/lib/libgcc/__moddi3.c @@ -0,0 +1,23 @@ +#include "libgcc.h" + +s64 __moddi3(s64 num, s64 den) +{ + int minus = 0; + s64 v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + (void)__udivmoddi4(num, den, (u64 *) & v); + if (minus) + v = -v; + + return v; +} +EXPORT_SYMBOL(__moddi3); diff --git a/trunk/arch/parisc/lib/libgcc/__modsi3.c b/trunk/arch/parisc/lib/libgcc/__modsi3.c new file mode 100644 index 000000000000..62f773efaeea --- /dev/null +++ b/trunk/arch/parisc/lib/libgcc/__modsi3.c @@ -0,0 +1,23 @@ +#include "libgcc.h" + +s32 __modsi3(s32 num, s32 den) +{ + int minus = 0; + s32 v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + (void)__udivmodsi4(num, den, (u32 *) & v); + if (minus) + v = -v; + + return v; +} +EXPORT_SYMBOL(__modsi3); diff --git a/trunk/arch/parisc/lib/libgcc/__muldi3.c b/trunk/arch/parisc/lib/libgcc/__muldi3.c new file mode 100644 index 000000000000..3308abdd5580 --- /dev/null +++ b/trunk/arch/parisc/lib/libgcc/__muldi3.c @@ -0,0 +1,22 @@ +#include "libgcc.h" + +union DWunion { + struct { + s32 high; + s32 low; + } s; + s64 ll; +}; + +s64 __muldi3(s64 u, s64 v) +{ + const union DWunion uu = { .ll = u }; + const union DWunion vv = { .ll = v }; + union DWunion w = { .ll = __umulsidi3(uu.s.low, vv.s.low) }; + + w.s.high += ((u32)uu.s.low * (u32)vv.s.high + + (u32)uu.s.high * (u32)vv.s.low); + + return w.ll; +} +EXPORT_SYMBOL(__muldi3); diff --git a/trunk/arch/parisc/lib/libgcc/__udivdi3.c b/trunk/arch/parisc/lib/libgcc/__udivdi3.c new file mode 100644 index 000000000000..740023d690f5 --- /dev/null +++ b/trunk/arch/parisc/lib/libgcc/__udivdi3.c @@ -0,0 +1,7 @@ +#include "libgcc.h" + +u64 __udivdi3(u64 num, u64 den) +{ + return __udivmoddi4(num, den, NULL); +} +EXPORT_SYMBOL(__udivdi3); diff --git a/trunk/arch/parisc/lib/libgcc/__udivmoddi4.c b/trunk/arch/parisc/lib/libgcc/__udivmoddi4.c new file mode 100644 index 000000000000..2df0caa5a7d8 --- /dev/null +++ b/trunk/arch/parisc/lib/libgcc/__udivmoddi4.c @@ -0,0 +1,31 @@ +#include "libgcc.h" + +u64 __udivmoddi4(u64 num, u64 den, u64 * rem_p) +{ + u64 quot = 0, qbit = 1; + + if (den == 0) { + BUG(); + } + + /* Left-justify denominator and count shift */ + while ((s64) den >= 0) { + den <<= 1; + qbit <<= 1; + } + + while (qbit) { + if (den <= num) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + if (rem_p) + *rem_p = num; + + return quot; +} +EXPORT_SYMBOL(__udivmoddi4); diff --git a/trunk/arch/parisc/lib/libgcc/__udivmodsi4.c b/trunk/arch/parisc/lib/libgcc/__udivmodsi4.c new file mode 100644 index 000000000000..2a2fc28b2026 --- /dev/null +++ b/trunk/arch/parisc/lib/libgcc/__udivmodsi4.c @@ -0,0 +1,31 @@ +#include "libgcc.h" + +u32 __udivmodsi4(u32 num, u32 den, u32 * rem_p) +{ + u32 quot = 0, qbit = 1; + + if (den == 0) { + BUG(); + } + + /* Left-justify denominator and count shift */ + while ((s32) den >= 0) { + den <<= 1; + qbit <<= 1; + } + + while (qbit) { + if (den <= num) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + if (rem_p) + *rem_p = num; + + return quot; +} +EXPORT_SYMBOL(__udivmodsi4); diff --git a/trunk/arch/parisc/lib/libgcc/__udivsi3.c b/trunk/arch/parisc/lib/libgcc/__udivsi3.c new file mode 100644 index 000000000000..756a44164e90 --- /dev/null +++ b/trunk/arch/parisc/lib/libgcc/__udivsi3.c @@ -0,0 +1,7 @@ +#include "libgcc.h" + +u32 __udivsi3(u32 num, u32 den) +{ + return __udivmodsi4(num, den, NULL); +} +EXPORT_SYMBOL(__udivsi3); diff --git a/trunk/arch/parisc/lib/libgcc/__umoddi3.c b/trunk/arch/parisc/lib/libgcc/__umoddi3.c new file mode 100644 index 000000000000..ac744e948bc1 --- /dev/null +++ b/trunk/arch/parisc/lib/libgcc/__umoddi3.c @@ -0,0 +1,10 @@ +#include "libgcc.h" + +u64 __umoddi3(u64 num, u64 den) +{ + u64 v; + + (void)__udivmoddi4(num, den, &v); + return v; +} +EXPORT_SYMBOL(__umoddi3); diff --git a/trunk/arch/parisc/lib/libgcc/__umodsi3.c b/trunk/arch/parisc/lib/libgcc/__umodsi3.c new file mode 100644 index 000000000000..51f55aa89f9a --- /dev/null +++ b/trunk/arch/parisc/lib/libgcc/__umodsi3.c @@ -0,0 +1,10 @@ +#include "libgcc.h" + +u32 __umodsi3(u32 num, u32 den) +{ + u32 v; + + (void)__udivmodsi4(num, den, &v); + return v; +} +EXPORT_SYMBOL(__umodsi3); diff --git a/trunk/arch/parisc/lib/libgcc/__umulsidi3.c b/trunk/arch/parisc/lib/libgcc/__umulsidi3.c new file mode 100644 index 000000000000..396f669164d4 --- /dev/null +++ b/trunk/arch/parisc/lib/libgcc/__umulsidi3.c @@ -0,0 +1,46 @@ +#include "libgcc.h" + +#define __ll_B ((u32) 1 << (32 / 2)) +#define __ll_lowpart(t) ((u32) (t) & (__ll_B - 1)) +#define __ll_highpart(t) ((u32) (t) >> 16) + +#define umul_ppmm(w1, w0, u, v) \ + do { \ + u32 __x0, __x1, __x2, __x3; \ + u16 __ul, __vl, __uh, __vh; \ + \ + __ul = __ll_lowpart (u); \ + __uh = __ll_highpart (u); \ + __vl = __ll_lowpart (v); \ + __vh = __ll_highpart (v); \ + \ + __x0 = (u32) __ul * __vl; \ + __x1 = (u32) __ul * __vh; \ + __x2 = (u32) __uh * __vl; \ + __x3 = (u32) __uh * __vh; \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ + } while (0) + +union DWunion { + struct { + s32 high; + s32 low; + } s; + s64 ll; +}; + +u64 __umulsidi3(u32 u, u32 v) +{ + union DWunion __w; + + umul_ppmm(__w.s.high, __w.s.low, u, v); + + return __w.ll; +} diff --git a/trunk/arch/parisc/lib/libgcc/libgcc.h b/trunk/arch/parisc/lib/libgcc/libgcc.h new file mode 100644 index 000000000000..5a6f7a510fbd --- /dev/null +++ b/trunk/arch/parisc/lib/libgcc/libgcc.h @@ -0,0 +1,32 @@ +#ifndef _PA_LIBGCC_H_ +#define _PA_LIBGCC_H_ + +#include +#include + +/* Cribbed from klibc/libgcc/ */ +u64 __ashldi3(u64 v, int cnt); +u64 __ashrdi3(u64 v, int cnt); + +u32 __clzsi2(u32 v); + +s64 __divdi3(s64 num, s64 den); +s32 __divsi3(s32 num, s32 den); + +u64 __lshrdi3(u64 v, int cnt); + +s64 __moddi3(s64 num, s64 den); +s32 __modsi3(s32 num, s32 den); + +u64 __udivdi3(u64 num, u64 den); +u32 __udivsi3(u32 num, u32 den); + +u64 __udivmoddi4(u64 num, u64 den, u64 * rem_p); +u32 __udivmodsi4(u32 num, u32 den, u32 * rem_p); + +u64 __umulsidi3(u32 u, u32 v); + +u64 __umoddi3(u64 num, u64 den); +u32 __umodsi3(u32 num, u32 den); + +#endif /*_PA_LIBGCC_H_*/ diff --git a/trunk/arch/parisc/lib/milli/Makefile b/trunk/arch/parisc/lib/milli/Makefile new file mode 100644 index 000000000000..9b24e9b1f3cb --- /dev/null +++ b/trunk/arch/parisc/lib/milli/Makefile @@ -0,0 +1 @@ +obj-y := dyncall.o divI.o divU.o remI.o remU.o div_const.o mulI.o diff --git a/trunk/arch/parisc/lib/milli/divI.S b/trunk/arch/parisc/lib/milli/divI.S new file mode 100644 index 000000000000..ac106b7b6f24 --- /dev/null +++ b/trunk/arch/parisc/lib/milli/divI.S @@ -0,0 +1,254 @@ +/* 32 and 64-bit millicode, original author Hewlett-Packard + adapted for gcc by Paul Bame + and Alan Modra . + + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + This file is part of GCC and is released under the terms of + of the GNU General Public License as published by the Free Software + Foundation; either version 2, or (at your option) any later version. + See the file COPYING in the top-level GCC source directory for a copy + of the license. */ + +#include "milli.h" + +#ifdef L_divI +/* ROUTINES: $$divI, $$divoI + + Single precision divide for signed binary integers. + + The quotient is truncated towards zero. + The sign of the quotient is the XOR of the signs of the dividend and + divisor. + Divide by zero is trapped. + Divide of -2**31 by -1 is trapped for $$divoI but not for $$divI. + + INPUT REGISTERS: + . arg0 == dividend + . arg1 == divisor + . mrp == return pc + . sr0 == return space when called externally + + OUTPUT REGISTERS: + . arg0 = undefined + . arg1 = undefined + . ret1 = quotient + + OTHER REGISTERS AFFECTED: + . r1 = undefined + + SIDE EFFECTS: + . Causes a trap under the following conditions: + . divisor is zero (traps with ADDIT,= 0,25,0) + . dividend==-2**31 and divisor==-1 and routine is $$divoI + . (traps with ADDO 26,25,0) + . Changes memory at the following places: + . NONE + + PERMISSIBLE CONTEXT: + . Unwindable. + . Suitable for internal or external millicode. + . Assumes the special millicode register conventions. + + DISCUSSION: + . Branchs to other millicode routines using BE + . $$div_# for # being 2,3,4,5,6,7,8,9,10,12,14,15 + . + . For selected divisors, calls a divide by constant routine written by + . Karl Pettis. Eligible divisors are 1..15 excluding 11 and 13. + . + . The only overflow case is -2**31 divided by -1. + . Both routines return -2**31 but only $$divoI traps. */ + +RDEFINE(temp,r1) +RDEFINE(retreg,ret1) /* r29 */ +RDEFINE(temp1,arg0) + SUBSPA_MILLI_DIV + ATTR_MILLI + .import $$divI_2,millicode + .import $$divI_3,millicode + .import $$divI_4,millicode + .import $$divI_5,millicode + .import $$divI_6,millicode + .import $$divI_7,millicode + .import $$divI_8,millicode + .import $$divI_9,millicode + .import $$divI_10,millicode + .import $$divI_12,millicode + .import $$divI_14,millicode + .import $$divI_15,millicode + .export $$divI,millicode + .export $$divoI,millicode + .proc + .callinfo millicode + .entry +GSYM($$divoI) + comib,=,n -1,arg1,LREF(negative1) /* when divisor == -1 */ +GSYM($$divI) + ldo -1(arg1),temp /* is there at most one bit set ? */ + and,<> arg1,temp,r0 /* if not, don't use power of 2 divide */ + addi,> 0,arg1,r0 /* if divisor > 0, use power of 2 divide */ + b,n LREF(neg_denom) +LSYM(pow2) + addi,>= 0,arg0,retreg /* if numerator is negative, add the */ + add arg0,temp,retreg /* (denominaotr -1) to correct for shifts */ + extru,= arg1,15,16,temp /* test denominator with 0xffff0000 */ + extrs retreg,15,16,retreg /* retreg = retreg >> 16 */ + or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 16) */ + ldi 0xcc,temp1 /* setup 0xcc in temp1 */ + extru,= arg1,23,8,temp /* test denominator with 0xff00 */ + extrs retreg,23,24,retreg /* retreg = retreg >> 8 */ + or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 8) */ + ldi 0xaa,temp /* setup 0xaa in temp */ + extru,= arg1,27,4,r0 /* test denominator with 0xf0 */ + extrs retreg,27,28,retreg /* retreg = retreg >> 4 */ + and,= arg1,temp1,r0 /* test denominator with 0xcc */ + extrs retreg,29,30,retreg /* retreg = retreg >> 2 */ + and,= arg1,temp,r0 /* test denominator with 0xaa */ + extrs retreg,30,31,retreg /* retreg = retreg >> 1 */ + MILLIRETN +LSYM(neg_denom) + addi,< 0,arg1,r0 /* if arg1 >= 0, it's not power of 2 */ + b,n LREF(regular_seq) + sub r0,arg1,temp /* make denominator positive */ + comb,=,n arg1,temp,LREF(regular_seq) /* test against 0x80000000 and 0 */ + ldo -1(temp),retreg /* is there at most one bit set ? */ + and,= temp,retreg,r0 /* if so, the denominator is power of 2 */ + b,n LREF(regular_seq) + sub r0,arg0,retreg /* negate numerator */ + comb,=,n arg0,retreg,LREF(regular_seq) /* test against 0x80000000 */ + copy retreg,arg0 /* set up arg0, arg1 and temp */ + copy temp,arg1 /* before branching to pow2 */ + b LREF(pow2) + ldo -1(arg1),temp +LSYM(regular_seq) + comib,>>=,n 15,arg1,LREF(small_divisor) + add,>= 0,arg0,retreg /* move dividend, if retreg < 0, */ +LSYM(normal) + subi 0,retreg,retreg /* make it positive */ + sub 0,arg1,temp /* clear carry, */ + /* negate the divisor */ + ds 0,temp,0 /* set V-bit to the comple- */ + /* ment of the divisor sign */ + add retreg,retreg,retreg /* shift msb bit into carry */ + ds r0,arg1,temp /* 1st divide step, if no carry */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 2nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 3rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 4th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 5th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 6th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 7th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 8th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 9th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 10th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 11th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 12th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 13th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 14th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 15th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 16th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 17th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 18th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 19th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 20th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 21st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 22nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 23rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 24th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 25th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 26th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 27th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 28th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 29th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 30th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 31st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 32nd divide step, */ + addc retreg,retreg,retreg /* shift last retreg bit into retreg */ + xor,>= arg0,arg1,0 /* get correct sign of quotient */ + sub 0,retreg,retreg /* based on operand signs */ + MILLIRETN + nop + +LSYM(small_divisor) + +#if defined(CONFIG_64BIT) +/* Clear the upper 32 bits of the arg1 register. We are working with */ +/* small divisors (and 32-bit integers) We must not be mislead */ +/* by "1" bits left in the upper 32 bits. */ + depd %r0,31,32,%r25 +#endif + blr,n arg1,r0 + nop +/* table for divisor == 0,1, ... ,15 */ + addit,= 0,arg1,r0 /* trap if divisor == 0 */ + nop + MILLIRET /* divisor == 1 */ + copy arg0,retreg + MILLI_BEN($$divI_2) /* divisor == 2 */ + nop + MILLI_BEN($$divI_3) /* divisor == 3 */ + nop + MILLI_BEN($$divI_4) /* divisor == 4 */ + nop + MILLI_BEN($$divI_5) /* divisor == 5 */ + nop + MILLI_BEN($$divI_6) /* divisor == 6 */ + nop + MILLI_BEN($$divI_7) /* divisor == 7 */ + nop + MILLI_BEN($$divI_8) /* divisor == 8 */ + nop + MILLI_BEN($$divI_9) /* divisor == 9 */ + nop + MILLI_BEN($$divI_10) /* divisor == 10 */ + nop + b LREF(normal) /* divisor == 11 */ + add,>= 0,arg0,retreg + MILLI_BEN($$divI_12) /* divisor == 12 */ + nop + b LREF(normal) /* divisor == 13 */ + add,>= 0,arg0,retreg + MILLI_BEN($$divI_14) /* divisor == 14 */ + nop + MILLI_BEN($$divI_15) /* divisor == 15 */ + nop + +LSYM(negative1) + sub 0,arg0,retreg /* result is negation of dividend */ + MILLIRET + addo arg0,arg1,r0 /* trap iff dividend==0x80000000 && divisor==-1 */ + .exit + .procend + .end +#endif diff --git a/trunk/arch/parisc/lib/milli/divU.S b/trunk/arch/parisc/lib/milli/divU.S new file mode 100644 index 000000000000..9287fe2546fa --- /dev/null +++ b/trunk/arch/parisc/lib/milli/divU.S @@ -0,0 +1,235 @@ +/* 32 and 64-bit millicode, original author Hewlett-Packard + adapted for gcc by Paul Bame + and Alan Modra . + + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + This file is part of GCC and is released under the terms of + of the GNU General Public License as published by the Free Software + Foundation; either version 2, or (at your option) any later version. + See the file COPYING in the top-level GCC source directory for a copy + of the license. */ + +#include "milli.h" + +#ifdef L_divU +/* ROUTINE: $$divU + . + . Single precision divide for unsigned integers. + . + . Quotient is truncated towards zero. + . Traps on divide by zero. + + INPUT REGISTERS: + . arg0 == dividend + . arg1 == divisor + . mrp == return pc + . sr0 == return space when called externally + + OUTPUT REGISTERS: + . arg0 = undefined + . arg1 = undefined + . ret1 = quotient + + OTHER REGISTERS AFFECTED: + . r1 = undefined + + SIDE EFFECTS: + . Causes a trap under the following conditions: + . divisor is zero + . Changes memory at the following places: + . NONE + + PERMISSIBLE CONTEXT: + . Unwindable. + . Does not create a stack frame. + . Suitable for internal or external millicode. + . Assumes the special millicode register conventions. + + DISCUSSION: + . Branchs to other millicode routines using BE: + . $$divU_# for 3,5,6,7,9,10,12,14,15 + . + . For selected small divisors calls the special divide by constant + . routines written by Karl Pettis. These are: 3,5,6,7,9,10,12,14,15. */ + +RDEFINE(temp,r1) +RDEFINE(retreg,ret1) /* r29 */ +RDEFINE(temp1,arg0) + SUBSPA_MILLI_DIV + ATTR_MILLI + .export $$divU,millicode + .import $$divU_3,millicode + .import $$divU_5,millicode + .import $$divU_6,millicode + .import $$divU_7,millicode + .import $$divU_9,millicode + .import $$divU_10,millicode + .import $$divU_12,millicode + .import $$divU_14,millicode + .import $$divU_15,millicode + .proc + .callinfo millicode + .entry +GSYM($$divU) +/* The subtract is not nullified since it does no harm and can be used + by the two cases that branch back to "normal". */ + ldo -1(arg1),temp /* is there at most one bit set ? */ + and,= arg1,temp,r0 /* if so, denominator is power of 2 */ + b LREF(regular_seq) + addit,= 0,arg1,0 /* trap for zero dvr */ + copy arg0,retreg + extru,= arg1,15,16,temp /* test denominator with 0xffff0000 */ + extru retreg,15,16,retreg /* retreg = retreg >> 16 */ + or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 16) */ + ldi 0xcc,temp1 /* setup 0xcc in temp1 */ + extru,= arg1,23,8,temp /* test denominator with 0xff00 */ + extru retreg,23,24,retreg /* retreg = retreg >> 8 */ + or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 8) */ + ldi 0xaa,temp /* setup 0xaa in temp */ + extru,= arg1,27,4,r0 /* test denominator with 0xf0 */ + extru retreg,27,28,retreg /* retreg = retreg >> 4 */ + and,= arg1,temp1,r0 /* test denominator with 0xcc */ + extru retreg,29,30,retreg /* retreg = retreg >> 2 */ + and,= arg1,temp,r0 /* test denominator with 0xaa */ + extru retreg,30,31,retreg /* retreg = retreg >> 1 */ + MILLIRETN + nop +LSYM(regular_seq) + comib,>= 15,arg1,LREF(special_divisor) + subi 0,arg1,temp /* clear carry, negate the divisor */ + ds r0,temp,r0 /* set V-bit to 1 */ +LSYM(normal) + add arg0,arg0,retreg /* shift msb bit into carry */ + ds r0,arg1,temp /* 1st divide step, if no carry */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 2nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 3rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 4th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 5th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 6th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 7th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 8th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 9th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 10th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 11th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 12th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 13th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 14th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 15th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 16th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 17th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 18th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 19th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 20th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 21st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 22nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 23rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 24th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 25th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 26th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 27th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 28th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 29th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 30th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 31st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 32nd divide step, */ + MILLIRET + addc retreg,retreg,retreg /* shift last retreg bit into retreg */ + +/* Handle the cases where divisor is a small constant or has high bit on. */ +LSYM(special_divisor) +/* blr arg1,r0 */ +/* comib,>,n 0,arg1,LREF(big_divisor) ; nullify previous instruction */ + +/* Pratap 8/13/90. The 815 Stirling chip set has a bug that prevents us from + generating such a blr, comib sequence. A problem in nullification. So I + rewrote this code. */ + +#if defined(CONFIG_64BIT) +/* Clear the upper 32 bits of the arg1 register. We are working with + small divisors (and 32-bit unsigned integers) We must not be mislead + by "1" bits left in the upper 32 bits. */ + depd %r0,31,32,%r25 +#endif + comib,> 0,arg1,LREF(big_divisor) + nop + blr arg1,r0 + nop + +LSYM(zero_divisor) /* this label is here to provide external visibility */ + addit,= 0,arg1,0 /* trap for zero dvr */ + nop + MILLIRET /* divisor == 1 */ + copy arg0,retreg + MILLIRET /* divisor == 2 */ + extru arg0,30,31,retreg + MILLI_BEN($$divU_3) /* divisor == 3 */ + nop + MILLIRET /* divisor == 4 */ + extru arg0,29,30,retreg + MILLI_BEN($$divU_5) /* divisor == 5 */ + nop + MILLI_BEN($$divU_6) /* divisor == 6 */ + nop + MILLI_BEN($$divU_7) /* divisor == 7 */ + nop + MILLIRET /* divisor == 8 */ + extru arg0,28,29,retreg + MILLI_BEN($$divU_9) /* divisor == 9 */ + nop + MILLI_BEN($$divU_10) /* divisor == 10 */ + nop + b LREF(normal) /* divisor == 11 */ + ds r0,temp,r0 /* set V-bit to 1 */ + MILLI_BEN($$divU_12) /* divisor == 12 */ + nop + b LREF(normal) /* divisor == 13 */ + ds r0,temp,r0 /* set V-bit to 1 */ + MILLI_BEN($$divU_14) /* divisor == 14 */ + nop + MILLI_BEN($$divU_15) /* divisor == 15 */ + nop + +/* Handle the case where the high bit is on in the divisor. + Compute: if( dividend>=divisor) quotient=1; else quotient=0; + Note: dividend>==divisor iff dividend-divisor does not borrow + and not borrow iff carry. */ +LSYM(big_divisor) + sub arg0,arg1,r0 + MILLIRET + addc r0,r0,retreg + .exit + .procend + .end +#endif diff --git a/trunk/arch/parisc/lib/milli/div_const.S b/trunk/arch/parisc/lib/milli/div_const.S new file mode 100644 index 000000000000..dd660076e944 --- /dev/null +++ b/trunk/arch/parisc/lib/milli/div_const.S @@ -0,0 +1,682 @@ +/* 32 and 64-bit millicode, original author Hewlett-Packard + adapted for gcc by Paul Bame + and Alan Modra . + + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + This file is part of GCC and is released under the terms of + of the GNU General Public License as published by the Free Software + Foundation; either version 2, or (at your option) any later version. + See the file COPYING in the top-level GCC source directory for a copy + of the license. */ + +#include "milli.h" + +#ifdef L_div_const +/* ROUTINE: $$divI_2 + . $$divI_3 $$divU_3 + . $$divI_4 + . $$divI_5 $$divU_5 + . $$divI_6 $$divU_6 + . $$divI_7 $$divU_7 + . $$divI_8 + . $$divI_9 $$divU_9 + . $$divI_10 $$divU_10 + . + . $$divI_12 $$divU_12 + . + . $$divI_14 $$divU_14 + . $$divI_15 $$divU_15 + . $$divI_16 + . $$divI_17 $$divU_17 + . + . Divide by selected constants for single precision binary integers. + + INPUT REGISTERS: + . arg0 == dividend + . mrp == return pc + . sr0 == return space when called externally + + OUTPUT REGISTERS: + . arg0 = undefined + . arg1 = undefined + . ret1 = quotient + + OTHER REGISTERS AFFECTED: + . r1 = undefined + + SIDE EFFECTS: + . Causes a trap under the following conditions: NONE + . Changes memory at the following places: NONE + + PERMISSIBLE CONTEXT: + . Unwindable. + . Does not create a stack frame. + . Suitable for internal or external millicode. + . Assumes the special millicode register conventions. + + DISCUSSION: + . Calls other millicode routines using mrp: NONE + . Calls other millicode routines: NONE */ + + +/* TRUNCATED DIVISION BY SMALL INTEGERS + + We are interested in q(x) = floor(x/y), where x >= 0 and y > 0 + (with y fixed). + + Let a = floor(z/y), for some choice of z. Note that z will be + chosen so that division by z is cheap. + + Let r be the remainder(z/y). In other words, r = z - ay. + + Now, our method is to choose a value for b such that + + q'(x) = floor((ax+b)/z) + + is equal to q(x) over as large a range of x as possible. If the + two are equal over a sufficiently large range, and if it is easy to + form the product (ax), and it is easy to divide by z, then we can + perform the division much faster than the general division algorithm. + + So, we want the following to be true: + + . For x in the following range: + . + . ky <= x < (k+1)y + . + . implies that + . + . k <= (ax+b)/z < (k+1) + + We want to determine b such that this is true for all k in the + range {0..K} for some maximum K. + + Since (ax+b) is an increasing function of x, we can take each + bound separately to determine the "best" value for b. + + (ax+b)/z < (k+1) implies + + (a((k+1)y-1)+b < (k+1)z implies + + b < a + (k+1)(z-ay) implies + + b < a + (k+1)r + + This needs to be true for all k in the range {0..K}. In + particular, it is true for k = 0 and this leads to a maximum + acceptable value for b. + + b < a+r or b <= a+r-1 + + Taking the other bound, we have + + k <= (ax+b)/z implies + + k <= (aky+b)/z implies + + k(z-ay) <= b implies + + kr <= b + + Clearly, the largest range for k will be achieved by maximizing b, + when r is not zero. When r is zero, then the simplest choice for b + is 0. When r is not 0, set + + . b = a+r-1 + + Now, by construction, q'(x) = floor((ax+b)/z) = q(x) = floor(x/y) + for all x in the range: + + . 0 <= x < (K+1)y + + We need to determine what K is. Of our two bounds, + + . b < a+(k+1)r is satisfied for all k >= 0, by construction. + + The other bound is + + . kr <= b + + This is always true if r = 0. If r is not 0 (the usual case), then + K = floor((a+r-1)/r), is the maximum value for k. + + Therefore, the formula q'(x) = floor((ax+b)/z) yields the correct + answer for q(x) = floor(x/y) when x is in the range + + (0,(K+1)y-1) K = floor((a+r-1)/r) + + To be most useful, we want (K+1)y-1 = (max x) >= 2**32-1 so that + the formula for q'(x) yields the correct value of q(x) for all x + representable by a single word in HPPA. + + We are also constrained in that computing the product (ax), adding + b, and dividing by z must all be done quickly, otherwise we will be + better off going through the general algorithm using the DS + instruction, which uses approximately 70 cycles. + + For each y, there is a choice of z which satisfies the constraints + for (K+1)y >= 2**32. We may not, however, be able to satisfy the + timing constraints for arbitrary y. It seems that z being equal to + a power of 2 or a power of 2 minus 1 is as good as we can do, since + it minimizes the time to do division by z. We want the choice of z + to also result in a value for (a) that minimizes the computation of + the product (ax). This is best achieved if (a) has a regular bit + pattern (so the multiplication can be done with shifts and adds). + The value of (a) also needs to be less than 2**32 so the product is + always guaranteed to fit in 2 words. + + In actual practice, the following should be done: + + 1) For negative x, you should take the absolute value and remember + . the fact so that the result can be negated. This obviously does + . not apply in the unsigned case. + 2) For even y, you should factor out the power of 2 that divides y + . and divide x by it. You can then proceed by dividing by the + . odd factor of y. + + Here is a table of some odd values of y, and corresponding choices + for z which are "good". + + y z r a (hex) max x (hex) + + 3 2**32 1 55555555 100000001 + 5 2**32 1 33333333 100000003 + 7 2**24-1 0 249249 (infinite) + 9 2**24-1 0 1c71c7 (infinite) + 11 2**20-1 0 1745d (infinite) + 13 2**24-1 0 13b13b (infinite) + 15 2**32 1 11111111 10000000d + 17 2**32 1 f0f0f0f 10000000f + + If r is 1, then b = a+r-1 = a. This simplifies the computation + of (ax+b), since you can compute (x+1)(a) instead. If r is 0, + then b = 0 is ok to use which simplifies (ax+b). + + The bit patterns for 55555555, 33333333, and 11111111 are obviously + very regular. The bit patterns for the other values of a above are: + + y (hex) (binary) + + 7 249249 001001001001001001001001 << regular >> + 9 1c71c7 000111000111000111000111 << regular >> + 11 1745d 000000010111010001011101 << irregular >> + 13 13b13b 000100111011000100111011 << irregular >> + + The bit patterns for (a) corresponding to (y) of 11 and 13 may be + too irregular to warrant using this method. + + When z is a power of 2 minus 1, then the division by z is slightly + more complicated, involving an iterative solution. + + The code presented here solves division by 1 through 17, except for + 11 and 13. There are algorithms for both signed and unsigned + quantities given. + + TIMINGS (cycles) + + divisor positive negative unsigned + + . 1 2 2 2 + . 2 4 4 2 + . 3 19 21 19 + . 4 4 4 2 + . 5 18 22 19 + . 6 19 22 19 + . 8 4 4 2 + . 10 18 19 17 + . 12 18 20 18 + . 15 16 18 16 + . 16 4 4 2 + . 17 16 18 16 + + Now, the algorithm for 7, 9, and 14 is an iterative one. That is, + a loop body is executed until the tentative quotient is 0. The + number of times the loop body is executed varies depending on the + dividend, but is never more than two times. If the dividend is + less than the divisor, then the loop body is not executed at all. + Each iteration adds 4 cycles to the timings. + + divisor positive negative unsigned + + . 7 19+4n 20+4n 20+4n n = number of iterations + . 9 21+4n 22+4n 21+4n + . 14 21+4n 22+4n 20+4n + + To give an idea of how the number of iterations varies, here is a + table of dividend versus number of iterations when dividing by 7. + + smallest largest required + dividend dividend iterations + + . 0 6 0 + . 7 0x6ffffff 1 + 0x1000006 0xffffffff 2 + + There is some overlap in the range of numbers requiring 1 and 2 + iterations. */ + +RDEFINE(t2,r1) +RDEFINE(x2,arg0) /* r26 */ +RDEFINE(t1,arg1) /* r25 */ +RDEFINE(x1,ret1) /* r29 */ + + SUBSPA_MILLI_DIV + ATTR_MILLI + + .proc + .callinfo millicode + .entry +/* NONE of these routines require a stack frame + ALL of these routines are unwindable from millicode */ + +GSYM($$divide_by_constant) + .export $$divide_by_constant,millicode +/* Provides a "nice" label for the code covered by the unwind descriptor + for things like gprof. */ + +/* DIVISION BY 2 (shift by 1) */ +GSYM($$divI_2) + .export $$divI_2,millicode + comclr,>= arg0,0,0 + addi 1,arg0,arg0 + MILLIRET + extrs arg0,30,31,ret1 + + +/* DIVISION BY 4 (shift by 2) */ +GSYM($$divI_4) + .export $$divI_4,millicode + comclr,>= arg0,0,0 + addi 3,arg0,arg0 + MILLIRET + extrs arg0,29,30,ret1 + + +/* DIVISION BY 8 (shift by 3) */ +GSYM($$divI_8) + .export $$divI_8,millicode + comclr,>= arg0,0,0 + addi 7,arg0,arg0 + MILLIRET + extrs arg0,28,29,ret1 + +/* DIVISION BY 16 (shift by 4) */ +GSYM($$divI_16) + .export $$divI_16,millicode + comclr,>= arg0,0,0 + addi 15,arg0,arg0 + MILLIRET + extrs arg0,27,28,ret1 + +/**************************************************************************** +* +* DIVISION BY DIVISORS OF FFFFFFFF, and powers of 2 times these +* +* includes 3,5,15,17 and also 6,10,12 +* +****************************************************************************/ + +/* DIVISION BY 3 (use z = 2**32; a = 55555555) */ + +GSYM($$divI_3) + .export $$divI_3,millicode + comb,<,N x2,0,LREF(neg3) + + addi 1,x2,x2 /* this cannot overflow */ + extru x2,1,2,x1 /* multiply by 5 to get started */ + sh2add x2,x2,x2 + b LREF(pos) + addc x1,0,x1 + +LSYM(neg3) + subi 1,x2,x2 /* this cannot overflow */ + extru x2,1,2,x1 /* multiply by 5 to get started */ + sh2add x2,x2,x2 + b LREF(neg) + addc x1,0,x1 + +GSYM($$divU_3) + .export $$divU_3,millicode + addi 1,x2,x2 /* this CAN overflow */ + addc 0,0,x1 + shd x1,x2,30,t1 /* multiply by 5 to get started */ + sh2add x2,x2,x2 + b LREF(pos) + addc x1,t1,x1 + +/* DIVISION BY 5 (use z = 2**32; a = 33333333) */ + +GSYM($$divI_5) + .export $$divI_5,millicode + comb,<,N x2,0,LREF(neg5) + + addi 3,x2,t1 /* this cannot overflow */ + sh1add x2,t1,x2 /* multiply by 3 to get started */ + b LREF(pos) + addc 0,0,x1 + +LSYM(neg5) + sub 0,x2,x2 /* negate x2 */ + addi 1,x2,x2 /* this cannot overflow */ + shd 0,x2,31,x1 /* get top bit (can be 1) */ + sh1add x2,x2,x2 /* multiply by 3 to get started */ + b LREF(neg) + addc x1,0,x1 + +GSYM($$divU_5) + .export $$divU_5,millicode + addi 1,x2,x2 /* this CAN overflow */ + addc 0,0,x1 + shd x1,x2,31,t1 /* multiply by 3 to get started */ + sh1add x2,x2,x2 + b LREF(pos) + addc t1,x1,x1 + +/* DIVISION BY 6 (shift to divide by 2 then divide by 3) */ +GSYM($$divI_6) + .export $$divI_6,millicode + comb,<,N x2,0,LREF(neg6) + extru x2,30,31,x2 /* divide by 2 */ + addi 5,x2,t1 /* compute 5*(x2+1) = 5*x2+5 */ + sh2add x2,t1,x2 /* multiply by 5 to get started */ + b LREF(pos) + addc 0,0,x1 + +LSYM(neg6) + subi 2,x2,x2 /* negate, divide by 2, and add 1 */ + /* negation and adding 1 are done */ + /* at the same time by the SUBI */ + extru x2,30,31,x2 + shd 0,x2,30,x1 + sh2add x2,x2,x2 /* multiply by 5 to get started */ + b LREF(neg) + addc x1,0,x1 + +GSYM($$divU_6) + .export $$divU_6,millicode + extru x2,30,31,x2 /* divide by 2 */ + addi 1,x2,x2 /* cannot carry */ + shd 0,x2,30,x1 /* multiply by 5 to get started */ + sh2add x2,x2,x2 + b LREF(pos) + addc x1,0,x1 + +/* DIVISION BY 10 (shift to divide by 2 then divide by 5) */ +GSYM($$divU_10) + .export $$divU_10,millicode + extru x2,30,31,x2 /* divide by 2 */ + addi 3,x2,t1 /* compute 3*(x2+1) = (3*x2)+3 */ + sh1add x2,t1,x2 /* multiply by 3 to get started */ + addc 0,0,x1 +LSYM(pos) + shd x1,x2,28,t1 /* multiply by 0x11 */ + shd x2,0,28,t2 + add x2,t2,x2 + addc x1,t1,x1 +LSYM(pos_for_17) + shd x1,x2,24,t1 /* multiply by 0x101 */ + shd x2,0,24,t2 + add x2,t2,x2 + addc x1,t1,x1 + + shd x1,x2,16,t1 /* multiply by 0x10001 */ + shd x2,0,16,t2 + add x2,t2,x2 + MILLIRET + addc x1,t1,x1 + +GSYM($$divI_10) + .export $$divI_10,millicode + comb,< x2,0,LREF(neg10) + copy 0,x1 + extru x2,30,31,x2 /* divide by 2 */ + addib,TR 1,x2,LREF(pos) /* add 1 (cannot overflow) */ + sh1add x2,x2,x2 /* multiply by 3 to get started */ + +LSYM(neg10) + subi 2,x2,x2 /* negate, divide by 2, and add 1 */ + /* negation and adding 1 are done */ + /* at the same time by the SUBI */ + extru x2,30,31,x2 + sh1add x2,x2,x2 /* multiply by 3 to get started */ +LSYM(neg) + shd x1,x2,28,t1 /* multiply by 0x11 */ + shd x2,0,28,t2 + add x2,t2,x2 + addc x1,t1,x1 +LSYM(neg_for_17) + shd x1,x2,24,t1 /* multiply by 0x101 */ + shd x2,0,24,t2 + add x2,t2,x2 + addc x1,t1,x1 + + shd x1,x2,16,t1 /* multiply by 0x10001 */ + shd x2,0,16,t2 + add x2,t2,x2 + addc x1,t1,x1 + MILLIRET + sub 0,x1,x1 + +/* DIVISION BY 12 (shift to divide by 4 then divide by 3) */ +GSYM($$divI_12) + .export $$divI_12,millicode + comb,< x2,0,LREF(neg12) + copy 0,x1 + extru x2,29,30,x2 /* divide by 4 */ + addib,tr 1,x2,LREF(pos) /* compute 5*(x2+1) = 5*x2+5 */ + sh2add x2,x2,x2 /* multiply by 5 to get started */ + +LSYM(neg12) + subi 4,x2,x2 /* negate, divide by 4, and add 1 */ + /* negation and adding 1 are done */ + /* at the same time by the SUBI */ + extru x2,29,30,x2 + b LREF(neg) + sh2add x2,x2,x2 /* multiply by 5 to get started */ + +GSYM($$divU_12) + .export $$divU_12,millicode + extru x2,29,30,x2 /* divide by 4 */ + addi 5,x2,t1 /* cannot carry */ + sh2add x2,t1,x2 /* multiply by 5 to get started */ + b LREF(pos) + addc 0,0,x1 + +/* DIVISION BY 15 (use z = 2**32; a = 11111111) */ +GSYM($$divI_15) + .export $$divI_15,millicode + comb,< x2,0,LREF(neg15) + copy 0,x1 + addib,tr 1,x2,LREF(pos)+4 + shd x1,x2,28,t1 + +LSYM(neg15) + b LREF(neg) + subi 1,x2,x2 + +GSYM($$divU_15) + .export $$divU_15,millicode + addi 1,x2,x2 /* this CAN overflow */ + b LREF(pos) + addc 0,0,x1 + +/* DIVISION BY 17 (use z = 2**32; a = f0f0f0f) */ +GSYM($$divI_17) + .export $$divI_17,millicode + comb,<,n x2,0,LREF(neg17) + addi 1,x2,x2 /* this cannot overflow */ + shd 0,x2,28,t1 /* multiply by 0xf to get started */ + shd x2,0,28,t2 + sub t2,x2,x2 + b LREF(pos_for_17) + subb t1,0,x1 + +LSYM(neg17) + subi 1,x2,x2 /* this cannot overflow */ + shd 0,x2,28,t1 /* multiply by 0xf to get started */ + shd x2,0,28,t2 + sub t2,x2,x2 + b LREF(neg_for_17) + subb t1,0,x1 + +GSYM($$divU_17) + .export $$divU_17,millicode + addi 1,x2,x2 /* this CAN overflow */ + addc 0,0,x1 + shd x1,x2,28,t1 /* multiply by 0xf to get started */ +LSYM(u17) + shd x2,0,28,t2 + sub t2,x2,x2 + b LREF(pos_for_17) + subb t1,x1,x1 + + +/* DIVISION BY DIVISORS OF FFFFFF, and powers of 2 times these + includes 7,9 and also 14 + + + z = 2**24-1 + r = z mod x = 0 + + so choose b = 0 + + Also, in order to divide by z = 2**24-1, we approximate by dividing + by (z+1) = 2**24 (which is easy), and then correcting. + + (ax) = (z+1)q' + r + . = zq' + (q'+r) + + So to compute (ax)/z, compute q' = (ax)/(z+1) and r = (ax) mod (z+1) + Then the true remainder of (ax)/z is (q'+r). Repeat the process + with this new remainder, adding the tentative quotients together, + until a tentative quotient is 0 (and then we are done). There is + one last correction to be done. It is possible that (q'+r) = z. + If so, then (q'+r)/(z+1) = 0 and it looks like we are done. But, + in fact, we need to add 1 more to the quotient. Now, it turns + out that this happens if and only if the original value x is + an exact multiple of y. So, to avoid a three instruction test at + the end, instead use 1 instruction to add 1 to x at the beginning. */ + +/* DIVISION BY 7 (use z = 2**24-1; a = 249249) */ +GSYM($$divI_7) + .export $$divI_7,millicode + comb,<,n x2,0,LREF(neg7) +LSYM(7) + addi 1,x2,x2 /* cannot overflow */ + shd 0,x2,29,x1 + sh3add x2,x2,x2 + addc x1,0,x1 +LSYM(pos7) + shd x1,x2,26,t1 + shd x2,0,26,t2 + add x2,t2,x2 + addc x1,t1,x1 + + shd x1,x2,20,t1 + shd x2,0,20,t2 + add x2,t2,x2 + addc x1,t1,t1 + + /* computed . Now divide it by (2**24 - 1) */ + + copy 0,x1 + shd,= t1,x2,24,t1 /* tentative quotient */ +LSYM(1) + addb,tr t1,x1,LREF(2) /* add to previous quotient */ + extru x2,31,24,x2 /* new remainder (unadjusted) */ + + MILLIRETN + +LSYM(2) + addb,tr t1,x2,LREF(1) /* adjust remainder */ + extru,= x2,7,8,t1 /* new quotient */ + +LSYM(neg7) + subi 1,x2,x2 /* negate x2 and add 1 */ +LSYM(8) + shd 0,x2,29,x1 + sh3add x2,x2,x2 + addc x1,0,x1 + +LSYM(neg7_shift) + shd x1,x2,26,t1 + shd x2,0,26,t2 + add x2,t2,x2 + addc x1,t1,x1 + + shd x1,x2,20,t1 + shd x2,0,20,t2 + add x2,t2,x2 + addc x1,t1,t1 + + /* computed . Now divide it by (2**24 - 1) */ + + copy 0,x1 + shd,= t1,x2,24,t1 /* tentative quotient */ +LSYM(3) + addb,tr t1,x1,LREF(4) /* add to previous quotient */ + extru x2,31,24,x2 /* new remainder (unadjusted) */ + + MILLIRET + sub 0,x1,x1 /* negate result */ + +LSYM(4) + addb,tr t1,x2,LREF(3) /* adjust remainder */ + extru,= x2,7,8,t1 /* new quotient */ + +GSYM($$divU_7) + .export $$divU_7,millicode + addi 1,x2,x2 /* can carry */ + addc 0,0,x1 + shd x1,x2,29,t1 + sh3add x2,x2,x2 + b LREF(pos7) + addc t1,x1,x1 + +/* DIVISION BY 9 (use z = 2**24-1; a = 1c71c7) */ +GSYM($$divI_9) + .export $$divI_9,millicode + comb,<,n x2,0,LREF(neg9) + addi 1,x2,x2 /* cannot overflow */ + shd 0,x2,29,t1 + shd x2,0,29,t2 + sub t2,x2,x2 + b LREF(pos7) + subb t1,0,x1 + +LSYM(neg9) + subi 1,x2,x2 /* negate and add 1 */ + shd 0,x2,29,t1 + shd x2,0,29,t2 + sub t2,x2,x2 + b LREF(neg7_shift) + subb t1,0,x1 + +GSYM($$divU_9) + .export $$divU_9,millicode + addi 1,x2,x2 /* can carry */ + addc 0,0,x1 + shd x1,x2,29,t1 + shd x2,0,29,t2 + sub t2,x2,x2 + b LREF(pos7) + subb t1,x1,x1 + +/* DIVISION BY 14 (shift to divide by 2 then divide by 7) */ +GSYM($$divI_14) + .export $$divI_14,millicode + comb,<,n x2,0,LREF(neg14) +GSYM($$divU_14) + .export $$divU_14,millicode + b LREF(7) /* go to 7 case */ + extru x2,30,31,x2 /* divide by 2 */ + +LSYM(neg14) + subi 2,x2,x2 /* negate (and add 2) */ + b LREF(8) + extru x2,30,31,x2 /* divide by 2 */ + .exit + .procend + .end +#endif diff --git a/trunk/arch/parisc/lib/milli/dyncall.S b/trunk/arch/parisc/lib/milli/dyncall.S new file mode 100644 index 000000000000..27f9ca558d0a --- /dev/null +++ b/trunk/arch/parisc/lib/milli/dyncall.S @@ -0,0 +1,32 @@ +/* 32 and 64-bit millicode, original author Hewlett-Packard + adapted for gcc by Paul Bame + and Alan Modra . + + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + This file is part of GCC and is released under the terms of + of the GNU General Public License as published by the Free Software + Foundation; either version 2, or (at your option) any later version. + See the file COPYING in the top-level GCC source directory for a copy + of the license. */ + +#include "milli.h" + +#ifdef L_dyncall + SUBSPA_MILLI + ATTR_DATA +GSYM($$dyncall) + .export $$dyncall,millicode + .proc + .callinfo millicode + .entry + bb,>=,n %r22,30,LREF(1) ; branch if not plabel address + depi 0,31,2,%r22 ; clear the two least significant bits + ldw 4(%r22),%r19 ; load new LTP value + ldw 0(%r22),%r22 ; load address of target +LSYM(1) + bv %r0(%r22) ; branch to the real target + stw %r2,-24(%r30) ; save return address into frame marker + .exit + .procend +#endif diff --git a/trunk/arch/parisc/lib/milli/milli.S b/trunk/arch/parisc/lib/milli/milli.S new file mode 100644 index 000000000000..47c6cde712e3 --- /dev/null +++ b/trunk/arch/parisc/lib/milli/milli.S @@ -0,0 +1,2071 @@ +/* 32 and 64-bit millicode, original author Hewlett-Packard + adapted for gcc by Paul Bame + and Alan Modra . + + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + This file is part of GCC and is released under the terms of + of the GNU General Public License as published by the Free Software + Foundation; either version 2, or (at your option) any later version. + See the file COPYING in the top-level GCC source directory for a copy + of the license. */ + +#ifdef CONFIG_64BIT + .level 2.0w +#endif + +/* Hardware General Registers. */ +r0: .reg %r0 +r1: .reg %r1 +r2: .reg %r2 +r3: .reg %r3 +r4: .reg %r4 +r5: .reg %r5 +r6: .reg %r6 +r7: .reg %r7 +r8: .reg %r8 +r9: .reg %r9 +r10: .reg %r10 +r11: .reg %r11 +r12: .reg %r12 +r13: .reg %r13 +r14: .reg %r14 +r15: .reg %r15 +r16: .reg %r16 +r17: .reg %r17 +r18: .reg %r18 +r19: .reg %r19 +r20: .reg %r20 +r21: .reg %r21 +r22: .reg %r22 +r23: .reg %r23 +r24: .reg %r24 +r25: .reg %r25 +r26: .reg %r26 +r27: .reg %r27 +r28: .reg %r28 +r29: .reg %r29 +r30: .reg %r30 +r31: .reg %r31 + +/* Hardware Space Registers. */ +sr0: .reg %sr0 +sr1: .reg %sr1 +sr2: .reg %sr2 +sr3: .reg %sr3 +sr4: .reg %sr4 +sr5: .reg %sr5 +sr6: .reg %sr6 +sr7: .reg %sr7 + +/* Hardware Floating Point Registers. */ +fr0: .reg %fr0 +fr1: .reg %fr1 +fr2: .reg %fr2 +fr3: .reg %fr3 +fr4: .reg %fr4 +fr5: .reg %fr5 +fr6: .reg %fr6 +fr7: .reg %fr7 +fr8: .reg %fr8 +fr9: .reg %fr9 +fr10: .reg %fr10 +fr11: .reg %fr11 +fr12: .reg %fr12 +fr13: .reg %fr13 +fr14: .reg %fr14 +fr15: .reg %fr15 + +/* Hardware Control Registers. */ +cr11: .reg %cr11 +sar: .reg %cr11 /* Shift Amount Register */ + +/* Software Architecture General Registers. */ +rp: .reg r2 /* return pointer */ +#ifdef CONFIG_64BIT +mrp: .reg r2 /* millicode return pointer */ +#else +mrp: .reg r31 /* millicode return pointer */ +#endif +ret0: .reg r28 /* return value */ +ret1: .reg r29 /* return value (high part of double) */ +sp: .reg r30 /* stack pointer */ +dp: .reg r27 /* data pointer */ +arg0: .reg r26 /* argument */ +arg1: .reg r25 /* argument or high part of double argument */ +arg2: .reg r24 /* argument */ +arg3: .reg r23 /* argument or high part of double argument */ + +/* Software Architecture Space Registers. */ +/* sr0 ; return link from BLE */ +sret: .reg sr1 /* return value */ +sarg: .reg sr1 /* argument */ +/* sr4 ; PC SPACE tracker */ +/* sr5 ; process private data */ + +/* Frame Offsets (millicode convention!) Used when calling other + millicode routines. Stack unwinding is dependent upon these + definitions. */ +r31_slot: .equ -20 /* "current RP" slot */ +sr0_slot: .equ -16 /* "static link" slot */ +#if defined(CONFIG_64BIT) +mrp_slot: .equ -16 /* "current RP" slot */ +psp_slot: .equ -8 /* "previous SP" slot */ +#else +mrp_slot: .equ -20 /* "current RP" slot (replacing "r31_slot") */ +#endif + + +#define DEFINE(name,value)name: .EQU value +#define RDEFINE(name,value)name: .REG value +#ifdef milliext +#define MILLI_BE(lbl) BE lbl(sr7,r0) +#define MILLI_BEN(lbl) BE,n lbl(sr7,r0) +#define MILLI_BLE(lbl) BLE lbl(sr7,r0) +#define MILLI_BLEN(lbl) BLE,n lbl(sr7,r0) +#define MILLIRETN BE,n 0(sr0,mrp) +#define MILLIRET BE 0(sr0,mrp) +#define MILLI_RETN BE,n 0(sr0,mrp) +#define MILLI_RET BE 0(sr0,mrp) +#else +#define MILLI_BE(lbl) B lbl +#define MILLI_BEN(lbl) B,n lbl +#define MILLI_BLE(lbl) BL lbl,mrp +#define MILLI_BLEN(lbl) BL,n lbl,mrp +#define MILLIRETN BV,n 0(mrp) +#define MILLIRET BV 0(mrp) +#define MILLI_RETN BV,n 0(mrp) +#define MILLI_RET BV 0(mrp) +#endif + +#define CAT(a,b) a##b + +#define SUBSPA_MILLI .section .text +#define SUBSPA_MILLI_DIV .section .text.div,"ax",@progbits! .align 16 +#define SUBSPA_MILLI_MUL .section .text.mul,"ax",@progbits! .align 16 +#define ATTR_MILLI +#define SUBSPA_DATA .section .data +#define ATTR_DATA +#define GLOBAL $global$ +#define GSYM(sym) !sym: +#define LSYM(sym) !CAT(.L,sym:) +#define LREF(sym) CAT(.L,sym) + +#ifdef L_dyncall + SUBSPA_MILLI + ATTR_DATA +GSYM($$dyncall) + .export $$dyncall,millicode + .proc + .callinfo millicode + .entry + bb,>=,n %r22,30,LREF(1) ; branch if not plabel address + depi 0,31,2,%r22 ; clear the two least significant bits + ldw 4(%r22),%r19 ; load new LTP value + ldw 0(%r22),%r22 ; load address of target +LSYM(1) + bv %r0(%r22) ; branch to the real target + stw %r2,-24(%r30) ; save return address into frame marker + .exit + .procend +#endif + +#ifdef L_divI +/* ROUTINES: $$divI, $$divoI + + Single precision divide for signed binary integers. + + The quotient is truncated towards zero. + The sign of the quotient is the XOR of the signs of the dividend and + divisor. + Divide by zero is trapped. + Divide of -2**31 by -1 is trapped for $$divoI but not for $$divI. + + INPUT REGISTERS: + . arg0 == dividend + . arg1 == divisor + . mrp == return pc + . sr0 == return space when called externally + + OUTPUT REGISTERS: + . arg0 = undefined + . arg1 = undefined + . ret1 = quotient + + OTHER REGISTERS AFFECTED: + . r1 = undefined + + SIDE EFFECTS: + . Causes a trap under the following conditions: + . divisor is zero (traps with ADDIT,= 0,25,0) + . dividend==-2**31 and divisor==-1 and routine is $$divoI + . (traps with ADDO 26,25,0) + . Changes memory at the following places: + . NONE + + PERMISSIBLE CONTEXT: + . Unwindable. + . Suitable for internal or external millicode. + . Assumes the special millicode register conventions. + + DISCUSSION: + . Branchs to other millicode routines using BE + . $$div_# for # being 2,3,4,5,6,7,8,9,10,12,14,15 + . + . For selected divisors, calls a divide by constant routine written by + . Karl Pettis. Eligible divisors are 1..15 excluding 11 and 13. + . + . The only overflow case is -2**31 divided by -1. + . Both routines return -2**31 but only $$divoI traps. */ + +RDEFINE(temp,r1) +RDEFINE(retreg,ret1) /* r29 */ +RDEFINE(temp1,arg0) + SUBSPA_MILLI_DIV + ATTR_MILLI + .import $$divI_2,millicode + .import $$divI_3,millicode + .import $$divI_4,millicode + .import $$divI_5,millicode + .import $$divI_6,millicode + .import $$divI_7,millicode + .import $$divI_8,millicode + .import $$divI_9,millicode + .import $$divI_10,millicode + .import $$divI_12,millicode + .import $$divI_14,millicode + .import $$divI_15,millicode + .export $$divI,millicode + .export $$divoI,millicode + .proc + .callinfo millicode + .entry +GSYM($$divoI) + comib,=,n -1,arg1,LREF(negative1) /* when divisor == -1 */ +GSYM($$divI) + ldo -1(arg1),temp /* is there at most one bit set ? */ + and,<> arg1,temp,r0 /* if not, don't use power of 2 divide */ + addi,> 0,arg1,r0 /* if divisor > 0, use power of 2 divide */ + b,n LREF(neg_denom) +LSYM(pow2) + addi,>= 0,arg0,retreg /* if numerator is negative, add the */ + add arg0,temp,retreg /* (denominaotr -1) to correct for shifts */ + extru,= arg1,15,16,temp /* test denominator with 0xffff0000 */ + extrs retreg,15,16,retreg /* retreg = retreg >> 16 */ + or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 16) */ + ldi 0xcc,temp1 /* setup 0xcc in temp1 */ + extru,= arg1,23,8,temp /* test denominator with 0xff00 */ + extrs retreg,23,24,retreg /* retreg = retreg >> 8 */ + or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 8) */ + ldi 0xaa,temp /* setup 0xaa in temp */ + extru,= arg1,27,4,r0 /* test denominator with 0xf0 */ + extrs retreg,27,28,retreg /* retreg = retreg >> 4 */ + and,= arg1,temp1,r0 /* test denominator with 0xcc */ + extrs retreg,29,30,retreg /* retreg = retreg >> 2 */ + and,= arg1,temp,r0 /* test denominator with 0xaa */ + extrs retreg,30,31,retreg /* retreg = retreg >> 1 */ + MILLIRETN +LSYM(neg_denom) + addi,< 0,arg1,r0 /* if arg1 >= 0, it's not power of 2 */ + b,n LREF(regular_seq) + sub r0,arg1,temp /* make denominator positive */ + comb,=,n arg1,temp,LREF(regular_seq) /* test against 0x80000000 and 0 */ + ldo -1(temp),retreg /* is there at most one bit set ? */ + and,= temp,retreg,r0 /* if so, the denominator is power of 2 */ + b,n LREF(regular_seq) + sub r0,arg0,retreg /* negate numerator */ + comb,=,n arg0,retreg,LREF(regular_seq) /* test against 0x80000000 */ + copy retreg,arg0 /* set up arg0, arg1 and temp */ + copy temp,arg1 /* before branching to pow2 */ + b LREF(pow2) + ldo -1(arg1),temp +LSYM(regular_seq) + comib,>>=,n 15,arg1,LREF(small_divisor) + add,>= 0,arg0,retreg /* move dividend, if retreg < 0, */ +LSYM(normal) + subi 0,retreg,retreg /* make it positive */ + sub 0,arg1,temp /* clear carry, */ + /* negate the divisor */ + ds 0,temp,0 /* set V-bit to the comple- */ + /* ment of the divisor sign */ + add retreg,retreg,retreg /* shift msb bit into carry */ + ds r0,arg1,temp /* 1st divide step, if no carry */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 2nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 3rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 4th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 5th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 6th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 7th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 8th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 9th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 10th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 11th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 12th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 13th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 14th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 15th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 16th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 17th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 18th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 19th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 20th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 21st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 22nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 23rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 24th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 25th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 26th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 27th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 28th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 29th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 30th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 31st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 32nd divide step, */ + addc retreg,retreg,retreg /* shift last retreg bit into retreg */ + xor,>= arg0,arg1,0 /* get correct sign of quotient */ + sub 0,retreg,retreg /* based on operand signs */ + MILLIRETN + nop + +LSYM(small_divisor) + +#if defined(CONFIG_64BIT) +/* Clear the upper 32 bits of the arg1 register. We are working with */ +/* small divisors (and 32-bit integers) We must not be mislead */ +/* by "1" bits left in the upper 32 bits. */ + depd %r0,31,32,%r25 +#endif + blr,n arg1,r0 + nop +/* table for divisor == 0,1, ... ,15 */ + addit,= 0,arg1,r0 /* trap if divisor == 0 */ + nop + MILLIRET /* divisor == 1 */ + copy arg0,retreg + MILLI_BEN($$divI_2) /* divisor == 2 */ + nop + MILLI_BEN($$divI_3) /* divisor == 3 */ + nop + MILLI_BEN($$divI_4) /* divisor == 4 */ + nop + MILLI_BEN($$divI_5) /* divisor == 5 */ + nop + MILLI_BEN($$divI_6) /* divisor == 6 */ + nop + MILLI_BEN($$divI_7) /* divisor == 7 */ + nop + MILLI_BEN($$divI_8) /* divisor == 8 */ + nop + MILLI_BEN($$divI_9) /* divisor == 9 */ + nop + MILLI_BEN($$divI_10) /* divisor == 10 */ + nop + b LREF(normal) /* divisor == 11 */ + add,>= 0,arg0,retreg + MILLI_BEN($$divI_12) /* divisor == 12 */ + nop + b LREF(normal) /* divisor == 13 */ + add,>= 0,arg0,retreg + MILLI_BEN($$divI_14) /* divisor == 14 */ + nop + MILLI_BEN($$divI_15) /* divisor == 15 */ + nop + +LSYM(negative1) + sub 0,arg0,retreg /* result is negation of dividend */ + MILLIRET + addo arg0,arg1,r0 /* trap iff dividend==0x80000000 && divisor==-1 */ + .exit + .procend + .end +#endif + +#ifdef L_divU +/* ROUTINE: $$divU + . + . Single precision divide for unsigned integers. + . + . Quotient is truncated towards zero. + . Traps on divide by zero. + + INPUT REGISTERS: + . arg0 == dividend + . arg1 == divisor + . mrp == return pc + . sr0 == return space when called externally + + OUTPUT REGISTERS: + . arg0 = undefined + . arg1 = undefined + . ret1 = quotient + + OTHER REGISTERS AFFECTED: + . r1 = undefined + + SIDE EFFECTS: + . Causes a trap under the following conditions: + . divisor is zero + . Changes memory at the following places: + . NONE + + PERMISSIBLE CONTEXT: + . Unwindable. + . Does not create a stack frame. + . Suitable for internal or external millicode. + . Assumes the special millicode register conventions. + + DISCUSSION: + . Branchs to other millicode routines using BE: + . $$divU_# for 3,5,6,7,9,10,12,14,15 + . + . For selected small divisors calls the special divide by constant + . routines written by Karl Pettis. These are: 3,5,6,7,9,10,12,14,15. */ + +RDEFINE(temp,r1) +RDEFINE(retreg,ret1) /* r29 */ +RDEFINE(temp1,arg0) + SUBSPA_MILLI_DIV + ATTR_MILLI + .export $$divU,millicode + .import $$divU_3,millicode + .import $$divU_5,millicode + .import $$divU_6,millicode + .import $$divU_7,millicode + .import $$divU_9,millicode + .import $$divU_10,millicode + .import $$divU_12,millicode + .import $$divU_14,millicode + .import $$divU_15,millicode + .proc + .callinfo millicode + .entry +GSYM($$divU) +/* The subtract is not nullified since it does no harm and can be used + by the two cases that branch back to "normal". */ + ldo -1(arg1),temp /* is there at most one bit set ? */ + and,= arg1,temp,r0 /* if so, denominator is power of 2 */ + b LREF(regular_seq) + addit,= 0,arg1,0 /* trap for zero dvr */ + copy arg0,retreg + extru,= arg1,15,16,temp /* test denominator with 0xffff0000 */ + extru retreg,15,16,retreg /* retreg = retreg >> 16 */ + or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 16) */ + ldi 0xcc,temp1 /* setup 0xcc in temp1 */ + extru,= arg1,23,8,temp /* test denominator with 0xff00 */ + extru retreg,23,24,retreg /* retreg = retreg >> 8 */ + or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 8) */ + ldi 0xaa,temp /* setup 0xaa in temp */ + extru,= arg1,27,4,r0 /* test denominator with 0xf0 */ + extru retreg,27,28,retreg /* retreg = retreg >> 4 */ + and,= arg1,temp1,r0 /* test denominator with 0xcc */ + extru retreg,29,30,retreg /* retreg = retreg >> 2 */ + and,= arg1,temp,r0 /* test denominator with 0xaa */ + extru retreg,30,31,retreg /* retreg = retreg >> 1 */ + MILLIRETN + nop +LSYM(regular_seq) + comib,>= 15,arg1,LREF(special_divisor) + subi 0,arg1,temp /* clear carry, negate the divisor */ + ds r0,temp,r0 /* set V-bit to 1 */ +LSYM(normal) + add arg0,arg0,retreg /* shift msb bit into carry */ + ds r0,arg1,temp /* 1st divide step, if no carry */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 2nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 3rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 4th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 5th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 6th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 7th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 8th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 9th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 10th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 11th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 12th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 13th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 14th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 15th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 16th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 17th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 18th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 19th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 20th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 21st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 22nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 23rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 24th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 25th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 26th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 27th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 28th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 29th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 30th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 31st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 32nd divide step, */ + MILLIRET + addc retreg,retreg,retreg /* shift last retreg bit into retreg */ + +/* Handle the cases where divisor is a small constant or has high bit on. */ +LSYM(special_divisor) +/* blr arg1,r0 */ +/* comib,>,n 0,arg1,LREF(big_divisor) ; nullify previous instruction */ + +/* Pratap 8/13/90. The 815 Stirling chip set has a bug that prevents us from + generating such a blr, comib sequence. A problem in nullification. So I + rewrote this code. */ + +#if defined(CONFIG_64BIT) +/* Clear the upper 32 bits of the arg1 register. We are working with + small divisors (and 32-bit unsigned integers) We must not be mislead + by "1" bits left in the upper 32 bits. */ + depd %r0,31,32,%r25 +#endif + comib,> 0,arg1,LREF(big_divisor) + nop + blr arg1,r0 + nop + +LSYM(zero_divisor) /* this label is here to provide external visibility */ + addit,= 0,arg1,0 /* trap for zero dvr */ + nop + MILLIRET /* divisor == 1 */ + copy arg0,retreg + MILLIRET /* divisor == 2 */ + extru arg0,30,31,retreg + MILLI_BEN($$divU_3) /* divisor == 3 */ + nop + MILLIRET /* divisor == 4 */ + extru arg0,29,30,retreg + MILLI_BEN($$divU_5) /* divisor == 5 */ + nop + MILLI_BEN($$divU_6) /* divisor == 6 */ + nop + MILLI_BEN($$divU_7) /* divisor == 7 */ + nop + MILLIRET /* divisor == 8 */ + extru arg0,28,29,retreg + MILLI_BEN($$divU_9) /* divisor == 9 */ + nop + MILLI_BEN($$divU_10) /* divisor == 10 */ + nop + b LREF(normal) /* divisor == 11 */ + ds r0,temp,r0 /* set V-bit to 1 */ + MILLI_BEN($$divU_12) /* divisor == 12 */ + nop + b LREF(normal) /* divisor == 13 */ + ds r0,temp,r0 /* set V-bit to 1 */ + MILLI_BEN($$divU_14) /* divisor == 14 */ + nop + MILLI_BEN($$divU_15) /* divisor == 15 */ + nop + +/* Handle the case where the high bit is on in the divisor. + Compute: if( dividend>=divisor) quotient=1; else quotient=0; + Note: dividend>==divisor iff dividend-divisor does not borrow + and not borrow iff carry. */ +LSYM(big_divisor) + sub arg0,arg1,r0 + MILLIRET + addc r0,r0,retreg + .exit + .procend + .end +#endif + +#ifdef L_remI +/* ROUTINE: $$remI + + DESCRIPTION: + . $$remI returns the remainder of the division of two signed 32-bit + . integers. The sign of the remainder is the same as the sign of + . the dividend. + + + INPUT REGISTERS: + . arg0 == dividend + . arg1 == divisor + . mrp == return pc + . sr0 == return space when called externally + + OUTPUT REGISTERS: + . arg0 = destroyed + . arg1 = destroyed + . ret1 = remainder + + OTHER REGISTERS AFFECTED: + . r1 = undefined + + SIDE EFFECTS: + . Causes a trap under the following conditions: DIVIDE BY ZERO + . Changes memory at the following places: NONE + + PERMISSIBLE CONTEXT: + . Unwindable + . Does not create a stack frame + . Is usable for internal or external microcode + + DISCUSSION: + . Calls other millicode routines via mrp: NONE + . Calls other millicode routines: NONE */ + +RDEFINE(tmp,r1) +RDEFINE(retreg,ret1) + + SUBSPA_MILLI + ATTR_MILLI + .proc + .callinfo millicode + .entry +GSYM($$remI) +GSYM($$remoI) + .export $$remI,MILLICODE + .export $$remoI,MILLICODE + ldo -1(arg1),tmp /* is there at most one bit set ? */ + and,<> arg1,tmp,r0 /* if not, don't use power of 2 */ + addi,> 0,arg1,r0 /* if denominator > 0, use power */ + /* of 2 */ + b,n LREF(neg_denom) +LSYM(pow2) + comb,>,n 0,arg0,LREF(neg_num) /* is numerator < 0 ? */ + and arg0,tmp,retreg /* get the result */ + MILLIRETN +LSYM(neg_num) + subi 0,arg0,arg0 /* negate numerator */ + and arg0,tmp,retreg /* get the result */ + subi 0,retreg,retreg /* negate result */ + MILLIRETN +LSYM(neg_denom) + addi,< 0,arg1,r0 /* if arg1 >= 0, it's not power */ + /* of 2 */ + b,n LREF(regular_seq) + sub r0,arg1,tmp /* make denominator positive */ + comb,=,n arg1,tmp,LREF(regular_seq) /* test against 0x80000000 and 0 */ + ldo -1(tmp),retreg /* is there at most one bit set ? */ + and,= tmp,retreg,r0 /* if not, go to regular_seq */ + b,n LREF(regular_seq) + comb,>,n 0,arg0,LREF(neg_num_2) /* if arg0 < 0, negate it */ + and arg0,retreg,retreg + MILLIRETN +LSYM(neg_num_2) + subi 0,arg0,tmp /* test against 0x80000000 */ + and tmp,retreg,retreg + subi 0,retreg,retreg + MILLIRETN +LSYM(regular_seq) + addit,= 0,arg1,0 /* trap if div by zero */ + add,>= 0,arg0,retreg /* move dividend, if retreg < 0, */ + sub 0,retreg,retreg /* make it positive */ + sub 0,arg1, tmp /* clear carry, */ + /* negate the divisor */ + ds 0, tmp,0 /* set V-bit to the comple- */ + /* ment of the divisor sign */ + or 0,0, tmp /* clear tmp */ + add retreg,retreg,retreg /* shift msb bit into carry */ + ds tmp,arg1, tmp /* 1st divide step, if no carry */ + /* out, msb of quotient = 0 */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ +LSYM(t1) + ds tmp,arg1, tmp /* 2nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 3rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 4th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 5th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 6th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 7th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 8th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 9th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 10th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 11th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 12th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 13th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 14th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 15th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 16th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 17th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 18th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 19th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 20th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 21st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 22nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 23rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 24th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 25th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 26th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 27th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 28th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 29th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 30th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 31st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 32nd divide step, */ + addc retreg,retreg,retreg /* shift last bit into retreg */ + movb,>=,n tmp,retreg,LREF(finish) /* branch if pos. tmp */ + add,< arg1,0,0 /* if arg1 > 0, add arg1 */ + add,tr tmp,arg1,retreg /* for correcting remainder tmp */ + sub tmp,arg1,retreg /* else add absolute value arg1 */ +LSYM(finish) + add,>= arg0,0,0 /* set sign of remainder */ + sub 0,retreg,retreg /* to sign of dividend */ + MILLIRET + nop + .exit + .procend +#ifdef milliext + .origin 0x00000200 +#endif + .end +#endif + +#ifdef L_remU +/* ROUTINE: $$remU + . Single precision divide for remainder with unsigned binary integers. + . + . The remainder must be dividend-(dividend/divisor)*divisor. + . Divide by zero is trapped. + + INPUT REGISTERS: + . arg0 == dividend + . arg1 == divisor + . mrp == return pc + . sr0 == return space when called externally + + OUTPUT REGISTERS: + . arg0 = undefined + . arg1 = undefined + . ret1 = remainder + + OTHER REGISTERS AFFECTED: + . r1 = undefined + + SIDE EFFECTS: + . Causes a trap under the following conditions: DIVIDE BY ZERO + . Changes memory at the following places: NONE + + PERMISSIBLE CONTEXT: + . Unwindable. + . Does not create a stack frame. + . Suitable for internal or external millicode. + . Assumes the special millicode register conventions. + + DISCUSSION: + . Calls other millicode routines using mrp: NONE + . Calls other millicode routines: NONE */ + + +RDEFINE(temp,r1) +RDEFINE(rmndr,ret1) /* r29 */ + SUBSPA_MILLI + ATTR_MILLI + .export $$remU,millicode + .proc + .callinfo millicode + .entry +GSYM($$remU) + ldo -1(arg1),temp /* is there at most one bit set ? */ + and,= arg1,temp,r0 /* if not, don't use power of 2 */ + b LREF(regular_seq) + addit,= 0,arg1,r0 /* trap on div by zero */ + and arg0,temp,rmndr /* get the result for power of 2 */ + MILLIRETN +LSYM(regular_seq) + comib,>=,n 0,arg1,LREF(special_case) + subi 0,arg1,rmndr /* clear carry, negate the divisor */ + ds r0,rmndr,r0 /* set V-bit to 1 */ + add arg0,arg0,temp /* shift msb bit into carry */ + ds r0,arg1,rmndr /* 1st divide step, if no carry */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 2nd divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 3rd divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 4th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 5th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 6th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 7th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 8th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 9th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 10th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 11th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 12th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 13th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 14th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 15th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 16th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 17th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 18th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 19th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 20th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 21st divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 22nd divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 23rd divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 24th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 25th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 26th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 27th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 28th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 29th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 30th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 31st divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 32nd divide step, */ + comiclr,<= 0,rmndr,r0 + add rmndr,arg1,rmndr /* correction */ + MILLIRETN + nop + +/* Putting >= on the last DS and deleting COMICLR does not work! */ +LSYM(special_case) + sub,>>= arg0,arg1,rmndr + copy arg0,rmndr + MILLIRETN + nop + .exit + .procend + .end +#endif + +#ifdef L_div_const +/* ROUTINE: $$divI_2 + . $$divI_3 $$divU_3 + . $$divI_4 + . $$divI_5 $$divU_5 + . $$divI_6 $$divU_6 + . $$divI_7 $$divU_7 + . $$divI_8 + . $$divI_9 $$divU_9 + . $$divI_10 $$divU_10 + . + . $$divI_12 $$divU_12 + . + . $$divI_14 $$divU_14 + . $$divI_15 $$divU_15 + . $$divI_16 + . $$divI_17 $$divU_17 + . + . Divide by selected constants for single precision binary integers. + + INPUT REGISTERS: + . arg0 == dividend + . mrp == return pc + . sr0 == return space when called externally + + OUTPUT REGISTERS: + . arg0 = undefined + . arg1 = undefined + . ret1 = quotient + + OTHER REGISTERS AFFECTED: + . r1 = undefined + + SIDE EFFECTS: + . Causes a trap under the following conditions: NONE + . Changes memory at the following places: NONE + + PERMISSIBLE CONTEXT: + . Unwindable. + . Does not create a stack frame. + . Suitable for internal or external millicode. + . Assumes the special millicode register conventions. + + DISCUSSION: + . Calls other millicode routines using mrp: NONE + . Calls other millicode routines: NONE */ + + +/* TRUNCATED DIVISION BY SMALL INTEGERS + + We are interested in q(x) = floor(x/y), where x >= 0 and y > 0 + (with y fixed). + + Let a = floor(z/y), for some choice of z. Note that z will be + chosen so that division by z is cheap. + + Let r be the remainder(z/y). In other words, r = z - ay. + + Now, our method is to choose a value for b such that + + q'(x) = floor((ax+b)/z) + + is equal to q(x) over as large a range of x as possible. If the + two are equal over a sufficiently large range, and if it is easy to + form the product (ax), and it is easy to divide by z, then we can + perform the division much faster than the general division algorithm. + + So, we want the following to be true: + + . For x in the following range: + . + . ky <= x < (k+1)y + . + . implies that + . + . k <= (ax+b)/z < (k+1) + + We want to determine b such that this is true for all k in the + range {0..K} for some maximum K. + + Since (ax+b) is an increasing function of x, we can take each + bound separately to determine the "best" value for b. + + (ax+b)/z < (k+1) implies + + (a((k+1)y-1)+b < (k+1)z implies + + b < a + (k+1)(z-ay) implies + + b < a + (k+1)r + + This needs to be true for all k in the range {0..K}. In + particular, it is true for k = 0 and this leads to a maximum + acceptable value for b. + + b < a+r or b <= a+r-1 + + Taking the other bound, we have + + k <= (ax+b)/z implies + + k <= (aky+b)/z implies + + k(z-ay) <= b implies + + kr <= b + + Clearly, the largest range for k will be achieved by maximizing b, + when r is not zero. When r is zero, then the simplest choice for b + is 0. When r is not 0, set + + . b = a+r-1 + + Now, by construction, q'(x) = floor((ax+b)/z) = q(x) = floor(x/y) + for all x in the range: + + . 0 <= x < (K+1)y + + We need to determine what K is. Of our two bounds, + + . b < a+(k+1)r is satisfied for all k >= 0, by construction. + + The other bound is + + . kr <= b + + This is always true if r = 0. If r is not 0 (the usual case), then + K = floor((a+r-1)/r), is the maximum value for k. + + Therefore, the formula q'(x) = floor((ax+b)/z) yields the correct + answer for q(x) = floor(x/y) when x is in the range + + (0,(K+1)y-1) K = floor((a+r-1)/r) + + To be most useful, we want (K+1)y-1 = (max x) >= 2**32-1 so that + the formula for q'(x) yields the correct value of q(x) for all x + representable by a single word in HPPA. + + We are also constrained in that computing the product (ax), adding + b, and dividing by z must all be done quickly, otherwise we will be + better off going through the general algorithm using the DS + instruction, which uses approximately 70 cycles. + + For each y, there is a choice of z which satisfies the constraints + for (K+1)y >= 2**32. We may not, however, be able to satisfy the + timing constraints for arbitrary y. It seems that z being equal to + a power of 2 or a power of 2 minus 1 is as good as we can do, since + it minimizes the time to do division by z. We want the choice of z + to also result in a value for (a) that minimizes the computation of + the product (ax). This is best achieved if (a) has a regular bit + pattern (so the multiplication can be done with shifts and adds). + The value of (a) also needs to be less than 2**32 so the product is + always guaranteed to fit in 2 words. + + In actual practice, the following should be done: + + 1) For negative x, you should take the absolute value and remember + . the fact so that the result can be negated. This obviously does + . not apply in the unsigned case. + 2) For even y, you should factor out the power of 2 that divides y + . and divide x by it. You can then proceed by dividing by the + . odd factor of y. + + Here is a table of some odd values of y, and corresponding choices + for z which are "good". + + y z r a (hex) max x (hex) + + 3 2**32 1 55555555 100000001 + 5 2**32 1 33333333 100000003 + 7 2**24-1 0 249249 (infinite) + 9 2**24-1 0 1c71c7 (infinite) + 11 2**20-1 0 1745d (infinite) + 13 2**24-1 0 13b13b (infinite) + 15 2**32 1 11111111 10000000d + 17 2**32 1 f0f0f0f 10000000f + + If r is 1, then b = a+r-1 = a. This simplifies the computation + of (ax+b), since you can compute (x+1)(a) instead. If r is 0, + then b = 0 is ok to use which simplifies (ax+b). + + The bit patterns for 55555555, 33333333, and 11111111 are obviously + very regular. The bit patterns for the other values of a above are: + + y (hex) (binary) + + 7 249249 001001001001001001001001 << regular >> + 9 1c71c7 000111000111000111000111 << regular >> + 11 1745d 000000010111010001011101 << irregular >> + 13 13b13b 000100111011000100111011 << irregular >> + + The bit patterns for (a) corresponding to (y) of 11 and 13 may be + too irregular to warrant using this method. + + When z is a power of 2 minus 1, then the division by z is slightly + more complicated, involving an iterative solution. + + The code presented here solves division by 1 through 17, except for + 11 and 13. There are algorithms for both signed and unsigned + quantities given. + + TIMINGS (cycles) + + divisor positive negative unsigned + + . 1 2 2 2 + . 2 4 4 2 + . 3 19 21 19 + . 4 4 4 2 + . 5 18 22 19 + . 6 19 22 19 + . 8 4 4 2 + . 10 18 19 17 + . 12 18 20 18 + . 15 16 18 16 + . 16 4 4 2 + . 17 16 18 16 + + Now, the algorithm for 7, 9, and 14 is an iterative one. That is, + a loop body is executed until the tentative quotient is 0. The + number of times the loop body is executed varies depending on the + dividend, but is never more than two times. If the dividend is + less than the divisor, then the loop body is not executed at all. + Each iteration adds 4 cycles to the timings. + + divisor positive negative unsigned + + . 7 19+4n 20+4n 20+4n n = number of iterations + . 9 21+4n 22+4n 21+4n + . 14 21+4n 22+4n 20+4n + + To give an idea of how the number of iterations varies, here is a + table of dividend versus number of iterations when dividing by 7. + + smallest largest required + dividend dividend iterations + + . 0 6 0 + . 7 0x6ffffff 1 + 0x1000006 0xffffffff 2 + + There is some overlap in the range of numbers requiring 1 and 2 + iterations. */ + +RDEFINE(t2,r1) +RDEFINE(x2,arg0) /* r26 */ +RDEFINE(t1,arg1) /* r25 */ +RDEFINE(x1,ret1) /* r29 */ + + SUBSPA_MILLI_DIV + ATTR_MILLI + + .proc + .callinfo millicode + .entry +/* NONE of these routines require a stack frame + ALL of these routines are unwindable from millicode */ + +GSYM($$divide_by_constant) + .export $$divide_by_constant,millicode +/* Provides a "nice" label for the code covered by the unwind descriptor + for things like gprof. */ + +/* DIVISION BY 2 (shift by 1) */ +GSYM($$divI_2) + .export $$divI_2,millicode + comclr,>= arg0,0,0 + addi 1,arg0,arg0 + MILLIRET + extrs arg0,30,31,ret1 + + +/* DIVISION BY 4 (shift by 2) */ +GSYM($$divI_4) + .export $$divI_4,millicode + comclr,>= arg0,0,0 + addi 3,arg0,arg0 + MILLIRET + extrs arg0,29,30,ret1 + + +/* DIVISION BY 8 (shift by 3) */ +GSYM($$divI_8) + .export $$divI_8,millicode + comclr,>= arg0,0,0 + addi 7,arg0,arg0 + MILLIRET + extrs arg0,28,29,ret1 + +/* DIVISION BY 16 (shift by 4) */ +GSYM($$divI_16) + .export $$divI_16,millicode + comclr,>= arg0,0,0 + addi 15,arg0,arg0 + MILLIRET + extrs arg0,27,28,ret1 + +/**************************************************************************** +* +* DIVISION BY DIVISORS OF FFFFFFFF, and powers of 2 times these +* +* includes 3,5,15,17 and also 6,10,12 +* +****************************************************************************/ + +/* DIVISION BY 3 (use z = 2**32; a = 55555555) */ + +GSYM($$divI_3) + .export $$divI_3,millicode + comb,<,N x2,0,LREF(neg3) + + addi 1,x2,x2 /* this cannot overflow */ + extru x2,1,2,x1 /* multiply by 5 to get started */ + sh2add x2,x2,x2 + b LREF(pos) + addc x1,0,x1 + +LSYM(neg3) + subi 1,x2,x2 /* this cannot overflow */ + extru x2,1,2,x1 /* multiply by 5 to get started */ + sh2add x2,x2,x2 + b LREF(neg) + addc x1,0,x1 + +GSYM($$divU_3) + .export $$divU_3,millicode + addi 1,x2,x2 /* this CAN overflow */ + addc 0,0,x1 + shd x1,x2,30,t1 /* multiply by 5 to get started */ + sh2add x2,x2,x2 + b LREF(pos) + addc x1,t1,x1 + +/* DIVISION BY 5 (use z = 2**32; a = 33333333) */ + +GSYM($$divI_5) + .export $$divI_5,millicode + comb,<,N x2,0,LREF(neg5) + + addi 3,x2,t1 /* this cannot overflow */ + sh1add x2,t1,x2 /* multiply by 3 to get started */ + b LREF(pos) + addc 0,0,x1 + +LSYM(neg5) + sub 0,x2,x2 /* negate x2 */ + addi 1,x2,x2 /* this cannot overflow */ + shd 0,x2,31,x1 /* get top bit (can be 1) */ + sh1add x2,x2,x2 /* multiply by 3 to get started */ + b LREF(neg) + addc x1,0,x1 + +GSYM($$divU_5) + .export $$divU_5,millicode + addi 1,x2,x2 /* this CAN overflow */ + addc 0,0,x1 + shd x1,x2,31,t1 /* multiply by 3 to get started */ + sh1add x2,x2,x2 + b LREF(pos) + addc t1,x1,x1 + +/* DIVISION BY 6 (shift to divide by 2 then divide by 3) */ +GSYM($$divI_6) + .export $$divI_6,millicode + comb,<,N x2,0,LREF(neg6) + extru x2,30,31,x2 /* divide by 2 */ + addi 5,x2,t1 /* compute 5*(x2+1) = 5*x2+5 */ + sh2add x2,t1,x2 /* multiply by 5 to get started */ + b LREF(pos) + addc 0,0,x1 + +LSYM(neg6) + subi 2,x2,x2 /* negate, divide by 2, and add 1 */ + /* negation and adding 1 are done */ + /* at the same time by the SUBI */ + extru x2,30,31,x2 + shd 0,x2,30,x1 + sh2add x2,x2,x2 /* multiply by 5 to get started */ + b LREF(neg) + addc x1,0,x1 + +GSYM($$divU_6) + .export $$divU_6,millicode + extru x2,30,31,x2 /* divide by 2 */ + addi 1,x2,x2 /* cannot carry */ + shd 0,x2,30,x1 /* multiply by 5 to get started */ + sh2add x2,x2,x2 + b LREF(pos) + addc x1,0,x1 + +/* DIVISION BY 10 (shift to divide by 2 then divide by 5) */ +GSYM($$divU_10) + .export $$divU_10,millicode + extru x2,30,31,x2 /* divide by 2 */ + addi 3,x2,t1 /* compute 3*(x2+1) = (3*x2)+3 */ + sh1add x2,t1,x2 /* multiply by 3 to get started */ + addc 0,0,x1 +LSYM(pos) + shd x1,x2,28,t1 /* multiply by 0x11 */ + shd x2,0,28,t2 + add x2,t2,x2 + addc x1,t1,x1 +LSYM(pos_for_17) + shd x1,x2,24,t1 /* multiply by 0x101 */ + shd x2,0,24,t2 + add x2,t2,x2 + addc x1,t1,x1 + + shd x1,x2,16,t1 /* multiply by 0x10001 */ + shd x2,0,16,t2 + add x2,t2,x2 + MILLIRET + addc x1,t1,x1 + +GSYM($$divI_10) + .export $$divI_10,millicode + comb,< x2,0,LREF(neg10) + copy 0,x1 + extru x2,30,31,x2 /* divide by 2 */ + addib,TR 1,x2,LREF(pos) /* add 1 (cannot overflow) */ + sh1add x2,x2,x2 /* multiply by 3 to get started */ + +LSYM(neg10) + subi 2,x2,x2 /* negate, divide by 2, and add 1 */ + /* negation and adding 1 are done */ + /* at the same time by the SUBI */ + extru x2,30,31,x2 + sh1add x2,x2,x2 /* multiply by 3 to get started */ +LSYM(neg) + shd x1,x2,28,t1 /* multiply by 0x11 */ + shd x2,0,28,t2 + add x2,t2,x2 + addc x1,t1,x1 +LSYM(neg_for_17) + shd x1,x2,24,t1 /* multiply by 0x101 */ + shd x2,0,24,t2 + add x2,t2,x2 + addc x1,t1,x1 + + shd x1,x2,16,t1 /* multiply by 0x10001 */ + shd x2,0,16,t2 + add x2,t2,x2 + addc x1,t1,x1 + MILLIRET + sub 0,x1,x1 + +/* DIVISION BY 12 (shift to divide by 4 then divide by 3) */ +GSYM($$divI_12) + .export $$divI_12,millicode + comb,< x2,0,LREF(neg12) + copy 0,x1 + extru x2,29,30,x2 /* divide by 4 */ + addib,tr 1,x2,LREF(pos) /* compute 5*(x2+1) = 5*x2+5 */ + sh2add x2,x2,x2 /* multiply by 5 to get started */ + +LSYM(neg12) + subi 4,x2,x2 /* negate, divide by 4, and add 1 */ + /* negation and adding 1 are done */ + /* at the same time by the SUBI */ + extru x2,29,30,x2 + b LREF(neg) + sh2add x2,x2,x2 /* multiply by 5 to get started */ + +GSYM($$divU_12) + .export $$divU_12,millicode + extru x2,29,30,x2 /* divide by 4 */ + addi 5,x2,t1 /* cannot carry */ + sh2add x2,t1,x2 /* multiply by 5 to get started */ + b LREF(pos) + addc 0,0,x1 + +/* DIVISION BY 15 (use z = 2**32; a = 11111111) */ +GSYM($$divI_15) + .export $$divI_15,millicode + comb,< x2,0,LREF(neg15) + copy 0,x1 + addib,tr 1,x2,LREF(pos)+4 + shd x1,x2,28,t1 + +LSYM(neg15) + b LREF(neg) + subi 1,x2,x2 + +GSYM($$divU_15) + .export $$divU_15,millicode + addi 1,x2,x2 /* this CAN overflow */ + b LREF(pos) + addc 0,0,x1 + +/* DIVISION BY 17 (use z = 2**32; a = f0f0f0f) */ +GSYM($$divI_17) + .export $$divI_17,millicode + comb,<,n x2,0,LREF(neg17) + addi 1,x2,x2 /* this cannot overflow */ + shd 0,x2,28,t1 /* multiply by 0xf to get started */ + shd x2,0,28,t2 + sub t2,x2,x2 + b LREF(pos_for_17) + subb t1,0,x1 + +LSYM(neg17) + subi 1,x2,x2 /* this cannot overflow */ + shd 0,x2,28,t1 /* multiply by 0xf to get started */ + shd x2,0,28,t2 + sub t2,x2,x2 + b LREF(neg_for_17) + subb t1,0,x1 + +GSYM($$divU_17) + .export $$divU_17,millicode + addi 1,x2,x2 /* this CAN overflow */ + addc 0,0,x1 + shd x1,x2,28,t1 /* multiply by 0xf to get started */ +LSYM(u17) + shd x2,0,28,t2 + sub t2,x2,x2 + b LREF(pos_for_17) + subb t1,x1,x1 + + +/* DIVISION BY DIVISORS OF FFFFFF, and powers of 2 times these + includes 7,9 and also 14 + + + z = 2**24-1 + r = z mod x = 0 + + so choose b = 0 + + Also, in order to divide by z = 2**24-1, we approximate by dividing + by (z+1) = 2**24 (which is easy), and then correcting. + + (ax) = (z+1)q' + r + . = zq' + (q'+r) + + So to compute (ax)/z, compute q' = (ax)/(z+1) and r = (ax) mod (z+1) + Then the true remainder of (ax)/z is (q'+r). Repeat the process + with this new remainder, adding the tentative quotients together, + until a tentative quotient is 0 (and then we are done). There is + one last correction to be done. It is possible that (q'+r) = z. + If so, then (q'+r)/(z+1) = 0 and it looks like we are done. But, + in fact, we need to add 1 more to the quotient. Now, it turns + out that this happens if and only if the original value x is + an exact multiple of y. So, to avoid a three instruction test at + the end, instead use 1 instruction to add 1 to x at the beginning. */ + +/* DIVISION BY 7 (use z = 2**24-1; a = 249249) */ +GSYM($$divI_7) + .export $$divI_7,millicode + comb,<,n x2,0,LREF(neg7) +LSYM(7) + addi 1,x2,x2 /* cannot overflow */ + shd 0,x2,29,x1 + sh3add x2,x2,x2 + addc x1,0,x1 +LSYM(pos7) + shd x1,x2,26,t1 + shd x2,0,26,t2 + add x2,t2,x2 + addc x1,t1,x1 + + shd x1,x2,20,t1 + shd x2,0,20,t2 + add x2,t2,x2 + addc x1,t1,t1 + + /* computed . Now divide it by (2**24 - 1) */ + + copy 0,x1 + shd,= t1,x2,24,t1 /* tentative quotient */ +LSYM(1) + addb,tr t1,x1,LREF(2) /* add to previous quotient */ + extru x2,31,24,x2 /* new remainder (unadjusted) */ + + MILLIRETN + +LSYM(2) + addb,tr t1,x2,LREF(1) /* adjust remainder */ + extru,= x2,7,8,t1 /* new quotient */ + +LSYM(neg7) + subi 1,x2,x2 /* negate x2 and add 1 */ +LSYM(8) + shd 0,x2,29,x1 + sh3add x2,x2,x2 + addc x1,0,x1 + +LSYM(neg7_shift) + shd x1,x2,26,t1 + shd x2,0,26,t2 + add x2,t2,x2 + addc x1,t1,x1 + + shd x1,x2,20,t1 + shd x2,0,20,t2 + add x2,t2,x2 + addc x1,t1,t1 + + /* computed . Now divide it by (2**24 - 1) */ + + copy 0,x1 + shd,= t1,x2,24,t1 /* tentative quotient */ +LSYM(3) + addb,tr t1,x1,LREF(4) /* add to previous quotient */ + extru x2,31,24,x2 /* new remainder (unadjusted) */ + + MILLIRET + sub 0,x1,x1 /* negate result */ + +LSYM(4) + addb,tr t1,x2,LREF(3) /* adjust remainder */ + extru,= x2,7,8,t1 /* new quotient */ + +GSYM($$divU_7) + .export $$divU_7,millicode + addi 1,x2,x2 /* can carry */ + addc 0,0,x1 + shd x1,x2,29,t1 + sh3add x2,x2,x2 + b LREF(pos7) + addc t1,x1,x1 + +/* DIVISION BY 9 (use z = 2**24-1; a = 1c71c7) */ +GSYM($$divI_9) + .export $$divI_9,millicode + comb,<,n x2,0,LREF(neg9) + addi 1,x2,x2 /* cannot overflow */ + shd 0,x2,29,t1 + shd x2,0,29,t2 + sub t2,x2,x2 + b LREF(pos7) + subb t1,0,x1 + +LSYM(neg9) + subi 1,x2,x2 /* negate and add 1 */ + shd 0,x2,29,t1 + shd x2,0,29,t2 + sub t2,x2,x2 + b LREF(neg7_shift) + subb t1,0,x1 + +GSYM($$divU_9) + .export $$divU_9,millicode + addi 1,x2,x2 /* can carry */ + addc 0,0,x1 + shd x1,x2,29,t1 + shd x2,0,29,t2 + sub t2,x2,x2 + b LREF(pos7) + subb t1,x1,x1 + +/* DIVISION BY 14 (shift to divide by 2 then divide by 7) */ +GSYM($$divI_14) + .export $$divI_14,millicode + comb,<,n x2,0,LREF(neg14) +GSYM($$divU_14) + .export $$divU_14,millicode + b LREF(7) /* go to 7 case */ + extru x2,30,31,x2 /* divide by 2 */ + +LSYM(neg14) + subi 2,x2,x2 /* negate (and add 2) */ + b LREF(8) + extru x2,30,31,x2 /* divide by 2 */ + .exit + .procend + .end +#endif + +#ifdef L_mulI +/* VERSION "@(#)$$mulI $ Revision: 12.4 $ $ Date: 94/03/17 17:18:51 $" */ +/****************************************************************************** +This routine is used on PA2.0 processors when gcc -mno-fpregs is used + +ROUTINE: $$mulI + + +DESCRIPTION: + + $$mulI multiplies two single word integers, giving a single + word result. + + +INPUT REGISTERS: + + arg0 = Operand 1 + arg1 = Operand 2 + r31 == return pc + sr0 == return space when called externally + + +OUTPUT REGISTERS: + + arg0 = undefined + arg1 = undefined + ret1 = result + +OTHER REGISTERS AFFECTED: + + r1 = undefined + +SIDE EFFECTS: + + Causes a trap under the following conditions: NONE + Changes memory at the following places: NONE + +PERMISSIBLE CONTEXT: + + Unwindable + Does not create a stack frame + Is usable for internal or external microcode + +DISCUSSION: + + Calls other millicode routines via mrp: NONE + Calls other millicode routines: NONE + +***************************************************************************/ + + +#define a0 %arg0 +#define a1 %arg1 +#define t0 %r1 +#define r %ret1 + +#define a0__128a0 zdep a0,24,25,a0 +#define a0__256a0 zdep a0,23,24,a0 +#define a1_ne_0_b_l0 comb,<> a1,0,LREF(l0) +#define a1_ne_0_b_l1 comb,<> a1,0,LREF(l1) +#define a1_ne_0_b_l2 comb,<> a1,0,LREF(l2) +#define b_n_ret_t0 b,n LREF(ret_t0) +#define b_e_shift b LREF(e_shift) +#define b_e_t0ma0 b LREF(e_t0ma0) +#define b_e_t0 b LREF(e_t0) +#define b_e_t0a0 b LREF(e_t0a0) +#define b_e_t02a0 b LREF(e_t02a0) +#define b_e_t04a0 b LREF(e_t04a0) +#define b_e_2t0 b LREF(e_2t0) +#define b_e_2t0a0 b LREF(e_2t0a0) +#define b_e_2t04a0 b LREF(e2t04a0) +#define b_e_3t0 b LREF(e_3t0) +#define b_e_4t0 b LREF(e_4t0) +#define b_e_4t0a0 b LREF(e_4t0a0) +#define b_e_4t08a0 b LREF(e4t08a0) +#define b_e_5t0 b LREF(e_5t0) +#define b_e_8t0 b LREF(e_8t0) +#define b_e_8t0a0 b LREF(e_8t0a0) +#define r__r_a0 add r,a0,r +#define r__r_2a0 sh1add a0,r,r +#define r__r_4a0 sh2add a0,r,r +#define r__r_8a0 sh3add a0,r,r +#define r__r_t0 add r,t0,r +#define r__r_2t0 sh1add t0,r,r +#define r__r_4t0 sh2add t0,r,r +#define r__r_8t0 sh3add t0,r,r +#define t0__3a0 sh1add a0,a0,t0 +#define t0__4a0 sh2add a0,0,t0 +#define t0__5a0 sh2add a0,a0,t0 +#define t0__8a0 sh3add a0,0,t0 +#define t0__9a0 sh3add a0,a0,t0 +#define t0__16a0 zdep a0,27,28,t0 +#define t0__32a0 zdep a0,26,27,t0 +#define t0__64a0 zdep a0,25,26,t0 +#define t0__128a0 zdep a0,24,25,t0 +#define t0__t0ma0 sub t0,a0,t0 +#define t0__t0_a0 add t0,a0,t0 +#define t0__t0_2a0 sh1add a0,t0,t0 +#define t0__t0_4a0 sh2add a0,t0,t0 +#define t0__t0_8a0 sh3add a0,t0,t0 +#define t0__2t0_a0 sh1add t0,a0,t0 +#define t0__3t0 sh1add t0,t0,t0 +#define t0__4t0 sh2add t0,0,t0 +#define t0__4t0_a0 sh2add t0,a0,t0 +#define t0__5t0 sh2add t0,t0,t0 +#define t0__8t0 sh3add t0,0,t0 +#define t0__8t0_a0 sh3add t0,a0,t0 +#define t0__9t0 sh3add t0,t0,t0 +#define t0__16t0 zdep t0,27,28,t0 +#define t0__32t0 zdep t0,26,27,t0 +#define t0__256a0 zdep a0,23,24,t0 + + + SUBSPA_MILLI + ATTR_MILLI + .align 16 + .proc + .callinfo millicode + .export $$mulI,millicode +GSYM($$mulI) + combt,<<= a1,a0,LREF(l4) /* swap args if unsigned a1>a0 */ + copy 0,r /* zero out the result */ + xor a0,a1,a0 /* swap a0 & a1 using the */ + xor a0,a1,a1 /* old xor trick */ + xor a0,a1,a0 +LSYM(l4) + combt,<= 0,a0,LREF(l3) /* if a0>=0 then proceed like unsigned */ + zdep a1,30,8,t0 /* t0 = (a1&0xff)<<1 ********* */ + sub,> 0,a1,t0 /* otherwise negate both and */ + combt,<=,n a0,t0,LREF(l2) /* swap back if |a0|<|a1| */ + sub 0,a0,a1 + movb,tr,n t0,a0,LREF(l2) /* 10th inst. */ + +LSYM(l0) r__r_t0 /* add in this partial product */ +LSYM(l1) a0__256a0 /* a0 <<= 8 ****************** */ +LSYM(l2) zdep a1,30,8,t0 /* t0 = (a1&0xff)<<1 ********* */ +LSYM(l3) blr t0,0 /* case on these 8 bits ****** */ + extru a1,23,24,a1 /* a1 >>= 8 ****************** */ + +/*16 insts before this. */ +/* a0 <<= 8 ************************** */ +LSYM(x0) a1_ne_0_b_l2 ! a0__256a0 ! MILLIRETN ! nop +LSYM(x1) a1_ne_0_b_l1 ! r__r_a0 ! MILLIRETN ! nop +LSYM(x2) a1_ne_0_b_l1 ! r__r_2a0 ! MILLIRETN ! nop +LSYM(x3) a1_ne_0_b_l0 ! t0__3a0 ! MILLIRET ! r__r_t0 +LSYM(x4) a1_ne_0_b_l1 ! r__r_4a0 ! MILLIRETN ! nop +LSYM(x5) a1_ne_0_b_l0 ! t0__5a0 ! MILLIRET ! r__r_t0 +LSYM(x6) t0__3a0 ! a1_ne_0_b_l1 ! r__r_2t0 ! MILLIRETN +LSYM(x7) t0__3a0 ! a1_ne_0_b_l0 ! r__r_4a0 ! b_n_ret_t0 +LSYM(x8) a1_ne_0_b_l1 ! r__r_8a0 ! MILLIRETN ! nop +LSYM(x9) a1_ne_0_b_l0 ! t0__9a0 ! MILLIRET ! r__r_t0 +LSYM(x10) t0__5a0 ! a1_ne_0_b_l1 ! r__r_2t0 ! MILLIRETN +LSYM(x11) t0__3a0 ! a1_ne_0_b_l0 ! r__r_8a0 ! b_n_ret_t0 +LSYM(x12) t0__3a0 ! a1_ne_0_b_l1 ! r__r_4t0 ! MILLIRETN +LSYM(x13) t0__5a0 ! a1_ne_0_b_l0 ! r__r_8a0 ! b_n_ret_t0 +LSYM(x14) t0__3a0 ! t0__2t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x15) t0__5a0 ! a1_ne_0_b_l0 ! t0__3t0 ! b_n_ret_t0 +LSYM(x16) t0__16a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN +LSYM(x17) t0__9a0 ! a1_ne_0_b_l0 ! t0__t0_8a0 ! b_n_ret_t0 +LSYM(x18) t0__9a0 ! a1_ne_0_b_l1 ! r__r_2t0 ! MILLIRETN +LSYM(x19) t0__9a0 ! a1_ne_0_b_l0 ! t0__2t0_a0 ! b_n_ret_t0 +LSYM(x20) t0__5a0 ! a1_ne_0_b_l1 ! r__r_4t0 ! MILLIRETN +LSYM(x21) t0__5a0 ! a1_ne_0_b_l0 ! t0__4t0_a0 ! b_n_ret_t0 +LSYM(x22) t0__5a0 ! t0__2t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x23) t0__5a0 ! t0__2t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x24) t0__3a0 ! a1_ne_0_b_l1 ! r__r_8t0 ! MILLIRETN +LSYM(x25) t0__5a0 ! a1_ne_0_b_l0 ! t0__5t0 ! b_n_ret_t0 +LSYM(x26) t0__3a0 ! t0__4t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x27) t0__3a0 ! a1_ne_0_b_l0 ! t0__9t0 ! b_n_ret_t0 +LSYM(x28) t0__3a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x29) t0__3a0 ! t0__2t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x30) t0__5a0 ! t0__3t0 ! b_e_shift ! r__r_2t0 +LSYM(x31) t0__32a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0 +LSYM(x32) t0__32a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN +LSYM(x33) t0__8a0 ! a1_ne_0_b_l0 ! t0__4t0_a0 ! b_n_ret_t0 +LSYM(x34) t0__16a0 ! t0__t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x35) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__t0_8a0 +LSYM(x36) t0__9a0 ! a1_ne_0_b_l1 ! r__r_4t0 ! MILLIRETN +LSYM(x37) t0__9a0 ! a1_ne_0_b_l0 ! t0__4t0_a0 ! b_n_ret_t0 +LSYM(x38) t0__9a0 ! t0__2t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x39) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x40) t0__5a0 ! a1_ne_0_b_l1 ! r__r_8t0 ! MILLIRETN +LSYM(x41) t0__5a0 ! a1_ne_0_b_l0 ! t0__8t0_a0 ! b_n_ret_t0 +LSYM(x42) t0__5a0 ! t0__4t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x43) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x44) t0__5a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x45) t0__9a0 ! a1_ne_0_b_l0 ! t0__5t0 ! b_n_ret_t0 +LSYM(x46) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__t0_a0 +LSYM(x47) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__t0_2a0 +LSYM(x48) t0__3a0 ! a1_ne_0_b_l0 ! t0__16t0 ! b_n_ret_t0 +LSYM(x49) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__t0_4a0 +LSYM(x50) t0__5a0 ! t0__5t0 ! b_e_shift ! r__r_2t0 +LSYM(x51) t0__9a0 ! t0__t0_8a0 ! b_e_t0 ! t0__3t0 +LSYM(x52) t0__3a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x53) t0__3a0 ! t0__4t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x54) t0__9a0 ! t0__3t0 ! b_e_shift ! r__r_2t0 +LSYM(x55) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x56) t0__3a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x57) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x58) t0__3a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x59) t0__9a0 ! t0__2t0_a0 ! b_e_t02a0 ! t0__3t0 +LSYM(x60) t0__5a0 ! t0__3t0 ! b_e_shift ! r__r_4t0 +LSYM(x61) t0__5a0 ! t0__3t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x62) t0__32a0 ! t0__t0ma0 ! b_e_shift ! r__r_2t0 +LSYM(x63) t0__64a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0 +LSYM(x64) t0__64a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN +LSYM(x65) t0__8a0 ! a1_ne_0_b_l0 ! t0__8t0_a0 ! b_n_ret_t0 +LSYM(x66) t0__32a0 ! t0__t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x67) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x68) t0__8a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x69) t0__8a0 ! t0__2t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x70) t0__64a0 ! t0__t0_4a0 ! b_e_t0 ! t0__t0_2a0 +LSYM(x71) t0__9a0 ! t0__8t0 ! b_e_t0 ! t0__t0ma0 +LSYM(x72) t0__9a0 ! a1_ne_0_b_l1 ! r__r_8t0 ! MILLIRETN +LSYM(x73) t0__9a0 ! t0__8t0_a0 ! b_e_shift ! r__r_t0 +LSYM(x74) t0__9a0 ! t0__4t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x75) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x76) t0__9a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x77) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x78) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x79) t0__16a0 ! t0__5t0 ! b_e_t0 ! t0__t0ma0 +LSYM(x80) t0__16a0 ! t0__5t0 ! b_e_shift ! r__r_t0 +LSYM(x81) t0__9a0 ! t0__9t0 ! b_e_shift ! r__r_t0 +LSYM(x82) t0__5a0 ! t0__8t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x83) t0__5a0 ! t0__8t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x84) t0__5a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x85) t0__8a0 ! t0__2t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x86) t0__5a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x87) t0__9a0 ! t0__9t0 ! b_e_t02a0 ! t0__t0_4a0 +LSYM(x88) t0__5a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x89) t0__5a0 ! t0__2t0_a0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x90) t0__9a0 ! t0__5t0 ! b_e_shift ! r__r_2t0 +LSYM(x91) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x92) t0__5a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__2t0_a0 +LSYM(x93) t0__32a0 ! t0__t0ma0 ! b_e_t0 ! t0__3t0 +LSYM(x94) t0__9a0 ! t0__5t0 ! b_e_2t0 ! t0__t0_2a0 +LSYM(x95) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x96) t0__8a0 ! t0__3t0 ! b_e_shift ! r__r_4t0 +LSYM(x97) t0__8a0 ! t0__3t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x98) t0__32a0 ! t0__3t0 ! b_e_t0 ! t0__t0_2a0 +LSYM(x99) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x100) t0__5a0 ! t0__5t0 ! b_e_shift ! r__r_4t0 +LSYM(x101) t0__5a0 ! t0__5t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x102) t0__32a0 ! t0__t0_2a0 ! b_e_t0 ! t0__3t0 +LSYM(x103) t0__5a0 ! t0__5t0 ! b_e_t02a0 ! t0__4t0_a0 +LSYM(x104) t0__3a0 ! t0__4t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x105) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x106) t0__3a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x107) t0__9a0 ! t0__t0_4a0 ! b_e_t02a0 ! t0__8t0_a0 +LSYM(x108) t0__9a0 ! t0__3t0 ! b_e_shift ! r__r_4t0 +LSYM(x109) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x110) t0__9a0 ! t0__3t0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x111) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x112) t0__3a0 ! t0__2t0_a0 ! b_e_t0 ! t0__16t0 +LSYM(x113) t0__9a0 ! t0__4t0_a0 ! b_e_t02a0 ! t0__3t0 +LSYM(x114) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__3t0 +LSYM(x115) t0__9a0 ! t0__2t0_a0 ! b_e_2t0a0 ! t0__3t0 +LSYM(x116) t0__3a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__4t0_a0 +LSYM(x117) t0__3a0 ! t0__4t0_a0 ! b_e_t0 ! t0__9t0 +LSYM(x118) t0__3a0 ! t0__4t0_a0 ! b_e_t0a0 ! t0__9t0 +LSYM(x119) t0__3a0 ! t0__4t0_a0 ! b_e_t02a0 ! t0__9t0 +LSYM(x120) t0__5a0 ! t0__3t0 ! b_e_shift ! r__r_8t0 +LSYM(x121) t0__5a0 ! t0__3t0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x122) t0__5a0 ! t0__3t0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x123) t0__5a0 ! t0__8t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x124) t0__32a0 ! t0__t0ma0 ! b_e_shift ! r__r_4t0 +LSYM(x125) t0__5a0 ! t0__5t0 ! b_e_t0 ! t0__5t0 +LSYM(x126) t0__64a0 ! t0__t0ma0 ! b_e_shift ! r__r_2t0 +LSYM(x127) t0__128a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0 +LSYM(x128) t0__128a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN +LSYM(x129) t0__128a0 ! a1_ne_0_b_l0 ! t0__t0_a0 ! b_n_ret_t0 +LSYM(x130) t0__64a0 ! t0__t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x131) t0__8a0 ! t0__8t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x132) t0__8a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x133) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x134) t0__8a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x135) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__3t0 +LSYM(x136) t0__8a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x137) t0__8a0 ! t0__2t0_a0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x138) t0__8a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x139) t0__8a0 ! t0__2t0_a0 ! b_e_2t0a0 ! t0__4t0_a0 +LSYM(x140) t0__3a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__5t0 +LSYM(x141) t0__8a0 ! t0__2t0_a0 ! b_e_4t0a0 ! t0__2t0_a0 +LSYM(x142) t0__9a0 ! t0__8t0 ! b_e_2t0 ! t0__t0ma0 +LSYM(x143) t0__16a0 ! t0__9t0 ! b_e_t0 ! t0__t0ma0 +LSYM(x144) t0__9a0 ! t0__8t0 ! b_e_shift ! r__r_2t0 +LSYM(x145) t0__9a0 ! t0__8t0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x146) t0__9a0 ! t0__8t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x147) t0__9a0 ! t0__8t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x148) t0__9a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x149) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x150) t0__9a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x151) t0__9a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__2t0_a0 +LSYM(x152) t0__9a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x153) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x154) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x155) t0__32a0 ! t0__t0ma0 ! b_e_t0 ! t0__5t0 +LSYM(x156) t0__9a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__2t0_a0 +LSYM(x157) t0__32a0 ! t0__t0ma0 ! b_e_t02a0 ! t0__5t0 +LSYM(x158) t0__16a0 ! t0__5t0 ! b_e_2t0 ! t0__t0ma0 +LSYM(x159) t0__32a0 ! t0__5t0 ! b_e_t0 ! t0__t0ma0 +LSYM(x160) t0__5a0 ! t0__4t0 ! b_e_shift ! r__r_8t0 +LSYM(x161) t0__8a0 ! t0__5t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x162) t0__9a0 ! t0__9t0 ! b_e_shift ! r__r_2t0 +LSYM(x163) t0__9a0 ! t0__9t0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x164) t0__5a0 ! t0__8t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x165) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x166) t0__5a0 ! t0__8t0_a0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x167) t0__5a0 ! t0__8t0_a0 ! b_e_2t0a0 ! t0__2t0_a0 +LSYM(x168) t0__5a0 ! t0__4t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x169) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x170) t0__32a0 ! t0__t0_2a0 ! b_e_t0 ! t0__5t0 +LSYM(x171) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__9t0 +LSYM(x172) t0__5a0 ! t0__4t0_a0 ! b_e_4t0 ! t0__2t0_a0 +LSYM(x173) t0__9a0 ! t0__2t0_a0 ! b_e_t02a0 ! t0__9t0 +LSYM(x174) t0__32a0 ! t0__t0_2a0 ! b_e_t04a0 ! t0__5t0 +LSYM(x175) t0__8a0 ! t0__2t0_a0 ! b_e_5t0 ! t0__2t0_a0 +LSYM(x176) t0__5a0 ! t0__4t0_a0 ! b_e_8t0 ! t0__t0_a0 +LSYM(x177) t0__5a0 ! t0__4t0_a0 ! b_e_8t0a0 ! t0__t0_a0 +LSYM(x178) t0__5a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__8t0_a0 +LSYM(x179) t0__5a0 ! t0__2t0_a0 ! b_e_2t0a0 ! t0__8t0_a0 +LSYM(x180) t0__9a0 ! t0__5t0 ! b_e_shift ! r__r_4t0 +LSYM(x181) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x182) t0__9a0 ! t0__5t0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x183) t0__9a0 ! t0__5t0 ! b_e_2t0a0 ! t0__2t0_a0 +LSYM(x184) t0__5a0 ! t0__9t0 ! b_e_4t0 ! t0__t0_a0 +LSYM(x185) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x186) t0__32a0 ! t0__t0ma0 ! b_e_2t0 ! t0__3t0 +LSYM(x187) t0__9a0 ! t0__4t0_a0 ! b_e_t02a0 ! t0__5t0 +LSYM(x188) t0__9a0 ! t0__5t0 ! b_e_4t0 ! t0__t0_2a0 +LSYM(x189) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__9t0 +LSYM(x190) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__5t0 +LSYM(x191) t0__64a0 ! t0__3t0 ! b_e_t0 ! t0__t0ma0 +LSYM(x192) t0__8a0 ! t0__3t0 ! b_e_shift ! r__r_8t0 +LSYM(x193) t0__8a0 ! t0__3t0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x194) t0__8a0 ! t0__3t0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x195) t0__8a0 ! t0__8t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x196) t0__8a0 ! t0__3t0 ! b_e_4t0 ! t0__2t0_a0 +LSYM(x197) t0__8a0 ! t0__3t0 ! b_e_4t0a0 ! t0__2t0_a0 +LSYM(x198) t0__64a0 ! t0__t0_2a0 ! b_e_t0 ! t0__3t0 +LSYM(x199) t0__8a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__3t0 +LSYM(x200) t0__5a0 ! t0__5t0 ! b_e_shift ! r__r_8t0 +LSYM(x201) t0__5a0 ! t0__5t0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x202) t0__5a0 ! t0__5t0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x203) t0__5a0 ! t0__5t0 ! b_e_2t0a0 ! t0__4t0_a0 +LSYM(x204) t0__8a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__3t0 +LSYM(x205) t0__5a0 ! t0__8t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x206) t0__64a0 ! t0__t0_4a0 ! b_e_t02a0 ! t0__3t0 +LSYM(x207) t0__8a0 ! t0__2t0_a0 ! b_e_3t0 ! t0__4t0_a0 +LSYM(x208) t0__5a0 ! t0__5t0 ! b_e_8t0 ! t0__t0_a0 +LSYM(x209) t0__5a0 ! t0__5t0 ! b_e_8t0a0 ! t0__t0_a0 +LSYM(x210) t0__5a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__5t0 +LSYM(x211) t0__5a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__5t0 +LSYM(x212) t0__3a0 ! t0__4t0_a0 ! b_e_4t0 ! t0__4t0_a0 +LSYM(x213) t0__3a0 ! t0__4t0_a0 ! b_e_4t0a0 ! t0__4t0_a0 +LSYM(x214) t0__9a0 ! t0__t0_4a0 ! b_e_2t04a0 ! t0__8t0_a0 +LSYM(x215) t0__5a0 ! t0__4t0_a0 ! b_e_5t0 ! t0__2t0_a0 +LSYM(x216) t0__9a0 ! t0__3t0 ! b_e_shift ! r__r_8t0 +LSYM(x217) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x218) t0__9a0 ! t0__3t0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x219) t0__9a0 ! t0__8t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x220) t0__3a0 ! t0__9t0 ! b_e_4t0 ! t0__2t0_a0 +LSYM(x221) t0__3a0 ! t0__9t0 ! b_e_4t0a0 ! t0__2t0_a0 +LSYM(x222) t0__9a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__3t0 +LSYM(x223) t0__9a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__3t0 +LSYM(x224) t0__9a0 ! t0__3t0 ! b_e_8t0 ! t0__t0_a0 +LSYM(x225) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__5t0 +LSYM(x226) t0__3a0 ! t0__2t0_a0 ! b_e_t02a0 ! t0__32t0 +LSYM(x227) t0__9a0 ! t0__5t0 ! b_e_t02a0 ! t0__5t0 +LSYM(x228) t0__9a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__3t0 +LSYM(x229) t0__9a0 ! t0__2t0_a0 ! b_e_4t0a0 ! t0__3t0 +LSYM(x230) t0__9a0 ! t0__5t0 ! b_e_5t0 ! t0__t0_a0 +LSYM(x231) t0__9a0 ! t0__2t0_a0 ! b_e_3t0 ! t0__4t0_a0 +LSYM(x232) t0__3a0 ! t0__2t0_a0 ! b_e_8t0 ! t0__4t0_a0 +LSYM(x233) t0__3a0 ! t0__2t0_a0 ! b_e_8t0a0 ! t0__4t0_a0 +LSYM(x234) t0__3a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__9t0 +LSYM(x235) t0__3a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__9t0 +LSYM(x236) t0__9a0 ! t0__2t0_a0 ! b_e_4t08a0 ! t0__3t0 +LSYM(x237) t0__16a0 ! t0__5t0 ! b_e_3t0 ! t0__t0ma0 +LSYM(x238) t0__3a0 ! t0__4t0_a0 ! b_e_2t04a0 ! t0__9t0 +LSYM(x239) t0__16a0 ! t0__5t0 ! b_e_t0ma0 ! t0__3t0 +LSYM(x240) t0__9a0 ! t0__t0_a0 ! b_e_8t0 ! t0__3t0 +LSYM(x241) t0__9a0 ! t0__t0_a0 ! b_e_8t0a0 ! t0__3t0 +LSYM(x242) t0__5a0 ! t0__3t0 ! b_e_2t0 ! t0__8t0_a0 +LSYM(x243) t0__9a0 ! t0__9t0 ! b_e_t0 ! t0__3t0 +LSYM(x244) t0__5a0 ! t0__3t0 ! b_e_4t0 ! t0__4t0_a0 +LSYM(x245) t0__8a0 ! t0__3t0 ! b_e_5t0 ! t0__2t0_a0 +LSYM(x246) t0__5a0 ! t0__8t0_a0 ! b_e_2t0 ! t0__3t0 +LSYM(x247) t0__5a0 ! t0__8t0_a0 ! b_e_2t0a0 ! t0__3t0 +LSYM(x248) t0__32a0 ! t0__t0ma0 ! b_e_shift ! r__r_8t0 +LSYM(x249) t0__32a0 ! t0__t0ma0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x250) t0__5a0 ! t0__5t0 ! b_e_2t0 ! t0__5t0 +LSYM(x251) t0__5a0 ! t0__5t0 ! b_e_2t0a0 ! t0__5t0 +LSYM(x252) t0__64a0 ! t0__t0ma0 ! b_e_shift ! r__r_4t0 +LSYM(x253) t0__64a0 ! t0__t0ma0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x254) t0__128a0 ! t0__t0ma0 ! b_e_shift ! r__r_2t0 +LSYM(x255) t0__256a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0 +/*1040 insts before this. */ +LSYM(ret_t0) MILLIRET +LSYM(e_t0) r__r_t0 +LSYM(e_shift) a1_ne_0_b_l2 + a0__256a0 /* a0 <<= 8 *********** */ + MILLIRETN +LSYM(e_t0ma0) a1_ne_0_b_l0 + t0__t0ma0 + MILLIRET + r__r_t0 +LSYM(e_t0a0) a1_ne_0_b_l0 + t0__t0_a0 + MILLIRET + r__r_t0 +LSYM(e_t02a0) a1_ne_0_b_l0 + t0__t0_2a0 + MILLIRET + r__r_t0 +LSYM(e_t04a0) a1_ne_0_b_l0 + t0__t0_4a0 + MILLIRET + r__r_t0 +LSYM(e_2t0) a1_ne_0_b_l1 + r__r_2t0 + MILLIRETN +LSYM(e_2t0a0) a1_ne_0_b_l0 + t0__2t0_a0 + MILLIRET + r__r_t0 +LSYM(e2t04a0) t0__t0_2a0 + a1_ne_0_b_l1 + r__r_2t0 + MILLIRETN +LSYM(e_3t0) a1_ne_0_b_l0 + t0__3t0 + MILLIRET + r__r_t0 +LSYM(e_4t0) a1_ne_0_b_l1 + r__r_4t0 + MILLIRETN +LSYM(e_4t0a0) a1_ne_0_b_l0 + t0__4t0_a0 + MILLIRET + r__r_t0 +LSYM(e4t08a0) t0__t0_2a0 + a1_ne_0_b_l1 + r__r_4t0 + MILLIRETN +LSYM(e_5t0) a1_ne_0_b_l0 + t0__5t0 + MILLIRET + r__r_t0 +LSYM(e_8t0) a1_ne_0_b_l1 + r__r_8t0 + MILLIRETN +LSYM(e_8t0a0) a1_ne_0_b_l0 + t0__8t0_a0 + MILLIRET + r__r_t0 + + .procend + .end +#endif diff --git a/trunk/arch/parisc/lib/milli/milli.h b/trunk/arch/parisc/lib/milli/milli.h new file mode 100644 index 000000000000..19ac79f336de --- /dev/null +++ b/trunk/arch/parisc/lib/milli/milli.h @@ -0,0 +1,165 @@ +/* 32 and 64-bit millicode, original author Hewlett-Packard + adapted for gcc by Paul Bame + and Alan Modra . + + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + This file is part of GCC and is released under the terms of + of the GNU General Public License as published by the Free Software + Foundation; either version 2, or (at your option) any later version. + See the file COPYING in the top-level GCC source directory for a copy + of the license. */ + +#ifndef _PA_MILLI_H_ +#define _PA_MILLI_H_ + +#define L_dyncall +#define L_divI +#define L_divU +#define L_remI +#define L_remU +#define L_div_const +#define L_mulI + +#ifdef CONFIG_64BIT + .level 2.0w +#endif + +/* Hardware General Registers. */ +r0: .reg %r0 +r1: .reg %r1 +r2: .reg %r2 +r3: .reg %r3 +r4: .reg %r4 +r5: .reg %r5 +r6: .reg %r6 +r7: .reg %r7 +r8: .reg %r8 +r9: .reg %r9 +r10: .reg %r10 +r11: .reg %r11 +r12: .reg %r12 +r13: .reg %r13 +r14: .reg %r14 +r15: .reg %r15 +r16: .reg %r16 +r17: .reg %r17 +r18: .reg %r18 +r19: .reg %r19 +r20: .reg %r20 +r21: .reg %r21 +r22: .reg %r22 +r23: .reg %r23 +r24: .reg %r24 +r25: .reg %r25 +r26: .reg %r26 +r27: .reg %r27 +r28: .reg %r28 +r29: .reg %r29 +r30: .reg %r30 +r31: .reg %r31 + +/* Hardware Space Registers. */ +sr0: .reg %sr0 +sr1: .reg %sr1 +sr2: .reg %sr2 +sr3: .reg %sr3 +sr4: .reg %sr4 +sr5: .reg %sr5 +sr6: .reg %sr6 +sr7: .reg %sr7 + +/* Hardware Floating Point Registers. */ +fr0: .reg %fr0 +fr1: .reg %fr1 +fr2: .reg %fr2 +fr3: .reg %fr3 +fr4: .reg %fr4 +fr5: .reg %fr5 +fr6: .reg %fr6 +fr7: .reg %fr7 +fr8: .reg %fr8 +fr9: .reg %fr9 +fr10: .reg %fr10 +fr11: .reg %fr11 +fr12: .reg %fr12 +fr13: .reg %fr13 +fr14: .reg %fr14 +fr15: .reg %fr15 + +/* Hardware Control Registers. */ +cr11: .reg %cr11 +sar: .reg %cr11 /* Shift Amount Register */ + +/* Software Architecture General Registers. */ +rp: .reg r2 /* return pointer */ +#ifdef CONFIG_64BIT +mrp: .reg r2 /* millicode return pointer */ +#else +mrp: .reg r31 /* millicode return pointer */ +#endif +ret0: .reg r28 /* return value */ +ret1: .reg r29 /* return value (high part of double) */ +sp: .reg r30 /* stack pointer */ +dp: .reg r27 /* data pointer */ +arg0: .reg r26 /* argument */ +arg1: .reg r25 /* argument or high part of double argument */ +arg2: .reg r24 /* argument */ +arg3: .reg r23 /* argument or high part of double argument */ + +/* Software Architecture Space Registers. */ +/* sr0 ; return link from BLE */ +sret: .reg sr1 /* return value */ +sarg: .reg sr1 /* argument */ +/* sr4 ; PC SPACE tracker */ +/* sr5 ; process private data */ + +/* Frame Offsets (millicode convention!) Used when calling other + millicode routines. Stack unwinding is dependent upon these + definitions. */ +r31_slot: .equ -20 /* "current RP" slot */ +sr0_slot: .equ -16 /* "static link" slot */ +#if defined(CONFIG_64BIT) +mrp_slot: .equ -16 /* "current RP" slot */ +psp_slot: .equ -8 /* "previous SP" slot */ +#else +mrp_slot: .equ -20 /* "current RP" slot (replacing "r31_slot") */ +#endif + + +#define DEFINE(name,value)name: .EQU value +#define RDEFINE(name,value)name: .REG value +#ifdef milliext +#define MILLI_BE(lbl) BE lbl(sr7,r0) +#define MILLI_BEN(lbl) BE,n lbl(sr7,r0) +#define MILLI_BLE(lbl) BLE lbl(sr7,r0) +#define MILLI_BLEN(lbl) BLE,n lbl(sr7,r0) +#define MILLIRETN BE,n 0(sr0,mrp) +#define MILLIRET BE 0(sr0,mrp) +#define MILLI_RETN BE,n 0(sr0,mrp) +#define MILLI_RET BE 0(sr0,mrp) +#else +#define MILLI_BE(lbl) B lbl +#define MILLI_BEN(lbl) B,n lbl +#define MILLI_BLE(lbl) BL lbl,mrp +#define MILLI_BLEN(lbl) BL,n lbl,mrp +#define MILLIRETN BV,n 0(mrp) +#define MILLIRET BV 0(mrp) +#define MILLI_RETN BV,n 0(mrp) +#define MILLI_RET BV 0(mrp) +#endif + +#define CAT(a,b) a##b + +#define SUBSPA_MILLI .section .text +#define SUBSPA_MILLI_DIV .section .text.div,"ax",@progbits! .align 16 +#define SUBSPA_MILLI_MUL .section .text.mul,"ax",@progbits! .align 16 +#define ATTR_MILLI +#define SUBSPA_DATA .section .data +#define ATTR_DATA +#define GLOBAL $global$ +#define GSYM(sym) !sym: +#define LSYM(sym) !CAT(.L,sym:) +#define LREF(sym) CAT(.L,sym) + +#endif /*_PA_MILLI_H_*/ diff --git a/trunk/arch/parisc/lib/milli/mulI.S b/trunk/arch/parisc/lib/milli/mulI.S new file mode 100644 index 000000000000..4c7e0c36d15e --- /dev/null +++ b/trunk/arch/parisc/lib/milli/mulI.S @@ -0,0 +1,474 @@ +/* 32 and 64-bit millicode, original author Hewlett-Packard + adapted for gcc by Paul Bame + and Alan Modra . + + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + This file is part of GCC and is released under the terms of + of the GNU General Public License as published by the Free Software + Foundation; either version 2, or (at your option) any later version. + See the file COPYING in the top-level GCC source directory for a copy + of the license. */ + +#include "milli.h" + +#ifdef L_mulI +/* VERSION "@(#)$$mulI $ Revision: 12.4 $ $ Date: 94/03/17 17:18:51 $" */ +/****************************************************************************** +This routine is used on PA2.0 processors when gcc -mno-fpregs is used + +ROUTINE: $$mulI + + +DESCRIPTION: + + $$mulI multiplies two single word integers, giving a single + word result. + + +INPUT REGISTERS: + + arg0 = Operand 1 + arg1 = Operand 2 + r31 == return pc + sr0 == return space when called externally + + +OUTPUT REGISTERS: + + arg0 = undefined + arg1 = undefined + ret1 = result + +OTHER REGISTERS AFFECTED: + + r1 = undefined + +SIDE EFFECTS: + + Causes a trap under the following conditions: NONE + Changes memory at the following places: NONE + +PERMISSIBLE CONTEXT: + + Unwindable + Does not create a stack frame + Is usable for internal or external microcode + +DISCUSSION: + + Calls other millicode routines via mrp: NONE + Calls other millicode routines: NONE + +***************************************************************************/ + + +#define a0 %arg0 +#define a1 %arg1 +#define t0 %r1 +#define r %ret1 + +#define a0__128a0 zdep a0,24,25,a0 +#define a0__256a0 zdep a0,23,24,a0 +#define a1_ne_0_b_l0 comb,<> a1,0,LREF(l0) +#define a1_ne_0_b_l1 comb,<> a1,0,LREF(l1) +#define a1_ne_0_b_l2 comb,<> a1,0,LREF(l2) +#define b_n_ret_t0 b,n LREF(ret_t0) +#define b_e_shift b LREF(e_shift) +#define b_e_t0ma0 b LREF(e_t0ma0) +#define b_e_t0 b LREF(e_t0) +#define b_e_t0a0 b LREF(e_t0a0) +#define b_e_t02a0 b LREF(e_t02a0) +#define b_e_t04a0 b LREF(e_t04a0) +#define b_e_2t0 b LREF(e_2t0) +#define b_e_2t0a0 b LREF(e_2t0a0) +#define b_e_2t04a0 b LREF(e2t04a0) +#define b_e_3t0 b LREF(e_3t0) +#define b_e_4t0 b LREF(e_4t0) +#define b_e_4t0a0 b LREF(e_4t0a0) +#define b_e_4t08a0 b LREF(e4t08a0) +#define b_e_5t0 b LREF(e_5t0) +#define b_e_8t0 b LREF(e_8t0) +#define b_e_8t0a0 b LREF(e_8t0a0) +#define r__r_a0 add r,a0,r +#define r__r_2a0 sh1add a0,r,r +#define r__r_4a0 sh2add a0,r,r +#define r__r_8a0 sh3add a0,r,r +#define r__r_t0 add r,t0,r +#define r__r_2t0 sh1add t0,r,r +#define r__r_4t0 sh2add t0,r,r +#define r__r_8t0 sh3add t0,r,r +#define t0__3a0 sh1add a0,a0,t0 +#define t0__4a0 sh2add a0,0,t0 +#define t0__5a0 sh2add a0,a0,t0 +#define t0__8a0 sh3add a0,0,t0 +#define t0__9a0 sh3add a0,a0,t0 +#define t0__16a0 zdep a0,27,28,t0 +#define t0__32a0 zdep a0,26,27,t0 +#define t0__64a0 zdep a0,25,26,t0 +#define t0__128a0 zdep a0,24,25,t0 +#define t0__t0ma0 sub t0,a0,t0 +#define t0__t0_a0 add t0,a0,t0 +#define t0__t0_2a0 sh1add a0,t0,t0 +#define t0__t0_4a0 sh2add a0,t0,t0 +#define t0__t0_8a0 sh3add a0,t0,t0 +#define t0__2t0_a0 sh1add t0,a0,t0 +#define t0__3t0 sh1add t0,t0,t0 +#define t0__4t0 sh2add t0,0,t0 +#define t0__4t0_a0 sh2add t0,a0,t0 +#define t0__5t0 sh2add t0,t0,t0 +#define t0__8t0 sh3add t0,0,t0 +#define t0__8t0_a0 sh3add t0,a0,t0 +#define t0__9t0 sh3add t0,t0,t0 +#define t0__16t0 zdep t0,27,28,t0 +#define t0__32t0 zdep t0,26,27,t0 +#define t0__256a0 zdep a0,23,24,t0 + + + SUBSPA_MILLI + ATTR_MILLI + .align 16 + .proc + .callinfo millicode + .export $$mulI,millicode +GSYM($$mulI) + combt,<<= a1,a0,LREF(l4) /* swap args if unsigned a1>a0 */ + copy 0,r /* zero out the result */ + xor a0,a1,a0 /* swap a0 & a1 using the */ + xor a0,a1,a1 /* old xor trick */ + xor a0,a1,a0 +LSYM(l4) + combt,<= 0,a0,LREF(l3) /* if a0>=0 then proceed like unsigned */ + zdep a1,30,8,t0 /* t0 = (a1&0xff)<<1 ********* */ + sub,> 0,a1,t0 /* otherwise negate both and */ + combt,<=,n a0,t0,LREF(l2) /* swap back if |a0|<|a1| */ + sub 0,a0,a1 + movb,tr,n t0,a0,LREF(l2) /* 10th inst. */ + +LSYM(l0) r__r_t0 /* add in this partial product */ +LSYM(l1) a0__256a0 /* a0 <<= 8 ****************** */ +LSYM(l2) zdep a1,30,8,t0 /* t0 = (a1&0xff)<<1 ********* */ +LSYM(l3) blr t0,0 /* case on these 8 bits ****** */ + extru a1,23,24,a1 /* a1 >>= 8 ****************** */ + +/*16 insts before this. */ +/* a0 <<= 8 ************************** */ +LSYM(x0) a1_ne_0_b_l2 ! a0__256a0 ! MILLIRETN ! nop +LSYM(x1) a1_ne_0_b_l1 ! r__r_a0 ! MILLIRETN ! nop +LSYM(x2) a1_ne_0_b_l1 ! r__r_2a0 ! MILLIRETN ! nop +LSYM(x3) a1_ne_0_b_l0 ! t0__3a0 ! MILLIRET ! r__r_t0 +LSYM(x4) a1_ne_0_b_l1 ! r__r_4a0 ! MILLIRETN ! nop +LSYM(x5) a1_ne_0_b_l0 ! t0__5a0 ! MILLIRET ! r__r_t0 +LSYM(x6) t0__3a0 ! a1_ne_0_b_l1 ! r__r_2t0 ! MILLIRETN +LSYM(x7) t0__3a0 ! a1_ne_0_b_l0 ! r__r_4a0 ! b_n_ret_t0 +LSYM(x8) a1_ne_0_b_l1 ! r__r_8a0 ! MILLIRETN ! nop +LSYM(x9) a1_ne_0_b_l0 ! t0__9a0 ! MILLIRET ! r__r_t0 +LSYM(x10) t0__5a0 ! a1_ne_0_b_l1 ! r__r_2t0 ! MILLIRETN +LSYM(x11) t0__3a0 ! a1_ne_0_b_l0 ! r__r_8a0 ! b_n_ret_t0 +LSYM(x12) t0__3a0 ! a1_ne_0_b_l1 ! r__r_4t0 ! MILLIRETN +LSYM(x13) t0__5a0 ! a1_ne_0_b_l0 ! r__r_8a0 ! b_n_ret_t0 +LSYM(x14) t0__3a0 ! t0__2t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x15) t0__5a0 ! a1_ne_0_b_l0 ! t0__3t0 ! b_n_ret_t0 +LSYM(x16) t0__16a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN +LSYM(x17) t0__9a0 ! a1_ne_0_b_l0 ! t0__t0_8a0 ! b_n_ret_t0 +LSYM(x18) t0__9a0 ! a1_ne_0_b_l1 ! r__r_2t0 ! MILLIRETN +LSYM(x19) t0__9a0 ! a1_ne_0_b_l0 ! t0__2t0_a0 ! b_n_ret_t0 +LSYM(x20) t0__5a0 ! a1_ne_0_b_l1 ! r__r_4t0 ! MILLIRETN +LSYM(x21) t0__5a0 ! a1_ne_0_b_l0 ! t0__4t0_a0 ! b_n_ret_t0 +LSYM(x22) t0__5a0 ! t0__2t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x23) t0__5a0 ! t0__2t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x24) t0__3a0 ! a1_ne_0_b_l1 ! r__r_8t0 ! MILLIRETN +LSYM(x25) t0__5a0 ! a1_ne_0_b_l0 ! t0__5t0 ! b_n_ret_t0 +LSYM(x26) t0__3a0 ! t0__4t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x27) t0__3a0 ! a1_ne_0_b_l0 ! t0__9t0 ! b_n_ret_t0 +LSYM(x28) t0__3a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x29) t0__3a0 ! t0__2t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x30) t0__5a0 ! t0__3t0 ! b_e_shift ! r__r_2t0 +LSYM(x31) t0__32a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0 +LSYM(x32) t0__32a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN +LSYM(x33) t0__8a0 ! a1_ne_0_b_l0 ! t0__4t0_a0 ! b_n_ret_t0 +LSYM(x34) t0__16a0 ! t0__t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x35) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__t0_8a0 +LSYM(x36) t0__9a0 ! a1_ne_0_b_l1 ! r__r_4t0 ! MILLIRETN +LSYM(x37) t0__9a0 ! a1_ne_0_b_l0 ! t0__4t0_a0 ! b_n_ret_t0 +LSYM(x38) t0__9a0 ! t0__2t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x39) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x40) t0__5a0 ! a1_ne_0_b_l1 ! r__r_8t0 ! MILLIRETN +LSYM(x41) t0__5a0 ! a1_ne_0_b_l0 ! t0__8t0_a0 ! b_n_ret_t0 +LSYM(x42) t0__5a0 ! t0__4t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x43) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x44) t0__5a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x45) t0__9a0 ! a1_ne_0_b_l0 ! t0__5t0 ! b_n_ret_t0 +LSYM(x46) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__t0_a0 +LSYM(x47) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__t0_2a0 +LSYM(x48) t0__3a0 ! a1_ne_0_b_l0 ! t0__16t0 ! b_n_ret_t0 +LSYM(x49) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__t0_4a0 +LSYM(x50) t0__5a0 ! t0__5t0 ! b_e_shift ! r__r_2t0 +LSYM(x51) t0__9a0 ! t0__t0_8a0 ! b_e_t0 ! t0__3t0 +LSYM(x52) t0__3a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x53) t0__3a0 ! t0__4t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x54) t0__9a0 ! t0__3t0 ! b_e_shift ! r__r_2t0 +LSYM(x55) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x56) t0__3a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x57) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x58) t0__3a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x59) t0__9a0 ! t0__2t0_a0 ! b_e_t02a0 ! t0__3t0 +LSYM(x60) t0__5a0 ! t0__3t0 ! b_e_shift ! r__r_4t0 +LSYM(x61) t0__5a0 ! t0__3t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x62) t0__32a0 ! t0__t0ma0 ! b_e_shift ! r__r_2t0 +LSYM(x63) t0__64a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0 +LSYM(x64) t0__64a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN +LSYM(x65) t0__8a0 ! a1_ne_0_b_l0 ! t0__8t0_a0 ! b_n_ret_t0 +LSYM(x66) t0__32a0 ! t0__t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x67) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x68) t0__8a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x69) t0__8a0 ! t0__2t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x70) t0__64a0 ! t0__t0_4a0 ! b_e_t0 ! t0__t0_2a0 +LSYM(x71) t0__9a0 ! t0__8t0 ! b_e_t0 ! t0__t0ma0 +LSYM(x72) t0__9a0 ! a1_ne_0_b_l1 ! r__r_8t0 ! MILLIRETN +LSYM(x73) t0__9a0 ! t0__8t0_a0 ! b_e_shift ! r__r_t0 +LSYM(x74) t0__9a0 ! t0__4t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x75) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x76) t0__9a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x77) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x78) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x79) t0__16a0 ! t0__5t0 ! b_e_t0 ! t0__t0ma0 +LSYM(x80) t0__16a0 ! t0__5t0 ! b_e_shift ! r__r_t0 +LSYM(x81) t0__9a0 ! t0__9t0 ! b_e_shift ! r__r_t0 +LSYM(x82) t0__5a0 ! t0__8t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x83) t0__5a0 ! t0__8t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x84) t0__5a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x85) t0__8a0 ! t0__2t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x86) t0__5a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x87) t0__9a0 ! t0__9t0 ! b_e_t02a0 ! t0__t0_4a0 +LSYM(x88) t0__5a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x89) t0__5a0 ! t0__2t0_a0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x90) t0__9a0 ! t0__5t0 ! b_e_shift ! r__r_2t0 +LSYM(x91) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x92) t0__5a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__2t0_a0 +LSYM(x93) t0__32a0 ! t0__t0ma0 ! b_e_t0 ! t0__3t0 +LSYM(x94) t0__9a0 ! t0__5t0 ! b_e_2t0 ! t0__t0_2a0 +LSYM(x95) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x96) t0__8a0 ! t0__3t0 ! b_e_shift ! r__r_4t0 +LSYM(x97) t0__8a0 ! t0__3t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x98) t0__32a0 ! t0__3t0 ! b_e_t0 ! t0__t0_2a0 +LSYM(x99) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x100) t0__5a0 ! t0__5t0 ! b_e_shift ! r__r_4t0 +LSYM(x101) t0__5a0 ! t0__5t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x102) t0__32a0 ! t0__t0_2a0 ! b_e_t0 ! t0__3t0 +LSYM(x103) t0__5a0 ! t0__5t0 ! b_e_t02a0 ! t0__4t0_a0 +LSYM(x104) t0__3a0 ! t0__4t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x105) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x106) t0__3a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x107) t0__9a0 ! t0__t0_4a0 ! b_e_t02a0 ! t0__8t0_a0 +LSYM(x108) t0__9a0 ! t0__3t0 ! b_e_shift ! r__r_4t0 +LSYM(x109) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x110) t0__9a0 ! t0__3t0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x111) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x112) t0__3a0 ! t0__2t0_a0 ! b_e_t0 ! t0__16t0 +LSYM(x113) t0__9a0 ! t0__4t0_a0 ! b_e_t02a0 ! t0__3t0 +LSYM(x114) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__3t0 +LSYM(x115) t0__9a0 ! t0__2t0_a0 ! b_e_2t0a0 ! t0__3t0 +LSYM(x116) t0__3a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__4t0_a0 +LSYM(x117) t0__3a0 ! t0__4t0_a0 ! b_e_t0 ! t0__9t0 +LSYM(x118) t0__3a0 ! t0__4t0_a0 ! b_e_t0a0 ! t0__9t0 +LSYM(x119) t0__3a0 ! t0__4t0_a0 ! b_e_t02a0 ! t0__9t0 +LSYM(x120) t0__5a0 ! t0__3t0 ! b_e_shift ! r__r_8t0 +LSYM(x121) t0__5a0 ! t0__3t0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x122) t0__5a0 ! t0__3t0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x123) t0__5a0 ! t0__8t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x124) t0__32a0 ! t0__t0ma0 ! b_e_shift ! r__r_4t0 +LSYM(x125) t0__5a0 ! t0__5t0 ! b_e_t0 ! t0__5t0 +LSYM(x126) t0__64a0 ! t0__t0ma0 ! b_e_shift ! r__r_2t0 +LSYM(x127) t0__128a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0 +LSYM(x128) t0__128a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN +LSYM(x129) t0__128a0 ! a1_ne_0_b_l0 ! t0__t0_a0 ! b_n_ret_t0 +LSYM(x130) t0__64a0 ! t0__t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x131) t0__8a0 ! t0__8t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x132) t0__8a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x133) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x134) t0__8a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x135) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__3t0 +LSYM(x136) t0__8a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x137) t0__8a0 ! t0__2t0_a0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x138) t0__8a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x139) t0__8a0 ! t0__2t0_a0 ! b_e_2t0a0 ! t0__4t0_a0 +LSYM(x140) t0__3a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__5t0 +LSYM(x141) t0__8a0 ! t0__2t0_a0 ! b_e_4t0a0 ! t0__2t0_a0 +LSYM(x142) t0__9a0 ! t0__8t0 ! b_e_2t0 ! t0__t0ma0 +LSYM(x143) t0__16a0 ! t0__9t0 ! b_e_t0 ! t0__t0ma0 +LSYM(x144) t0__9a0 ! t0__8t0 ! b_e_shift ! r__r_2t0 +LSYM(x145) t0__9a0 ! t0__8t0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x146) t0__9a0 ! t0__8t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x147) t0__9a0 ! t0__8t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x148) t0__9a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x149) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x150) t0__9a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x151) t0__9a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__2t0_a0 +LSYM(x152) t0__9a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x153) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x154) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x155) t0__32a0 ! t0__t0ma0 ! b_e_t0 ! t0__5t0 +LSYM(x156) t0__9a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__2t0_a0 +LSYM(x157) t0__32a0 ! t0__t0ma0 ! b_e_t02a0 ! t0__5t0 +LSYM(x158) t0__16a0 ! t0__5t0 ! b_e_2t0 ! t0__t0ma0 +LSYM(x159) t0__32a0 ! t0__5t0 ! b_e_t0 ! t0__t0ma0 +LSYM(x160) t0__5a0 ! t0__4t0 ! b_e_shift ! r__r_8t0 +LSYM(x161) t0__8a0 ! t0__5t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x162) t0__9a0 ! t0__9t0 ! b_e_shift ! r__r_2t0 +LSYM(x163) t0__9a0 ! t0__9t0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x164) t0__5a0 ! t0__8t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x165) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x166) t0__5a0 ! t0__8t0_a0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x167) t0__5a0 ! t0__8t0_a0 ! b_e_2t0a0 ! t0__2t0_a0 +LSYM(x168) t0__5a0 ! t0__4t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x169) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x170) t0__32a0 ! t0__t0_2a0 ! b_e_t0 ! t0__5t0 +LSYM(x171) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__9t0 +LSYM(x172) t0__5a0 ! t0__4t0_a0 ! b_e_4t0 ! t0__2t0_a0 +LSYM(x173) t0__9a0 ! t0__2t0_a0 ! b_e_t02a0 ! t0__9t0 +LSYM(x174) t0__32a0 ! t0__t0_2a0 ! b_e_t04a0 ! t0__5t0 +LSYM(x175) t0__8a0 ! t0__2t0_a0 ! b_e_5t0 ! t0__2t0_a0 +LSYM(x176) t0__5a0 ! t0__4t0_a0 ! b_e_8t0 ! t0__t0_a0 +LSYM(x177) t0__5a0 ! t0__4t0_a0 ! b_e_8t0a0 ! t0__t0_a0 +LSYM(x178) t0__5a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__8t0_a0 +LSYM(x179) t0__5a0 ! t0__2t0_a0 ! b_e_2t0a0 ! t0__8t0_a0 +LSYM(x180) t0__9a0 ! t0__5t0 ! b_e_shift ! r__r_4t0 +LSYM(x181) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x182) t0__9a0 ! t0__5t0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x183) t0__9a0 ! t0__5t0 ! b_e_2t0a0 ! t0__2t0_a0 +LSYM(x184) t0__5a0 ! t0__9t0 ! b_e_4t0 ! t0__t0_a0 +LSYM(x185) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x186) t0__32a0 ! t0__t0ma0 ! b_e_2t0 ! t0__3t0 +LSYM(x187) t0__9a0 ! t0__4t0_a0 ! b_e_t02a0 ! t0__5t0 +LSYM(x188) t0__9a0 ! t0__5t0 ! b_e_4t0 ! t0__t0_2a0 +LSYM(x189) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__9t0 +LSYM(x190) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__5t0 +LSYM(x191) t0__64a0 ! t0__3t0 ! b_e_t0 ! t0__t0ma0 +LSYM(x192) t0__8a0 ! t0__3t0 ! b_e_shift ! r__r_8t0 +LSYM(x193) t0__8a0 ! t0__3t0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x194) t0__8a0 ! t0__3t0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x195) t0__8a0 ! t0__8t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x196) t0__8a0 ! t0__3t0 ! b_e_4t0 ! t0__2t0_a0 +LSYM(x197) t0__8a0 ! t0__3t0 ! b_e_4t0a0 ! t0__2t0_a0 +LSYM(x198) t0__64a0 ! t0__t0_2a0 ! b_e_t0 ! t0__3t0 +LSYM(x199) t0__8a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__3t0 +LSYM(x200) t0__5a0 ! t0__5t0 ! b_e_shift ! r__r_8t0 +LSYM(x201) t0__5a0 ! t0__5t0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x202) t0__5a0 ! t0__5t0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x203) t0__5a0 ! t0__5t0 ! b_e_2t0a0 ! t0__4t0_a0 +LSYM(x204) t0__8a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__3t0 +LSYM(x205) t0__5a0 ! t0__8t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x206) t0__64a0 ! t0__t0_4a0 ! b_e_t02a0 ! t0__3t0 +LSYM(x207) t0__8a0 ! t0__2t0_a0 ! b_e_3t0 ! t0__4t0_a0 +LSYM(x208) t0__5a0 ! t0__5t0 ! b_e_8t0 ! t0__t0_a0 +LSYM(x209) t0__5a0 ! t0__5t0 ! b_e_8t0a0 ! t0__t0_a0 +LSYM(x210) t0__5a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__5t0 +LSYM(x211) t0__5a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__5t0 +LSYM(x212) t0__3a0 ! t0__4t0_a0 ! b_e_4t0 ! t0__4t0_a0 +LSYM(x213) t0__3a0 ! t0__4t0_a0 ! b_e_4t0a0 ! t0__4t0_a0 +LSYM(x214) t0__9a0 ! t0__t0_4a0 ! b_e_2t04a0 ! t0__8t0_a0 +LSYM(x215) t0__5a0 ! t0__4t0_a0 ! b_e_5t0 ! t0__2t0_a0 +LSYM(x216) t0__9a0 ! t0__3t0 ! b_e_shift ! r__r_8t0 +LSYM(x217) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x218) t0__9a0 ! t0__3t0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x219) t0__9a0 ! t0__8t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x220) t0__3a0 ! t0__9t0 ! b_e_4t0 ! t0__2t0_a0 +LSYM(x221) t0__3a0 ! t0__9t0 ! b_e_4t0a0 ! t0__2t0_a0 +LSYM(x222) t0__9a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__3t0 +LSYM(x223) t0__9a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__3t0 +LSYM(x224) t0__9a0 ! t0__3t0 ! b_e_8t0 ! t0__t0_a0 +LSYM(x225) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__5t0 +LSYM(x226) t0__3a0 ! t0__2t0_a0 ! b_e_t02a0 ! t0__32t0 +LSYM(x227) t0__9a0 ! t0__5t0 ! b_e_t02a0 ! t0__5t0 +LSYM(x228) t0__9a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__3t0 +LSYM(x229) t0__9a0 ! t0__2t0_a0 ! b_e_4t0a0 ! t0__3t0 +LSYM(x230) t0__9a0 ! t0__5t0 ! b_e_5t0 ! t0__t0_a0 +LSYM(x231) t0__9a0 ! t0__2t0_a0 ! b_e_3t0 ! t0__4t0_a0 +LSYM(x232) t0__3a0 ! t0__2t0_a0 ! b_e_8t0 ! t0__4t0_a0 +LSYM(x233) t0__3a0 ! t0__2t0_a0 ! b_e_8t0a0 ! t0__4t0_a0 +LSYM(x234) t0__3a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__9t0 +LSYM(x235) t0__3a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__9t0 +LSYM(x236) t0__9a0 ! t0__2t0_a0 ! b_e_4t08a0 ! t0__3t0 +LSYM(x237) t0__16a0 ! t0__5t0 ! b_e_3t0 ! t0__t0ma0 +LSYM(x238) t0__3a0 ! t0__4t0_a0 ! b_e_2t04a0 ! t0__9t0 +LSYM(x239) t0__16a0 ! t0__5t0 ! b_e_t0ma0 ! t0__3t0 +LSYM(x240) t0__9a0 ! t0__t0_a0 ! b_e_8t0 ! t0__3t0 +LSYM(x241) t0__9a0 ! t0__t0_a0 ! b_e_8t0a0 ! t0__3t0 +LSYM(x242) t0__5a0 ! t0__3t0 ! b_e_2t0 ! t0__8t0_a0 +LSYM(x243) t0__9a0 ! t0__9t0 ! b_e_t0 ! t0__3t0 +LSYM(x244) t0__5a0 ! t0__3t0 ! b_e_4t0 ! t0__4t0_a0 +LSYM(x245) t0__8a0 ! t0__3t0 ! b_e_5t0 ! t0__2t0_a0 +LSYM(x246) t0__5a0 ! t0__8t0_a0 ! b_e_2t0 ! t0__3t0 +LSYM(x247) t0__5a0 ! t0__8t0_a0 ! b_e_2t0a0 ! t0__3t0 +LSYM(x248) t0__32a0 ! t0__t0ma0 ! b_e_shift ! r__r_8t0 +LSYM(x249) t0__32a0 ! t0__t0ma0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x250) t0__5a0 ! t0__5t0 ! b_e_2t0 ! t0__5t0 +LSYM(x251) t0__5a0 ! t0__5t0 ! b_e_2t0a0 ! t0__5t0 +LSYM(x252) t0__64a0 ! t0__t0ma0 ! b_e_shift ! r__r_4t0 +LSYM(x253) t0__64a0 ! t0__t0ma0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x254) t0__128a0 ! t0__t0ma0 ! b_e_shift ! r__r_2t0 +LSYM(x255) t0__256a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0 +/*1040 insts before this. */ +LSYM(ret_t0) MILLIRET +LSYM(e_t0) r__r_t0 +LSYM(e_shift) a1_ne_0_b_l2 + a0__256a0 /* a0 <<= 8 *********** */ + MILLIRETN +LSYM(e_t0ma0) a1_ne_0_b_l0 + t0__t0ma0 + MILLIRET + r__r_t0 +LSYM(e_t0a0) a1_ne_0_b_l0 + t0__t0_a0 + MILLIRET + r__r_t0 +LSYM(e_t02a0) a1_ne_0_b_l0 + t0__t0_2a0 + MILLIRET + r__r_t0 +LSYM(e_t04a0) a1_ne_0_b_l0 + t0__t0_4a0 + MILLIRET + r__r_t0 +LSYM(e_2t0) a1_ne_0_b_l1 + r__r_2t0 + MILLIRETN +LSYM(e_2t0a0) a1_ne_0_b_l0 + t0__2t0_a0 + MILLIRET + r__r_t0 +LSYM(e2t04a0) t0__t0_2a0 + a1_ne_0_b_l1 + r__r_2t0 + MILLIRETN +LSYM(e_3t0) a1_ne_0_b_l0 + t0__3t0 + MILLIRET + r__r_t0 +LSYM(e_4t0) a1_ne_0_b_l1 + r__r_4t0 + MILLIRETN +LSYM(e_4t0a0) a1_ne_0_b_l0 + t0__4t0_a0 + MILLIRET + r__r_t0 +LSYM(e4t08a0) t0__t0_2a0 + a1_ne_0_b_l1 + r__r_4t0 + MILLIRETN +LSYM(e_5t0) a1_ne_0_b_l0 + t0__5t0 + MILLIRET + r__r_t0 +LSYM(e_8t0) a1_ne_0_b_l1 + r__r_8t0 + MILLIRETN +LSYM(e_8t0a0) a1_ne_0_b_l0 + t0__8t0_a0 + MILLIRET + r__r_t0 + + .procend + .end +#endif diff --git a/trunk/arch/parisc/lib/milli/remI.S b/trunk/arch/parisc/lib/milli/remI.S new file mode 100644 index 000000000000..63bc094471e2 --- /dev/null +++ b/trunk/arch/parisc/lib/milli/remI.S @@ -0,0 +1,185 @@ +/* 32 and 64-bit millicode, original author Hewlett-Packard + adapted for gcc by Paul Bame + and Alan Modra . + + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + This file is part of GCC and is released under the terms of + of the GNU General Public License as published by the Free Software + Foundation; either version 2, or (at your option) any later version. + See the file COPYING in the top-level GCC source directory for a copy + of the license. */ + +#include "milli.h" + +#ifdef L_remI +/* ROUTINE: $$remI + + DESCRIPTION: + . $$remI returns the remainder of the division of two signed 32-bit + . integers. The sign of the remainder is the same as the sign of + . the dividend. + + + INPUT REGISTERS: + . arg0 == dividend + . arg1 == divisor + . mrp == return pc + . sr0 == return space when called externally + + OUTPUT REGISTERS: + . arg0 = destroyed + . arg1 = destroyed + . ret1 = remainder + + OTHER REGISTERS AFFECTED: + . r1 = undefined + + SIDE EFFECTS: + . Causes a trap under the following conditions: DIVIDE BY ZERO + . Changes memory at the following places: NONE + + PERMISSIBLE CONTEXT: + . Unwindable + . Does not create a stack frame + . Is usable for internal or external microcode + + DISCUSSION: + . Calls other millicode routines via mrp: NONE + . Calls other millicode routines: NONE */ + +RDEFINE(tmp,r1) +RDEFINE(retreg,ret1) + + SUBSPA_MILLI + ATTR_MILLI + .proc + .callinfo millicode + .entry +GSYM($$remI) +GSYM($$remoI) + .export $$remI,MILLICODE + .export $$remoI,MILLICODE + ldo -1(arg1),tmp /* is there at most one bit set ? */ + and,<> arg1,tmp,r0 /* if not, don't use power of 2 */ + addi,> 0,arg1,r0 /* if denominator > 0, use power */ + /* of 2 */ + b,n LREF(neg_denom) +LSYM(pow2) + comb,>,n 0,arg0,LREF(neg_num) /* is numerator < 0 ? */ + and arg0,tmp,retreg /* get the result */ + MILLIRETN +LSYM(neg_num) + subi 0,arg0,arg0 /* negate numerator */ + and arg0,tmp,retreg /* get the result */ + subi 0,retreg,retreg /* negate result */ + MILLIRETN +LSYM(neg_denom) + addi,< 0,arg1,r0 /* if arg1 >= 0, it's not power */ + /* of 2 */ + b,n LREF(regular_seq) + sub r0,arg1,tmp /* make denominator positive */ + comb,=,n arg1,tmp,LREF(regular_seq) /* test against 0x80000000 and 0 */ + ldo -1(tmp),retreg /* is there at most one bit set ? */ + and,= tmp,retreg,r0 /* if not, go to regular_seq */ + b,n LREF(regular_seq) + comb,>,n 0,arg0,LREF(neg_num_2) /* if arg0 < 0, negate it */ + and arg0,retreg,retreg + MILLIRETN +LSYM(neg_num_2) + subi 0,arg0,tmp /* test against 0x80000000 */ + and tmp,retreg,retreg + subi 0,retreg,retreg + MILLIRETN +LSYM(regular_seq) + addit,= 0,arg1,0 /* trap if div by zero */ + add,>= 0,arg0,retreg /* move dividend, if retreg < 0, */ + sub 0,retreg,retreg /* make it positive */ + sub 0,arg1, tmp /* clear carry, */ + /* negate the divisor */ + ds 0, tmp,0 /* set V-bit to the comple- */ + /* ment of the divisor sign */ + or 0,0, tmp /* clear tmp */ + add retreg,retreg,retreg /* shift msb bit into carry */ + ds tmp,arg1, tmp /* 1st divide step, if no carry */ + /* out, msb of quotient = 0 */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ +LSYM(t1) + ds tmp,arg1, tmp /* 2nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 3rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 4th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 5th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 6th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 7th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 8th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 9th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 10th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 11th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 12th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 13th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 14th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 15th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 16th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 17th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 18th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 19th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 20th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 21st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 22nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 23rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 24th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 25th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 26th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 27th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 28th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 29th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 30th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 31st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 32nd divide step, */ + addc retreg,retreg,retreg /* shift last bit into retreg */ + movb,>=,n tmp,retreg,LREF(finish) /* branch if pos. tmp */ + add,< arg1,0,0 /* if arg1 > 0, add arg1 */ + add,tr tmp,arg1,retreg /* for correcting remainder tmp */ + sub tmp,arg1,retreg /* else add absolute value arg1 */ +LSYM(finish) + add,>= arg0,0,0 /* set sign of remainder */ + sub 0,retreg,retreg /* to sign of dividend */ + MILLIRET + nop + .exit + .procend +#ifdef milliext + .origin 0x00000200 +#endif + .end +#endif diff --git a/trunk/arch/parisc/lib/milli/remU.S b/trunk/arch/parisc/lib/milli/remU.S new file mode 100644 index 000000000000..c0a2d6e247c3 --- /dev/null +++ b/trunk/arch/parisc/lib/milli/remU.S @@ -0,0 +1,148 @@ +/* 32 and 64-bit millicode, original author Hewlett-Packard + adapted for gcc by Paul Bame + and Alan Modra . + + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + This file is part of GCC and is released under the terms of + of the GNU General Public License as published by the Free Software + Foundation; either version 2, or (at your option) any later version. + See the file COPYING in the top-level GCC source directory for a copy + of the license. */ + +#include "milli.h" + +#ifdef L_remU +/* ROUTINE: $$remU + . Single precision divide for remainder with unsigned binary integers. + . + . The remainder must be dividend-(dividend/divisor)*divisor. + . Divide by zero is trapped. + + INPUT REGISTERS: + . arg0 == dividend + . arg1 == divisor + . mrp == return pc + . sr0 == return space when called externally + + OUTPUT REGISTERS: + . arg0 = undefined + . arg1 = undefined + . ret1 = remainder + + OTHER REGISTERS AFFECTED: + . r1 = undefined + + SIDE EFFECTS: + . Causes a trap under the following conditions: DIVIDE BY ZERO + . Changes memory at the following places: NONE + + PERMISSIBLE CONTEXT: + . Unwindable. + . Does not create a stack frame. + . Suitable for internal or external millicode. + . Assumes the special millicode register conventions. + + DISCUSSION: + . Calls other millicode routines using mrp: NONE + . Calls other millicode routines: NONE */ + + +RDEFINE(temp,r1) +RDEFINE(rmndr,ret1) /* r29 */ + SUBSPA_MILLI + ATTR_MILLI + .export $$remU,millicode + .proc + .callinfo millicode + .entry +GSYM($$remU) + ldo -1(arg1),temp /* is there at most one bit set ? */ + and,= arg1,temp,r0 /* if not, don't use power of 2 */ + b LREF(regular_seq) + addit,= 0,arg1,r0 /* trap on div by zero */ + and arg0,temp,rmndr /* get the result for power of 2 */ + MILLIRETN +LSYM(regular_seq) + comib,>=,n 0,arg1,LREF(special_case) + subi 0,arg1,rmndr /* clear carry, negate the divisor */ + ds r0,rmndr,r0 /* set V-bit to 1 */ + add arg0,arg0,temp /* shift msb bit into carry */ + ds r0,arg1,rmndr /* 1st divide step, if no carry */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 2nd divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 3rd divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 4th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 5th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 6th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 7th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 8th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 9th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 10th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 11th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 12th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 13th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 14th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 15th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 16th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 17th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 18th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 19th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 20th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 21st divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 22nd divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 23rd divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 24th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 25th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 26th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 27th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 28th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 29th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 30th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 31st divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 32nd divide step, */ + comiclr,<= 0,rmndr,r0 + add rmndr,arg1,rmndr /* correction */ + MILLIRETN + nop + +/* Putting >= on the last DS and deleting COMICLR does not work! */ +LSYM(special_case) + sub,>>= arg0,arg1,rmndr + copy arg0,rmndr + MILLIRETN + nop + .exit + .procend + .end +#endif diff --git a/trunk/arch/powerpc/kernel/asm-offsets.c b/trunk/arch/powerpc/kernel/asm-offsets.c index ed083feaf6f9..d67bcd84f329 100644 --- a/trunk/arch/powerpc/kernel/asm-offsets.c +++ b/trunk/arch/powerpc/kernel/asm-offsets.c @@ -326,7 +326,8 @@ int main(void) DEFINE(VMALLOC_START_VSID, KERNEL_VSID(VMALLOC_START)); #endif +#ifdef CONFIG_PPC64 DEFINE(PGD_TABLE_SIZE, PGD_TABLE_SIZE); - +#endif return 0; } diff --git a/trunk/arch/powerpc/kernel/head_32.S b/trunk/arch/powerpc/kernel/head_32.S index 0f4fac512020..a5b13ae7fd20 100644 --- a/trunk/arch/powerpc/kernel/head_32.S +++ b/trunk/arch/powerpc/kernel/head_32.S @@ -1311,7 +1311,7 @@ empty_zero_page: .globl swapper_pg_dir swapper_pg_dir: - .space PGD_TABLE_SIZE + .space 4096 .globl intercept_table intercept_table: diff --git a/trunk/arch/powerpc/kernel/head_40x.S b/trunk/arch/powerpc/kernel/head_40x.S index 8552e67e3a8b..cfefc2df8f2a 100644 --- a/trunk/arch/powerpc/kernel/head_40x.S +++ b/trunk/arch/powerpc/kernel/head_40x.S @@ -994,7 +994,7 @@ empty_zero_page: .space 4096 .globl swapper_pg_dir swapper_pg_dir: - .space PGD_TABLE_SIZE + .space 4096 /* Stack for handling critical exceptions from kernel mode */ diff --git a/trunk/arch/powerpc/kernel/head_44x.S b/trunk/arch/powerpc/kernel/head_44x.S index 56aba84c1f6e..409db6123924 100644 --- a/trunk/arch/powerpc/kernel/head_44x.S +++ b/trunk/arch/powerpc/kernel/head_44x.S @@ -722,7 +722,7 @@ empty_zero_page: */ .globl swapper_pg_dir swapper_pg_dir: - .space PGD_TABLE_SIZE + .space 8192 /* Reserved 4k for the critical exception stack & 4k for the machine * check stack per CPU for kernel mode exceptions */ diff --git a/trunk/arch/powerpc/kernel/head_fsl_booke.S b/trunk/arch/powerpc/kernel/head_fsl_booke.S index 7aecb39a5a45..4b9822728aea 100644 --- a/trunk/arch/powerpc/kernel/head_fsl_booke.S +++ b/trunk/arch/powerpc/kernel/head_fsl_booke.S @@ -1035,7 +1035,7 @@ empty_zero_page: .space 4096 .globl swapper_pg_dir swapper_pg_dir: - .space PGD_TABLE_SIZE + .space 4096 /* Reserved 4k for the critical exception stack & 4k for the machine * check stack per CPU for kernel mode exceptions */ diff --git a/trunk/arch/s390/kernel/entry.S b/trunk/arch/s390/kernel/entry.S index 1a6dac8df6fb..b2b2edc40eb1 100644 --- a/trunk/arch/s390/kernel/entry.S +++ b/trunk/arch/s390/kernel/entry.S @@ -1079,10 +1079,8 @@ cleanup_io_leave_insn: .Lexecve_tail: .long execve_tail .Ljump_table: .long pgm_check_table .Lschedule: .long schedule -#ifdef CONFIG_PREEMPT .Lpreempt_schedule_irq: .long preempt_schedule_irq -#endif .Ltrace: .long syscall_trace .Lschedtail: .long schedule_tail .Lsysc_table: .long sys_call_table diff --git a/trunk/arch/s390/kernel/setup.c b/trunk/arch/s390/kernel/setup.c index 577aa7dd660e..50f8f1e3760e 100644 --- a/trunk/arch/s390/kernel/setup.c +++ b/trunk/arch/s390/kernel/setup.c @@ -486,7 +486,9 @@ static void setup_addressing_mode(void) if (s390_noexec) { printk("S390 execute protection active, "); set_amode_and_uaccess(PSW_ASC_SECONDARY, PSW32_ASC_SECONDARY); - } else if (switch_amode) { + return; + } + if (switch_amode) { printk("S390 address spaces switched, "); set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY); } diff --git a/trunk/arch/sparc/kernel/devices.c b/trunk/arch/sparc/kernel/devices.c index b240b8863fd0..af90a5f9ab57 100644 --- a/trunk/arch/sparc/kernel/devices.c +++ b/trunk/arch/sparc/kernel/devices.c @@ -62,10 +62,8 @@ static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg, int err = check_cpu_node(dp->node, &cur_inst, compare, compare_arg, prom_node, mid); - if (!err) { - of_node_put(dp); + if (!err) return 0; - } } return -ENODEV; diff --git a/trunk/arch/sparc/kernel/pcic.c b/trunk/arch/sparc/kernel/pcic.c index 4cd5d7818dc6..f2d432edc92d 100644 --- a/trunk/arch/sparc/kernel/pcic.c +++ b/trunk/arch/sparc/kernel/pcic.c @@ -329,7 +329,7 @@ int __init pcic_probe(void) pcic->pcic_res_cfg_addr.name = "pcic_cfg_addr"; if ((pcic->pcic_config_space_addr = ioremap(regs[2].phys_addr, regs[2].reg_size * 2)) == 0) { - prom_printf("PCIC: Error, cannot map " + prom_printf("PCIC: Error, cannot map" "PCI Configuration Space Address.\n"); prom_halt(); } @@ -341,7 +341,7 @@ int __init pcic_probe(void) pcic->pcic_res_cfg_data.name = "pcic_cfg_data"; if ((pcic->pcic_config_space_data = ioremap(regs[3].phys_addr, regs[3].reg_size * 2)) == 0) { - prom_printf("PCIC: Error, cannot map " + prom_printf("PCIC: Error, cannot map" "PCI Configuration Space Data.\n"); prom_halt(); } @@ -518,8 +518,8 @@ static void pcic_map_pci_device(struct linux_pcic *pcic, * board in a PCI slot. We must remap it * under 64K but it is not done yet. XXX */ - printk("PCIC: Skipping I/O space at 0x%lx, " - "this will Oops if a driver attaches " + printk("PCIC: Skipping I/O space at 0x%lx," + "this will Oops if a driver attaches;" "device '%s' at %02x:%02x)\n", address, namebuf, dev->bus->number, dev->devfn); } diff --git a/trunk/arch/sparc64/defconfig b/trunk/arch/sparc64/defconfig index f62d9f6c5e2a..22734ac08c8a 100644 --- a/trunk/arch/sparc64/defconfig +++ b/trunk/arch/sparc64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.24-rc4 -# Tue Dec 4 00:37:59 2007 +# Linux kernel version: 2.6.24-rc1 +# Wed Oct 31 15:36:47 2007 # CONFIG_SPARC=y CONFIG_SPARC64=y @@ -47,7 +47,6 @@ CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set # CONFIG_USER_NS is not set -# CONFIG_PID_NS is not set # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=18 @@ -155,7 +154,6 @@ CONFIG_PCI_DOMAINS=y CONFIG_PCI_SYSCALL=y CONFIG_ARCH_SUPPORTS_MSI=y CONFIG_PCI_MSI=y -# CONFIG_PCI_LEGACY is not set # CONFIG_PCI_DEBUG is not set CONFIG_SUN_OPENPROMFS=m CONFIG_SPARC32_COMPAT=y @@ -361,6 +359,7 @@ CONFIG_IDE_GENERIC=y CONFIG_BLK_DEV_IDEPCI=y # CONFIG_IDEPCI_SHARE_IRQ is not set CONFIG_IDEPCI_PCIBUS_ORDER=y +# CONFIG_BLK_DEV_OFFBOARD is not set # CONFIG_BLK_DEV_GENERIC is not set # CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_IDEDMA_PCI=y @@ -585,6 +584,7 @@ CONFIG_NIU=m # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET_MII is not set # CONFIG_USB_USBNET is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set @@ -780,7 +780,6 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ADT7470 is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_I5K_AMB is not set # CONFIG_SENSORS_F71805F is not set # CONFIG_SENSORS_F71882FG is not set # CONFIG_SENSORS_F75375S is not set diff --git a/trunk/arch/sparc64/kernel/isa.c b/trunk/arch/sparc64/kernel/isa.c index b5f7b354084f..0f19dce1c905 100644 --- a/trunk/arch/sparc64/kernel/isa.c +++ b/trunk/arch/sparc64/kernel/isa.c @@ -155,7 +155,6 @@ void __init isa_init(void) isa_br = kzalloc(sizeof(*isa_br), GFP_KERNEL); if (!isa_br) { printk(KERN_DEBUG "isa: cannot allocate sparc_isa_bridge"); - pci_dev_put(pdev); return; } @@ -169,7 +168,6 @@ void __init isa_init(void) printk(KERN_DEBUG "isa: device registration error for %s!\n", dp->path_component_name); kfree(isa_br); - pci_dev_put(pdev); return; } diff --git a/trunk/arch/sparc64/kernel/ldc.c b/trunk/arch/sparc64/kernel/ldc.c index 63969f610284..217478a94128 100644 --- a/trunk/arch/sparc64/kernel/ldc.c +++ b/trunk/arch/sparc64/kernel/ldc.c @@ -2338,7 +2338,6 @@ static int __init ldc_init(void) unsigned long major, minor; struct mdesc_handle *hp; const u64 *v; - int err; u64 mp; hp = mdesc_grab(); @@ -2346,33 +2345,29 @@ static int __init ldc_init(void) return -ENODEV; mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "platform"); - err = -ENODEV; if (mp == MDESC_NODE_NULL) - goto out; + return -ENODEV; v = mdesc_get_property(hp, mp, "domaining-enabled", NULL); if (!v) - goto out; + return -ENODEV; major = 1; minor = 0; if (sun4v_hvapi_register(HV_GRP_LDOM, major, &minor)) { printk(KERN_INFO PFX "Could not register LDOM hvapi.\n"); - goto out; + return -ENODEV; } printk(KERN_INFO "%s", version); if (!*v) { printk(KERN_INFO PFX "Domaining disabled.\n"); - goto out; + return -ENODEV; } ldom_domaining_enabled = 1; - err = 0; -out: - mdesc_release(hp); - return err; + return 0; } core_initcall(ldc_init); diff --git a/trunk/arch/sparc64/kernel/pci_sun4v.c b/trunk/arch/sparc64/kernel/pci_sun4v.c index e587a372f3fe..8c4875bdb4a8 100644 --- a/trunk/arch/sparc64/kernel/pci_sun4v.c +++ b/trunk/arch/sparc64/kernel/pci_sun4v.c @@ -1022,10 +1022,6 @@ void __init sun4v_pci_init(struct device_node *dp, char *model_name) } prop = of_find_property(dp, "reg", NULL); - if (!prop) { - prom_printf("SUN4V_PCI: Could not find config registers\n"); - prom_halt(); - } regs = prop->value; devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff; diff --git a/trunk/arch/sparc64/kernel/smp.c b/trunk/arch/sparc64/kernel/smp.c index 894b506f9636..7cd8d94df0dc 100644 --- a/trunk/arch/sparc64/kernel/smp.c +++ b/trunk/arch/sparc64/kernel/smp.c @@ -236,9 +236,8 @@ void smp_synchronize_tick_client(void) t[i].rt, t[i].master, t[i].diff, t[i].lat); #endif - printk(KERN_INFO "CPU %d: synchronized TICK with master CPU " - "(last diff %ld cycles, maxerr %lu cycles)\n", - smp_processor_id(), delta, rt); + printk(KERN_INFO "CPU %d: synchronized TICK with master CPU (last diff %ld cycles," + "maxerr %lu cycles)\n", smp_processor_id(), delta, rt); } static void smp_start_sync_tick_client(int cpu); diff --git a/trunk/arch/um/Makefile-i386 b/trunk/arch/um/Makefile-i386 index 561e373bd850..67290117d909 100644 --- a/trunk/arch/um/Makefile-i386 +++ b/trunk/arch/um/Makefile-i386 @@ -22,6 +22,11 @@ export LDFLAGS HOSTCFLAGS HOSTLDFLAGS UML_OBJCOPYFLAGS endif endif +KBUILD_CFLAGS += -DCONFIG_X86_32 +KBUILD_AFLAGS += -DCONFIG_X86_32 +CONFIG_X86_32 := y +export CONFIG_X86_32 + # First of all, tune CFLAGS for the specific CPU. This actually sets cflags-y. include $(srctree)/arch/x86/Makefile_32.cpu diff --git a/trunk/arch/x86/Kconfig b/trunk/arch/x86/Kconfig index 80b7ba4056db..368864dfe6eb 100644 --- a/trunk/arch/x86/Kconfig +++ b/trunk/arch/x86/Kconfig @@ -112,9 +112,8 @@ config GENERIC_TIME_VSYSCALL bool default X86_64 -config ARCH_SUPPORTS_OPROFILE - bool - default y + + config ZONE_DMA32 @@ -149,8 +148,7 @@ config X86_SMP config X86_HT bool - depends on SMP - depends on (X86_32 && !(X86_VISWS || X86_VOYAGER)) || (X86_64 && !MK8) + depends on SMP && !(X86_VISWS || X86_VOYAGER || MK8) default y config X86_BIOS_REBOOT diff --git a/trunk/arch/x86/kernel/cpu/intel_cacheinfo.c b/trunk/arch/x86/kernel/cpu/intel_cacheinfo.c index 606fe4d55a91..9921b01fe199 100644 --- a/trunk/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/trunk/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -497,7 +497,7 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) {} static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index) {} #endif -static void __cpuinit free_cache_attributes(unsigned int cpu) +static void free_cache_attributes(unsigned int cpu) { int i; diff --git a/trunk/arch/x86/kernel/nmi_32.c b/trunk/arch/x86/kernel/nmi_32.c index 80ca72e5ac29..f5cc47c60b13 100644 --- a/trunk/arch/x86/kernel/nmi_32.c +++ b/trunk/arch/x86/kernel/nmi_32.c @@ -106,8 +106,7 @@ static int __init check_nmi_watchdog(void) if (!per_cpu(wd_enabled, cpu)) continue; if (nmi_count(cpu) - prev_nmi_count[cpu] <= 5) { - printk(KERN_WARNING "WARNING: CPU#%d: NMI " - "appears to be stuck (%d->%d)!\n", + printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n", cpu, prev_nmi_count[cpu], nmi_count(cpu)); diff --git a/trunk/arch/x86/kernel/nmi_64.c b/trunk/arch/x86/kernel/nmi_64.c index 4253c4e8849c..a576fd740062 100644 --- a/trunk/arch/x86/kernel/nmi_64.c +++ b/trunk/arch/x86/kernel/nmi_64.c @@ -109,8 +109,7 @@ int __init check_nmi_watchdog (void) if (!per_cpu(wd_enabled, cpu)) continue; if (cpu_pda(cpu)->__nmi_count - counts[cpu] <= 5) { - printk(KERN_WARNING "WARNING: CPU#%d: NMI " - "appears to be stuck (%d->%d)!\n", + printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n", cpu, counts[cpu], cpu_pda(cpu)->__nmi_count); diff --git a/trunk/arch/x86/kernel/topology.c b/trunk/arch/x86/kernel/topology.c index 7e16d675eb85..8caa0b777466 100644 --- a/trunk/arch/x86/kernel/topology.c +++ b/trunk/arch/x86/kernel/topology.c @@ -33,7 +33,7 @@ static struct i386_cpu cpu_devices[NR_CPUS]; -int __cpuinit arch_register_cpu(int num) +int arch_register_cpu(int num) { /* * CPU0 cannot be offlined due to several @@ -53,8 +53,7 @@ int __cpuinit arch_register_cpu(int num) } #ifdef CONFIG_HOTPLUG_CPU -void arch_unregister_cpu(int num) -{ +void arch_unregister_cpu(int num) { return unregister_cpu(&cpu_devices[num].cpu); } EXPORT_SYMBOL(arch_register_cpu); diff --git a/trunk/crypto/fcrypt.c b/trunk/crypto/fcrypt.c index a32cb68bbc60..d161949fdb94 100644 --- a/trunk/crypto/fcrypt.c +++ b/trunk/crypto/fcrypt.c @@ -51,7 +51,7 @@ #define ROUNDS 16 struct fcrypt_ctx { - __be32 sched[ROUNDS]; + u32 sched[ROUNDS]; }; /* Rotate right two 32 bit numbers as a 56 bit number */ @@ -73,8 +73,8 @@ do { \ * /afs/transarc.com/public/afsps/afs.rel31b.export-src/rxkad/sboxes.h */ #undef Z -#define Z(x) __constant_cpu_to_be32(x << 3) -static const __be32 sbox0[256] = { +#define Z(x) __constant_be32_to_cpu(x << 3) +static const u32 sbox0[256] = { Z(0xea), Z(0x7f), Z(0xb2), Z(0x64), Z(0x9d), Z(0xb0), Z(0xd9), Z(0x11), Z(0xcd), Z(0x86), Z(0x86), Z(0x91), Z(0x0a), Z(0xb2), Z(0x93), Z(0x06), Z(0x0e), Z(0x06), Z(0xd2), Z(0x65), Z(0x73), Z(0xc5), Z(0x28), Z(0x60), @@ -110,8 +110,8 @@ static const __be32 sbox0[256] = { }; #undef Z -#define Z(x) __constant_cpu_to_be32((x << 27) | (x >> 5)) -static const __be32 sbox1[256] = { +#define Z(x) __constant_be32_to_cpu((x << 27) | (x >> 5)) +static const u32 sbox1[256] = { Z(0x77), Z(0x14), Z(0xa6), Z(0xfe), Z(0xb2), Z(0x5e), Z(0x8c), Z(0x3e), Z(0x67), Z(0x6c), Z(0xa1), Z(0x0d), Z(0xc2), Z(0xa2), Z(0xc1), Z(0x85), Z(0x6c), Z(0x7b), Z(0x67), Z(0xc6), Z(0x23), Z(0xe3), Z(0xf2), Z(0x89), @@ -147,8 +147,8 @@ static const __be32 sbox1[256] = { }; #undef Z -#define Z(x) __constant_cpu_to_be32(x << 11) -static const __be32 sbox2[256] = { +#define Z(x) __constant_be32_to_cpu(x << 11) +static const u32 sbox2[256] = { Z(0xf0), Z(0x37), Z(0x24), Z(0x53), Z(0x2a), Z(0x03), Z(0x83), Z(0x86), Z(0xd1), Z(0xec), Z(0x50), Z(0xf0), Z(0x42), Z(0x78), Z(0x2f), Z(0x6d), Z(0xbf), Z(0x80), Z(0x87), Z(0x27), Z(0x95), Z(0xe2), Z(0xc5), Z(0x5d), @@ -184,8 +184,8 @@ static const __be32 sbox2[256] = { }; #undef Z -#define Z(x) __constant_cpu_to_be32(x << 19) -static const __be32 sbox3[256] = { +#define Z(x) __constant_be32_to_cpu(x << 19) +static const u32 sbox3[256] = { Z(0xa9), Z(0x2a), Z(0x48), Z(0x51), Z(0x84), Z(0x7e), Z(0x49), Z(0xe2), Z(0xb5), Z(0xb7), Z(0x42), Z(0x33), Z(0x7d), Z(0x5d), Z(0xa6), Z(0x12), Z(0x44), Z(0x48), Z(0x6d), Z(0x28), Z(0xaa), Z(0x20), Z(0x6d), Z(0x57), @@ -225,7 +225,7 @@ static const __be32 sbox3[256] = { */ #define F_ENCRYPT(R, L, sched) \ do { \ - union lc4 { __be32 l; u8 c[4]; } u; \ + union lc4 { u32 l; u8 c[4]; } u; \ u.l = sched ^ R; \ L ^= sbox0[u.c[0]] ^ sbox1[u.c[1]] ^ sbox2[u.c[2]] ^ sbox3[u.c[3]]; \ } while(0) @@ -237,7 +237,7 @@ static void fcrypt_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { const struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm); struct { - __be32 l, r; + u32 l, r; } X; memcpy(&X, src, sizeof(X)); @@ -269,7 +269,7 @@ static void fcrypt_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { const struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm); struct { - __be32 l, r; + u32 l, r; } X; memcpy(&X, src, sizeof(X)); @@ -328,22 +328,22 @@ static int fcrypt_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int key k |= (*key) >> 1; /* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */ - ctx->sched[0x0] = cpu_to_be32(k); ror56_64(k, 11); - ctx->sched[0x1] = cpu_to_be32(k); ror56_64(k, 11); - ctx->sched[0x2] = cpu_to_be32(k); ror56_64(k, 11); - ctx->sched[0x3] = cpu_to_be32(k); ror56_64(k, 11); - ctx->sched[0x4] = cpu_to_be32(k); ror56_64(k, 11); - ctx->sched[0x5] = cpu_to_be32(k); ror56_64(k, 11); - ctx->sched[0x6] = cpu_to_be32(k); ror56_64(k, 11); - ctx->sched[0x7] = cpu_to_be32(k); ror56_64(k, 11); - ctx->sched[0x8] = cpu_to_be32(k); ror56_64(k, 11); - ctx->sched[0x9] = cpu_to_be32(k); ror56_64(k, 11); - ctx->sched[0xa] = cpu_to_be32(k); ror56_64(k, 11); - ctx->sched[0xb] = cpu_to_be32(k); ror56_64(k, 11); - ctx->sched[0xc] = cpu_to_be32(k); ror56_64(k, 11); - ctx->sched[0xd] = cpu_to_be32(k); ror56_64(k, 11); - ctx->sched[0xe] = cpu_to_be32(k); ror56_64(k, 11); - ctx->sched[0xf] = cpu_to_be32(k); + ctx->sched[0x0] = be32_to_cpu(k); ror56_64(k, 11); + ctx->sched[0x1] = be32_to_cpu(k); ror56_64(k, 11); + ctx->sched[0x2] = be32_to_cpu(k); ror56_64(k, 11); + ctx->sched[0x3] = be32_to_cpu(k); ror56_64(k, 11); + ctx->sched[0x4] = be32_to_cpu(k); ror56_64(k, 11); + ctx->sched[0x5] = be32_to_cpu(k); ror56_64(k, 11); + ctx->sched[0x6] = be32_to_cpu(k); ror56_64(k, 11); + ctx->sched[0x7] = be32_to_cpu(k); ror56_64(k, 11); + ctx->sched[0x8] = be32_to_cpu(k); ror56_64(k, 11); + ctx->sched[0x9] = be32_to_cpu(k); ror56_64(k, 11); + ctx->sched[0xa] = be32_to_cpu(k); ror56_64(k, 11); + ctx->sched[0xb] = be32_to_cpu(k); ror56_64(k, 11); + ctx->sched[0xc] = be32_to_cpu(k); ror56_64(k, 11); + ctx->sched[0xd] = be32_to_cpu(k); ror56_64(k, 11); + ctx->sched[0xe] = be32_to_cpu(k); ror56_64(k, 11); + ctx->sched[0xf] = be32_to_cpu(k); return 0; #else @@ -369,22 +369,22 @@ static int fcrypt_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int key lo |= (*key) >> 1; /* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */ - ctx->sched[0x0] = cpu_to_be32(lo); ror56(hi, lo, 11); - ctx->sched[0x1] = cpu_to_be32(lo); ror56(hi, lo, 11); - ctx->sched[0x2] = cpu_to_be32(lo); ror56(hi, lo, 11); - ctx->sched[0x3] = cpu_to_be32(lo); ror56(hi, lo, 11); - ctx->sched[0x4] = cpu_to_be32(lo); ror56(hi, lo, 11); - ctx->sched[0x5] = cpu_to_be32(lo); ror56(hi, lo, 11); - ctx->sched[0x6] = cpu_to_be32(lo); ror56(hi, lo, 11); - ctx->sched[0x7] = cpu_to_be32(lo); ror56(hi, lo, 11); - ctx->sched[0x8] = cpu_to_be32(lo); ror56(hi, lo, 11); - ctx->sched[0x9] = cpu_to_be32(lo); ror56(hi, lo, 11); - ctx->sched[0xa] = cpu_to_be32(lo); ror56(hi, lo, 11); - ctx->sched[0xb] = cpu_to_be32(lo); ror56(hi, lo, 11); - ctx->sched[0xc] = cpu_to_be32(lo); ror56(hi, lo, 11); - ctx->sched[0xd] = cpu_to_be32(lo); ror56(hi, lo, 11); - ctx->sched[0xe] = cpu_to_be32(lo); ror56(hi, lo, 11); - ctx->sched[0xf] = cpu_to_be32(lo); + ctx->sched[0x0] = be32_to_cpu(lo); ror56(hi, lo, 11); + ctx->sched[0x1] = be32_to_cpu(lo); ror56(hi, lo, 11); + ctx->sched[0x2] = be32_to_cpu(lo); ror56(hi, lo, 11); + ctx->sched[0x3] = be32_to_cpu(lo); ror56(hi, lo, 11); + ctx->sched[0x4] = be32_to_cpu(lo); ror56(hi, lo, 11); + ctx->sched[0x5] = be32_to_cpu(lo); ror56(hi, lo, 11); + ctx->sched[0x6] = be32_to_cpu(lo); ror56(hi, lo, 11); + ctx->sched[0x7] = be32_to_cpu(lo); ror56(hi, lo, 11); + ctx->sched[0x8] = be32_to_cpu(lo); ror56(hi, lo, 11); + ctx->sched[0x9] = be32_to_cpu(lo); ror56(hi, lo, 11); + ctx->sched[0xa] = be32_to_cpu(lo); ror56(hi, lo, 11); + ctx->sched[0xb] = be32_to_cpu(lo); ror56(hi, lo, 11); + ctx->sched[0xc] = be32_to_cpu(lo); ror56(hi, lo, 11); + ctx->sched[0xd] = be32_to_cpu(lo); ror56(hi, lo, 11); + ctx->sched[0xe] = be32_to_cpu(lo); ror56(hi, lo, 11); + ctx->sched[0xf] = be32_to_cpu(lo); return 0; #endif } diff --git a/trunk/drivers/ata/ahci.c b/trunk/drivers/ata/ahci.c index 4688dbf2d111..ed9b407e42d4 100644 --- a/trunk/drivers/ata/ahci.c +++ b/trunk/drivers/ata/ahci.c @@ -536,10 +536,6 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci }, /* MCP77 */ { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci }, /* MCP77 */ { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci }, /* MCP77 */ - { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci }, /* MCP79 */ - { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci }, /* MCP79 */ - { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci }, /* MCP79 */ - { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci }, /* MCP79 */ { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci }, /* MCP79 */ { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci }, /* MCP79 */ { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci }, /* MCP79 */ diff --git a/trunk/drivers/ata/pata_amd.c b/trunk/drivers/ata/pata_amd.c index 3cc27b514654..c5779ad4abca 100644 --- a/trunk/drivers/ata/pata_amd.c +++ b/trunk/drivers/ata/pata_amd.c @@ -25,7 +25,7 @@ #include #define DRV_NAME "pata_amd" -#define DRV_VERSION "0.3.10" +#define DRV_VERSION "0.3.9" /** * timing_setup - shared timing computation and load @@ -115,8 +115,7 @@ static void timing_setup(struct ata_port *ap, struct ata_device *adev, int offse } /* UDMA timing */ - if (at.udma) - pci_write_config_byte(pdev, offset + 0x10 + (3 - dn), t); + pci_write_config_byte(pdev, offset + 0x10 + (3 - dn), t); } /** diff --git a/trunk/drivers/ata/pata_via.c b/trunk/drivers/ata/pata_via.c index 453d72bf2598..a4175fbdd170 100644 --- a/trunk/drivers/ata/pata_via.c +++ b/trunk/drivers/ata/pata_via.c @@ -63,7 +63,7 @@ #include #define DRV_NAME "pata_via" -#define DRV_VERSION "0.3.3" +#define DRV_VERSION "0.3.2" /* * The following comes directly from Vojtech Pavlik's ide/pci/via82cxxx @@ -296,7 +296,7 @@ static void via_do_set_mode(struct ata_port *ap, struct ata_device *adev, int mo } /* Set UDMA unless device is not UDMA capable */ - if (udma_type && t.udma) { + if (udma_type) { u8 cable80_status; /* Get 80-wire cable detection bit */ diff --git a/trunk/drivers/ata/sata_mv.c b/trunk/drivers/ata/sata_mv.c index fe0105d35bae..8d864e5e97ed 100644 --- a/trunk/drivers/ata/sata_mv.c +++ b/trunk/drivers/ata/sata_mv.c @@ -2503,15 +2503,6 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) case chip_7042: hp_flags |= MV_HP_PCIE; - if (pdev->vendor == PCI_VENDOR_ID_TTI && - (pdev->device == 0x2300 || pdev->device == 0x2310)) - { - printk(KERN_WARNING "sata_mv: Highpoint RocketRAID BIOS" - " will CORRUPT DATA on attached drives when" - " configured as \"Legacy\". BEWARE!\n"); - printk(KERN_WARNING "sata_mv: Use BIOS \"JBOD\" volumes" - " instead for safety.\n"); - } case chip_6042: hpriv->ops = &mv6xxx_ops; hp_flags |= MV_HP_GEN_IIE; diff --git a/trunk/drivers/ata/sata_nv.c b/trunk/drivers/ata/sata_nv.c index ed5dc7cb50cd..44f9e5d9e362 100644 --- a/trunk/drivers/ata/sata_nv.c +++ b/trunk/drivers/ata/sata_nv.c @@ -791,13 +791,11 @@ static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc) static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf) { - /* Other than when internal or pass-through commands are executed, - the only time this function will be called in ADMA mode will be - if a command fails. In the failure case we don't care about going - into register mode with ADMA commands pending, as the commands will - all shortly be aborted anyway. We assume that NCQ commands are not - issued via passthrough, which is the only way that switching into - ADMA mode could abort outstanding commands. */ + /* Since commands where a result TF is requested are not + executed in ADMA mode, the only time this function will be called + in ADMA mode will be if a command fails. In this case we + don't care about going into register mode with ADMA commands + pending, as the commands will all shortly be aborted anyway. */ nv_adma_register_mode(ap); ata_tf_read(ap, tf); @@ -1361,9 +1359,11 @@ static int nv_adma_use_reg_mode(struct ata_queued_cmd *qc) struct nv_adma_port_priv *pp = qc->ap->private_data; /* ADMA engine can only be used for non-ATAPI DMA commands, - or interrupt-driven no-data commands. */ + or interrupt-driven no-data commands, where a result taskfile + is not required. */ if ((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) || - (qc->tf.flags & ATA_TFLAG_POLLING)) + (qc->tf.flags & ATA_TFLAG_POLLING) || + (qc->flags & ATA_QCFLAG_RESULT_TF)) return 1; if ((qc->flags & ATA_QCFLAG_DMAMAP) || @@ -1381,8 +1381,6 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc) NV_CPB_CTL_IEN; if (nv_adma_use_reg_mode(qc)) { - BUG_ON(!(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) && - (qc->flags & ATA_QCFLAG_DMAMAP)); nv_adma_register_mode(qc->ap); ata_qc_prep(qc); return; @@ -1427,21 +1425,9 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc) VPRINTK("ENTER\n"); - /* We can't handle result taskfile with NCQ commands, since - retrieving the taskfile switches us out of ADMA mode and would abort - existing commands. */ - if (unlikely(qc->tf.protocol == ATA_PROT_NCQ && - (qc->flags & ATA_QCFLAG_RESULT_TF))) { - ata_dev_printk(qc->dev, KERN_ERR, - "NCQ w/ RESULT_TF not allowed\n"); - return AC_ERR_SYSTEM; - } - if (nv_adma_use_reg_mode(qc)) { /* use ATA register mode */ VPRINTK("using ATA register mode: 0x%lx\n", qc->flags); - BUG_ON(!(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) && - (qc->flags & ATA_QCFLAG_DMAMAP)); nv_adma_register_mode(qc->ap); return ata_qc_issue_prot(qc); } else diff --git a/trunk/drivers/char/cs5535_gpio.c b/trunk/drivers/char/cs5535_gpio.c index c2d23cae9515..fe6d2407baed 100644 --- a/trunk/drivers/char/cs5535_gpio.c +++ b/trunk/drivers/char/cs5535_gpio.c @@ -104,11 +104,6 @@ static ssize_t cs5535_gpio_write(struct file *file, const char __user *data, for (j = 0; j < ARRAY_SIZE(rm); j++) { if (c == rm[j].on) { outl(m1, base + rm[j].wr_offset); - /* If enabling output, turn off AUX 1 and AUX 2 */ - if (c == 'O') { - outl(m0, base + 0x10); - outl(m0, base + 0x14); - } break; } else if (c == rm[j].off) { outl(m0, base + rm[j].wr_offset); diff --git a/trunk/drivers/hwmon/coretemp.c b/trunk/drivers/hwmon/coretemp.c index 5c82ec7f8bbd..3ee60d26e3a2 100644 --- a/trunk/drivers/hwmon/coretemp.c +++ b/trunk/drivers/hwmon/coretemp.c @@ -337,11 +337,10 @@ static int coretemp_cpu_callback(struct notifier_block *nfb, switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: + case CPU_DOWN_FAILED: coretemp_device_add(cpu); break; - case CPU_DEAD: - case CPU_DEAD_FROZEN: + case CPU_DOWN_PREPARE: coretemp_device_remove(cpu); break; } diff --git a/trunk/drivers/input/touchscreen/ads7846.c b/trunk/drivers/input/touchscreen/ads7846.c index fd9c5d51870a..f59aecf5ec15 100644 --- a/trunk/drivers/input/touchscreen/ads7846.c +++ b/trunk/drivers/input/touchscreen/ads7846.c @@ -267,12 +267,13 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) ts->irq_disabled = 0; enable_irq(spi->irq); - if (status == 0) { - /* on-wire is a must-ignore bit, a BE12 value, then padding */ - sample = be16_to_cpu(req->sample); - sample = sample >> 3; - sample &= 0x0fff; - } + if (req->msg.status) + status = req->msg.status; + + /* on-wire is a must-ignore bit, a BE12 value, then padding */ + sample = be16_to_cpu(req->sample); + sample = sample >> 3; + sample &= 0x0fff; kfree(req); return status ? status : sample; diff --git a/trunk/drivers/mmc/host/mmc_spi.c b/trunk/drivers/mmc/host/mmc_spi.c index 365024b83d3d..a6469218f194 100644 --- a/trunk/drivers/mmc/host/mmc_spi.c +++ b/trunk/drivers/mmc/host/mmc_spi.c @@ -176,6 +176,8 @@ mmc_spi_readbytes(struct mmc_spi_host *host, unsigned len) DMA_FROM_DEVICE); status = spi_sync(host->spi, &host->readback); + if (status == 0) + status = host->readback.status; if (host->dma_dev) dma_sync_single_for_cpu(host->dma_dev, @@ -478,6 +480,8 @@ mmc_spi_command_send(struct mmc_spi_host *host, DMA_BIDIRECTIONAL); } status = spi_sync(host->spi, &host->m); + if (status == 0) + status = host->m.status; if (host->dma_dev) dma_sync_single_for_cpu(host->dma_dev, @@ -620,6 +624,8 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t) DMA_BIDIRECTIONAL); status = spi_sync(spi, &host->m); + if (status == 0) + status = host->m.status; if (status != 0) { dev_dbg(&spi->dev, "write error (%d)\n", status); @@ -720,6 +726,8 @@ mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t) } status = spi_sync(spi, &host->m); + if (status == 0) + status = host->m.status; if (host->dma_dev) { dma_sync_single_for_cpu(host->dma_dev, @@ -897,6 +905,8 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, DMA_BIDIRECTIONAL); tmp = spi_sync(spi, &host->m); + if (tmp == 0) + tmp = host->m.status; if (host->dma_dev) dma_sync_single_for_cpu(host->dma_dev, diff --git a/trunk/drivers/net/chelsio/cxgb2.c b/trunk/drivers/net/chelsio/cxgb2.c old mode 100644 new mode 100755 diff --git a/trunk/drivers/net/chelsio/pm3393.c b/trunk/drivers/net/chelsio/pm3393.c old mode 100644 new mode 100755 diff --git a/trunk/drivers/net/chelsio/sge.c b/trunk/drivers/net/chelsio/sge.c old mode 100644 new mode 100755 diff --git a/trunk/drivers/net/chelsio/sge.h b/trunk/drivers/net/chelsio/sge.h old mode 100644 new mode 100755 diff --git a/trunk/drivers/net/fec_mpc52xx.c b/trunk/drivers/net/fec_mpc52xx.c index 79f7eade4773..bf5a7caa5b52 100644 --- a/trunk/drivers/net/fec_mpc52xx.c +++ b/trunk/drivers/net/fec_mpc52xx.c @@ -422,7 +422,7 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id) rskb = bcom_retrieve_buffer(priv->rx_dmatsk, &status, (struct bcom_bd **)&bd); - dma_unmap_single(&dev->dev, bd->skb_pa, rskb->len, DMA_FROM_DEVICE); + dma_unmap_single(&dev->dev, bd->skb_pa, skb->len, DMA_FROM_DEVICE); /* Test for errors in received frame */ if (status & BCOM_FEC_RX_BD_ERRORS) { @@ -467,7 +467,7 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id) bcom_prepare_next_buffer(priv->rx_dmatsk); bd->status = FEC_RX_BUFFER_SIZE; - bd->skb_pa = dma_map_single(&dev->dev, skb->data, + bd->skb_pa = dma_map_single(&dev->dev, rskb->data, FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE); bcom_submit_next_buffer(priv->rx_dmatsk, skb); diff --git a/trunk/drivers/net/gianfar.c b/trunk/drivers/net/gianfar.c index 0431e9ed0fac..38268d7335a8 100644 --- a/trunk/drivers/net/gianfar.c +++ b/trunk/drivers/net/gianfar.c @@ -696,7 +696,7 @@ int startup_gfar(struct net_device *dev) { struct txbd8 *txbdp; struct rxbd8 *rxbdp; - dma_addr_t addr = 0; + dma_addr_t addr; unsigned long vaddr; int i; struct gfar_private *priv = netdev_priv(dev); diff --git a/trunk/drivers/net/myri10ge/myri10ge.c b/trunk/drivers/net/myri10ge/myri10ge.c index 8def8657251f..0f306ddb5630 100644 --- a/trunk/drivers/net/myri10ge/myri10ge.c +++ b/trunk/drivers/net/myri10ge/myri10ge.c @@ -1979,7 +1979,6 @@ static int myri10ge_open(struct net_device *dev) lro_mgr->lro_arr = mgp->rx_done.lro_desc; lro_mgr->get_frag_header = myri10ge_get_frag_header; lro_mgr->max_aggr = myri10ge_lro_max_pkts; - lro_mgr->frag_align_pad = 2; if (lro_mgr->max_aggr > MAX_SKB_FRAGS) lro_mgr->max_aggr = MAX_SKB_FRAGS; diff --git a/trunk/drivers/net/pasemi_mac.c b/trunk/drivers/net/pasemi_mac.c index 816a59e801b2..09b4fde8d924 100644 --- a/trunk/drivers/net/pasemi_mac.c +++ b/trunk/drivers/net/pasemi_mac.c @@ -586,7 +586,7 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit) /* CRC error flagged */ mac->netdev->stats.rx_errors++; mac->netdev->stats.rx_crc_errors++; - /* No need to free skb, it'll be reused */ + dev_kfree_skb_irq(skb); goto next; } @@ -1362,7 +1362,7 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netif_napi_add(dev, &mac->napi, pasemi_mac_poll, 64); - dev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX | NETIF_F_SG; + dev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX | NETIF_F_SG; /* These should come out of the device tree eventually */ mac->dma_txch = index; diff --git a/trunk/drivers/net/phy/mdio_bus.c b/trunk/drivers/net/phy/mdio_bus.c index c30196d0ad16..fc2f0e695a13 100644 --- a/trunk/drivers/net/phy/mdio_bus.c +++ b/trunk/drivers/net/phy/mdio_bus.c @@ -91,12 +91,9 @@ int mdiobus_register(struct mii_bus *bus) err = device_register(&phydev->dev); - if (err) { + if (err) printk(KERN_ERR "phy %d failed to register\n", i); - phy_device_free(phydev); - phydev = NULL; - } } bus->phy_map[i] = phydev; @@ -113,8 +110,10 @@ void mdiobus_unregister(struct mii_bus *bus) int i; for (i = 0; i < PHY_MAX_ADDR; i++) { - if (bus->phy_map[i]) + if (bus->phy_map[i]) { device_unregister(&bus->phy_map[i]->dev); + kfree(bus->phy_map[i]); + } } } EXPORT_SYMBOL(mdiobus_unregister); diff --git a/trunk/drivers/net/phy/phy_device.c b/trunk/drivers/net/phy/phy_device.c index 5b9e1751e1b4..f6e484812a98 100644 --- a/trunk/drivers/net/phy/phy_device.c +++ b/trunk/drivers/net/phy/phy_device.c @@ -44,16 +44,6 @@ static struct phy_driver genphy_driver; extern int mdio_bus_init(void); extern void mdio_bus_exit(void); -void phy_device_free(struct phy_device *phydev) -{ - kfree(phydev); -} - -static void phy_device_release(struct device *dev) -{ - phy_device_free(to_phy_device(dev)); -} - struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id) { struct phy_device *dev; @@ -64,8 +54,6 @@ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id) if (NULL == dev) return (struct phy_device*) PTR_ERR((void*)-ENOMEM); - dev->dev.release = phy_device_release; - dev->speed = 0; dev->duplex = -1; dev->pause = dev->asym_pause = 0; diff --git a/trunk/drivers/net/sky2.c b/trunk/drivers/net/sky2.c index 6197afb3ed83..3d1dfc948405 100644 --- a/trunk/drivers/net/sky2.c +++ b/trunk/drivers/net/sky2.c @@ -2906,14 +2906,16 @@ static void sky2_restart(struct work_struct *work) int i, err; rtnl_lock(); + sky2_write32(hw, B0_IMSK, 0); + sky2_read32(hw, B0_IMSK); + napi_disable(&hw->napi); + for (i = 0; i < hw->ports; i++) { dev = hw->dev[i]; if (netif_running(dev)) sky2_down(dev); } - napi_disable(&hw->napi); - sky2_write32(hw, B0_IMSK, 0); sky2_reset(hw); sky2_write32(hw, B0_IMSK, Y2_IS_BASE); napi_enable(&hw->napi); diff --git a/trunk/drivers/net/smc911x.c b/trunk/drivers/net/smc911x.c index 76cc1d3adf71..1a3d80bfe9ea 100644 --- a/trunk/drivers/net/smc911x.c +++ b/trunk/drivers/net/smc911x.c @@ -1299,9 +1299,9 @@ smc911x_rx_dma_irq(int dma, void *data) PRINT_PKT(skb->data, skb->len); dev->last_rx = jiffies; skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); dev->stats.rx_packets++; dev->stats.rx_bytes += skb->len; - netif_rx(skb); spin_lock_irqsave(&lp->lock, flags); pkts = (SMC_GET_RX_FIFO_INF() & RX_FIFO_INF_RXSUSED_) >> 16; diff --git a/trunk/drivers/parisc/lba_pci.c b/trunk/drivers/parisc/lba_pci.c index 66ce61048361..5eace9e66e14 100644 --- a/trunk/drivers/parisc/lba_pci.c +++ b/trunk/drivers/parisc/lba_pci.c @@ -768,13 +768,9 @@ lba_fixup_bus(struct pci_bus *bus) DBG("lba_fixup_bus() WTF? 0x%lx [%lx/%lx] XXX", res->flags, res->start, res->end); } - - /* - ** FIXME: this will result in whinging for devices - ** that share expansion ROMs (think quad tulip), but - ** isn't harmful. - */ - pci_claim_resource(dev, i); + if ((i != PCI_ROM_RESOURCE) || + (res->flags & IORESOURCE_ROM_ENABLE)) + pci_claim_resource(dev, i); } #ifdef FBB_SUPPORT diff --git a/trunk/drivers/rtc/interface.c b/trunk/drivers/rtc/interface.c index f1e00ff54ce8..a4f56e95cf96 100644 --- a/trunk/drivers/rtc/interface.c +++ b/trunk/drivers/rtc/interface.c @@ -293,7 +293,7 @@ int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task) return -EINVAL; /* Cannot register while the char dev is in use */ - if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags)) + if (test_and_set_bit(RTC_DEV_BUSY, &rtc->flags)) return -EBUSY; spin_lock_irq(&rtc->irq_task_lock); @@ -303,7 +303,7 @@ int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task) } spin_unlock_irq(&rtc->irq_task_lock); - clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags); + clear_bit(RTC_DEV_BUSY, &rtc->flags); return retval; } diff --git a/trunk/drivers/rtc/rtc-dev.c b/trunk/drivers/rtc/rtc-dev.c index 025c60a17a4a..ae1bf177d625 100644 --- a/trunk/drivers/rtc/rtc-dev.c +++ b/trunk/drivers/rtc/rtc-dev.c @@ -26,7 +26,7 @@ static int rtc_dev_open(struct inode *inode, struct file *file) struct rtc_device, char_dev); const struct rtc_class_ops *ops = rtc->ops; - if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags)) + if (test_and_set_bit(RTC_DEV_BUSY, &rtc->flags)) return -EBUSY; file->private_data = rtc; @@ -41,7 +41,7 @@ static int rtc_dev_open(struct inode *inode, struct file *file) } /* something has gone wrong */ - clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags); + clear_bit(RTC_DEV_BUSY, &rtc->flags); return err; } @@ -402,7 +402,7 @@ static int rtc_dev_release(struct inode *inode, struct file *file) if (rtc->ops->release) rtc->ops->release(rtc->dev.parent); - clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags); + clear_bit(RTC_DEV_BUSY, &rtc->flags); return 0; } diff --git a/trunk/drivers/rtc/rtc-max6902.c b/trunk/drivers/rtc/rtc-max6902.c index 1f956dc5d56e..3e183cfee10f 100644 --- a/trunk/drivers/rtc/rtc-max6902.c +++ b/trunk/drivers/rtc/rtc-max6902.c @@ -89,9 +89,13 @@ static int max6902_get_reg(struct device *dev, unsigned char address, /* do the i/o */ status = spi_sync(spi, &message); - if (status == 0) - *data = chip->rx_buf[1]; + status = message.status; + else + return status; + + *data = chip->rx_buf[1]; + return status; } @@ -121,7 +125,9 @@ static int max6902_get_datetime(struct device *dev, struct rtc_time *dt) /* do the i/o */ status = spi_sync(spi, &message); - if (status) + if (status == 0) + status = message.status; + else return status; /* The chip sends data in this order: diff --git a/trunk/drivers/s390/block/dcssblk.c b/trunk/drivers/s390/block/dcssblk.c index 15a5789b7734..5e083d1f57e7 100644 --- a/trunk/drivers/s390/block/dcssblk.c +++ b/trunk/drivers/s390/block/dcssblk.c @@ -472,11 +472,11 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char if (rc) goto unregister_dev; + add_disk(dev_info->gd); + blk_queue_make_request(dev_info->dcssblk_queue, dcssblk_make_request); blk_queue_hardsect_size(dev_info->dcssblk_queue, 4096); - add_disk(dev_info->gd); - switch (dev_info->segment_type) { case SEG_TYPE_SR: case SEG_TYPE_ER: diff --git a/trunk/drivers/s390/cio/css.c b/trunk/drivers/s390/cio/css.c index c3df2cd009a4..6db31089d2d7 100644 --- a/trunk/drivers/s390/cio/css.c +++ b/trunk/drivers/s390/cio/css.c @@ -451,7 +451,6 @@ static int reprobe_subchannel(struct subchannel_id schid, void *data) break; case -ENXIO: case -ENOMEM: - case -EIO: /* These should abort looping */ break; default: diff --git a/trunk/drivers/s390/cio/device_id.c b/trunk/drivers/s390/cio/device_id.c index 156f3f9786b5..2f6bf462425e 100644 --- a/trunk/drivers/s390/cio/device_id.c +++ b/trunk/drivers/s390/cio/device_id.c @@ -113,7 +113,6 @@ __ccw_device_sense_id_start(struct ccw_device *cdev) { struct subchannel *sch; struct ccw1 *ccw; - int ret; sch = to_subchannel(cdev->dev.parent); /* Setup sense channel program. */ @@ -125,25 +124,9 @@ __ccw_device_sense_id_start(struct ccw_device *cdev) /* Reset device status. */ memset(&cdev->private->irb, 0, sizeof(struct irb)); + cdev->private->flags.intretry = 0; - /* Try on every path. */ - ret = -ENODEV; - while (cdev->private->imask != 0) { - if ((sch->opm & cdev->private->imask) != 0 && - cdev->private->iretry > 0) { - cdev->private->iretry--; - /* Reset internal retry indication. */ - cdev->private->flags.intretry = 0; - ret = cio_start (sch, cdev->private->iccws, - cdev->private->imask); - /* ret is 0, -EBUSY, -EACCES or -ENODEV */ - if (ret != -EACCES) - return ret; - } - cdev->private->imask >>= 1; - cdev->private->iretry = 5; - } - return ret; + return cio_start(sch, ccw, LPM_ANYPATH); } void @@ -153,8 +136,7 @@ ccw_device_sense_id_start(struct ccw_device *cdev) memset (&cdev->private->senseid, 0, sizeof (struct senseid)); cdev->private->senseid.cu_type = 0xFFFF; - cdev->private->imask = 0x80; - cdev->private->iretry = 5; + cdev->private->iretry = 3; ret = __ccw_device_sense_id_start(cdev); if (ret && ret != -EBUSY) ccw_device_sense_id_done(cdev, ret); @@ -270,14 +252,13 @@ ccw_device_sense_id_irq(struct ccw_device *cdev, enum dev_event dev_event) ccw_device_sense_id_done(cdev, ret); break; case -EACCES: /* channel is not operational. */ - sch->lpm &= ~cdev->private->imask; - cdev->private->imask >>= 1; - cdev->private->iretry = 5; - /* fall through. */ case -EAGAIN: /* try again. */ - ret = __ccw_device_sense_id_start(cdev); - if (ret == 0 || ret == -EBUSY) - break; + cdev->private->iretry--; + if (cdev->private->iretry > 0) { + ret = __ccw_device_sense_id_start(cdev); + if (ret == 0 || ret == -EBUSY) + break; + } /* fall through. */ default: /* Sense ID failed. Try asking VM. */ if (MACHINE_IS_VM) { diff --git a/trunk/drivers/s390/net/ctcmain.c b/trunk/drivers/s390/net/ctcmain.c index 97adc701a819..b3b6f654365c 100644 --- a/trunk/drivers/s390/net/ctcmain.c +++ b/trunk/drivers/s390/net/ctcmain.c @@ -2802,6 +2802,7 @@ void ctc_init_netdevice(struct net_device * dev) dev->type = ARPHRD_SLIP; dev->tx_queue_len = 100; dev->flags = IFF_POINTOPOINT | IFF_NOARP; + SET_MODULE_OWNER(dev); } diff --git a/trunk/drivers/spi/at25.c b/trunk/drivers/spi/at25.c index 290dbe99647a..e007833cca59 100644 --- a/trunk/drivers/spi/at25.c +++ b/trunk/drivers/spi/at25.c @@ -21,13 +21,6 @@ #include -/* - * NOTE: this is an *EEPROM* driver. The vagaries of product naming - * mean that some AT25 products are EEPROMs, and others are FLASH. - * Handle FLASH chips with the drivers/mtd/devices/m25p80.c driver, - * not this one! - */ - struct at25_data { struct spi_device *spi; struct mutex lock; diff --git a/trunk/drivers/spi/spi.c b/trunk/drivers/spi/spi.c index 93e9de46977a..b31f4431849b 100644 --- a/trunk/drivers/spi/spi.c +++ b/trunk/drivers/spi/spi.c @@ -541,7 +541,10 @@ static void spi_complete(void *arg) * Also, the caller is guaranteeing that the memory associated with the * message will not be freed before this call returns. * - * It returns zero on success, else a negative error code. + * The return value is a negative error code if the message could not be + * submitted, else zero. When the value is zero, then message->status is + * also defined; it's the completion code for the transfer, either zero + * or a negative error code from the controller driver. */ int spi_sync(struct spi_device *spi, struct spi_message *message) { @@ -551,10 +554,8 @@ int spi_sync(struct spi_device *spi, struct spi_message *message) message->complete = spi_complete; message->context = &done; status = spi_async(spi, message); - if (status == 0) { + if (status == 0) wait_for_completion(&done); - status = message->status; - } message->context = NULL; return status; } @@ -588,7 +589,7 @@ int spi_write_then_read(struct spi_device *spi, const u8 *txbuf, unsigned n_tx, u8 *rxbuf, unsigned n_rx) { - static DEFINE_MUTEX(lock); + static DECLARE_MUTEX(lock); int status; struct spi_message message; @@ -614,7 +615,7 @@ int spi_write_then_read(struct spi_device *spi, } /* ... unless someone else is using the pre-allocated buffer */ - if (!mutex_trylock(&lock)) { + if (down_trylock(&lock)) { local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL); if (!local_buf) return -ENOMEM; @@ -627,11 +628,13 @@ int spi_write_then_read(struct spi_device *spi, /* do the i/o */ status = spi_sync(spi, &message); - if (status == 0) + if (status == 0) { memcpy(rxbuf, x[1].rx_buf, n_rx); + status = message.status; + } if (x[0].tx_buf == buf) - mutex_unlock(&lock); + up(&lock); else kfree(local_buf); diff --git a/trunk/drivers/spi/spi_bfin5xx.c b/trunk/drivers/spi/spi_bfin5xx.c index 22697b812205..2ef11bb70b2e 100644 --- a/trunk/drivers/spi/spi_bfin5xx.c +++ b/trunk/drivers/spi/spi_bfin5xx.c @@ -1,22 +1,17 @@ /* - * File: drivers/spi/bfin5xx_spi.c - * Maintainer: - * Bryan Wu - * Original Author: - * Luke Yang (Analog Devices Inc.) + * File: drivers/spi/bfin5xx_spi.c + * Based on: N/A + * Author: Luke Yang (Analog Devices Inc.) * - * Created: March. 10th 2006 - * Description: SPI controller driver for Blackfin BF5xx - * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * Created: March. 10th 2006 + * Description: SPI controller driver for Blackfin 5xx + * Bugs: Enter bugs at http://blackfin.uclinux.org/ * * Modified: * March 10, 2006 bfin5xx_spi.c Created. (Luke Yang) * August 7, 2006 added full duplex mode (Axel Weiss & Luke Yang) - * July 17, 2007 add support for BF54x SPI0 controller (Bryan Wu) - * July 30, 2007 add platfrom_resource interface to support multi-port - * SPI controller (Bryan Wu) * - * Copyright 2004-2007 Analog Devices Inc. + * Copyright 2004-2006 Analog Devices Inc. * * This program is free software ; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,39 +31,50 @@ #include #include -#include #include -#include #include -#include #include #include #include #include #include #include +#include +#include +#include +#include #include -#include -#include -#define DRV_NAME "bfin-spi" -#define DRV_AUTHOR "Bryan Wu, Luke Yang" -#define DRV_DESC "Blackfin BF5xx on-chip SPI Contoller Driver" -#define DRV_VERSION "1.0" +#include -MODULE_AUTHOR(DRV_AUTHOR); -MODULE_DESCRIPTION(DRV_DESC); +MODULE_AUTHOR("Luke Yang"); +MODULE_DESCRIPTION("Blackfin 5xx SPI Contoller"); MODULE_LICENSE("GPL"); -#define IS_DMA_ALIGNED(x) (((u32)(x)&0x07) == 0) +#define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0) + +#define DEFINE_SPI_REG(reg, off) \ +static inline u16 read_##reg(void) \ + { return *(volatile unsigned short*)(SPI0_REGBASE + off); } \ +static inline void write_##reg(u16 v) \ + {*(volatile unsigned short*)(SPI0_REGBASE + off) = v;\ + SSYNC();} -#define START_STATE ((void *)0) -#define RUNNING_STATE ((void *)1) -#define DONE_STATE ((void *)2) -#define ERROR_STATE ((void *)-1) -#define QUEUE_RUNNING 0 -#define QUEUE_STOPPED 1 +DEFINE_SPI_REG(CTRL, 0x00) +DEFINE_SPI_REG(FLAG, 0x04) +DEFINE_SPI_REG(STAT, 0x08) +DEFINE_SPI_REG(TDBR, 0x0C) +DEFINE_SPI_REG(RDBR, 0x10) +DEFINE_SPI_REG(BAUD, 0x14) +DEFINE_SPI_REG(SHAW, 0x18) +#define START_STATE ((void*)0) +#define RUNNING_STATE ((void*)1) +#define DONE_STATE ((void*)2) +#define ERROR_STATE ((void*)-1) +#define QUEUE_RUNNING 0 +#define QUEUE_STOPPED 1 +int dma_requested; struct driver_data { /* Driver model hookup */ @@ -77,12 +83,6 @@ struct driver_data { /* SPI framework hookup */ struct spi_master *master; - /* Regs base of SPI controller */ - void __iomem *regs_base; - - /* Pin request list */ - u16 *pin_req; - /* BFIN hookup */ struct bfin5xx_spi_master *master_info; @@ -107,18 +107,12 @@ struct driver_data { void *tx_end; void *rx; void *rx_end; - - /* DMA stuffs */ - int dma_channel; int dma_mapped; - int dma_requested; dma_addr_t rx_dma; dma_addr_t tx_dma; - size_t rx_map_len; size_t tx_map_len; u8 n_bytes; - int cs_change; void (*write) (struct driver_data *); void (*read) (struct driver_data *); void (*duplex) (struct driver_data *); @@ -135,40 +129,28 @@ struct chip_data { u8 enable_dma; u8 bits_per_word; /* 8 or 16 */ u8 cs_change_per_word; - u16 cs_chg_udelay; /* Some devices require > 255usec delay */ + u8 cs_chg_udelay; void (*write) (struct driver_data *); void (*read) (struct driver_data *); void (*duplex) (struct driver_data *); }; -#define DEFINE_SPI_REG(reg, off) \ -static inline u16 read_##reg(struct driver_data *drv_data) \ - { return bfin_read16(drv_data->regs_base + off); } \ -static inline void write_##reg(struct driver_data *drv_data, u16 v) \ - { bfin_write16(drv_data->regs_base + off, v); } - -DEFINE_SPI_REG(CTRL, 0x00) -DEFINE_SPI_REG(FLAG, 0x04) -DEFINE_SPI_REG(STAT, 0x08) -DEFINE_SPI_REG(TDBR, 0x0C) -DEFINE_SPI_REG(RDBR, 0x10) -DEFINE_SPI_REG(BAUD, 0x14) -DEFINE_SPI_REG(SHAW, 0x18) - static void bfin_spi_enable(struct driver_data *drv_data) { u16 cr; - cr = read_CTRL(drv_data); - write_CTRL(drv_data, (cr | BIT_CTL_ENABLE)); + cr = read_CTRL(); + write_CTRL(cr | BIT_CTL_ENABLE); + SSYNC(); } static void bfin_spi_disable(struct driver_data *drv_data) { u16 cr; - cr = read_CTRL(drv_data); - write_CTRL(drv_data, (cr & (~BIT_CTL_ENABLE))); + cr = read_CTRL(); + write_CTRL(cr & (~BIT_CTL_ENABLE)); + SSYNC(); } /* Caculate the SPI_BAUD register value based on input HZ */ @@ -188,71 +170,83 @@ static int flush(struct driver_data *drv_data) unsigned long limit = loops_per_jiffy << 1; /* wait for stop and clear stat */ - while (!(read_STAT(drv_data) & BIT_STAT_SPIF) && limit--) - cpu_relax(); + while (!(read_STAT() & BIT_STAT_SPIF) && limit--) + continue; - write_STAT(drv_data, BIT_STAT_CLR); + write_STAT(BIT_STAT_CLR); return limit; } -/* Chip select operation functions for cs_change flag */ -static void cs_active(struct driver_data *drv_data, struct chip_data *chip) -{ - u16 flag = read_FLAG(drv_data); - - flag |= chip->flag; - flag &= ~(chip->flag << 8); - - write_FLAG(drv_data, flag); -} - -static void cs_deactive(struct driver_data *drv_data, struct chip_data *chip) -{ - u16 flag = read_FLAG(drv_data); - - flag |= (chip->flag << 8); - - write_FLAG(drv_data, flag); - - /* Move delay here for consistency */ - if (chip->cs_chg_udelay) - udelay(chip->cs_chg_udelay); -} - -#define MAX_SPI_SSEL 7 - /* stop controller and re-config current chip*/ -static int restore_state(struct driver_data *drv_data) +static void restore_state(struct driver_data *drv_data) { struct chip_data *chip = drv_data->cur_chip; - int ret = 0; /* Clear status and disable clock */ - write_STAT(drv_data, BIT_STAT_CLR); + write_STAT(BIT_STAT_CLR); bfin_spi_disable(drv_data); dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n"); - /* Load the registers */ - write_CTRL(drv_data, chip->ctl_reg); - write_BAUD(drv_data, chip->baud); +#if defined(CONFIG_BF534) || defined(CONFIG_BF536) || defined(CONFIG_BF537) + dev_dbg(&drv_data->pdev->dev, + "chip select number is %d\n", chip->chip_select_num); + + switch (chip->chip_select_num) { + case 1: + bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3c00); + SSYNC(); + break; - bfin_spi_enable(drv_data); - cs_active(drv_data, chip); + case 2: + case 3: + bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PJSE_SPI); + SSYNC(); + bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3800); + SSYNC(); + break; - if (ret) - dev_dbg(&drv_data->pdev->dev, - ": request chip select number %d failed\n", - chip->chip_select_num); + case 4: + bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PFS4E_SPI); + SSYNC(); + bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3840); + SSYNC(); + break; + + case 5: + bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PFS5E_SPI); + SSYNC(); + bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3820); + SSYNC(); + break; - return ret; + case 6: + bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PFS6E_SPI); + SSYNC(); + bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3810); + SSYNC(); + break; + + case 7: + bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PJCE_SPI); + SSYNC(); + bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3800); + SSYNC(); + break; + } +#endif + + /* Load the registers */ + write_CTRL(chip->ctl_reg); + write_BAUD(chip->baud); + write_FLAG(chip->flag); } /* used to kick off transfer in rx mode */ -static unsigned short dummy_read(struct driver_data *drv_data) +static unsigned short dummy_read(void) { unsigned short tmp; - tmp = read_RDBR(drv_data); + tmp = read_RDBR(); return tmp; } @@ -261,9 +255,9 @@ static void null_writer(struct driver_data *drv_data) u8 n_bytes = drv_data->n_bytes; while (drv_data->tx < drv_data->tx_end) { - write_TDBR(drv_data, 0); - while ((read_STAT(drv_data) & BIT_STAT_TXS)) - cpu_relax(); + write_TDBR(0); + while ((read_STAT() & BIT_STAT_TXS)) + continue; drv_data->tx += n_bytes; } } @@ -271,78 +265,75 @@ static void null_writer(struct driver_data *drv_data) static void null_reader(struct driver_data *drv_data) { u8 n_bytes = drv_data->n_bytes; - dummy_read(drv_data); + dummy_read(); while (drv_data->rx < drv_data->rx_end) { - while (!(read_STAT(drv_data) & BIT_STAT_RXS)) - cpu_relax(); - dummy_read(drv_data); + while (!(read_STAT() & BIT_STAT_RXS)) + continue; + dummy_read(); drv_data->rx += n_bytes; } } static void u8_writer(struct driver_data *drv_data) { - dev_dbg(&drv_data->pdev->dev, - "cr8-s is 0x%x\n", read_STAT(drv_data)); - - /* poll for SPI completion before start */ - while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) - cpu_relax(); - + dev_dbg(&drv_data->pdev->dev, + "cr8-s is 0x%x\n", read_STAT()); while (drv_data->tx < drv_data->tx_end) { - write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); - while (read_STAT(drv_data) & BIT_STAT_TXS) - cpu_relax(); + write_TDBR(*(u8 *) (drv_data->tx)); + while (read_STAT() & BIT_STAT_TXS) + continue; ++drv_data->tx; } + + /* poll for SPI completion before returning */ + while (!(read_STAT() & BIT_STAT_SPIF)) + continue; } static void u8_cs_chg_writer(struct driver_data *drv_data) { struct chip_data *chip = drv_data->cur_chip; - /* poll for SPI completion before start */ - while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) - cpu_relax(); - while (drv_data->tx < drv_data->tx_end) { - cs_active(drv_data, chip); - - write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); - while (read_STAT(drv_data) & BIT_STAT_TXS) - cpu_relax(); - - cs_deactive(drv_data, chip); - + write_FLAG(chip->flag); + SSYNC(); + + write_TDBR(*(u8 *) (drv_data->tx)); + while (read_STAT() & BIT_STAT_TXS) + continue; + while (!(read_STAT() & BIT_STAT_SPIF)) + continue; + write_FLAG(0xFF00 | chip->flag); + SSYNC(); + if (chip->cs_chg_udelay) + udelay(chip->cs_chg_udelay); ++drv_data->tx; } + write_FLAG(0xFF00); + SSYNC(); } static void u8_reader(struct driver_data *drv_data) { - dev_dbg(&drv_data->pdev->dev, - "cr-8 is 0x%x\n", read_STAT(drv_data)); - - /* poll for SPI completion before start */ - while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) - cpu_relax(); + dev_dbg(&drv_data->pdev->dev, + "cr-8 is 0x%x\n", read_STAT()); /* clear TDBR buffer before read(else it will be shifted out) */ - write_TDBR(drv_data, 0xFFFF); + write_TDBR(0xFFFF); - dummy_read(drv_data); + dummy_read(); while (drv_data->rx < drv_data->rx_end - 1) { - while (!(read_STAT(drv_data) & BIT_STAT_RXS)) - cpu_relax(); - *(u8 *) (drv_data->rx) = read_RDBR(drv_data); + while (!(read_STAT() & BIT_STAT_RXS)) + continue; + *(u8 *) (drv_data->rx) = read_RDBR(); ++drv_data->rx; } - while (!(read_STAT(drv_data) & BIT_STAT_RXS)) - cpu_relax(); - *(u8 *) (drv_data->rx) = read_SHAW(drv_data); + while (!(read_STAT() & BIT_STAT_RXS)) + continue; + *(u8 *) (drv_data->rx) = read_SHAW(); ++drv_data->rx; } @@ -350,47 +341,36 @@ static void u8_cs_chg_reader(struct driver_data *drv_data) { struct chip_data *chip = drv_data->cur_chip; - /* poll for SPI completion before start */ - while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) - cpu_relax(); - - /* clear TDBR buffer before read(else it will be shifted out) */ - write_TDBR(drv_data, 0xFFFF); - - cs_active(drv_data, chip); - dummy_read(drv_data); - - while (drv_data->rx < drv_data->rx_end - 1) { - cs_deactive(drv_data, chip); - - while (!(read_STAT(drv_data) & BIT_STAT_RXS)) - cpu_relax(); - cs_active(drv_data, chip); - *(u8 *) (drv_data->rx) = read_RDBR(drv_data); + while (drv_data->rx < drv_data->rx_end) { + write_FLAG(chip->flag); + SSYNC(); + + read_RDBR(); /* kick off */ + while (!(read_STAT() & BIT_STAT_RXS)) + continue; + while (!(read_STAT() & BIT_STAT_SPIF)) + continue; + *(u8 *) (drv_data->rx) = read_SHAW(); + write_FLAG(0xFF00 | chip->flag); + SSYNC(); + if (chip->cs_chg_udelay) + udelay(chip->cs_chg_udelay); ++drv_data->rx; } - cs_deactive(drv_data, chip); - - while (!(read_STAT(drv_data) & BIT_STAT_RXS)) - cpu_relax(); - *(u8 *) (drv_data->rx) = read_SHAW(drv_data); - ++drv_data->rx; + write_FLAG(0xFF00); + SSYNC(); } static void u8_duplex(struct driver_data *drv_data) { - /* poll for SPI completion before start */ - while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) - cpu_relax(); - /* in duplex mode, clk is triggered by writing of TDBR */ while (drv_data->rx < drv_data->rx_end) { - write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); - while (read_STAT(drv_data) & BIT_STAT_TXS) - cpu_relax(); - while (!(read_STAT(drv_data) & BIT_STAT_RXS)) - cpu_relax(); - *(u8 *) (drv_data->rx) = read_RDBR(drv_data); + write_TDBR(*(u8 *) (drv_data->tx)); + while (!(read_STAT() & BIT_STAT_SPIF)) + continue; + while (!(read_STAT() & BIT_STAT_RXS)) + continue; + *(u8 *) (drv_data->rx) = read_RDBR(); ++drv_data->rx; ++drv_data->tx; } @@ -400,89 +380,83 @@ static void u8_cs_chg_duplex(struct driver_data *drv_data) { struct chip_data *chip = drv_data->cur_chip; - /* poll for SPI completion before start */ - while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) - cpu_relax(); - while (drv_data->rx < drv_data->rx_end) { - cs_active(drv_data, chip); - - write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); - while (read_STAT(drv_data) & BIT_STAT_TXS) - cpu_relax(); - while (!(read_STAT(drv_data) & BIT_STAT_RXS)) - cpu_relax(); - *(u8 *) (drv_data->rx) = read_RDBR(drv_data); - - cs_deactive(drv_data, chip); - + write_FLAG(chip->flag); + SSYNC(); + + write_TDBR(*(u8 *) (drv_data->tx)); + while (!(read_STAT() & BIT_STAT_SPIF)) + continue; + while (!(read_STAT() & BIT_STAT_RXS)) + continue; + *(u8 *) (drv_data->rx) = read_RDBR(); + write_FLAG(0xFF00 | chip->flag); + SSYNC(); + if (chip->cs_chg_udelay) + udelay(chip->cs_chg_udelay); ++drv_data->rx; ++drv_data->tx; } + write_FLAG(0xFF00); + SSYNC(); } static void u16_writer(struct driver_data *drv_data) { - dev_dbg(&drv_data->pdev->dev, - "cr16 is 0x%x\n", read_STAT(drv_data)); - - /* poll for SPI completion before start */ - while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) - cpu_relax(); + dev_dbg(&drv_data->pdev->dev, + "cr16 is 0x%x\n", read_STAT()); while (drv_data->tx < drv_data->tx_end) { - write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); - while ((read_STAT(drv_data) & BIT_STAT_TXS)) - cpu_relax(); + write_TDBR(*(u16 *) (drv_data->tx)); + while ((read_STAT() & BIT_STAT_TXS)) + continue; drv_data->tx += 2; } + + /* poll for SPI completion before returning */ + while (!(read_STAT() & BIT_STAT_SPIF)) + continue; } static void u16_cs_chg_writer(struct driver_data *drv_data) { struct chip_data *chip = drv_data->cur_chip; - /* poll for SPI completion before start */ - while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) - cpu_relax(); - while (drv_data->tx < drv_data->tx_end) { - cs_active(drv_data, chip); - - write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); - while ((read_STAT(drv_data) & BIT_STAT_TXS)) - cpu_relax(); - - cs_deactive(drv_data, chip); - + write_FLAG(chip->flag); + SSYNC(); + + write_TDBR(*(u16 *) (drv_data->tx)); + while ((read_STAT() & BIT_STAT_TXS)) + continue; + while (!(read_STAT() & BIT_STAT_SPIF)) + continue; + write_FLAG(0xFF00 | chip->flag); + SSYNC(); + if (chip->cs_chg_udelay) + udelay(chip->cs_chg_udelay); drv_data->tx += 2; } + write_FLAG(0xFF00); + SSYNC(); } static void u16_reader(struct driver_data *drv_data) { dev_dbg(&drv_data->pdev->dev, - "cr-16 is 0x%x\n", read_STAT(drv_data)); - - /* poll for SPI completion before start */ - while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) - cpu_relax(); - - /* clear TDBR buffer before read(else it will be shifted out) */ - write_TDBR(drv_data, 0xFFFF); - - dummy_read(drv_data); + "cr-16 is 0x%x\n", read_STAT()); + dummy_read(); while (drv_data->rx < (drv_data->rx_end - 2)) { - while (!(read_STAT(drv_data) & BIT_STAT_RXS)) - cpu_relax(); - *(u16 *) (drv_data->rx) = read_RDBR(drv_data); + while (!(read_STAT() & BIT_STAT_RXS)) + continue; + *(u16 *) (drv_data->rx) = read_RDBR(); drv_data->rx += 2; } - while (!(read_STAT(drv_data) & BIT_STAT_RXS)) - cpu_relax(); - *(u16 *) (drv_data->rx) = read_SHAW(drv_data); + while (!(read_STAT() & BIT_STAT_RXS)) + continue; + *(u16 *) (drv_data->rx) = read_SHAW(); drv_data->rx += 2; } @@ -490,47 +464,36 @@ static void u16_cs_chg_reader(struct driver_data *drv_data) { struct chip_data *chip = drv_data->cur_chip; - /* poll for SPI completion before start */ - while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) - cpu_relax(); - - /* clear TDBR buffer before read(else it will be shifted out) */ - write_TDBR(drv_data, 0xFFFF); - - cs_active(drv_data, chip); - dummy_read(drv_data); - - while (drv_data->rx < drv_data->rx_end - 2) { - cs_deactive(drv_data, chip); - - while (!(read_STAT(drv_data) & BIT_STAT_RXS)) - cpu_relax(); - cs_active(drv_data, chip); - *(u16 *) (drv_data->rx) = read_RDBR(drv_data); + while (drv_data->rx < drv_data->rx_end) { + write_FLAG(chip->flag); + SSYNC(); + + read_RDBR(); /* kick off */ + while (!(read_STAT() & BIT_STAT_RXS)) + continue; + while (!(read_STAT() & BIT_STAT_SPIF)) + continue; + *(u16 *) (drv_data->rx) = read_SHAW(); + write_FLAG(0xFF00 | chip->flag); + SSYNC(); + if (chip->cs_chg_udelay) + udelay(chip->cs_chg_udelay); drv_data->rx += 2; } - cs_deactive(drv_data, chip); - - while (!(read_STAT(drv_data) & BIT_STAT_RXS)) - cpu_relax(); - *(u16 *) (drv_data->rx) = read_SHAW(drv_data); - drv_data->rx += 2; + write_FLAG(0xFF00); + SSYNC(); } static void u16_duplex(struct driver_data *drv_data) { - /* poll for SPI completion before start */ - while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) - cpu_relax(); - /* in duplex mode, clk is triggered by writing of TDBR */ while (drv_data->tx < drv_data->tx_end) { - write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); - while (read_STAT(drv_data) & BIT_STAT_TXS) - cpu_relax(); - while (!(read_STAT(drv_data) & BIT_STAT_RXS)) - cpu_relax(); - *(u16 *) (drv_data->rx) = read_RDBR(drv_data); + write_TDBR(*(u16 *) (drv_data->tx)); + while (!(read_STAT() & BIT_STAT_SPIF)) + continue; + while (!(read_STAT() & BIT_STAT_RXS)) + continue; + *(u16 *) (drv_data->rx) = read_RDBR(); drv_data->rx += 2; drv_data->tx += 2; } @@ -540,25 +503,25 @@ static void u16_cs_chg_duplex(struct driver_data *drv_data) { struct chip_data *chip = drv_data->cur_chip; - /* poll for SPI completion before start */ - while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) - cpu_relax(); - while (drv_data->tx < drv_data->tx_end) { - cs_active(drv_data, chip); - - write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); - while (read_STAT(drv_data) & BIT_STAT_TXS) - cpu_relax(); - while (!(read_STAT(drv_data) & BIT_STAT_RXS)) - cpu_relax(); - *(u16 *) (drv_data->rx) = read_RDBR(drv_data); - - cs_deactive(drv_data, chip); - + write_FLAG(chip->flag); + SSYNC(); + + write_TDBR(*(u16 *) (drv_data->tx)); + while (!(read_STAT() & BIT_STAT_SPIF)) + continue; + while (!(read_STAT() & BIT_STAT_RXS)) + continue; + *(u16 *) (drv_data->rx) = read_RDBR(); + write_FLAG(0xFF00 | chip->flag); + SSYNC(); + if (chip->cs_chg_udelay) + udelay(chip->cs_chg_udelay); drv_data->rx += 2; drv_data->tx += 2; } + write_FLAG(0xFF00); + SSYNC(); } /* test if ther is more transfer to be done */ @@ -583,7 +546,6 @@ static void *next_transfer(struct driver_data *drv_data) */ static void giveback(struct driver_data *drv_data) { - struct chip_data *chip = drv_data->cur_chip; struct spi_transfer *last_transfer; unsigned long flags; struct spi_message *msg; @@ -603,13 +565,10 @@ static void giveback(struct driver_data *drv_data) /* disable chip select signal. And not stop spi in autobuffer mode */ if (drv_data->tx_dma != 0xFFFF) { - cs_deactive(drv_data, chip); + write_FLAG(0xFF00); bfin_spi_disable(drv_data); } - if (!drv_data->cs_change) - cs_deactive(drv_data, chip); - if (msg->complete) msg->complete(msg->context); } @@ -617,15 +576,14 @@ static void giveback(struct driver_data *drv_data) static irqreturn_t dma_irq_handler(int irq, void *dev_id) { struct driver_data *drv_data = (struct driver_data *)dev_id; - struct chip_data *chip = drv_data->cur_chip; struct spi_message *msg = drv_data->cur_msg; dev_dbg(&drv_data->pdev->dev, "in dma_irq_handler\n"); - clear_dma_irqstat(drv_data->dma_channel); + clear_dma_irqstat(CH_SPI); /* Wait for DMA to complete */ - while (get_dma_curr_irqstat(drv_data->dma_channel) & DMA_RUN) - cpu_relax(); + while (get_dma_curr_irqstat(CH_SPI) & DMA_RUN) + continue; /* * wait for the last transaction shifted out. HRM states: @@ -634,18 +592,17 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id) * register until it goes low for 2 successive reads */ if (drv_data->tx != NULL) { - while ((read_STAT(drv_data) & TXS) || - (read_STAT(drv_data) & TXS)) - cpu_relax(); + while ((bfin_read_SPI_STAT() & TXS) || + (bfin_read_SPI_STAT() & TXS)) + continue; } - while (!(read_STAT(drv_data) & SPIF)) - cpu_relax(); + while (!(bfin_read_SPI_STAT() & SPIF)) + continue; - msg->actual_length += drv_data->len_in_bytes; + bfin_spi_disable(drv_data); - if (drv_data->cs_change) - cs_deactive(drv_data, chip); + msg->actual_length += drv_data->len_in_bytes; /* Move to next transfer */ msg->state = next_transfer(drv_data); @@ -656,8 +613,8 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id) /* free the irq handler before next transfer */ dev_dbg(&drv_data->pdev->dev, "disable dma channel irq%d\n", - drv_data->dma_channel); - dma_disable_irq(drv_data->dma_channel); + CH_SPI); + dma_disable_irq(CH_SPI); return IRQ_HANDLED; } @@ -733,67 +690,31 @@ static void pump_transfers(unsigned long data) drv_data->rx_dma = transfer->rx_dma; drv_data->tx_dma = transfer->tx_dma; drv_data->len_in_bytes = transfer->len; - drv_data->cs_change = transfer->cs_change; - - /* Bits per word setup */ - switch (transfer->bits_per_word) { - case 8: - drv_data->n_bytes = 1; - width = CFG_SPI_WORDSIZE8; - drv_data->read = chip->cs_change_per_word ? - u8_cs_chg_reader : u8_reader; - drv_data->write = chip->cs_change_per_word ? - u8_cs_chg_writer : u8_writer; - drv_data->duplex = chip->cs_change_per_word ? - u8_cs_chg_duplex : u8_duplex; - break; - - case 16: - drv_data->n_bytes = 2; - width = CFG_SPI_WORDSIZE16; - drv_data->read = chip->cs_change_per_word ? - u16_cs_chg_reader : u16_reader; - drv_data->write = chip->cs_change_per_word ? - u16_cs_chg_writer : u16_writer; - drv_data->duplex = chip->cs_change_per_word ? - u16_cs_chg_duplex : u16_duplex; - break; - - default: - /* No change, the same as default setting */ - drv_data->n_bytes = chip->n_bytes; - width = chip->width; - drv_data->write = drv_data->tx ? chip->write : null_writer; - drv_data->read = drv_data->rx ? chip->read : null_reader; - drv_data->duplex = chip->duplex ? chip->duplex : null_writer; - break; - } - cr = (read_CTRL(drv_data) & (~BIT_CTL_TIMOD)); - cr |= (width << 8); - write_CTRL(drv_data, cr); + width = chip->width; if (width == CFG_SPI_WORDSIZE16) { drv_data->len = (transfer->len) >> 1; } else { drv_data->len = transfer->len; } - dev_dbg(&drv_data->pdev->dev, "transfer: ", - "drv_data->write is %p, chip->write is %p, null_wr is %p\n", - drv_data->write, chip->write, null_writer); + drv_data->write = drv_data->tx ? chip->write : null_writer; + drv_data->read = drv_data->rx ? chip->read : null_reader; + drv_data->duplex = chip->duplex ? chip->duplex : null_writer; + dev_dbg(&drv_data->pdev->dev, + "transfer: drv_data->write is %p, chip->write is %p, null_wr is %p\n", + drv_data->write, chip->write, null_writer); /* speed and width has been set on per message */ message->state = RUNNING_STATE; dma_config = 0; - /* Speed setup (surely valid because already checked) */ - if (transfer->speed_hz) - write_BAUD(drv_data, hz_to_spi_baud(transfer->speed_hz)); - else - write_BAUD(drv_data, chip->baud); - - write_STAT(drv_data, BIT_STAT_CLR); - cr = (read_CTRL(drv_data) & (~BIT_CTL_TIMOD)); - cs_active(drv_data, chip); + /* restore spi status for each spi transfer */ + if (transfer->speed_hz) { + write_BAUD(hz_to_spi_baud(transfer->speed_hz)); + } else { + write_BAUD(chip->baud); + } + write_FLAG(chip->flag); dev_dbg(&drv_data->pdev->dev, "now pumping a transfer: width is %d, len is %d\n", @@ -806,25 +727,25 @@ static void pump_transfers(unsigned long data) */ if (drv_data->cur_chip->enable_dma && drv_data->len > 6) { - disable_dma(drv_data->dma_channel); - clear_dma_irqstat(drv_data->dma_channel); + write_STAT(BIT_STAT_CLR); + disable_dma(CH_SPI); + clear_dma_irqstat(CH_SPI); bfin_spi_disable(drv_data); /* config dma channel */ dev_dbg(&drv_data->pdev->dev, "doing dma transfer\n"); if (width == CFG_SPI_WORDSIZE16) { - set_dma_x_count(drv_data->dma_channel, drv_data->len); - set_dma_x_modify(drv_data->dma_channel, 2); + set_dma_x_count(CH_SPI, drv_data->len); + set_dma_x_modify(CH_SPI, 2); dma_width = WDSIZE_16; } else { - set_dma_x_count(drv_data->dma_channel, drv_data->len); - set_dma_x_modify(drv_data->dma_channel, 1); + set_dma_x_count(CH_SPI, drv_data->len); + set_dma_x_modify(CH_SPI, 1); dma_width = WDSIZE_8; } - /* poll for SPI completion before start */ - while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) - cpu_relax(); + /* set transfer width,direction. And enable spi */ + cr = (read_CTRL() & (~BIT_CTL_TIMOD)); /* dirty hack for autobuffer DMA mode */ if (drv_data->tx_dma == 0xFFFF) { @@ -834,18 +755,13 @@ static void pump_transfers(unsigned long data) /* no irq in autobuffer mode */ dma_config = (DMAFLOW_AUTO | RESTART | dma_width | DI_EN); - set_dma_config(drv_data->dma_channel, dma_config); - set_dma_start_addr(drv_data->dma_channel, - (unsigned long)drv_data->tx); - enable_dma(drv_data->dma_channel); - - /* start SPI transfer */ - write_CTRL(drv_data, - (cr | CFG_SPI_DMAWRITE | BIT_CTL_ENABLE)); - - /* just return here, there can only be one transfer - * in this mode - */ + set_dma_config(CH_SPI, dma_config); + set_dma_start_addr(CH_SPI, (unsigned long)drv_data->tx); + enable_dma(CH_SPI); + write_CTRL(cr | CFG_SPI_DMAWRITE | (width << 8) | + (CFG_SPI_ENABLE << 14)); + + /* just return here, there can only be one transfer in this mode */ message->status = 0; giveback(drv_data); return; @@ -856,51 +772,58 @@ static void pump_transfers(unsigned long data) /* set transfer mode, and enable SPI */ dev_dbg(&drv_data->pdev->dev, "doing DMA in.\n"); + /* disable SPI before write to TDBR */ + write_CTRL(cr & ~BIT_CTL_ENABLE); + /* clear tx reg soformer data is not shifted out */ - write_TDBR(drv_data, 0xFFFF); + write_TDBR(0xFF); - set_dma_x_count(drv_data->dma_channel, drv_data->len); + set_dma_x_count(CH_SPI, drv_data->len); /* start dma */ - dma_enable_irq(drv_data->dma_channel); + dma_enable_irq(CH_SPI); dma_config = (WNR | RESTART | dma_width | DI_EN); - set_dma_config(drv_data->dma_channel, dma_config); - set_dma_start_addr(drv_data->dma_channel, - (unsigned long)drv_data->rx); - enable_dma(drv_data->dma_channel); - - /* start SPI transfer */ - write_CTRL(drv_data, - (cr | CFG_SPI_DMAREAD | BIT_CTL_ENABLE)); + set_dma_config(CH_SPI, dma_config); + set_dma_start_addr(CH_SPI, (unsigned long)drv_data->rx); + enable_dma(CH_SPI); + cr |= + CFG_SPI_DMAREAD | (width << 8) | (CFG_SPI_ENABLE << + 14); + /* set transfer mode, and enable SPI */ + write_CTRL(cr); } else if (drv_data->tx != NULL) { dev_dbg(&drv_data->pdev->dev, "doing DMA out.\n"); /* start dma */ - dma_enable_irq(drv_data->dma_channel); + dma_enable_irq(CH_SPI); dma_config = (RESTART | dma_width | DI_EN); - set_dma_config(drv_data->dma_channel, dma_config); - set_dma_start_addr(drv_data->dma_channel, - (unsigned long)drv_data->tx); - enable_dma(drv_data->dma_channel); - - /* start SPI transfer */ - write_CTRL(drv_data, - (cr | CFG_SPI_DMAWRITE | BIT_CTL_ENABLE)); + set_dma_config(CH_SPI, dma_config); + set_dma_start_addr(CH_SPI, (unsigned long)drv_data->tx); + enable_dma(CH_SPI); + + write_CTRL(cr | CFG_SPI_DMAWRITE | (width << 8) | + (CFG_SPI_ENABLE << 14)); + } } else { /* IO mode write then read */ dev_dbg(&drv_data->pdev->dev, "doing IO transfer\n"); + write_STAT(BIT_STAT_CLR); + if (drv_data->tx != NULL && drv_data->rx != NULL) { /* full duplex mode */ BUG_ON((drv_data->tx_end - drv_data->tx) != (drv_data->rx_end - drv_data->rx)); + cr = (read_CTRL() & (~BIT_CTL_TIMOD)); + cr |= CFG_SPI_WRITE | (width << 8) | + (CFG_SPI_ENABLE << 14); dev_dbg(&drv_data->pdev->dev, "IO duplex: cr is 0x%x\n", cr); - /* set SPI transfer mode */ - write_CTRL(drv_data, (cr | CFG_SPI_WRITE)); + write_CTRL(cr); + SSYNC(); drv_data->duplex(drv_data); @@ -908,11 +831,14 @@ static void pump_transfers(unsigned long data) tranf_success = 0; } else if (drv_data->tx != NULL) { /* write only half duplex */ - dev_dbg(&drv_data->pdev->dev, + cr = (read_CTRL() & (~BIT_CTL_TIMOD)); + cr |= CFG_SPI_WRITE | (width << 8) | + (CFG_SPI_ENABLE << 14); + dev_dbg(&drv_data->pdev->dev, "IO write: cr is 0x%x\n", cr); - /* set SPI transfer mode */ - write_CTRL(drv_data, (cr | CFG_SPI_WRITE)); + write_CTRL(cr); + SSYNC(); drv_data->write(drv_data); @@ -920,11 +846,14 @@ static void pump_transfers(unsigned long data) tranf_success = 0; } else if (drv_data->rx != NULL) { /* read only half duplex */ - dev_dbg(&drv_data->pdev->dev, + cr = (read_CTRL() & (~BIT_CTL_TIMOD)); + cr |= CFG_SPI_READ | (width << 8) | + (CFG_SPI_ENABLE << 14); + dev_dbg(&drv_data->pdev->dev, "IO read: cr is 0x%x\n", cr); - /* set SPI transfer mode */ - write_CTRL(drv_data, (cr | CFG_SPI_READ)); + write_CTRL(cr); + SSYNC(); drv_data->read(drv_data); if (drv_data->rx != drv_data->rx_end) @@ -932,7 +861,7 @@ static void pump_transfers(unsigned long data) } if (!tranf_success) { - dev_dbg(&drv_data->pdev->dev, + dev_dbg(&drv_data->pdev->dev, "IO write error!\n"); message->state = ERROR_STATE; } else { @@ -952,11 +881,9 @@ static void pump_transfers(unsigned long data) /* pop a msg from queue and kick off real transfer */ static void pump_messages(struct work_struct *work) { - struct driver_data *drv_data; + struct driver_data *drv_data = container_of(work, struct driver_data, pump_messages); unsigned long flags; - drv_data = container_of(work, struct driver_data, pump_messages); - /* Lock queue and check for queue work */ spin_lock_irqsave(&drv_data->lock, flags); if (list_empty(&drv_data->queue) || drv_data->run == QUEUE_STOPPED) { @@ -975,14 +902,6 @@ static void pump_messages(struct work_struct *work) /* Extract head of queue */ drv_data->cur_msg = list_entry(drv_data->queue.next, struct spi_message, queue); - - /* Setup the SSP using the per chip configuration */ - drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); - if (restore_state(drv_data)) { - spin_unlock_irqrestore(&drv_data->lock, flags); - return; - }; - list_del_init(&drv_data->cur_msg->queue); /* Initial message state */ @@ -990,12 +909,15 @@ static void pump_messages(struct work_struct *work) drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next, struct spi_transfer, transfer_list); - dev_dbg(&drv_data->pdev->dev, "got a message to pump, " - "state is set to: baud %d, flag 0x%x, ctl 0x%x\n", - drv_data->cur_chip->baud, drv_data->cur_chip->flag, - drv_data->cur_chip->ctl_reg); - + /* Setup the SSP using the per chip configuration */ + drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); + restore_state(drv_data); dev_dbg(&drv_data->pdev->dev, + "got a message to pump, state is set to: baud %d, flag 0x%x, ctl 0x%x\n", + drv_data->cur_chip->baud, drv_data->cur_chip->flag, + drv_data->cur_chip->ctl_reg); + + dev_dbg(&drv_data->pdev->dev, "the first transfer len is %d\n", drv_data->cur_transfer->len); @@ -1037,22 +959,6 @@ static int transfer(struct spi_device *spi, struct spi_message *msg) return 0; } -#define MAX_SPI_SSEL 7 - -static u16 ssel[3][MAX_SPI_SSEL] = { - {P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3, - P_SPI0_SSEL4, P_SPI0_SSEL5, - P_SPI0_SSEL6, P_SPI0_SSEL7}, - - {P_SPI1_SSEL1, P_SPI1_SSEL2, P_SPI1_SSEL3, - P_SPI1_SSEL4, P_SPI1_SSEL5, - P_SPI1_SSEL6, P_SPI1_SSEL7}, - - {P_SPI2_SSEL1, P_SPI2_SSEL2, P_SPI2_SSEL3, - P_SPI2_SSEL4, P_SPI2_SSEL5, - P_SPI2_SSEL6, P_SPI2_SSEL7}, -}; - /* first setup for new devices */ static int setup(struct spi_device *spi) { @@ -1087,18 +993,6 @@ static int setup(struct spi_device *spi) /* chip_info isn't always needed */ if (chip_info) { - /* Make sure people stop trying to set fields via ctl_reg - * when they should actually be using common SPI framework. - * Currently we let through: WOM EMISO PSSE GM SZ TIMOD. - * Not sure if a user actually needs/uses any of these, - * but let's assume (for now) they do. - */ - if (chip_info->ctl_reg & (SPE|MSTR|CPOL|CPHA|LSBF|SIZE)) { - dev_err(&spi->dev, "do not set bits in ctl_reg " - "that the SPI framework manages\n"); - return -EINVAL; - } - chip->enable_dma = chip_info->enable_dma != 0 && drv_data->master_info->enable_dma; chip->ctl_reg = chip_info->ctl_reg; @@ -1121,20 +1015,20 @@ static int setup(struct spi_device *spi) * if any one SPI chip is registered and wants DMA, request the * DMA channel for it */ - if (chip->enable_dma && !drv_data->dma_requested) { + if (chip->enable_dma && !dma_requested) { /* register dma irq handler */ - if (request_dma(drv_data->dma_channel, "BF53x_SPI_DMA") < 0) { + if (request_dma(CH_SPI, "BF53x_SPI_DMA") < 0) { dev_dbg(&spi->dev, "Unable to request BlackFin SPI DMA channel\n"); return -ENODEV; } - if (set_dma_callback(drv_data->dma_channel, - (void *)dma_irq_handler, drv_data) < 0) { + if (set_dma_callback(CH_SPI, (void *)dma_irq_handler, drv_data) + < 0) { dev_dbg(&spi->dev, "Unable to set dma callback\n"); return -EPERM; } - dma_disable_irq(drv_data->dma_channel); - drv_data->dma_requested = 1; + dma_disable_irq(CH_SPI); + dma_requested = 1; } /* @@ -1183,14 +1077,6 @@ static int setup(struct spi_device *spi) spi_set_ctldata(spi, chip); - dev_dbg(&spi->dev, "chip select number is %d\n", chip->chip_select_num); - if ((chip->chip_select_num > 0) - && (chip->chip_select_num <= spi->master->num_chipselect)) - peripheral_request(ssel[spi->master->bus_num] - [chip->chip_select_num-1], DRV_NAME); - - cs_deactive(drv_data, chip); - return 0; } @@ -1202,11 +1088,6 @@ static void cleanup(struct spi_device *spi) { struct chip_data *chip = spi_get_ctldata(spi); - if ((chip->chip_select_num > 0) - && (chip->chip_select_num <= spi->master->num_chipselect)) - peripheral_free(ssel[spi->master->bus_num] - [chip->chip_select_num-1]); - kfree(chip); } @@ -1302,7 +1183,6 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev) struct bfin5xx_spi_master *platform_info; struct spi_master *master; struct driver_data *drv_data = 0; - struct resource *res; int status = 0; platform_info = dev->platform_data; @@ -1313,12 +1193,10 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev) dev_err(&pdev->dev, "can not alloc spi_master\n"); return -ENOMEM; } - drv_data = spi_master_get_devdata(master); drv_data->master = master; drv_data->master_info = platform_info; drv_data->pdev = pdev; - drv_data->pin_req = platform_info->pin_req; master->bus_num = pdev->id; master->num_chipselect = platform_info->num_chipselect; @@ -1326,38 +1204,15 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev) master->setup = setup; master->transfer = transfer; - /* Find and map our resources */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(dev, "Cannot get IORESOURCE_MEM\n"); - status = -ENOENT; - goto out_error_get_res; - } - - drv_data->regs_base = ioremap(res->start, (res->end - res->start + 1)); - if (drv_data->regs_base == NULL) { - dev_err(dev, "Cannot map IO\n"); - status = -ENXIO; - goto out_error_ioremap; - } - - drv_data->dma_channel = platform_get_irq(pdev, 0); - if (drv_data->dma_channel < 0) { - dev_err(dev, "No DMA channel specified\n"); - status = -ENOENT; - goto out_error_no_dma_ch; - } - /* Initial and start queue */ status = init_queue(drv_data); if (status != 0) { - dev_err(dev, "problem initializing queue\n"); + dev_err(&pdev->dev, "problem initializing queue\n"); goto out_error_queue_alloc; } - status = start_queue(drv_data); if (status != 0) { - dev_err(dev, "problem starting queue\n"); + dev_err(&pdev->dev, "problem starting queue\n"); goto out_error_queue_alloc; } @@ -1365,30 +1220,15 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, drv_data); status = spi_register_master(master); if (status != 0) { - dev_err(dev, "problem registering spi master\n"); + dev_err(&pdev->dev, "problem registering spi master\n"); goto out_error_queue_alloc; } - - status = peripheral_request_list(drv_data->pin_req, DRV_NAME); - if (status != 0) { - dev_err(&pdev->dev, ": Requesting Peripherals failed\n"); - goto out_error; - } - - dev_info(dev, "%s, Version %s, regs_base@%p, dma channel@%d\n", - DRV_DESC, DRV_VERSION, drv_data->regs_base, - drv_data->dma_channel); + dev_dbg(&pdev->dev, "controller probe successfully\n"); return status; -out_error_queue_alloc: + out_error_queue_alloc: destroy_queue(drv_data); -out_error_no_dma_ch: - iounmap((void *) drv_data->regs_base); -out_error_ioremap: -out_error_get_res: -out_error: spi_master_put(master); - return status; } @@ -1411,15 +1251,13 @@ static int __devexit bfin5xx_spi_remove(struct platform_device *pdev) /* Release DMA */ if (drv_data->master_info->enable_dma) { - if (dma_channel_active(drv_data->dma_channel)) - free_dma(drv_data->dma_channel); + if (dma_channel_active(CH_SPI)) + free_dma(CH_SPI); } /* Disconnect from the SPI framework */ spi_unregister_master(drv_data->master); - peripheral_free_list(drv_data->pin_req); - /* Prevent double remove */ platform_set_drvdata(pdev, NULL); @@ -1467,7 +1305,7 @@ static int bfin5xx_spi_resume(struct platform_device *pdev) MODULE_ALIAS("bfin-spi-master"); /* for platform bus hotplug */ static struct platform_driver bfin5xx_spi_driver = { .driver = { - .name = DRV_NAME, + .name = "bfin-spi-master", .owner = THIS_MODULE, }, .suspend = bfin5xx_spi_suspend, diff --git a/trunk/fs/aio.c b/trunk/fs/aio.c index 9dec7d2d546e..f12db415c0f6 100644 --- a/trunk/fs/aio.c +++ b/trunk/fs/aio.c @@ -1161,12 +1161,7 @@ static int read_events(struct kioctx *ctx, ret = 0; if (to.timed_out) /* Only check after read evt */ break; - /* Try to only show up in io wait if there are ops - * in flight */ - if (ctx->reqs_active) - io_schedule(); - else - schedule(); + io_schedule(); if (signal_pending(tsk)) { ret = -EINTR; break; diff --git a/trunk/fs/bfs/inode.c b/trunk/fs/bfs/inode.c index a64a71d444f5..294c41baef6e 100644 --- a/trunk/fs/bfs/inode.c +++ b/trunk/fs/bfs/inode.c @@ -178,8 +178,7 @@ static void bfs_delete_inode(struct inode *inode) brelse(bh); if (bi->i_dsk_ino) { - if (bi->i_sblock) - info->si_freeb += bi->i_eblock + 1 - bi->i_sblock; + info->si_freeb += BFS_FILEBLOCKS(bi); info->si_freei++; clear_bit(ino, info->si_imap); dump_imap("delete_inode", s); diff --git a/trunk/fs/cifs/cifsacl.c b/trunk/fs/cifs/cifsacl.c index c312adcba4fc..f02fdef463a7 100644 --- a/trunk/fs/cifs/cifsacl.c +++ b/trunk/fs/cifs/cifsacl.c @@ -134,10 +134,9 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) pmode is the existing mode (we only want to overwrite part of this bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007 */ -static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode, +static void access_flags_to_mode(__u32 ace_flags, int type, umode_t *pmode, umode_t *pbits_to_set) { - __u32 flags = le32_to_cpu(ace_flags); /* the order of ACEs is important. The canonical order is to begin with DENY entries followed by ALLOW, otherwise an allow entry could be encountered first, making the subsequent deny entry like "dead code" @@ -147,17 +146,17 @@ static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode, /* For deny ACEs we change the mask so that subsequent allow access control entries do not turn on the bits we are denying */ if (type == ACCESS_DENIED) { - if (flags & GENERIC_ALL) { + if (ace_flags & GENERIC_ALL) { *pbits_to_set &= ~S_IRWXUGO; } - if ((flags & GENERIC_WRITE) || - ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) + if ((ace_flags & GENERIC_WRITE) || + ((ace_flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) *pbits_to_set &= ~S_IWUGO; - if ((flags & GENERIC_READ) || - ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) + if ((ace_flags & GENERIC_READ) || + ((ace_flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) *pbits_to_set &= ~S_IRUGO; - if ((flags & GENERIC_EXECUTE) || - ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) + if ((ace_flags & GENERIC_EXECUTE) || + ((ace_flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) *pbits_to_set &= ~S_IXUGO; return; } else if (type != ACCESS_ALLOWED) { @@ -166,25 +165,25 @@ static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode, } /* else ACCESS_ALLOWED type */ - if (flags & GENERIC_ALL) { + if (ace_flags & GENERIC_ALL) { *pmode |= (S_IRWXUGO & (*pbits_to_set)); #ifdef CONFIG_CIFS_DEBUG2 cFYI(1, ("all perms")); #endif return; } - if ((flags & GENERIC_WRITE) || - ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) + if ((ace_flags & GENERIC_WRITE) || + ((ace_flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) *pmode |= (S_IWUGO & (*pbits_to_set)); - if ((flags & GENERIC_READ) || - ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) + if ((ace_flags & GENERIC_READ) || + ((ace_flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) *pmode |= (S_IRUGO & (*pbits_to_set)); - if ((flags & GENERIC_EXECUTE) || - ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) + if ((ace_flags & GENERIC_EXECUTE) || + ((ace_flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) *pmode |= (S_IXUGO & (*pbits_to_set)); #ifdef CONFIG_CIFS_DEBUG2 - cFYI(1, ("access flags 0x%x mode now 0x%x", flags, *pmode)); + cFYI(1, ("access flags 0x%x mode now 0x%x", ace_flags, *pmode)); #endif return; } diff --git a/trunk/fs/jbd/checkpoint.c b/trunk/fs/jbd/checkpoint.c index 0f69c416eebc..47552d4a6324 100644 --- a/trunk/fs/jbd/checkpoint.c +++ b/trunk/fs/jbd/checkpoint.c @@ -602,15 +602,15 @@ int __journal_remove_checkpoint(struct journal_head *jh) /* * There is one special case to worry about: if we have just pulled the - * buffer off a running or committing transaction's checkpoing list, - * then even if the checkpoint list is empty, the transaction obviously - * cannot be dropped! + * buffer off a committing transaction's forget list, then even if the + * checkpoint list is empty, the transaction obviously cannot be + * dropped! * - * The locking here around t_state is a bit sleazy. + * The locking here around j_committing_transaction is a bit sleazy. * See the comment at the end of journal_commit_transaction(). */ - if (transaction->t_state != T_FINISHED) { - JBUFFER_TRACE(jh, "belongs to running/committing transaction"); + if (transaction == journal->j_committing_transaction) { + JBUFFER_TRACE(jh, "belongs to committing transaction"); goto out; } diff --git a/trunk/fs/jbd/commit.c b/trunk/fs/jbd/commit.c index 610264b99a8e..8f1f2aa5fb39 100644 --- a/trunk/fs/jbd/commit.c +++ b/trunk/fs/jbd/commit.c @@ -858,10 +858,10 @@ void journal_commit_transaction(journal_t *journal) } spin_unlock(&journal->j_list_lock); /* - * This is a bit sleazy. We use j_list_lock to protect transition - * of a transaction into T_FINISHED state and calling - * __journal_drop_transaction(). Otherwise we could race with - * other checkpointing code processing the transaction... + * This is a bit sleazy. We borrow j_list_lock to protect + * journal->j_committing_transaction in __journal_remove_checkpoint. + * Really, __journal_remove_checkpoint should be using j_state_lock but + * it's a bit hassle to hold that across __journal_remove_checkpoint */ spin_lock(&journal->j_state_lock); spin_lock(&journal->j_list_lock); diff --git a/trunk/fs/ocfs2/cluster/tcp.c b/trunk/fs/ocfs2/cluster/tcp.c index ee50c9610e7f..d84bd155997b 100644 --- a/trunk/fs/ocfs2/cluster/tcp.c +++ b/trunk/fs/ocfs2/cluster/tcp.c @@ -72,6 +72,14 @@ #include "tcp_internal.h" +/* + * The linux network stack isn't sparse endian clean.. It has macros like + * ntohs() which perform the endian checks and structs like sockaddr_in + * which aren't annotated. So __force is found here to get the build + * clean. When they emerge from the dark ages and annotate the code + * we can remove these. + */ + #define SC_NODEF_FMT "node %s (num %u) at %u.%u.%u.%u:%u" #define SC_NODEF_ARGS(sc) sc->sc_node->nd_name, sc->sc_node->nd_num, \ NIPQUAD(sc->sc_node->nd_ipv4_address), \ @@ -1492,7 +1500,7 @@ static void o2net_start_connect(struct work_struct *work) myaddr.sin_family = AF_INET; myaddr.sin_addr.s_addr = mynode->nd_ipv4_address; - myaddr.sin_port = htons(0); /* any port */ + myaddr.sin_port = (__force u16)htons(0); /* any port */ ret = sock->ops->bind(sock, (struct sockaddr *)&myaddr, sizeof(myaddr)); @@ -1693,11 +1701,11 @@ static int o2net_accept_one(struct socket *sock) if (ret < 0) goto out; - node = o2nm_get_node_by_ip(sin.sin_addr.s_addr); + node = o2nm_get_node_by_ip((__force __be32)sin.sin_addr.s_addr); if (node == NULL) { mlog(ML_NOTICE, "attempt to connect from unknown node at " "%u.%u.%u.%u:%d\n", NIPQUAD(sin.sin_addr.s_addr), - ntohs(sin.sin_port)); + ntohs((__force __be16)sin.sin_port)); ret = -EINVAL; goto out; } @@ -1706,7 +1714,7 @@ static int o2net_accept_one(struct socket *sock) mlog(ML_NOTICE, "unexpected connect attempted from a lower " "numbered node '%s' at " "%u.%u.%u.%u:%d with num %u\n", node->nd_name, NIPQUAD(sin.sin_addr.s_addr), - ntohs(sin.sin_port), node->nd_num); + ntohs((__force __be16)sin.sin_port), node->nd_num); ret = -EINVAL; goto out; } @@ -1717,7 +1725,7 @@ static int o2net_accept_one(struct socket *sock) mlog(ML_CONN, "attempt to connect from node '%s' at " "%u.%u.%u.%u:%d but it isn't heartbeating\n", node->nd_name, NIPQUAD(sin.sin_addr.s_addr), - ntohs(sin.sin_port)); + ntohs((__force __be16)sin.sin_port)); ret = -EINVAL; goto out; } @@ -1734,7 +1742,7 @@ static int o2net_accept_one(struct socket *sock) mlog(ML_NOTICE, "attempt to connect from node '%s' at " "%u.%u.%u.%u:%d but it already has an open connection\n", node->nd_name, NIPQUAD(sin.sin_addr.s_addr), - ntohs(sin.sin_port)); + ntohs((__force __be16)sin.sin_port)); goto out; } diff --git a/trunk/fs/proc/generic.c b/trunk/fs/proc/generic.c index 8d49838e5554..5fccfe222a63 100644 --- a/trunk/fs/proc/generic.c +++ b/trunk/fs/proc/generic.c @@ -595,7 +595,6 @@ static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent, ent->namelen = len; ent->mode = mode; ent->nlink = nlink; - atomic_set(&ent->count, 1); ent->pde_users = 0; spin_lock_init(&ent->pde_unload_lock); ent->pde_unload_completion = NULL; @@ -693,6 +692,7 @@ void free_proc_entry(struct proc_dir_entry *de) /* * Remove a /proc entry and free it if it's not currently in use. + * If it is in use, we set the 'deleted' flag. */ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) { @@ -741,8 +741,13 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) parent->nlink--; de->nlink = 0; WARN_ON(de->subdir); - if (atomic_dec_and_test(&de->count)) + if (!atomic_read(&de->count)) free_proc_entry(de); + else { + de->deleted = 1; + printk("remove_proc_entry: %s/%s busy, count=%d\n", + parent->name, de->name, atomic_read(&de->count)); + } break; } spin_unlock(&proc_subdir_lock); diff --git a/trunk/fs/proc/inode.c b/trunk/fs/proc/inode.c index 1a551d92e1d8..abe6a3f04368 100644 --- a/trunk/fs/proc/inode.c +++ b/trunk/fs/proc/inode.c @@ -43,8 +43,13 @@ void de_put(struct proc_dir_entry *de) return; } - if (atomic_dec_and_test(&de->count)) - free_proc_entry(de); + if (atomic_dec_and_test(&de->count)) { + if (de->deleted) { + printk("de_put: deferred delete of %s\n", + de->name); + free_proc_entry(de); + } + } unlock_kernel(); } } diff --git a/trunk/fs/proc/root.c b/trunk/fs/proc/root.c index 81f99e691f99..ec9cb3b6c93b 100644 --- a/trunk/fs/proc/root.c +++ b/trunk/fs/proc/root.c @@ -207,7 +207,6 @@ struct proc_dir_entry proc_root = { .name = "/proc", .mode = S_IFDIR | S_IRUGO | S_IXUGO, .nlink = 2, - .count = ATOMIC_INIT(1), .proc_iops = &proc_root_inode_operations, .proc_fops = &proc_root_operations, .parent = &proc_root, diff --git a/trunk/fs/reiserfs/procfs.c b/trunk/fs/reiserfs/procfs.c index 001144621672..9aa7a06e093f 100644 --- a/trunk/fs/reiserfs/procfs.c +++ b/trunk/fs/reiserfs/procfs.c @@ -420,6 +420,12 @@ static void *r_start(struct seq_file *m, loff_t * pos) return NULL; up_write(&s->s_umount); + + if (de->deleted) { + deactivate_super(s); + return NULL; + } + return s; } diff --git a/trunk/fs/ufs/dir.c b/trunk/fs/ufs/dir.c index aaf2878305ce..30f8c2bb0c3e 100644 --- a/trunk/fs/ufs/dir.c +++ b/trunk/fs/ufs/dir.c @@ -179,7 +179,7 @@ static void ufs_check_page(struct page *page) goto fail; Eend: p = (struct ufs_dir_entry *)(kaddr + offs); - ufs_error(sb, __FUNCTION__, + ufs_error (sb, "ext2_check_page", "entry in directory #%lu spans the page boundary" "offset=%lu", dir->i_ino, (page->index<s_fsize = block_size = 1024; uspi->s_fmask = ~(1024 - 1); uspi->s_fshift = 10; uspi->s_sbsize = super_block_size = 2048; uspi->s_sbbase = 0; - uspi->s_dirblksize = 1024; flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; if (!(sb->s_flags & MS_RDONLY)) { if (!silent) @@ -771,13 +771,13 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) break; case UFS_MOUNT_UFSTYPE_NEXTSTEP_CD: + /*TODO: check may be we need set special dir block size?*/ UFSD("ufstype=nextstep-cd\n"); uspi->s_fsize = block_size = 2048; uspi->s_fmask = ~(2048 - 1); uspi->s_fshift = 11; uspi->s_sbsize = super_block_size = 2048; uspi->s_sbbase = 0; - uspi->s_dirblksize = 1024; flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; if (!(sb->s_flags & MS_RDONLY)) { if (!silent) diff --git a/trunk/include/asm-blackfin/bfin5xx_spi.h b/trunk/include/asm-blackfin/bfin5xx_spi.h index 1a0b57f6a3d4..f617d8765451 100644 --- a/trunk/include/asm-blackfin/bfin5xx_spi.h +++ b/trunk/include/asm-blackfin/bfin5xx_spi.h @@ -152,7 +152,6 @@ struct bfin5xx_spi_master { u16 num_chipselect; u8 enable_dma; - u16 pin_req[4]; }; /* spi_board_info.controller_data for SPI slave devices, @@ -163,7 +162,7 @@ struct bfin5xx_spi_chip { u8 enable_dma; u8 bits_per_word; u8 cs_change_per_word; - u16 cs_chg_udelay; /* Some devices require 16-bit delays */ + u8 cs_chg_udelay; }; #endif /* _SPI_CHANNEL_H_ */ diff --git a/trunk/include/asm-blackfin/mach-bf533/portmux.h b/trunk/include/asm-blackfin/mach-bf533/portmux.h index 137f4884acfe..b88d7a03ee3e 100644 --- a/trunk/include/asm-blackfin/mach-bf533/portmux.h +++ b/trunk/include/asm-blackfin/mach-bf533/portmux.h @@ -42,7 +42,7 @@ #define P_SPORT0_DRPRI (P_DONTCARE) #define P_SPI0_MOSI (P_DONTCARE) -#define P_SPI0_MISO (P_DONTCARE) +#define P_SPI0_MIS0 (P_DONTCARE) #define P_SPI0_SCK (P_DONTCARE) #define P_SPI0_SSEL7 (P_DEFINED | P_IDENT(GPIO_PF7)) #define P_SPI0_SSEL6 (P_DEFINED | P_IDENT(GPIO_PF6)) diff --git a/trunk/include/asm-blackfin/mach-bf548/defBF54x_base.h b/trunk/include/asm-blackfin/mach-bf548/defBF54x_base.h index 319a48590c9c..da979cb62f7d 100644 --- a/trunk/include/asm-blackfin/mach-bf548/defBF54x_base.h +++ b/trunk/include/asm-blackfin/mach-bf548/defBF54x_base.h @@ -1644,25 +1644,8 @@ #define RESTART 0x20 /* Work Unit Transitions */ #define DI_SEL 0x40 /* Data Interrupt Timing Select */ #define DI_EN 0x80 /* Data Interrupt Enable */ - #define NDSIZE 0xf00 /* Flex Descriptor Size */ -#define NDSIZE_0 0x0000 /* Next Descriptor Size = 0 (Stop/Autobuffer) */ -#define NDSIZE_1 0x0100 /* Next Descriptor Size = 1 */ -#define NDSIZE_2 0x0200 /* Next Descriptor Size = 2 */ -#define NDSIZE_3 0x0300 /* Next Descriptor Size = 3 */ -#define NDSIZE_4 0x0400 /* Next Descriptor Size = 4 */ -#define NDSIZE_5 0x0500 /* Next Descriptor Size = 5 */ -#define NDSIZE_6 0x0600 /* Next Descriptor Size = 6 */ -#define NDSIZE_7 0x0700 /* Next Descriptor Size = 7 */ -#define NDSIZE_8 0x0800 /* Next Descriptor Size = 8 */ -#define NDSIZE_9 0x0900 /* Next Descriptor Size = 9 */ - #define DMAFLOW 0xf000 /* Next Operation */ -#define DMAFLOW_STOP 0x0000 /* Stop Mode */ -#define DMAFLOW_AUTO 0x1000 /* Autobuffer Mode */ -#define DMAFLOW_ARRAY 0x4000 /* Descriptor Array Mode */ -#define DMAFLOW_SMALL 0x6000 /* Small Model Descriptor List Mode */ -#define DMAFLOW_LARGE 0x7000 /* Large Model Descriptor List Mode */ /* Bit masks for DMAx_IRQ_STATUS, MDMA_Sx_IRQ_STATUS, MDMA_Dx_IRQ_STATUS */ diff --git a/trunk/include/asm-mips/mach-au1x00/au1000.h b/trunk/include/asm-mips/mach-au1x00/au1000.h index bf7701243d71..3bdce9126f16 100644 --- a/trunk/include/asm-mips/mach-au1x00/au1000.h +++ b/trunk/include/asm-mips/mach-au1x00/au1000.h @@ -526,7 +526,7 @@ extern struct au1xxx_irqmap au1xxx_irq_map[]; /* Au1000 */ #ifdef CONFIG_SOC_AU1000 enum soc_au1000_ints { - AU1000_FIRST_INT = MIPS_CPU_IRQ_BASE + 8, + AU1000_FIRST_INT = MIPS_CPU_IRQ_BASE, AU1000_UART0_INT = AU1000_FIRST_INT, AU1000_UART1_INT, /* au1000 */ AU1000_UART2_INT, /* au1000 */ @@ -605,7 +605,7 @@ enum soc_au1000_ints { /* Au1500 */ #ifdef CONFIG_SOC_AU1500 enum soc_au1500_ints { - AU1500_FIRST_INT = MIPS_CPU_IRQ_BASE + 8, + AU1500_FIRST_INT = MIPS_CPU_IRQ_BASE, AU1500_UART0_INT = AU1500_FIRST_INT, AU1000_PCI_INTA, /* au1500 */ AU1000_PCI_INTB, /* au1500 */ @@ -686,7 +686,7 @@ enum soc_au1500_ints { /* Au1100 */ #ifdef CONFIG_SOC_AU1100 enum soc_au1100_ints { - AU1100_FIRST_INT = MIPS_CPU_IRQ_BASE + 8, + AU1100_FIRST_INT = MIPS_CPU_IRQ_BASE, AU1100_UART0_INT, AU1100_UART1_INT, AU1100_SD_INT, @@ -761,7 +761,7 @@ enum soc_au1100_ints { #ifdef CONFIG_SOC_AU1550 enum soc_au1550_ints { - AU1550_FIRST_INT = MIPS_CPU_IRQ_BASE + 8, + AU1550_FIRST_INT = MIPS_CPU_IRQ_BASE, AU1550_UART0_INT = AU1550_FIRST_INT, AU1550_PCI_INTA, AU1550_PCI_INTB, @@ -851,7 +851,7 @@ enum soc_au1550_ints { #ifdef CONFIG_SOC_AU1200 enum soc_au1200_ints { - AU1200_FIRST_INT = MIPS_CPU_IRQ_BASE + 8, + AU1200_FIRST_INT = MIPS_CPU_IRQ_BASE, AU1200_UART0_INT = AU1200_FIRST_INT, AU1200_SWT_INT, AU1200_SD_INT, @@ -948,12 +948,11 @@ enum soc_au1200_ints { #endif /* CONFIG_SOC_AU1200 */ -#define AU1000_INTC0_INT_BASE (MIPS_CPU_IRQ_BASE + 8) -#define AU1000_INTC0_INT_LAST (AU1000_INTC0_INT_BASE + 31) -#define AU1000_INTC1_INT_BASE (AU1000_INTC0_INT_BASE + 32) -#define AU1000_INTC1_INT_LAST (AU1000_INTC1_INT_BASE + 31) - -#define AU1000_MAX_INTR AU1000_INTC1_INT_LAST +#define AU1000_INTC0_INT_BASE (MIPS_CPU_IRQ_BASE + 0) +#define AU1000_INTC0_INT_LAST (MIPS_CPU_IRQ_BASE + 31) +#define AU1000_INTC1_INT_BASE (MIPS_CPU_IRQ_BASE + 32) +#define AU1000_INTC1_INT_LAST (MIPS_CPU_IRQ_BASE + 63) +#define AU1000_MAX_INTR (MIPS_CPU_IRQ_BASE + 63) #define INTX 0xFF /* not valid */ /* Programmable Counters 0 and 1 */ diff --git a/trunk/include/asm-parisc/pdc.h b/trunk/include/asm-parisc/pdc.h index deda8c311373..5e0c3ca5450b 100644 --- a/trunk/include/asm-parisc/pdc.h +++ b/trunk/include/asm-parisc/pdc.h @@ -645,7 +645,8 @@ int pdc_soft_power_button(int sw_control); void pdc_io_reset(void); void pdc_io_reset_devices(void); int pdc_iodc_getc(void); -int pdc_iodc_print(unsigned char *str, unsigned count); +void pdc_iodc_putc(unsigned char c); +void pdc_iodc_outc(unsigned char c); void pdc_printf(const char *fmt, ...); void pdc_emergency_unlock(void); diff --git a/trunk/include/asm-powerpc/pgtable-ppc32.h b/trunk/include/asm-powerpc/pgtable-ppc32.h index d1332bbcbd9b..fea2d8ff1e73 100644 --- a/trunk/include/asm-powerpc/pgtable-ppc32.h +++ b/trunk/include/asm-powerpc/pgtable-ppc32.h @@ -86,11 +86,6 @@ extern int icache_44x_need_flush; * entries per page directory level: our page-table tree is two-level, so * we don't really have any PMD directory. */ -#ifndef __ASSEMBLY__ -#define PTE_TABLE_SIZE (sizeof(pte_t) << PTE_SHIFT) -#define PGD_TABLE_SIZE (sizeof(pgd_t) << (32 - PGDIR_SHIFT)) -#endif /* __ASSEMBLY__ */ - #define PTRS_PER_PTE (1 << PTE_SHIFT) #define PTRS_PER_PMD 1 #define PTRS_PER_PGD (1 << (32 - PGDIR_SHIFT)) diff --git a/trunk/include/linux/inet_lro.h b/trunk/include/linux/inet_lro.h index 80335b7d77c5..1246d46abbc0 100644 --- a/trunk/include/linux/inet_lro.h +++ b/trunk/include/linux/inet_lro.h @@ -91,9 +91,6 @@ struct net_lro_mgr { int max_desc; /* Max number of LRO descriptors */ int max_aggr; /* Max number of LRO packets to be aggregated */ - int frag_align_pad; /* Padding required to properly align layer 3 - * headers in generated skb when using frags */ - struct net_lro_desc *lro_arr; /* Array of LRO descriptors */ /* diff --git a/trunk/include/linux/jbd.h b/trunk/include/linux/jbd.h index d9ecd13393b0..16e7ed855a18 100644 --- a/trunk/include/linux/jbd.h +++ b/trunk/include/linux/jbd.h @@ -439,8 +439,6 @@ struct transaction_s /* * Transaction's current state * [no locking - only kjournald alters this] - * [j_list_lock] guards transition of a transaction into T_FINISHED - * state and subsequent call of __journal_drop_transaction() * FIXME: needs barriers * KLUDGE: [use j_state_lock] */ diff --git a/trunk/include/linux/mm.h b/trunk/include/linux/mm.h index 1b7b95c67aca..520238cbae5d 100644 --- a/trunk/include/linux/mm.h +++ b/trunk/include/linux/mm.h @@ -12,7 +12,6 @@ #include #include #include -#include struct mempolicy; struct anon_vma; @@ -513,21 +512,6 @@ static inline void set_page_links(struct page *page, enum zone_type zone, set_page_section(page, pfn_to_section_nr(pfn)); } -/* - * If a hint addr is less than mmap_min_addr change hint to be as - * low as possible but still greater than mmap_min_addr - */ -static inline unsigned long round_hint_to_min(unsigned long hint) -{ -#ifdef CONFIG_SECURITY - hint &= PAGE_MASK; - if (((void *)hint != NULL) && - (hint < mmap_min_addr)) - return PAGE_ALIGN(mmap_min_addr); -#endif - return hint; -} - /* * Some inline functions in vmstat.h depend on page_zone() */ diff --git a/trunk/include/linux/phy.h b/trunk/include/linux/phy.h index 554836edd915..e10763d79181 100644 --- a/trunk/include/linux/phy.h +++ b/trunk/include/linux/phy.h @@ -403,7 +403,6 @@ int phy_mii_ioctl(struct phy_device *phydev, int phy_start_interrupts(struct phy_device *phydev); void phy_print_status(struct phy_device *phydev); struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id); -void phy_device_free(struct phy_device *phydev); extern struct bus_type mdio_bus_type; #endif /* __PHY_H */ diff --git a/trunk/include/linux/proc_fs.h b/trunk/include/linux/proc_fs.h index a5316829215b..523528d237b0 100644 --- a/trunk/include/linux/proc_fs.h +++ b/trunk/include/linux/proc_fs.h @@ -77,6 +77,7 @@ struct proc_dir_entry { read_proc_t *read_proc; write_proc_t *write_proc; atomic_t count; /* use count */ + int deleted; /* delete flag */ int pde_users; /* number of callers into module in progress */ spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */ struct completion *pde_unload_completion; diff --git a/trunk/include/linux/thread_info.h b/trunk/include/linux/thread_info.h index 9c4ad755d7e5..1c4eb41dbd89 100644 --- a/trunk/include/linux/thread_info.h +++ b/trunk/include/linux/thread_info.h @@ -7,25 +7,12 @@ #ifndef _LINUX_THREAD_INFO_H #define _LINUX_THREAD_INFO_H -#include - /* - * System call restart block. + * System call restart block. */ struct restart_block { long (*fn)(struct restart_block *); - union { - struct { - unsigned long arg0, arg1, arg2, arg3; - }; - /* For futex_wait */ - struct { - u32 *uaddr; - u32 val; - u32 flags; - u64 time; - } futex; - }; + unsigned long arg0, arg1, arg2, arg3; }; extern long do_no_restart_syscall(struct restart_block *parm); diff --git a/trunk/kernel/Kconfig.instrumentation b/trunk/kernel/Kconfig.instrumentation index 468f47ad7503..2ea1e347df45 100644 --- a/trunk/kernel/Kconfig.instrumentation +++ b/trunk/kernel/Kconfig.instrumentation @@ -20,8 +20,8 @@ config PROFILING config OPROFILE tristate "OProfile system profiling (EXPERIMENTAL)" - depends on PROFILING && !UML - depends on ARCH_SUPPORTS_OPROFILE || ALPHA || ARM || BLACKFIN || IA64 || M32R || PARISC || PPC || S390 || SUPERH || SPARC + depends on PROFILING + depends on (ALPHA || ARM || BLACKFIN || X86_32 || IA64 || M32R || MIPS || PARISC || PPC || S390 || SUPERH || SPARC || X86_64) && !UML help OProfile is a profiling system capable of profiling the whole system, include the kernel, kernel modules, libraries, @@ -31,8 +31,8 @@ config OPROFILE config KPROBES bool "Kprobes" - depends on KALLSYMS && MODULES && !UML - depends on X86_32 || IA64 || PPC || S390 || SPARC64 || X86_64 || AVR32 + depends on KALLSYMS && MODULES + depends on (X86_32 || IA64 || PPC || S390 || SPARC64 || X86_64 || AVR32) && !UML help Kprobes allows you to trap at almost any kernel address and execute a callback function. register_kprobe() establishes diff --git a/trunk/kernel/fork.c b/trunk/kernel/fork.c index 8dd8ff281009..8ca1a14cdc8c 100644 --- a/trunk/kernel/fork.c +++ b/trunk/kernel/fork.c @@ -1292,14 +1292,23 @@ static struct task_struct *copy_process(unsigned long clone_flags, __ptrace_link(p, current->parent); if (thread_group_leader(p)) { - if (clone_flags & CLONE_NEWPID) + if (clone_flags & CLONE_NEWPID) { p->nsproxy->pid_ns->child_reaper = p; + p->signal->tty = NULL; + set_task_pgrp(p, p->pid); + set_task_session(p, p->pid); + attach_pid(p, PIDTYPE_PGID, pid); + attach_pid(p, PIDTYPE_SID, pid); + } else { + p->signal->tty = current->signal->tty; + set_task_pgrp(p, task_pgrp_nr(current)); + set_task_session(p, task_session_nr(current)); + attach_pid(p, PIDTYPE_PGID, + task_pgrp(current)); + attach_pid(p, PIDTYPE_SID, + task_session(current)); + } - p->signal->tty = current->signal->tty; - set_task_pgrp(p, task_pgrp_nr(current)); - set_task_session(p, task_session_nr(current)); - attach_pid(p, PIDTYPE_PGID, task_pgrp(current)); - attach_pid(p, PIDTYPE_SID, task_session(current)); list_add_tail_rcu(&p->tasks, &init_task.tasks); __get_cpu_var(process_counts)++; } diff --git a/trunk/kernel/futex.c b/trunk/kernel/futex.c index 172a1aeeafdb..9dc591ab681a 100644 --- a/trunk/kernel/futex.c +++ b/trunk/kernel/futex.c @@ -658,7 +658,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this) if (curval == -EFAULT) ret = -EFAULT; - else if (curval != uval) + if (curval != uval) ret = -EINVAL; if (ret) { spin_unlock(&pi_state->pi_mutex.wait_lock); @@ -1149,9 +1149,9 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, /* * In case we must use restart_block to restart a futex_wait, - * we encode in the 'flags' shared capability + * we encode in the 'arg3' shared capability */ -#define FLAGS_SHARED 1 +#define ARG3_SHARED 1 static long futex_wait_restart(struct restart_block *restart); @@ -1290,13 +1290,12 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, struct restart_block *restart; restart = ¤t_thread_info()->restart_block; restart->fn = futex_wait_restart; - restart->futex.uaddr = (u32 *)uaddr; - restart->futex.val = val; - restart->futex.time = abs_time->tv64; - restart->futex.flags = 0; - + restart->arg0 = (unsigned long)uaddr; + restart->arg1 = (unsigned long)val; + restart->arg2 = (unsigned long)abs_time; + restart->arg3 = 0; if (fshared) - restart->futex.flags |= FLAGS_SHARED; + restart->arg3 |= ARG3_SHARED; return -ERESTART_RESTARTBLOCK; } @@ -1311,15 +1310,15 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, static long futex_wait_restart(struct restart_block *restart) { - u32 __user *uaddr = (u32 __user *)restart->futex.uaddr; + u32 __user *uaddr = (u32 __user *)restart->arg0; + u32 val = (u32)restart->arg1; + ktime_t *abs_time = (ktime_t *)restart->arg2; struct rw_semaphore *fshared = NULL; - ktime_t t; - t.tv64 = restart->futex.time; restart->fn = do_no_restart_syscall; - if (restart->futex.flags & FLAGS_SHARED) + if (restart->arg3 & ARG3_SHARED) fshared = ¤t->mm->mmap_sem; - return (long)futex_wait(uaddr, fshared, restart->futex.val, &t); + return (long)futex_wait(uaddr, fshared, val, abs_time); } diff --git a/trunk/kernel/lockdep.c b/trunk/kernel/lockdep.c index 0f389621bb6b..ed38bbfc48a3 100644 --- a/trunk/kernel/lockdep.c +++ b/trunk/kernel/lockdep.c @@ -3054,6 +3054,11 @@ void __init lockdep_info(void) #endif } +static inline int in_range(const void *start, const void *addr, const void *end) +{ + return addr >= start && addr <= end; +} + static void print_freed_lock_bug(struct task_struct *curr, const void *mem_from, const void *mem_to, struct held_lock *hlock) @@ -3075,13 +3080,6 @@ print_freed_lock_bug(struct task_struct *curr, const void *mem_from, dump_stack(); } -static inline int not_in_range(const void* mem_from, unsigned long mem_len, - const void* lock_from, unsigned long lock_len) -{ - return lock_from + lock_len <= mem_from || - mem_from + mem_len <= lock_from; -} - /* * Called when kernel memory is freed (or unmapped), or if a lock * is destroyed or reinitialized - this code checks whether there is @@ -3089,6 +3087,7 @@ static inline int not_in_range(const void* mem_from, unsigned long mem_len, */ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len) { + const void *mem_to = mem_from + mem_len, *lock_from, *lock_to; struct task_struct *curr = current; struct held_lock *hlock; unsigned long flags; @@ -3101,11 +3100,14 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len) for (i = 0; i < curr->lockdep_depth; i++) { hlock = curr->held_locks + i; - if (not_in_range(mem_from, mem_len, hlock->instance, - sizeof(*hlock->instance))) + lock_from = (void *)hlock->instance; + lock_to = (void *)(hlock->instance + 1); + + if (!in_range(mem_from, lock_from, mem_to) && + !in_range(mem_from, lock_to, mem_to)) continue; - print_freed_lock_bug(curr, mem_from, mem_from + mem_len, hlock); + print_freed_lock_bug(curr, mem_from, mem_to, hlock); break; } local_irq_restore(flags); @@ -3171,13 +3173,6 @@ void debug_show_all_locks(void) printk(" locked it.\n"); do_each_thread(g, p) { - /* - * It's not reliable to print a task's held locks - * if it's not sleeping (or if it's not the current - * task): - */ - if (p->state == TASK_RUNNING && p != current) - continue; if (p->lockdep_depth) lockdep_print_held_locks(p); if (!unlock) diff --git a/trunk/kernel/sched.c b/trunk/kernel/sched.c index 67d9d1799d86..59ff6b140edb 100644 --- a/trunk/kernel/sched.c +++ b/trunk/kernel/sched.c @@ -209,8 +209,9 @@ static inline struct task_group *task_group(struct task_struct *p) tg = container_of(task_subsys_state(p, cpu_cgroup_subsys_id), struct task_group, css); #else - tg = &init_task_group; + tg = &init_task_group; #endif + return tg; } @@ -248,16 +249,15 @@ struct cfs_rq { #ifdef CONFIG_FAIR_GROUP_SCHED struct rq *rq; /* cpu runqueue to which this cfs_rq is attached */ - /* - * leaf cfs_rqs are those that hold tasks (lowest schedulable entity in + /* leaf cfs_rqs are those that hold tasks (lowest schedulable entity in * a hierarchy). Non-leaf lrqs hold other higher schedulable entities * (like users, containers etc.) * * leaf_cfs_rq_list ties together list of leaf cfs_rq's in a cpu. This * list is used during load balance. */ - struct list_head leaf_cfs_rq_list; - struct task_group *tg; /* group that "owns" this runqueue */ + struct list_head leaf_cfs_rq_list; /* Better name : task_cfs_rq_list? */ + struct task_group *tg; /* group that "owns" this runqueue */ #endif }; @@ -300,7 +300,7 @@ struct rq { /* list of leaf cfs_rq on this cpu: */ struct list_head leaf_cfs_rq_list; #endif - struct rt_rq rt; + struct rt_rq rt; /* * This is part of a global counter where only the total sum @@ -457,8 +457,8 @@ enum { SCHED_FEAT_NEW_FAIR_SLEEPERS = 1, SCHED_FEAT_WAKEUP_PREEMPT = 2, SCHED_FEAT_START_DEBIT = 4, - SCHED_FEAT_TREE_AVG = 8, - SCHED_FEAT_APPROX_AVG = 16, + SCHED_FEAT_TREE_AVG = 8, + SCHED_FEAT_APPROX_AVG = 16, }; const_debug unsigned int sysctl_sched_features = @@ -591,7 +591,7 @@ static inline struct rq *__task_rq_lock(struct task_struct *p) /* * task_rq_lock - lock the runqueue a given task resides on and disable - * interrupts. Note the ordering: we can safely lookup the task_rq without + * interrupts. Note the ordering: we can safely lookup the task_rq without * explicitly disabling preemption. */ static struct rq *task_rq_lock(struct task_struct *p, unsigned long *flags) @@ -779,7 +779,7 @@ static inline void update_load_sub(struct load_weight *lw, unsigned long dec) * To aid in avoiding the subversion of "niceness" due to uneven distribution * of tasks with abnormal "nice" values across CPUs the contribution that * each task makes to its run queue's load is weighted according to its - * scheduling class and "nice" value. For SCHED_NORMAL tasks this is just a + * scheduling class and "nice" value. For SCHED_NORMAL tasks this is just a * scaled version of the new time slice allocation that they receive on time * slice expiry etc. */ @@ -1854,7 +1854,7 @@ prepare_task_switch(struct rq *rq, struct task_struct *prev, * and do any other architecture-specific cleanup actions. * * Note that we may have delayed dropping an mm in context_switch(). If - * so, we finish that here outside of the runqueue lock. (Doing it + * so, we finish that here outside of the runqueue lock. (Doing it * with the lock held can cause deadlocks; see schedule() for * details.) */ @@ -2136,7 +2136,7 @@ static void double_lock_balance(struct rq *this_rq, struct rq *busiest) /* * If dest_cpu is allowed for this process, migrate the task to it. * This is accomplished by forcing the cpu_allowed mask to only - * allow dest_cpu, which will force the cpu onto dest_cpu. Then + * allow dest_cpu, which will force the cpu onto dest_cpu. Then * the cpu_allowed mask is restored. */ static void sched_migrate_task(struct task_struct *p, int dest_cpu) @@ -2581,7 +2581,7 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, * tasks around. Thus we look for the minimum possible imbalance. * Negative imbalances (*we* are more loaded than anyone else) will * be counted as no imbalance for these purposes -- we can't fix that - * by pulling tasks to us. Be careful of negative numbers as they'll + * by pulling tasks to us. Be careful of negative numbers as they'll * appear as very large values with unsigned longs. */ if (max_load <= busiest_load_per_task) @@ -3016,7 +3016,7 @@ static void active_load_balance(struct rq *busiest_rq, int busiest_cpu) /* * This condition is "impossible", if it occurs - * we need to fix it. Originally reported by + * we need to fix it. Originally reported by * Bjorn Helgaas on a 128-cpu setup. */ BUG_ON(busiest_rq == target_rq); @@ -3048,7 +3048,7 @@ static void active_load_balance(struct rq *busiest_rq, int busiest_cpu) #ifdef CONFIG_NO_HZ static struct { atomic_t load_balancer; - cpumask_t cpu_mask; + cpumask_t cpu_mask; } nohz ____cacheline_aligned = { .load_balancer = ATOMIC_INIT(-1), .cpu_mask = CPU_MASK_NONE, @@ -3552,7 +3552,7 @@ static noinline void __schedule_bug(struct task_struct *prev) static inline void schedule_debug(struct task_struct *prev) { /* - * Test if we are atomic. Since do_exit() needs to call into + * Test if we are atomic. Since do_exit() needs to call into * schedule() atomically, we ignore that path for now. * Otherwise, whine if we are scheduling when we should not be. */ @@ -3674,7 +3674,7 @@ EXPORT_SYMBOL(schedule); #ifdef CONFIG_PREEMPT /* * this is the entry point to schedule() from in-kernel preemption - * off of preempt_enable. Kernel preemptions off return from interrupt + * off of preempt_enable. Kernel preemptions off return from interrupt * occur there and call schedule directly. */ asmlinkage void __sched preempt_schedule(void) @@ -3686,7 +3686,7 @@ asmlinkage void __sched preempt_schedule(void) #endif /* * If there is a non-zero preempt_count or interrupts are disabled, - * we do not want to preempt the current task. Just return.. + * we do not want to preempt the current task. Just return.. */ if (likely(ti->preempt_count || irqs_disabled())) return; @@ -3772,12 +3772,12 @@ int default_wake_function(wait_queue_t *curr, unsigned mode, int sync, EXPORT_SYMBOL(default_wake_function); /* - * The core wakeup function. Non-exclusive wakeups (nr_exclusive == 0) just - * wake everything up. If it's an exclusive wakeup (nr_exclusive == small +ve + * The core wakeup function. Non-exclusive wakeups (nr_exclusive == 0) just + * wake everything up. If it's an exclusive wakeup (nr_exclusive == small +ve * number) then we wake all the non-exclusive tasks and one exclusive task. * * There are circumstances in which we can try to wake a task which has already - * started to run but is not in state TASK_RUNNING. try_to_wake_up() returns + * started to run but is not in state TASK_RUNNING. try_to_wake_up() returns * zero in this (rare) case, and we handle it by continuing to scan the queue. */ static void __wake_up_common(wait_queue_head_t *q, unsigned int mode, @@ -4390,8 +4390,8 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) * @policy: new policy. * @param: structure containing the new RT priority. */ -asmlinkage long -sys_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) +asmlinkage long sys_sched_setscheduler(pid_t pid, int policy, + struct sched_param __user *param) { /* negative values for policy are not valid */ if (policy < 0) @@ -4491,7 +4491,7 @@ long sched_setaffinity(pid_t pid, cpumask_t new_mask) /* * It is not safe to call set_cpus_allowed with the - * tasklist_lock held. We will bump the task_struct's + * tasklist_lock held. We will bump the task_struct's * usage count and then drop tasklist_lock. */ get_task_struct(p); @@ -4687,7 +4687,7 @@ EXPORT_SYMBOL(cond_resched); * cond_resched_lock() - if a reschedule is pending, drop the given lock, * call schedule, and on return reacquire the lock. * - * This works OK both with and without CONFIG_PREEMPT. We do strange low-level + * This works OK both with and without CONFIG_PREEMPT. We do strange low-level * operations here to prevent schedule() from being called twice (once via * spin_unlock(), once by hand). */ @@ -4741,7 +4741,7 @@ void __sched yield(void) EXPORT_SYMBOL(yield); /* - * This task is about to go to sleep on IO. Increment rq->nr_iowait so + * This task is about to go to sleep on IO. Increment rq->nr_iowait so * that process accounting knows that this is a task in IO wait state. * * But don't do that if it is a deliberate, throttling IO wait (this task @@ -4850,21 +4850,17 @@ long sys_sched_rr_get_interval(pid_t pid, struct timespec __user *interval) if (retval) goto out_unlock; - /* - * Time slice is 0 for SCHED_FIFO tasks and for SCHED_OTHER - * tasks that are on an otherwise idle runqueue: - */ - time_slice = 0; - if (p->policy == SCHED_RR) { + if (p->policy == SCHED_FIFO) + time_slice = 0; + else if (p->policy == SCHED_RR) time_slice = DEF_TIMESLICE; - } else { + else { struct sched_entity *se = &p->se; unsigned long flags; struct rq *rq; rq = task_rq_lock(p, &flags); - if (rq->cfs.load.weight) - time_slice = NS_TO_JIFFIES(sched_slice(&rq->cfs, se)); + time_slice = NS_TO_JIFFIES(sched_slice(cfs_rq_of(se), se)); task_rq_unlock(rq, &flags); } read_unlock(&tasklist_lock); @@ -5050,7 +5046,7 @@ static inline void sched_init_granularity(void) * is removed from the allowed bitmask. * * NOTE: the caller must have a valid reference to the task, the - * task must not exit() & deallocate itself prematurely. The + * task must not exit() & deallocate itself prematurely. The * call is not atomic; no spinlocks may be held. */ int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask) @@ -5087,7 +5083,7 @@ int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask) EXPORT_SYMBOL_GPL(set_cpus_allowed); /* - * Move (not current) task off this cpu, onto dest cpu. We're doing + * Move (not current) task off this cpu, onto dest cpu. We're doing * this because either it can't run here any more (set_cpus_allowed() * away from this CPU, or CPU going down), or because we're * attempting to rebalance this task on exec (sched_exec). @@ -5232,7 +5228,7 @@ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p) * Try to stay on the same cpuset, where the * current cpuset may be a subset of all cpus. * The cpuset_cpus_allowed_locked() variant of - * cpuset_cpus_allowed() will not block. It must be + * cpuset_cpus_allowed() will not block. It must be * called within calls to cpuset_lock/cpuset_unlock. */ rq = task_rq_lock(p, &flags); @@ -5245,11 +5241,10 @@ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p) * kernel threads (both mm NULL), since they never * leave kernel. */ - if (p->mm && printk_ratelimit()) { + if (p->mm && printk_ratelimit()) printk(KERN_INFO "process %d (%s) no " "longer affine to cpu%d\n", - task_pid_nr(p), p->comm, dead_cpu); - } + task_pid_nr(p), p->comm, dead_cpu); } } while (!__migrate_task_irq(p, dead_cpu, dest_cpu)); } @@ -5351,7 +5346,7 @@ static void migrate_dead(unsigned int dead_cpu, struct task_struct *p) /* * Drop lock around migration; if someone else moves it, - * that's OK. No task can be added to this CPU, so iteration is + * that's OK. No task can be added to this CPU, so iteration is * fine. */ spin_unlock_irq(&rq->lock); @@ -5415,7 +5410,7 @@ static void sd_free_ctl_entry(struct ctl_table **tablep) /* * In the intermediate directories, both the child directory and * procname are dynamically allocated and could fail but the mode - * will always be set. In the lowest directory the names are + * will always be set. In the lowest directory the names are * static strings and all have proc handlers. */ for (entry = *tablep; entry->mode; entry++) { @@ -5586,7 +5581,7 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) case CPU_UP_CANCELED_FROZEN: if (!cpu_rq(cpu)->migration_thread) break; - /* Unbind it from offline cpu so it can run. Fall thru. */ + /* Unbind it from offline cpu so it can run. Fall thru. */ kthread_bind(cpu_rq(cpu)->migration_thread, any_online_cpu(cpu_online_map)); kthread_stop(cpu_rq(cpu)->migration_thread); @@ -5613,11 +5608,9 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) migrate_nr_uninterruptible(rq); BUG_ON(rq->nr_running != 0); - /* - * No need to migrate the tasks: it was best-effort if - * they didn't take sched_hotcpu_mutex. Just wake up - * the requestors. - */ + /* No need to migrate the tasks: it was best-effort if + * they didn't take sched_hotcpu_mutex. Just wake up + * the requestors. */ spin_lock_irq(&rq->lock); while (!list_empty(&rq->migration_queue)) { struct migration_req *req; @@ -5925,7 +5918,7 @@ init_sched_build_groups(cpumask_t span, const cpumask_t *cpu_map, * @node: node whose sched_domain we're building * @used_nodes: nodes already in the sched_domain * - * Find the next node to include in a given scheduling domain. Simply + * Find the next node to include in a given scheduling domain. Simply * finds the closest node not already in the @used_nodes map. * * Should use nodemask_t. @@ -5965,7 +5958,7 @@ static int find_next_best_node(int node, unsigned long *used_nodes) * @node: node whose cpumask we're constructing * @size: number of nodes to include in this span * - * Given a node, construct a good cpumask for its sched_domain to span. It + * Given a node, construct a good cpumask for its sched_domain to span. It * should be one that prevents unnecessary balancing, but also spreads tasks * out optimally. */ @@ -6002,8 +5995,8 @@ int sched_smt_power_savings = 0, sched_mc_power_savings = 0; static DEFINE_PER_CPU(struct sched_domain, cpu_domains); static DEFINE_PER_CPU(struct sched_group, sched_group_cpus); -static int -cpu_to_cpu_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg) +static int cpu_to_cpu_group(int cpu, const cpumask_t *cpu_map, + struct sched_group **sg) { if (sg) *sg = &per_cpu(sched_group_cpus, cpu); @@ -6020,8 +6013,8 @@ static DEFINE_PER_CPU(struct sched_group, sched_group_core); #endif #if defined(CONFIG_SCHED_MC) && defined(CONFIG_SCHED_SMT) -static int -cpu_to_core_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg) +static int cpu_to_core_group(int cpu, const cpumask_t *cpu_map, + struct sched_group **sg) { int group; cpumask_t mask = per_cpu(cpu_sibling_map, cpu); @@ -6032,8 +6025,8 @@ cpu_to_core_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg) return group; } #elif defined(CONFIG_SCHED_MC) -static int -cpu_to_core_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg) +static int cpu_to_core_group(int cpu, const cpumask_t *cpu_map, + struct sched_group **sg) { if (sg) *sg = &per_cpu(sched_group_core, cpu); @@ -6044,8 +6037,8 @@ cpu_to_core_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg) static DEFINE_PER_CPU(struct sched_domain, phys_domains); static DEFINE_PER_CPU(struct sched_group, sched_group_phys); -static int -cpu_to_phys_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg) +static int cpu_to_phys_group(int cpu, const cpumask_t *cpu_map, + struct sched_group **sg) { int group; #ifdef CONFIG_SCHED_MC @@ -6225,7 +6218,7 @@ static int build_sched_domains(const cpumask_t *cpu_map) * Allocate the per-node list of sched groups */ sched_group_nodes = kcalloc(MAX_NUMNODES, sizeof(struct sched_group *), - GFP_KERNEL); + GFP_KERNEL); if (!sched_group_nodes) { printk(KERN_WARNING "Can not alloc sched group node list\n"); return -ENOMEM; @@ -6472,7 +6465,7 @@ static int ndoms_cur; /* number of sched domains in 'doms_cur' */ static cpumask_t fallback_doms; /* - * Set up scheduler domains and groups. Callers must hold the hotplug lock. + * Set up scheduler domains and groups. Callers must hold the hotplug lock. * For now this just excludes isolated cpus, but could be used to * exclude other special cases in the future. */ @@ -6514,19 +6507,19 @@ static void detach_destroy_domains(const cpumask_t *cpu_map) /* * Partition sched domains as specified by the 'ndoms_new' - * cpumasks in the array doms_new[] of cpumasks. This compares + * cpumasks in the array doms_new[] of cpumasks. This compares * doms_new[] to the current sched domain partitioning, doms_cur[]. * It destroys each deleted domain and builds each new domain. * * 'doms_new' is an array of cpumask_t's of length 'ndoms_new'. - * The masks don't intersect (don't overlap.) We should setup one - * sched domain for each mask. CPUs not in any of the cpumasks will - * not be load balanced. If the same cpumask appears both in the + * The masks don't intersect (don't overlap.) We should setup one + * sched domain for each mask. CPUs not in any of the cpumasks will + * not be load balanced. If the same cpumask appears both in the * current 'doms_cur' domains and in the new 'doms_new', we can leave * it as it is. * - * The passed in 'doms_new' should be kmalloc'd. This routine takes - * ownership of it and will kfree it when done with it. If the caller + * The passed in 'doms_new' should be kmalloc'd. This routine takes + * ownership of it and will kfree it when done with it. If the caller * failed the kmalloc call, then it can pass in doms_new == NULL, * and partition_sched_domains() will fallback to the single partition * 'fallback_doms'. @@ -6656,7 +6649,7 @@ int sched_create_sysfs_power_savings_entries(struct sysdev_class *cls) #endif /* - * Force a reinitialization of the sched domains hierarchy. The domains + * Force a reinitialization of the sched domains hierarchy. The domains * and groups cannot be updated in place without racing with the balancing * code, so we temporarily attach all running cpus to the NULL domain * which will prevent rebalancing while the sched domains are recalculated. @@ -6946,8 +6939,8 @@ struct task_struct *curr_task(int cpu) * @p: the task pointer to set. * * Description: This function must only be used when non-maskable interrupts - * are serviced on a separate stack. It allows the architecture to switch the - * notion of the current task on a cpu in a non-blocking manner. This function + * are serviced on a separate stack. It allows the architecture to switch the + * notion of the current task on a cpu in a non-blocking manner. This function * must be called with all CPU's synchronized, and interrupts disabled, the * and caller must save the original value of the current task (see * curr_task() above) and restore that value before reenabling interrupts and @@ -7196,17 +7189,16 @@ cpu_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cgrp) return &tg->css; } -static void -cpu_cgroup_destroy(struct cgroup_subsys *ss, struct cgroup *cgrp) +static void cpu_cgroup_destroy(struct cgroup_subsys *ss, + struct cgroup *cgrp) { struct task_group *tg = cgroup_tg(cgrp); sched_destroy_group(tg); } -static int -cpu_cgroup_can_attach(struct cgroup_subsys *ss, struct cgroup *cgrp, - struct task_struct *tsk) +static int cpu_cgroup_can_attach(struct cgroup_subsys *ss, + struct cgroup *cgrp, struct task_struct *tsk) { /* We don't support RT-tasks being in separate groups */ if (tsk->sched_class != &fair_sched_class) @@ -7312,8 +7304,8 @@ static struct cgroup_subsys_state *cpuacct_create( } /* destroy an existing cpu accounting group */ -static void -cpuacct_destroy(struct cgroup_subsys *ss, struct cgroup *cont) +static void cpuacct_destroy(struct cgroup_subsys *ss, + struct cgroup *cont) { struct cpuacct *ca = cgroup_ca(cont); diff --git a/trunk/kernel/sched_fair.c b/trunk/kernel/sched_fair.c index c33f0ceb3de9..37bb265598db 100644 --- a/trunk/kernel/sched_fair.c +++ b/trunk/kernel/sched_fair.c @@ -799,9 +799,8 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int sleep) */ static void yield_task_fair(struct rq *rq) { - struct task_struct *curr = rq->curr; - struct cfs_rq *cfs_rq = task_cfs_rq(curr); - struct sched_entity *rightmost, *se = &curr->se; + struct cfs_rq *cfs_rq = task_cfs_rq(rq->curr); + struct sched_entity *rightmost, *se = &rq->curr->se; /* * Are we the only task in the tree? @@ -809,7 +808,7 @@ static void yield_task_fair(struct rq *rq) if (unlikely(cfs_rq->nr_running == 1)) return; - if (likely(!sysctl_sched_compat_yield) && curr->policy != SCHED_BATCH) { + if (likely(!sysctl_sched_compat_yield)) { __update_rq_clock(rq); /* * Update run-time statistics of the 'current'. diff --git a/trunk/kernel/sysctl.c b/trunk/kernel/sysctl.c index 8ac51714b08c..0deed82a6156 100644 --- a/trunk/kernel/sysctl.c +++ b/trunk/kernel/sysctl.c @@ -1588,10 +1588,6 @@ struct ctl_table_header *register_sysctl_table(struct ctl_table * table) void unregister_sysctl_table(struct ctl_table_header * header) { might_sleep(); - - if (header == NULL) - return; - spin_lock(&sysctl_lock); start_unregistering(header); spin_unlock(&sysctl_lock); diff --git a/trunk/kernel/sysctl_check.c b/trunk/kernel/sysctl_check.c index bed939f82c31..6972f26c65f7 100644 --- a/trunk/kernel/sysctl_check.c +++ b/trunk/kernel/sysctl_check.c @@ -96,7 +96,7 @@ static struct trans_ctl_table trans_kern_table[] = { { KERN_PTY, "pty", trans_pty_table }, { KERN_NGROUPS_MAX, "ngroups_max" }, - { KERN_SPARC_SCONS_PWROFF, "scons-poweroff" }, + { KERN_SPARC_SCONS_PWROFF, "scons_poweroff" }, { KERN_HZ_TIMER, "hz_timer" }, { KERN_UNKNOWN_NMI_PANIC, "unknown_nmi_panic" }, { KERN_BOOTLOADER_TYPE, "bootloader_type" }, diff --git a/trunk/mm/backing-dev.c b/trunk/mm/backing-dev.c index e8644b1e5527..b0ceb29da4c7 100644 --- a/trunk/mm/backing-dev.c +++ b/trunk/mm/backing-dev.c @@ -7,7 +7,7 @@ int bdi_init(struct backing_dev_info *bdi) { - int i; + int i, j; int err; for (i = 0; i < NR_BDI_STAT_ITEMS; i++) { @@ -21,7 +21,7 @@ int bdi_init(struct backing_dev_info *bdi) if (err) { err: - while (i--) + for (j = 0; j < i; j++) percpu_counter_destroy(&bdi->bdi_stat[i]); } diff --git a/trunk/mm/filemap_xip.c b/trunk/mm/filemap_xip.c index e233fff61b4b..32132f3cd641 100644 --- a/trunk/mm/filemap_xip.c +++ b/trunk/mm/filemap_xip.c @@ -314,7 +314,7 @@ __xip_file_write(struct file *filp, const char __user *buf, fault_in_pages_readable(buf, bytes); kaddr = kmap_atomic(page, KM_USER0); copied = bytes - - __copy_from_user_inatomic_nocache(kaddr + offset, buf, bytes); + __copy_from_user_inatomic_nocache(kaddr, buf, bytes); kunmap_atomic(kaddr, KM_USER0); flush_dcache_page(page); diff --git a/trunk/mm/mmap.c b/trunk/mm/mmap.c index 15678aa6ec73..facc1a75bd4f 100644 --- a/trunk/mm/mmap.c +++ b/trunk/mm/mmap.c @@ -912,9 +912,6 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, if (!len) return -EINVAL; - if (!(flags & MAP_FIXED)) - addr = round_hint_to_min(addr); - error = arch_mmap_check(addr, len, flags); if (error) return error; @@ -1618,12 +1615,6 @@ static inline int expand_downwards(struct vm_area_struct *vma, */ if (unlikely(anon_vma_prepare(vma))) return -ENOMEM; - - address &= PAGE_MASK; - error = security_file_mmap(0, 0, 0, 0, address, 1); - if (error) - return error; - anon_vma_lock(vma); /* @@ -1631,6 +1622,8 @@ static inline int expand_downwards(struct vm_area_struct *vma, * is required to hold the mmap_sem in read mode. We need the * anon_vma lock to serialize against concurrent expand_stacks. */ + address &= PAGE_MASK; + error = 0; /* Somebody else might have raced and expanded it already */ if (address < vma->vm_start) { @@ -1941,10 +1934,6 @@ unsigned long do_brk(unsigned long addr, unsigned long len) if (is_hugepage_only_range(mm, addr, len)) return -EINVAL; - error = security_file_mmap(0, 0, 0, 0, addr, 1); - if (error) - return error; - flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; error = arch_mmap_check(addr, len, flags); diff --git a/trunk/mm/nommu.c b/trunk/mm/nommu.c index b989cb928a7c..35622c590925 100644 --- a/trunk/mm/nommu.c +++ b/trunk/mm/nommu.c @@ -829,9 +829,6 @@ unsigned long do_mmap_pgoff(struct file *file, void *result; int ret; - if (!(flags & MAP_FIXED)) - addr = round_hint_to_min(addr); - /* decide whether we should attempt the mapping, and if so what sort of * mapping */ ret = validate_mmap_request(file, addr, len, prot, flags, pgoff, diff --git a/trunk/mm/slab.c b/trunk/mm/slab.c index 2e338a5f7b14..202465a193c1 100644 --- a/trunk/mm/slab.c +++ b/trunk/mm/slab.c @@ -4475,4 +4475,3 @@ size_t ksize(const void *objp) return obj_size(virt_to_cache(objp)); } -EXPORT_SYMBOL(ksize); diff --git a/trunk/mm/slob.c b/trunk/mm/slob.c index ee2ef8af0d43..08a9bd91a1aa 100644 --- a/trunk/mm/slob.c +++ b/trunk/mm/slob.c @@ -495,7 +495,6 @@ size_t ksize(const void *block) else return sp->page.private; } -EXPORT_SYMBOL(ksize); struct kmem_cache { unsigned int size, align; diff --git a/trunk/mm/slub.c b/trunk/mm/slub.c index b9f37cb0f2e6..9acb413858ac 100644 --- a/trunk/mm/slub.c +++ b/trunk/mm/slub.c @@ -2558,12 +2558,8 @@ size_t ksize(const void *object) if (unlikely(object == ZERO_SIZE_PTR)) return 0; - page = virt_to_head_page(object); + page = get_object_page(object); BUG_ON(!page); - - if (unlikely(!PageSlab(page))) - return PAGE_SIZE << compound_order(page); - s = page->slab; BUG_ON(!s); diff --git a/trunk/net/ipv4/inet_lro.c b/trunk/net/ipv4/inet_lro.c index 9a96c277393d..ac3b1d3dba2e 100644 --- a/trunk/net/ipv4/inet_lro.c +++ b/trunk/net/ipv4/inet_lro.c @@ -401,11 +401,10 @@ static struct sk_buff *lro_gen_skb(struct net_lro_mgr *lro_mgr, int data_len = len; int hdr_len = min(len, hlen); - skb = netdev_alloc_skb(lro_mgr->dev, hlen + lro_mgr->frag_align_pad); + skb = netdev_alloc_skb(lro_mgr->dev, hlen); if (!skb) return NULL; - skb_reserve(skb, lro_mgr->frag_align_pad); skb->len = len; skb->data_len = len - hdr_len; skb->truesize += true_size; diff --git a/trunk/net/ipv4/ipvs/ip_vs_lblc.c b/trunk/net/ipv4/ipvs/ip_vs_lblc.c index ad89644ef5d2..b843a11d7cf7 100644 --- a/trunk/net/ipv4/ipvs/ip_vs_lblc.c +++ b/trunk/net/ipv4/ipvs/ip_vs_lblc.c @@ -580,14 +580,9 @@ static struct ip_vs_scheduler ip_vs_lblc_scheduler = static int __init ip_vs_lblc_init(void) { - int ret; - INIT_LIST_HEAD(&ip_vs_lblc_scheduler.n_list); sysctl_header = register_sysctl_table(lblc_root_table); - ret = register_ip_vs_scheduler(&ip_vs_lblc_scheduler); - if (ret) - unregister_sysctl_table(sysctl_header); - return ret; + return register_ip_vs_scheduler(&ip_vs_lblc_scheduler); } diff --git a/trunk/net/ipv4/ipvs/ip_vs_lblcr.c b/trunk/net/ipv4/ipvs/ip_vs_lblcr.c index 2a5ed85a3352..e5b323a6b2f7 100644 --- a/trunk/net/ipv4/ipvs/ip_vs_lblcr.c +++ b/trunk/net/ipv4/ipvs/ip_vs_lblcr.c @@ -769,14 +769,9 @@ static struct ip_vs_scheduler ip_vs_lblcr_scheduler = static int __init ip_vs_lblcr_init(void) { - int ret; - INIT_LIST_HEAD(&ip_vs_lblcr_scheduler.n_list); sysctl_header = register_sysctl_table(lblcr_root_table); - ret = register_ip_vs_scheduler(&ip_vs_lblcr_scheduler); - if (ret) - unregister_sysctl_table(sysctl_header); - return ret; + return register_ip_vs_scheduler(&ip_vs_lblcr_scheduler); } diff --git a/trunk/net/ipv4/ipvs/ip_vs_sched.c b/trunk/net/ipv4/ipvs/ip_vs_sched.c index 432235861908..1602304abbf9 100644 --- a/trunk/net/ipv4/ipvs/ip_vs_sched.c +++ b/trunk/net/ipv4/ipvs/ip_vs_sched.c @@ -183,6 +183,19 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler) /* increase the module use count */ ip_vs_use_count_inc(); + /* + * Make sure that the scheduler with this name doesn't exist + * in the scheduler list. + */ + sched = ip_vs_sched_getbyname(scheduler->name); + if (sched) { + ip_vs_scheduler_put(sched); + ip_vs_use_count_dec(); + IP_VS_ERR("register_ip_vs_scheduler(): [%s] scheduler " + "already existed in the system\n", scheduler->name); + return -EINVAL; + } + write_lock_bh(&__ip_vs_sched_lock); if (scheduler->n_list.next != &scheduler->n_list) { @@ -193,20 +206,6 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler) return -EINVAL; } - /* - * Make sure that the scheduler with this name doesn't exist - * in the scheduler list. - */ - list_for_each_entry(sched, &ip_vs_schedulers, n_list) { - if (strcmp(scheduler->name, sched->name) == 0) { - write_unlock_bh(&__ip_vs_sched_lock); - ip_vs_use_count_dec(); - IP_VS_ERR("register_ip_vs_scheduler(): [%s] scheduler " - "already existed in the system\n", - scheduler->name); - return -EINVAL; - } - } /* * Add it into the d-linked scheduler list */ diff --git a/trunk/net/ipv4/tcp_input.c b/trunk/net/ipv4/tcp_input.c index b9e429d2d1de..0f0c1c9829a1 100644 --- a/trunk/net/ipv4/tcp_input.c +++ b/trunk/net/ipv4/tcp_input.c @@ -3003,13 +3003,17 @@ static int tcp_process_frto(struct sock *sk, int flag) } if (tp->frto_counter == 1) { - /* tcp_may_send_now needs to see updated state */ + /* Sending of the next skb must be allowed or no F-RTO */ + if (!tcp_send_head(sk) || + after(TCP_SKB_CB(tcp_send_head(sk))->end_seq, + tp->snd_una + tp->snd_wnd)) { + tcp_enter_frto_loss(sk, (tp->frto_counter == 1 ? 2 : 3), + flag); + return 1; + } + tp->snd_cwnd = tcp_packets_in_flight(tp) + 2; tp->frto_counter = 2; - - if (!tcp_may_send_now(sk)) - tcp_enter_frto_loss(sk, 2, flag); - return 1; } else { switch (sysctl_tcp_frto_response) { @@ -3065,7 +3069,6 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) } prior_fackets = tp->fackets_out; - prior_in_flight = tcp_packets_in_flight(tp); if (!(flag&FLAG_SLOWPATH) && after(ack, prior_snd_una)) { /* Window is constant, pure forward advance. @@ -3105,6 +3108,8 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) if (!prior_packets) goto no_queue; + prior_in_flight = tcp_packets_in_flight(tp); + /* See if we can take anything off of the retransmit queue. */ flag |= tcp_clean_rtx_queue(sk, &seq_rtt, prior_fackets); diff --git a/trunk/net/ipv4/tcp_output.c b/trunk/net/ipv4/tcp_output.c index f4c1eef89af0..e5130a7fe181 100644 --- a/trunk/net/ipv4/tcp_output.c +++ b/trunk/net/ipv4/tcp_output.c @@ -1162,7 +1162,8 @@ int tcp_may_send_now(struct sock *sk) return (skb && tcp_snd_test(sk, skb, tcp_current_mss(sk, 1), (tcp_skb_is_last(sk, skb) ? - tp->nonagle : TCP_NAGLE_PUSH))); + TCP_NAGLE_PUSH : + tp->nonagle))); } /* Trim TSO SKB to LEN bytes, put the remaining data into a new packet diff --git a/trunk/net/irda/ircomm/ircomm_tty.c b/trunk/net/irda/ircomm/ircomm_tty.c index be627e1f04d8..1120b150e211 100644 --- a/trunk/net/irda/ircomm/ircomm_tty.c +++ b/trunk/net/irda/ircomm/ircomm_tty.c @@ -1245,7 +1245,6 @@ static void ircomm_tty_flow_indication(void *instance, void *sap, self->flow = cmd; } -#ifdef CONFIG_PROC_FS static int ircomm_tty_line_info(struct ircomm_tty_cb *self, char *buf) { int ret=0; @@ -1355,6 +1354,7 @@ static int ircomm_tty_line_info(struct ircomm_tty_cb *self, char *buf) * * */ +#ifdef CONFIG_PROC_FS static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len, int *eof, void *unused) { diff --git a/trunk/net/rose/rose_dev.c b/trunk/net/rose/rose_dev.c index 12cfcf09556b..1b6741f1d746 100644 --- a/trunk/net/rose/rose_dev.c +++ b/trunk/net/rose/rose_dev.c @@ -55,13 +55,13 @@ static int rose_header(struct sk_buff *skb, struct net_device *dev, static int rose_rebuild_header(struct sk_buff *skb) { -#ifdef CONFIG_INET struct net_device *dev = skb->dev; struct net_device_stats *stats = netdev_priv(dev); unsigned char *bp = (unsigned char *)skb->data; struct sk_buff *skbn; unsigned int len; +#ifdef CONFIG_INET if (arp_find(bp + 7, skb)) { return 1; } diff --git a/trunk/security/dummy.c b/trunk/security/dummy.c index 3ccfbbe973b6..6d895ade73de 100644 --- a/trunk/security/dummy.c +++ b/trunk/security/dummy.c @@ -426,7 +426,7 @@ static int dummy_file_mmap (struct file *file, unsigned long reqprot, unsigned long addr, unsigned long addr_only) { - if ((addr < mmap_min_addr) && !capable(CAP_SYS_RAWIO)) + if (addr < mmap_min_addr) return -EACCES; return 0; } diff --git a/trunk/security/selinux/selinuxfs.c b/trunk/security/selinux/selinuxfs.c index 2fa483f26113..f5f3e6da5da7 100644 --- a/trunk/security/selinux/selinuxfs.c +++ b/trunk/security/selinux/selinuxfs.c @@ -65,7 +65,6 @@ static DEFINE_MUTEX(sel_mutex); /* global data for booleans */ static struct dentry *bool_dir = NULL; static int bool_num = 0; -static char **bool_pending_names; static int *bool_pending_values = NULL; /* global data for classes */ @@ -833,16 +832,15 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, ssize_t length; ssize_t ret; int cur_enforcing; - struct inode *inode = filep->f_path.dentry->d_inode; - unsigned index = inode->i_ino & SEL_INO_MASK; - const char *name = filep->f_path.dentry->d_name.name; + struct inode *inode; mutex_lock(&sel_mutex); - if (index >= bool_num || strcmp(name, bool_pending_names[index])) { - ret = -EINVAL; + ret = -EFAULT; + + /* check to see if this file has been deleted */ + if (!filep->f_op) goto out; - } if (count > PAGE_SIZE) { ret = -EINVAL; @@ -853,13 +851,15 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, goto out; } - cur_enforcing = security_get_bool_value(index); + inode = filep->f_path.dentry->d_inode; + cur_enforcing = security_get_bool_value(inode->i_ino&SEL_INO_MASK); if (cur_enforcing < 0) { ret = cur_enforcing; goto out; } + length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing, - bool_pending_values[index]); + bool_pending_values[inode->i_ino&SEL_INO_MASK]); ret = simple_read_from_buffer(buf, count, ppos, page, length); out: mutex_unlock(&sel_mutex); @@ -872,11 +872,9 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, size_t count, loff_t *ppos) { char *page = NULL; - ssize_t length; + ssize_t length = -EFAULT; int new_value; - struct inode *inode = filep->f_path.dentry->d_inode; - unsigned index = inode->i_ino & SEL_INO_MASK; - const char *name = filep->f_path.dentry->d_name.name; + struct inode *inode; mutex_lock(&sel_mutex); @@ -884,19 +882,16 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, if (length) goto out; - if (index >= bool_num || strcmp(name, bool_pending_names[index])) { - length = -EINVAL; + /* check to see if this file has been deleted */ + if (!filep->f_op) goto out; - } if (count >= PAGE_SIZE) { length = -ENOMEM; goto out; } - if (*ppos != 0) { /* No partial writes. */ - length = -EINVAL; goto out; } page = (char*)get_zeroed_page(GFP_KERNEL); @@ -905,7 +900,6 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, goto out; } - length = -EFAULT; if (copy_from_user(page, buf, count)) goto out; @@ -916,7 +910,8 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, if (new_value) new_value = 1; - bool_pending_values[index] = new_value; + inode = filep->f_path.dentry->d_inode; + bool_pending_values[inode->i_ino&SEL_INO_MASK] = new_value; length = count; out: @@ -936,7 +931,7 @@ static ssize_t sel_commit_bools_write(struct file *filep, size_t count, loff_t *ppos) { char *page = NULL; - ssize_t length; + ssize_t length = -EFAULT; int new_value; mutex_lock(&sel_mutex); @@ -945,6 +940,10 @@ static ssize_t sel_commit_bools_write(struct file *filep, if (length) goto out; + /* check to see if this file has been deleted */ + if (!filep->f_op) + goto out; + if (count >= PAGE_SIZE) { length = -ENOMEM; goto out; @@ -959,7 +958,6 @@ static ssize_t sel_commit_bools_write(struct file *filep, goto out; } - length = -EFAULT; if (copy_from_user(page, buf, count)) goto out; @@ -984,9 +982,11 @@ static const struct file_operations sel_commit_bools_ops = { .write = sel_commit_bools_write, }; +/* partial revoke() from fs/proc/generic.c proc_kill_inodes */ static void sel_remove_entries(struct dentry *de) { - struct list_head *node; + struct list_head *p, *node; + struct super_block *sb = de->d_sb; spin_lock(&dcache_lock); node = de->d_subdirs.next; @@ -1006,6 +1006,18 @@ static void sel_remove_entries(struct dentry *de) } spin_unlock(&dcache_lock); + + file_list_lock(); + list_for_each(p, &sb->s_files) { + struct file * filp = list_entry(p, struct file, f_u.fu_list); + struct dentry * dentry = filp->f_path.dentry; + + if (dentry->d_parent != de) { + continue; + } + filp->f_op = NULL; + } + file_list_unlock(); } #define BOOL_DIR_NAME "booleans" @@ -1024,9 +1036,7 @@ static int sel_make_bools(void) u32 sid; /* remove any existing files */ - kfree(bool_pending_names); kfree(bool_pending_values); - bool_pending_names = NULL; bool_pending_values = NULL; sel_remove_entries(dir); @@ -1068,17 +1078,16 @@ static int sel_make_bools(void) d_add(dentry, inode); } bool_num = num; - bool_pending_names = names; bool_pending_values = values; out: free_page((unsigned long)page); - return ret; -err: if (names) { for (i = 0; i < num; i++) kfree(names[i]); kfree(names); } + return ret; +err: kfree(values); sel_remove_entries(dir); ret = -ENOMEM;