Updated emulator to reflect ISA changes
This commit is contained in:
parent
c17585e356
commit
6aff466f4e
103
emulator/main.py
103
emulator/main.py
|
@ -1,7 +1,7 @@
|
||||||
# Kyler Olsen
|
# Kyler Olsen
|
||||||
# Feb 2024
|
# Feb 2024
|
||||||
|
|
||||||
MAX_INT = 4089
|
MAX_INT = 0x1000
|
||||||
|
|
||||||
|
|
||||||
class Memory:
|
class Memory:
|
||||||
|
@ -94,12 +94,9 @@ class Computer:
|
||||||
self,
|
self,
|
||||||
index: int,
|
index: int,
|
||||||
*,
|
*,
|
||||||
top: bool = False,
|
strict: bool = True,
|
||||||
strict: bool = False,
|
|
||||||
) -> int:
|
) -> int:
|
||||||
if strict and not (0 <= index <= 7): raise IndexError
|
if strict and not (0 <= index <= 7): raise IndexError
|
||||||
elif strict and top and not (0 <= index <= 3): raise IndexError
|
|
||||||
elif top and not (0 <= index <= 3): index = (index % 4) + 4
|
|
||||||
else: index %= 8
|
else: index %= 8
|
||||||
|
|
||||||
return self._get_reg(index)
|
return self._get_reg(index)
|
||||||
|
@ -119,12 +116,9 @@ class Computer:
|
||||||
index: int,
|
index: int,
|
||||||
value: int,
|
value: int,
|
||||||
*,
|
*,
|
||||||
top: bool = False,
|
strict: bool = True,
|
||||||
strict: bool = False,
|
|
||||||
):
|
):
|
||||||
if strict and not (0 <= index <= 7): raise IndexError
|
if strict and not (0 <= index <= 7): raise IndexError
|
||||||
elif strict and top and not (0 <= index <= 3): raise IndexError
|
|
||||||
elif top and not (0 <= index <= 3): index = (index % 4) + 4
|
|
||||||
else: index %= 8
|
else: index %= 8
|
||||||
|
|
||||||
value %= MAX_INT
|
value %= MAX_INT
|
||||||
|
@ -143,6 +137,44 @@ class Computer:
|
||||||
def interrupt(self, index: int):
|
def interrupt(self, index: int):
|
||||||
self._interrupt_flag.append(index % MAX_INT)
|
self._interrupt_flag.append(index % MAX_INT)
|
||||||
|
|
||||||
|
def step(self):
|
||||||
|
instruction = self._mem[self.program_counter]
|
||||||
|
|
||||||
|
if instruction == 0: self.NOP()
|
||||||
|
elif instruction == 1: self.HLT()
|
||||||
|
elif instruction == 2: self.INT()
|
||||||
|
elif instruction == 3: self.BNZ()
|
||||||
|
elif instruction & 0xFF8 == 0x10: self.GET(instruction & 0x7)
|
||||||
|
elif instruction & 0xFF8 == 0x18: self.SET(instruction & 0x7)
|
||||||
|
elif instruction & 0xFF8 == 0x20: self.LOD(instruction & 0x7)
|
||||||
|
elif instruction & 0xFF8 == 0x28: self.STR(instruction & 0x7)
|
||||||
|
elif instruction & 0xFF8 == 0x30: self.PSH(instruction & 0x7)
|
||||||
|
elif instruction & 0xFF8 == 0x38: self.POP(instruction & 0x7)
|
||||||
|
elif instruction & 0xF80 == 0x80: self.LDI(instruction & 0x7F)
|
||||||
|
elif instruction & 0xFC0 == 0x100:
|
||||||
|
self.LSH(instruction & 0x38, instruction & 0x7)
|
||||||
|
elif instruction & 0xFC0 == 0x140:
|
||||||
|
self.RSH(instruction & 0x38, instruction & 0x7)
|
||||||
|
elif instruction & 0xFC0 == 0x180:
|
||||||
|
self.INC(instruction & 0x38, instruction & 0x7)
|
||||||
|
elif instruction & 0xFC0 == 0x1C0:
|
||||||
|
self.DEC(instruction & 0x38, instruction & 0x7)
|
||||||
|
elif instruction & 0xE0 == 0x200:
|
||||||
|
self.AND(instruction & 0x1C, instruction & 0x38, instruction & 0x7)
|
||||||
|
elif instruction & 0xE0 == 0x400:
|
||||||
|
self.OR(instruction & 0x1C, instruction & 0x38, instruction & 0x7)
|
||||||
|
elif instruction & 0xE0 == 0x600:
|
||||||
|
self.NAD(instruction & 0x1C, instruction & 0x38, instruction & 0x7)
|
||||||
|
elif instruction & 0xE0 == 0x800:
|
||||||
|
self.SUB(instruction & 0x1C, instruction & 0x38, instruction & 0x7)
|
||||||
|
elif instruction & 0xE0 == 0xA00:
|
||||||
|
self.XOR(instruction & 0x1C, instruction & 0x38, instruction & 0x7)
|
||||||
|
elif instruction & 0xE0 == 0xC00:
|
||||||
|
self.NOR(instruction & 0x1C, instruction & 0x38, instruction & 0x7)
|
||||||
|
elif instruction & 0xE0 == 0xE00:
|
||||||
|
self.ADD(instruction & 0x1C, instruction & 0x38, instruction & 0x7)
|
||||||
|
else: raise LookupError()
|
||||||
|
|
||||||
# === Operations ===
|
# === Operations ===
|
||||||
|
|
||||||
def NOP(self):
|
def NOP(self):
|
||||||
|
@ -156,21 +188,25 @@ class Computer:
|
||||||
self.interrupt(self.pointer)
|
self.interrupt(self.pointer)
|
||||||
self.program_counter += 1
|
self.program_counter += 1
|
||||||
|
|
||||||
def JPZ(self):
|
def BNZ(self):
|
||||||
if self.zero_flag:
|
if self.zero_flag:
|
||||||
self.program_counter = self.pointer
|
self.program_counter = self.pointer
|
||||||
self.program_counter += 1
|
self.program_counter += 1
|
||||||
|
|
||||||
|
def GET(self, REG: int):
|
||||||
|
self.set_reg(REG, self._interrupt_map[self.pointer])
|
||||||
|
self.program_counter += 1
|
||||||
|
|
||||||
def SET(self, REG: int):
|
def SET(self, REG: int):
|
||||||
self._interrupt_map[self.pointer] = self.get_reg(REG, top=True)
|
self._interrupt_map[self.pointer] = self.get_reg(REG)
|
||||||
self.program_counter += 1
|
self.program_counter += 1
|
||||||
|
|
||||||
def LOD(self, REG: int):
|
def LOD(self, REG: int):
|
||||||
self.set_reg(REG, self._mem[self.pointer], top=True)
|
self.set_reg(REG, self._mem[self.pointer])
|
||||||
self.program_counter += 1
|
self.program_counter += 1
|
||||||
|
|
||||||
def STR(self, REG: int):
|
def STR(self, REG: int):
|
||||||
self._mem[self.pointer] = self.get_reg(REG, top=True)
|
self._mem[self.pointer] = self.get_reg(REG)
|
||||||
self.program_counter += 1
|
self.program_counter += 1
|
||||||
|
|
||||||
def PSH(self, REG: int):
|
def PSH(self, REG: int):
|
||||||
|
@ -181,11 +217,15 @@ class Computer:
|
||||||
self._mem[self.stack_pointer] = self.get_reg(REG)
|
self._mem[self.stack_pointer] = self.get_reg(REG)
|
||||||
self.program_counter += 1
|
self.program_counter += 1
|
||||||
|
|
||||||
|
def LDI(self, Immediate: int):
|
||||||
|
self.pointer = Immediate % 0x3F
|
||||||
|
self.program_counter += 1
|
||||||
|
|
||||||
def LSH(self, REG_D: int, REG_A: int):
|
def LSH(self, REG_D: int, REG_A: int):
|
||||||
result = self.get_reg(REG_A) << 1
|
result = self.get_reg(REG_A) << 1
|
||||||
result %= MAX_INT
|
result %= MAX_INT
|
||||||
self._zero_flag = result == 0
|
self._zero_flag = result == 0
|
||||||
self.set_reg(REG_D, result, top=True)
|
self.set_reg(REG_D, result)
|
||||||
self.program_counter += 1
|
self.program_counter += 1
|
||||||
|
|
||||||
def RSH(self, REG_D: int, REG_A: int):
|
def RSH(self, REG_D: int, REG_A: int):
|
||||||
|
@ -210,28 +250,42 @@ class Computer:
|
||||||
self.program_counter += 1
|
self.program_counter += 1
|
||||||
|
|
||||||
def AND(self, REG_D: int, REG_A: int, REG_B: int):
|
def AND(self, REG_D: int, REG_A: int, REG_B: int):
|
||||||
result = self.get_reg(REG_A) & self.get_reg(REG_B, top=True)
|
result = self.get_reg(REG_A) & self.get_reg(REG_B)
|
||||||
result %= MAX_INT
|
result %= MAX_INT
|
||||||
self._zero_flag = result == 0
|
self._zero_flag = result == 0
|
||||||
self.set_reg(REG_D, result, top=True)
|
self.set_reg(REG_D, result)
|
||||||
self.program_counter += 1
|
self.program_counter += 1
|
||||||
|
|
||||||
def XOR(self, REG_D: int, REG_A: int, REG_B: int):
|
def OR(self, REG_D: int, REG_A: int, REG_B: int):
|
||||||
result = self.get_reg(REG_A) ^ self.get_reg(REG_B, top=True)
|
result = self.get_reg(REG_A) | self.get_reg(REG_B)
|
||||||
result %= MAX_INT
|
result %= MAX_INT
|
||||||
self._zero_flag = result == 0
|
self._zero_flag = result == 0
|
||||||
self.set_reg(REG_D, result, top=True)
|
self.set_reg(REG_D, result)
|
||||||
self.program_counter += 1
|
self.program_counter += 1
|
||||||
|
|
||||||
def NOR(self, REG_D: int, REG_A: int, REG_B: int):
|
def NAD(self, REG_D: int, REG_A: int, REG_B: int):
|
||||||
result = MAX_INT ^ (self.get_reg(REG_A) | self.get_reg(REG_B))
|
result = (MAX_INT - 1) ^ (self.get_reg(REG_A) & self.get_reg(REG_B))
|
||||||
result %= MAX_INT
|
result %= MAX_INT
|
||||||
self._zero_flag = result == 0
|
self._zero_flag = result == 0
|
||||||
self.set_reg(REG_D, result)
|
self.set_reg(REG_D, result)
|
||||||
self.program_counter += 1
|
self.program_counter += 1
|
||||||
|
|
||||||
def SUB(self, REG_D: int, REG_A: int, REG_B: int):
|
def SUB(self, REG_D: int, REG_A: int, REG_B: int):
|
||||||
result = self.get_reg(REG_A) - self.get_reg(REG_B)
|
result = self.get_reg(REG_A) + ((MAX_INT - 1) ^ self.get_reg(REG_B)) + 1
|
||||||
|
result %= MAX_INT
|
||||||
|
self._zero_flag = result == 0
|
||||||
|
self.set_reg(REG_D, result)
|
||||||
|
self.program_counter += 1
|
||||||
|
|
||||||
|
def XOR(self, REG_D: int, REG_A: int, REG_B: int):
|
||||||
|
result = self.get_reg(REG_A) ^ self.get_reg(REG_B)
|
||||||
|
result %= MAX_INT
|
||||||
|
self._zero_flag = result == 0
|
||||||
|
self.set_reg(REG_D, result)
|
||||||
|
self.program_counter += 1
|
||||||
|
|
||||||
|
def NOR(self, REG_D: int, REG_A: int, REG_B: int):
|
||||||
|
result = (MAX_INT - 1) ^ (self.get_reg(REG_A) | self.get_reg(REG_B))
|
||||||
result %= MAX_INT
|
result %= MAX_INT
|
||||||
self._zero_flag = result == 0
|
self._zero_flag = result == 0
|
||||||
self.set_reg(REG_D, result)
|
self.set_reg(REG_D, result)
|
||||||
|
@ -243,8 +297,3 @@ class Computer:
|
||||||
self._zero_flag = result == 0
|
self._zero_flag = result == 0
|
||||||
self.set_reg(REG_D, result)
|
self.set_reg(REG_D, result)
|
||||||
self.program_counter += 1
|
self.program_counter += 1
|
||||||
|
|
||||||
def LDI(self, REG: int, Immediate: int):
|
|
||||||
self.set_reg(REG, Immediate)
|
|
||||||
self.program_counter += 1
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue