Skip to content

Instantly share code, notes, and snippets.

@MightyPork
Created March 20, 2017 20:11
Show Gist options
  • Select an option

  • Save MightyPork/bced42104ef9a32f6a114ed79dbaba0a to your computer and use it in GitHub Desktop.

Select an option

Save MightyPork/bced42104ef9a32f6a114ed79dbaba0a to your computer and use it in GitHub Desktop.
;***************************************************************************************************
;*
;* Utility macros
;*
;* (c) Ondrej Hruska, 2015
;*
;***************************************************************************************************
; Xors a memory value (for bit banding)
; Trashes r0-2
;
; $addr ... absolute address (direct)
MACRO
$label MemToggle $addr
$label MemXor 1, $addr
MEND
; Write a value to memory.
; Trashes r0-1.
;
; $value ... value to write
; $addr ... absolute address (direct)
MACRO
$label MemWrite $value, $addr
$label LDR R0, =$addr
LDR R1, =$value
STR R1, [R0]
MEND
; Write a register value to memory.
; Trashes r0.
; Register must not be R0.
;
; $register ... register to use (R0, R1...)
; $addr ...... absolute address (direct)
MACRO
$label MemWriteR $register, $addr
$label LDR R0, =$addr
STR $register, [R0]
MEND
; Read a memory value.
; Trashes r0.
;
; $register ... register to read into
; $addr ...... absolute address (direct)
MACRO
$label MemRead $register, $addr
$label LDR R0, =$addr
LDR $register, [R0]
MEND
; Read a memory value pointed to by a register.
;
; $addrReg ... register with address to read
; $register ... register to read into
MACRO
$label MemReadR $register, $addrReg
$label LDR $register, [$addrReg]
MEND
; OR a value in memory.
; Trashes r0-2
;
; $value ... mask to OR with memory value. Direct value.
; $addr ... absolute memory address (direct)
MACRO
$label MemOr $value, $addr
$label LDR R2, =$addr
LDR R1, [R2]
LDR R0, =$value
ORR R1, R1, R0
STR R1, [R2]
MEND
; AND a value in memory.
; Trashes r0-2
;
; $value ... mask to AND with memory value. Direct value.
; $addr ... absolute memory address (direct)
MACRO
$label MemAnd $value, $addr
$label LDR R2, =$addr
LDR R1, [R2]
LDR R0, =$value
AND R1, R1, R0
STR R1, [R2]
MEND
; XOR a value in memory.
; Trashes r0-2
;
; $value ... mask to XOR with memory value. Direct value.
; $addr ... absolute memory address (direct)
MACRO
$label MemXor $value, $addr
$label LDR R2, =$addr
LDR R1, [R2]
LDR R0, =$value
EOR R1, R1, R0
STR R1, [R2]
MEND
; Write a part of a memory register, while retaining the rest.
; Trashes r0-2
;
; $value ... value to write to the register. Direct.
; $mask ... mask of the bits to overwrite. Direct.
; $addr ... absolute memory address (direct)
MACRO
$label MemPatch $value, $mask, $addr
$label LDR R2, =$addr ; Load memory value to R1
LDR R1, [R2]
LDR R2, =$mask ; Load mask to R2
BIC R1, R1, R2 ; Clear the masked area in memory value
LDR R0, =$value ; Load value to R0
AND R0, R0, R2 ; Restrict value to mask bits
ORR R1, R1, R0 ; Apply patch to memory value
LDR R2, =$addr ; Store back to memory
STR R1, [R2]
MEND
; Extract a part of a memory register, clearing the rest.
; Trashes R0-1
;
; $register ... register where to store the extracted data
; $mask ... mask of the bits to extract Direct.
; $addr ... absolute memory address (direct)
MACRO
$label MemExtract $register, $mask, $addr
$label LDR R0, =$addr
LDR $register, [R0]
AND $register, $register, =$mask
MEND
; Wait for a bit in a memory register to be set
; Trashes R0-1
;
; $bitmask ... the bit(s) to check for
; $addr ... register address to check
;
; Must be called at label.
MACRO
$label WaitForBit $bitmask, $addr
$label LDR R0, =$addr
$label.a LDR R1, [R0]
TST R1, #$bitmask
BEQ $label.a
MEND
; Wait for a bit in a memory register to be cleared
; Trashes R0-1
;
; $bitmask ... the bit(s) to check for
; $addr ... register address to check
;
; Must be called at label.
MACRO
$label WaitForBitN $bitmask, $addr
$label LDR R0, =$addr
$label.a LDR R1, [R0]
TST R1, #$bitmask
BNE $label.a
MEND
; Wait for a register to reach value 1 (for BB)
; Trashes R0-1
;
; $addr ... register address to check
;
; Must be called at label.
MACRO
$label WaitForSet $addr
$label LDR R0, =$addr
$label.a LDR R1, [R0]
TST R1, #1
BEQ $label.a
MEND
; Wait for a register to reach value 0 (for BB)
; Trashes R0-1
;
; $addr ... register address to check
;
; Must be called at label.
MACRO
$label WaitForClear $addr
$label LDR R0, =$addr
$label.a LDR R1, [R0]
TST R1, #1
BNE $label.a
MEND
; Good old DJNZ meets ARM!
;
; $register ... decremented register
; $target ... jump target register
MACRO
$label DJNZ $register, $target
$label SUBS $register, $register, #1
BNE $target
MEND
; CBNE
; CBEQ etc
;
; Note: CBZ, CBNZ are actual instructions
;
; Trashes R0. $a must not be R0.
;
; $a ... operand A
; $b ... operand B (imm)
; $target ... target label
MACRO
$label CB$cond $a, $b, $target
$label LDR R0, =$b
CMP $a, R0
B$cond $target
MEND
; Decrement a register if greater than zero, updating flags
MACRO
$label DECZ $reg
$label CMP $reg, #0
IT NE
SUBSNE $reg, $reg, #1
MEND
; CBZ with memory addr
MACRO
$label MemCBZ $addr, $jmp
$label MemRead R0, $addr
CBZ R0, $jmp
MEND
; CBNZ with memory addr
MACRO
$label MemCBNZ $addr, $jmp
$label MemRead R0, $addr
CBNZ R0, $jmp
MEND
ALIGN
END
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment