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
7 # Awk implementation sanity check
8 function check_awk_implement() {
9 if (!match("abc", "[[:lower:]]+"))
10 return "Your awk doesn't support charactor-class."
11 if (sprintf("%x", 0) != "0")
12 return "Your awk has a printf-format problem."
17 # Implementation error checking
18 awkchecked = check_awk_implement()
19 if (awkchecked != "") {
20 print "Error: " awkchecked > "/dev/stderr"
21 print "Please try to use gawk." > "/dev/stderr"
25 # Setup generating tables
26 print "/* x86 opcode map generated from x86-opcode-map.txt */"
27 print "/* Do not change this code. */"
31 opnd_expr = "^[[:alpha:]]"
34 group_expr = "^Grp[[:alnum:]]+"
36 imm_expr = "^[IJAO][[:lower:]]"
37 imm_flag["Ib"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
38 imm_flag["Jb"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
39 imm_flag["Iw"] = "INAT_MAKE_IMM(INAT_IMM_WORD)"
40 imm_flag["Id"] = "INAT_MAKE_IMM(INAT_IMM_DWORD)"
41 imm_flag["Iq"] = "INAT_MAKE_IMM(INAT_IMM_QWORD)"
42 imm_flag["Ap"] = "INAT_MAKE_IMM(INAT_IMM_PTR)"
43 imm_flag["Iz"] = "INAT_MAKE_IMM(INAT_IMM_VWORD32)"
44 imm_flag["Jz"] = "INAT_MAKE_IMM(INAT_IMM_VWORD32)"
45 imm_flag["Iv"] = "INAT_MAKE_IMM(INAT_IMM_VWORD)"
46 imm_flag["Ob"] = "INAT_MOFFSET"
47 imm_flag["Ov"] = "INAT_MOFFSET"
49 modrm_expr = "^([CDEGMNPQRSUVW][[:lower:]]+|NTA|T[012])"
50 force64_expr = "\\([df]64\\)"
51 rex_expr = "^REX(\\.[XRWB]+)*"
52 fpu_expr = "^ESC" # TODO
54 lprefix1_expr = "\\(66\\)"
56 lprefix2_expr = "\\(F2\\)"
58 lprefix3_expr = "\\(F3\\)"
62 prefix_expr = "\\(Prefix\\)"
63 prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ"
64 prefix_num["REPNE"] = "INAT_PFX_REPNE"
65 prefix_num["REP/REPE"] = "INAT_PFX_REPE"
66 prefix_num["LOCK"] = "INAT_PFX_LOCK"
67 prefix_num["SEG=CS"] = "INAT_PFX_CS"
68 prefix_num["SEG=DS"] = "INAT_PFX_DS"
69 prefix_num["SEG=ES"] = "INAT_PFX_ES"
70 prefix_num["SEG=FS"] = "INAT_PFX_FS"
71 prefix_num["SEG=GS"] = "INAT_PFX_GS"
72 prefix_num["SEG=SS"] = "INAT_PFX_SS"
73 prefix_num["Address-Size"] = "INAT_PFX_ADDRSZ"
82 function semantic_error(msg) {
83 print "Semantic error at " NR ": " msg > "/dev/stderr"
91 function array_size(arr, i,c) {
104 # primary opcode table
105 tname = "inat_primary_table"
108 # escape opcode table
110 for (i = 2; i <= NF; i++)
113 tname = sprintf("inat_escape_table_%d", eid)
120 semantic_error("No group: " $2 )
122 tname = "inat_group_table_" gid
125 function print_table(tbl,name,fmt,n)
127 print "const insn_attr_t " name " = {"
128 for (i = 0; i < n; i++) {
131 print " [" id "] = " tbl[id] ","
139 if (array_size(table) != 0) {
140 print_table(table, tname "[INAT_GROUP_TABLE_SIZE]",
142 gtable[gid,0] = tname
144 if (array_size(lptable1) != 0) {
145 print_table(lptable1, tname "_1[INAT_GROUP_TABLE_SIZE]",
147 gtable[gid,1] = tname "_1"
149 if (array_size(lptable2) != 0) {
150 print_table(lptable2, tname "_2[INAT_GROUP_TABLE_SIZE]",
152 gtable[gid,2] = tname "_2"
154 if (array_size(lptable3) != 0) {
155 print_table(lptable3, tname "_3[INAT_GROUP_TABLE_SIZE]",
157 gtable[gid,3] = tname "_3"
160 # print primary/escaped tables
161 if (array_size(table) != 0) {
162 print_table(table, tname "[INAT_OPCODE_TABLE_SIZE]",
164 etable[eid,0] = tname
166 if (array_size(lptable1) != 0) {
167 print_table(lptable1,tname "_1[INAT_OPCODE_TABLE_SIZE]",
169 etable[eid,1] = tname "_1"
171 if (array_size(lptable2) != 0) {
172 print_table(lptable2,tname "_2[INAT_OPCODE_TABLE_SIZE]",
174 etable[eid,2] = tname "_2"
176 if (array_size(lptable3) != 0) {
177 print_table(lptable3,tname "_3[INAT_OPCODE_TABLE_SIZE]",
179 etable[eid,3] = tname "_3"
191 function add_flags(old,new) {
200 # convert operands to flags.
201 function convert_operands(opnd, i,imm,mod)
207 if (match(i, imm_expr) == 1) {
209 semantic_error("Unknown imm opnd: " i)
212 semantic_error("Second IMM error")
213 imm = add_flags(imm, "INAT_SCNDIMM")
216 } else if (match(i, modrm_expr))
219 return add_flags(imm, mod)
226 idx = "0x" substr($1, 1, index($1,":") - 1)
228 semantic_error("Redefine " idx " in " tname)
230 # check if escaped opcode
231 if ("escape" == $2) {
233 semantic_error("No escaped name")
235 for (i = 4; i <= NF; i++)
238 semantic_error("Redefine escape (" ref ")")
241 table[idx] = "INAT_MAKE_ESCAPE(" escape[ref] ")"
255 if (match($i, opnd_expr)) {
257 split($(i++), opnds, ",")
258 flags = convert_operands(opnds)
260 if (match($i, ext_expr))
262 if (match($i, sep_expr))
265 semantic_error($i " is not a separator")
267 # check if group opcode
268 if (match(opcode, group_expr)) {
269 if (!(opcode in group)) {
273 flags = add_flags(flags, "INAT_MAKE_GROUP(" group[opcode] ")")
275 # check force(or default) 64bit
276 if (match(ext, force64_expr))
277 flags = add_flags(flags, "INAT_FORCE64")
280 if (match(opcode, rex_expr))
281 flags = add_flags(flags, "INAT_REXPFX")
283 # check coprocessor escape : TODO
284 if (match(opcode, fpu_expr))
285 flags = add_flags(flags, "INAT_MODRM")
288 if (match(ext, prefix_expr)) {
289 if (!prefix_num[opcode])
290 semantic_error("Unknown prefix: " opcode)
291 flags = add_flags(flags, "INAT_MAKE_PREFIX(" prefix_num[opcode] ")")
293 if (length(flags) == 0)
295 # check if last prefix
296 if (match(ext, lprefix1_expr)) {
297 lptable1[idx] = add_flags(lptable1[idx],flags)
298 variant = "INAT_VARIANT"
299 } else if (match(ext, lprefix2_expr)) {
300 lptable2[idx] = add_flags(lptable2[idx],flags)
301 variant = "INAT_VARIANT"
302 } else if (match(ext, lprefix3_expr)) {
303 lptable3[idx] = add_flags(lptable3[idx],flags)
304 variant = "INAT_VARIANT"
306 table[idx] = add_flags(table[idx],flags)
310 table[idx] = add_flags(table[idx],variant)
314 if (awkchecked != "")
316 # print escape opcode map's array
317 print "/* Escape opcode map array */"
318 print "const insn_attr_t const *inat_escape_tables[INAT_ESC_MAX + 1]" \
319 "[INAT_LPREFIX_MAX + 1] = {"
320 for (i = 0; i < geid; i++)
321 for (j = 0; j < max_lprefix; j++)
323 print " ["i"]["j"] = "etable[i,j]","
325 # print group opcode map's array
326 print "/* Group opcode map array */"
327 print "const insn_attr_t const *inat_group_tables[INAT_GRP_MAX + 1]"\
328 "[INAT_LPREFIX_MAX + 1] = {"
329 for (i = 0; i < ggid; i++)
330 for (j = 0; j < max_lprefix; j++)
332 print " ["i"]["j"] = "gtable[i,j]","