1 ;; A ROSE-8 definition for customasm
3 ;; Differences from the original ROSE-8 assembler:
4 ;; - Label, comment, and literal syntax uses customasm rules, of course
5 ;; - Offset-based branches that take labels (`BEZI`, `JOFI`, `COFI`) will not work correctly if given bare integers (they will be treated as addresses rather than offsets)
6 ;; - There are no pseudo-instructions; use expressions instead (see Utility Functions, below)
7 ;; - There is no `.fragment`; use an explicit `#addr` or `#align NEXT_SEGMENT` to start a new segment, and just rely on concatenation otherwise.
8 ;; - `.nosplit` is implemented by `!nosplit <label>`; alternately you can `!assert_eq <value>, seg($)`
9 ;; - customasm does not have an equivalent to `.fill <count> <value>`. Sorry. Use `#res` for `.fill` with zeros, and `#d` for everything else.
17 ;; A ROSE-8 binary is always the full size of memory as a single bank.
19 ;; See the ISA guide for the initial register state.
28 ;; An alias for use with the `#align` directive.
29 #const(noemit) NEXT_SEGMENT = 0x800
36 ;; Returns the segment of `label`, as an 8-bit value
37 #fn seg(label) => (label / 256)`8
39 ;; Returns the address of `label` within its segment, as an 8-bit value
40 #fn addr(label) => (label % 256)`8
42 ;; Produces the segment of `label` followed by its address
44 ;; Intended to be used with `#d` for more clarity than a bare label.
45 #fn segAddr(label) => (label)`16 ; big-endian
47 ;; Produces the offset of `label` from the current address, as an 8-bit signed value
49 ;; Fails if `label` is out of range, though it does not need to be in the same segment.
50 #fn offset(label) => {
52 assert(result <= 0x7f, "offset is too far")
53 assert(result >= -0x80, "offset is too far")
57 ;; Slightly prettier way of writing a C string for the #d directive.
58 #fn c(str) => { str @ "\0" }
62 ;; Exposes `assert` functionality outside of rules.
64 ;; Can be used to verify that a function is in a particular segment.
65 !assert_eq {x}, {y} => {
70 ;; Asserts that `l` is in the same segment as the current address.
72 ;; Useful for checking that a `CABL` return will restore the code segment register to its previous state.
73 !nosplit {label: u16} => {
74 assert(seg(label) == seg($), "fragment has been split")
118 r{value: u3} => value
121 #ruledef register_ops
123 GETR {r: register} => 0b001_00 @ r
124 SETR {r: register} => 0b001_01 @ r
125 SWAP {r: register} => 0b001_10 @ r
126 ISLT {r: register} => 0b001_11 @ r
128 ADDR {r: register} => 0b01_000 @ r
129 SUBR {r: register} => 0b01_001 @ r
130 ANDR {r: register} => 0b01_010 @ r
131 IORR {r: register} => 0b01_011 @ r
132 XORR {r: register} => 0b01_100 @ r
133 LSLR {r: register} => 0b01_101 @ r
134 LSRR {r: register} => 0b01_110 @ r
135 ASRR {r: register} => 0b01_111 @ r
137 LD1R {r: register} => 0b100_00 @ r
138 ST1R {r: register} => 0b100_01 @ r
139 LD1U {r: register} => 0b100_10 @ r
140 ST1U {r: register} => 0b100_11 @ r
142 LD2R {r: register} => 0b101_00 @ r
143 ST2R {r: register} => 0b101_01 @ r
144 LD2U {r: register} => 0b101_10 @ r
145 ST2U {r: register} => 0b101_11 @ r
147 LD2D {r: register} => 0b111_00 @ r
148 ST2D {r: register} => 0b111_01 @ r
151 #ruledef immediate_ops
153 ANDI {i: u8} => 0b1111_0000 @ i
154 IORI {i: u8} => 0b1111_0001 @ i
155 XORI {i: u8} => 0b1111_0010 @ i
158 assert(i >= -64, "too negative")
162 ROLI {i: u3} => 0b1111_0011 @ 0b10_000 @ i
163 LSLI {i: u3} => 0b1111_0011 @ 0b10_001 @ i
164 LSRI {i: u3} => 0b1111_0011 @ 0b10_010 @ i
165 ASRI {i: u3} => 0b1111_0011 @ 0b10_011 @ i
166 EXTI {i: u3} => 0b1111_0011 @ 0b10_111 @ i
168 BEZI {l: u16} => 0b1111_0100 @ offset(l)
169 JOFI {l: u16} => 0b1111_0101 @ offset(l)
170 CABI {l: u16} => 0b1111_0110 @ addr(l)
171 COFI {l: u16} => 0b1111_0111 @ offset(l)
173 GETI {i: i8} => 0b1111_1110 @ i