diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /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')
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 |