summaryrefslogtreecommitdiffstats
path: root/arch/alpha/lib
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-08-25 09:12:35 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-08-25 09:12:35 +0000
commitc7fc24dc4420057f103afe8fc64524ebc25c5d37 (patch)
tree3682407a599b8f9f03fc096298134cafba1c9b2f /arch/alpha/lib
parent1d793fade8b063fde3cf275bf1a5c2d381292cd9 (diff)
o Merge with Linux 2.1.116.
o New Newport console code. o New G364 console code.
Diffstat (limited to 'arch/alpha/lib')
-rw-r--r--arch/alpha/lib/Makefile2
-rw-r--r--arch/alpha/lib/io.c170
-rw-r--r--arch/alpha/lib/memset.S25
-rw-r--r--arch/alpha/lib/strcasecmp.c26
-rw-r--r--arch/alpha/lib/strlen_user.S2
5 files changed, 188 insertions, 37 deletions
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 <linux/kernel.h>
-
+#include <linux/types.h>
#include <asm/io.h>
-/*
- * 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 <linux/string.h>
+
+
+/* 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 <alpha/regdef.h>