^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/copy_template.s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Code template for optimized memory copy functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author: Nicolas Pitre
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Created: Sep 28, 2005
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright: MontaVista Software, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Theory of operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * -------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * This file provides the core code for a forward memory copy used in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * the implementation of memcopy(), copy_to_user() and copy_from_user().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * The including file must define the following accessor macros
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * according to the need of the given function:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * ldr1w ptr reg abort
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * This loads one word from 'ptr', stores it in 'reg' and increments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * 'ptr' to the next word. The 'abort' argument is used for fixup tables.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * ldr4w ptr reg1 reg2 reg3 reg4 abort
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * ldr8w ptr, reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * This loads four or eight words starting from 'ptr', stores them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * in provided registers and increments 'ptr' past those words.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * The'abort' argument is used for fixup tables.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * ldr1b ptr reg cond abort
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * Similar to ldr1w, but it loads a byte and increments 'ptr' one byte.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * It also must apply the condition code if provided, otherwise the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * "al" condition is assumed by default.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * str1w ptr reg abort
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * str1b ptr reg cond abort
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * Same as their ldr* counterparts, but data is stored to 'ptr' location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * rather than being loaded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * enter reg1 reg2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * Preserve the provided registers on the stack plus any additional
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * data as needed by the implementation including this code. Called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * upon code entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * usave reg1 reg2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * Unwind annotation macro is corresponding for 'enter' macro.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * It tell unwinder that preserved some provided registers on the stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * and additional data by a prior 'enter' macro.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * exit reg1 reg2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * Restore registers with the values previously saved with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * 'preserv' macro. Called upon code termination.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * LDR1W_SHIFT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * STR1W_SHIFT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * Correction to be applied to the "ip" register when branching into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * the ldr1w or str1w instructions (some of these macros may expand to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * than one 32bit instruction in Thumb-2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) UNWIND( .fnstart )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) enter r4, lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) UNWIND( .fnend )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) UNWIND( .fnstart )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) usave r4, lr @ in first stmdb block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) subs r2, r2, #4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) blt 8f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) ands ip, r0, #3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) PLD( pld [r1, #0] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) bne 9f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) ands ip, r1, #3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) bne 10f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) 1: subs r2, r2, #(28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) stmfd sp!, {r5 - r8}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) UNWIND( .fnend )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) UNWIND( .fnstart )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) usave r4, lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) UNWIND( .save {r5 - r8} ) @ in second stmfd block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) blt 5f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) CALGN( ands ip, r0, #31 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) CALGN( rsb r3, ip, #32 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) CALGN( sbcsne r4, r3, r2 ) @ C is always set here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) CALGN( bcs 2f )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) CALGN( adr r4, 6f )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) CALGN( subs r2, r2, r3 ) @ C gets set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) CALGN( add pc, r4, ip )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) PLD( pld [r1, #0] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 2: PLD( subs r2, r2, #96 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) PLD( pld [r1, #28] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) PLD( blt 4f )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) PLD( pld [r1, #60] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) PLD( pld [r1, #92] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 3: PLD( pld [r1, #124] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 4: ldr8w r1, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) subs r2, r2, #32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) str8w r0, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) bge 3b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) PLD( cmn r2, #96 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) PLD( bge 4b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 5: ands ip, r2, #28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) rsb ip, ip, #32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #if LDR1W_SHIFT > 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) lsl ip, ip, #LDR1W_SHIFT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) addne pc, pc, ip @ C is always clear here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) b 7f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .rept (1 << LDR1W_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) W(nop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .endr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) ldr1w r1, r3, abort=20f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) ldr1w r1, r4, abort=20f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) ldr1w r1, r5, abort=20f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ldr1w r1, r6, abort=20f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) ldr1w r1, r7, abort=20f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) ldr1w r1, r8, abort=20f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ldr1w r1, lr, abort=20f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #if LDR1W_SHIFT < STR1W_SHIFT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) lsl ip, ip, #STR1W_SHIFT - LDR1W_SHIFT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #elif LDR1W_SHIFT > STR1W_SHIFT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) lsr ip, ip, #LDR1W_SHIFT - STR1W_SHIFT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) add pc, pc, ip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .rept (1 << STR1W_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) W(nop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .endr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) str1w r0, r3, abort=20f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) str1w r0, r4, abort=20f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) str1w r0, r5, abort=20f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) str1w r0, r6, abort=20f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) str1w r0, r7, abort=20f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) str1w r0, r8, abort=20f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) str1w r0, lr, abort=20f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) CALGN( bcs 2b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 7: ldmfd sp!, {r5 - r8}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) UNWIND( .fnend ) @ end of second stmfd block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) UNWIND( .fnstart )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) usave r4, lr @ still in first stmdb block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 8: movs r2, r2, lsl #31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) ldr1b r1, r3, ne, abort=21f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ldr1b r1, r4, cs, abort=21f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) ldr1b r1, ip, cs, abort=21f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) str1b r0, r3, ne, abort=21f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) str1b r0, r4, cs, abort=21f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) str1b r0, ip, cs, abort=21f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) exit r4, pc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 9: rsb ip, ip, #4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) cmp ip, #2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) ldr1b r1, r3, gt, abort=21f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) ldr1b r1, r4, ge, abort=21f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) ldr1b r1, lr, abort=21f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) str1b r0, r3, gt, abort=21f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) str1b r0, r4, ge, abort=21f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) subs r2, r2, ip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) str1b r0, lr, abort=21f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) blt 8b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) ands ip, r1, #3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) beq 1b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 10: bic r1, r1, #3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) cmp ip, #2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ldr1w r1, lr, abort=21f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) beq 17f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) bgt 18f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) UNWIND( .fnend )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) .macro forward_copy_shift pull push
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) UNWIND( .fnstart )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) usave r4, lr @ still in first stmdb block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) subs r2, r2, #28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) blt 14f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) CALGN( ands ip, r0, #31 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) CALGN( rsb ip, ip, #32 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) CALGN( sbcsne r4, ip, r2 ) @ C is always set here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) CALGN( subcc r2, r2, ip )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) CALGN( bcc 15f )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 11: stmfd sp!, {r5 - r9}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) UNWIND( .fnend )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) UNWIND( .fnstart )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) usave r4, lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) UNWIND( .save {r5 - r9} ) @ in new second stmfd block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) PLD( pld [r1, #0] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) PLD( subs r2, r2, #96 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) PLD( pld [r1, #28] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) PLD( blt 13f )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) PLD( pld [r1, #60] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) PLD( pld [r1, #92] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 12: PLD( pld [r1, #124] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 13: ldr4w r1, r4, r5, r6, r7, abort=19f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) mov r3, lr, lspull #\pull
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) subs r2, r2, #32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) ldr4w r1, r8, r9, ip, lr, abort=19f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) orr r3, r3, r4, lspush #\push
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) mov r4, r4, lspull #\pull
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) orr r4, r4, r5, lspush #\push
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) mov r5, r5, lspull #\pull
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) orr r5, r5, r6, lspush #\push
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) mov r6, r6, lspull #\pull
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) orr r6, r6, r7, lspush #\push
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) mov r7, r7, lspull #\pull
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) orr r7, r7, r8, lspush #\push
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) mov r8, r8, lspull #\pull
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) orr r8, r8, r9, lspush #\push
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) mov r9, r9, lspull #\pull
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) orr r9, r9, ip, lspush #\push
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) mov ip, ip, lspull #\pull
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) orr ip, ip, lr, lspush #\push
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) str8w r0, r3, r4, r5, r6, r7, r8, r9, ip, abort=19f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) bge 12b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) PLD( cmn r2, #96 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) PLD( bge 13b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) ldmfd sp!, {r5 - r9}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) UNWIND( .fnend ) @ end of the second stmfd block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) UNWIND( .fnstart )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) usave r4, lr @ still in first stmdb block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 14: ands ip, r2, #28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) beq 16f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 15: mov r3, lr, lspull #\pull
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) ldr1w r1, lr, abort=21f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) subs ip, ip, #4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) orr r3, r3, lr, lspush #\push
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) str1w r0, r3, abort=21f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) bgt 15b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) CALGN( cmp r2, #0 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) CALGN( bge 11b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 16: sub r1, r1, #(\push / 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) b 8b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) UNWIND( .fnend )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) .endm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) forward_copy_shift pull=8 push=24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 17: forward_copy_shift pull=16 push=16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 18: forward_copy_shift pull=24 push=8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * Abort preamble and completion macros.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * If a fixup handler is required then those macros must surround it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * It is assumed that the fixup code will handle the private part of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * the exit macro.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) .macro copy_abort_preamble
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 19: ldmfd sp!, {r5 - r9}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) b 21f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 20: ldmfd sp!, {r5 - r8}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 21:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) .endm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) .macro copy_abort_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) ldmfd sp!, {r4, pc}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) .endm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)