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
|
#!/usr/bin/env python3
# Usage of Exception() is to give an easy traceback, not to actually be used as an exception
import math
import glob
import os
import sys
thisdir = os.path.abspath(os.path.dirname(__file__))
datadir = os.path.abspath(thisdir+"/../cpu")
paths = glob.glob(datadir+"/instructions/*/*")
paths.sort()
instructions = {}
num_instructions = 0
for file in paths:
if os.path.isfile(file) and not os.path.basename(file).endswith("notes.txt"):
name = os.path.splitext(os.path.basename(file))[0]
try:
_ = instructions[name]
raise Exception("Instruction name conflict")
except KeyError:
pass
instructions[name] = {"path": file, "id": num_instructions}
num_instructions += 1
for ins in instructions:
info = instructions[ins]
f = open(info["path"], "r")
line = f.readline()
f.close()
header, num = line.rsplit(maxsplit=1)
if header != "Number of parameters:":
print("Unable to read file "+info["path"]+": does not look like an instruction. ignoring...")
if type(int(num)) != int:
raise Exception("Invalid number: "+num)
info["params"] = int(num)
print("Opcodes:", instructions)
print("Opcode count:", num_instructions)
instruction_bit_size = math.ceil(math.log2(num_instructions)) + 1 # + 1 for is_conditional
print("Bits per opcode:", instruction_bit_size)
# do this after reading the config
f = open(thisdir+"/arbitrary_constants.py");
exec(f.read())
f.close()
argc = len(sys.argv)
print("Number of args given:", argc)
if argc < 2 or argc > 3:
raise Exception("Too few arguments given! Syntax: "+sys.argv[0]+" <input> [<output>]")
if argc >= 3:
output = open(sys.argv[2], "wb")
else:
output = open("/dev/stdout", "wb") # not going to fiddle with using fd 1 from python
print("Using output file", output)
try:
inputf = open(sys.argv[1], "r")
except Exception:
print("Unable to open file `"+sys.argv[1]+"'! Exiting...")
os._exit(1)
input = inputf.read()
inputf.close()
print(input)
# first pass: evaluate instructions, calculate sizes, validate syntax
linenum = 0
in_queue = False
last_queue_opcode = None
for line in input.split('\n'):
linenum+=1
line = line.strip()
if line == "" or line[0] == ";":
continue
i=0
while i < len(line):
if line[i] == " " or line[i] == " ":
break
elif line[i] == "'" or line[i] == "\"" or line == "`":
raise Exception("Invalid instruction at line "+str(linenum)+": "+line)
i+=1
print(line[0:i])
# second pass: calculate label addresses
# third pass: evaluate parameter values, create binary output
|