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")
158 f
.write ("const char mono_{0} [] = {{\n".format (symbol_name
))
160 for i
in range(MONO_INST_MAX
):
162 f
.write ("\"\t/* null entry */\n")
164 for op
in sorted_opcodes
:
169 for c
in op
.spec
[:MONO_INST_MAX
]:
173 elif c
.isalnum () and ord (c
) < 0x80:
176 f
.write (r
"\x{0:x}".format (ord (c
)))
178 f
.write ("\"\t/* {0} */\n".format (op
.name
))
179 op
.desc_idx
= idx
* MONO_INST_MAX
182 print ("Error emitting opcode '{0}': '{1}'.".format (op
.name
, sys
.exc_info()))
186 f
.write ("const guint16 mono_{0}_idx [] = {{\n".format (symbol_name
))
187 for op
in sorted_opcodes
:
189 f
.write ("\t0,\t/* {0} */\n".format (op
.name
))
191 f
.write ("\t{0},\t/* {1} */\n".format (op
.desc_idx
, op
.name
))
198 if len (sys
.argv
) != 6:
202 target_define
= sys
.argv
[1]
203 srcdir
= sys
.argv
[2]
204 outfile_name
= sys
.argv
[3]
205 symbol_name
= sys
.argv
[4]
206 infile_name
= sys
.argv
[5]
208 # Parse mini-ops.h file for opcode metadata
209 opcodes
= parse_mini_ops(target_define
)
212 infile
= open (infile_name
, 'r')
213 parse_input (infile
, opcodes
)
216 f
= open (outfile_name
, 'w')
217 gen_output (f
, opcodes
)