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