New SplitBit programs.
This commit is contained in:
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