Skip to content
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@

- [ ] Add the timer interrupt to the LS-8 emulator
- [ ] Add the keyboard interrupt to the LS-8 emulator
- [ ] Write an LS-8 assembly program to draw a curved histogram on the screen
- [ ] Write an LS-8 assembly program to draw a curved histogram on the screen
131 changes: 106 additions & 25 deletions ls8/cpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,68 @@

import sys

HLT = 0b00000001
LDI = 0b10000010
PRN = 0b01000111
MUL = 0b10100010
PUSH = 0b01000101
POP = 0b01000110
CALL = 0b01010000
RET = 0b00010001
CMP = 0b10100111
JMP = 0b01010100
JEQ = 0b01010101
JNE = 0b01010110

SP = 7

class CPU:
"""Main CPU class."""

def __init__(self):
"""Construct a new CPU."""
pass

def load(self):
self.registers = [0] * 8
self.registers[7] = 0xF4
self.pc = 0
self.ram = [0] * 256
self.halted = False
self.fl = 0

def load(self, filename):
"""Load a program into memory."""

address = 0

# For now, we've just hardcoded a program:

program = [
# From print8.ls8
0b10000010, # LDI R0,8
0b00000000,
0b00001000,
0b01000111, # PRN R0
0b00000000,
0b00000001, # HLT
]

for instruction in program:
self.ram[address] = instruction
address += 1

# open the file
with open(filename) as my_file:
# go through each line to parse and get instruction
for line in my_file:
# try and get the instruction/operand in the line
comment_split = line.split("#")
maybe_binary_number = comment_split[0]
try:
x = int(maybe_binary_number, 2)
self.ram_write(x, address)
address += 1
except:
continue

def alu(self, op, reg_a, reg_b):
"""ALU operations."""

if op == "ADD":
self.reg[reg_a] += self.reg[reg_b]
#elif op == "SUB": etc
if op == MUL:
self.registers[reg_a] *= self.registers[reg_b]
self.pd += 3
else:
raise Exception("Unsupported ALU operation")
if op == CMP:
if self.registers[reg_a] == self.registers[reg_b]:
self.fl = 1
if self.registers[reg_a] < registers[reg_b]:
self.fl = 1
if self.registers[reg_a] > registers[reg_b]:
self.fl = 1
else:
self.fl = 0

def trace(self):
"""
Expand All @@ -48,7 +73,7 @@ def trace(self):

print(f"TRACE: %02X | %02X %02X %02X |" % (
self.pc,
#self.fl,
self.fl,
#self.ie,
self.ram_read(self.pc),
self.ram_read(self.pc + 1),
Expand All @@ -60,6 +85,62 @@ def trace(self):

print()

def ram_read(self, address):
return self.ram[address]

def ram_write(self, value, address):
self.ram[address] = value

def run(self):
"""Run the CPU."""
pass

while not self.halted:
instruction_to_execute = self.ram_read(self.pc)
operand_a = self.ram_read(self.pc + 1)
operand_b = self.ram_read(self.pc + 2)
self.execute_instruction(instruction_to_execute, operand_a, operand_b)

def execute_instruction(self, instruction, operand_a, operand_b):
if instruction == HLT:
self.halted = True
self.pc += 1
elif instruction == PRN:
print(self.registers[operand_a])
self.pc += 2
elif instruction == LDI:
self.registers[operand_a] = operand_b
self.pc += 3
elif instruction == MUL:
self.alu(instruction, operand_a, operand_b)
elif instruction == PUSH:
# decrement the stack pointer
self.registers[SP] -= 1
# store the operand ine the stack
self.ram_write(self.registers[operand_a], self.registers[SP])
self.pc += 2
elif instruction == POP:
self.registers[operand_a] = self.ram_read(self.registers[SP])
self.pc += 2
elif instruction == CALL:
# self.registers[SP] -= 1
# address_of_next_instruction = self.pc + 2
pass
elif instruction == RET:
pass


elif instruction == CMP:
self.alu(instruction, operand_a, operand_b)
elif instruction == JMP:
self.pc = self.registers[operand_a]
elif instruction == JEQ:
if self.fl = 1:
self.pc = self.registers[operand_a]
elif instruction == JNE:
if self.fl = 0:
self.pc = self.registers[operand_a]


else:
print('idk what to do.')
pass
10 changes: 6 additions & 4 deletions ls8/ls8.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import sys
from cpu import *

cpu = CPU()

cpu.load()
cpu.run()
if len(sys.argv) != 2:
print("wrong number of arguments passed in")
else:
cpu = CPU()
cpu.load(sys.argv[0])
cpu.run()