/* * linux/arch/arm/lib/io-ebsa.S * * Copyright (C) 1995, 1996 Russell King */ #include #include .text .align #define OUT(reg) \ mov r8, reg, lsl $16 ;\ orr r8, r8, r8, lsr $16 ;\ str r8, [r3, r0, lsl $2] ;\ mov r8, reg, lsr $16 ;\ orr r8, r8, r8, lsl $16 ;\ str r8, [r3, r0, lsl $2] #define IN(reg) \ ldr reg, [r0] ;\ and reg, reg, ip ;\ ldr lr, [r0] ;\ orr reg, reg, lr, lsl $16 /* * These make no sense on these machines. * Print a warning message. */ ENTRY(insl) ENTRY(outsl) ENTRY(insb) ENTRY(outsb) adr r0, io_long_warning mov r1, lr b SYMBOL_NAME(printk) io_long_warning: .ascii "<4>ins?/outs? not implemented on this architecture\0" .align @ Purpose: read a block of data from a hardware register to memory. @ Proto : insw(int from_port, void *to, int len_in_words); @ Proto : inswb(int from_port, void *to, int len_in_bytes); @ Notes : increment to ENTRY(insw) mov r2, r2, lsl#1 ENTRY(inswb) mov ip, sp stmfd sp!, {r4 - r10 ,fp ,ip ,lr ,pc} sub fp, ip, #4 cmp r0, #0x00c00000 movge r3, #0 movlt r3, #0xf0000000 add r0, r3, r0, lsl #2 tst r1, #3 beq Linswok tst r1, #1 bne Linsw_notaligned cmp r2, #1 ldrge r4, [r0] strgeb r4, [r1], #1 movgt r4, r4, LSR#8 strgtb r4, [r1], #1 ldmleea fp, {r4 - r10, fp, sp, pc}^ sub r2, r2, #2 Linswok: mov ip, #0xFF orr ip, ip, ip, lsl #8 Linswlp: subs r2, r2, #64 bmi Linsw_toosmall IN(r3) IN(r4) IN(r5) IN(r6) IN(r7) IN(r8) IN(r9) IN(r10) stmia r1!, {r3 - r10} IN(r3) IN(r4) IN(r5) IN(r6) IN(r7) IN(r8) IN(r9) IN(r10) stmia r1!, {r3 - r10} bne Linswlp LOADREGS(ea, fp, {r4 - r10, fp, sp, pc}) Linsw_toosmall: add r2, r2, #32 bmi Linsw_toosmall2 Linsw2lp: IN(r3) IN(r4) IN(r5) IN(r6) IN(r7) IN(r8) IN(r9) IN(r10) stmia r1!, {r3 - r10} LOADREGS(eqea, fp, {r4 - r10, fp, sp, pc}) b Linsw_notaligned Linsw_toosmall2: add r2, r2, #32 Linsw_notaligned: cmp r2, #1 LOADREGS(ltea, fp, {r4 - r10, fp, sp, pc}) ldr r4, [r0] strb r4, [r1], #1 movgt r4, r4, LSR#8 strgtb r4, [r1], #1 subs r2, r2, #2 bgt Linsw_notaligned LOADREGS(ea, fp, {r4 - r10, fp, sp, pc}) @ Purpose: write a block of data from memory to a hardware register. @ Proto : outsw(int to_reg, void *from, int len_in_words); @ Proto : outswb(int to_reg, void *from, int len_in_bytes); @ Notes : increments from ENTRY(outsw) mov r2, r2, LSL#1 ENTRY(outswb) mov ip, sp stmfd sp!, {r4 - r8, fp, ip, lr, pc} sub fp, ip, #4 cmp r0, #0x00c00000 movge r3, #0 movlt r3, #0xf0000000 tst r1, #2 beq Loutsw32lp ldr r4, [r1], #2 mov r4, r4, lsl #16 orr r4, r4, r4, lsr #16 str r4, [r3, r0, lsl #2] sub r2, r2, #2 teq r2, #0 LOADREGS(eqea, fp, {r4 - r8, fp, sp, pc}) Loutsw32lp: subs r2,r2,#32 blt Loutsw_toosmall ldmia r1!,{r4,r5,r6,r7} OUT(r4) OUT(r5) OUT(r6) OUT(r7) ldmia r1!,{r4,r5,r6,r7} OUT(r4) OUT(r5) OUT(r6) OUT(r7) LOADREGS(eqea, fp, {r4 - r8, fp, sp, pc}) b Loutsw32lp Loutsw_toosmall: adds r2,r2,#32 LOADREGS(eqea, fp, {r4 - r8, fp, sp, pc}) Llpx: ldr r4,[r1],#2 mov r4,r4,LSL#16 orr r4,r4,r4,LSR#16 str r4,[r3,r0,LSL#2] subs r2,r2,#2 bgt Llpx LOADREGS(ea, fp, {r4 - r8, fp, sp, pc})