0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 UNWIND( .fnstart )
0073 enter r4, UNWIND(fpreg,) lr
0074 UNWIND( .setfp fpreg, sp )
0075 UNWIND( mov fpreg, sp )
0076
0077 subs r2, r2, #4
0078 blt 8f
0079 ands ip, r0, #3
0080 PLD( pld [r1, #0] )
0081 bne 9f
0082 ands ip, r1, #3
0083 bne 10f
0084
0085 1: subs r2, r2, #(28)
0086 stmfd sp!, {r5, r6, r8, r9}
0087 blt 5f
0088
0089 CALGN( ands ip, r0, #31 )
0090 CALGN( rsb r3, ip, #32 )
0091 CALGN( sbcsne r4, r3, r2 ) @ C is always set here
0092 CALGN( bcs 2f )
0093 CALGN( adr r4, 6f )
0094 CALGN( subs r2, r2, r3 ) @ C gets set
0095 CALGN( add pc, r4, ip )
0096
0097 PLD( pld [r1, #0] )
0098 2: PLD( subs r2, r2, #96 )
0099 PLD( pld [r1, #28] )
0100 PLD( blt 4f )
0101 PLD( pld [r1, #60] )
0102 PLD( pld [r1, #92] )
0103
0104 3: PLD( pld [r1, #124] )
0105 4: ldr8w r1, r3, r4, r5, r6, r8, r9, ip, lr, abort=20f
0106 subs r2, r2, #32
0107 str8w r0, r3, r4, r5, r6, r8, r9, ip, lr, abort=20f
0108 bge 3b
0109 PLD( cmn r2, #96 )
0110 PLD( bge 4b )
0111
0112 5: ands ip, r2, #28
0113 rsb ip, ip, #32
0114 #if LDR1W_SHIFT > 0
0115 lsl ip, ip, #LDR1W_SHIFT
0116 #endif
0117 addne pc, pc, ip @ C is always clear here
0118 b 7f
0119 6:
0120 .rept (1 << LDR1W_SHIFT)
0121 W(nop)
0122 .endr
0123 ldr1w r1, r3, abort=20f
0124 ldr1w r1, r4, abort=20f
0125 ldr1w r1, r5, abort=20f
0126 ldr1w r1, r6, abort=20f
0127 ldr1w r1, r8, abort=20f
0128 ldr1w r1, r9, abort=20f
0129 ldr1w r1, lr, abort=20f
0130
0131 #if LDR1W_SHIFT < STR1W_SHIFT
0132 lsl ip, ip, #STR1W_SHIFT - LDR1W_SHIFT
0133 #elif LDR1W_SHIFT > STR1W_SHIFT
0134 lsr ip, ip, #LDR1W_SHIFT - STR1W_SHIFT
0135 #endif
0136 add pc, pc, ip
0137 nop
0138 .rept (1 << STR1W_SHIFT)
0139 W(nop)
0140 .endr
0141 str1w r0, r3, abort=20f
0142 str1w r0, r4, abort=20f
0143 str1w r0, r5, abort=20f
0144 str1w r0, r6, abort=20f
0145 str1w r0, r8, abort=20f
0146 str1w r0, r9, abort=20f
0147 str1w r0, lr, abort=20f
0148
0149 CALGN( bcs 2b )
0150
0151 7: ldmfd sp!, {r5, r6, r8, r9}
0152
0153 8: movs r2, r2, lsl #31
0154 ldr1b r1, r3, ne, abort=21f
0155 ldr1b r1, r4, cs, abort=21f
0156 ldr1b r1, ip, cs, abort=21f
0157 str1b r0, r3, ne, abort=21f
0158 str1b r0, r4, cs, abort=21f
0159 str1b r0, ip, cs, abort=21f
0160
0161 exit r4, UNWIND(fpreg,) pc
0162
0163 9: rsb ip, ip, #4
0164 cmp ip, #2
0165 ldr1b r1, r3, gt, abort=21f
0166 ldr1b r1, r4, ge, abort=21f
0167 ldr1b r1, lr, abort=21f
0168 str1b r0, r3, gt, abort=21f
0169 str1b r0, r4, ge, abort=21f
0170 subs r2, r2, ip
0171 str1b r0, lr, abort=21f
0172 blt 8b
0173 ands ip, r1, #3
0174 beq 1b
0175
0176 10: bic r1, r1, #3
0177 cmp ip, #2
0178 ldr1w r1, lr, abort=21f
0179 beq 17f
0180 bgt 18f
0181
0182
0183 .macro forward_copy_shift pull push
0184
0185 subs r2, r2, #28
0186 blt 14f
0187
0188 CALGN( ands ip, r0, #31 )
0189 CALGN( rsb ip, ip, #32 )
0190 CALGN( sbcsne r4, ip, r2 ) @ C is always set here
0191 CALGN( subcc r2, r2, ip )
0192 CALGN( bcc 15f )
0193
0194 11: stmfd sp!, {r5, r6, r8 - r10}
0195
0196 PLD( pld [r1, #0] )
0197 PLD( subs r2, r2, #96 )
0198 PLD( pld [r1, #28] )
0199 PLD( blt 13f )
0200 PLD( pld [r1, #60] )
0201 PLD( pld [r1, #92] )
0202
0203 12: PLD( pld [r1, #124] )
0204 13: ldr4w r1, r4, r5, r6, r8, abort=19f
0205 mov r3, lr, lspull #\pull
0206 subs r2, r2, #32
0207 ldr4w r1, r9, r10, ip, lr, abort=19f
0208 orr r3, r3, r4, lspush #\push
0209 mov r4, r4, lspull #\pull
0210 orr r4, r4, r5, lspush #\push
0211 mov r5, r5, lspull #\pull
0212 orr r5, r5, r6, lspush #\push
0213 mov r6, r6, lspull #\pull
0214 orr r6, r6, r8, lspush #\push
0215 mov r8, r8, lspull #\pull
0216 orr r8, r8, r9, lspush #\push
0217 mov r9, r9, lspull #\pull
0218 orr r9, r9, r10, lspush #\push
0219 mov r10, r10, lspull #\pull
0220 orr r10, r10, ip, lspush #\push
0221 mov ip, ip, lspull #\pull
0222 orr ip, ip, lr, lspush #\push
0223 str8w r0, r3, r4, r5, r6, r8, r9, r10, ip, abort=19f
0224 bge 12b
0225 PLD( cmn r2, #96 )
0226 PLD( bge 13b )
0227
0228 ldmfd sp!, {r5, r6, r8 - r10}
0229
0230 14: ands ip, r2, #28
0231 beq 16f
0232
0233 15: mov r3, lr, lspull #\pull
0234 ldr1w r1, lr, abort=21f
0235 subs ip, ip, #4
0236 orr r3, r3, lr, lspush #\push
0237 str1w r0, r3, abort=21f
0238 bgt 15b
0239 CALGN( cmp r2, #0 )
0240 CALGN( bge 11b )
0241
0242 16: sub r1, r1, #(\push / 8)
0243 b 8b
0244
0245 .endm
0246
0247
0248 forward_copy_shift pull=8 push=24
0249
0250 17: forward_copy_shift pull=16 push=16
0251
0252 18: forward_copy_shift pull=24 push=8
0253
0254 UNWIND( .fnend )
0255
0256
0257
0258
0259
0260
0261
0262
0263 .macro copy_abort_preamble
0264 19: ldmfd sp!, {r5, r6, r8 - r10}
0265 b 21f
0266 20: ldmfd sp!, {r5, r6, r8, r9}
0267 21:
0268 .endm
0269
0270 .macro copy_abort_end
0271 ldmfd sp!, {r4, UNWIND(fpreg,) pc}
0272 .endm
0273