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
|
||||
|
||||
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
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue