Factor out some drawing code.
[kugel-rb.git] / firmware / target / coldfire / memset16-coldfire.S
blob1673038d033c176d0fbb67b9b2379c0bf9b7ed47
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     .global     memset16
26     .type       memset16,@function
28 /* Fills a memory region with specified word value
29  * Start address must be word aligned, length is in words
30  * This version is optimized for speed
31  *
32  * arguments:
33  *  (4,%sp)  - start address
34  *  (8,%sp)  - data
35  *  (12,%sp) - length
36  *
37  * return value:
38  *  %d0 - start address
39  *
40  * register usage:
41  *  %d0 - data (spread to both words when using long stores)
42  *  %d1 - temporary / data (for burst transfer)
43  *  %d2 - data (for burst transfer)
44  *  %d3 - data (for burst transfer)
45  *  %a0 - start address
46  *  %a1 - current address (runs down from end to start)
47  *
48  * For maximum speed this routine uses both long stores and burst mode,
49  * storing whole lines with movem.l. The routine fills memory from end
50  * to start in order to ease returning the start address.
51  */
52 memset16:
53     move.l  (4,%sp),%a0     /* start address */
54     move.l  (8,%sp),%d0     /* data */
55     move.l  (12,%sp),%a1    /* length */
56     add.l   %a1,%a1
57     add.l   %a0,%a1         /* %a1 = end address */
59     move.l  %a0,%d1
60     addq.l  #6,%d1
61     and.l   #0xFFFFFFFC,%d1 /* %d1 = first long bound + 4 */
62     cmp.l   %d1,%a1         /* at least one aligned longword to fill? */
63     blo.b   .no_longs       /* no, jump directly to word loop */
65     and.l   #0xFFFF,%d0     /* start: spread data to both words */
66     move.l  %d0,%d1
67     swap    %d1
68     or.l    %d1,%d0         /* data now in both words */
70     move.l  %a1,%d1
71     and.l   #0xFFFFFFFC,%d1 /* %d1 = last long bound */
72     cmp.l   %d1,%a1         /* one extra word? */
73     bls.b   .end_w1         /* no: skip */
75     move.w  %d0,-(%a1)      /* set leading word */
77 .end_w1:
78     moveq.l #30,%d1
79     add.l   %a0,%d1
80     and.l   #0xFFFFFFF0,%d1 /* %d1 = first line bound + 16 */
81     cmp.l   %d1,%a1         /* at least one full line to fill? */
82     blo.b   .no_lines       /* no, jump to longword loop */
84     mov.l   %a1,%d1
85     and.l   #0xFFFFFFF0,%d1 /* %d1 = last line bound */
86     cmp.l   %d1,%a1         /* any longwords to set? */
87     bls.b   .end_l1         /* no: skip longword loop */
89     /* leading longword loop: sets 0..3 longwords */
90 .loop_l1:
91     move.l  %d0,-(%a1)      /* store longword */
92     cmp.l   %d1,%a1         /* runs %a1 down to last line bound */
93     bhi.b   .loop_l1
95 .end_l1:
96     move.l  %d2,-(%sp)      /* free some registers */
97     move.l  %d3,-(%sp)
99     move.l  %d0,%d1         /* spread data to 4 data registers */
100     move.l  %d0,%d2
101     move.l  %d0,%d3
102     lea.l   (14,%a0),%a0    /* start address += 14, acct. for trl. data */
103     
104     /* main loop: set whole lines utilising burst mode */
105 .loop_line:
106     lea.l   (-16,%a1),%a1   /* pre-decrement */
107     movem.l %d0-%d3,(%a1)   /* store line */
108     cmp.l   %a0,%a1         /* runs %a1 down to first line bound */
109     bhi.b   .loop_line
111     lea.l   (-14,%a0),%a0   /* correct start address */
112     move.l  (%sp)+,%d3      /* restore registers */
113     move.l  (%sp)+,%d2
115     move.l  %a0,%d1         /* %d1 = start address ... */
116     addq.l  #2,%d1          /* ... +2, account for possible trailing word */
117     cmp.l   %d1,%a1         /* any longwords left */
118     bhi.b   .loop_l2        /* yes: jump to longword loop */
119     bra.b   .no_longs       /* no: skip loop */
121 .no_lines:
122     move.l  %a0,%d1         /* %d1 = start address ... */
123     addq.l  #2,%d1          /* ... +2, account for possible trailing word */
125     /* trailing longword loop */
126 .loop_l2:
127     move.l  %d0,-(%a1)      /* store longword */
128     cmp.l   %d1,%a1         /* runs %a1 down to first long bound */
129     bhi.b   .loop_l2
131 .no_longs:
132     cmp.l   %a0,%a1         /* any words left? */
133     bls.b   .end_w2         /* no: skip loop */
135     /* trailing word loop */
136 .loop_w2:
137     move.w  %d0,-(%a1)      /* store word */
138     cmp.l   %a0,%a1         /* runs %a1 down to start address */
139     bhi.b   .loop_w2
141 .end_w2:
142     move.l  %a0,%d0         /* return start address */
143     rts
145 .end:
146     .size   memset16,.end-memset16