summaryrefslogtreecommitdiff
path: root/firmware/target/coldfire/memset-coldfire.S
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/coldfire/memset-coldfire.S')
-rwxr-xr-xfirmware/target/coldfire/memset-coldfire.S150
1 files changed, 150 insertions, 0 deletions
diff --git a/firmware/target/coldfire/memset-coldfire.S b/firmware/target/coldfire/memset-coldfire.S
new file mode 100755
index 0000000000..7c9fe88463
--- /dev/null
+++ b/firmware/target/coldfire/memset-coldfire.S
@@ -0,0 +1,150 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2004 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 .align 2
24 .global memset
25 .type memset,@function
26
27/* Fills a memory region with specified byte value
28 * This version is optimized for speed
29 *
30 * arguments:
31 * (4,%sp) - start address
32 * (8,%sp) - data
33 * (12,%sp) - length
34 *
35 * return value:
36 * %d0 - start address (like ANSI version)
37 *
38 * register usage:
39 * %d0 - data (spread to all 4 bytes when using long stores)
40 * %d1 - temporary / data (for burst transfer)
41 * %d2 - data (for burst transfer)
42 * %d3 - data (for burst transfer)
43 * %a0 - start address
44 * %a1 - current address (runs down from end to start)
45 *
46 * For maximum speed this routine uses both long stores and burst mode,
47 * storing whole lines with movem.l. The routine fills memory from end
48 * to start in order to ease returning the start address.
49 */
50memset:
51 move.l (4,%sp),%a0 /* start address */
52 move.l (8,%sp),%d0 /* data */
53 move.l (12,%sp),%a1 /* length */
54 add.l %a0,%a1 /* %a1 = end address */
55
56 move.l %a0,%d1
57 addq.l #7,%d1
58 and.l #0xFFFFFFFC,%d1 /* %d1 = first long bound + 4 */
59 cmp.l %d1,%a1 /* at least one aligned longword to fill? */
60 blo.b .no_longs /* no, jump directly to byte loop */
61
62 and.l #0xFF,%d0 /* start: spread data to all 4 bytes */
63 move.l %d0,%d1
64 lsl.l #8,%d1
65 or.l %d1,%d0 /* data now in 2 lower bytes of %d0 */
66 move.l %d0,%d1
67 swap %d0
68 or.l %d1,%d0 /* data now in all 4 bytes of %d0 */
69
70 move.l %a1,%d1
71 and.l #0xFFFFFFFC,%d1 /* %d1 = last long bound */
72 cmp.l %d1,%a1 /* any bytes to set? */
73 bls.b .end_b1 /* no: skip byte loop */
74
75 /* leading byte loop: sets 0..3 bytes */
76.loop_b1:
77 move.b %d0,-(%a1) /* store byte */
78 cmp.l %d1,%a1 /* runs %a1 down to last long bound */
79 bhi.b .loop_b1
80
81.end_b1:
82 moveq.l #31,%d1
83 add.l %a0,%d1
84 and.l #0xFFFFFFF0,%d1 /* %d1 = first line bound + 16 */
85 cmp.l %d1,%a1 /* at least one full line to fill? */
86 blo.b .no_lines /* no, jump to longword loop */
87
88 mov.l %a1,%d1
89 and.l #0xFFFFFFF0,%d1 /* %d1 = last line bound */
90 cmp.l %d1,%a1 /* any longwords to set? */
91 bls.b .end_l1 /* no: skip longword loop */
92
93 /* leading longword loop: sets 0..3 longwords */
94.loop_l1:
95 move.l %d0,-(%a1) /* store longword */
96 cmp.l %d1,%a1 /* runs %a1 down to last line bound */
97 bhi.b .loop_l1
98
99.end_l1:
100 move.l %d2,-(%sp) /* free some registers */
101 move.l %d3,-(%sp)
102
103 move.l %d0,%d1 /* spread data to 4 data registers */
104 move.l %d0,%d2
105 move.l %d0,%d3
106 lea.l (15,%a0),%a0 /* start address += 15, acct. for trl. data */
107
108 /* main loop: set whole lines utilising burst mode */
109.loop_line:
110 lea.l (-16,%a1),%a1 /* pre-decrement */
111 movem.l %d0-%d3,(%a1) /* store line */
112 cmp.l %a0,%a1 /* runs %a1 down to first line bound */
113 bhi.b .loop_line
114
115 lea.l (-15,%a0),%a0 /* correct start address */
116 move.l (%sp)+,%d3 /* restore registers */
117 move.l (%sp)+,%d2
118
119 move.l %a0,%d1 /* %d1 = start address ... */
120 addq.l #3,%d1 /* ... +3, account for possible trailing bytes */
121 cmp.l %d1,%a1 /* any longwords left */
122 bhi.b .loop_l2 /* yes: jump to longword loop */
123 bra.b .no_longs /* no: skip loop */
124
125.no_lines:
126 move.l %a0,%d1 /* %d1 = start address ... */
127 addq.l #3,%d1 /* ... +3, account for possible trailing bytes */
128
129 /* trailing longword loop */
130.loop_l2:
131 move.l %d0,-(%a1) /* store longword */
132 cmp.l %d1,%a1 /* runs %a1 down to first long bound */
133 bhi.b .loop_l2
134
135.no_longs:
136 cmp.l %a0,%a1 /* any bytes left? */
137 bls.b .end_b2 /* no: skip loop */
138
139 /* trailing byte loop */
140.loop_b2:
141 move.b %d0,-(%a1) /* store byte */
142 cmp.l %a0,%a1 /* runs %a1 down to start address */
143 bhi.b .loop_b2
144
145.end_b2:
146 move.l %a0,%d0 /* return start address */
147 rts
148
149.end:
150 .size memset,.end-memset