Start work on a calculator program for Thingamajig

This commit is contained in:
Juhani Krekelä 2022-08-08 18:52:34 +03:00
parent 110280ed5e
commit 117a2e24c2
2 changed files with 730 additions and 0 deletions

18
Makefile Normal file
View File

@ -0,0 +1,18 @@
BIN=calculator.bin
.SUFFIXES:
.SUFFIXES: .asm .bin
.PHONY: all
all: $(BIN)
.asm.bin:
thingamajig_assembler $@ < $<
.PHONY: clean distclean
clean:
rm -f $(BIN)
distclean: clean
.PHONY: run
run: $(BIN)
thingamajig_emulator $(BIN)

712
calculator.asm Normal file
View File

@ -0,0 +1,712 @@
org 0
start:
cleq r0, r0, initStack
load r0, lit01
load r1, litff
cleq r0, r0, pushWord
cleq r0, r0, stPrinthex
xor r0, r0
load r1, lit41
cleq r0, r0, pushWord
cleq r0, r0, stPrinthex
cleq r0, r0, stSub
cleq r0, r0, stPrinthex
halt
; ==================================================================
; Stack-based functions
; ==================================================================
; ------------------------------------------------------------------
; Arithmetic
; ------------------------------------------------------------------
; a b -- a+b
stAdd:
cleq r0, r0, popWord
cleq r0, r0, tmpStoreWord01
cleq r0, r0, popWord
cleq r0, r0, tmpLoadWord23
cleq r0, r0, addWord
breq r0, r0, pushWord
; a b -- a-b
stSub:
cleq r0, r0, stNeg
breq r0, r0, stAdd
; n -- -n
stNeg:
cleq r0, r0, popWord
nand r0, r0
nand r1, r1
cleq r0, r0, incWord
breq r0, r0, pushWord
; ------------------------------------------------------------------
; I/O
; ------------------------------------------------------------------
; n -- n
stPrinthex:
cleq r0, r0, peekWord
cleq r0, r0, writehexWord
breq r0, r0, newline
; -- c
stKey:
xor r0, r0
load r1, ffff
breq r0, r0, pushWord
; c --
stEmit:
cleq r0, r0, popWord
store ffff, r1
ret
; ==================================================================
; Low-level functions
; ==================================================================
; ------------------------------------------------------------------
; Memory
; ------------------------------------------------------------------
tmpWordHigh: data 0
tmpWordLow: data 0
; out:
; r0:r1 = word
peekWord:
cleq r0, r0, popWord
cleq r0, r0, tmpStoreWord01
cleq r0, r0, pushWord
breq r0, r0, tmpLoadWord01
; in:
; r0:r1 = word
tmpStoreWord01:
store tmpWordHigh, r0
store tmpWordLow, r1
ret
; out:
; r0:r1 = word
tmpLoadWord01:
load r0, tmpWordHigh
load r1, tmpWordLow
ret
; out:
; r2:r3 = word
tmpLoadWord23:
load r2, tmpWordHigh
load r3, tmpWordLow
ret
; in:
; r0:r1 = word
; trashes:
; r0, r1, r2, r3
pushWord:
store pushWordLow, r1
cleq r0, r0, pushByte
load r0, pushWordLow
breq r0, r0, pushByte
pushWordLow: data 0
; out:
; r0:r1
; trashes:
; r2, r3
popWord:
cleq r0, r0, popByte
store popWordLow, r0
cleq r0, r0, popByte
load r1, popWordLow
ret
popWordLow: data 0
; in:
; r0 = byte
; trashes:
; r0, r1, r2, r3
pushByte:
load r2, SPHigh
store storeByteHigh, r2
load r3, SPLow
store storeByteLow, r3
cleq r0, r0, storeByte
load r0, SPHigh
load r1, SPLow
cleq r0, r0, incWord
store SPHigh, r0
store SPLow, r1
ret
; out:
; r0 = byte
; trashes:
; r1, r2, r3
popByte:
load r0, SPHigh
load r1, SPLow
cleq r0, r0, decWord
store SPHigh, r0
store SPLow, r1
store loadByteHigh, r0
store loadByteLow, r1
breq r0, r0, loadByte
; in:
; storeByteHigh:storeByteLow = address
; r0 = byte
storeByte:
data b0 ; store addr, r0
storeByteHigh: data 0
storeByteLow: data 0
ret
; in:
; loadByteHigh:loadByteLow = address
; out:
; r0 = byte
loadByte:
data a0 ; load r0, addr
loadByteHigh: data 0
loadByteLow: data 0
ret
; ------------------------------------------------------------------
; Arithmetic
; ------------------------------------------------------------------
; in:
; r0:r1 = first addend
; r2:r3 = second addend
; out:
; r0:r1 = result
; r2 = carryout
; trashes:
; r3
addWord:
store addWordFirstHigh, r0
store addWordSecondHigh, r2
; Add low bytes
xor r0, r0
or r0, r3
cleq r0, r0, addByte
store addWordResultLow, r0
; Add high bytes and carry (in r1)
load r0, addWordFirstHigh
load r2, addWordSecondHigh
cleq r0, r0, addByte3
; Move carryout to r2
xor r2, r2
or r2, r1
load r1, addWordResultLow
ret
addWordFirstHigh: data 0
addWordSecondHigh: data 0
addWordResultLow: data 0
; in/out:
; r0:r1 = word
; trashes:
; r2, r3
incWord:
store incWordHigh, r0
; Add 1 to low byte
load r0, lit01
cleq r0, r0, addByte
store incWordLow, r0
; Add carry to high byte
load r0, incWordHigh
cleq r0, r0, addByte
load r1, incWordLow
ret
incWordHigh: data 0
incWordLow: data 0
; in/out:
; r0:r1 = word
; trashes:
; r2, r3
decWord:
store decWordHigh, r0
; Add ff to low byte
load r0, litff
cleq r0, r0, addByte
store decWordLow, r0
; Add ff and carry to high byte
load r0, litff
load r2, decWordHigh
cleq r0, r0, addByte3
load r1, decWordLow
ret
decWordHigh: data 0
decWordLow: data 0
; in:
; r0 = first addend
; r1 = second addend
; r2 = third addend
; out:
; r0 = result
; r1 = carryout
; trashes:
; r2, r3
addByte3:
store addByte3ThirdAddend, r2
cleq r0, r0, addByte
store addByte3Carryout, r1
load r1, addByte3ThirdAddend
cleq r0, r0, addByte
load r3, addByte3Carryout
or r1, r3
ret
addByte3ThirdAddend: data 0
addByte3Carryout: data 0
; in:
; r0 = first addend
; r1 = second addend
; out:
; r0 = result
; r1 = carryout
; trashes:
; r2, r3
addByte:
; Initiliaze carryout to 0
xor r2, r2
addByteLoop:
; Copy second addend to r3
xor r3, r3
or r3, r1
; Calculate carries in r3
and r3, r0
or r2, r3 ; Accumulate carry into carryout
shl r3
; Calculate sums in r0
xor r0, r1
; Copy carries into second addend
xor r1, r1
or r1, r3
; Loop until second addend is 0
xor r3, r3
brneq r1, r3, addByteLoop
; Shift carryout, as we want carry from highest place = 1
shr r2
shr r2
shr r2
shr r2
shr r2
shr r2
shr r2
; Move carryout to r1
; (We know r1 is already 0 since it's the loop condition)
or r1, r2
ret
; ------------------------------------------------------------------
; Hex conversion routines
; ------------------------------------------------------------------
; in:
; r0 = number in range [0, 0xf]
; out:
; r0 = ascii character corresponding to input
; trashes:
; r3
nybble2hex:
xor r3, r3
breq r0, r3, nybble2hex0
load r3, lit01
breq r0, r3, nybble2hex1
load r3, lit02
breq r0, r3, nybble2hex2
load r3, lit03
breq r0, r3, nybble2hex3
load r3, lit04
breq r0, r3, nybble2hex4
load r3, lit05
breq r0, r3, nybble2hex5
load r3, lit06
breq r0, r3, nybble2hex6
load r3, lit07
breq r0, r3, nybble2hex7
load r3, lit08
breq r0, r3, nybble2hex8
load r3, lit09
breq r0, r3, nybble2hex9
load r3, lit0a
breq r0, r3, nybble2hexa
load r3, lit0b
breq r0, r3, nybble2hexb
load r3, lit0c
breq r0, r3, nybble2hexc
load r3, lit0d
breq r0, r3, nybble2hexd
load r3, lit0e
breq r0, r3, nybble2hexe
load r3, lit0f
breq r0, r3, nybble2hexf
breq r0, r0, error
nybble2hex0:
load r0, litchar0
ret
nybble2hex1:
load r0, litchar1
ret
nybble2hex2:
load r0, litchar2
ret
nybble2hex3:
load r0, litchar3
ret
nybble2hex4:
load r0, litchar4
ret
nybble2hex5:
load r0, litchar5
ret
nybble2hex6:
load r0, litchar6
ret
nybble2hex7:
load r0, litchar7
ret
nybble2hex8:
load r0, litchar8
ret
nybble2hex9:
load r0, litchar9
ret
nybble2hexa:
load r0, litchara
ret
nybble2hexb:
load r0, litcharb
ret
nybble2hexc:
load r0, litcharc
ret
nybble2hexd:
load r0, litchard
ret
nybble2hexe:
load r0, litchare
ret
nybble2hexf:
load r0, litcharf
ret
; in:
; r0 = ascii hex digit
; out:
; r0 = corresponding nybble
; trashes:
; r3
hex2nybble:
load r3, litchar0
breq r0, r3, hex2nybble0
load r3, litchar1
breq r0, r3, hex2nybble1
load r3, litchar2
breq r0, r3, hex2nybble2
load r3, litchar3
breq r0, r3, hex2nybble3
load r3, litchar4
breq r0, r3, hex2nybble4
load r3, litchar5
breq r0, r3, hex2nybble5
load r3, litchar6
breq r0, r3, hex2nybble6
load r3, litchar7
breq r0, r3, hex2nybble7
load r3, litchar8
breq r0, r3, hex2nybble8
load r3, litchar9
breq r0, r3, hex2nybble9
load r3, litchara
breq r0, r3, hex2nybblea
load r3, litcharb
breq r0, r3, hex2nybbleb
load r3, litcharc
breq r0, r3, hex2nybblec
load r3, litchard
breq r0, r3, hex2nybbled
load r3, litchare
breq r0, r3, hex2nybblee
load r3, litcharf
breq r0, r3, hex2nybblef
load r3, litcharUppera
breq r0, r3, hex2nybblea
load r3, litcharUpperb
breq r0, r3, hex2nybbleb
load r3, litcharUpperC
breq r0, r3, hex2nybblec
load r3, litcharUpperD
breq r0, r3, hex2nybbled
load r3, litcharUpperE
breq r0, r3, hex2nybblee
load r3, litcharUpperF
breq r0, r3, hex2nybblef
breq r0, r0, error
hex2nybble0:
xor r0, r0
ret
hex2nybble1:
load r0, lit01
ret
hex2nybble2:
load r0, lit02
ret
hex2nybble3:
load r0, lit03
ret
hex2nybble4:
load r0, lit04
ret
hex2nybble5:
load r0, lit05
ret
hex2nybble6:
load r0, lit06
ret
hex2nybble7:
load r0, lit07
ret
hex2nybble8:
load r0, lit08
ret
hex2nybble9:
load r0, lit09
ret
hex2nybblea:
load r0, lit0a
ret
hex2nybbleb:
load r0, lit0b
ret
hex2nybblec:
load r0, lit0c
ret
hex2nybbled:
load r0, lit0d
ret
hex2nybblee:
load r0, lit0e
ret
hex2nybblef:
load r0, lit0f
ret
; ------------------------------------------------------------------
; Hex output
; ------------------------------------------------------------------
; in:
; r1:r0 = word
; trashes:
; r0, r2, r3
writehexWord:
cleq r0, r0, writehexByte
; Move low byte to r0
xor r0, r0
or r0, r1
breq r0, r0, writehexByte
; in:
; r0 = byte
; trashes:
; r0, r2, r3
writehexByte:
; Store copy of the byte (as r0 is modified by nybble2hex)
xor r2, r2
or r2, r0
; High nybble
shr r0
shr r0
shr r0
shr r0
cleq r0, r0, nybble2hex
store ffff, r0
; Low nybble
load r0, lit0f
and r0, r2
cleq r0, r0, nybble2hex
store ffff, r0
ret
; ------------------------------------------------------------------
; Common output routines
; ------------------------------------------------------------------
; trashes:
; r3
newline:
load r3, litcharCR
store ffff, r3
load r3, litcharLF
store ffff, r3
ret
; noreturn
error:
load r0, litchare
store ffff, r0
load r0, litcharr
store ffff, r0
store ffff, r0
load r1, litcharo
store ffff, r1
store ffff, r0
cleq r0, r0, newline
halt
; ==================================================================
; Literals pool
; ==================================================================
lit01: data 01
lit02: data 02
lit03: data 03
lit04: data 04
lit05: data 05
lit06: data 06
lit07: data 07
litcharBS:
lit08: data 08
lit09: data 09
litcharLF:
lit0a: data 0a
lit0b: data 0b
lit0c: data 0c
litcharCR:
lit0d: data 0d
lit0e: data 0e
lit0f: data 0f
litchar0:
lit30: data 30
litchar1:
lit31: data 31
litchar2:
lit32: data 32
litchar3:
lit33: data 33
litchar4:
lit34: data 34
litchar5:
lit35: data 35
litchar6:
lit36: data 36
litchar7:
lit37: data 37
litchar8:
lit38: data 38
litchar9:
lit39: data 39
litcharUppera:
lit41: data 41
litcharUpperb:
lit42: data 42
litcharUpperc:
lit43: data 43
litcharUpperd:
lit44: data 44
litcharUppere:
lit45: data 45
litcharUpperf:
lit46: data 46
litchara:
lit61: data 61
litcharb:
lit62: data 62
litcharc:
lit63: data 63
litchard:
lit64: data 64
litchare:
lit65: data 65
litcharf:
lit66: data 66
litcharo:
lit6f: data 6f
litcharr:
lit72: data 72
litff: data ff
; ==================================================================
; Stack
; ==================================================================
SPHigh: data 0
SPLow: data 0
; trashes:
; r3
initStack:
load r3, initStackDummyLoad+1
store SPHigh, r3
load r3, initStackDummyLoad+2
store SPLow, r3
ret
initStackDummyLoad: load r0, stackBase
stackBase: