Tree @master (Download .tar.gz)
UampirNexol-Extraction.md @master — view markup · raw · history · blame
UampirNexol Extraction
This document provides some tests for the machine-code extraction facility supported by UampirNexol.
These tests are written in Falderal format. Each indented code block
(generally preceded by a description) represents a test. All the lines of
the code block up until the ===>
line give the input to be tested; the
text after ===>
gives the expected output. ???>
gives an expected
error message, which is permitted to be a partial (substring) match.
Code Extraction
-> Tests for functionality "Extract Code from UampirNexol Expression"
-> Functionality "Extract Code from UampirNexol Expression" is implemented by
-> shell command "bin/uampirnexol extract %(test-body-file)"
Given a UampirNexol expression, we can extract MOS 6502 machine code from it.
LDA# 0
===> a9 00 60
The type of the expression must be a function mapping machine states to machine states.
LDA#
???> error: unsupported type for extraction: (Byte -> (State[/] -> State[A,Z,N/]))
0
???> error: unsupported type for extraction: Byte
We require that all instructions are given all the meaningful inputs that
they require. In this case, INX
needs X
to be meaningful on its input.
LDA# 0 ; INX
???> error: uninitialized locations: [X]
Inserting a TAX
will make the X
location meaningful on the input of INX
.
LDA# 0 ; TAX ; INX
===> a9 00 aa e8 60
Extract code from conditional. Note that the flag to be tested needs to be meaningful, as does the input of both branches.
if C (LDA# 0; TAX) else TAY
???> error: uninitialized locations: [A,C]
Extract code from conditional.
LDA# 0; CLC; if C (LDA# 0; TAX) else TAY
===> a9 00 18 b0 05 a8 b0 05 90 03 a9 00 aa 60
Extract code from a repeat
..until
loop. Note that the flag to be tested
needs to be meaningful.
repeat (LDA# 0; TAX) until ~C
???> error: uninitialized locations: [C]
Extract code from a repeat
..until
loop.
CLC ; repeat (LDA# 0; TAX) until ~C
===> 18 a9 00 aa 90 fb 60
Extract code from a let
block. Note that the value being bound must be
a plain value such as a byte, not a function; it must be used in
operand position.
CLC; let zero = 0 in repeat (LDA# zero; TAX) until ~C
===> 18 a9 00 aa 90 fb 60
CLC; let instr = TAX in repeat (LDA# 0; instr) until ~C
???> unsupported for extraction
We can extract code from an expression involving a location.
LDA# 0x41 ; STA @0x0400
===> a9 41 8d 00 04 60
Calling Routines
Code for calling routines is significantly more complicated to extract from a UampirNexol expression.
The usual idiom is to bind a routine value to a name, then refer to that routine by that name when calling it.
let
bumpupx = routine (INX; INX; INX)
in
LDA# 40 ; TAX ; (call bumpupx) ; (call bumpupx) ; INX
===> a9 28 aa 20 0b c0 20 0b c0 e8 60 e8 e8 e8 60
But naming routines isn't necessary. Anonymous routines can be called.
LDA# 40 ; TAX ; (call routine (INX; INX; INX))
===> a9 28 aa 20 07 c0 60 e8 e8 e8 60
Extern routines (routines whose address and type is declared but which are defined elsewhere) can be called as well.
let
chrout = extern @0xffd2 : State[A/] -> State[A/]
in
LDA# 40 ; call chrout
===> a9 28 20 d2 ff 60