New SplitBit programs.
This commit is contained in:
@@ -1 +1,5 @@
|
|||||||
Tests/build/
|
Tests/build/
|
||||||
|
Object/
|
||||||
|
Assembler
|
||||||
|
SplitBit
|
||||||
|
CLAUDE.md
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,79 @@
|
|||||||
|
#Program
|
||||||
|
; These routines untested and written entirely by Claude Code!
|
||||||
|
; int32 subroutines.
|
||||||
|
|
||||||
|
; An int32 value is a 32-bit unsigned integer, represented by four bytes,
|
||||||
|
; in the order most-significant to least-significant.
|
||||||
|
|
||||||
|
; The basic operations take two sequential int32 values as operands from Data Memory.
|
||||||
|
; They assume that the Data Pointer is set to the high byte of Operand A.
|
||||||
|
; Operands are stored in an eight-byte array in the following order:
|
||||||
|
; Operand A, byte 3 (most significant)
|
||||||
|
; Operand A, byte 2
|
||||||
|
; Operand A, byte 1
|
||||||
|
; Operand A, byte 0 (least significant)
|
||||||
|
; Operand B, byte 3 (most significant)
|
||||||
|
; Operand B, byte 2
|
||||||
|
; Operand B, byte 1
|
||||||
|
; Operand B, byte 0 (least significant)
|
||||||
|
; All operations overwrite Operand A. This causes the Data Pointer to point to the result after returning.
|
||||||
|
|
||||||
|
int32add:
|
||||||
|
; Add two int32 values.
|
||||||
|
; If the addition results in a carry, the carry flag will be set.
|
||||||
|
CCF ; Clear the Carry Flag.
|
||||||
|
DPUP 0d07 ; Move to Operand B's byte 0 (least significant).
|
||||||
|
LDB ; Load it to B.
|
||||||
|
DPDN 0d04 ; Move to Operand A's byte 0.
|
||||||
|
LDA ; Load it to A.
|
||||||
|
ADD ; Add them together.
|
||||||
|
STQ ; Store the result.
|
||||||
|
DPUP 0d03 ; Move to Operand B's byte 1.
|
||||||
|
LDB ; Load it to B.
|
||||||
|
DPDN 0d04 ; Move to Operand A's byte 1.
|
||||||
|
LDA ; Load it to A.
|
||||||
|
ADD ; Add with carry from byte 0.
|
||||||
|
STQ ; Store the result.
|
||||||
|
DPUP 0d03 ; Move to Operand B's byte 2.
|
||||||
|
LDB ; Load it to B.
|
||||||
|
DPDN 0d04 ; Move to Operand A's byte 2.
|
||||||
|
LDA ; Load it to A.
|
||||||
|
ADD ; Add with carry from byte 1.
|
||||||
|
STQ ; Store the result.
|
||||||
|
DPUP 0d03 ; Move to Operand B's byte 3 (most significant).
|
||||||
|
LDB ; Load it to B.
|
||||||
|
DPDN 0d04 ; Move to Operand A's byte 3.
|
||||||
|
LDA ; Load it to A.
|
||||||
|
ADD ; Add with carry from byte 2.
|
||||||
|
STQ ; Store the result.
|
||||||
|
RET ; Return to the caller.
|
||||||
|
|
||||||
|
int32sub:
|
||||||
|
; Subtract Operand B from Operand A.
|
||||||
|
; If the subtraction results in a borrow, the carry flag will be set.
|
||||||
|
CCF ; Clear the Carry Flag.
|
||||||
|
DPUP 0d07 ; Move to Operand B's byte 0 (least significant).
|
||||||
|
LDB ; Load it to B.
|
||||||
|
DPDN 0d04 ; Move to Operand A's byte 0.
|
||||||
|
LDA ; Load it to A.
|
||||||
|
SUB ; Subtract B from A.
|
||||||
|
STQ ; Store the result.
|
||||||
|
DPUP 0d03 ; Move to Operand B's byte 1.
|
||||||
|
LDB ; Load it to B.
|
||||||
|
DPDN 0d04 ; Move to Operand A's byte 1.
|
||||||
|
LDA ; Load it to A.
|
||||||
|
SUB ; Subtract with borrow from byte 0.
|
||||||
|
STQ ; Store the result.
|
||||||
|
DPUP 0d03 ; Move to Operand B's byte 2.
|
||||||
|
LDB ; Load it to B.
|
||||||
|
DPDN 0d04 ; Move to Operand A's byte 2.
|
||||||
|
LDA ; Load it to A.
|
||||||
|
SUB ; Subtract with borrow from byte 1.
|
||||||
|
STQ ; Store the result.
|
||||||
|
DPUP 0d03 ; Move to Operand B's byte 3 (most significant).
|
||||||
|
LDB ; Load it to B.
|
||||||
|
DPDN 0d04 ; Move to Operand A's byte 3.
|
||||||
|
LDA ; Load it to A.
|
||||||
|
SUB ; Subtract with borrow from byte 2.
|
||||||
|
STQ ; Store the result.
|
||||||
|
RET ; Return to the caller.
|
||||||
@@ -0,0 +1,326 @@
|
|||||||
|
; Conway's Game of Life for SplitBit.
|
||||||
|
;
|
||||||
|
; The visible field is 16x16, surrounded by a permanently dead one-cell border.
|
||||||
|
; Each of the 18x18 allocated cells is stored as two adjacent bytes:
|
||||||
|
; current state, next state
|
||||||
|
; This makes double buffering possible with SplitBit's single Data Pointer.
|
||||||
|
;
|
||||||
|
; The initial pattern is a glider. ANSI terminal control codes redraw the field
|
||||||
|
; in place. Press Ctrl-C to stop the emulator.
|
||||||
|
|
||||||
|
#Include Libraries/print.asm
|
||||||
|
|
||||||
|
#Program
|
||||||
|
|
||||||
|
start:
|
||||||
|
CALL seedGlider
|
||||||
|
SETD ClearScreen
|
||||||
|
CALL printString
|
||||||
|
|
||||||
|
generationLoop:
|
||||||
|
CALL renderBoard
|
||||||
|
CALL evolveBoard
|
||||||
|
CALL commitBoard
|
||||||
|
CALL frameDelay
|
||||||
|
BRI generationLoop
|
||||||
|
|
||||||
|
seedGlider:
|
||||||
|
; Coordinates in the padded field:
|
||||||
|
; .#.
|
||||||
|
; ..#
|
||||||
|
; ###
|
||||||
|
SETD Board
|
||||||
|
DPUP 0d42
|
||||||
|
INIA 0x01
|
||||||
|
STA
|
||||||
|
SETD Board
|
||||||
|
DPUP 0d80
|
||||||
|
STA
|
||||||
|
SETD Board
|
||||||
|
DPUP 0d112
|
||||||
|
STA
|
||||||
|
SETD Board
|
||||||
|
DPUP 0d114
|
||||||
|
STA
|
||||||
|
SETD Board
|
||||||
|
DPUP 0d116
|
||||||
|
STA
|
||||||
|
RET
|
||||||
|
|
||||||
|
renderBoard:
|
||||||
|
SETD CursorHome
|
||||||
|
CALL printString
|
||||||
|
SETD Board
|
||||||
|
DPUP 0d38
|
||||||
|
INIA 0d16
|
||||||
|
SETD RowCount
|
||||||
|
STA
|
||||||
|
SETD Board
|
||||||
|
DPUP 0d38
|
||||||
|
|
||||||
|
renderRow:
|
||||||
|
PSHD
|
||||||
|
INIA 0d16
|
||||||
|
SETD ColCount
|
||||||
|
STA
|
||||||
|
POPD
|
||||||
|
|
||||||
|
renderCell:
|
||||||
|
LDA
|
||||||
|
BRA renderDead
|
||||||
|
INIB 0x23
|
||||||
|
OUTB 0x00
|
||||||
|
BRI renderCellDone
|
||||||
|
renderDead:
|
||||||
|
INIB 0x20
|
||||||
|
OUTB 0x00
|
||||||
|
renderCellDone:
|
||||||
|
DPUP 0d02
|
||||||
|
PSHD
|
||||||
|
SETD ColCount
|
||||||
|
LDA
|
||||||
|
DECA
|
||||||
|
STA
|
||||||
|
BRA renderRowDone
|
||||||
|
POPD
|
||||||
|
BRI renderCell
|
||||||
|
|
||||||
|
renderRowDone:
|
||||||
|
POPD
|
||||||
|
CALL lineFeed
|
||||||
|
DPUP 0d04
|
||||||
|
PSHD
|
||||||
|
SETD RowCount
|
||||||
|
LDA
|
||||||
|
DECA
|
||||||
|
STA
|
||||||
|
BRA renderDone
|
||||||
|
POPD
|
||||||
|
BRI renderRow
|
||||||
|
|
||||||
|
renderDone:
|
||||||
|
POPD
|
||||||
|
RET
|
||||||
|
|
||||||
|
evolveBoard:
|
||||||
|
SETD Board
|
||||||
|
DPUP 0d38
|
||||||
|
INIA 0d16
|
||||||
|
SETD RowCount
|
||||||
|
STA
|
||||||
|
SETD Board
|
||||||
|
DPUP 0d38
|
||||||
|
|
||||||
|
evolveRow:
|
||||||
|
PSHD
|
||||||
|
INIA 0d16
|
||||||
|
SETD ColCount
|
||||||
|
STA
|
||||||
|
POPD
|
||||||
|
|
||||||
|
evolveCellLoop:
|
||||||
|
CALL evolveCell
|
||||||
|
DPUP 0d02
|
||||||
|
PSHD
|
||||||
|
SETD ColCount
|
||||||
|
LDA
|
||||||
|
DECA
|
||||||
|
STA
|
||||||
|
BRA evolveRowDone
|
||||||
|
POPD
|
||||||
|
BRI evolveCellLoop
|
||||||
|
|
||||||
|
evolveRowDone:
|
||||||
|
POPD
|
||||||
|
DPUP 0d04
|
||||||
|
PSHD
|
||||||
|
SETD RowCount
|
||||||
|
LDA
|
||||||
|
DECA
|
||||||
|
STA
|
||||||
|
BRA evolveDone
|
||||||
|
POPD
|
||||||
|
BRI evolveRow
|
||||||
|
|
||||||
|
evolveDone:
|
||||||
|
POPD
|
||||||
|
RET
|
||||||
|
|
||||||
|
; DP points to the current-state byte of a visible cell.
|
||||||
|
evolveCell:
|
||||||
|
CALL countNeighbors
|
||||||
|
PSHQ
|
||||||
|
LDA
|
||||||
|
POPB
|
||||||
|
|
||||||
|
; Three neighbors always produces a live cell.
|
||||||
|
INIA 0d03
|
||||||
|
CCF
|
||||||
|
SUB
|
||||||
|
BRQ makeAlive
|
||||||
|
|
||||||
|
; Two neighbors preserve the current state.
|
||||||
|
INIA 0d02
|
||||||
|
CCF
|
||||||
|
SUB
|
||||||
|
BRQ preserveCell
|
||||||
|
|
||||||
|
makeDead:
|
||||||
|
RSTA
|
||||||
|
INCD
|
||||||
|
STA
|
||||||
|
DECD
|
||||||
|
RET
|
||||||
|
|
||||||
|
preserveCell:
|
||||||
|
LDA
|
||||||
|
BRA makeDead
|
||||||
|
|
||||||
|
makeAlive:
|
||||||
|
INIA 0x01
|
||||||
|
INCD
|
||||||
|
STA
|
||||||
|
DECD
|
||||||
|
RET
|
||||||
|
|
||||||
|
; Return the sum of the eight neighboring current-state bytes in Q.
|
||||||
|
; With interleaved cells and an 18-cell row, the relative offsets are:
|
||||||
|
; -38, -36, -34, -2, +2, +34, +36, +38.
|
||||||
|
countNeighbors:
|
||||||
|
RSTA
|
||||||
|
DPDN 0d38
|
||||||
|
|
||||||
|
LDB
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
PSHQ
|
||||||
|
POPA
|
||||||
|
DPUP 0d02
|
||||||
|
|
||||||
|
LDB
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
PSHQ
|
||||||
|
POPA
|
||||||
|
DPUP 0d02
|
||||||
|
|
||||||
|
LDB
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
PSHQ
|
||||||
|
POPA
|
||||||
|
DPUP 0d32
|
||||||
|
|
||||||
|
LDB
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
PSHQ
|
||||||
|
POPA
|
||||||
|
DPUP 0d04
|
||||||
|
|
||||||
|
LDB
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
PSHQ
|
||||||
|
POPA
|
||||||
|
DPUP 0d32
|
||||||
|
|
||||||
|
LDB
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
PSHQ
|
||||||
|
POPA
|
||||||
|
DPUP 0d02
|
||||||
|
|
||||||
|
LDB
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
PSHQ
|
||||||
|
POPA
|
||||||
|
DPUP 0d02
|
||||||
|
|
||||||
|
LDB
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
RET
|
||||||
|
|
||||||
|
; Copy every next-state byte to its adjacent current-state byte.
|
||||||
|
; The border's next bytes remain zero, so it stays permanently dead.
|
||||||
|
commitBoard:
|
||||||
|
SETD Board
|
||||||
|
INIA 0d18
|
||||||
|
SETD RowCount
|
||||||
|
STA
|
||||||
|
SETD Board
|
||||||
|
|
||||||
|
commitRow:
|
||||||
|
PSHD
|
||||||
|
INIA 0d18
|
||||||
|
SETD ColCount
|
||||||
|
STA
|
||||||
|
POPD
|
||||||
|
|
||||||
|
commitCell:
|
||||||
|
INCD
|
||||||
|
LDA
|
||||||
|
DECD
|
||||||
|
STA
|
||||||
|
DPUP 0d02
|
||||||
|
PSHD
|
||||||
|
SETD ColCount
|
||||||
|
LDA
|
||||||
|
DECA
|
||||||
|
STA
|
||||||
|
BRA commitRowDone
|
||||||
|
POPD
|
||||||
|
BRI commitCell
|
||||||
|
|
||||||
|
commitRowDone:
|
||||||
|
POPD
|
||||||
|
PSHD
|
||||||
|
SETD RowCount
|
||||||
|
LDA
|
||||||
|
DECA
|
||||||
|
STA
|
||||||
|
BRA commitDone
|
||||||
|
POPD
|
||||||
|
BRI commitRow
|
||||||
|
|
||||||
|
commitDone:
|
||||||
|
POPD
|
||||||
|
RET
|
||||||
|
|
||||||
|
; Approximately 0.2 seconds at the emulator's nominal 1 MHz rate.
|
||||||
|
frameDelay:
|
||||||
|
INIA 0xFF
|
||||||
|
delayOuter:
|
||||||
|
INIB 0xFF
|
||||||
|
delayInner:
|
||||||
|
DECB
|
||||||
|
BRB delayInnerDone
|
||||||
|
BRI delayInner
|
||||||
|
delayInnerDone:
|
||||||
|
DECA
|
||||||
|
BRA delayDone
|
||||||
|
BRI delayOuter
|
||||||
|
delayDone:
|
||||||
|
RET
|
||||||
|
|
||||||
|
#Data
|
||||||
|
|
||||||
|
RowCount:
|
||||||
|
0x00
|
||||||
|
ColCount:
|
||||||
|
0x00
|
||||||
|
|
||||||
|
ClearScreen:
|
||||||
|
0x1B
|
||||||
|
"[2J"
|
||||||
|
CursorHome:
|
||||||
|
0x1B
|
||||||
|
"[H"
|
||||||
|
|
||||||
|
; The emulator zero-fills the remainder of Data Memory. Board names the first
|
||||||
|
; byte of a 648-byte logical allocation (18 * 18 * 2).
|
||||||
|
Board:
|
||||||
|
0x00
|
||||||
@@ -0,0 +1,236 @@
|
|||||||
|
; A segmented Sieve of Eratosthenes for the complete 16-bit address range.
|
||||||
|
;
|
||||||
|
; The sieve uses a 256-byte sliding window. Each entry in PrimeStates contains:
|
||||||
|
; prime, high byte of next multiple, low byte of next multiple
|
||||||
|
;
|
||||||
|
; Once a prime becomes active at p*p, adding an 8-bit prime to offsets in a
|
||||||
|
; 256-byte window must wrap exactly once before the next window. The wrapped
|
||||||
|
; low byte becomes that prime's starting offset in the following window.
|
||||||
|
;
|
||||||
|
; Output is hexadecimal (0002 through FFFD), separated by spaces.
|
||||||
|
|
||||||
|
#Include Libraries/print.asm
|
||||||
|
|
||||||
|
#Program
|
||||||
|
|
||||||
|
start:
|
||||||
|
RSTA
|
||||||
|
SETD Page
|
||||||
|
STA
|
||||||
|
|
||||||
|
nextPage:
|
||||||
|
; Clear all 256 flags. A wrapping to zero terminates the loop.
|
||||||
|
SETD Segment
|
||||||
|
RSTA
|
||||||
|
RSTB
|
||||||
|
clearSegment:
|
||||||
|
STB
|
||||||
|
INCD
|
||||||
|
INCA
|
||||||
|
BRA segmentCleared
|
||||||
|
BRI clearSegment
|
||||||
|
|
||||||
|
segmentCleared:
|
||||||
|
; Zero and one are not prime.
|
||||||
|
SETD Page
|
||||||
|
LDA
|
||||||
|
BRA excludeZeroAndOne
|
||||||
|
BRI markSegment
|
||||||
|
excludeZeroAndOne:
|
||||||
|
SETD Segment
|
||||||
|
INIA 0x01
|
||||||
|
STA
|
||||||
|
INCD
|
||||||
|
STA
|
||||||
|
|
||||||
|
markSegment:
|
||||||
|
; Process the 54 primes not greater than sqrt(0xFFFF).
|
||||||
|
SETD PrimeStates
|
||||||
|
INIA 0d54
|
||||||
|
primeLoop:
|
||||||
|
CALL processPrime
|
||||||
|
DPUP 0d03
|
||||||
|
DECA
|
||||||
|
BRA scanSegment
|
||||||
|
BRI primeLoop
|
||||||
|
|
||||||
|
scanSegment:
|
||||||
|
; A is the low byte of the candidate and wraps after 0xFF.
|
||||||
|
SETD Segment
|
||||||
|
RSTA
|
||||||
|
scanLoop:
|
||||||
|
LDB
|
||||||
|
BRB emitPrime
|
||||||
|
scanNext:
|
||||||
|
INCD
|
||||||
|
INCA
|
||||||
|
BRA advancePage
|
||||||
|
BRI scanLoop
|
||||||
|
|
||||||
|
emitPrime:
|
||||||
|
CALL printCandidateHex
|
||||||
|
BRI scanNext
|
||||||
|
|
||||||
|
advancePage:
|
||||||
|
SETD Page
|
||||||
|
LDA
|
||||||
|
INCA
|
||||||
|
STA
|
||||||
|
BRA finished
|
||||||
|
BRI nextPage
|
||||||
|
|
||||||
|
finished:
|
||||||
|
CALL lineFeed
|
||||||
|
HALT
|
||||||
|
|
||||||
|
; DP points at a PrimeStates entry on entry and is preserved by CALL.
|
||||||
|
processPrime:
|
||||||
|
PSHD
|
||||||
|
INCD
|
||||||
|
LDA
|
||||||
|
SETD Page
|
||||||
|
LDB
|
||||||
|
XOR
|
||||||
|
BRQ primeIsActive
|
||||||
|
POPD
|
||||||
|
RET
|
||||||
|
|
||||||
|
primeIsActive:
|
||||||
|
; Recover and retain the state-entry pointer for the final update.
|
||||||
|
POPD
|
||||||
|
PSHD
|
||||||
|
|
||||||
|
; Load the prime into B and its current offset into A.
|
||||||
|
LDA
|
||||||
|
PSHA
|
||||||
|
DPUP 0d02
|
||||||
|
LDA
|
||||||
|
POPB
|
||||||
|
|
||||||
|
; Form Segment + offset. Segment is page-aligned in Data Memory.
|
||||||
|
SETD Segment
|
||||||
|
PSHB
|
||||||
|
PSHD
|
||||||
|
POPB
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
PSHQ
|
||||||
|
POPD
|
||||||
|
POPB
|
||||||
|
|
||||||
|
markPrimeLoop:
|
||||||
|
INIA 0x01
|
||||||
|
STA
|
||||||
|
|
||||||
|
; Add the prime to the low byte of DP using the stack as a 16-bit
|
||||||
|
; address adapter. Carry means that the next multiple is in the next page.
|
||||||
|
PSHD
|
||||||
|
POPA
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
PSHQ
|
||||||
|
POPD
|
||||||
|
BRC primeFinished
|
||||||
|
BRI markPrimeLoop
|
||||||
|
|
||||||
|
primeFinished:
|
||||||
|
; Q is the wrapped offset for the next page.
|
||||||
|
POPD
|
||||||
|
INCD
|
||||||
|
LDA
|
||||||
|
INCA
|
||||||
|
STA
|
||||||
|
INCD
|
||||||
|
STQ
|
||||||
|
RET
|
||||||
|
|
||||||
|
; A contains the candidate's low byte. Page contains its high byte.
|
||||||
|
printCandidateHex:
|
||||||
|
PSHA
|
||||||
|
SETD Page
|
||||||
|
LDA
|
||||||
|
CALL printByteHex
|
||||||
|
POPA
|
||||||
|
CALL printByteHex
|
||||||
|
CALL blankSpace
|
||||||
|
RET
|
||||||
|
|
||||||
|
#Data
|
||||||
|
|
||||||
|
; print.asm deliberately pads its data to one page, so this begins at 0x0100.
|
||||||
|
Segment:
|
||||||
|
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||||
|
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||||
|
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||||
|
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||||
|
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||||
|
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||||
|
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||||
|
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||||
|
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||||
|
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||||
|
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||||
|
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||||
|
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||||
|
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||||
|
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||||
|
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||||
|
|
||||||
|
Page:
|
||||||
|
0x00
|
||||||
|
|
||||||
|
PrimeStates:
|
||||||
|
0x02 0x00 0x04
|
||||||
|
0x03 0x00 0x09
|
||||||
|
0x05 0x00 0x19
|
||||||
|
0x07 0x00 0x31
|
||||||
|
0x0B 0x00 0x79
|
||||||
|
0x0D 0x00 0xA9
|
||||||
|
0x11 0x01 0x21
|
||||||
|
0x13 0x01 0x69
|
||||||
|
0x17 0x02 0x11
|
||||||
|
0x1D 0x03 0x49
|
||||||
|
0x1F 0x03 0xC1
|
||||||
|
0x25 0x05 0x59
|
||||||
|
0x29 0x06 0x91
|
||||||
|
0x2B 0x07 0x39
|
||||||
|
0x2F 0x08 0xA1
|
||||||
|
0x35 0x0A 0xF9
|
||||||
|
0x3B 0x0D 0x99
|
||||||
|
0x3D 0x0E 0x89
|
||||||
|
0x43 0x11 0x89
|
||||||
|
0x47 0x13 0xB1
|
||||||
|
0x49 0x14 0xD1
|
||||||
|
0x4F 0x18 0x61
|
||||||
|
0x53 0x1A 0xE9
|
||||||
|
0x59 0x1E 0xF1
|
||||||
|
0x61 0x24 0xC1
|
||||||
|
0x65 0x27 0xD9
|
||||||
|
0x67 0x29 0x71
|
||||||
|
0x6B 0x2C 0xB9
|
||||||
|
0x6D 0x2E 0x69
|
||||||
|
0x71 0x31 0xE1
|
||||||
|
0x7F 0x3F 0x01
|
||||||
|
0x83 0x43 0x09
|
||||||
|
0x89 0x49 0x51
|
||||||
|
0x8B 0x4B 0x79
|
||||||
|
0x95 0x56 0xB9
|
||||||
|
0x97 0x59 0x11
|
||||||
|
0x9D 0x60 0x49
|
||||||
|
0xA3 0x67 0xC9
|
||||||
|
0xA7 0x6C 0xF1
|
||||||
|
0xAD 0x74 0xE9
|
||||||
|
0xB3 0x7D 0x29
|
||||||
|
0xB5 0x7F 0xF9
|
||||||
|
0xBF 0x8E 0x81
|
||||||
|
0xC1 0x91 0x81
|
||||||
|
0xC5 0x97 0x99
|
||||||
|
0xC7 0x9A 0xB1
|
||||||
|
0xD3 0xAD 0xE9
|
||||||
|
0xDF 0xC2 0x41
|
||||||
|
0xE3 0xC9 0x49
|
||||||
|
0xE5 0xCC 0xD9
|
||||||
|
0xE9 0xD4 0x11
|
||||||
|
0xEF 0xDF 0x21
|
||||||
|
0xF1 0xE2 0xE1
|
||||||
|
0xFB 0xF6 0x19
|
||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,410 @@
|
|||||||
|
; Interactive hexadecimal calculator for SplitBit.
|
||||||
|
;
|
||||||
|
; Enter expressions as:
|
||||||
|
; HH operator HH
|
||||||
|
; Whitespace is optional. Supported operators are + - * & | and ^.
|
||||||
|
; Arithmetic wraps to eight bits. Enter Q to quit.
|
||||||
|
|
||||||
|
#Include Libraries/print.asm
|
||||||
|
|
||||||
|
#Program
|
||||||
|
|
||||||
|
start:
|
||||||
|
SETD Welcome
|
||||||
|
CALL printString
|
||||||
|
|
||||||
|
repl:
|
||||||
|
SETD Prompt
|
||||||
|
CALL printString
|
||||||
|
|
||||||
|
CALL readNonSpace
|
||||||
|
PSHQ
|
||||||
|
POPA
|
||||||
|
|
||||||
|
; Q, q, or end-of-file exits.
|
||||||
|
INIB 0xFF
|
||||||
|
XOR
|
||||||
|
BRQ quit
|
||||||
|
INIB 0x51
|
||||||
|
XOR
|
||||||
|
BRQ quit
|
||||||
|
INIB 0x71
|
||||||
|
XOR
|
||||||
|
BRQ quit
|
||||||
|
|
||||||
|
CALL readHexByteFirst
|
||||||
|
SETD LeftOperand
|
||||||
|
STQ
|
||||||
|
CALL parseIsInvalid
|
||||||
|
BRQ inputError
|
||||||
|
|
||||||
|
CALL readNonSpace
|
||||||
|
PSHQ
|
||||||
|
POPA
|
||||||
|
SETD Operator
|
||||||
|
STA
|
||||||
|
|
||||||
|
CALL readNonSpace
|
||||||
|
PSHQ
|
||||||
|
POPA
|
||||||
|
CALL readHexByteFirst
|
||||||
|
SETD RightOperand
|
||||||
|
STQ
|
||||||
|
CALL parseIsInvalid
|
||||||
|
BRQ inputError
|
||||||
|
|
||||||
|
CALL discardLine
|
||||||
|
CALL evaluate
|
||||||
|
SETD Result
|
||||||
|
STQ
|
||||||
|
CALL operatorIsInvalid
|
||||||
|
BRQ operatorError
|
||||||
|
|
||||||
|
SETD Result
|
||||||
|
LDA
|
||||||
|
CALL printByteHex
|
||||||
|
CALL lineFeed
|
||||||
|
BRI repl
|
||||||
|
|
||||||
|
inputError:
|
||||||
|
CALL discardLine
|
||||||
|
SETD BadInput
|
||||||
|
CALL printString
|
||||||
|
BRI repl
|
||||||
|
|
||||||
|
operatorError:
|
||||||
|
SETD BadOperator
|
||||||
|
CALL printString
|
||||||
|
BRI repl
|
||||||
|
|
||||||
|
quit:
|
||||||
|
SETD Goodbye
|
||||||
|
CALL printString
|
||||||
|
HALT
|
||||||
|
|
||||||
|
; Read a character other than space, tab, CR, or LF. Return it in Q.
|
||||||
|
readNonSpace:
|
||||||
|
readNonSpaceLoop:
|
||||||
|
INA 0x00
|
||||||
|
INIB 0x20
|
||||||
|
XOR
|
||||||
|
BRQ readNonSpaceLoop
|
||||||
|
INIB 0x09
|
||||||
|
XOR
|
||||||
|
BRQ readNonSpaceLoop
|
||||||
|
INIB 0x0A
|
||||||
|
XOR
|
||||||
|
BRQ readNonSpaceLoop
|
||||||
|
INIB 0x0D
|
||||||
|
XOR
|
||||||
|
BRQ readNonSpaceLoop
|
||||||
|
INIB 0x00
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
RET
|
||||||
|
|
||||||
|
; A contains the first hexadecimal digit. Read the second and return the byte
|
||||||
|
; in Q. Q is 0xFF on malformed input.
|
||||||
|
readHexByteFirst:
|
||||||
|
CALL clearParseStatus
|
||||||
|
CALL hexNibble
|
||||||
|
PSHQ
|
||||||
|
POPA
|
||||||
|
INIB 0xFF
|
||||||
|
XOR
|
||||||
|
BRQ invalidByte
|
||||||
|
INIB 0x00
|
||||||
|
SHL
|
||||||
|
SHL
|
||||||
|
SHL
|
||||||
|
SHL
|
||||||
|
PSHA
|
||||||
|
|
||||||
|
CALL readNonSpace
|
||||||
|
PSHQ
|
||||||
|
POPA
|
||||||
|
CALL hexNibble
|
||||||
|
PSHQ
|
||||||
|
POPA
|
||||||
|
INIB 0xFF
|
||||||
|
XOR
|
||||||
|
BRQ invalidLowNibble
|
||||||
|
POPB
|
||||||
|
OR
|
||||||
|
RET
|
||||||
|
|
||||||
|
invalidLowNibble:
|
||||||
|
POPB
|
||||||
|
invalidByte:
|
||||||
|
PSHD
|
||||||
|
SETD ParseStatus
|
||||||
|
INIA 0x01
|
||||||
|
STA
|
||||||
|
POPD
|
||||||
|
INIA 0xFF
|
||||||
|
INIB 0x00
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
RET
|
||||||
|
|
||||||
|
; Convert the ASCII hexadecimal digit in A to a value in Q.
|
||||||
|
; Uppercase and lowercase letters are accepted. Q=0xFF means invalid.
|
||||||
|
hexNibble:
|
||||||
|
PSHA
|
||||||
|
|
||||||
|
; Try 0 through 9.
|
||||||
|
INIB 0x30
|
||||||
|
CCF
|
||||||
|
SUB
|
||||||
|
BRC tryUpperHex
|
||||||
|
PSHQ
|
||||||
|
POPA
|
||||||
|
INIB 0d10
|
||||||
|
CCF
|
||||||
|
SUB
|
||||||
|
BRC decimalNibble
|
||||||
|
|
||||||
|
tryUpperHex:
|
||||||
|
POPA
|
||||||
|
PSHA
|
||||||
|
INIB 0x41
|
||||||
|
CCF
|
||||||
|
SUB
|
||||||
|
BRC tryLowerHex
|
||||||
|
PSHQ
|
||||||
|
POPA
|
||||||
|
INIB 0d06
|
||||||
|
CCF
|
||||||
|
SUB
|
||||||
|
BRC upperNibble
|
||||||
|
|
||||||
|
tryLowerHex:
|
||||||
|
POPA
|
||||||
|
PSHA
|
||||||
|
INIB 0x61
|
||||||
|
CCF
|
||||||
|
SUB
|
||||||
|
BRC badNibble
|
||||||
|
PSHQ
|
||||||
|
POPA
|
||||||
|
INIB 0d06
|
||||||
|
CCF
|
||||||
|
SUB
|
||||||
|
BRC lowerNibble
|
||||||
|
|
||||||
|
badNibble:
|
||||||
|
POPA
|
||||||
|
INIA 0xFF
|
||||||
|
INIB 0x00
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
RET
|
||||||
|
|
||||||
|
decimalNibble:
|
||||||
|
POPB
|
||||||
|
INIB 0x00
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
RET
|
||||||
|
|
||||||
|
upperNibble:
|
||||||
|
POPB
|
||||||
|
INIB 0d10
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
RET
|
||||||
|
|
||||||
|
lowerNibble:
|
||||||
|
POPB
|
||||||
|
INIB 0d10
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
RET
|
||||||
|
|
||||||
|
; Return Q=0 if Q was 0xFF, otherwise return a nonzero value.
|
||||||
|
resultIsInvalid:
|
||||||
|
PSHQ
|
||||||
|
POPA
|
||||||
|
INIB 0xFF
|
||||||
|
XOR
|
||||||
|
RET
|
||||||
|
|
||||||
|
clearParseStatus:
|
||||||
|
PSHD
|
||||||
|
SETD ParseStatus
|
||||||
|
RSTA
|
||||||
|
STA
|
||||||
|
POPD
|
||||||
|
RET
|
||||||
|
|
||||||
|
parseIsInvalid:
|
||||||
|
PSHD
|
||||||
|
SETD ParseStatus
|
||||||
|
LDA
|
||||||
|
INIB 0x01
|
||||||
|
XOR
|
||||||
|
POPD
|
||||||
|
RET
|
||||||
|
|
||||||
|
operatorIsInvalid:
|
||||||
|
PSHD
|
||||||
|
SETD OperatorStatus
|
||||||
|
LDA
|
||||||
|
INIB 0x01
|
||||||
|
XOR
|
||||||
|
POPD
|
||||||
|
RET
|
||||||
|
|
||||||
|
; Evaluate the stored expression and return its result in Q.
|
||||||
|
evaluate:
|
||||||
|
PSHD
|
||||||
|
SETD OperatorStatus
|
||||||
|
RSTA
|
||||||
|
STA
|
||||||
|
POPD
|
||||||
|
SETD Operator
|
||||||
|
LDA
|
||||||
|
|
||||||
|
INIB 0x2B
|
||||||
|
XOR
|
||||||
|
BRQ evaluateAdd
|
||||||
|
INIB 0x2D
|
||||||
|
XOR
|
||||||
|
BRQ evaluateSubtract
|
||||||
|
INIB 0x2A
|
||||||
|
XOR
|
||||||
|
BRQ evaluateMultiply
|
||||||
|
INIB 0x26
|
||||||
|
XOR
|
||||||
|
BRQ evaluateAnd
|
||||||
|
INIB 0x7C
|
||||||
|
XOR
|
||||||
|
BRQ evaluateOr
|
||||||
|
INIB 0x5E
|
||||||
|
XOR
|
||||||
|
BRQ evaluateXor
|
||||||
|
|
||||||
|
SETD OperatorStatus
|
||||||
|
INIA 0x01
|
||||||
|
STA
|
||||||
|
RSTA
|
||||||
|
INIB 0x00
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
RET
|
||||||
|
|
||||||
|
evaluateAdd:
|
||||||
|
SETD LeftOperand
|
||||||
|
LDA
|
||||||
|
INCD
|
||||||
|
LDB
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
RET
|
||||||
|
|
||||||
|
evaluateSubtract:
|
||||||
|
SETD LeftOperand
|
||||||
|
LDA
|
||||||
|
INCD
|
||||||
|
LDB
|
||||||
|
CCF
|
||||||
|
SUB
|
||||||
|
RET
|
||||||
|
|
||||||
|
evaluateAnd:
|
||||||
|
SETD LeftOperand
|
||||||
|
LDA
|
||||||
|
INCD
|
||||||
|
LDB
|
||||||
|
AND
|
||||||
|
RET
|
||||||
|
|
||||||
|
evaluateOr:
|
||||||
|
SETD LeftOperand
|
||||||
|
LDA
|
||||||
|
INCD
|
||||||
|
LDB
|
||||||
|
OR
|
||||||
|
RET
|
||||||
|
|
||||||
|
evaluateXor:
|
||||||
|
SETD LeftOperand
|
||||||
|
LDA
|
||||||
|
INCD
|
||||||
|
LDB
|
||||||
|
XOR
|
||||||
|
RET
|
||||||
|
|
||||||
|
evaluateMultiply:
|
||||||
|
RSTA
|
||||||
|
SETD Product
|
||||||
|
STA
|
||||||
|
|
||||||
|
multiplyLoop:
|
||||||
|
SETD RightOperand
|
||||||
|
LDA
|
||||||
|
BRA multiplyDone
|
||||||
|
DECA
|
||||||
|
STA
|
||||||
|
|
||||||
|
SETD Product
|
||||||
|
LDA
|
||||||
|
SETD LeftOperand
|
||||||
|
LDB
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
SETD Product
|
||||||
|
STQ
|
||||||
|
BRI multiplyLoop
|
||||||
|
|
||||||
|
multiplyDone:
|
||||||
|
SETD Product
|
||||||
|
LDA
|
||||||
|
INIB 0x00
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
RET
|
||||||
|
|
||||||
|
; Consume the rest of the current input line.
|
||||||
|
discardLine:
|
||||||
|
discardLoop:
|
||||||
|
INA 0x00
|
||||||
|
INIB 0x0A
|
||||||
|
XOR
|
||||||
|
BRQ discardDone
|
||||||
|
INIB 0xFF
|
||||||
|
XOR
|
||||||
|
BRQ discardDone
|
||||||
|
BRI discardLoop
|
||||||
|
discardDone:
|
||||||
|
RET
|
||||||
|
|
||||||
|
#Data
|
||||||
|
|
||||||
|
LeftOperand:
|
||||||
|
0x00
|
||||||
|
RightOperand:
|
||||||
|
0x00
|
||||||
|
Operator:
|
||||||
|
0x00
|
||||||
|
Product:
|
||||||
|
0x00
|
||||||
|
Result:
|
||||||
|
0x00
|
||||||
|
ParseStatus:
|
||||||
|
0x00
|
||||||
|
OperatorStatus:
|
||||||
|
0x00
|
||||||
|
|
||||||
|
Welcome:
|
||||||
|
"SplitBit calculator (+ - * & | ^), Q quits."
|
||||||
|
Prompt:
|
||||||
|
0x0A
|
||||||
|
"> "
|
||||||
|
BadInput:
|
||||||
|
"Invalid hexadecimal input."
|
||||||
|
BadOperator:
|
||||||
|
"Unknown operator."
|
||||||
|
Goodbye:
|
||||||
|
"Goodbye!"
|
||||||
|
0x0A
|
||||||
Binary file not shown.
@@ -0,0 +1,54 @@
|
|||||||
|
; Tests the Data Pointer calling convention.
|
||||||
|
;
|
||||||
|
; Every Data Pointer is aimed at a different marker byte, then a subroutine
|
||||||
|
; repoints all four of them at Z and returns.
|
||||||
|
;
|
||||||
|
; DP0 through DP2 are preserved across a CALL, so they should come back still
|
||||||
|
; aimed at their own markers. DP3 is volatile, which is what lets a subroutine
|
||||||
|
; hand an address back to its caller, so it should come back aimed at Z.
|
||||||
|
;
|
||||||
|
; Correct output is ABCZ.
|
||||||
|
|
||||||
|
#Program
|
||||||
|
|
||||||
|
start:
|
||||||
|
SETD.0 MarkA
|
||||||
|
SETD.1 MarkB
|
||||||
|
SETD.2 MarkC
|
||||||
|
SETD.3 MarkD
|
||||||
|
CALL clobber
|
||||||
|
|
||||||
|
; Read a byte through each pointer in turn and print it.
|
||||||
|
LDA.0
|
||||||
|
OUTA 0x00
|
||||||
|
LDA.1
|
||||||
|
OUTA 0x00
|
||||||
|
LDA.2
|
||||||
|
OUTA 0x00
|
||||||
|
LDA.3
|
||||||
|
OUTA 0x00
|
||||||
|
|
||||||
|
INIA 0x0A
|
||||||
|
OUTA 0x00
|
||||||
|
HALT
|
||||||
|
|
||||||
|
clobber:
|
||||||
|
; Aim every pointer somewhere else. Only the change to DP3 should outlive the RET.
|
||||||
|
SETD.0 MarkZ
|
||||||
|
SETD.1 MarkZ
|
||||||
|
SETD.2 MarkZ
|
||||||
|
SETD.3 MarkZ
|
||||||
|
RET
|
||||||
|
|
||||||
|
#Data
|
||||||
|
|
||||||
|
MarkA:
|
||||||
|
"A"
|
||||||
|
MarkB:
|
||||||
|
"B"
|
||||||
|
MarkC:
|
||||||
|
"C"
|
||||||
|
MarkD:
|
||||||
|
"D"
|
||||||
|
MarkZ:
|
||||||
|
"Z"
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
; Copies a string from one place in Data Memory to another, reading through DP0
|
||||||
|
; and writing through DP1 at the same time.
|
||||||
|
;
|
||||||
|
; On a machine with one Data Pointer this loop needs a PSHD and a POPD on every
|
||||||
|
; pass to swap the pointer between the two regions. With two pointers it is just
|
||||||
|
; a load and a store.
|
||||||
|
;
|
||||||
|
; It also checks that a bare mnemonic still means DP0.
|
||||||
|
|
||||||
|
#Program
|
||||||
|
|
||||||
|
start:
|
||||||
|
SETD.0 Source ; DP0 walks the source.
|
||||||
|
SETD.1 Dest ; DP1 walks the destination.
|
||||||
|
|
||||||
|
copy:
|
||||||
|
LDA.0 ; Read a byte through DP0.
|
||||||
|
BRA copyDone ; A zero byte is the end of the string.
|
||||||
|
STA.1 ; Write it through DP1.
|
||||||
|
INCD.0
|
||||||
|
INCD.1
|
||||||
|
BRI copy
|
||||||
|
|
||||||
|
copyDone:
|
||||||
|
SETD Dest ; No selector, so this is DP0.
|
||||||
|
print:
|
||||||
|
LDA
|
||||||
|
BRA end
|
||||||
|
OUTA 0x00
|
||||||
|
INCD
|
||||||
|
BRI print
|
||||||
|
|
||||||
|
end:
|
||||||
|
INIA 0x0A
|
||||||
|
OUTA 0x00
|
||||||
|
HALT
|
||||||
|
|
||||||
|
#Data
|
||||||
|
|
||||||
|
Source:
|
||||||
|
"Two pointers, no stack shenanigans."
|
||||||
|
|
||||||
|
Dest:
|
||||||
|
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||||
|
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||||
|
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||||
Reference in New Issue
Block a user