From c7fc24dc4420057f103afe8fc64524ebc25c5d37 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 25 Aug 1998 09:12:35 +0000 Subject: o Merge with Linux 2.1.116. o New Newport console code. o New G364 console code. --- arch/alpha/lib/Makefile | 2 +- arch/alpha/lib/io.c | 170 +++++++++++++++++++++++++++++++++++-------- arch/alpha/lib/memset.S | 25 ++++++- arch/alpha/lib/strcasecmp.c | 26 +++++++ arch/alpha/lib/strlen_user.S | 2 +- 5 files changed, 188 insertions(+), 37 deletions(-) create mode 100644 arch/alpha/lib/strcasecmp.c (limited to 'arch/alpha/lib') diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile index 7c1e37bac..4dd7d591d 100644 --- a/arch/alpha/lib/Makefile +++ b/arch/alpha/lib/Makefile @@ -7,7 +7,7 @@ OBJS = __divqu.o __remqu.o __divlu.o __remlu.o memset.o memcpy.o io.o \ strcat.o strcpy.o strncat.o strncpy.o stxcpy.o stxncpy.o \ strchr.o strrchr.o \ copy_user.o clear_user.o strncpy_from_user.o strlen_user.o \ - csum_ipv6_magic.o + csum_ipv6_magic.o strcasecmp.o lib.a: $(OBJS) $(AR) rcs lib.a $(OBJS) diff --git a/arch/alpha/lib/io.c b/arch/alpha/lib/io.c index 405a3afa8..50cc1fe05 100644 --- a/arch/alpha/lib/io.c +++ b/arch/alpha/lib/io.c @@ -3,26 +3,9 @@ * files.. */ #include - +#include #include -/* - * Jensen has a separate "local" and "bus" IO space for - * byte-wide IO. - */ -#ifdef __is_local - -unsigned int _bus_inb(unsigned long addr) -{ - return __bus_inb(addr); -} - -void _bus_outb(unsigned char b, unsigned long addr) -{ - __bus_outb(b, addr); -} -#endif - unsigned int _inb(unsigned long addr) { return __inb(addr); @@ -70,6 +53,10 @@ unsigned long _readl(unsigned long addr) return __readl(addr); } +unsigned long _readq(unsigned long addr) +{ + return __readq(addr); +} void _writeb(unsigned char b, unsigned long addr) { @@ -86,6 +73,11 @@ void _writel(unsigned int b, unsigned long addr) __writel(b, addr); } +void _writeq(unsigned long b, unsigned long addr) +{ + __writeq(b, addr); +} + /* * Read COUNT 8-bit bytes from port PORT into memory starting at * SRC. @@ -363,12 +355,48 @@ void outsl (unsigned long port, const void *src, unsigned long count) * Copy data from IO memory space to "real" memory space. * This needs to be optimized. */ -void _memcpy_fromio(void * to, unsigned long from, unsigned long count) +void _memcpy_fromio(void * to, unsigned long from, long count) { - while (count) { + /* Optimize co-aligned transfers. Everything else gets handled + a byte at a time. */ + + if (count >= 8 && ((long)to & 7) == (from & 7)) { + count -= 8; + do { + *(u64 *)to = readq(from); + count -= 8; + to += 8; + from += 8; + } while (count >= 0); + count += 8; + } + + if (count >= 4 && ((long)to & 3) == (from & 3)) { + count -= 4; + do { + *(u32 *)to = readl(from); + count -= 4; + to += 4; + from += 4; + } while (count >= 0); + count += 4; + } + + if (count >= 2 && ((long)to & 1) == (from & 1)) { + count -= 2; + do { + *(u16 *)to = readw(from); + count -= 2; + to += 2; + from += 2; + } while (count >= 0); + count += 2; + } + + while (count > 0) { + *(u8 *) to = readb(from); count--; - *(char *) to = readb(from); - ((char *) to)++; + to++; from++; } } @@ -377,25 +405,105 @@ void _memcpy_fromio(void * to, unsigned long from, unsigned long count) * Copy data from "real" memory space to IO memory space. * This needs to be optimized. */ -void _memcpy_toio(unsigned long to, void * from, unsigned long count) +void _memcpy_toio(unsigned long to, void * from, long count) { - while (count) { + /* Optimize co-aligned transfers. Everything else gets handled + a byte at a time. */ + + if (count >= 8 && (to & 7) == ((long)from & 7)) { + count -= 8; + do { + writeq(*(u64 *)from, to); + count -= 8; + to += 8; + from += 8; + } while (count >= 0); + count += 8; + } + + if (count >= 4 && (to & 3) == ((long)from & 3)) { + count -= 4; + do { + writel(*(u32 *)from, to); + count -= 4; + to += 4; + from += 4; + } while (count >= 0); + count += 4; + } + + if (count >= 2 && (to & 1) == ((long)from & 1)) { + count -= 2; + do { + writew(*(u16 *)from, to); + count -= 2; + to += 2; + from += 2; + } while (count >= 0); + count += 2; + } + + while (count > 0) { + writeb(*(u8 *) from, to); count--; - writeb(*(char *) from, to); - ((char *) from)++; to++; + from++; } } /* * "memset" on IO memory space. - * This needs to be optimized. */ -void _memset_io(unsigned long dst, int c, unsigned long count) +void _memset_c_io(unsigned long to, unsigned long c, long count) { - while (count) { + /* Handle any initial odd byte */ + if (count > 0 && (to & 1)) { + writeb(c, to); + to++; count--; - writeb(c, dst); - dst++; + } + + /* Handle any initial odd halfword */ + if (count >= 2 && (to & 2)) { + writew(c, to); + to += 2; + count -= 2; + } + + /* Handle any initial odd word */ + if (count >= 4 && (to & 4)) { + writel(c, to); + to += 4; + count -= 4; + } + + /* Handle all full-sized quadwords: we're aligned (or have a small count) */ + count -= 8; + if (count >= 0) { + do { + writeq(c, to); + to += 8; + count -= 8; + } while (count >= 0); + } + count += 8; + + /* The tail is word-aligned if we still have count >= 4 */ + if (count >= 4) { + writel(c, to); + to += 4; + count -= 4; + } + + /* The tail is half-word aligned if we have count >= 2 */ + if (count >= 2) { + writew(c, to); + to += 2; + count -= 2; + } + + /* And finally, one last byte.. */ + if (count) { + writeb(c, to); } } diff --git a/arch/alpha/lib/memset.S b/arch/alpha/lib/memset.S index dc2075e1f..f39197dee 100644 --- a/arch/alpha/lib/memset.S +++ b/arch/alpha/lib/memset.S @@ -18,6 +18,7 @@ .set noreorder .text .globl __memset + .globl __memsetw .globl __constant_c_memset .ent __memset .align 5 @@ -25,8 +26,8 @@ __memset: .frame $30,0,$26,0 .prologue 0 - zapnot $17,1,$17 /* E0 */ - sll $17,8,$1 /* E1 (p-c latency, next cycle) */ + and $17,255,$1 /* E1 */ + insbl $17,1,$17 /* .. E0 */ bis $17,$1,$17 /* E0 (p-c latency, next cycle) */ sll $17,16,$1 /* E1 (p-c latency, next cycle) */ @@ -52,9 +53,9 @@ __constant_c_memset: insql $17,$16,$2 /* E0 */ subq $3,8,$3 /* .. E1 */ - addq $18,$3,$18 /* E0 $18 is new count ($3 is negative) */ + addq $18,$3,$18 /* E0 $18 is new count ($3 is negative) */ mskql $4,$16,$4 /* .. E1 (and possible load stall) */ - subq $16,$3,$16 /* E0 $16 is new aligned destination */ + subq $16,$3,$16 /* E0 $16 is new aligned destination */ bis $2,$4,$1 /* .. E1 */ bis $31,$31,$31 /* E0 */ @@ -103,6 +104,22 @@ end: ret $31,($26),1 /* E1 */ .end __memset + .align 5 + .ent __memsetw +__memsetw: + .prologue 0 + + inswl $17,0,$1 /* E0 */ + inswl $17,2,$2 /* E0 */ + inswl $17,4,$3 /* E0 */ + or $1,$2,$1 /* .. E1 */ + inswl $17,6,$4 /* E0 */ + or $1,$3,$1 /* .. E1 */ + or $1,$4,$17 /* E0 */ + br __constant_c_memset /* .. E1 */ + + .end __memsetw + #ifdef __ELF__ .weak memset; memset = __memset #else diff --git a/arch/alpha/lib/strcasecmp.c b/arch/alpha/lib/strcasecmp.c new file mode 100644 index 000000000..4e57a216f --- /dev/null +++ b/arch/alpha/lib/strcasecmp.c @@ -0,0 +1,26 @@ +/* + * linux/arch/alpha/lib/strcasecmp.c + */ + +#include + + +/* We handle nothing here except the C locale. Since this is used in + only one place, on strings known to contain only 7 bit ASCII, this + is ok. */ + +int strcasecmp(const char *a, const char *b) +{ + int ca, cb; + + do { + ca = *a++ & 0xff; + cb = *b++ & 0xff; + if (ca >= 'A' && ca <= 'Z') + ca += 'a' - 'A'; + if (cb >= 'A' && cb <= 'Z') + cb += 'a' - 'A'; + } while (ca == cb && ca != '\0'); + + return ca - cb; +} diff --git a/arch/alpha/lib/strlen_user.S b/arch/alpha/lib/strlen_user.S index b84d9a4c3..cdf71158f 100644 --- a/arch/alpha/lib/strlen_user.S +++ b/arch/alpha/lib/strlen_user.S @@ -2,7 +2,7 @@ * arch/alpha/lib/strlen_user.S * * Return the length of the string including the NUL terminator - * (strlen+1) or zero if an error occured. + * (strlen+1) or zero if an error occurred. */ #include -- cgit v1.2.3