Compare commits
No commits in common. "2ad8720cd757432001227ebd70359aa064a6f9eb" and "b2b148f7cea5248c9adf890a1e626551c6ef4707" have entirely different histories.
2ad8720cd7
...
b2b148f7ce
1 changed files with 0 additions and 155 deletions
155
zasm.py
155
zasm.py
|
@ -1,155 +0,0 @@
|
||||||
class Things:
|
|
||||||
opcodes = {
|
|
||||||
'nop': 0x00,
|
|
||||||
'hlt': 0x01,
|
|
||||||
'ld': 0x04,
|
|
||||||
'push': 0x05,
|
|
||||||
'pop': 0x06,
|
|
||||||
'jmp': 0x07,
|
|
||||||
'jz': 0x08,
|
|
||||||
'cmp': 0x09,
|
|
||||||
'inc': 0x0A,
|
|
||||||
'dec': 0x0B,
|
|
||||||
'addi': 0x0C,
|
|
||||||
'subi': 0x0D,
|
|
||||||
'add': 0x0E,
|
|
||||||
'sub': 0x0F,
|
|
||||||
'muli': 0x10,
|
|
||||||
'divi': 0x11,
|
|
||||||
'mul': 0x12,
|
|
||||||
'div': 0x13,
|
|
||||||
'test': 0x16,
|
|
||||||
'prt': 0x17,
|
|
||||||
|
|
||||||
'je': 0x08,
|
|
||||||
}
|
|
||||||
|
|
||||||
registers = {
|
|
||||||
'ip': 0x00,
|
|
||||||
'sp': 0x01,
|
|
||||||
'flags': 0x03,
|
|
||||||
'a': 0x04,
|
|
||||||
'b': 0x05,
|
|
||||||
'c': 0x06,
|
|
||||||
'd': 0x07,
|
|
||||||
'r8': 0x08,
|
|
||||||
'r9': 0x09,
|
|
||||||
'r10': 0x0A,
|
|
||||||
'r11': 0x0B,
|
|
||||||
'r12': 0x0C,
|
|
||||||
'r13': 0x0D,
|
|
||||||
'r14': 0x0E,
|
|
||||||
'r15': 0x0F,
|
|
||||||
'r16': 0x10,
|
|
||||||
}
|
|
||||||
|
|
||||||
class ZASM:
|
|
||||||
def __init__(self):
|
|
||||||
self._out = []
|
|
||||||
self._pc = 0
|
|
||||||
self._org = 0
|
|
||||||
self._labels = {}
|
|
||||||
self._to_be_resolved = {}
|
|
||||||
|
|
||||||
def emit8(self, value):
|
|
||||||
self._out.append(value & 0xFF)
|
|
||||||
self._pc += 1
|
|
||||||
|
|
||||||
def emit16(self, value):
|
|
||||||
self._out.append((value & 0xFF00) >> 8)
|
|
||||||
self._out.append(value & 0xFF)
|
|
||||||
self._pc += 2
|
|
||||||
|
|
||||||
def set8(self, addr, value):
|
|
||||||
self._out[addr - self._org] = bytes([value & 0xFF])
|
|
||||||
|
|
||||||
def set16(self, addr, value):
|
|
||||||
print(self._out)
|
|
||||||
self._out[addr - self._org] = (value & 0xFF00) >> 8
|
|
||||||
self._out[addr - self._org + 1] = value & 0xFF
|
|
||||||
|
|
||||||
def assemble(self, path):
|
|
||||||
with open(path, 'r') as f:
|
|
||||||
lines = f.readlines()
|
|
||||||
|
|
||||||
line_no = 0
|
|
||||||
for line in lines:
|
|
||||||
# Strip away bullshit
|
|
||||||
line = line.replace(',', '')
|
|
||||||
line = line.replace('\n', '')
|
|
||||||
|
|
||||||
# Increment line number
|
|
||||||
line_no += 1
|
|
||||||
|
|
||||||
# Ignore blank lines and comments
|
|
||||||
if line == '':
|
|
||||||
continue
|
|
||||||
if line.startswith('#'):
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Is it a label?
|
|
||||||
if not line.startswith(' '):
|
|
||||||
if line.startswith('org'):
|
|
||||||
self._pc = int(line.split(' ')[1], 16)
|
|
||||||
self._org = self._pc
|
|
||||||
else:
|
|
||||||
self._labels[line.split(':')[0]] = self._pc
|
|
||||||
# It is code
|
|
||||||
else:
|
|
||||||
line = line[4:]
|
|
||||||
chunks = line.split(' ')
|
|
||||||
if chunks[0] in Things.opcodes:
|
|
||||||
self.emit8(Things.opcodes[chunks[0]])
|
|
||||||
else:
|
|
||||||
print(f'Unknown opcode: {chunks[0]} at {line_no}: {line}')
|
|
||||||
break
|
|
||||||
|
|
||||||
# SUUUUPER dirty hack to do indirect addressing
|
|
||||||
#if chunks[1].startswith('[') and chunks[1].endswith(']'):
|
|
||||||
# self.set8(self._pc - 1, Things.opcodes[chunks[0]] - 2)
|
|
||||||
# chunk[1] = chunk[1][1:-1]
|
|
||||||
if len(chunks) == 1:
|
|
||||||
self.emit16(0)
|
|
||||||
elif chunks[1].startswith('#'):
|
|
||||||
self.emit16(int(chunks[1][1:]))
|
|
||||||
elif chunks[1] in Things.registers:
|
|
||||||
self.emit16(Things.registers[chunks[1]])
|
|
||||||
else:
|
|
||||||
self._to_be_resolved[self._pc] = (chunks[1], line_no, line)
|
|
||||||
self.emit16(0xDADA)
|
|
||||||
# print(f'Unknown register or invalid immediate: {chunks[1]!r}')
|
|
||||||
# break
|
|
||||||
|
|
||||||
# SUUUUPER dirty hack to do indirect addressing
|
|
||||||
#if chunks[2].startswith('[') and chunks[2].endswith(']'):
|
|
||||||
# self.set8(self._pc - 2, Things.opcodes[chunks[0]] - 2)
|
|
||||||
# chunk[2] = chunk[2][1:-1]
|
|
||||||
if len(chunks) <= 2:
|
|
||||||
self.emit8(0)
|
|
||||||
elif chunks[2] in Things.registers:
|
|
||||||
self.emit8(Things.registers[chunks[2]])
|
|
||||||
elif chunks[2].startswith('#'):
|
|
||||||
self.emit8(int(chunks[2][1:]))
|
|
||||||
else:
|
|
||||||
print(f'Invalid immediate: {chunks[2]} at {line_no}: {line}')
|
|
||||||
break
|
|
||||||
|
|
||||||
for loc, (label, line_no, line) in self._to_be_resolved.items():
|
|
||||||
print(loc, label, line_no, line)
|
|
||||||
print(self._labels)
|
|
||||||
if label in self._labels.keys():
|
|
||||||
self.set16(loc, self._labels[label])
|
|
||||||
else:
|
|
||||||
print(f'Failed to resolve {label} at {line_no}: {line}')
|
|
||||||
break
|
|
||||||
|
|
||||||
def write(self, path):
|
|
||||||
with open(path, 'wb') as f:
|
|
||||||
f.write(bytes(self._out))
|
|
||||||
self._out = b''
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
asm = ZASM()
|
|
||||||
|
|
||||||
asm.assemble('test.zasm')
|
|
||||||
asm.write('test.bin')
|
|
Loading…
Reference in a new issue