4 # This tool is used to generate the cpu-<ARCH>.h files used by the JIT. The input is the
5 # cpu-<ARCH>.md file, along with the instruction metadata in mini-ops.h.
12 # Keep it in sync with mini.h
21 allowed_defines
= { "TARGET_X86" : 1,
36 def __init__ (self
, num
, name
, dest_def
, src1_def
, src2_def
):
37 # num is the opcode value/index
40 self
.dest_def
= dest_def
41 self
.src1_def
= src1_def
42 self
.src2_def
= src2_def
44 # Data read from the cpu descriptor file
45 self
.spec
= ["", "", "", "", "", "", "", "", "", ""]
49 print ("Usage: genmdesc.py <target define> <srcdir> <output file name> <c symbol name> <input file name>")
51 def parse_mini_ops (target_define
):
54 enabled
= [target_define
]
56 opcode_file
= open (os
.path
.join (srcdir
, "mini-ops.h"))
58 # Implement a subset of a c preprocessor, only handling #ifdef/#endif directives
60 for line
in opcode_file
:
62 # print ("{0} {1}".format (line, is_enabled))
63 m
= re
.search (r
'^\s*#if (.+)', line
)
64 # FIXME: Check list of defines against an allowed list
67 parts
= m
.group (1).split ("||")
70 m
= re
.search (r
'defined\((.+)\)', part
)
72 print ("Unknown #ifdef line {0}".format (line
))
75 # Check that the file only contains TARGET_... defines
76 if not define
in allowed_defines
:
77 print ("Unknown define '{0}' in mini-ops.h".format (define
))
82 elif line
== "#endif":
85 if is_enabled
and line
.startswith ("MINI_OP"):
86 m
= re
.search (r
"MINI_OP\(\w+\s*\,\s*\"([^
\"]+)\", (\w
+), (\w
+), (\w
+)\
)", line)
88 opcodes [m.group (1)] = OpDef(opcode_id, m.group (1), m.group (2), m.group (3), m.group (4))
90 m = re.search (r"MINI_OP3\
(\w
+\s
*\
,\s
*\"([^
\"]+)\", (\w
+), (\w
+), (\w
+), (\w
+)\
)", line)
92 opcodes [m.group (1)] = OpDef(opcode_id, m.group (1), m.group (2), m.group (3), m.group (4))
94 print ("Unable to parse line
: '{0}'".format (line))
100 def parse_input(infile, opcodes):
102 # Comments are pound sign to end of string.
103 remove_comments = re.compile ("#.*")
108 line
= re
.sub (remove_comments
, "", line
)
110 # Ignore empty lines -- including it was just a comment.
114 # expand_i2: dest:x src1:i len:18
115 parts
= line
.split (" ")
116 op_name
= parts
[0][:-1]
117 if not op_name
in opcodes
:
118 print ("Unknown opcode '{0}'".format (op_name
))
120 opcode
= opcodes
[op_name
]
122 for part
in parts
[1:]:
126 [spec
, value
] = part
.split (":")
128 if opcode
.dest_def
== "NONE":
129 print ("Inconsistent dreg for opcode '{0}'".format (op_name
))
130 opcode
.spec
[MONO_INST_DEST
] = value
132 if opcode
.src1_def
== "NONE":
133 print ("Inconsistent src1 for opcode '{0}'".format (op_name
))
134 opcode
.spec
[MONO_INST_SRC1
] = value
136 if opcode
.src2_def
== "NONE":
137 print ("Inconsistent src2 for opcode '{0}'".format (op_name
))
138 opcode
.spec
[MONO_INST_SRC2
] = value
140 opcode
.spec
[MONO_INST_SRC3
] = value
142 opcode
.spec
[MONO_INST_LEN
] = chr(int(value
))
144 opcode
.spec
[MONO_INST_CLOB
] = value
146 print ("Unknown specifier '{0}' for opcode '{0}'".format (spec
))
149 def gen_output(f
, opcodes
):
151 for op
in opcodes
.values ():
152 sorted_opcodes
.append (op
)
153 sorted_opcodes
.sort (key
=lambda op
: op
.num
)
155 f
.write ("/* File automatically generated by genmdesc.py, don't change */\n\n")
159 f
.write ("const MonoInstSpec mono_{0} [] = {{\n".format (symbol_name
))
162 for i
in range(MONO_INST_MAX
):
164 if i
!= MONO_INST_MAX
- 1:
166 f
.write ("}}, // null entry\n")
169 for op
in sorted_opcodes
:
174 f
.write("// dest src1 src2 src3 len clob\n");
175 f
.write("// ----- ----- ----- ---- ----- -----\n");
181 for c
in op
.spec
[:MONO_INST_MAX
]:
185 elif c
.isalnum () and ord (c
) < 0x80:
186 f
.write (" '%c'" % c
)
187 elif ord (c
) >= 0 and ord (c
) <= 9:
188 f
.write (" %d" % ord (c
))
190 f
.write ("0x%02x" % ord (c
))
191 if j
< MONO_INST_MAX
:
193 f
.write ("}}, // %s\n" % op
.name
)
197 print ("Error emitting opcode '{0}': '{1}'.".format (op
.name
, sys
.exc_info()))
201 f
.write ("const guint16 mono_{0}_idx [] = {{\n".format (symbol_name
))
202 for op
in sorted_opcodes
:
204 f
.write (" 0, // {0}\n".format (op
.name
))
206 f
.write (" {0}, // {1}\n".format (op
.desc_idx
, op
.name
))
213 if len (sys
.argv
) != 6:
217 target_define
= sys
.argv
[1]
218 srcdir
= sys
.argv
[2]
219 outfile_name
= sys
.argv
[3]
220 symbol_name
= sys
.argv
[4]
221 infile_name
= sys
.argv
[5]
223 # Parse mini-ops.h file for opcode metadata
224 opcodes
= parse_mini_ops(target_define
)
227 infile
= open (infile_name
, 'r')
228 parse_input (infile
, opcodes
)
231 f
= open (outfile_name
, 'w')
232 gen_output (f
, opcodes
)