-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathisa.py
More file actions
139 lines (114 loc) · 3.48 KB
/
isa.py
File metadata and controls
139 lines (114 loc) · 3.48 KB
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
from __future__ import annotations
import json
from enum import Enum
class EnumEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Register):
return "r" + str(obj.value)
return super().default(obj)
class StaticMemoryAddressStub:
offset: int # -1 означает последний элемент после всей статической памяти
def __init__(self, offset: int = 0):
self.offset = offset
class Opcode(Enum):
ST = "ST" # прямая адресация сохранения
ST_ADDR = "ST_ADDR" # косвенная адресация сохранения
ST_STACK = "ST_STACK" # относительно конца стека
LD_ADDR = "LD_ADDR" # косвенная адресация загрузки
LD_LITERAL = "LD_LITERAL" # для загрузки литерала напрямую
LD_STACK = "LD_STACK" # загрузка относительно конца стека
LD = "LD" # косвенная адресация загрузки
JMP = "JMP"
ADD = "ADD"
DIV = "DIV"
MUL = "MUL"
MOD = "MOD"
SUB = "SUB"
MV = "MV"
READ = "READ"
PRINT = "PRINT"
JLE = "JLE" # less or equals
JL = "JL" # less
JGE = "JGE" # greater or equals
JG = "JG" # greater
JNE = "JNE" # not equals
JE = "JE" # equals
NEG = "NEG"
SHL = "SHL"
SHR = "SHR"
AND = "AND"
OR = "OR"
XOR = "XOR"
CMP = "CMP"
PUSH = "PUSH"
POP = "POP"
INC = "INC"
DEC = "DEC"
HALT = "HALT"
ADD_LITERAL = "ADD_LITERAL"
data_memory_size = 4096
class Register(Enum):
r0 = 0
r1 = 1
r2 = 2
r3 = 3
r4 = 4
r5 = 5
r6 = 6
r7 = 7
r8 = 8
r9 = 9
r10 = 10
r11 = 11
r12 = 12
r13 = 13
r14 = 14
r15 = 15
SP: Register = Register.r14
DR: Register = Register.r13
PC: Register = Register.r1
class MachineWord:
index: int
opcode: Opcode
arg1: int | Register | StaticMemoryAddressStub
arg2: int | Register | StaticMemoryAddressStub
def __init__(self, index: int, opcode: Opcode, arg1=None, arg2=None):
self.index = index
self.opcode = opcode
self.arg1 = arg1
self.arg2 = arg2
def write_machine_code_to_file(filename: str, code: list[MachineWord]) -> None:
with open(filename, "w", encoding="utf-8") as file:
buf = []
for instr in code:
buf.append(
json.dumps(
{
"index": instr.index,
"opcode": instr.opcode.value,
"arg1": instr.arg1,
"arg2": instr.arg2,
},
cls=EnumEncoder,
)
)
file.write("[" + ",\n ".join(buf) + "]")
def convert_to_register(arg):
if arg and isinstance(arg, str) and arg.startswith("r"):
return Register[arg]
return arg
def read_code_from_file(filename: str) -> list[MachineWord]:
with open(filename, encoding="utf-8") as file:
code = json.loads(file.read())
prog: list[MachineWord] = []
for instr in code:
word = MachineWord(
instr["index"],
Opcode[instr["opcode"]],
convert_to_register(instr["arg1"]),
convert_to_register(instr["arg2"]),
)
prog.append(word)
for index in range(len(prog), data_memory_size):
prog.append(MachineWord(index, Opcode.JMP, 0))
return prog