1/* 2 * linux/arch/arm/lib/memset.S 3 * 4 * Copyright (C) 1995-2000 Russell King 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * ASM optimised string functions 11 */ 12#include "assembler.h" 13 14 .text 15 .align 5 16 17ENTRY(memset) 18 ands r3, r0, #3 @ 1 unaligned? 19 mov ip, r0 @ preserve r0 as return value 20 bne 6f @ 1 21/* 22 * we know that the pointer in ip is aligned to a word boundary. 23 */ 241: orr r1, r1, r1, lsl #8 25 orr r1, r1, r1, lsl #16 26 mov r3, r1 27 cmp r2, #16 28 blt 4f 29 30#if ! CALGN(1)+0 31 32/* 33 * We need 2 extra registers for this loop - use r8 and the LR 34 */ 35 stmfd sp!, {r8, lr} 36 mov r8, r1 37 mov lr, r1 38 392: subs r2, r2, #64 40 stmgeia ip!, {r1, r3, r8, lr} @ 64 bytes at a time. 41 stmgeia ip!, {r1, r3, r8, lr} 42 stmgeia ip!, {r1, r3, r8, lr} 43 stmgeia ip!, {r1, r3, r8, lr} 44 bgt 2b 45 ldmeqfd sp!, {r8, pc} @ Now <64 bytes to go. 46/* 47 * No need to correct the count; we're only testing bits from now on 48 */ 49 tst r2, #32 50 stmneia ip!, {r1, r3, r8, lr} 51 stmneia ip!, {r1, r3, r8, lr} 52 tst r2, #16 53 stmneia ip!, {r1, r3, r8, lr} 54 ldmfd sp!, {r8, lr} 55 56#else 57 58/* 59 * This version aligns the destination pointer in order to write 60 * whole cache lines at once. 61 */ 62 63 stmfd sp!, {r4-r8, lr} 64 mov r4, r1 65 mov r5, r1 66 mov r6, r1 67 mov r7, r1 68 mov r8, r1 69 mov lr, r1 70 71 cmp r2, #96 72 tstgt ip, #31 73 ble 3f 74 75 and r8, ip, #31 76 rsb r8, r8, #32 77 sub r2, r2, r8 78 movs r8, r8, lsl #(32 - 4) 79 stmcsia ip!, {r4, r5, r6, r7} 80 stmmiia ip!, {r4, r5} 81 tst r8, #(1 << 30) 82 mov r8, r1 83 strne r1, [ip], #4 84 853: subs r2, r2, #64 86 stmgeia ip!, {r1, r3-r8, lr} 87 stmgeia ip!, {r1, r3-r8, lr} 88 bgt 3b 89 ldmeqfd sp!, {r4-r8, pc} 90 91 tst r2, #32 92 stmneia ip!, {r1, r3-r8, lr} 93 tst r2, #16 94 stmneia ip!, {r4-r7} 95 ldmfd sp!, {r4-r8, lr} 96 97#endif 98 994: tst r2, #8 100 stmneia ip!, {r1, r3} 101 tst r2, #4 102 strne r1, [ip], #4 103/* 104 * When we get here, we've got less than 4 bytes to zero. We 105 * may have an unaligned pointer as well. 106 */ 1075: tst r2, #2 108 strneb r1, [ip], #1 109 strneb r1, [ip], #1 110 tst r2, #1 111 strneb r1, [ip], #1 112 mov pc, lr 113 1146: subs r2, r2, #4 @ 1 do we have enough 115 blt 5b @ 1 bytes to align with? 116 cmp r3, #2 @ 1 117 strltb r1, [ip], #1 @ 1 118 strleb r1, [ip], #1 @ 1 119 strb r1, [ip], #1 @ 1 120 add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) 121 b 1b 122ENDPROC(memset) 123