|
Useful objasm macros |
|
; EQUB <value>
; set a byte
MACRO
EQUB $var
DCB $var
MEND
; EQUW <value>
; Set a 16 bit value
MACRO
EQUW $var
DCW $var
MEND
; EQUD <value>
; Set a 32 bit value
MACRO
EQUD $var
DCD $var
MEND
; EQUS "<value>"
; Set a string.
; For 'EQUS "something", 13, 0'
; you will need use DCB directly.
MACRO
EQUS $var
DCB "$var"
MEND
; EQUSZ "<value>"
; Set a string and zero-terminate it.
MACRO
EQUSZ $var
DCB "$var", 0
MEND
; EQUSB "<value>"
; Set a string and BASIC-style terminate it.
MACRO
EQUSZ $var
DCB "$var", 13
MEND
; EQUSZA "<value>"
; Set a string and zero-terminate it, then align.
MACRO
EQUSZA $var
DCB "$var", 0
ALIGN
MEND
stm_temp RLIST {R0-R3,R14}
ldm_temp RLIST {R0-R3,PC}
str_temp RLIST {R0-R3}
Then, in your code, instead of: STMFD R13!, {R0-R3, R14}
...
LDMFD R13!, {R0-R3, PC} STMFD R13!, stm_temp
...
LDMFD R13!, ldm_temp
The 'str_temp' version is for when you want to store/load without messing with R14/PC. The same is used for both loading and storing.
; BSR "<function>"
; Branch to subroutine saving R14 around it
; This is a lot like JSR on the 6502.
MACRO
$label BSR $dest
$label PushLR
BL $dest
PullLR
MEND
; Pull "<reglist>" [,<"condition"> [,"^"]]
; Pull registers given in reglist. Can be conditional.
; Use '^' with care.
; Example:
; Pull "R2-R4", "EQ"
MACRO
$label Pull $reglist, $cond, $hat
$label LDM$cond.FD R13!, {$reglist}$hat
MEND
; Push "<reglist>" [,<"condition">]
; Push registers given in reglist. Can be conditional.
; Example:
; Push "R2-R4", "EQ"
MACRO
$label Push $reglist, $cond
$label STM$cond.FD R13!, {$reglist}
MEND
; Push LR (and only LR) to the stack.
; Optimised for fast saving of one register,
; instead of using STMFD R13!, {LR}
; Can be conditional.
MACRO
$label PushLR $cond
$label STR$cond. R14, [R13, #-4]!
MEND
; Pull LR (and only LR) from the stack.
; Optimised form of LDMFD R13!, {LR}
; Can be conditional.
MACRO
$label PullLR $cond
$label LDR$cond. R14, [R13], #4
MEND
; Return from function.
; Can be conditional. DOES NOT RESTORE FLAGS.
MACRO
$label Ret $cond
$label MOV$cond PC, R14
MEND
; This is functionally the same as 'Ret'. Use
; whichever you prefer.
MACRO
$label Return $cond
$label MOV$cond PC, R14
MEND
; Pull LR and Return
; This is equivalent to:
; PullLR
; Return
; but it saves an instruction as we load to PC
MACRO
$label PullRet $cond
$label LDR$cond. PC, [R13], #4
MEND
; SetV sets the oVerflow flag
; regardless of processor type
MACRO
$label SetV ; DOES NOT TAKE A CONDITION
$label CMP R0, #1<<31
CMNVC R0, #1<<31
MEND
; ProcMode returns:
; EQ if 32 bit (PC and CPSR) mode
; NE if 26 bit (PC + PSR) mode
MACRO
$label ProcMode ; DOES NOT TAKE A CONDITION
$label TEQ PC, #0
TEQ PC, PC
MEND
Sometimes it can be useful to stick in an on-screen debugging message so you can quickly trace the flow of the program without restorting to the tedium of single-stepping in the debugger...
; DebugMsg - embeds a debugging message
MACRO
DebugMsg $msg
SWI XOS_WriteS
DCB "$msg", 13, 10, 0
ALIGN
MEND
You could expand upon this by, for instance, wrapping it in a conditional test for a DEBUG
'define'. In this way, you can simply alter the DEBUG 'define' to make the macro either output
the in-line debugging string or simply do nothing.