diff --git a/main.py b/main.py index a5907d4..6fab8d7 100644 --- a/main.py +++ b/main.py @@ -1,120 +1,105 @@ -#made by zombie -#02/01/21 - -#0-255 is internal registers and flags and etc -# program execcution starts at 256 -#stack starts at 65535 FILO - -#0 IP #Instruction Pointer -#1 EAX -#2 EBX -#3 ECX -#4 EDX -#5 ESI -#6 EDI -#7 ESP #stack pointer -#8 EBP -#9 FLAG #Read-Only contains the flags - - -#list of opcodes -#0 interrupt -#1 reset -#2 debug info (nop) -#3 mov -#4 push (onto stack) -#5 pop (off of stack into address) - +# made by zombie +# 02/01/21 import math import numpy as np + +import opcodes as ops from console import Console +from memory import Memory +from registers import Registers np.set_printoptions(threshold=np.inf) +class ZCPU: + _halted = False + _regs = Registers() + _mem = None -class Zomcpu: - def __init__(self, memorysize=None, debug=None): + def __init__(self, memory, debug=None): print('Processor Init') - self._memorysize = memorysize - self._memory = np.zeros(memorysize) self._debug = debug - + self._mem = memory + def reset(self): print('Processor Resetting') - self._memory = np.zeros(self._memorysize) #clear memory - - self._memory[7] = self._memorysize - 1 #set stackpointer - self._memory[0] = 256 #set instructiojn pointer - + self._regs.sp = self._mem.size() - 1 # Set stackpointer + self._regs.ip = 0 # Set instruction pointer + def exec(self): - Go = 1 - while Go: #change this to if not halt - #fetch - opcode = self._memory[int(self._memory[0])] - address = self._memory[int(self._memory[0] + 1)] - value = self._memory[int(self._memory[0] + 2)] - + while not self._halted: + # Fetch instruction + opcode = self._mem.read(self._regs.ip) + address = self._mem.read(self._regs.ip + 1) + value = self._mem.read(self._regs.ip + 2) + if self._debug: - print(f'Opcode: {opcode}\nAddress: {address}\nValue: {value}\nIP: {self._memory[0]}') + print(f'Opcode: {opcode}\nAddress: {address}\nValue: {value}\nIP: {self._regs.ip}') - if opcode == 0: - Go = value - if value == 0: - print('Processor Halted') + if opcode == ops.NOP: # No-op + pass - elif opcode == 1: #reset + elif opcode == ops.HLT: # Halt + self._halted = True + + elif opcode == ops.RST: # Reset self.reset() - - elif opcode == 2: #debug (nop if debug is not set) + + elif opcode == ops.DBG: # Debug (nop if debug is not set) -- This is stoopid if self._debug: print(f'Opcode: {opcode}\nAddress: {address}\nValue: {value}') - - elif opcode == 3: #mov - self.write_memory(address, value) - - elif opcode == 4: #push - self.write_memory(self._memory[7], value) #put value onto stack - self.write_memory(7, self._memory[7] - 1) #dec stackpointer - - elif opcode == 5: #pop - self.write_memory(address, self.read_memory_address(self._memory[7] + 1)) #read the last value and put it into address (not the empty space) - self.write_memory(7, self._memory[7] + 1) #inc stackpointer - - self._memory[0] += 3 #increment instruction pointer - - - def set_memory(self, memory): - self._memory = memory - def write_memory(self, address, value): - self._memory[int(address)] = value - def read_memory(self): - return self._memory - def read_memory_address(self, address): - return self._memory[int(address)] - + + elif opcode == ops.LDI: # ldi + self._mem.write(address, value) + + elif opcode == ops.PUSH: # push + self._mem.write(self._regs.sp, value) + self._regs.sp -= 1 + + elif opcode == ops.POP: # pop + self._regs.sp += 1 + self._mem.write(address, self._mem.read(self._regs.sp)) + + else: + raise RuntimeException(f'Invalid Opcode: {opcode}') + + #increment instruction pointer + self._regs.ip += 3 + + if __name__ == "__main__": - cpu = Zomcpu(65536, True) - cpu.reset() - #hard coded opcodes - cpu.write_memory(256, 3) #mov - cpu.write_memory(257, 27) #address 27 - cpu.write_memory(258, 105) #105 into ^ - cpu.write_memory(259, 4) #push - cpu.write_memory(260, 0) #unused in this op - cpu.write_memory(261, 27) #the value at address 27 onto the stack - cpu.write_memory(262, 5) #pop - cpu.write_memory(263, 100) #into 100 - cpu.write_memory(264, 0) #unused in this op - - + ram = Memory(65536) + + ram.write(0, ops.LDI) + ram.write(1, 100) + ram.write(2, 5) + + ram.write(3, ops.PUSH) + ram.write(4, 0) + ram.write(5, 69) + + ram.write(6, ops.POP) + ram.write(7, 101) + ram.write(8, 0) + + ram.write(9, ops.DBG) + ram.write(10, 1) + ram.write(11, 2) + + ram.write(12, ops.HLT) + ram.write(13, 0) + ram.write(14, 0) + + cpu = ZCPU(ram, False) + cpu.reset() cpu.exec() - print(cpu.read_memory_address(100)) - print(cpu.read_memory_address(264)) - print(cpu.read_memory_address(7)) + + print(ram.read(100)) + print(ram.read(101)) + print(ram.read(102)) #c = Console(cpu.read_memory()) ima finish this later #c.draw() - + diff --git a/memory.py b/memory.py new file mode 100644 index 0000000..44098c4 --- /dev/null +++ b/memory.py @@ -0,0 +1,27 @@ +import numpy as np + +class Memory: + def __init__(self, size): + self._memory = np.zeros(size) + + def write(self, address, data): + address = int(address) + if 0 > address >= self._memory.size: + # TODO: Raise an exception and throw an interrupt here + raise RuntimeException('Invalid write address') + + self._memory[address] = data + + def read(self, address): + address = int(address) + if 0 > address >= self._memory.size: + # TODO: Raise an exception and throw an interrupt here + raise RuntimeException('Invalid write address') + + return self._memory[address] + + def clear(self, data=0): + self._memory.fill(data) + + def size(self): + return self._memory.size diff --git a/opcodes.py b/opcodes.py new file mode 100644 index 0000000..6361470 --- /dev/null +++ b/opcodes.py @@ -0,0 +1,7 @@ +NOP = 0 # No-op +HLT = 1 # Halt +RST = 2 # Reset +DBG = 3 # Debug +LDI = 4 # Load Immediate +PUSH = 5 # Push +POP = 6 # Pop diff --git a/registers.py b/registers.py new file mode 100644 index 0000000..74ded50 --- /dev/null +++ b/registers.py @@ -0,0 +1,11 @@ +class Registers: + ip = 0 + ax = 0 + bx = 0 + cx = 0 + dx = 0 + si = 0 + di = 0 + sp = 0 + bp = 0 + flags = 0