-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
Copy pathcpu.py
153 lines (133 loc) · 5.09 KB
/
cpu.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
"""CPU functionality."""
import sys
HLT = 0b00000001
LDI = 0b10000010
PRN = 0b01000111
MUL = 0b10100010
PUSH = 0b01000101
POP = 0b01000110
CALL = 0b01010000
RET = 0b00010001
JMP = 0b01010100
CMP = 0b10100111
JEQ = 0b01010101
JNE = 0b01010110
SP = 7
class CPU:
def __init__(self):
"""Construct a new CPU."""
self.ram = [0] * 256
self.pc = 0
self.reg = [0] * 8
self.reg[7] = 0xF4 #refer PowerON state in Spec
self.running = True
self.fl = 0b00000000
def ram_read(self,addr):
return self.ram[addr]
def ram_write(self,val,addr):
self.ram[addr] = val
def load(self,filename):
"""Load a program into memory."""
address = 0
# program = []
try:
with open(filename) as f:
for line in f:
comment_split = line.split("#")
maybe_binary_number = comment_split[0].strip()
try:
x = int(maybe_binary_number, 2)
self.ram_write(x, address)
address += 1
except:
continue
except FileNotFoundError:
print("Cannot find this file..")
def alu(self, op, reg_a, reg_b):
"""ALU operations."""
# if op == "ADD":
# self.reg[reg_a] += self.reg[reg_b]
if op == MUL:
self.reg[reg_a] *= self.reg[reg_b]
else:
raise Exception("Unsupported ALU operation")
def trace(self):
"""
Handy function to print out the CPU state. You might want to call this
from run() if you need help debugging.
"""
print(f"TRACE: %02X | %02X %02X %02X |" % (
self.pc,
#self.fl,
#self.ie,
self.ram_read(self.pc),
self.ram_read(self.pc + 1),
self.ram_read(self.pc + 2)
), end='')
for i in range(8):
print(" %02X" % self.reg[i], end='')
print()
def num_of_operands(self, instruction_to_execute):
return ((instruction_to_execute >> 6) & 0b11) + 1
def run(self):
"""Run the CPU."""
#self.load()
while self.running:
instruction_to_excecute = self.ram[self.pc]
operand_a = self.ram_read(self.pc+1)
operand_b = self.ram_read(self.pc+2)
if instruction_to_excecute == LDI:
self.reg[operand_a] = operand_b
self.pc += self.num_of_operands(instruction_to_excecute)
elif instruction_to_excecute == PRN:
reg = self.reg[operand_a]
print (reg)
self.pc += self.num_of_operands(instruction_to_excecute)
elif instruction_to_excecute == HLT:
self.running = False
self.pc += self.num_of_operands(instruction_to_excecute)
elif instruction_to_excecute == MUL:
self.alu(instruction_to_excecute,operand_a,operand_b)
self.pc += self.num_of_operands(instruction_to_excecute)
elif instruction_to_excecute == PUSH:
self.reg[SP] -=1 # decrement the stack pointer
self.ram_write(self.reg[operand_a],self.reg[SP])
self.pc += self.num_of_operands(instruction_to_excecute)
elif instruction_to_excecute == POP:
self.reg[operand_a] = self.ram_read(self.reg[SP])
self.reg[SP]+=1
self.pc += self.num_of_operands(instruction_to_excecute)
elif instruction_to_excecute == CALL:
self.reg[SP]-=1
addr_of_next_inst = self.pc+2
self.ram_write(addr_of_next_inst,self.reg[SP])
reg_to_get_addr_from = operand_a
jump_to_addr = self.reg[reg_to_get_addr_from]
self.pc = jump_to_addr
elif instruction_to_excecute == RET:
addr_to_return = self.ram_read(self.reg[SP])
self.pc = addr_to_return
self.reg[SP]+=1
elif instruction_to_excecute == JMP:
self.pc = self.reg[operand_a]
elif instruction_to_excecute == CMP:
if self.reg[operand_a]>self.reg[operand_b]:
self.fl = 0b00000010
elif self.reg[operand_a]<self.reg[operand_b]:
self.fl = 0b00000100
else:
self.fl = 0b00000001
self.pc += self.num_of_operands(instruction_to_excecute)
elif instruction_to_excecute == JNE:
if self.fl != 0b00000001:
self.pc = self.reg[operand_a]
else:
self.pc += self.num_of_operands(instruction_to_excecute)
elif instruction_to_excecute == JEQ:
if self.fl == 0b00000001:
self.pc = self.reg[operand_a]
else:
self.pc += self.num_of_operands(instruction_to_excecute)
else:
print ("idk what to to")
sys.exit()