FS#8961 - Anti-Aliased Fonts.
[kugel-rb.git] / firmware / target / coldfire / memmove-coldfire.S
blob736cd619e1f259d0a7e21a837ede70d56926a0e3
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"
23     .section    .icode,"ax",@progbits
25 #define FULLSPEED /* use burst writing for word aligned destinations */
26     .align  2
27     .global memmove
28     .type   memmove,@function
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  */
57 memmove:
58     move.l  (4,%sp),%a1     /* Destination */
59     move.l  (8,%sp),%a0     /* Source */
60     move.l  (12,%sp),%d1    /* Length */
62     cmp.l   %a0,%a1
63     bhi.b   .backward       /* dest > src -> backward copy */
64     jmp     __memcpy_fwd_entry
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 */
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
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
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)
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 */
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
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
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 */
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 */
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
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
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
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 */
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
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
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 */
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
306     jra     .lines_lo12r_end   /* handle trailing longwords */
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
318     jra     .lines_lo0r_end /* handle trailing longwords */
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
339     jra     .lines_lo8r_end /* handle trailing longwords */
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
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 */
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
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 */
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 */
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 */
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 */
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 */
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 */
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 */
571 #else /* !FULLSPEED */
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 */
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
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
632 .lines_do2r_tail_end:
633     swap    %d3             /* get final high word */
634     move.w  %d3,-(%a1)      /* store it */
635  /* jra     .linesr_end    implicit */
637 #endif /* !FULLSPEED */
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 */
646 .longr_start:
647     addq.l  #3,%d0          /* adjust start address for doing 4 bytes/ pass */
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
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 */
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
666 .bytes2r_end:
667     rts                     /* returns start address */
669 .end:
670     .size   memmove,.end-memmove