2 # gen-insn-attr-x86.awk: Instruction attribute table generator
3 # Written by Masami Hiramatsu <mhiramat@redhat.com>
5 # Usage: awk -f gen-insn-attr-x86.awk x86-opcode-map.txt > inat-tables.c
8 print "/* x86 opcode map generated from x86-opcode-map.txt */"
9 print "/* Do not change this code. */"
13 opnd_expr = "^[[:alpha:]]"
16 group_expr = "^Grp[[:alnum:]]+"
18 imm_expr = "^[IJAO][[:lower:]]"
19 imm_flag["Ib"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
20 imm_flag["Jb"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
21 imm_flag["Iw"] = "INAT_MAKE_IMM(INAT_IMM_WORD)"
22 imm_flag["Id"] = "INAT_MAKE_IMM(INAT_IMM_DWORD)"
23 imm_flag["Iq"] = "INAT_MAKE_IMM(INAT_IMM_QWORD)"
24 imm_flag["Ap"] = "INAT_MAKE_IMM(INAT_IMM_PTR)"
25 imm_flag["Iz"] = "INAT_MAKE_IMM(INAT_IMM_VWORD32)"
26 imm_flag["Jz"] = "INAT_MAKE_IMM(INAT_IMM_VWORD32)"
27 imm_flag["Iv"] = "INAT_MAKE_IMM(INAT_IMM_VWORD)"
28 imm_flag["Ob"] = "INAT_MOFFSET"
29 imm_flag["Ov"] = "INAT_MOFFSET"
31 modrm_expr = "^([CDEGMNPQRSUVW][[:lower:]]+|NTA|T[012])"
32 force64_expr = "\\([df]64\\)"
33 rex_expr = "^REX(\\.[XRWB]+)*"
34 fpu_expr = "^ESC" # TODO
36 lprefix1_expr = "\\(66\\)"
38 lprefix2_expr = "\\(F2\\)"
40 lprefix3_expr = "\\(F3\\)"
44 prefix_expr = "\\(Prefix\\)"
45 prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ"
46 prefix_num["REPNE"] = "INAT_PFX_REPNE"
47 prefix_num["REP/REPE"] = "INAT_PFX_REPE"
48 prefix_num["LOCK"] = "INAT_PFX_LOCK"
49 prefix_num["SEG=CS"] = "INAT_PFX_CS"
50 prefix_num["SEG=DS"] = "INAT_PFX_DS"
51 prefix_num["SEG=ES"] = "INAT_PFX_ES"
52 prefix_num["SEG=FS"] = "INAT_PFX_FS"
53 prefix_num["SEG=GS"] = "INAT_PFX_GS"
54 prefix_num["SEG=SS"] = "INAT_PFX_SS"
55 prefix_num["Address-Size"] = "INAT_PFX_ADDRSZ"
64 function semantic_error(msg) {
65 print "Semantic error at " NR ": " msg > "/dev/stderr"
73 function array_size(arr, i,c) {
86 # primary opcode table
87 tname = "inat_primary_table"
92 for (i = 2; i <= NF; i++)
95 tname = sprintf("inat_escape_table_%d", eid)
102 semantic_error("No group: " $2 )
104 tname = "inat_group_table_" gid
107 function print_table(tbl,name,fmt,n)
109 print "const insn_attr_t " name " = {"
110 for (i = 0; i < n; i++) {
113 print " [" id "] = " tbl[id] ","
121 if (array_size(table) != 0) {
122 print_table(table, tname "[INAT_GROUP_TABLE_SIZE]",
124 gtable[gid,0] = tname
126 if (array_size(lptable1) != 0) {
127 print_table(lptable1, tname "_1[INAT_GROUP_TABLE_SIZE]",
129 gtable[gid,1] = tname "_1"
131 if (array_size(lptable2) != 0) {
132 print_table(lptable2, tname "_2[INAT_GROUP_TABLE_SIZE]",
134 gtable[gid,2] = tname "_2"
136 if (array_size(lptable3) != 0) {
137 print_table(lptable3, tname "_3[INAT_GROUP_TABLE_SIZE]",
139 gtable[gid,3] = tname "_3"
142 # print primary/escaped tables
143 if (array_size(table) != 0) {
144 print_table(table, tname "[INAT_OPCODE_TABLE_SIZE]",
146 etable[eid,0] = tname
148 if (array_size(lptable1) != 0) {
149 print_table(lptable1,tname "_1[INAT_OPCODE_TABLE_SIZE]",
151 etable[eid,1] = tname "_1"
153 if (array_size(lptable2) != 0) {
154 print_table(lptable2,tname "_2[INAT_OPCODE_TABLE_SIZE]",
156 etable[eid,2] = tname "_2"
158 if (array_size(lptable3) != 0) {
159 print_table(lptable3,tname "_3[INAT_OPCODE_TABLE_SIZE]",
161 etable[eid,3] = tname "_3"
173 function add_flags(old,new) {
182 # convert operands to flags.
183 function convert_operands(opnd, i,imm,mod)
189 if (match(i, imm_expr) == 1) {
191 semantic_error("Unknown imm opnd: " i)
194 semantic_error("Second IMM error")
195 imm = add_flags(imm, "INAT_SCNDIMM")
198 } else if (match(i, modrm_expr))
201 return add_flags(imm, mod)
208 idx = "0x" substr($1, 1, index($1,":") - 1)
210 semantic_error("Redefine " idx " in " tname)
212 # check if escaped opcode
213 if ("escape" == $2) {
215 semantic_error("No escaped name")
217 for (i = 4; i <= NF; i++)
220 semantic_error("Redefine escape (" ref ")")
223 table[idx] = "INAT_MAKE_ESCAPE(" escape[ref] ")"
237 if (match($i, opnd_expr)) {
239 split($(i++), opnds, ",")
240 flags = convert_operands(opnds)
242 if (match($i, ext_expr))
244 if (match($i, sep_expr))
247 semantic_error($i " is not a separator")
249 # check if group opcode
250 if (match(opcode, group_expr)) {
251 if (!(opcode in group)) {
255 flags = add_flags(flags, "INAT_MAKE_GROUP(" group[opcode] ")")
257 # check force(or default) 64bit
258 if (match(ext, force64_expr))
259 flags = add_flags(flags, "INAT_FORCE64")
262 if (match(opcode, rex_expr))
263 flags = add_flags(flags, "INAT_REXPFX")
265 # check coprocessor escape : TODO
266 if (match(opcode, fpu_expr))
267 flags = add_flags(flags, "INAT_MODRM")
270 if (match(ext, prefix_expr)) {
271 if (!prefix_num[opcode])
272 semantic_error("Unknown prefix: " opcode)
273 flags = add_flags(flags, "INAT_MAKE_PREFIX(" prefix_num[opcode] ")")
275 if (length(flags) == 0)
277 # check if last prefix
278 if (match(ext, lprefix1_expr)) {
279 lptable1[idx] = add_flags(lptable1[idx],flags)
280 variant = "INAT_VARIANT"
281 } else if (match(ext, lprefix2_expr)) {
282 lptable2[idx] = add_flags(lptable2[idx],flags)
283 variant = "INAT_VARIANT"
284 } else if (match(ext, lprefix3_expr)) {
285 lptable3[idx] = add_flags(lptable3[idx],flags)
286 variant = "INAT_VARIANT"
288 table[idx] = add_flags(table[idx],flags)
292 table[idx] = add_flags(table[idx],variant)
296 # print escape opcode map's array
297 print "/* Escape opcode map array */"
298 print "const insn_attr_t const *inat_escape_tables[INAT_ESC_MAX + 1]" \
299 "[INAT_LPREFIX_MAX + 1] = {"
300 for (i = 0; i < geid; i++)
301 for (j = 0; j < max_lprefix; j++)
303 print " ["i"]["j"] = "etable[i,j]","
305 # print group opcode map's array
306 print "/* Group opcode map array */"
307 print "const insn_attr_t const *inat_group_tables[INAT_GRP_MAX + 1]"\
308 "[INAT_LPREFIX_MAX + 1] = {"
309 for (i = 0; i < ggid; i++)
310 for (j = 0; j < max_lprefix; j++)
312 print " ["i"]["j"] = "gtable[i,j]","