summaryrefslogtreecommitdiff
path: root/firmware/common/memset16_a.S
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/common/memset16_a.S')
-rwxr-xr-xfirmware/common/memset16_a.S146
1 files changed, 146 insertions, 0 deletions
diff --git a/firmware/common/memset16_a.S b/firmware/common/memset16_a.S
new file mode 100755
index 0000000000..9ab1bdcb5b
--- /dev/null
+++ b/firmware/common/memset16_a.S
@@ -0,0 +1,146 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Jens Arnold
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "config.h"
20
21 .section .icode,"ax",@progbits
22
23#ifdef CPU_COLDFIRE
24 .global memset16
25 .type memset16,@function
26
27/* Fills a memory region with specified word value
28 * Start address must be word aligned, length is in words
29 * This version is optimized for speed
30 *
31 * arguments:
32 * (4,%sp) - start address
33 * (8,%sp) - data
34 * (12,%sp) - length
35 *
36 * return value:
37 * %d0 - start address
38 *
39 * register usage:
40 * %d0 - data (spread to both words when using long stores)
41 * %d1 - temporary / data (for burst transfer)
42 * %d2 - data (for burst transfer)
43 * %d3 - data (for burst transfer)
44 * %a0 - start address
45 * %a1 - current address (runs down from end to start)
46 *
47 * For maximum speed this routine uses both long stores and burst mode,
48 * storing whole lines with movem.l. The routine fills memory from end
49 * to start in order to ease returning the start address.
50 */
51memset16:
52 move.l (4,%sp),%a0 /* start address */
53 move.l (8,%sp),%d0 /* data */
54 move.l (12,%sp),%a1 /* length */
55 add.l %a1,%a1
56 add.l %a0,%a1 /* %a1 = end address */
57
58 move.l %a0,%d1
59 addq.l #6,%d1
60 and.l #0xFFFFFFFC,%d1 /* %d1 = first long bound + 4 */
61 cmp.l %d1,%a1 /* at least one aligned longword to fill? */
62 blo.b .no_longs /* no, jump directly to word loop */
63
64 and.l #0xFFFF,%d0 /* start: spread data to both words */
65 move.l %d0,%d1
66 swap %d1
67 or.l %d1,%d0 /* data now in both words */
68
69 move.l %a1,%d1
70 and.l #0xFFFFFFFC,%d1 /* %d1 = last long bound */
71 cmp.l %d1,%a1 /* one extra word? */
72 bls.b .end_w1 /* no: skip */
73
74 move.w %d0,-(%a1) /* set leading word */
75
76.end_w1:
77 moveq.l #30,%d1
78 add.l %a0,%d1
79 and.l #0xFFFFFFF0,%d1 /* %d1 = first line bound + 16 */
80 cmp.l %d1,%a1 /* at least one full line to fill? */
81 blo.b .no_lines /* no, jump to longword loop */
82
83 mov.l %a1,%d1
84 and.l #0xFFFFFFF0,%d1 /* %d1 = last line bound */
85 cmp.l %d1,%a1 /* any longwords to set? */
86 bls.b .end_l1 /* no: skip longword loop */
87
88 /* leading longword loop: sets 0..3 longwords */
89.loop_l1:
90 move.l %d0,-(%a1) /* store longword */
91 cmp.l %d1,%a1 /* runs %a1 down to last line bound */
92 bhi.b .loop_l1
93
94.end_l1:
95 move.l %d2,-(%sp) /* free some registers */
96 move.l %d3,-(%sp)
97
98 move.l %d0,%d1 /* spread data to 4 data registers */
99 move.l %d0,%d2
100 move.l %d0,%d3
101 lea.l (14,%a0),%a0 /* start address += 14, acct. for trl. data */
102
103 /* main loop: set whole lines utilising burst mode */
104.loop_line:
105 lea.l (-16,%a1),%a1 /* pre-decrement */
106 movem.l %d0-%d3,(%a1) /* store line */
107 cmp.l %a0,%a1 /* runs %a1 down to first line bound */
108 bhi.b .loop_line
109
110 lea.l (-14,%a0),%a0 /* correct start address */
111 move.l (%sp)+,%d3 /* restore registers */
112 move.l (%sp)+,%d2
113
114 move.l %a0,%d1 /* %d1 = start address ... */
115 addq.l #2,%d1 /* ... +2, account for possible trailing word */
116 cmp.l %d1,%a1 /* any longwords left */
117 bhi.b .loop_l2 /* yes: jump to longword loop */
118 bra.b .no_longs /* no: skip loop */
119
120.no_lines:
121 move.l %a0,%d1 /* %d1 = start address ... */
122 addq.l #2,%d1 /* ... +2, account for possible trailing word */
123
124 /* trailing longword loop */
125.loop_l2:
126 move.l %d0,-(%a1) /* store longword */
127 cmp.l %d1,%a1 /* runs %a1 down to first long bound */
128 bhi.b .loop_l2
129
130.no_longs:
131 cmp.l %a0,%a1 /* any words left? */
132 bls.b .end_w2 /* no: skip loop */
133
134 /* trailing word loop */
135.loop_w2:
136 move.w %d0,-(%a1) /* store word */
137 cmp.l %a0,%a1 /* runs %a1 down to start address */
138 bhi.b .loop_w2
139
140.end_w2:
141 move.l %a0,%d0 /* return start address */
142 rts
143
144.end:
145 .size memset16,.end-memset16
146#endif