-
-
Notifications
You must be signed in to change notification settings - Fork 60
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
}
}
When an instruction matches multiple rules, you can use
assert()
to select the best possible binary representation.
Make sure the asserted conditions don't overlap, otherwise
the assembler may throw an error.
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.
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