Skip to content

Instantly share code, notes, and snippets.

@RossComputerGuy
Created February 18, 2021 07:49
Show Gist options
  • Save RossComputerGuy/3cbb6837a67d2a748f0ccf1346b7ac40 to your computer and use it in GitHub Desktop.
Save RossComputerGuy/3cbb6837a67d2a748f0ccf1346b7ac40 to your computer and use it in GitHub Desktop.
Simple Emulator
REG_NAMES = [
'ADDR',
]
INSTRS = {
'nop': ( 0, False ),
'set': ( 1, True ),
'mmove': ( 2, True ),
'rmove': ( 3, True ),
'rmm': ( 4, True ),
'mmr': ( 5, True ),
'add': ( 6, True ),
'sub': ( 7, True ),
'mul': ( 8, True ),
'div': ( 9, True ),
'print': ( 10, True ),
'mrun': ( 11, True )
}
class CPU:
def __init__(self):
self.mem = bytearray([0] * 1024)
self.regs = bytearray([0] * 16)
self.pc = 0
self.running = False
self.mrun = False
def write_reg(self, regname, value):
if regname in REG_NAMES:
self.regs[REG_NAMES.index(regname)] = value
else:
raise RuntimeError('Unknown register name: {}'.format(regname))
def read_reg(self, regname):
if regname in REG_NAMES:
return self.regs[REG_NAMES.index(regname)]
else:
raise RuntimeError('Unknown register name: {}'.format(regname))
def fetch(self):
if self.mrun == False:
str_instr = input('Instruction: ').lower().split(' ')
instr = { 'op': 0, 'val': 0 }
for key, value in INSTRS.items():
if str_instr[0] == key:
instr['op'] = value[0]
if value[1] == True:
instr['val'] = int(str_instr[1])
return instr
instr['op'] = int(str_instr[0])
instr['val'] = int(str_instr[1])
else:
return { 'op': (self.mem[self.pc] << 8) | self.mem[self.pc + 1], 'val': (self.mem[self.pc + 2] << 8) | self.mem[self.pc + 3] }
def execute(self, instr):
if instr['op'] == 0x0:
self.running = False
elif instr['op'] == 1:
# Set address
self.write_reg('ADDR', instr['val'])
elif instr['op'] == 2:
# Move data to memory
self.mem[self.read_reg('ADDR')] = instr['val']
elif instr['op'] == 3:
# Move data to register
self.regs[self.read_reg('ADDR')] = instr['val']
elif instr['op'] == 4:
# Move register to memory
self.mem[self.read_reg('ADDR')] = self.regs[instr['val']]
elif instr['op'] == 5:
# Move memory to register
self.regs[instr.val] = self.mem[self.read_reg('ADDR')]
elif instr['op'] == 6:
# Add value in register
self.regs[self.read_reg('ADDR')] += instr['val']
elif instr['op'] == 7:
# Subtract value in register
self.regs[self.read_reg('ADDR')] -= instr['val']
elif instr['op'] == 8:
# Multiply value in register
self.regs[self.read_reg('ADDR')] *= instr['val']
elif instr['op'] == 9:
# Divide value in register
self.regs[self.read_reg('ADDR')] /= instr['val']
elif instr['op'] == 10:
# Prints a register
val = self.regs[self.read_reg('ADDR')]
if instr['val'] == 0:
print(chr(val))
elif instr['val'] == 1:
print(val)
else:
raise RuntimeError('Unknown print type: {}'.format(instr['val']))
elif instr['op'] == 11:
# Toggles the "memory run" flag
self.mrun = instr['val'] == 1
else:
raise RuntimeError('Unknown opcode: {}'.format(instr['op']))
if self.mrun == True:
self.pc += 4
def cycle(self):
self.execute(self.fetch())
def main():
cpu = CPU()
cpu.running = True
while cpu.running:
try:
cpu.cycle()
except ZeroDivisionError:
print('Error: Division by zero')
except ValueError:
print('Error: value is too big')
except RuntimeError:
print('Error: something is wrong with your code')
except TypeError:
print('Error: wrong type')
except KeyboardInterrupt:
cpu.running = False
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment