2 changed files with 730 additions and 0 deletions
@ -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)
|
@ -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 new issue