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>
53 * Read bytes from an I/O address into a block of memory
55 * r0 = address to read from (IO)
56 * r1 = address to write to (memory)
60 /* This code will look very familiar if you've read _memcpy(). */
63 stmfd sp!, {fp, ip, lr, pc}
65 subs r2, r2, #4 /* r2 = length - 4 */
66 blt .Lrm1_l4 /* less than 4 bytes */
68 beq .Lrm1_main /* aligned destination */
83 orr r3, r3, r12, lsl #8
85 orr r3, r3, r12, lsl #16
87 orr r3, r3, r12, lsl #24
92 adds r2, r2, #4 /* r2 = length again */
93 ldmdbeq fp, {fp, sp, pc}
102 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 ldmdbeq fp, {fp, sp, pc}
154 ldmdb fp, {fp, sp, pc}
158 * Reads short ints (16 bits) from an I/O address into a block of memory
160 * r0 = address to read from (IO)
161 * r1 = address to write to (memory)
166 /* Make sure that we have a positive length */
170 /* If the destination address and the size is word aligned, do it fast */
173 tsteq r1, #0x00000003
176 /* Non aligned insw */
180 subs r2, r2, #0x00000001 /* Loop test in load delay slot */
181 strb r3, [r1], #0x0001
183 strb r3, [r1], #0x0001
188 /* Word aligned insw */
193 ldr r3, [r0, #0x0002] /* take advantage of nonaligned
196 mov r3, r3, lsr #16 /* Put the two shorts together */
197 orr r3, r3, ip, lsl #16
198 str r3, [r1], #0x0004 /* Store */
199 subs r2, r2, #0x00000002 /* Next */
206 * Writes short ints (16 bits) from a block of memory to an I/O address
208 * r0 = address to write to (IO)
209 * r1 = address to read from (memory)
214 /* Make sure that we have a positive length */
218 /* If the destination address and the size is word aligned, do it fast */
221 tsteq r1, #0x00000003
224 /* Non aligned outsw */
227 ldrb r3, [r1], #0x0001
228 ldrb ip, [r1], #0x0001
229 subs r2, r2, #0x00000001 /* Loop test in load delay slot */
230 orr r3, r3, ip, lsl #8
231 orr r3, r3, r3, lsl #16
237 /* Word aligned outsw */
242 ldr r3, [r1], #0x0004 /* r3 = (H)(L) */
243 subs r2, r2, #0x00000002 /* Loop test in load delay slot */
245 eor ip, r3, r3, lsr #16 /* ip = (H)(H^L) */
246 eor r3, r3, ip, lsl #16 /* r3 = (H^H^L)(L) = (L)(L) */
247 eor ip, ip, r3, lsr #16 /* ip = (H)(H^L^L) = (H)(H) */
252 /* mov ip, r3, lsl #16
253 * orr ip, ip, ip, lsr #16
256 * mov ip, r3, lsr #16
257 * orr ip, ip, ip, lsl #16
267 * reads short ints (16 bits) from an I/O address into a block of memory
268 * with a length garenteed to be a multiple of 16 bytes
269 * with a word aligned destination address
271 * r0 = address to read from (IO)
272 * r1 = address to write to (memory)
277 /* Make sure that we have a positive length */
281 /* If the destination address is word aligned and the size suitably
282 aligned, do it fast */
285 tsteq r1, #0x00000003
289 /* Word aligned insw */
291 stmfd sp!, {r4,r5,lr}
294 ldr r3, [r0, #0x0002] /* take advantage of nonaligned
297 mov r3, r3, lsr #16 /* Put the two shorts together */
298 orr r3, r3, lr, lsl #16
300 ldr r4, [r0, #0x0002] /* take advantage of nonaligned
303 mov r4, r4, lsr #16 /* Put the two shorts together */
304 orr r4, r4, lr, lsl #16
306 ldr r5, [r0, #0x0002] /* take advantage of nonaligned
309 mov r5, r5, lsr #16 /* Put the two shorts together */
310 orr r5, r5, lr, lsl #16
312 ldr ip, [r0, #0x0002] /* take advantage of nonaligned
315 mov ip, ip, lsr #16 /* Put the two shorts together */
316 orr ip, ip, lr, lsl #16
318 stmia r1!, {r3-r5,ip}
319 subs r2, r2, #0x00000008 /* Next */
322 ldmfd sp!, {r4,r5,pc} /* Restore regs and go home */
326 * Writes short ints (16 bits) from a block of memory to an I/O address
328 * r0 = address to write to (IO)
329 * r1 = address to read from (memory)
334 /* Make sure that we have a positive length */
338 /* If the destination address is word aligned and the size suitably
339 aligned, do it fast */
342 tsteq r1, #0x00000003
346 /* Word aligned outsw */
348 stmfd sp!, {r4,r5,lr}
351 ldmia r1!, {r4,r5,ip,lr}
353 eor r3, r4, r4, lsl #16 /* r3 = (A^B)(B) */
354 eor r4, r4, r3, lsr #16 /* r4 = (A)(B^A^B) = (A)(A) */
355 eor r3, r3, r4, lsl #16 /* r3 = (A^B^A)(B) = (B)(B) */
359 /* mov r3, r4, lsl #16
360 * orr r3, r3, r3, lsr #16
363 * mov r3, r4, lsr #16
364 * orr r3, r3, r3, lsl #16
368 eor r3, r5, r5, lsl #16 /* r3 = (A^B)(B) */
369 eor r5, r5, r3, lsr #16 /* r4 = (A)(B^A^B) = (A)(A) */
370 eor r3, r3, r5, lsl #16 /* r3 = (A^B^A)(B) = (B)(B) */
374 eor r3, ip, ip, lsl #16 /* r3 = (A^B)(B) */
375 eor ip, ip, r3, lsr #16 /* r4 = (A)(B^A^B) = (A)(A) */
376 eor r3, r3, ip, lsl #16 /* r3 = (A^B^A)(B) = (B)(B) */
380 eor r3, lr, lr, lsl #16 /* r3 = (A^B)(B) */
381 eor lr, lr, r3, lsr #16 /* r4 = (A)(B^A^B) = (A)(A) */
382 eor r3, r3, lr, lsl #16 /* r3 = (A^B^A)(B) = (B)(B) */
386 subs r2, r2, #0x00000008
389 ldmfd sp!, {r4,r5,pc} /* and go home */
393 * reads short ints (16 bits) from an I/O address into a block of memory
394 * The I/O address is assumed to be mapped multiple times in a block of
396 * The destination address should be word aligned.
398 * r0 = address to read from (IO)
399 * r1 = address to write to (memory)
404 /* Make sure that we have a positive length */
408 /* If the destination address is word aligned and the size suitably
409 aligned, do it fast */
415 /* Word aligned insw */
417 stmfd sp!, {r4-r9,lr}
420 orr lr, lr, #0x00ff0000
429 orr r3, r3, r4, lsl #16
431 orr r4, r5, r6, lsl #16
433 orr r5, r7, r8, lsl #16
435 orr r6, r9, ip, lsl #16
439 subs r2, r2, #0x00000008 /* Next */
450 orr r3, r3, r4, lsl #16
452 orr r4, r5, r6, lsl #16
456 subs r2, r2, #0x00000004
466 orr r3, r3, r4, lsl #16
467 str r3, [r1], #0x0004
469 subs r2, r2, #0x00000002
477 subs r2, r2, #0x00000001 /* Test in load delay slot */
478 /* XXX, why don't we use result? */
480 strb r3, [r1], #0x0001
482 strb r3, [r1], #0x0001
486 ldmfd sp!, {r4-r9,pc} /* And go home */
490 * write short ints (16 bits) to an I/O address from a block of memory
491 * The I/O address is assumed to be mapped multiple times in a block of
493 * The source address should be word aligned.
495 * r0 = address to read to (IO)
496 * r1 = address to write from (memory)
501 /* Make sure that we have a positive length */
505 /* If the destination address is word aligned and the size suitably
506 aligned, do it fast */
512 /* Word aligned outsw */
514 stmfd sp!, {r4-r8,lr}
520 ldmia r1!, {r3,r5,r7,ip}
522 eor r4, r3, r3, lsr #16 /* r4 = (A)(A^B) */
523 eor r3, r3, r4, lsl #16 /* r3 = (A^A^B)(B) = (B)(B) */
524 eor r4, r4, r3, lsr #16 /* r4 = (A)(B^A^B) = (A)(A) */
526 eor r6, r5, r5, lsr #16 /* r6 = (A)(A^B) */
527 eor r5, r5, r6, lsl #16 /* r5 = (A^A^B)(B) = (B)(B) */
528 eor r6, r6, r5, lsr #16 /* r6 = (A)(B^A^B) = (A)(A) */
530 eor r8, r7, r7, lsr #16 /* r8 = (A)(A^B) */
531 eor r7, r7, r8, lsl #16 /* r7 = (A^A^B)(B) = (B)(B) */
532 eor r8, r8, r7, lsr #16 /* r8 = (A)(B^A^B) = (A)(A) */
534 eor lr, ip, ip, lsr #16 /* lr = (A)(A^B) */
535 eor ip, ip, lr, lsl #16 /* ip = (A^A^B)(B) = (B)(B) */
536 eor lr, lr, ip, lsr #16 /* lr = (A)(B^A^B) = (A)(A) */
538 stmia r0, {r3-r8,ip,lr}
540 subs r2, r2, #0x00000008 /* Next */
550 eor r6, r3, r3, lsr #16 /* r6 = (A)(A^B) */
551 eor r5, r3, r6, lsl #16 /* r5 = (A^A^B)(B) = (B)(B) */
552 eor r6, r6, r5, lsr #16 /* r6 = (A)(B^A^B) = (A)(A) */
554 eor r8, r4, r4, lsr #16 /* r8 = (A)(A^B) */
555 eor r7, r4, r8, lsl #16 /* r7 = (A^A^B)(B) = (B)(B) */
556 eor r8, r8, r7, lsr #16 /* r8 = (A)(B^A^B) = (A)(A) */
560 subs r2, r2, #0x00000004
567 ldr r3, [r1], #0x0004 /* r3 = (A)(B) */
568 subs r2, r2, #0x00000002 /* Done test in Load delay slot */
570 eor r5, r3, r3, lsr #16 /* r5 = (A)(A^B)*/
571 eor r4, r3, r5, lsl #16 /* r4 = (A^A^B)(B) = (B)(B) */
572 eor r5, r5, r4, lsr #16 /* r5 = (A)(B^A^B) = (A)(A) */
582 ldrb r3, [r1], #0x0001
583 ldrb r4, [r1], #0x0001
584 subs r2, r2, #0x00000001 /* Done test in load delay slot */
585 /* XXX This test isn't used? */
586 orr r3, r3, r4, lsl #8
587 orr r3, r3, r3, lsl #16
591 ldmfd sp!, {r4-r8,pc} /* And go home */