git @ Cat's Eye Technologies UampirNexol / master doc / UampirNexol-Extraction.md
master

Tree @master (Download .tar.gz)

UampirNexol-Extraction.md @masterview 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