1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * linux/arch/arm/lib/memset.S 4 * 5 * Copyright (C) 1995-2000 Russell King 6 * 7 * ASM optimised string functions 8 */ 9#include <linux/linkage.h> 10#include <asm/assembler.h> 11 12 .text 13 .align 5 14 15 .syntax unified 16#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD) && !defined(MEMSET_NO_THUMB_BUILD) 17 .thumb 18 .thumb_func 19#endif 20ENTRY(memset) 21 ands r3, r0, #3 @ 1 unaligned? 22 mov ip, r0 @ preserve r0 as return value 23 bne 6f @ 1 24/* 25 * we know that the pointer in ip is aligned to a word boundary. 26 */ 271: orr r1, r1, r1, lsl #8 28 orr r1, r1, r1, lsl #16 29 mov r3, r1 30 cmp r2, #16 31 blt 4f 32 33#if ! CALGN(1)+0 34 35/* 36 * We need 2 extra registers for this loop - use r8 and the LR 37 */ 38 stmfd sp!, {r8, lr} 39 mov r8, r1 40 mov lr, r1 41 422: subs r2, r2, #64 43 stmiage ip!, {r1, r3, r8, lr} @ 64 bytes at a time. 44 stmiage ip!, {r1, r3, r8, lr} 45 stmiage ip!, {r1, r3, r8, lr} 46 stmiage ip!, {r1, r3, r8, lr} 47 bgt 2b 48 ldmfdeq sp!, {r8, pc} @ Now <64 bytes to go. 49/* 50 * No need to correct the count; we're only testing bits from now on 51 */ 52 tst r2, #32 53 stmiane ip!, {r1, r3, r8, lr} 54 stmiane ip!, {r1, r3, r8, lr} 55 tst r2, #16 56 stmiane ip!, {r1, r3, r8, lr} 57 ldmfd sp!, {r8, lr} 58 59#else 60 61/* 62 * This version aligns the destination pointer in order to write 63 * whole cache lines at once. 64 */ 65 66 stmfd sp!, {r4-r8, lr} 67 mov r4, r1 68 mov r5, r1 69 mov r6, r1 70 mov r7, r1 71 mov r8, r1 72 mov lr, r1 73 74 cmp r2, #96 75 tstgt ip, #31 76 ble 3f 77 78 and r8, ip, #31 79 rsb r8, r8, #32 80 sub r2, r2, r8 81 movs r8, r8, lsl #(32 - 4) 82 stmiacs ip!, {r4, r5, r6, r7} 83 stmiami ip!, {r4, r5} 84 tst r8, #(1 << 30) 85 mov r8, r1 86 strne r1, [ip], #4 87 883: subs r2, r2, #64 89 stmiage ip!, {r1, r3-r8, lr} 90 stmiage ip!, {r1, r3-r8, lr} 91 bgt 3b 92 ldmfdeq sp!, {r4-r8, pc} 93 94 tst r2, #32 95 stmiane ip!, {r1, r3-r8, lr} 96 tst r2, #16 97 stmiane ip!, {r4-r7} 98 ldmfd sp!, {r4-r8, lr} 99 100#endif 101 1024: tst r2, #8 103 stmiane ip!, {r1, r3} 104 tst r2, #4 105 strne r1, [ip], #4 106/* 107 * When we get here, we've got less than 4 bytes to zero. We 108 * may have an unaligned pointer as well. 109 */ 1105: tst r2, #2 111 strbne r1, [ip], #1 112 strbne r1, [ip], #1 113 tst r2, #1 114 strbne r1, [ip], #1 115 ret lr 116 1176: subs r2, r2, #4 @ 1 do we have enough 118 blt 5b @ 1 bytes to align with? 119 cmp r3, #2 @ 1 120 strblt r1, [ip], #1 @ 1 121 strble r1, [ip], #1 @ 1 122 strb r1, [ip], #1 @ 1 123 add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) 124 b 1b 125ENDPROC(memset) 126