summaryrefslogtreecommitdiff
path: root/firmware/asm/m68k/memmove.S
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/asm/m68k/memmove.S')
-rw-r--r--firmware/asm/m68k/memmove.S670
1 files changed, 670 insertions, 0 deletions
diff --git a/firmware/asm/m68k/memmove.S b/firmware/asm/m68k/memmove.S
new file mode 100644
index 0000000000..736cd619e1
--- /dev/null
+++ b/firmware/asm/m68k/memmove.S
@@ -0,0 +1,670 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22
23 .section .icode,"ax",@progbits
24
25#define FULLSPEED /* use burst writing for word aligned destinations */
26 .align 2
27 .global memmove
28 .type memmove,@function
29
30/* Moves <length> bytes of data in memory from <source> to <dest>
31 * Regions may overlap.
32 * This version is optimized for speed, and needs the corresponding memcpy
33 * implementation for the forward copy branch.
34 *
35 * arguments:
36 * (4,%sp) - destination address
37 * (8,%sp) - source address
38 * (12,%sp) - length
39 *
40 * return value:
41 * %d0 - destination address (like ANSI version)
42 *
43 * register usage:
44 * %a0 - current source address
45 * %a1 - current dest address
46 * %a2 - source start address (in line-copy loops)
47 * %d0 - source start address (byte and longword copy) / data / scratch
48 * %d1 - data / scratch
49 * %d2 - data / scratch
50 * %d3..%d7 - data
51 *
52 * For maximum speed this routine reads and writes whole lines using burst
53 * move (movem.l) where possible. For byte aligned destinations (long-1 and
54 * long-3) it writes longwords only. Same goes for word aligned destinations
55 * if FULLSPEED is undefined.
56 */
57memmove:
58 move.l (4,%sp),%a1 /* Destination */
59 move.l (8,%sp),%a0 /* Source */
60 move.l (12,%sp),%d1 /* Length */
61
62 cmp.l %a0,%a1
63 bhi.b .backward /* dest > src -> backward copy */
64 jmp __memcpy_fwd_entry
65
66.backward:
67 move.l %a0,%d0 /* %d0 = source start */
68 add.l %d1,%a0 /* %a0 = source end */
69 add.l %d1,%a1 /* %a1 = destination end */
70
71 move.l %a0,%d1
72 and.l #0xFFFFFFFC,%d1 /* %d1 = last source long bound */
73 subq.l #4,%d1
74 cmp.l %d0,%d1 /* at least one aligned longword to copy? */
75 blo.w .bytes2r_start
76
77 addq.l #4,%d1 /* %d1 = last source long bound */
78 cmp.l %d1,%a0 /* any bytes to copy */
79 jls .bytes1r_end /* no: skip byte loop */
80
81 /* leading byte loop: copies 0..3 bytes */
82.bytes1r_loop:
83 move.b -(%a0),-(%a1) /* copy byte */
84 cmp.l %d1,%a0 /* runs %a0 down to last long bound */
85 jhi .bytes1r_loop
86
87.bytes1r_end:
88 moveq.l #-16,%d1
89 add.l %a0,%d1
90 and.l #0xFFFFFFF0,%d1 /* %d1 = last source line bound - 16 */
91 cmp.l %d0,%d1 /* at least one aligned line to copy? */
92 blo.w .longr_start /* no: jump to longword copy loop */
93
94 lea.l (-28,%sp),%sp /* free up some registers */
95 movem.l %d2-%d7/%a2,(%sp)
96
97 moveq.l #16,%d2
98 add.l %d2,%d1 /* %d1 = last source line bound */
99 move.l %d0,%a2 /* %a2 = start address */
100 lea.l (15,%a2),%a2 /* adjust start address for loops doing 16 bytes/pass */
101 move.l %a1,%d0
102 moveq.l #3,%d2 /* mask */
103 and.l %d2,%d0
104 jmp.l (2,%pc,%d0.l*4) /* switch (dest_addr & 3) */
105 bra.w .lines_do0r_start
106 bra.w .lines_do1r_start
107 bra.w .lines_do2r_start
108 /* bra.w .lines_do3r_start implicit */
109
110 /* byte aligned destination (long - 1): use line burst reads in main loop */
111.lines_do3r_start:
112 moveq.l #24,%d0 /* shift count for shifting by 3 bytes */
113 cmp.l %d1,%a0 /* any leading longwords? */
114 jhi .lines_do3r_head_start /* yes: leading longword copy */
115
116 lea.l (-16,%a0),%a0
117 movem.l (%a0),%d3-%d6 /* load initial line */
118 move.l %d6,%d2 /* last longword, bytes 3210 */
119 move.b %d2,-(%a1) /* store byte */
120 lsr.l #8,%d2 /* last longword, bytes .321 */
121 move.w %d2,-(%a1) /* store word */
122 jra .lines_do3r_entry
123
124.lines_do3r_head_start:
125 move.l -(%a0),%d3 /* load initial longword */
126 move.l %d3,%d2 /* bytes 3210 */
127 move.b %d2,-(%a1) /* store byte */
128 lsr.l #8,%d2 /* bytes .321 */
129 move.w %d2,-(%a1) /* store word */
130 jra .lines_do3r_head_entry
131
132.lines_do3r_head_loop:
133 move.l %d3,%d4 /* move old longword away */
134 move.l -(%a0),%d3 /* load new longword */
135 move.l %d3,%d2
136 lsl.l #8,%d2 /* get bytes 210. */
137 or.l %d2,%d4 /* combine with old high byte */
138 move.l %d4,-(%a1) /* store longword */
139.lines_do3r_head_entry:
140 lsr.l %d0,%d3 /* shift down high byte */
141 cmp.l %d1,%a0 /* run %a0 down to last line bound */
142 jhi .lines_do3r_head_loop
143
144.lines_do3r_loop:
145 move.l %d3,%d7 /* move first longword of last line away */
146 lea.l (-16,%a0),%a0
147 movem.l (%a0),%d3-%d6 /* load new line */
148 move.l %d6,%d2
149 lsl.l #8,%d2 /* get bytes 210. of 4th longword */
150 or.l %d2,%d7 /* combine with high byte of old longword */
151 move.l %d7,-(%a1) /* store longword */
152.lines_do3r_entry:
153 lsr.l %d0,%d6 /* shift down high byte */
154 move.l %d5,%d2
155 lsl.l #8,%d2 /* get bytes 210. of 3rd longword */
156 or.l %d2,%d6 /* combine with high byte of 4th longword */
157 move.l %d6,-(%a1) /* store longword */
158 lsr.l %d0,%d5 /* shift down high byte */
159 move.l %d4,%d2
160 lsl.l #8,%d2 /* get bytes 210. of 2nd longword */
161 or.l %d2,%d5 /* combine with high byte or 3rd longword */
162 move.l %d5,-(%a1) /* store longword */
163 lsr.l %d0,%d4 /* shift down high byte */
164 move.l %d3,%d2
165 lsl.l #8,%d2 /* get bytes 210. of 1st longword */
166 or.l %d2,%d4 /* combine with high byte of 2nd longword */
167 move.l %d4,-(%a1) /* store longword */
168 lsr.l %d0,%d3 /* shift down high byte */
169 cmp.l %a2,%a0 /* run %a0 down to first line bound */
170 jhi .lines_do3r_loop
171
172 lea.l (-12,%a2),%a2 /* readjust start address for doing longwords */
173 cmp.l %a2,%a0 /* any trailing longwords? */
174 jls .lines_do3r_tail_end /* no: just store last high byte */
175
176.lines_do3r_tail_loop:
177 move.l %d3,%d4 /* move old longword away */
178 move.l -(%a0),%d3 /* load new longword */
179 move.l %d3,%d2
180 lsl.l #8,%d2 /* get bytes 210. */
181 or.l %d2,%d4 /* combine with old high byte */
182 move.l %d4,-(%a1) /* store longword */
183 lsr.l %d0,%d3 /* shift down high byte */
184 cmp.l %a2,%a0 /* run %a0 down to first long bound */
185 jhi .lines_do3r_tail_loop
186
187.lines_do3r_tail_end:
188 move.b %d3,-(%a1) /* store shifted-down high byte */
189 jra .linesr_end
190
191 /* byte aligned destination (long - 3): use line burst reads in main loop */
192.lines_do1r_start:
193 moveq.l #24,%d0 /* shift count for shifting by 3 bytes */
194 cmp.l %d1,%a0 /* any leading longwords? */
195 jhi .lines_do1r_head_start /* yes: leading longword copy */
196
197 lea.l (-16,%a0),%a0
198 movem.l (%a0),%d3-%d6 /* load initial line */
199 move.b %d6,-(%a1) /* store low byte of last longword */
200 jra .lines_do1r_entry
201
202.lines_do1r_head_start:
203 move.l -(%a0),%d3 /* load initial longword */
204 move.b %d3,-(%a1) /* store low byte */
205 jra .lines_do1r_head_entry
206
207.lines_do1r_head_loop:
208 move.l %d3,%d4 /* move old longword away */
209 move.l -(%a0),%d3 /* load new longword */
210 move.l %d3,%d2
211 lsl.l %d0,%d2 /* get low byte */
212 or.l %d2,%d4 /* combine with old bytes .321 */
213 move.l %d4,-(%a1) /* store longword */
214.lines_do1r_head_entry:
215 lsr.l #8,%d3 /* get bytes .321 */
216 cmp.l %d1,%a0 /* run %a0 down to last line bound */
217 jhi .lines_do1r_head_loop
218
219.lines_do1r_loop:
220 move.l %d3,%d7 /* move first longword of old line away */
221 lea.l (-16,%a0),%a0
222 movem.l (%a0),%d3-%d6 /* load new line */
223 move.l %d6,%d2
224 lsl.l %d0,%d2 /* get low byte of 4th longword */
225 or.l %d2,%d7 /* combine with bytes .321 of old longword */
226 move.l %d7,-(%a1) /* store longword */
227.lines_do1r_entry:
228 lsr.l #8,%d6 /* get bytes .321 */
229 move.l %d5,%d2
230 lsl.l %d0,%d2 /* get low byte of 3rd longword */
231 or.l %d2,%d6 /* combine with bytes .321 of 4th longword */
232 move.l %d6,-(%a1) /* store longword */
233 lsr.l #8,%d5 /* get bytes .321 */
234 move.l %d4,%d2
235 lsl.l %d0,%d2 /* get low byte of 2nd longword */
236 or.l %d2,%d5 /* combine with bytes .321 of 3rd longword */
237 move.l %d5,-(%a1) /* store longword */
238 lsr.l #8,%d4 /* get bytes .321 */
239 move.l %d3,%d2
240 lsl.l %d0,%d2 /* get low byte of 1st longword */
241 or.l %d2,%d4 /* combine with bytes .321 of 2nd longword */
242 move.l %d4,-(%a1) /* store longword */
243 lsr.l #8,%d3 /* get bytes .321 */
244 cmp.l %a2,%a0 /* run %a0 down to first line bound */
245 jhi .lines_do1r_loop
246
247 lea.l (-12,%a2),%a2 /* readjust start address for doing longwords */
248 cmp.l %a2,%a0 /* any trailing longwords? */
249 jls .lines_do1r_tail_end /* no: just store last high byte */
250
251.lines_do1r_tail_loop:
252 move.l %d3,%d4 /* move old longword away */
253 move.l -(%a0),%d3 /* load new longword */
254 move.l %d3,%d2
255 lsl.l %d0,%d2 /* get low byte */
256 or.l %d2,%d4 /* combine with old bytes .321 */
257 move.l %d4,-(%a1) /* store longword */
258 lsr.l #8,%d3 /* get bytes .321 */
259 cmp.l %a2,%a0 /* run %a0 down to first long bound */
260 jhi .lines_do1r_tail_loop
261
262.lines_do1r_tail_end:
263 move.w %d3,-(%a1) /* store word 21 */
264 swap %d3
265 move.b %d3,-(%a1) /* store byte 3 */
266 jra .linesr_end
267
268 /* long aligned destination (line - 0/4/8/12): head */
269.lines_do0r_head_loop:
270 move.l -(%a0),-(%a1) /* copy longword */
271.lines_do0r_start:
272 cmp.l %d1,%a0 /* run %a0 down to last line bound */
273 jhi .lines_do0r_head_loop
274
275.lines_do0r_head_end:
276 move.l %a1,%d1
277 lsr.l #2,%d1
278 moveq.l #3,%d0 /* mask */
279 and.l %d0,%d1
280 moveq.l #16,%d0 /* address decrement for one main loop pass */
281 jmp.l (2,%pc,%d1.l*2) /* switch ((dest_addr >> 2) & 3) */
282 bra.b .lines_lo0r_start
283 bra.b .lines_lo4r_start
284 bra.b .lines_lo8r_start
285 /* bra.b .lines_lo12r_start implicit */
286
287 /* long aligned destination (line - 4): use line bursts in the loop */
288.lines_lo12r_start:
289 sub.l %d0,%a0
290 movem.l (%a0),%d1-%d4 /* load initial line */
291 move.l %d4,-(%a1) /* store 4th longword */
292 move.l %d3,-(%a1) /* store 3rd longword */
293 move.l %d2,-(%a1) /* store 2nd longword */
294 cmp.l %a2,%a0 /* any full lines? */
295 jls .lines_lo12r_end /* no: skip main loop */
296
297.lines_lo12r_loop:
298 move.l %d1,%d5 /* move first longword of old line away */
299 sub.l %d0,%a0
300 movem.l (%a0),%d1-%d4 /* load new line */
301 sub.l %d0,%a1
302 movem.l %d2-%d5,(%a1) /* store line (1 old + 3 new longwords */
303 cmp.l %a2,%a0 /* run %a0 down to first line bound */
304 jhi .lines_lo12r_loop
305
306 jra .lines_lo12r_end /* handle trailing longwords */
307
308 /* line aligned destination: use line bursts in the loop */
309.lines_lo0r_start:
310.lines_lo0r_loop:
311 sub.l %d0,%a0
312 movem.l (%a0),%d1-%d4 /* load line */
313 sub.l %d0,%a1
314 movem.l %d1-%d4,(%a1) /* store line */
315 cmp.l %a2,%a0 /* run %a0 down to first line bound */
316 jhi .lines_lo0r_loop
317
318 jra .lines_lo0r_end /* handle trailing longwords */
319
320 /* long aligned destination (line - 8): use line bursts in the loop */
321.lines_lo8r_start:
322 sub.l %d0,%a0
323 movem.l (%a0),%d1-%d4 /* load initial line */
324 move.l %d4,-(%a1) /* store 4th longword */
325 move.l %d3,-(%a1) /* store 3rd longword */
326 cmp.l %a2,%a0 /* any full lines? */
327 jls .lines_lo8r_end /* no: skip main loop */
328
329.lines_lo8r_loop:
330 move.l %d2,%d6 /* move first 2 longwords of old line away */
331 move.l %d1,%d5
332 sub.l %d0,%a0
333 movem.l (%a0),%d1-%d4 /* load new line */
334 sub.l %d0,%a1
335 movem.l %d3-%d6,(%a1) /* store line (2 old + 2 new longwords */
336 cmp.l %a2,%a0 /* run %a0 down to first line bound */
337 jhi .lines_lo8r_loop
338
339 jra .lines_lo8r_end /* handle trailing longwords */
340
341 /* long aligned destination (line - 12): use line bursts in the loop */
342.lines_lo4r_start:
343 sub.l %d0,%a0
344 movem.l (%a0),%d1-%d4 /* load initial line */
345 move.l %d4,-(%a1) /* store 4th longword */
346 cmp.l %a2,%a0 /* any full lines? */
347 jls .lines_lo4r_end /* no: skip main loop */
348
349.lines_lo4r_loop:
350 move.l %d3,%d7 /* move first 3 longwords of old line away */
351 move.l %d2,%d6
352 move.l %d1,%d5
353 sub.l %d0,%a0
354 movem.l (%a0),%d1-%d4 /* load new line */
355 sub.l %d0,%a1
356 movem.l %d4-%d7,(%a1) /* store line (3 old + 1 new longwords */
357 cmp.l %a2,%a0 /* run %a0 down to first line bound */
358 jhi .lines_lo4r_loop
359
360 /* long aligned destination (line - 0/4/8/12): tail */
361.lines_lo4r_end:
362 move.l %d3,-(%a1) /* store 3rd last longword */
363.lines_lo8r_end:
364 move.l %d2,-(%a1) /* store 2nd last longword */
365.lines_lo12r_end:
366 move.l %d1,-(%a1) /* store last longword */
367.lines_lo0r_end:
368 lea.l (-12,%a2),%a2 /* readjust end address for doing longwords */
369 cmp.l %a2,%a0 /* any trailing longwords? */
370 jls .linesr_end /* no: get outta here */
371
372.lines_do0r_tail_loop:
373 move.l -(%a0),-(%a1) /* copy longword */
374 cmp.l %a2,%a0 /* run %a0 down to first long bound */
375 jhi .lines_do0r_tail_loop
376
377 jra .linesr_end
378
379#ifdef FULLSPEED
380 /* word aligned destination (line - 2/6/10/14): head */
381.lines_do2r_start:
382 cmp.l %d1,%a0 /* any leading longwords? */
383 jls .lines_do2r_selector /* no: jump to mainloop selector */
384
385 move.l -(%a0),%d3 /* load initial longword */
386 move.w %d3,-(%a1) /* store low word */
387 cmp.l %d1,%a0 /* any more longwords? */
388 jls .lines_do2r_head_end /* no: skip head loop */
389
390.lines_do2r_head_loop:
391 move.l %d3,%d4 /* move old longword away */
392 move.l -(%a0),%d3 /* load new longword */
393 move.w %d3,%d4 /* combine low word with old high word */
394 swap %d4 /* swap words */
395 move.l %d4,-(%a1) /* store longword */
396 cmp.l %d1,%a0 /* run %a0 down to last line bound */
397 jhi .lines_do2r_head_loop
398
399.lines_do2r_head_end:
400 swap %d3 /* get high word */
401 move.w %d3,-(%a1) /* and store it */
402
403.lines_do2r_selector:
404 move.l %a1,%d1
405 lsr.l #2,%d1
406 moveq.l #3,%d0 /* mask */
407 and.l %d0,%d1
408 moveq.l #16,%d7 /* address decrement for one main loop pass */
409 jmp.l (2,%pc,%d1.l*4) /* switch ((dest_addr >> 2) & 3) */
410 bra.w .lines_lo2r_start
411 bra.w .lines_lo6r_start
412 bra.w .lines_lo10r_start
413 /* bra.w .lines_lo14r_start implicit */
414
415 /* word aligned destination (line - 2): use line bursts in the loop */
416.lines_lo14r_start:
417 sub.l %d7,%a0
418 movem.l (%a0),%d0-%d3 /* load initial line */
419 move.w %d3,-(%a1) /* store last low word */
420 move.w %d2,%d3 /* combine 3rd low word with 4th high word */
421 swap %d3 /* swap words of 3rd long */
422 move.w %d1,%d2 /* combine 2nd low word with 3rd high word */
423 swap %d2 /* swap words of 2nd long */
424 move.w %d0,%d1 /* combine 1st low word with 2nd high word */
425 swap %d1 /* swap words of 1st long */
426 move.l %d3,-(%a1) /* store 3rd longword */
427 move.l %d2,-(%a1) /* store 2nd longword */
428 move.l %d1,-(%a1) /* store 1st longword */
429 cmp.l %a2,%a0 /* any full lines? */
430 jls .lines_lo14r_end /* no: skip main loop */
431
432.lines_lo14r_loop:
433 move.l %d0,%d4 /* move first longword of old line away */
434 sub.l %d7,%a0
435 movem.l (%a0),%d0-%d3 /* load line */
436 move.w %d3,%d4 /* combine 4th low word with old high word */
437 swap %d4 /* swap words of 4th long */
438 move.w %d2,%d3 /* combine 3rd low word with 4th high word */
439 swap %d3 /* swap words of 3rd long */
440 move.w %d1,%d2 /* combine 2nd low word with 3rd high word */
441 swap %d2 /* swap words of 2nd long */
442 move.w %d0,%d1 /* combine 1st low word with 2nd high word */
443 swap %d1 /* swap words of 1st long */
444 sub.l %d7,%a1
445 movem.l %d1-%d4,(%a1) /* store line */
446 cmp.l %a2,%a0 /* run %a0 down to first line bound */
447 jhi .lines_lo14r_loop
448
449 jra .lines_lo14r_end /* handle trailing longwords */
450
451 /* word aligned destination (line - 6): use line bursts in the loop */
452.lines_lo10r_start:
453 sub.l %d7,%a0
454 movem.l (%a0),%d0-%d3 /* load initial line */
455 move.w %d3,-(%a1) /* store last low word */
456 move.w %d2,%d3 /* combine 3rd low word with 4th high word */
457 swap %d3 /* swap words of 3rd long */
458 move.w %d1,%d2 /* combine 2nd low word with 3rd high word */
459 swap %d2 /* swap words of 2nd long */
460 move.l %d3,-(%a1) /* store 3rd longword */
461 move.l %d2,-(%a1) /* store 2nd longword */
462 jra .lines_lo10r_entry /* jump into main loop */
463
464.lines_lo10r_loop:
465 move.l %d0,%d4 /* move first 2 longwords of old line away */
466 move.l %d1,%d5
467 sub.l %d7,%a0
468 movem.l (%a0),%d0-%d3 /* load line */
469 move.w %d3,%d4 /* combine 4th low word with old high word */
470 swap %d4 /* swap words of 4th long */
471 move.w %d2,%d3 /* combine 3rd low word with 4th high word */
472 swap %d3 /* swap words of 3rd long */
473 move.w %d1,%d2 /* combine 2nd low word with 3rd high word */
474 swap %d2 /* swap words of 2nd long */
475 sub.l %d7,%a1
476 movem.l %d2-%d5,(%a1) /* store line */
477.lines_lo10r_entry:
478 move.w %d0,%d1 /* combine 1st low word with 2nd high word */
479 swap %d1 /* swap words of 1st long */
480 cmp.l %a2,%a0 /* run %a0 down to first line bound */
481 jhi .lines_lo10r_loop
482
483 jra .lines_lo10r_end /* handle trailing longwords */
484
485 /* word aligned destination (line - 10): use line bursts in the loop */
486.lines_lo6r_start:
487 sub.l %d7,%a0
488 movem.l (%a0),%d0-%d3 /* load initial line */
489 move.w %d3,-(%a1) /* store last low word */
490 move.w %d2,%d3 /* combine 3rd low word with 4th high word */
491 swap %d3 /* swap words of 3rd long */
492 move.l %d3,-(%a1) /* store 3rd longword */
493 jra .lines_lo6r_entry /* jump into main loop */
494
495.lines_lo6r_loop:
496 move.l %d0,%d4 /* move first 3 longwords of old line away */
497 move.l %d1,%d5
498 move.l %d2,%d6
499 sub.l %d7,%a0
500 movem.l (%a0),%d0-%d3 /* load line */
501 move.w %d3,%d4 /* combine 4th low word with old high word */
502 swap %d4 /* swap words of 4th long */
503 move.w %d2,%d3 /* combine 3rd low word with 4th high word */
504 swap %d3 /* swap words of 3rd long */
505 sub.l %d7,%a1
506 movem.l %d3-%d6,(%a1) /* store line */
507.lines_lo6r_entry:
508 move.w %d1,%d2 /* combine 2nd low word with 3rd high word */
509 swap %d2 /* swap words of 2nd long */
510 move.w %d0,%d1 /* combine 1st low word with 2nd high word */
511 swap %d1 /* swap words of 1st long */
512 cmp.l %a2,%a0 /* run %a0 down to first line bound */
513 jhi .lines_lo6r_loop
514
515 jra .lines_lo6r_end /* handle trailing longwords */
516
517 /* word aligned destination (line - 14): use line bursts in the loop */
518.lines_lo2r_start:
519 sub.l %d7,%a0
520 movem.l (%a0),%d0-%d3 /* load initial line */
521 move.w %d3,-(%a1) /* store last low word */
522 jra .lines_lo2r_entry /* jump into main loop */
523
524.lines_lo2r_loop:
525 move.l %d0,%d4 /* move old line away */
526 move.l %d1,%d5
527 move.l %d2,%d6
528 move.l %d3,%d7
529 lea.l (-16,%a0),%a0
530 movem.l (%a0),%d0-%d3 /* load line */
531 move.w %d3,%d4 /* combine 4th low word with old high word */
532 swap %d4 /* swap words of 4th long */
533 lea.l (-16,%a1),%a1
534 movem.l %d4-%d7,(%a1) /* store line */
535.lines_lo2r_entry:
536 move.w %d2,%d3 /* combine 3rd low word with 4th high word */
537 swap %d3 /* swap words of 3rd long */
538 move.w %d1,%d2 /* combine 2nd low word with 3rd high word */
539 swap %d2 /* swap words of 2nd long */
540 move.w %d0,%d1 /* combine 1st low word with 2nd high word */
541 swap %d1 /* swap words of 1st long */
542 cmp.l %a2,%a0 /* run %a0 down to first line bound */
543 jhi .lines_lo2r_loop
544
545 /* word aligned destination (line - 2/6/10/14): tail */
546.lines_lo2r_end:
547 move.l %d3,-(%a1) /* store third last longword */
548.lines_lo6r_end:
549 move.l %d2,-(%a1) /* store second last longword */
550.lines_lo10r_end:
551 move.l %d1,-(%a1) /* store last longword */
552.lines_lo14r_end:
553 lea.l (-12,%a2),%a2 /* readjust start address for doing longwords */
554 cmp.l %a2,%a0 /* any trailing longwords? */
555 jls .lines_do2r_tail_end /* no: skip tail loop */
556
557.lines_do2r_tail_loop:
558 move.l %d0,%d1 /* move old longword away */
559 move.l -(%a0),%d0 /* load new longword */
560 move.w %d0,%d1 /* combine low word with old high word */
561 swap %d1 /* swap words */
562 move.l %d1,-(%a1) /* store longword */
563 cmp.l %a2,%a0 /* run %a0 down to first long bound */
564 jhi .lines_do2r_tail_loop
565
566.lines_do2r_tail_end:
567 swap %d0 /* get final high word */
568 move.w %d0,-(%a1) /* store it */
569 /* jra .linesr_end implicit */
570
571#else /* !FULLSPEED */
572
573 /* word aligned destination (long - 2): use line burst reads in the loop */
574.lines_do2r_start:
575 cmp.l %d1,%a0 /* any leading longwords? */
576 jhi .lines_do2r_head_start /* yes: leading longword copy */
577
578 lea.l (-16,%a0),%a0
579 movem.l (%a0),%d3-%d6 /* load initial line */
580 move.w %d6,-(%a1) /* store last low word */
581 jra .lines_do2r_entry /* jump into main loop */
582
583.lines_do2r_head_start:
584 move.l -(%a0),%d3 /* load initial longword */
585 move.w %d3,-(%a1) /* store low word */
586 cmp.l %d1,%a0 /* any full longword? */
587 jls .lines_do2r_loop /* no: skip head loop */
588
589.lines_do2r_head_loop:
590 move.l %d3,%d4 /* move old longword away */
591 move.l -(%a0),%d3 /* load new longword */
592 move.w %d3,%d4 /* combine low word with old high word */
593 swap %d4 /* swap words */
594 move.l %d4,-(%a1) /* store longword */
595 cmp.l %d1,%a0 /* run %a0 down to last line bound */
596 jhi .lines_do2r_head_loop
597
598.lines_do2r_loop:
599 move.l %d3,%d7 /* move first longword of old line away */
600 lea.l (-16,%a0),%a0
601 movem.l (%a0),%d3-%d6 /* load line */
602 move.w %d6,%d7 /* combine 4th low word with old high word */
603 swap %d7 /* swap words of 4th long */
604 move.l %d7,-(%a1) /* store 4th longword */
605.lines_do2r_entry:
606 move.w %d5,%d6 /* combine 3rd low word with 4th high word */
607 swap %d6 /* swap words of 3rd long */
608 move.l %d6,-(%a1) /* store 3rd longword */
609 move.w %d4,%d5 /* combine 2nd low word with 3rd high word */
610 swap %d5 /* swap words of 2nd long */
611 move.l %d5,-(%a1) /* store 2nd longword */
612 move.w %d3,%d4 /* combine 1st low word with 2nd high word */
613 swap %d4 /* swap words of 1st long */
614 move.l %d4,-(%a1) /* store 1st longword */
615 cmp.l %a2,%a0 /* run %a0 down to first line bound */
616 jhi .lines_do2r_loop
617
618.lines_do2r_end:
619 lea.l (-12,%a2),%a2 /* readjust start address for doing longwords */
620 cmp.l %a2,%a0 /* any trailing longwords? */
621 jls .lines_do2r_tail_end /* no: skip tail loop */
622
623.lines_do2r_tail_loop:
624 move.l %d3,%d4 /* move old longword away */
625 move.l -(%a0),%d3 /* load new longword */
626 move.w %d3,%d4 /* combine low word with old high word */
627 swap %d4 /* swap words */
628 move.l %d4,-(%a1) /* store longword */
629 cmp.l %a2,%a0 /* run %a0 down to first long bound */
630 jhi .lines_do2r_tail_loop
631
632.lines_do2r_tail_end:
633 swap %d3 /* get final high word */
634 move.w %d3,-(%a1) /* store it */
635 /* jra .linesr_end implicit */
636
637#endif /* !FULLSPEED */
638
639.linesr_end:
640 subq.l #3,%a2 /* readjust end address */
641 move.l %a2,%d0 /* start address in %d0 again */
642 movem.l (%sp),%d2-%d7/%a2 /* restore registers */
643 lea.l (28,%sp),%sp
644 jra .bytes2r_start /* jump to trailing byte loop */
645
646.longr_start:
647 addq.l #3,%d0 /* adjust start address for doing 4 bytes/ pass */
648
649 /* longword copy loop - no lines */
650.longr_loop:
651 move.l -(%a0),-(%a1) /* copy longword (write can be unaligned) */
652 cmp.l %d0,%a0 /* runs %a0 down to first long bound */
653 jhi .longr_loop
654
655 subq.l #3,%d0 /* readjust start address */
656 cmp.l %d0,%a0 /* any bytes left? */
657 jls .bytes2r_end /* no: skip trailing byte loop */
658
659 /* trailing byte loop */
660.bytes2r_loop:
661 move.b -(%a0),-(%a1) /* copy byte */
662.bytes2r_start:
663 cmp.l %d0,%a0 /* runs %a0 down to start address */
664 jhi .bytes2r_loop
665
666.bytes2r_end:
667 rts /* returns start address */
668
669.end:
670 .size memmove,.end-memmove