Compare commits
7 Commits
a993cab542
...
677f31ea91
Author | SHA1 | Date |
---|---|---|
Juhani Krekelä | 677f31ea91 | |
Juhani Krekelä | 0fc5da3483 | |
Juhani Krekelä | bbb5b4b35f | |
Juhani Krekelä | e8102339d7 | |
Juhani Krekelä | 8526919479 | |
Juhani Krekelä | 3583fc8379 | |
Juhani Krekelä | 5cfae260fd |
226
calculator.asm
226
calculator.asm
|
@ -1,64 +1,145 @@
|
||||||
org 0
|
org 0
|
||||||
|
|
||||||
start:
|
cleq r0, r0, readline
|
||||||
cleq r0, r0, stReadline
|
|
||||||
cleq r0, r0, dumpstack
|
|
||||||
|
|
||||||
halt
|
load r0, linelen+0
|
||||||
|
load r1, linelen+1
|
||||||
|
cleq r0, r0, pushWord
|
||||||
|
|
||||||
|
cleq r0, r0, stDup
|
||||||
|
cleq r0, r0, stPrinthex
|
||||||
|
|
||||||
|
xor r0, r0
|
||||||
|
xor r1, r1
|
||||||
|
cleq r0, r0, pushWord
|
||||||
|
|
||||||
|
printloop:
|
||||||
|
cleq r0, r0, stOver
|
||||||
|
cleq r0, r0, stOver
|
||||||
|
cleq r0, r0, stSwap
|
||||||
|
cleq r0, r0, stGtEq
|
||||||
|
brneq r0, r1, printend
|
||||||
|
|
||||||
|
cleq r0, r0, stDup
|
||||||
|
load r0, linebufStart+0
|
||||||
|
load r1, linebufStart+1
|
||||||
|
cleq r0, r0, pushWord
|
||||||
|
cleq r0, r0, stAdd
|
||||||
|
|
||||||
|
cleq r0, r0, stLoadByte
|
||||||
|
cleq r0, r0, stEmit
|
||||||
|
|
||||||
|
cleq r0, r0, stInc
|
||||||
|
|
||||||
|
breq r0, r0, printloop
|
||||||
|
|
||||||
|
printend:
|
||||||
|
cleq r0, r0, newline
|
||||||
|
halt
|
||||||
|
|
||||||
|
debug:
|
||||||
|
store debugr0, r0
|
||||||
|
store debugr1, r1
|
||||||
|
store debugr2, r2
|
||||||
|
store debugr3, r3
|
||||||
|
|
||||||
|
debugRegs:
|
||||||
|
load r0, debugr0
|
||||||
|
cleq r0, r0, writehexByte
|
||||||
|
load r0, litcharSpace
|
||||||
|
store ffff, r0
|
||||||
|
|
||||||
|
load r0, debugr1
|
||||||
|
cleq r0, r0, writehexByte
|
||||||
|
load r0, litcharSpace
|
||||||
|
store ffff, r0
|
||||||
|
|
||||||
|
load r0, debugr2
|
||||||
|
cleq r0, r0, writehexByte
|
||||||
|
load r0, litcharSpace
|
||||||
|
store ffff, r0
|
||||||
|
|
||||||
|
load r0, debugr3
|
||||||
|
cleq r0, r0, writehexByte
|
||||||
|
load r0, litcharSpace
|
||||||
|
store ffff, r0
|
||||||
|
|
||||||
|
debugTmpWords:
|
||||||
|
load r0, tmpWordHigh
|
||||||
|
load r1, tmpWordLow
|
||||||
|
cleq r0, r0, writeHexWord
|
||||||
|
load r0, litcharSpace
|
||||||
|
store ffff, r0
|
||||||
|
|
||||||
|
load r0, tmpWord2High
|
||||||
|
load r1, tmpWord2Low
|
||||||
|
cleq r0, r0, writeHexWord
|
||||||
|
load r0, litcharPipe
|
||||||
|
store ffff, r0
|
||||||
|
|
||||||
dumpstack:
|
|
||||||
load r0, SPStart+0
|
load r0, SPStart+0
|
||||||
load r1, SPStart+1
|
load r1, SPStart+1
|
||||||
store dumpstackPtr+0, r0
|
store debugPtr+0, r0
|
||||||
store dumpstackPtr+1, r1
|
store debugPtr+1, r1
|
||||||
|
|
||||||
dumpstackLoop:
|
debugLoop:
|
||||||
load r0, dumpstackPtr+0
|
load r0, debugPtr+0
|
||||||
load r1, dumpstackPtr+1
|
load r1, debugPtr+1
|
||||||
load r2, SP+0
|
load r2, SP+0
|
||||||
load r3, SP+1
|
load r3, SP+1
|
||||||
|
|
||||||
brneq r0, r2, dumpstackDumpword
|
brneq r0, r2, debugDumpword
|
||||||
breq r1, r3, dumpstackEnd
|
breq r1, r3, debugEnd
|
||||||
|
|
||||||
dumpstackDumpword:
|
debugDumpword:
|
||||||
load r0, dumpstackPtr+0
|
load r0, debugPtr+0
|
||||||
load r1, dumpstackPtr+1
|
load r1, debugPtr+1
|
||||||
store loadByteHigh, r0
|
store loadByteHigh, r0
|
||||||
store loadByteLow, r1
|
store loadByteLow, r1
|
||||||
cleq r0, r0, loadByte
|
cleq r0, r0, loadByte
|
||||||
cleq r0, r0, writehexByte
|
cleq r0, r0, writehexByte
|
||||||
|
|
||||||
load r0, dumpstackPtr+0
|
load r0, debugPtr+0
|
||||||
load r1, dumpstackPtr+1
|
load r1, debugPtr+1
|
||||||
cleq r0, r0, incWord
|
cleq r0, r0, incWord
|
||||||
store dumpstackPtr+0, r0
|
store debugPtr+0, r0
|
||||||
store dumpstackPtr+1, r1
|
store debugPtr+1, r1
|
||||||
|
|
||||||
load r0, dumpstackPtr+0
|
load r0, debugPtr+0
|
||||||
load r1, dumpstackPtr+1
|
load r1, debugPtr+1
|
||||||
store loadByteHigh, r0
|
store loadByteHigh, r0
|
||||||
store loadByteLow, r1
|
store loadByteLow, r1
|
||||||
cleq r0, r0, loadByte
|
cleq r0, r0, loadByte
|
||||||
cleq r0, r0, writehexByte
|
cleq r0, r0, writehexByte
|
||||||
|
|
||||||
load r0, dumpstackPtr+0
|
load r0, debugPtr+0
|
||||||
load r1, dumpstackPtr+1
|
load r1, debugPtr+1
|
||||||
cleq r0, r0, incWord
|
cleq r0, r0, incWord
|
||||||
store dumpstackPtr+0, r0
|
store debugPtr+0, r0
|
||||||
store dumpstackPtr+1, r1
|
store debugPtr+1, r1
|
||||||
|
|
||||||
load r0, litcharSpace
|
load r0, litcharSpace
|
||||||
store ffff, r0
|
store ffff, r0
|
||||||
|
|
||||||
breq r0, r0, dumpstackLoop
|
breq r0, r0, debugLoop
|
||||||
|
|
||||||
dumpstackEnd:
|
debugEnd:
|
||||||
breq r0, r0, newline
|
cleq r0, r0, newline
|
||||||
|
|
||||||
dumpstackPtr: addr dumpstackPtr
|
load r0, debugr0
|
||||||
|
load r1, debugr1
|
||||||
|
load r2, debugr2
|
||||||
|
load r3, debugr3
|
||||||
|
|
||||||
stReadline:
|
ret
|
||||||
|
|
||||||
|
debugPtr: addr debugPtr
|
||||||
|
debugr0: data 0
|
||||||
|
debugr1: data 0
|
||||||
|
debugr2: data 0
|
||||||
|
debugr3: data 0
|
||||||
|
|
||||||
|
readline:
|
||||||
; Current index starts at 0
|
; Current index starts at 0
|
||||||
xor r0, r0
|
xor r0, r0
|
||||||
xor r1, r1
|
xor r1, r1
|
||||||
|
@ -101,8 +182,13 @@ stReadline:
|
||||||
breq r0, r0, readlineLoop
|
breq r0, r0, readlineLoop
|
||||||
|
|
||||||
readlineEnter:
|
readlineEnter:
|
||||||
; Remove the CR byte off the stack, as we only want to return the length
|
; Remove the CR byte off the stack, as it's not needed
|
||||||
cleq r0, r0, popWord
|
cleq r0, r0, popWord
|
||||||
|
|
||||||
|
cleq r0, r0, popWord
|
||||||
|
store linelen+0, r0
|
||||||
|
store linelen+1, r1
|
||||||
|
|
||||||
breq r0, r0, newline
|
breq r0, r0, newline
|
||||||
|
|
||||||
readlineBackspace:
|
readlineBackspace:
|
||||||
|
@ -119,6 +205,7 @@ stReadline:
|
||||||
brneq r0, r1, readlineLoop
|
brneq r0, r1, readlineLoop
|
||||||
|
|
||||||
; Decrease the index and erase the echoed character
|
; Decrease the index and erase the echoed character
|
||||||
|
; TODO: utf-8
|
||||||
cleq r0, r0, stDec
|
cleq r0, r0, stDec
|
||||||
load r3, litcharSpace
|
load r3, litcharSpace
|
||||||
store ffff, r3
|
store ffff, r3
|
||||||
|
@ -129,6 +216,7 @@ stReadline:
|
||||||
|
|
||||||
readlineBufFull:
|
readlineBufFull:
|
||||||
; Drop the input byte and erase the echoed character
|
; Drop the input byte and erase the echoed character
|
||||||
|
; TODO: utf-8
|
||||||
cleq r0, r0, popWord
|
cleq r0, r0, popWord
|
||||||
load r3, litcharBS
|
load r3, litcharBS
|
||||||
store ffff, r3
|
store ffff, r3
|
||||||
|
@ -247,7 +335,7 @@ stSwap:
|
||||||
; Memory
|
; Memory
|
||||||
; ------------------------------------------------------------------
|
; ------------------------------------------------------------------
|
||||||
|
|
||||||
; a p --
|
; b ptr --
|
||||||
stStoreByte:
|
stStoreByte:
|
||||||
cleq r0, r0, popWord
|
cleq r0, r0, popWord
|
||||||
store storeByteHigh, r0
|
store storeByteHigh, r0
|
||||||
|
@ -257,6 +345,53 @@ stStoreByte:
|
||||||
or r0, r1
|
or r0, r1
|
||||||
breq r0, r0, storeByte
|
breq r0, r0, storeByte
|
||||||
|
|
||||||
|
; ptr -- b
|
||||||
|
stLoadByte:
|
||||||
|
cleq r0, r0, popWord
|
||||||
|
store loadByteHigh, r0
|
||||||
|
store loadByteLow, r1
|
||||||
|
cleq r0, r0, loadByte
|
||||||
|
xor r1, r1
|
||||||
|
or r1, r0
|
||||||
|
xor r0, r0
|
||||||
|
breq r0, r0, pushWord
|
||||||
|
|
||||||
|
; n ptr --
|
||||||
|
stStoreWord:
|
||||||
|
cleq r0, r0, popWord
|
||||||
|
cleq r0, r0, tmpStoreWord01
|
||||||
|
store storeByteHigh, r0
|
||||||
|
store storeByteLow, r1
|
||||||
|
cleq r0, r0, peekWord
|
||||||
|
cleq r0, r0, storeByte
|
||||||
|
cleq r0, r0, tmpLoadWord01
|
||||||
|
cleq r0, r0, incWord
|
||||||
|
store storeByteHigh, r0
|
||||||
|
store storeByteLow, r1
|
||||||
|
cleq r0, r0, popWord
|
||||||
|
xor r0, r0
|
||||||
|
or r0, r1
|
||||||
|
breq r0, r0, storeByte
|
||||||
|
|
||||||
|
; ptr -- n
|
||||||
|
stLoadWord:
|
||||||
|
cleq r0, r0, peekWord
|
||||||
|
store loadByteHigh, r0
|
||||||
|
store loadByteLow, r1
|
||||||
|
cleq r0, r0, loadByte
|
||||||
|
cleq r0, r0, tmpStoreWord01
|
||||||
|
cleq r0, r0, popWord
|
||||||
|
cleq r0, r0, incWord
|
||||||
|
store loadByteHigh, r0
|
||||||
|
store loadByteLow, r1
|
||||||
|
cleq r0, r0, loadByte
|
||||||
|
xor r2, r2
|
||||||
|
or r2, r0
|
||||||
|
cleq r0, r0, tmpLoadWord01
|
||||||
|
xor r1, r1
|
||||||
|
or r1, r2
|
||||||
|
breq r0, r0, pushWord
|
||||||
|
|
||||||
; ==================================================================
|
; ==================================================================
|
||||||
; Low-level functions
|
; Low-level functions
|
||||||
; ==================================================================
|
; ==================================================================
|
||||||
|
@ -308,12 +443,21 @@ tmp2LoadWord01:
|
||||||
; out:
|
; out:
|
||||||
; r0:r1 = word
|
; r0:r1 = word
|
||||||
; clobbers:
|
; clobbers:
|
||||||
; r2, r2
|
; r2, r3
|
||||||
peekWord:
|
peekWord:
|
||||||
cleq r0, r0, popWord
|
cleq r0, r0, popWord
|
||||||
store peekWordHigh, r0
|
store peekWordHigh, r0
|
||||||
store peekWordLow, r1
|
store peekWordLow, r1
|
||||||
cleq r0, r0, pushWord
|
|
||||||
|
; Return SP back to where it was
|
||||||
|
load r0, SP+0
|
||||||
|
load r1, SP+1
|
||||||
|
xor r2, r2
|
||||||
|
load r3, lit02
|
||||||
|
cleq r0, r0, addWord
|
||||||
|
store SP+0, r0
|
||||||
|
store SP+1, r1
|
||||||
|
|
||||||
load r0, peekWordHigh
|
load r0, peekWordHigh
|
||||||
load r1, peekWordLow
|
load r1, peekWordLow
|
||||||
ret
|
ret
|
||||||
|
@ -375,6 +519,13 @@ pushByte:
|
||||||
popByte:
|
popByte:
|
||||||
load r0, SP+0
|
load r0, SP+0
|
||||||
load r1, SP+1
|
load r1, SP+1
|
||||||
|
|
||||||
|
load r2, SPStart+0
|
||||||
|
load r3, SPStart+1
|
||||||
|
brneq r0, r2, popByteNoUnderflow
|
||||||
|
breq r1, r3, error
|
||||||
|
|
||||||
|
popByteNoUnderflow:
|
||||||
cleq r0, r0, decWord
|
cleq r0, r0, decWord
|
||||||
store SP+0, r0
|
store SP+0, r0
|
||||||
store SP+1, r1
|
store SP+1, r1
|
||||||
|
@ -942,12 +1093,19 @@ lit6f: data 6f
|
||||||
litcharr:
|
litcharr:
|
||||||
lit72: data 72
|
lit72: data 72
|
||||||
|
|
||||||
|
litcharPipe:
|
||||||
|
lit7c: data 7c
|
||||||
|
|
||||||
litff: data ff
|
litff: data ff
|
||||||
|
|
||||||
; ==================================================================
|
; ==================================================================
|
||||||
; Data
|
; Data
|
||||||
; ==================================================================
|
; ==================================================================
|
||||||
|
|
||||||
|
linelen:
|
||||||
|
data 0
|
||||||
|
data 0
|
||||||
|
|
||||||
linebufStart: addr end
|
linebufStart: addr end
|
||||||
linebufSize:
|
linebufSize:
|
||||||
data 00
|
data 00
|
||||||
|
|
|
@ -1,32 +1,32 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
Opcode = namedtuple('Opcode', ('mnemonic', 'rx', 'ry', 'addr'))
|
Opcode = namedtuple('Opcode', ('mnemonic', 'rx', 'ry', 'addr', 'immediate'))
|
||||||
|
|
||||||
opcodes = [
|
opcodes = [
|
||||||
Opcode('halt', rx=False, ry=False, addr=False),
|
Opcode('halt', rx=False, ry=False, addr=False, immediate=False),
|
||||||
Opcode('ret', rx=False, ry=False, addr=False),
|
Opcode('ret', rx=False, ry=False, addr=False, immediate=False),
|
||||||
|
|
||||||
Opcode('shl', rx=True, ry=False, addr=False),
|
Opcode('shl', rx=True, ry=False, addr=False, immediate=False),
|
||||||
Opcode('shr', rx=True, ry=False, addr=False),
|
Opcode('shr', rx=True, ry=False, addr=False, immediate=False),
|
||||||
Opcode('rol', rx=True, ry=False, addr=False),
|
Opcode('rol', rx=True, ry=False, addr=False, immediate=False),
|
||||||
Opcode('ror', rx=True, ry=False, addr=False),
|
Opcode('ror', rx=True, ry=False, addr=False, immediate=False),
|
||||||
|
|
||||||
Opcode('nand', rx=True, ry=True, addr=False),
|
Opcode('nand', rx=True, ry=True, addr=False, immediate=False),
|
||||||
Opcode('and', rx=True, ry=True, addr=False),
|
Opcode('and', rx=True, ry=True, addr=False, immediate=False),
|
||||||
Opcode('or', rx=True, ry=True, addr=False),
|
Opcode('or', rx=True, ry=True, addr=False, immediate=False),
|
||||||
Opcode('xor', rx=True, ry=True, addr=False),
|
Opcode('xor', rx=True, ry=True, addr=False, immediate=False),
|
||||||
|
|
||||||
Opcode('load', rx=True, ry=False, addr=True),
|
Opcode('load', rx=True, ry=False, addr=True, immediate=True),
|
||||||
Opcode('store', rx=True, ry=False, addr=True),
|
Opcode('store', rx=False, ry=True, addr=True, immediate=False),
|
||||||
|
|
||||||
Opcode('breq', rx=True, ry=True, addr=True),
|
Opcode('breq', rx=True, ry=True, addr=True, immediate=False),
|
||||||
Opcode('brneq', rx=True, ry=True, addr=True),
|
Opcode('brneq', rx=True, ry=True, addr=True, immediate=False),
|
||||||
Opcode('cleq', rx=True, ry=True, addr=True),
|
Opcode('cleq', rx=True, ry=True, addr=True, immediate=False),
|
||||||
Opcode('clneq', rx=True, ry=True, addr=True),
|
Opcode('clneq', rx=True, ry=True, addr=True, immediate=False),
|
||||||
]
|
]
|
||||||
|
|
||||||
Instruction = namedtuple('Instruction', ['opcode', 'rx', 'ry', 'addr'])
|
Instruction = namedtuple('Instruction', ['opcode', 'rx', 'ry', 'addr', 'immediate'])
|
||||||
Data = namedtuple('Data', ['byte'])
|
Data = namedtuple('Data', ['byte'])
|
||||||
|
|
||||||
Statement = namedtuple('Statement', ['addr', 'raw', 'contents'])
|
Statement = namedtuple('Statement', ['addr', 'raw', 'contents'])
|
||||||
|
@ -42,24 +42,32 @@ def segment(binary, origin):
|
||||||
rx = (byte >> 2) & 3
|
rx = (byte >> 2) & 3
|
||||||
ry = byte & 3
|
ry = byte & 3
|
||||||
|
|
||||||
|
immediate = opcodes[opcode].immediate and ry == 3
|
||||||
|
|
||||||
valid = True
|
valid = True
|
||||||
if not opcodes[opcode].rx and rx != 0: valid = False
|
if not opcodes[opcode].rx and rx != 0: valid = False
|
||||||
if not opcodes[opcode].ry and ry != 0: valid = False
|
if not opcodes[opcode].ry and not immediate and ry != 0: valid = False
|
||||||
if opcodes[opcode].addr and ip + 2 >= len(binary): valid = False
|
if opcodes[opcode].addr and not immediate and ip + 2 >= len(binary): valid = False
|
||||||
|
if immediate and ip + 1 >= len(binary): valid = False
|
||||||
|
|
||||||
if not valid:
|
if not valid:
|
||||||
raw = binary[ip:ip + 1]
|
raw = binary[ip:ip + 1]
|
||||||
statements.append(Statement(ip, raw, Data(byte)))
|
statements.append(Statement(ip, raw, Data(byte)))
|
||||||
ip += 1
|
ip += 1
|
||||||
|
elif immediate:
|
||||||
|
raw = binary[ip:ip + 2]
|
||||||
|
instruction = Instruction(opcode, rx, ry, None, binary[ip + 1])
|
||||||
|
statements.append(Statement(ip, raw, instruction))
|
||||||
|
ip += 2
|
||||||
elif opcodes[opcode].addr:
|
elif opcodes[opcode].addr:
|
||||||
raw = binary[ip:ip + 3]
|
raw = binary[ip:ip + 3]
|
||||||
addr = (binary[ip + 1] << 8) + binary[ip + 2]
|
addr = (binary[ip + 1] << 8) + binary[ip + 2]
|
||||||
instruction = Instruction(opcode, rx, ry, addr)
|
instruction = Instruction(opcode, rx, ry, addr, None)
|
||||||
statements.append(Statement(ip, raw, instruction))
|
statements.append(Statement(ip, raw, instruction))
|
||||||
ip += 3
|
ip += 3
|
||||||
else:
|
else:
|
||||||
raw = binary[ip:ip + 1]
|
raw = binary[ip:ip + 1]
|
||||||
instruction = Instruction(opcode, rx, ry, None)
|
instruction = Instruction(opcode, rx, ry, None, None)
|
||||||
statements.append(Statement(ip, raw, instruction))
|
statements.append(Statement(ip, raw, instruction))
|
||||||
ip += 1
|
ip += 1
|
||||||
|
|
||||||
|
@ -68,7 +76,7 @@ def segment(binary, origin):
|
||||||
def disasm(binary, origin = 0):
|
def disasm(binary, origin = 0):
|
||||||
for addr, raw, contents in segment(binary, origin):
|
for addr, raw, contents in segment(binary, origin):
|
||||||
if type(contents) == Data:
|
if type(contents) == Data:
|
||||||
statement = f'db 0x{contents.byte:02x}'
|
statement = f'data {contents.byte:02x}'
|
||||||
else:
|
else:
|
||||||
mnemonic = opcodes[contents.opcode].mnemonic
|
mnemonic = opcodes[contents.opcode].mnemonic
|
||||||
fields = []
|
fields = []
|
||||||
|
@ -76,8 +84,10 @@ def disasm(binary, origin = 0):
|
||||||
fields.append(f'r{contents.rx}')
|
fields.append(f'r{contents.rx}')
|
||||||
if opcodes[contents.opcode].ry:
|
if opcodes[contents.opcode].ry:
|
||||||
fields.append(f'r{contents.ry}')
|
fields.append(f'r{contents.ry}')
|
||||||
if opcodes[contents.opcode].addr:
|
if contents.immediate is not None:
|
||||||
fields.append(f'0x{contents.addr:04x}')
|
fields.append(f'#{contents.immediate:02x}')
|
||||||
|
elif opcodes[contents.opcode].addr:
|
||||||
|
fields.append(f'{contents.addr:04x}')
|
||||||
|
|
||||||
if mnemonic == 'store':
|
if mnemonic == 'store':
|
||||||
fields = ', '.join(reversed(fields))
|
fields = ', '.join(reversed(fields))
|
||||||
|
|
Loading…
Reference in New Issue