0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/linkage.h>
0011 #include <asm/assembler.h>
0012 #include <asm/unwind.h>
0013
0014 .text
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 ENTRY(__memmove)
0028 WEAK(memmove)
0029 UNWIND( .fnstart )
0030
0031 subs ip, r0, r1
0032 cmphi r2, ip
0033 bls __memcpy
0034 UNWIND( .fnend )
0035
0036 UNWIND( .fnstart )
0037 UNWIND( .save {r0, r4, fpreg, lr} )
0038 stmfd sp!, {r0, r4, UNWIND(fpreg,) lr}
0039 UNWIND( .setfp fpreg, sp )
0040 UNWIND( mov fpreg, sp )
0041 add r1, r1, r2
0042 add r0, r0, r2
0043 subs r2, r2, #4
0044 blt 8f
0045 ands ip, r0, #3
0046 PLD( pld [r1, #-4] )
0047 bne 9f
0048 ands ip, r1, #3
0049 bne 10f
0050
0051 1: subs r2, r2, #(28)
0052 stmfd sp!, {r5, r6, r8, r9}
0053 blt 5f
0054
0055 CALGN( ands ip, r0, #31 )
0056 CALGN( sbcsne r4, ip, r2 ) @ C is always set here
0057 CALGN( bcs 2f )
0058 CALGN( adr r4, 6f )
0059 CALGN( subs r2, r2, ip ) @ C is set here
0060 CALGN( rsb ip, ip, #32 )
0061 CALGN( add pc, r4, ip )
0062
0063 PLD( pld [r1, #-4] )
0064 2: PLD( subs r2, r2, #96 )
0065 PLD( pld [r1, #-32] )
0066 PLD( blt 4f )
0067 PLD( pld [r1, #-64] )
0068 PLD( pld [r1, #-96] )
0069
0070 3: PLD( pld [r1, #-128] )
0071 4: ldmdb r1!, {r3, r4, r5, r6, r8, r9, ip, lr}
0072 subs r2, r2, #32
0073 stmdb r0!, {r3, r4, r5, r6, r8, r9, ip, lr}
0074 bge 3b
0075 PLD( cmn r2, #96 )
0076 PLD( bge 4b )
0077
0078 5: ands ip, r2, #28
0079 rsb ip, ip, #32
0080 addne pc, pc, ip @ C is always clear here
0081 b 7f
0082 6: W(nop)
0083 W(ldr) r3, [r1, #-4]!
0084 W(ldr) r4, [r1, #-4]!
0085 W(ldr) r5, [r1, #-4]!
0086 W(ldr) r6, [r1, #-4]!
0087 W(ldr) r8, [r1, #-4]!
0088 W(ldr) r9, [r1, #-4]!
0089 W(ldr) lr, [r1, #-4]!
0090
0091 add pc, pc, ip
0092 nop
0093 W(nop)
0094 W(str) r3, [r0, #-4]!
0095 W(str) r4, [r0, #-4]!
0096 W(str) r5, [r0, #-4]!
0097 W(str) r6, [r0, #-4]!
0098 W(str) r8, [r0, #-4]!
0099 W(str) r9, [r0, #-4]!
0100 W(str) lr, [r0, #-4]!
0101
0102 CALGN( bcs 2b )
0103
0104 7: ldmfd sp!, {r5, r6, r8, r9}
0105
0106 8: movs r2, r2, lsl #31
0107 ldrbne r3, [r1, #-1]!
0108 ldrbcs r4, [r1, #-1]!
0109 ldrbcs ip, [r1, #-1]
0110 strbne r3, [r0, #-1]!
0111 strbcs r4, [r0, #-1]!
0112 strbcs ip, [r0, #-1]
0113 ldmfd sp!, {r0, r4, UNWIND(fpreg,) pc}
0114
0115 9: cmp ip, #2
0116 ldrbgt r3, [r1, #-1]!
0117 ldrbge r4, [r1, #-1]!
0118 ldrb lr, [r1, #-1]!
0119 strbgt r3, [r0, #-1]!
0120 strbge r4, [r0, #-1]!
0121 subs r2, r2, ip
0122 strb lr, [r0, #-1]!
0123 blt 8b
0124 ands ip, r1, #3
0125 beq 1b
0126
0127 10: bic r1, r1, #3
0128 cmp ip, #2
0129 ldr r3, [r1, #0]
0130 beq 17f
0131 blt 18f
0132
0133
0134 .macro backward_copy_shift push pull
0135
0136 subs r2, r2, #28
0137 blt 14f
0138
0139 CALGN( ands ip, r0, #31 )
0140 CALGN( sbcsne r4, ip, r2 ) @ C is always set here
0141 CALGN( subcc r2, r2, ip )
0142 CALGN( bcc 15f )
0143
0144 11: stmfd sp!, {r5, r6, r8 - r10}
0145
0146 PLD( pld [r1, #-4] )
0147 PLD( subs r2, r2, #96 )
0148 PLD( pld [r1, #-32] )
0149 PLD( blt 13f )
0150 PLD( pld [r1, #-64] )
0151 PLD( pld [r1, #-96] )
0152
0153 12: PLD( pld [r1, #-128] )
0154 13: ldmdb r1!, {r8, r9, r10, ip}
0155 mov lr, r3, lspush #\push
0156 subs r2, r2, #32
0157 ldmdb r1!, {r3, r4, r5, r6}
0158 orr lr, lr, ip, lspull #\pull
0159 mov ip, ip, lspush #\push
0160 orr ip, ip, r10, lspull #\pull
0161 mov r10, r10, lspush #\push
0162 orr r10, r10, r9, lspull #\pull
0163 mov r9, r9, lspush #\push
0164 orr r9, r9, r8, lspull #\pull
0165 mov r8, r8, lspush #\push
0166 orr r8, r8, r6, lspull #\pull
0167 mov r6, r6, lspush #\push
0168 orr r6, r6, r5, lspull #\pull
0169 mov r5, r5, lspush #\push
0170 orr r5, r5, r4, lspull #\pull
0171 mov r4, r4, lspush #\push
0172 orr r4, r4, r3, lspull #\pull
0173 stmdb r0!, {r4 - r6, r8 - r10, ip, lr}
0174 bge 12b
0175 PLD( cmn r2, #96 )
0176 PLD( bge 13b )
0177
0178 ldmfd sp!, {r5, r6, r8 - r10}
0179
0180 14: ands ip, r2, #28
0181 beq 16f
0182
0183 15: mov lr, r3, lspush #\push
0184 ldr r3, [r1, #-4]!
0185 subs ip, ip, #4
0186 orr lr, lr, r3, lspull #\pull
0187 str lr, [r0, #-4]!
0188 bgt 15b
0189 CALGN( cmp r2, #0 )
0190 CALGN( bge 11b )
0191
0192 16: add r1, r1, #(\pull / 8)
0193 b 8b
0194
0195 .endm
0196
0197
0198 backward_copy_shift push=8 pull=24
0199
0200 17: backward_copy_shift push=16 pull=16
0201
0202 18: backward_copy_shift push=24 pull=8
0203
0204 UNWIND( .fnend )
0205 ENDPROC(memmove)
0206 ENDPROC(__memmove)