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