1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
|
@ vim:filetype=armasm
@ Generic memory routines.
@ (c) Copyright 2007, Grazvydas "notaz" Ignotas
.global memcpy16 @ unsigned short *dest, unsigned short *src, int count
memcpy16:
eor r3, r0, r1
tst r3, #2
bne mcp16_cant_align
tst r0, #2
ldrneh r3, [r1], #2
subne r2, r2, #1
strneh r3, [r0], #2
subs r2, r2, #4
bmi mcp16_fin
mcp16_loop:
ldmia r1!, {r3,r12}
subs r2, r2, #4
stmia r0!, {r3,r12}
bpl mcp16_loop
mcp16_fin:
tst r2, #2
ldrne r3, [r1], #4
strne r3, [r0], #4
ands r2, r2, #1
bxeq lr
mcp16_cant_align:
ldrh r3, [r1], #2
subs r2, r2, #1
strh r3, [r0], #2
bne mcp16_cant_align
bx lr
@ 0x12345678 -> 0x34127856
@ r4=temp, lr=0x00ff00ff
.macro bswap reg
and r4, \reg, lr
and \reg, lr, \reg, lsr #8
orr \reg, \reg, r4, lsl #8
.endm
@ dest must be halfword aligned, src can be unaligned
.global memcpy16bswap @ unsigned short *dest, void *src, int count
memcpy16bswap:
tst r1, #1
bne mcp16bs_cant_align2
eor r3, r0, r1
tst r3, #2
bne mcp16bs_cant_align
tst r0, #2
beq mcp16bs_aligned
ldrh r3, [r1], #2
sub r2, r2, #1
orr r3, r3, r3, lsl #16
mov r3, r3, lsr #8
strh r3, [r0], #2
mcp16bs_aligned:
stmfd sp!, {r4,lr}
mov lr, #0xff
orr lr, lr, lr, lsl #16
subs r2, r2, #4
bmi mcp16bs_fin4
mcp16bs_loop:
ldmia r1!, {r3,r12}
subs r2, r2, #4
bswap r3
bswap r12
stmia r0!, {r3,r12}
bpl mcp16bs_loop
mcp16bs_fin4:
tst r2, #2
beq mcp16bs_fin2
ldr r3, [r1], #4
bswap r3
str r3, [r0], #4
mcp16bs_fin2:
ldmfd sp!, {r4,lr}
ands r2, r2, #1
bxeq lr
mcp16bs_cant_align:
ldrh r3, [r1], #2
subs r2, r2, #1
orr r3, r3, r3, lsl #16
mov r3, r3, lsr #8
strh r3, [r0], #2
bne mcp16bs_cant_align
bx lr
@ worst case
mcp16bs_cant_align2:
ldrb r3, [r1], #1
ldrb r12,[r1], #1
subs r2, r2, #1
mov r3, r3, lsl #8
orr r3, r3, r12
strh r3, [r0], #2
bne mcp16bs_cant_align2
bx lr
.global memcpy32 @ int *dest, int *src, int count
memcpy32:
stmfd sp!, {r4,lr}
subs r2, r2, #4
bmi mcp32_fin
mcp32_loop:
ldmia r1!, {r3,r4,r12,lr}
subs r2, r2, #4
stmia r0!, {r3,r4,r12,lr}
bpl mcp32_loop
mcp32_fin:
tst r2, #3
ldmeqfd sp!, {r4,pc}
tst r2, #1
ldrne r3, [r1], #4
strne r3, [r0], #4
mcp32_no_unal1:
tst r2, #2
ldmneia r1!, {r3,r12}
ldmfd sp!, {r4,lr}
stmneia r0!, {r3,r12}
bx lr
.global memset32 @ int *dest, int c, int count
memset32:
stmfd sp!, {lr}
mov r3, r1
subs r2, r2, #4
bmi mst32_fin
mov r12,r1
mov lr, r1
mst32_loop:
subs r2, r2, #4
stmia r0!, {r1,r3,r12,lr}
bpl mst32_loop
mst32_fin:
tst r2, #1
strne r1, [r0], #4
tst r2, #2
stmneia r0!, {r1,r3}
ldmfd sp!, {pc}
|