diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
commit | 19c9bba94152148523ba0f7ef7cffe3d45656b11 (patch) | |
tree | 40b1cb534496a7f1ca0f5c314a523c69f1fee464 /arch/sparc/lib/memset.S | |
parent | 7206675c40394c78a90e74812bbdbf8cf3cca1be (diff) |
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'arch/sparc/lib/memset.S')
-rw-r--r-- | arch/sparc/lib/memset.S | 151 |
1 files changed, 90 insertions, 61 deletions
diff --git a/arch/sparc/lib/memset.S b/arch/sparc/lib/memset.S index 95691debb..b8ca55e50 100644 --- a/arch/sparc/lib/memset.S +++ b/arch/sparc/lib/memset.S @@ -1,16 +1,37 @@ -/* linux/arch/sparc/lib/memset.S: Sparc optimized memset and bzero code - * Hand optimized from GNU libc's memset +/* linux/arch/sparc/lib/memset.S: Sparc optimized memset, bzero and clear_user code * Copyright (C) 1991,1996 Free Software Foundation - * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + * + * Returns 0, if ok, and number of bytes not yet set if exception + * occurs and we were called as clear_user. */ #include <asm/cprefix.h> #include <asm/ptrace.h> -#define HANDLE_UNALIGNED 1 - - /* Store 64 bytes at (BASE + OFFSET) using value SOURCE. */ +#define EX(x,y,a,b,z) \ +98: x,y; \ + .section .fixup,z##alloc,z##execinstr; \ + .align 4; \ +99: ba 30f; \ + a, b, %o0; \ + .section __ex_table,z##alloc; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4 + +#define EXT(start,end,handler,z) \ + .section __ex_table,z##alloc; \ + .align 4; \ + .word start, 0, end, handler; \ + .text; \ + .align 4 + +/* Please don't change these macros, unless you change the logic + * in the .fixup section below as well. + * Store 64 bytes at (BASE + OFFSET) using value SOURCE. */ #define ZERO_BIG_BLOCK(base, offset, source) \ std source, [base + offset + 0x00]; \ std source, [base + offset + 0x08]; \ @@ -34,7 +55,10 @@ .text .align 4 - .globl C_LABEL(__bzero), C_LABEL(__memset), C_LABEL(memset) + .globl C_LABEL(__bzero), C_LABEL(__memset), + .globl C_LABEL(memset) + .globl C_LABEL(__memset_start), C_LABEL(__memset_end) +C_LABEL(__memset_start): C_LABEL(__memset): C_LABEL(memset): and %o1, 0xff, %g3 @@ -44,123 +68,128 @@ C_LABEL(memset): or %g3, %g2, %g3 b 1f mov %o2, %o1 - -#if HANDLE_UNALIGNED -/* As this is highly unprobable, we optimize the other case (4 aligned) - * Define HANDLE_UNALIGNED to 0, if all the alignment work is done by - * the trap. Then we have to hope nobody will memset something unaligned - * with large counts, as this would lead to a lot of traps... - */ 3: cmp %o2, 3 be 2f - stb %g3, [%o0] + EX(stb %g3, [%o0], sub %o1, 0,#) cmp %o2, 2 be 2f - stb %g3, [%o0 + 0x01] + EX(stb %g3, [%o0 + 0x01], sub %o1, 1,#) - stb %g3, [%o0 + 0x02] + EX(stb %g3, [%o0 + 0x02], sub %o1, 2,#) 2: sub %o2, 4, %o2 add %o1, %o2, %o1 b 4f sub %o0, %o2, %o0 -#endif /* HANDLE_UNALIGNED */ - - .globl C_LABEL(__clear_user) -C_LABEL(__clear_user): - st %o0, [%g6 + THREAD_EX_ADDR] - ld [%g6 + THREAD_EX_COUNT], %g1 - set clear_user_failure, %g2 - add %g1, 1, %g1 - st %o7, [%g6 + THREAD_EX_PC] - st %g1, [%g6 + THREAD_EX_COUNT] - call C_LABEL(__bzero) - st %g2, [%g6 + THREAD_EX_EXPC] - -clear_user_success: - ldd [%g6 + THREAD_EX_COUNT], %g2 - mov 0, %o0 - sub %g2, 1, %g1 - jmpl %g3 + 0x8, %g0 - st %g1, [%g6 + THREAD_EX_COUNT] - -clear_user_failure: - jmpl %g3 + 0x8, %g0 - mov %g2, %o0 C_LABEL(__bzero): mov %g0, %g3 1: cmp %o1, 7 bleu 7f - mov %o0, %g1 + andcc %o0, 3, %o2 -#if HANDLE_UNALIGNED - andcc %o0, 3, %o2 bne 3b -#endif /* HANDLE_UNALIGNED */ 4: andcc %o0, 4, %g0 be 2f mov %g3, %g2 - st %g3, [%o0] + EX(st %g3, [%o0], sub %o1, 0,#) sub %o1, 4, %o1 add %o0, 4, %o0 2: andcc %o1, 0xffffff80, %o3 ! Now everything is 8 aligned and o1 is len to run be 9f andcc %o1, 0x78, %o2 -4: +10: ZERO_BIG_BLOCK(%o0, 0x00, %g2) subcc %o3, 128, %o3 ZERO_BIG_BLOCK(%o0, 0x40, %g2) - bne 4b +11: + EXT(10b, 11b, 20f,#) + bne 10b add %o0, 128, %o0 orcc %o2, %g0, %g0 9: - be 6f + be 13f andcc %o1, 7, %o1 srl %o2, 1, %o3 - set bzero_table + 64, %o4 + set 13f, %o4 sub %o4, %o3, %o4 jmp %o4 add %o0, %o2, %o0 -bzero_table: +12: ZERO_LAST_BLOCKS(%o0, 0x48, %g2) ZERO_LAST_BLOCKS(%o0, 0x08, %g2) - -6: +13: be 8f andcc %o1, 4, %g0 be 1f andcc %o1, 2, %g0 - st %g3, [%o0] + EX(st %g3, [%o0], and %o1, 7,#) add %o0, 4, %o0 1: be 1f andcc %o1, 1, %g0 - sth %g3, [%o0] + EX(sth %g3, [%o0], and %o1, 3,#) add %o0, 2, %o0 1: bne,a 8f - stb %g3, [%o0] + EX(stb %g3, [%o0], and %o1, 1,#) 8: retl - mov %g1,%o0 - -/* Don't care about alignment here. It is highly - * unprobable and at most two traps may happen - */ + clr %o0 7: - b 6b + be 13b orcc %o1, 0, %g0 + + be 0f +8: + add %o0, 1, %o0 + subcc %o1, 1, %o1 + bne,a 8b + EX(stb %g3, [%o0 - 1], add %o1, 1,#) +0: + retl + clr %o0 +C_LABEL(__memset_end): + + .section .fixup,#alloc,#execinstr + .align 4 +20: + cmp %g2, 8 + bleu 1f + and %o1, 0x7f, %o1 + sub %g2, 9, %g2 + add %o3, 64, %o3 +1: + sll %g2, 3, %g2 + add %o3, %o1, %o0 + b 30f + sub %o0, %g2, %o0 +21: + mov 8, %o0 + and %o1, 7, %o1 + sub %o0, %g2, %o0 + sll %o0, 3, %o0 + b 30f + add %o0, %o1, %o0 +30: +/* %o4 is faulting address, %o5 is %pc where fault occured */ + save %sp, -104, %sp + mov %i5, %o0 + mov %i7, %o1 + call C_LABEL(lookup_fault) + mov %i4, %o2 + ret + restore |