Compare commits

...

7 Commits

2 changed files with 227 additions and 59 deletions

View File

@ -1,64 +1,145 @@
org 0
start:
cleq r0, r0, stReadline
cleq r0, r0, dumpstack
cleq r0, r0, readline
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 r1, SPStart+1
store dumpstackPtr+0, r0
store dumpstackPtr+1, r1
store debugPtr+0, r0
store debugPtr+1, r1
dumpstackLoop:
load r0, dumpstackPtr+0
load r1, dumpstackPtr+1
debugLoop:
load r0, debugPtr+0
load r1, debugPtr+1
load r2, SP+0
load r3, SP+1
brneq r0, r2, dumpstackDumpword
breq r1, r3, dumpstackEnd
brneq r0, r2, debugDumpword
breq r1, r3, debugEnd
dumpstackDumpword:
load r0, dumpstackPtr+0
load r1, dumpstackPtr+1
debugDumpword:
load r0, debugPtr+0
load r1, debugPtr+1
store loadByteHigh, r0
store loadByteLow, r1
cleq r0, r0, loadByte
cleq r0, r0, writehexByte
load r0, dumpstackPtr+0
load r1, dumpstackPtr+1
load r0, debugPtr+0
load r1, debugPtr+1
cleq r0, r0, incWord
store dumpstackPtr+0, r0
store dumpstackPtr+1, r1
store debugPtr+0, r0
store debugPtr+1, r1
load r0, dumpstackPtr+0
load r1, dumpstackPtr+1
load r0, debugPtr+0
load r1, debugPtr+1
store loadByteHigh, r0
store loadByteLow, r1
cleq r0, r0, loadByte
cleq r0, r0, writehexByte
load r0, dumpstackPtr+0
load r1, dumpstackPtr+1
load r0, debugPtr+0
load r1, debugPtr+1
cleq r0, r0, incWord
store dumpstackPtr+0, r0
store dumpstackPtr+1, r1
store debugPtr+0, r0
store debugPtr+1, r1
load r0, litcharSpace
store ffff, r0
breq r0, r0, dumpstackLoop
breq r0, r0, debugLoop
dumpstackEnd:
breq r0, r0, newline
debugEnd:
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
xor r0, r0
xor r1, r1
@ -101,8 +182,13 @@ stReadline:
breq r0, r0, readlineLoop
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
store linelen+0, r0
store linelen+1, r1
breq r0, r0, newline
readlineBackspace:
@ -119,6 +205,7 @@ stReadline:
brneq r0, r1, readlineLoop
; Decrease the index and erase the echoed character
; TODO: utf-8
cleq r0, r0, stDec
load r3, litcharSpace
store ffff, r3
@ -129,6 +216,7 @@ stReadline:
readlineBufFull:
; Drop the input byte and erase the echoed character
; TODO: utf-8
cleq r0, r0, popWord
load r3, litcharBS
store ffff, r3
@ -247,7 +335,7 @@ stSwap:
; Memory
; ------------------------------------------------------------------
; a p --
; b ptr --
stStoreByte:
cleq r0, r0, popWord
store storeByteHigh, r0
@ -257,6 +345,53 @@ stStoreByte:
or r0, r1
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
; ==================================================================
@ -308,12 +443,21 @@ tmp2LoadWord01:
; out:
; r0:r1 = word
; clobbers:
; r2, r2
; r2, r3
peekWord:
cleq r0, r0, popWord
store peekWordHigh, r0
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 r1, peekWordLow
ret
@ -375,6 +519,13 @@ pushByte:
popByte:
load r0, SP+0
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
store SP+0, r0
store SP+1, r1
@ -942,12 +1093,19 @@ lit6f: data 6f
litcharr:
lit72: data 72
litcharPipe:
lit7c: data 7c
litff: data ff
; ==================================================================
; Data
; ==================================================================
linelen:
data 0
data 0
linebufStart: addr end
linebufSize:
data 00

View File

@ -1,32 +1,32 @@
#!/usr/bin/env python
from collections import namedtuple
Opcode = namedtuple('Opcode', ('mnemonic', 'rx', 'ry', 'addr'))
Opcode = namedtuple('Opcode', ('mnemonic', 'rx', 'ry', 'addr', 'immediate'))
opcodes = [
Opcode('halt', rx=False, ry=False, addr=False),
Opcode('ret', rx=False, ry=False, addr=False),
Opcode('halt', rx=False, ry=False, addr=False, immediate=False),
Opcode('ret', rx=False, ry=False, addr=False, immediate=False),
Opcode('shl', rx=True, ry=False, addr=False),
Opcode('shr', rx=True, ry=False, addr=False),
Opcode('rol', rx=True, ry=False, addr=False),
Opcode('ror', rx=True, ry=False, addr=False),
Opcode('shl', rx=True, ry=False, addr=False, immediate=False),
Opcode('shr', rx=True, ry=False, addr=False, immediate=False),
Opcode('rol', rx=True, ry=False, addr=False, immediate=False),
Opcode('ror', rx=True, ry=False, addr=False, immediate=False),
Opcode('nand', rx=True, ry=True, addr=False),
Opcode('and', rx=True, ry=True, addr=False),
Opcode('or', rx=True, ry=True, addr=False),
Opcode('xor', rx=True, ry=True, addr=False),
Opcode('nand', rx=True, ry=True, addr=False, immediate=False),
Opcode('and', rx=True, ry=True, addr=False, immediate=False),
Opcode('or', rx=True, ry=True, addr=False, immediate=False),
Opcode('xor', rx=True, ry=True, addr=False, immediate=False),
Opcode('load', rx=True, ry=False, addr=True),
Opcode('store', rx=True, ry=False, addr=True),
Opcode('load', rx=True, ry=False, addr=True, immediate=True),
Opcode('store', rx=False, ry=True, addr=True, immediate=False),
Opcode('breq', rx=True, ry=True, addr=True),
Opcode('brneq', rx=True, ry=True, addr=True),
Opcode('cleq', rx=True, ry=True, addr=True),
Opcode('clneq', rx=True, ry=True, addr=True),
Opcode('breq', rx=True, ry=True, addr=True, immediate=False),
Opcode('brneq', rx=True, ry=True, addr=True, immediate=False),
Opcode('cleq', rx=True, ry=True, addr=True, immediate=False),
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'])
Statement = namedtuple('Statement', ['addr', 'raw', 'contents'])
@ -42,24 +42,32 @@ def segment(binary, origin):
rx = (byte >> 2) & 3
ry = byte & 3
immediate = opcodes[opcode].immediate and ry == 3
valid = True
if not opcodes[opcode].rx and rx != 0: valid = False
if not opcodes[opcode].ry and ry != 0: valid = False
if opcodes[opcode].addr and ip + 2 >= len(binary): valid = False
if not opcodes[opcode].ry and not immediate and ry != 0: 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:
raw = binary[ip:ip + 1]
statements.append(Statement(ip, raw, Data(byte)))
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:
raw = binary[ip:ip + 3]
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))
ip += 3
else:
raw = binary[ip:ip + 1]
instruction = Instruction(opcode, rx, ry, None)
instruction = Instruction(opcode, rx, ry, None, None)
statements.append(Statement(ip, raw, instruction))
ip += 1
@ -68,7 +76,7 @@ def segment(binary, origin):
def disasm(binary, origin = 0):
for addr, raw, contents in segment(binary, origin):
if type(contents) == Data:
statement = f'db 0x{contents.byte:02x}'
statement = f'data {contents.byte:02x}'
else:
mnemonic = opcodes[contents.opcode].mnemonic
fields = []
@ -76,8 +84,10 @@ def disasm(binary, origin = 0):
fields.append(f'r{contents.rx}')
if opcodes[contents.opcode].ry:
fields.append(f'r{contents.ry}')
if opcodes[contents.opcode].addr:
fields.append(f'0x{contents.addr:04x}')
if contents.immediate is not None:
fields.append(f'#{contents.immediate:02x}')
elif opcodes[contents.opcode].addr:
fields.append(f'{contents.addr:04x}')
if mnemonic == 'store':
fields = ', '.join(reversed(fields))