summaryrefslogtreecommitdiff
path: root/src/libultra/libc/bcopy.s
blob: 3c0742048e12a59778822307e236d97f50c3ecc5 (plain)
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#include "PR/asm.h"
#include "PR/regdef.h"

.text

LEAF(bcopy)
    move    a3, a1
    beqz    a2, ret
    beq     a0, a1, ret
    blt     a1, a0, goforwards
    add     v0, a0, a2
    bge     a1, v0, goforwards
    b       gobackwards

goforwards:
    blt     a2, 0x10, forwards_bytecopy
    and     v0, a0, 3
    and     v1, a1, 3
    beq     v0, v1, forwalignable

forwards_bytecopy:
    beqz    a2, ret
    addu    v1, a0, a2
99:
    lb      v0, (a0)
    addu    a0, a0, 1
    sb      v0, (a1)
    addu    a1, a1, 1
    bne     a0, v1, 99b
ret:
    move    v0, a3
    jr      ra

forwalignable:
    beqz    v0, forwards_32
    beq     v0, 1, forw_copy3
    beq     v0, 2, forw_copy2

    lb      v0, (a0)
    addu    a0, a0, 1
    sb      v0, (a1)
    addu    a1, a1, 1
    addu    a2, a2, -1
    b       forwards_32

forw_copy2:
    lh      v0, (a0)
    addu    a0, a0, 2
    sh      v0, (a1)
    addu    a1, a1, 2
    addu    a2, a2, -2
    b       forwards_32

forw_copy3:
    lb      v0, (a0)
    lh      v1, 1(a0)
    addu    a0, a0, 3
    sb      v0, (a1)
    sh      v1, 1(a1)
    addu    a1, a1, 3
    addu    a2, a2, -3

forwards:
forwards_32:
    blt     a2, 32, forwards_16
    lw      v0, 0(a0)
    lw      v1, 4(a0)
    lw      t0, 8(a0)
    lw      t1, 12(a0)
    lw      t2, 16(a0)
    lw      t3, 20(a0)
    lw      t4, 24(a0)
    lw      t5, 28(a0)
    addu    a0, a0, 32
    sw      v0, 0(a1)
    sw      v1, 4(a1)
    sw      t0, 8(a1)
    sw      t1, 12(a1)
    sw      t2, 16(a1)
    sw      t3, 20(a1)
    sw      t4, 24(a1)
    sw      t5, 28(a1)
    addu    a1, a1, 32
    addu    a2, a2, -32
    b       forwards_32

forwards_16:
    blt     a2, 16, forwards_4
    lw      v0, 0(a0)
    lw      v1, 4(a0)
    lw      t0, 8(a0)
    lw      t1, 12(a0)
    addu    a0, a0, 16
    sw      v0, 0(a1)
    sw      v1, 4(a1)
    sw      t0, 8(a1)
    sw      t1, 12(a1)
    addu    a1, a1, 16
    addu    a2, a2, -16
    b       forwards_16

forwards_4:
    blt     a2, 4, forwards_bytecopy

    lw      v0, 0(a0)
    addu    a0, a0, 4
    sw      v0, 0(a1)
    addu    a1, a1, 4
    addu    a2, a2, -4
    b       forwards_4

gobackwards:
    add     a0, a0,a2
    add     a1, a1,a2
    blt     a2, 16, backwards_bytecopy

    and     v0, a0, 0x3
    and     v1, a1, 0x3
    beq     v0, v1, backalignable

backwards_bytecopy:
    beqz    a2, ret
    addu    a0, a0, -1
    addu    a1, a1, -1
    subu    v1, a0,a2
99:
    lb      v0, 0(a0)
    addu    a0, a0, -1
    sb      v0, 0(a1)
    addu    a1, a1, -1
    bne     a0, v1,99b

    move    v0, a3
    jr      ra

backalignable:
    beqz    v0, backwards
    beq     v0, 3, back_copy3
    beq     v0, 2, back_copy2
    lb      v0, -1(a0)
    addu    a0, a0, -1
    sb      v0, -1(a1)
    addu    a1, a1, -1
    addu    a2, a2, -1
    b       backwards

back_copy2:
    lh      v0, -2(a0)
    addu    a0, a0, -2
    sh      v0, -2(a1)
    addu    a1, a1, -2
    addu    a2, a2, -2
    b       backwards

back_copy3:
    lb      v0, -1(a0)
    lh      v1, -3(a0)
    addu    a0, a0, -3
    sb      v0, -1(a1)
    sh      v1, -3(a1)
    addu    a1, a1, -3
    addu    a2, a2, -3

backwards:
backwards_32:
    blt     a2, 32, backwards_16
    lw      v0, -4(a0)
    lw      v1, -8(a0)
    lw      t0, -12(a0)
    lw      t1, -16(a0)
    lw      t2, -20(a0)
    lw      t3, -24(a0)
    lw      t4, -28(a0)
    lw      t5, -32(a0)
    addu    a0, a0, -32
    sw      v0, -4(a1)
    sw      v1, -8(a1)
    sw      t0, -12(a1)
    sw      t1, -16(a1)
    sw      t2, -20(a1)
    sw      t3, -24(a1)
    sw      t4, -28(a1)
    sw      t5, -32(a1)
    addu    a1, a1, -32
    addu    a2, a2, -32
    b       backwards_32

backwards_16:
    blt     a2, 16, backwards_4
    lw      v0, -4(a0)
    lw      v1, -8(a0)
    lw      t0, -12(a0)
    lw      t1, -16(a0)
    addu    a0, a0, -16
    sw      v0, -4(a1)
    sw      v1, -8(a1)
    sw      t0, -12(a1)
    sw      t1, -16(a1)
    addu    a1, a1, -16
    addu    a2, a2, -16
    b       backwards_16

backwards_4:
    blt     a2, 4, backwards_bytecopy
    lw      v0, -4(a0)
    addu    a0, a0, -4
    sw      v0, -4(a1)
    addu    a1, a1, -4
    addu    a2, a2, -4
    b       backwards_4
END(bcopy)