Start work on a calculator program for Thingamajig
This commit is contained in:
parent
110280ed5e
commit
117a2e24c2
2 changed files with 730 additions and 0 deletions
18
Makefile
Normal file
18
Makefile
Normal 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
712
calculator.asm
Normal 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:
|
Loading…
Reference in a new issue