summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/nios/NM_Macros.S
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2004-07-16 11:09:34 +0000
committerEric Andersen <andersen@codepoet.org>2004-07-16 11:09:34 +0000
commitc3d50a69839f8d80fc7244fde6e4a57e5e39dd36 (patch)
treec9e27baac7541384b806cce0845f28c1f59b5a2e /libc/sysdeps/linux/nios/NM_Macros.S
parent3cf731bf40f153a73373798085d1f45a80b972d6 (diff)
Pete Popov writes:
Hi Erik, I'm not sure why the NIOS support is not in uClibc -- perhaps the patch was rejected or never submitted? In any case, I'm playing with some NIOS stuff and created this patch against 0.9.26. The work was done by Microtronix. I'm not sure who else contributed to it. It would be great to have the NIOS support available in uClibc so developers don't have to go searching for these bits. Pete
Diffstat (limited to 'libc/sysdeps/linux/nios/NM_Macros.S')
-rw-r--r--libc/sysdeps/linux/nios/NM_Macros.S473
1 files changed, 473 insertions, 0 deletions
diff --git a/libc/sysdeps/linux/nios/NM_Macros.S b/libc/sysdeps/linux/nios/NM_Macros.S
new file mode 100644
index 000000000..da6136593
--- /dev/null
+++ b/libc/sysdeps/linux/nios/NM_Macros.S
@@ -0,0 +1,473 @@
+
+;------------------------------
+; Macros I: Faux Instructions
+;
+; The following "faux instructions" are
+; implemented here as macros:
+;
+; MOVIP register,constant MOVI with optional PFX & MOVHI, or BGEN
+; ADDIP register,constant PFX and ADDI with optional PFX
+; SUBIP register,constant PFX and SUBI with optional PFX
+; CMPIP register,constant PFX and CMPI with optional PFX
+;
+; MOVI16 register,constant PFX and MOVI
+; MOVI32 register,constant PFX, MOVI, PFX, and MOVHI
+; MOVIA register,constant PFX and MOVHI on Nios32, and PFX and MOVI
+;
+; ANDIP register,constant PFX and ANDI
+; ANDNIP register,constant PFX and ANDN
+; ORIP register,constant PFX and ORI
+; XORIP register,constant PFX and XORI
+;
+; _BSR address MOVIP address to %g7, and CALL
+; _BR address MOVIP address to %g7, and JMP
+;
+; BEQ address SKPS cc_nz and BR, has delay slot
+; BNE address SKPS cc_z and BR, has delay slot
+; BLE address SKPS cc_gt and BR, has delay slot
+; BLT address SKPS cc_ge and BR, has delay slot
+; RESTRET RESTORE and JMP %i7
+;
+;-------------------------------
+; Macros II: Printing
+;
+; These macros are guaranteed *not*
+; to have branch delay slot after them.
+;
+; NM_PrintChar char
+; NM_Print "string"
+; NM_PrintLn "string" Follows it with a carriage return
+; NM_PrintRegister reg For debugging, prints register name & value
+;
+;-------------------------------
+; Macros III: Inline Debugging
+;
+; These macros print various information
+; using large sections of expanded inline code.
+; They each use either few or no registers.
+; Thus, they may be safely used in interrupt handlers.
+;
+; NM_D_TxChar char print char to UART, affects no registers
+; NM_D_TxRegister char,char,register prints the two characters, and the hex register value
+
+; --------------------------------------
+
+
+ .macro _pfx_op OP,reg,val,pForce=0
+ .if (\pForce) || ((\val) > (31)) || ((\val) < (0))
+ PFX %hi(\val)
+ .endif
+ \OP \reg,%lo(\val)
+ .endm
+
+ .macro _bgen reg,val,bit
+ .if ((\val)==(1<<\bit))
+ BGEN \reg,\bit
+ .equ _bgenBit,1
+ .endif
+ .endm
+
+ ;------------------------
+ ; MOVIP %reg,32-bit-value
+ .macro MOVIP reg,val
+ ; Methodically test every BGEN possibility...
+ .equ _bgenBit,0
+.if 1
+ _bgen \reg,\val,0
+ _bgen \reg,\val,1
+ _bgen \reg,\val,2
+ _bgen \reg,\val,3
+ _bgen \reg,\val,4
+ _bgen \reg,\val,5
+ _bgen \reg,\val,6
+ _bgen \reg,\val,7
+ _bgen \reg,\val,8
+ _bgen \reg,\val,9
+ _bgen \reg,\val,10
+ _bgen \reg,\val,11
+ _bgen \reg,\val,12
+ _bgen \reg,\val,13
+ _bgen \reg,\val,14
+ _bgen \reg,\val,15
+ _bgen \reg,\val,16
+ _bgen \reg,\val,17
+ _bgen \reg,\val,18
+ _bgen \reg,\val,19
+ _bgen \reg,\val,20
+ _bgen \reg,\val,21
+ _bgen \reg,\val,22
+ _bgen \reg,\val,23
+ _bgen \reg,\val,24
+ _bgen \reg,\val,25
+ _bgen \reg,\val,26
+ _bgen \reg,\val,27
+ _bgen \reg,\val,28
+ _bgen \reg,\val,29
+ _bgen \reg,\val,30
+ _bgen \reg,\val,31
+
+ ; If no bgen fit...
+.endif
+ .if !_bgenBit
+ .if ((\val) & 0xFFE0)
+ PFX %hi(\val)
+ .endif
+ MOVI \reg,%lo(\val)
+ .if __nios32__
+ .if ((\val) & 0xffff0000)
+ .if ((\val) & 0xFFE00000)
+ PFX %xhi(\val)
+ .endif
+ MOVHI \reg,%xlo(\val)
+ .endif
+ .endif
+ .endif
+
+ .endm
+
+ ; ADDIP %reg,16-bit-value
+ .macro ADDIP reg,val
+ _pfx_op ADDI,\reg,\val
+ .endm
+
+ ; SUBIP %reg,16-bit-value
+ .macro SUBIP reg,val
+ _pfx_op SUBI,\reg,\val
+ .endm
+
+ ; CMPIP %reg,16-bit-value
+ .macro CMPIP reg,val
+ _pfx_op CMPI,\reg,\val
+ .endm
+
+ ; ANDIP %reg,16-bit-value
+ .macro ANDIP reg,val
+ PFX %hi(\val)
+ AND \reg,%lo(\val)
+ .endm
+
+ ; ANDNIP %reg,16-bit-value
+ .macro ANDNIP reg,val
+ PFX %hi(\val)
+ ANDN \reg,%lo(\val)
+ .endm
+
+ ; ORIP %reg,16-bit-value
+ .macro ORIP reg,val
+ PFX %hi(\val)
+ OR \reg,%lo(\val)
+ .endm
+
+ ; XORIP %reg,16-bit-value
+ .macro XORIP reg,val
+ PFX %hi(\val)
+ XOR \reg,%lo(\val)
+ .endm
+
+ ; BEQ addr
+ .macro BEQ addr
+ IFS cc_eq
+ BR \addr
+ .endm
+
+ ; BNE addr
+ .macro BNE addr
+ IFS cc_ne
+ BR \addr
+ .endm
+
+ ; BLE addr
+ .macro BLE addr
+ SKPS cc_gt
+ BR \addr
+ .endm
+
+ ; BLT addr
+ .macro BLT addr
+ SKPS cc_ge
+ BR \addr
+ .endm
+
+ .macro digitToChar reg
+ ANDIP \reg,0x000f
+ CMPI \reg,10
+ SKPS cc_lt
+ ADDI \reg,'A'-'0'-10
+ PFX %hi('0')
+ ADDI \reg,%lo('0')
+ .endm
+
+; PUSHRET == dec sp, and stash return addr
+ .macro PUSHRET
+ SUBI %sp,2
+ ST [%sp],%o7
+ .endm
+; POPRET == pop and jump
+ .macro POPRET
+ LD %o7,[%sp]
+ JMP %o7
+ ADDI %sp,2 ; branch delay slot
+ .endm
+
+; RESTRET = restore & return
+ .macro RESTRET
+ JMP %i7
+ RESTORE
+ .endm
+
+ ;--------------------
+ ; MOVI16 %reg,Address
+ ;
+ .macro MOVI16 reg,val
+ PFX %hi(\val)
+ MOVI \reg,%lo(\val)
+ .endm
+
+ ;--------------------
+ ; MOVI32 %reg,Address
+ ;
+ .macro MOVI32 reg,val
+ PFX %hi(\val)
+ MOVI \reg,%lo(\val)
+ PFX %xhi(\val)
+ MOVHI \reg,%xlo(\val)
+ .endm
+
+ ;--------------------
+ ; MOVIA %reg,Address
+ ;
+ .macro MOVIA reg,val
+ .if __nios32__
+ MOVI32 \reg,\val
+ .else
+ MOVI16 \reg,\val
+ .endif
+ .endm
+
+ ;--------------------
+ ; _BR
+
+ .macro _BR target,viaRegister=%g7
+ MOVIA \viaRegister,\target@h
+ JMP \viaRegister
+ .endm
+
+ ;--------------------
+ ; _BSR
+
+ .macro _BSR target,viaRegister=%g7
+ MOVIA \viaRegister,\target@h
+ CALL \viaRegister
+ .endm
+
+ ;---------------------
+ ; NM_Print "Your String Here"
+ ;
+ .macro NM_Print string
+
+ BR pastStringData\@
+ NOP
+
+stringData\@:
+ .asciz "\string"
+ .align 1 ; aligns by 2^n
+pastStringData\@:
+ MOVIA %o0,stringData\@
+ _BSR NR_TxString
+ NOP
+ .endm
+
+ .macro NM_PrintLn string
+ NM_Print "\string"
+ _BSR NR_TxCR
+ NOP
+ .endm
+
+ .macro NM_PrintRegister reg ; affects %g0 & %g1 & %g7, but thrashes the CWP a bit
+ SAVE %sp,-16
+ NM_Print "\reg = "
+ RESTORE
+ MOV %g0,\reg
+ SAVE %sp,-16
+ MOV %o0,%g0
+ _BSR NR_TxHex
+ NOP
+ _BSR NR_TxCR
+ NOP
+ RESTORE
+ .endm
+
+ .macro NM_PrintChar char
+ MOVIP %o0,\char
+ _BSR NR_TxChar
+ NOP
+ .endm
+
+ .macro NM_Print2Chars char1,char2
+ MOVIP %o0,(\char2<<8)+\char1
+ _BSR NR_TxChar
+ NOP
+ _BSR NR_TxChar
+ LSRI %o0,8
+ .endm
+
+
+
+; ---------------------------
+; Completely inline UART sends
+; Send the char, or %g7 if not there.
+; Trashes %g5 and %g6 and %g7...
+
+ .macro NM_TxChar char=0
+;NM_D_Delay 1000
+ MOVIA %g6,NA_UARTBase
+txCharLoop\@:
+ PFX 2
+.if \char
+ LD %g7,[%g6]
+ SKP1 %g7,6
+.else
+ LD %g5,[%g6]
+ SKP1 %g5,6
+.endif
+ BR txCharLoop\@
+ NOP
+.if \char
+ MOVIP %g7,\char
+.endif
+ PFX 1
+ ST [%g6],%g7
+;NM_D_Delay 4
+ .endm
+
+ .macro NM_TxCR
+ NM_TxChar 13
+ NM_TxChar 10
+ .endm
+
+ .macro NM_TxHexDigit,reg,shift
+ MOV %g7,\reg
+ LSRI %g7,\shift
+ ANDIP %g7,0x000f
+ CMPI %g7,10
+ SKPS cc_lt
+ ADDIP %g7,'A'-'0'-10
+ ADDIP %g7,'0'
+ NM_TxChar
+ .endm
+
+ .macro NM_TxHex
+
+ .if __nios32__
+ NM_TxHexDigit %g0,28
+ NM_TxHexDigit %g0,24
+ NM_TxHexDigit %g0,20
+ NM_TxHexDigit %g0,16
+ .endif
+
+ NM_TxHexDigit %g0,12
+ NM_TxHexDigit %g0,8
+ NM_TxHexDigit %g0,4
+ NM_TxHexDigit %g0,0
+ .endm
+
+
+
+
+
+
+
+
+
+
+; ----------------------
+; The following macros are
+; rather mighty. They expand
+; to large inline code for
+; printing various things to
+; the serial port. They are
+; useful for debugging
+; trap handlers, where you
+; can't just go and call
+; NR_TxChar and such, because,
+; well, the CWP might be
+; off limits!
+;
+; They do, however, presume
+; that the stack is in good
+; working order.
+
+
+.macro NM_D_PushGRegisters
+ SUBIP %sp,16+69 ; oddball number so if we accidentally see it, it looks funny.
+ STS [%sp,16+0],%g0
+ STS [%sp,16+1],%g1
+ STS [%sp,16+2],%g2
+ STS [%sp,16+3],%g3
+ STS [%sp,16+4],%g4
+ STS [%sp,16+5],%g5
+ STS [%sp,16+6],%g6
+ STS [%sp,16+7],%g7
+ .endm
+
+.macro NM_D_PopGRegisters
+ LDS %g0,[%sp,16+0]
+ LDS %g1,[%sp,16+1]
+ LDS %g2,[%sp,16+2]
+ LDS %g3,[%sp,16+3]
+ LDS %g4,[%sp,16+4]
+ LDS %g5,[%sp,16+5]
+ LDS %g6,[%sp,16+6]
+ LDS %g7,[%sp,16+7]
+ ADDIP %sp,16+69 ; must match the push
+ .endm
+
+
+.macro NM_D_TxChar c
+ SUBI %sp,16+8 ; 32 or 16 bit, that's enough space
+ STS [%sp,16+0],%g6
+ STS [%sp,16+0],%g7
+ NM_TxChar \c
+ LDS %g6,[%sp,16+0]
+ LDS %g7,[%sp,16+1]
+ ADDI %sp,16+8
+ .endm
+
+.macro NM_D_TxChar3 c1,c2,c3
+ NM_D_TxChar '<'
+ NM_D_TxChar \c1
+ NM_D_TxChar \c2
+ NM_D_TxChar \c3
+ NM_D_TxChar '>'
+.endm
+
+.macro NM_D_TxRegister r,n,reg
+ NM_D_PushGRegisters
+ NM_TxChar '('
+ NM_TxChar \r
+ NM_TxChar \n
+ NM_TxChar ':'
+ MOV %g0,\reg
+ NM_TxHex
+ NM_TxChar ')'
+ NM_D_PopGRegisters
+.endm
+
+.macro NM_D_TxReg r,n,reg
+ NM_D_TxRegister \r,\n,\reg
+.endm
+
+; Do a delay loop, affects no registers.
+
+.macro NM_D_Delay d
+ SUBI %sp,16+4
+ STS [%sp,16+0],%g0
+ MOVIP %g0,\d
+NM_D_DelayLoop\@:
+ IFRnz %g0
+ BR NM_D_DelayLoop\@
+ SUBI %g0,1
+ LDS %g0,[%sp,16+0]
+ ADDI %sp,16+4
+.endm
+