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
|
#!/usr/bin/python
import sys
import re
# Initial state
state = 1
text = ""
dispatch_to_states = { "MAIN" : 0 }
states_to_dispatch = { 0 : "MAIN" }
def load_file(fname, lines):
path = fname.rpartition('/')[0]
if path != "":
path += '/'
try:
f = open(fname, "rU")
except Exception:
err = sys.exc_info()[1]
sys.stderr.write("Cannot read opcodes file %s [%s]\n" % (fname, err))
sys.exit(1)
rawlines = re.split('(\n|; *\n?)', f.read())
count = 0
while count < len(rawlines)-1:
line = rawlines[count+0] + rawlines[count+1]
if line.startswith("#include"):
load_file(path + line.split('"')[1], lines)
else:
lines.append(line)
count += 2
f.close()
# Get lines
lines = []
load_file(sys.argv[1], lines)
count = 0
while count < len(lines):
# Retrieve this line
line = lines[count]
# Retrieve the whitespace
whitespace = line[:len(line) - len(line.lstrip())]
# Check to see if the next line is a return
next_line_is_return = (count + 1 == len(lines)) or lines[count+1].strip() == "return;"
# Check to see if the next line is a dispatch followed by return
next_line_is_dispatch_and_return = (count + 1 < len(lines)) and re.match('([A-Za-z0-9\t ]+\:)*\s*\%', lines[count+1]) and lines[count+2].strip() == "return;"
if re.match('([A-Za-z0-9\t ]+\:)*\s*\%', line):
# This is a dispatch - find the '%'
percent_pos = line.find("%")
dispatch = line[percent_pos+1:].strip("\t\n; ")
# Do we have a label?
label = line[:percent_pos].strip()
if label != "":
text += whitespace + label + "\n"
whitespace += "\t"
# Create the goto command
if dispatch[-1:] == "*":
goto_command = "if (is_register_register_op_16_bit()) goto %s16; else goto %s8;\n" %(dispatch[:-1], dispatch[:-1])
else:
goto_command = "goto %s;\n" % dispatch
# Are we right before a 'return'?
if next_line_is_return:
text += whitespace + goto_command
count += 1 # Skip the return
elif next_line_is_dispatch_and_return:
# We are followed by a dispatch/return combo; identify the next dispatch
percent_pos = lines[count+1].find("%")
next_dispatch = lines[count+1][percent_pos+1:].strip("\t\n; ")
# If there is no state number associated with the next dispatch, make one
if next_dispatch not in dispatch_to_states:
dispatch_to_states[next_dispatch] = state
states_to_dispatch[state] = next_dispatch
state += 1
text += whitespace + "push_state(%s);\t// %s\n" % (dispatch_to_states[next_dispatch], next_dispatch)
text += whitespace + goto_command
count += 2 # Skip the dispatch/return
else:
# Normal dispatch
text += whitespace + "push_state(%s);\n" % state
text += whitespace + goto_command
text += "state_%s:\n" % state
state += 1
else:
# "Normal" code
# Is there an '@' here?
check_icount = line.lstrip().startswith("@")
if check_icount:
line = line.replace("@", "", 1)
# Output the line
text += line
# If we have to decrement the icount, output more info
if check_icount and not next_line_is_return:
text += whitespace + "if (UNEXPECTED(m_icount <= 0)) { push_state(%s); return; }\n" % state
text += "state_%s:\n" % state
state += 1
# Advance to next line
count += 1
# Output the case labels
for i in range(0, state):
print("\tcase %d: goto %s;" % (i, states_to_dispatch.get(i, "state_%d" % i)))
# Output a default case
print("\tdefault:")
print("\t\tfatalerror(\"Unexpected state\");")
print("\t\tbreak;")
print("")
# Finally output the text
print(text)
|