aboutsummaryrefslogtreecommitdiff
path: root/arch/alpha/lib
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/alpha/lib
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/alpha/lib')
-rw-r--r--arch/alpha/lib/Makefile58
-rw-r--r--arch/alpha/lib/callback_srm.S104
-rw-r--r--arch/alpha/lib/checksum.c186
-rw-r--r--arch/alpha/lib/clear_page.S39
-rw-r--r--arch/alpha/lib/clear_user.S113
-rw-r--r--arch/alpha/lib/copy_page.S49
-rw-r--r--arch/alpha/lib/copy_user.S145
-rw-r--r--arch/alpha/lib/csum_ipv6_magic.S92
-rw-r--r--arch/alpha/lib/csum_partial_copy.c391
-rw-r--r--arch/alpha/lib/dbg_current.S29
-rw-r--r--arch/alpha/lib/dbg_stackcheck.S27
-rw-r--r--arch/alpha/lib/dbg_stackkill.S35
-rw-r--r--arch/alpha/lib/dec_and_lock.c42
-rw-r--r--arch/alpha/lib/divide.S195
-rw-r--r--arch/alpha/lib/ev6-clear_page.S54
-rw-r--r--arch/alpha/lib/ev6-clear_user.S225
-rw-r--r--arch/alpha/lib/ev6-copy_page.S203
-rw-r--r--arch/alpha/lib/ev6-copy_user.S259
-rw-r--r--arch/alpha/lib/ev6-csum_ipv6_magic.S126
-rw-r--r--arch/alpha/lib/ev6-divide.S259
-rw-r--r--arch/alpha/lib/ev6-memchr.S191
-rw-r--r--arch/alpha/lib/ev6-memcpy.S248
-rw-r--r--arch/alpha/lib/ev6-memset.S597
-rw-r--r--arch/alpha/lib/ev6-strncpy_from_user.S424
-rw-r--r--arch/alpha/lib/ev6-stxcpy.S321
-rw-r--r--arch/alpha/lib/ev6-stxncpy.S397
-rw-r--r--arch/alpha/lib/ev67-strcat.S54
-rw-r--r--arch/alpha/lib/ev67-strchr.S88
-rw-r--r--arch/alpha/lib/ev67-strlen.S49
-rw-r--r--arch/alpha/lib/ev67-strlen_user.S107
-rw-r--r--arch/alpha/lib/ev67-strncat.S94
-rw-r--r--arch/alpha/lib/ev67-strrchr.S109
-rw-r--r--arch/alpha/lib/fpreg.c193
-rw-r--r--arch/alpha/lib/memchr.S164
-rw-r--r--arch/alpha/lib/memcpy.c163
-rw-r--r--arch/alpha/lib/memmove.S181
-rw-r--r--arch/alpha/lib/memset.S124
-rw-r--r--arch/alpha/lib/srm_printk.c41
-rw-r--r--arch/alpha/lib/srm_puts.c23
-rw-r--r--arch/alpha/lib/stacktrace.c103
-rw-r--r--arch/alpha/lib/strcasecmp.c26
-rw-r--r--arch/alpha/lib/strcat.S52
-rw-r--r--arch/alpha/lib/strchr.S70
-rw-r--r--arch/alpha/lib/strcpy.S23
-rw-r--r--arch/alpha/lib/strlen.S57
-rw-r--r--arch/alpha/lib/strlen_user.S91
-rw-r--r--arch/alpha/lib/strncat.S84
-rw-r--r--arch/alpha/lib/strncpy.S81
-rw-r--r--arch/alpha/lib/strncpy_from_user.S339
-rw-r--r--arch/alpha/lib/strrchr.S87
-rw-r--r--arch/alpha/lib/stxcpy.S289
-rw-r--r--arch/alpha/lib/stxncpy.S345
-rw-r--r--arch/alpha/lib/udelay.c55
53 files changed, 7901 insertions, 0 deletions
diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile
new file mode 100644
index 00000000000..21cf624d732
--- /dev/null
+++ b/arch/alpha/lib/Makefile
@@ -0,0 +1,58 @@
+#
+# Makefile for alpha-specific library files..
+#
+
+EXTRA_AFLAGS := $(CFLAGS)
+EXTRA_CFLAGS := -Werror
+
+# Many of these routines have implementations tuned for ev6.
+# Choose them iff we're targeting ev6 specifically.
+ev6-$(CONFIG_ALPHA_EV6) := ev6-
+
+# Several make use of the cttz instruction introduced in ev67.
+ev67-$(CONFIG_ALPHA_EV67) := ev67-
+
+lib-y = __divqu.o __remqu.o __divlu.o __remlu.o \
+ udelay.o \
+ $(ev6-y)memset.o \
+ $(ev6-y)memcpy.o \
+ memmove.o \
+ checksum.o \
+ csum_partial_copy.o \
+ $(ev67-y)strlen.o \
+ $(ev67-y)strcat.o \
+ strcpy.o \
+ $(ev67-y)strncat.o \
+ strncpy.o \
+ $(ev6-y)stxcpy.o \
+ $(ev6-y)stxncpy.o \
+ $(ev67-y)strchr.o \
+ $(ev67-y)strrchr.o \
+ $(ev6-y)memchr.o \
+ $(ev6-y)copy_user.o \
+ $(ev6-y)clear_user.o \
+ $(ev6-y)strncpy_from_user.o \
+ $(ev67-y)strlen_user.o \
+ $(ev6-y)csum_ipv6_magic.o \
+ $(ev6-y)clear_page.o \
+ $(ev6-y)copy_page.o \
+ strcasecmp.o \
+ fpreg.o \
+ callback_srm.o srm_puts.o srm_printk.o
+
+lib-$(CONFIG_SMP) += dec_and_lock.o
+
+# The division routines are built from single source, with different defines.
+AFLAGS___divqu.o = -DDIV
+AFLAGS___remqu.o = -DREM
+AFLAGS___divlu.o = -DDIV -DINTSIZE
+AFLAGS___remlu.o = -DREM -DINTSIZE
+
+$(obj)/__divqu.o: $(obj)/$(ev6-y)divide.S
+ $(cmd_as_o_S)
+$(obj)/__remqu.o: $(obj)/$(ev6-y)divide.S
+ $(cmd_as_o_S)
+$(obj)/__divlu.o: $(obj)/$(ev6-y)divide.S
+ $(cmd_as_o_S)
+$(obj)/__remlu.o: $(obj)/$(ev6-y)divide.S
+ $(cmd_as_o_S)
diff --git a/arch/alpha/lib/callback_srm.S b/arch/alpha/lib/callback_srm.S
new file mode 100644
index 00000000000..0528acd0d9a
--- /dev/null
+++ b/arch/alpha/lib/callback_srm.S
@@ -0,0 +1,104 @@
+/*
+ * arch/alpha/lib/callback_srm.S
+ */
+
+#include <linux/config.h>
+#include <asm/console.h>
+
+.text
+#define HWRPB_CRB_OFFSET 0xc0
+
+#if defined(CONFIG_ALPHA_SRM) || defined(CONFIG_ALPHA_GENERIC)
+.align 4
+srm_dispatch:
+#if defined(CONFIG_ALPHA_GENERIC)
+ ldl $4,alpha_using_srm
+ beq $4,nosrm
+#endif
+ ldq $0,hwrpb # gp is set up by CALLBACK macro.
+ ldl $25,0($25) # Pick up the wrapper data.
+ mov $20,$21 # Shift arguments right.
+ mov $19,$20
+ ldq $1,HWRPB_CRB_OFFSET($0)
+ mov $18,$19
+ mov $17,$18
+ mov $16,$17
+ addq $0,$1,$2 # CRB address
+ ldq $27,0($2) # DISPATCH procedure descriptor (VMS call std)
+ extwl $25,0,$16 # SRM callback function code
+ ldq $3,8($27) # call address
+ extwl $25,2,$25 # argument information (VMS calling std)
+ jmp ($3) # Return directly to caller of wrapper.
+
+.align 4
+.globl srm_fixup
+.ent srm_fixup
+srm_fixup:
+ ldgp $29,0($27)
+#if defined(CONFIG_ALPHA_GENERIC)
+ ldl $4,alpha_using_srm
+ beq $4,nosrm
+#endif
+ ldq $0,hwrpb
+ ldq $1,HWRPB_CRB_OFFSET($0)
+ addq $0,$1,$2 # CRB address
+ ldq $27,16($2) # VA of FIXUP procedure descriptor
+ ldq $3,8($27) # call address
+ lda $25,2($31) # two integer arguments
+ jmp ($3) # Return directly to caller of srm_fixup.
+.end srm_fixup
+
+#if defined(CONFIG_ALPHA_GENERIC)
+.align 3
+nosrm:
+ lda $0,-1($31)
+ ret
+#endif
+
+#define CALLBACK(NAME, CODE, ARG_CNT) \
+.align 4; .globl callback_##NAME; .ent callback_##NAME; callback_##NAME##: \
+ldgp $29,0($27); br $25,srm_dispatch; .word CODE, ARG_CNT; .end callback_##NAME
+
+#else /* defined(CONFIG_ALPHA_SRM) || defined(CONFIG_ALPHA_GENERIC) */
+
+#define CALLBACK(NAME, CODE, ARG_CNT) \
+.align 3; .globl callback_##NAME; .ent callback_##NAME; callback_##NAME##: \
+lda $0,-1($31); ret; .end callback_##NAME
+
+.align 3
+.globl srm_fixup
+.ent srm_fixup
+srm_fixup:
+ lda $0,-1($31)
+ ret
+.end srm_fixup
+#endif /* defined(CONFIG_ALPHA_SRM) || defined(CONFIG_ALPHA_GENERIC) */
+
+CALLBACK(puts, CCB_PUTS, 4)
+CALLBACK(open, CCB_OPEN, 3)
+CALLBACK(close, CCB_CLOSE, 2)
+CALLBACK(read, CCB_READ, 5)
+CALLBACK(open_console, CCB_OPEN_CONSOLE, 1)
+CALLBACK(close_console, CCB_CLOSE_CONSOLE, 1)
+CALLBACK(getenv, CCB_GET_ENV, 4)
+CALLBACK(setenv, CCB_SET_ENV, 4)
+CALLBACK(getc, CCB_GETC, 2)
+CALLBACK(reset_term, CCB_RESET_TERM, 2)
+CALLBACK(term_int, CCB_SET_TERM_INT, 3)
+CALLBACK(term_ctl, CCB_SET_TERM_CTL, 3)
+CALLBACK(process_keycode, CCB_PROCESS_KEYCODE, 3)
+CALLBACK(ioctl, CCB_IOCTL, 6)
+CALLBACK(write, CCB_WRITE, 5)
+CALLBACK(reset_env, CCB_RESET_ENV, 4)
+CALLBACK(save_env, CCB_SAVE_ENV, 1)
+CALLBACK(pswitch, CCB_PSWITCH, 3)
+CALLBACK(bios_emul, CCB_BIOS_EMUL, 5)
+
+.data
+__alpha_using_srm: # For use by bootpheader
+ .long 7 # value is not 1 for link debugging
+ .weak alpha_using_srm; alpha_using_srm = __alpha_using_srm
+__callback_init_done: # For use by bootpheader
+ .long 7 # value is not 1 for link debugging
+ .weak callback_init_done; callback_init_done = __callback_init_done
+
diff --git a/arch/alpha/lib/checksum.c b/arch/alpha/lib/checksum.c
new file mode 100644
index 00000000000..89044e6385f
--- /dev/null
+++ b/arch/alpha/lib/checksum.c
@@ -0,0 +1,186 @@
+/*
+ * arch/alpha/lib/checksum.c
+ *
+ * This file contains network checksum routines that are better done
+ * in an architecture-specific manner due to speed..
+ * Comments in other versions indicate that the algorithms are from RFC1071
+ *
+ * accellerated versions (and 21264 assembly versions ) contributed by
+ * Rick Gorton <rick.gorton@alpha-processor.com>
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <asm/byteorder.h>
+
+static inline unsigned short from64to16(unsigned long x)
+{
+ /* Using extract instructions is a bit more efficient
+ than the original shift/bitmask version. */
+
+ union {
+ unsigned long ul;
+ unsigned int ui[2];
+ unsigned short us[4];
+ } in_v, tmp_v, out_v;
+
+ in_v.ul = x;
+ tmp_v.ul = (unsigned long) in_v.ui[0] + (unsigned long) in_v.ui[1];
+
+ /* Since the bits of tmp_v.sh[3] are going to always be zero,
+ we don't have to bother to add that in. */
+ out_v.ul = (unsigned long) tmp_v.us[0] + (unsigned long) tmp_v.us[1]
+ + (unsigned long) tmp_v.us[2];
+
+ /* Similarly, out_v.us[2] is always zero for the final add. */
+ return out_v.us[0] + out_v.us[1];
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented.
+ */
+unsigned short int csum_tcpudp_magic(unsigned long saddr,
+ unsigned long daddr,
+ unsigned short len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ return ~from64to16(saddr + daddr + sum +
+ ((unsigned long) ntohs(len) << 16) +
+ ((unsigned long) proto << 8));
+}
+
+unsigned int csum_tcpudp_nofold(unsigned long saddr,
+ unsigned long daddr,
+ unsigned short len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ unsigned long result;
+
+ result = (saddr + daddr + sum +
+ ((unsigned long) ntohs(len) << 16) +
+ ((unsigned long) proto << 8));
+
+ /* Fold down to 32-bits so we don't lose in the typedef-less
+ network stack. */
+ /* 64 to 33 */
+ result = (result & 0xffffffff) + (result >> 32);
+ /* 33 to 32 */
+ result = (result & 0xffffffff) + (result >> 32);
+ return result;
+}
+
+/*
+ * Do a 64-bit checksum on an arbitrary memory area..
+ *
+ * This isn't a great routine, but it's not _horrible_ either. The
+ * inner loop could be unrolled a bit further, and there are better
+ * ways to do the carry, but this is reasonable.
+ */
+static inline unsigned long do_csum(const unsigned char * buff, int len)
+{
+ int odd, count;
+ unsigned long result = 0;
+
+ if (len <= 0)
+ goto out;
+ odd = 1 & (unsigned long) buff;
+ if (odd) {
+ result = *buff << 8;
+ len--;
+ buff++;
+ }
+ count = len >> 1; /* nr of 16-bit words.. */
+ if (count) {
+ if (2 & (unsigned long) buff) {
+ result += *(unsigned short *) buff;
+ count--;
+ len -= 2;
+ buff += 2;
+ }
+ count >>= 1; /* nr of 32-bit words.. */
+ if (count) {
+ if (4 & (unsigned long) buff) {
+ result += *(unsigned int *) buff;
+ count--;
+ len -= 4;
+ buff += 4;
+ }
+ count >>= 1; /* nr of 64-bit words.. */
+ if (count) {
+ unsigned long carry = 0;
+ do {
+ unsigned long w = *(unsigned long *) buff;
+ count--;
+ buff += 8;
+ result += carry;
+ result += w;
+ carry = (w > result);
+ } while (count);
+ result += carry;
+ result = (result & 0xffffffff) + (result >> 32);
+ }
+ if (len & 4) {
+ result += *(unsigned int *) buff;
+ buff += 4;
+ }
+ }
+ if (len & 2) {
+ result += *(unsigned short *) buff;
+ buff += 2;
+ }
+ }
+ if (len & 1)
+ result += *buff;
+ result = from64to16(result);
+ if (odd)
+ result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
+out:
+ return result;
+}
+
+/*
+ * This is a version of ip_compute_csum() optimized for IP headers,
+ * which always checksum on 4 octet boundaries.
+ */
+unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
+{
+ return ~do_csum(iph,ihl*4);
+}
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+{
+ unsigned long result = do_csum(buff, len);
+
+ /* add in old sum, and carry.. */
+ result += sum;
+ /* 32+c bits -> 32 bits */
+ result = (result & 0xffffffff) + (result >> 32);
+ return result;
+}
+
+EXPORT_SYMBOL(csum_partial);
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+unsigned short ip_compute_csum(unsigned char * buff, int len)
+{
+ return ~from64to16(do_csum(buff,len));
+}
diff --git a/arch/alpha/lib/clear_page.S b/arch/alpha/lib/clear_page.S
new file mode 100644
index 00000000000..a221ae266e2
--- /dev/null
+++ b/arch/alpha/lib/clear_page.S
@@ -0,0 +1,39 @@
+/*
+ * arch/alpha/lib/clear_page.S
+ *
+ * Zero an entire page.
+ */
+
+ .text
+ .align 4
+ .global clear_page
+ .ent clear_page
+clear_page:
+ .prologue 0
+
+ lda $0,128
+ nop
+ unop
+ nop
+
+1: stq $31,0($16)
+ stq $31,8($16)
+ stq $31,16($16)
+ stq $31,24($16)
+
+ stq $31,32($16)
+ stq $31,40($16)
+ stq $31,48($16)
+ subq $0,1,$0
+
+ stq $31,56($16)
+ addq $16,64,$16
+ unop
+ bne $0,1b
+
+ ret
+ nop
+ unop
+ nop
+
+ .end clear_page
diff --git a/arch/alpha/lib/clear_user.S b/arch/alpha/lib/clear_user.S
new file mode 100644
index 00000000000..8860316c195
--- /dev/null
+++ b/arch/alpha/lib/clear_user.S
@@ -0,0 +1,113 @@
+/*
+ * arch/alpha/lib/clear_user.S
+ * Contributed by Richard Henderson <rth@tamu.edu>
+ *
+ * Zero user space, handling exceptions as we go.
+ *
+ * We have to make sure that $0 is always up-to-date and contains the
+ * right "bytes left to zero" value (and that it is updated only _after_
+ * a successful copy). There is also some rather minor exception setup
+ * stuff.
+ *
+ * NOTE! This is not directly C-callable, because the calling semantics
+ * are different:
+ *
+ * Inputs:
+ * length in $0
+ * destination address in $6
+ * exception pointer in $7
+ * return address in $28 (exceptions expect it there)
+ *
+ * Outputs:
+ * bytes left to copy in $0
+ *
+ * Clobbers:
+ * $1,$2,$3,$4,$5,$6
+ */
+
+/* Allow an exception for an insn; exit if we get one. */
+#define EX(x,y...) \
+ 99: x,##y; \
+ .section __ex_table,"a"; \
+ .long 99b - .; \
+ lda $31, $exception-99b($31); \
+ .previous
+
+ .set noat
+ .set noreorder
+ .align 4
+
+ .globl __do_clear_user
+ .ent __do_clear_user
+ .frame $30, 0, $28
+ .prologue 0
+
+$loop:
+ and $1, 3, $4 # e0 :
+ beq $4, 1f # .. e1 :
+
+0: EX( stq_u $31, 0($6) ) # e0 : zero one word
+ subq $0, 8, $0 # .. e1 :
+ subq $4, 1, $4 # e0 :
+ addq $6, 8, $6 # .. e1 :
+ bne $4, 0b # e1 :
+ unop # :
+
+1: bic $1, 3, $1 # e0 :
+ beq $1, $tail # .. e1 :
+
+2: EX( stq_u $31, 0($6) ) # e0 : zero four words
+ subq $0, 8, $0 # .. e1 :
+ EX( stq_u $31, 8($6) ) # e0 :
+ subq $0, 8, $0 # .. e1 :
+ EX( stq_u $31, 16($6) ) # e0 :
+ subq $0, 8, $0 # .. e1 :
+ EX( stq_u $31, 24($6) ) # e0 :
+ subq $0, 8, $0 # .. e1 :
+ subq $1, 4, $1 # e0 :
+ addq $6, 32, $6 # .. e1 :
+ bne $1, 2b # e1 :
+
+$tail:
+ bne $2, 1f # e1 : is there a tail to do?
+ ret $31, ($28), 1 # .. e1 :
+
+1: EX( ldq_u $5, 0($6) ) # e0 :
+ clr $0 # .. e1 :
+ nop # e1 :
+ mskqh $5, $0, $5 # e0 :
+ EX( stq_u $5, 0($6) ) # e0 :
+ ret $31, ($28), 1 # .. e1 :
+
+__do_clear_user:
+ and $6, 7, $4 # e0 : find dest misalignment
+ beq $0, $zerolength # .. e1 :
+ addq $0, $4, $1 # e0 : bias counter
+ and $1, 7, $2 # e1 : number of bytes in tail
+ srl $1, 3, $1 # e0 :
+ beq $4, $loop # .. e1 :
+
+ EX( ldq_u $5, 0($6) ) # e0 : load dst word to mask back in
+ beq $1, $oneword # .. e1 : sub-word store?
+
+ mskql $5, $6, $5 # e0 : take care of misaligned head
+ addq $6, 8, $6 # .. e1 :
+ EX( stq_u $5, -8($6) ) # e0 :
+ addq $0, $4, $0 # .. e1 : bytes left -= 8 - misalignment
+ subq $1, 1, $1 # e0 :
+ subq $0, 8, $0 # .. e1 :
+ br $loop # e1 :
+ unop # :
+
+$oneword:
+ mskql $5, $6, $4 # e0 :
+ mskqh $5, $2, $5 # e0 :
+ or $5, $4, $5 # e1 :
+ EX( stq_u $5, 0($6) ) # e0 :
+ clr $0 # .. e1 :
+
+$zerolength:
+$exception:
+ ret $31, ($28), 1 # .. e1 :
+
+ .end __do_clear_user
diff --git a/arch/alpha/lib/copy_page.S b/arch/alpha/lib/copy_page.S
new file mode 100644
index 00000000000..9f3b97459cc
--- /dev/null
+++ b/arch/alpha/lib/copy_page.S
@@ -0,0 +1,49 @@
+/*
+ * arch/alpha/lib/copy_page.S
+ *
+ * Copy an entire page.
+ */
+
+ .text
+ .align 4
+ .global copy_page
+ .ent copy_page
+copy_page:
+ .prologue 0
+
+ lda $18,128
+ nop
+ unop
+ nop
+
+1: ldq $0,0($17)
+ ldq $1,8($17)
+ ldq $2,16($17)
+ ldq $3,24($17)
+
+ ldq $4,32($17)
+ ldq $5,40($17)
+ ldq $6,48($17)
+ ldq $7,56($17)
+
+ stq $0,0($16)
+ subq $18,1,$18
+ stq $1,8($16)
+ addq $17,64,$17
+
+ stq $2,16($16)
+ stq $3,24($16)
+ stq $4,32($16)
+ stq $5,40($16)
+
+ stq $6,48($16)
+ stq $7,56($16)
+ addq $16,64,$16
+ bne $18, 1b
+
+ ret
+ nop
+ unop
+ nop
+
+ .end copy_page
diff --git a/arch/alpha/lib/copy_user.S b/arch/alpha/lib/copy_user.S
new file mode 100644
index 00000000000..6f3fab9eb43
--- /dev/null
+++ b/arch/alpha/lib/copy_user.S
@@ -0,0 +1,145 @@
+/*
+ * arch/alpha/lib/copy_user.S
+ *
+ * Copy to/from user space, handling exceptions as we go.. This
+ * isn't exactly pretty.
+ *
+ * This is essentially the same as "memcpy()", but with a few twists.
+ * Notably, we have to make sure that $0 is always up-to-date and
+ * contains the right "bytes left to copy" value (and that it is updated
+ * only _after_ a successful copy). There is also some rather minor
+ * exception setup stuff..
+ *
+ * NOTE! This is not directly C-callable, because the calling semantics are
+ * different:
+ *
+ * Inputs:
+ * length in $0
+ * destination address in $6
+ * source address in $7
+ * return address in $28
+ *
+ * Outputs:
+ * bytes left to copy in $0
+ *
+ * Clobbers:
+ * $1,$2,$3,$4,$5,$6,$7
+ */
+
+/* Allow an exception for an insn; exit if we get one. */
+#define EXI(x,y...) \
+ 99: x,##y; \
+ .section __ex_table,"a"; \
+ .long 99b - .; \
+ lda $31, $exitin-99b($31); \
+ .previous
+
+#define EXO(x,y...) \
+ 99: x,##y; \
+ .section __ex_table,"a"; \
+ .long 99b - .; \
+ lda $31, $exitout-99b($31); \
+ .previous
+
+ .set noat
+ .align 4
+ .globl __copy_user
+ .ent __copy_user
+__copy_user:
+ .prologue 0
+ and $6,7,$3
+ beq $0,$35
+ beq $3,$36
+ subq $3,8,$3
+ .align 4
+$37:
+ EXI( ldq_u $1,0($7) )
+ EXO( ldq_u $2,0($6) )
+ extbl $1,$7,$1
+ mskbl $2,$6,$2
+ insbl $1,$6,$1
+ addq $3,1,$3
+ bis $1,$2,$1
+ EXO( stq_u $1,0($6) )
+ subq $0,1,$0
+ addq $6,1,$6
+ addq $7,1,$7
+ beq $0,$41
+ bne $3,$37
+$36:
+ and $7,7,$1
+ bic $0,7,$4
+ beq $1,$43
+ beq $4,$48
+ EXI( ldq_u $3,0($7) )
+ .align 4
+$50:
+ EXI( ldq_u $2,8($7) )
+ subq $4,8,$4
+ extql $3,$7,$3
+ extqh $2,$7,$1
+ bis $3,$1,$1
+ EXO( stq $1,0($6) )
+ addq $7,8,$7
+ subq $0,8,$0
+ addq $6,8,$6
+ bis $2,$2,$3
+ bne $4,$50
+$48:
+ beq $0,$41
+ .align 4
+$57:
+ EXI( ldq_u $1,0($7) )
+ EXO( ldq_u $2,0($6) )
+ extbl $1,$7,$1
+ mskbl $2,$6,$2
+ insbl $1,$6,$1
+ bis $1,$2,$1
+ EXO( stq_u $1,0($6) )
+ subq $0,1,$0
+ addq $6,1,$6
+ addq $7,1,$7
+ bne $0,$57
+ br $31,$41
+ .align 4
+$43:
+ beq $4,$65
+ .align 4
+$66:
+ EXI( ldq $1,0($7) )
+ subq $4,8,$4
+ EXO( stq $1,0($6) )
+ addq $7,8,$7
+ subq $0,8,$0
+ addq $6,8,$6
+ bne $4,$66
+$65:
+ beq $0,$41
+ EXI( ldq $2,0($7) )
+ EXO( ldq $1,0($6) )
+ mskql $2,$0,$2
+ mskqh $1,$0,$1
+ bis $2,$1,$2
+ EXO( stq $2,0($6) )
+ bis $31,$31,$0
+$41:
+$35:
+$exitout:
+ ret $31,($28),1
+
+$exitin:
+ /* A stupid byte-by-byte zeroing of the rest of the output
+ buffer. This cures security holes by never leaving
+ random kernel data around to be copied elsewhere. */
+
+ mov $0,$1
+$101:
+ EXO ( ldq_u $2,0($6) )
+ subq $1,1,$1
+ mskbl $2,$6,$2
+ EXO ( stq_u $2,0($6) )
+ addq $6,1,$6
+ bgt $1,$101
+ ret $31,($28),1
+
+ .end __copy_user
diff --git a/arch/alpha/lib/csum_ipv6_magic.S b/arch/alpha/lib/csum_ipv6_magic.S
new file mode 100644
index 00000000000..e09748dbf2e
--- /dev/null
+++ b/arch/alpha/lib/csum_ipv6_magic.S
@@ -0,0 +1,92 @@
+/*
+ * arch/alpha/lib/csum_ipv6_magic.S
+ * Contributed by Richard Henderson <rth@tamu.edu>
+ *
+ * unsigned short csum_ipv6_magic(struct in6_addr *saddr,
+ * struct in6_addr *daddr,
+ * __u32 len,
+ * unsigned short proto,
+ * unsigned int csum);
+ */
+
+ .globl csum_ipv6_magic
+ .align 4
+ .ent csum_ipv6_magic
+ .frame $30,0,$26,0
+csum_ipv6_magic:
+ .prologue 0
+
+ ldq $0,0($16) # e0 : load src & dst addr words
+ zapnot $20,15,$20 # .. e1 : zero extend incoming csum
+ extqh $18,1,$4 # e0 : byte swap len & proto while we wait
+ ldq $1,8($16) # .. e1 :
+
+ extbl $18,1,$5 # e0 :
+ ldq $2,0($17) # .. e1 :
+ extbl $18,2,$6 # e0 :
+ ldq $3,8($17) # .. e1 :
+
+ extbl $18,3,$18 # e0 :
+ sra $4,32,$4 # e0 :
+ sll $5,16,$5 # e0 :
+ addq $20,$0,$20 # .. e1 : begin summing the words
+
+ sll $6,8,$6 # e0 :
+ cmpult $20,$0,$0 # .. e1 :
+ extwh $19,7,$7 # e0 :
+ or $4,$18,$18 # .. e1 :
+
+ extbl $19,1,$19 # e0 :
+ or $5,$6,$5 # .. e1 :
+ or $18,$5,$18 # e0 : len complete
+ or $19,$7,$19 # .. e1 :
+
+ sll $19,48,$19 # e0 :
+ addq $20,$1,$20 # .. e1 :
+ sra $19,32,$19 # e0 : proto complete
+ cmpult $20,$1,$1 # .. e1 :
+
+ nop # e0