1 /* $NetBSD: blockio.S,v 1.5 2002/08/15 01:38:16 briggs Exp $ */
4 * Copyright (c) 2001 Ben Harris.
5 * Copyright (c) 1994 Mark Brinicombe.
6 * Copyright (c) 1994 Brini.
9 * This code is derived from software written for Brini by Mark Brinicombe
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by Brini.
22 * 4. The name of the company nor the name of the author may be used to
23 * endorse or promote products derived from this software without specific
24 * prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
30 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * RiscBSD kernel project
42 * optimised block read/write from/to IO routines.
45 * Modified : 22/01/99 -- R.Earnshaw
46 * Faster, and small tweaks for StrongARM
49 #include <machine/asm.h>
51 __FBSDID("$FreeBSD$");
54 * Read bytes from an I/O address into a block of memory
56 * r0 = address to read from (IO)
57 * r1 = address to write to (memory)
61 /* This code will look very familiar if you've read _memcpy(). */
64 stmfd sp!, {fp, ip, lr, pc}
66 subs r2, r2, #4 /* r2 = length - 4 */
67 blt .Lrm1_l4 /* less than 4 bytes */
69 beq .Lrm1_main /* aligned destination */
84 orr r3, r3, r12, lsl #8
86 orr r3, r3, r12, lsl #16
88 orr r3, r3, r12, lsl #24
93 adds r2, r2, #4 /* r2 = length again */
94 ldmeqdb fp, {fp, sp, pc}
103 ldmdb fp, {fp, sp, pc}
106 * Write bytes to an I/O address from a block of memory
108 * r0 = address to write to (IO)
109 * r1 = address to read from (memory)
113 /* This code will look very familiar if you've read _memcpy(). */
116 stmfd sp!, {fp, ip, lr, pc}
118 subs r2, r2, #4 /* r2 = length - 4 */
119 blt .Lwm1_l4 /* less than 4 bytes */
121 beq .Lwm1_main /* aligned source */
145 adds r2, r2, #4 /* r2 = length again */
146 ldmeqdb fp, {fp, sp, pc}
154 ldmdb fp, {fp, sp, pc}
157 * Reads short ints (16 bits) from an I/O address into a block of memory
159 * r0 = address to read from (IO)
160 * r1 = address to write to (memory)
165 /* Make sure that we have a positive length */
169 /* If the destination address and the size is word aligned, do it fast */
172 tsteq r1, #0x00000003
175 /* Non aligned insw */
179 subs r2, r2, #0x00000001 /* Loop test in load delay slot */
180 strb r3, [r1], #0x0001
182 strb r3, [r1], #0x0001
187 /* Word aligned insw */
192 ldr r3, [r0, #0x0002] /* take advantage of nonaligned
195 mov r3, r3, lsr #16 /* Put the two shorts together */
196 orr r3, r3, ip, lsl #16
197 str r3, [r1], #0x0004 /* Store */
198 subs r2, r2, #0x00000002 /* Next */
205 * Writes short ints (16 bits) from a block of memory to an I/O address
207 * r0 = address to write to (IO)
208 * r1 = address to read from (memory)
213 /* Make sure that we have a positive length */
217 /* If the destination address and the size is word aligned, do it fast */
220 tsteq r1, #0x00000003
223 /* Non aligned outsw */
226 ldrb r3, [r1], #0x0001
227 ldrb ip, [r1], #0x0001
228 subs r2, r2, #0x00000001 /* Loop test in load delay slot */
229 orr r3, r3, ip, lsl #8
230 orr r3, r3, r3, lsl #16
236 /* Word aligned outsw */
241 ldr r3, [r1], #0x0004 /* r3 = (H)(L) */
242 subs r2, r2, #0x00000002 /* Loop test in load delay slot */
244 eor ip, r3, r3, lsr #16 /* ip = (H)(H^L) */
245 eor r3, r3, ip, lsl #16 /* r3 = (H^H^L)(L) = (L)(L) */
246 eor ip, ip, r3, lsr #16 /* ip = (H)(H^L^L) = (H)(H) */
251 /* mov ip, r3, lsl #16
252 * orr ip, ip, ip, lsr #16
255 * mov ip, r3, lsr #16
256 * orr ip, ip, ip, lsl #16
265 * reads short ints (16 bits) from an I/O address into a block of memory
266 * with a length garenteed to be a multiple of 16 bytes
267 * with a word aligned destination address
269 * r0 = address to read from (IO)
270 * r1 = address to write to (memory)
275 /* Make sure that we have a positive length */
279 /* If the destination address is word aligned and the size suitably
280 aligned, do it fast */
283 tsteq r1, #0x00000003
287 /* Word aligned insw */
289 stmfd sp!, {r4,r5,lr}
292 ldr r3, [r0, #0x0002] /* take advantage of nonaligned
295 mov r3, r3, lsr #16 /* Put the two shorts together */
296 orr r3, r3, lr, lsl #16
298 ldr r4, [r0, #0x0002] /* take advantage of nonaligned
301 mov r4, r4, lsr #16 /* Put the two shorts together */
302 orr r4, r4, lr, lsl #16
304 ldr r5, [r0, #0x0002] /* take advantage of nonaligned
307 mov r5, r5, lsr #16 /* Put the two shorts together */
308 orr r5, r5, lr, lsl #16
310 ldr ip, [r0, #0x0002] /* take advantage of nonaligned
313 mov ip, ip, lsr #16 /* Put the two shorts together */
314 orr ip, ip, lr, lsl #16
316 stmia r1!, {r3-r5,ip}
317 subs r2, r2, #0x00000008 /* Next */
320 ldmfd sp!, {r4,r5,pc} /* Restore regs and go home */
324 * Writes short ints (16 bits) from a block of memory to an I/O address
326 * r0 = address to write to (IO)
327 * r1 = address to read from (memory)
332 /* Make sure that we have a positive length */
336 /* If the destination address is word aligned and the size suitably
337 aligned, do it fast */
340 tsteq r1, #0x00000003
344 /* Word aligned outsw */
346 stmfd sp!, {r4,r5,lr}
349 ldmia r1!, {r4,r5,ip,lr}
351 eor r3, r4, r4, lsl #16 /* r3 = (A^B)(B) */
352 eor r4, r4, r3, lsr #16 /* r4 = (A)(B^A^B) = (A)(A) */
353 eor r3, r3, r4, lsl #16 /* r3 = (A^B^A)(B) = (B)(B) */
357 /* mov r3, r4, lsl #16
358 * orr r3, r3, r3, lsr #16
361 * mov r3, r4, lsr #16
362 * orr r3, r3, r3, lsl #16
366 eor r3, r5, r5, lsl #16 /* r3 = (A^B)(B) */
367 eor r5, r5, r3, lsr #16 /* r4 = (A)(B^A^B) = (A)(A) */
368 eor r3, r3, r5, lsl #16 /* r3 = (A^B^A)(B) = (B)(B) */
372 eor r3, ip, ip, lsl #16 /* r3 = (A^B)(B) */
373 eor ip, ip, r3, lsr #16 /* r4 = (A)(B^A^B) = (A)(A) */
374 eor r3, r3, ip, lsl #16 /* r3 = (A^B^A)(B) = (B)(B) */
378 eor r3, lr, lr, lsl #16 /* r3 = (A^B)(B) */
379 eor lr, lr, r3, lsr #16 /* r4 = (A)(B^A^B) = (A)(A) */
380 eor r3, r3, lr, lsl #16 /* r3 = (A^B^A)(B) = (B)(B) */
384 subs r2, r2, #0x00000008
387 ldmfd sp!, {r4,r5,pc} /* and go home */
390 * reads short ints (16 bits) from an I/O address into a block of memory
391 * The I/O address is assumed to be mapped multiple times in a block of
393 * The destination address should be word aligned.
395 * r0 = address to read from (IO)
396 * r1 = address to write to (memory)
401 /* Make sure that we have a positive length */
405 /* If the destination address is word aligned and the size suitably
406 aligned, do it fast */
412 /* Word aligned insw */
414 stmfd sp!, {r4-r9,lr}
417 orr lr, lr, #0x00ff0000
426 orr r3, r3, r4, lsl #16
428 orr r4, r5, r6, lsl #16
430 orr r5, r7, r8, lsl #16
432 orr r6, r9, ip, lsl #16
436 subs r2, r2, #0x00000008 /* Next */
447 orr r3, r3, r4, lsl #16
449 orr r4, r5, r6, lsl #16
453 subs r2, r2, #0x00000004
463 orr r3, r3, r4, lsl #16
464 str r3, [r1], #0x0004
466 subs r2, r2, #0x00000002
474 subs r2, r2, #0x00000001 /* Test in load delay slot */
475 /* XXX, why don't we use result? */
477 strb r3, [r1], #0x0001
479 strb r3, [r1], #0x0001
483 ldmfd sp!, {r4-r9,pc} /* And go home */
486 * write short ints (16 bits) to an I/O address from a block of memory
487 * The I/O address is assumed to be mapped multiple times in a block of
489 * The source address should be word aligned.
491 * r0 = address to read to (IO)
492 * r1 = address to write from (memory)
497 /* Make sure that we have a positive length */
501 /* If the destination address is word aligned and the size suitably
502 aligned, do it fast */
508 /* Word aligned outsw */
510 stmfd sp!, {r4-r8,lr}
516 ldmia r1!, {r3,r5,r7,ip}
518 eor r4, r3, r3, lsr #16 /* r4 = (A)(A^B) */
519 eor r3, r3, r4, lsl #16 /* r3 = (A^A^B)(B) = (B)(B) */
520 eor r4, r4, r3, lsr #16 /* r4 = (A)(B^A^B) = (A)(A) */
522 eor r6, r5, r5, lsr #16 /* r6 = (A)(A^B) */
523 eor r5, r5, r6, lsl #16 /* r5 = (A^A^B)(B) = (B)(B) */
524 eor r6, r6, r5, lsr #16 /* r6 = (A)(B^A^B) = (A)(A) */
526 eor r8, r7, r7, lsr #16 /* r8 = (A)(A^B) */
527 eor r7, r7, r8, lsl #16 /* r7 = (A^A^B)(B) = (B)(B) */
528 eor r8, r8, r7, lsr #16 /* r8 = (A)(B^A^B) = (A)(A) */
530 eor lr, ip, ip, lsr #16 /* lr = (A)(A^B) */
531 eor ip, ip, lr, lsl #16 /* ip = (A^A^B)(B) = (B)(B) */
532 eor lr, lr, ip, lsr #16 /* lr = (A)(B^A^B) = (A)(A) */
534 stmia r0, {r3-r8,ip,lr}
536 subs r2, r2, #0x00000008 /* Next */
546 eor r6, r3, r3, lsr #16 /* r6 = (A)(A^B) */
547 eor r5, r3, r6, lsl #16 /* r5 = (A^A^B)(B) = (B)(B) */
548 eor r6, r6, r5, lsr #16 /* r6 = (A)(B^A^B) = (A)(A) */
550 eor r8, r4, r4, lsr #16 /* r8 = (A)(A^B) */
551 eor r7, r4, r8, lsl #16 /* r7 = (A^A^B)(B) = (B)(B) */
552 eor r8, r8, r7, lsr #16 /* r8 = (A)(B^A^B) = (A)(A) */
556 subs r2, r2, #0x00000004
563 ldr r3, [r1], #0x0004 /* r3 = (A)(B) */
564 subs r2, r2, #0x00000002 /* Done test in Load delay slot */
566 eor r5, r3, r3, lsr #16 /* r5 = (A)(A^B)*/
567 eor r4, r3, r5, lsl #16 /* r4 = (A^A^B)(B) = (B)(B) */
568 eor r5, r5, r4, lsr #16 /* r5 = (A)(B^A^B) = (A)(A) */
578 ldrb r3, [r1], #0x0001
579 ldrb r4, [r1], #0x0001
580 subs r2, r2, #0x00000001 /* Done test in load delay slot */
581 /* XXX This test isn't used? */
582 orr r3, r3, r4, lsl #8
583 orr r3, r3, r3, lsl #16
587 ldmfd sp!, {r4-r8,pc} /* And go home */