Created
April 23, 2019 05:40
-
-
Save mmcloughlin/acf1c367dc6f9c36e10b9585a71ee152 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# Opcode values. | |
# | |
HALT = 0 | |
LOAD = 1 | |
STORE = 2 | |
ADDC = 3 | |
MVAC = 4 | |
JEQ = 5 | |
JLT = 6 | |
JMP = 7 | |
ADD = 8 | |
SUB = 9 | |
DEC = 10 | |
LA = 11 | |
LIA = 12 | |
SIA = 13 | |
MVAA = 14 | |
# | |
# Opcode name map. | |
# | |
opcode_name = [ | |
'HALT', | |
'LOAD', | |
'STORE', | |
'ADDC', | |
'MVAC', | |
'JEQ', | |
'JLT', | |
'JMP', | |
'ADD', | |
'SUB', | |
'DEC', | |
'LA', | |
'LIA', | |
'SIA', | |
'MVAA', | |
] | |
class Label: | |
def __init__(self, addr): | |
self.addr = addr | |
def resolve(self, prog): | |
return self.addr | |
def describe(self): | |
return str(self.addr) | |
class Instruction: | |
""" | |
An instruction. | |
""" | |
def __init__(self, opcode, addr=None): | |
self.opcode = opcode | |
self.addr = addr | |
def encode(self, prog): | |
code = self.opcode << 12 | |
if self.addr: | |
code |= self.addr.resolve(prog) | |
return code | |
def describe(self): | |
s = opcode_name[self.opcode] | |
if self.addr: | |
s += '\t' + self.addr.describe() | |
return s | |
class Data: | |
def __init__(self, name, val, offset): | |
self.name = name | |
self.val = val | |
self.offset = offset | |
def resolve(self, prog): | |
return self.offset + prog.data_offset() | |
def describe(self): | |
return self.name | |
class Program: | |
def __init__(self): | |
self.instructions = [] | |
self.data_section = [] | |
def label(self): | |
return Label(len(self.instructions)) | |
def add_instruction(self, instruction): | |
lbl = self.label() | |
self.instructions.append(instruction) | |
return lbl | |
def add_instructions(self, *args): | |
for arg in args: | |
self.add_instruction(Instruction(*arg)) | |
def add_data(self, name, val): | |
item = Data(name, val, len(self.data_section)) | |
self.data_section.append(item) | |
return item | |
def data_offset(self): | |
return len(self.instructions) | |
def output(self): | |
for instruction in self.instructions: | |
print('0x{encoding:04x}\t# {description}'.format( | |
encoding=instruction.encode(self), | |
description=instruction.describe(), | |
)) | |
if len(self.data_section) == 0: | |
return | |
print('#') | |
print('# Data Section.') | |
print('#') | |
for data in self.data_section: | |
print('0x{val:04x}\t# {name}'.format( | |
val=data.val, | |
name=data.name, | |
)) | |
def main(): | |
p = Program() | |
N = p.add_data('N', 6) | |
p.add_instruction(Instruction(LOAD, N)) | |
p.add_instruction(Instruction(LOAD, N)) | |
p.add_instruction(Instruction(LOAD, N)) | |
p.add_instruction(Instruction(LOAD, N)) | |
p.add_instruction(Instruction(LOAD, N)) | |
p.add_instruction(Instruction(LOAD, N)) | |
p.add_instruction(Instruction(LOAD, N)) | |
p.add_instruction(Instruction(LOAD, N)) | |
p.add_instruction(Instruction(LOAD, N)) | |
loopstart = p.label() | |
p.add_instruction(Instruction(LOAD, N)) | |
p.add_instruction(Instruction(LOAD, N)) | |
p.add_instruction(Instruction(JMP, loopstart)) | |
p.add_instruction(Instruction(HALT)) | |
p.output() | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment