-
-
Notifications
You must be signed in to change notification settings - Fork 57
Advanced rules
You can use braces {}
to create code blocks with
a sequence of expressions.
You can create and assign to local variables using =
.
There's no need for expression separators, but you can
use a comma ,
if needed.
The last expression in the block is automatically
returned.
For example:
#ruledef
{
; from the 6502 instruction set
bpl {addr} =>
{
reladdr = addr - $ - 2
0x10 @ reladdr`8
}
}
Asserts can be used in a code block to validate and reject certain
instruction arguments. If the condition given to assert()
turns out to be false, an error is thrown.
For example:
#ruledef
{
; from the 6502 instruction set
bpl {addr} =>
{
reladdr = addr - $ - 2
assert(reladdr <= 0x7f)
assert(reladdr >= !0x7f)
0x10 @ reladdr`8
}
}
You can also pass a custom message as the optional second argument, which will be shown on the error message in case the assert fails:
#ruledef
{
; from the 6502 instruction set
bpl {addr} =>
{
reladdr = addr - $ - 2
assert(reladdr <= 0x7f, "branch target is too far")
assert(reladdr >= !0x7f, "branch target is too far")
0x10 @ reladdr`8
}
}
When an instruction matches multiple rules, the assembler will select the rule which produces the fewest number of bits. You can use this to have automatic selection of the smallest binary representation for a given instruction. If multiple matching rules produce the same number of bits, the assembler will throw an error.
You can use assert()
to guide the assembler on its selection.
The assembler will safely disregard matching rules which fail
assertions. If multiple rules still match, even after assertion
filtering, the above-mentioned process kicks in, and the assembler
will select the rule which produces the fewest number of bits.
For example, we can write:
#ruledef
{
mov {value} =>
{
assert(value >= 0)
assert(value <= 0xff)
0x10 @ value`8
}
mov {value} =>
{
assert(value >= 0x100)
assert(value <= 0xffff)
0x11 @ value`16
}
mov {value} =>
{
assert(value >= 0x10000)
assert(value <= 0xffffff)
0x12 @ value`24
}
}
If the arguments to the instruction cannot be resolved in the first
pass, which can happen if you were using a label that will only be defined later,
0
or a value from the previous pass are used.
Further passes will refine the label value until it
stops changing, and the final form of the instruction is chosen.
To reuse an instruction's binary code in another instruction,
you can use asm
blocks:
#ruledef
{
mov {reg}, {value} => 0x11 @ reg`8 @ value`8
zero {reg} => asm { mov {reg}, 0 }
}
In the above example, the zero
instruction is really just an alias for
moving zero into a register, so the instruction body just calls the other
instruction with an asm
block to avoid repetition.
Note that the asm
block from the zero
instruction has access to
the reg
argument, and passes its value on to the mov
instruction.
Before v0.13.0, you could access the reg
value without using braces {}
,
but they're now required.
This works even if the argument was typed as a subrule instead:
#subruledef AorB
{
a => 0xaa
b => 0xbb
}
#ruledef
{
mov {reg: AorB}, {value} => 0x11 @ reg`8 @ value`8
zero {reg: AorB} => asm { mov {reg}, 0 }
}
The asm
block works just like any other expression, so you can, for example,
use concatenation:
#ruledef
{
mov {reg}, {value} => 0x11 @ reg`8 @ value`8
zero_all => asm { mov 0, 0 } @ asm { mov 1, 0 } @ asm { mov 2, 0 }
}
Or, equivalently, you can put multiple instructions inside a single asm
block,
one per line:
#ruledef
{
mov {reg}, {value} => 0x11 @ reg`8 @ value`8
zero_all => asm
{
mov 0, 0
mov 1, 0
mov 2, 0
}
}
- Getting started
- Defining mnemonics β #ruledef, #subruledef
- Declaring labels and constants
- Setting the minimum addressable unit β #bits
- Outputting data blocks β #d
- Working with banks β #bankdef, #bank
- Address manipulation directives β #addr, #align, #res
- Splitting your code into multiple files β #include, #once
- Advanced mnemonics, cascading, and deferred resolution β assert()
- Available expression operators and functions β incbin(), incbinstr(), inchexstr()
- Functions β #fn
- Conditional Compilation β #if, #elif, #else