1/* 2 * linux/arch/arm/lib/memzero.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#include "assembler.h" 11 12 .text 13 .align 5 14 .word 0 15/* 16 * Align the pointer in r0. r3 contains the number of bytes that we are 17 * mis-aligned by, and r1 is the number of bytes. If r1 < 4, then we 18 * don't bother; we use byte stores instead. 19 */ 201: subs r1, r1, #4 @ 1 do we have enough 21 blt 5f @ 1 bytes to align with? 22 cmp r3, #2 @ 1 23 strltb r2, [r0], #1 @ 1 24 strleb r2, [r0], #1 @ 1 25 strb r2, [r0], #1 @ 1 26 add r1, r1, r3 @ 1 (r1 = r1 - (4 - r3)) 27/* 28 * The pointer is now aligned and the length is adjusted. Try doing the 29 * memzero again. 30 */ 31 32ENTRY(__memzero) 33 mov r2, #0 @ 1 34 ands r3, r0, #3 @ 1 unaligned? 35 bne 1b @ 1 36/* 37 * r3 = 0, and we know that the pointer in r0 is aligned to a word boundary. 38 */ 39 cmp r1, #16 @ 1 we can skip this chunk if we 40 blt 4f @ 1 have < 16 bytes 41 42#if ! CALGN(1)+0 43 44/* 45 * We need an extra register for this loop - save the return address and 46 * use the LR 47 */ 48 str lr, [sp, #-4]! @ 1 49 mov ip, r2 @ 1 50 mov lr, r2 @ 1 51 523: subs r1, r1, #64 @ 1 write 32 bytes out per loop 53 stmgeia r0!, {r2, r3, ip, lr} @ 4 54 stmgeia r0!, {r2, r3, ip, lr} @ 4 55 stmgeia r0!, {r2, r3, ip, lr} @ 4 56 stmgeia r0!, {r2, r3, ip, lr} @ 4 57 bgt 3b @ 1 58 ldmeqfd sp!, {pc} @ 1/2 quick exit 59/* 60 * No need to correct the count; we're only testing bits from now on 61 */ 62 tst r1, #32 @ 1 63 stmneia r0!, {r2, r3, ip, lr} @ 4 64 stmneia r0!, {r2, r3, ip, lr} @ 4 65 tst r1, #16 @ 1 16 bytes or more? 66 stmneia r0!, {r2, r3, ip, lr} @ 4 67 ldr lr, [sp], #4 @ 1 68 69#else 70 71/* 72 * This version aligns the destination pointer in order to write 73 * whole cache lines at once. 74 */ 75 76 stmfd sp!, {r4-r7, lr} 77 mov r4, r2 78 mov r5, r2 79 mov r6, r2 80 mov r7, r2 81 mov ip, r2 82 mov lr, r2 83 84 cmp r1, #96 85 andgts ip, r0, #31 86 ble 3f 87 88 rsb ip, ip, #32 89 sub r1, r1, ip 90 movs ip, ip, lsl #(32 - 4) 91 stmcsia r0!, {r4, r5, r6, r7} 92 stmmiia r0!, {r4, r5} 93 movs ip, ip, lsl #2 94 strcs r2, [r0], #4 95 963: subs r1, r1, #64 97 stmgeia r0!, {r2-r7, ip, lr} 98 stmgeia r0!, {r2-r7, ip, lr} 99 bgt 3b 100 ldmeqfd sp!, {r4-r7, pc} 101 102 tst r1, #32 103 stmneia r0!, {r2-r7, ip, lr} 104 tst r1, #16 105 stmneia r0!, {r4-r7} 106 ldmfd sp!, {r4-r7, lr} 107 108#endif 109 1104: tst r1, #8 @ 1 8 bytes or more? 111 stmneia r0!, {r2, r3} @ 2 112 tst r1, #4 @ 1 4 bytes or more? 113 strne r2, [r0], #4 @ 1 114/* 115 * When we get here, we've got less than 4 bytes to zero. We 116 * may have an unaligned pointer as well. 117 */ 1185: tst r1, #2 @ 1 2 bytes or more? 119 strneb r2, [r0], #1 @ 1 120 strneb r2, [r0], #1 @ 1 121 tst r1, #1 @ 1 a byte left over 122 strneb r2, [r0], #1 @ 1 123 mov pc, lr @ 1 124ENDPROC(__memzero) 125