Created
March 20, 2017 20:11
-
-
Save MightyPork/bced42104ef9a32f6a114ed79dbaba0a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ;*************************************************************************************************** | |
| ;* | |
| ;* 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