1 #!/bin/awk -f 2 # SPDX-License-Identifier: GPL-2.0 3 # gen-insn-attr-x86.awk: Instruction attribute 4 # Written by Masami Hiramatsu <mhiramat@redhat. 5 # 6 # Usage: awk -f gen-insn-attr-x86.awk x86-opco 7 8 # Awk implementation sanity check 9 function check_awk_implement() { 10 if (sprintf("%x", 0) != "0") 11 return "Your awk has a printf- 12 return "" 13 } 14 15 # Clear working vars 16 function clear_vars() { 17 delete table 18 delete lptable2 19 delete lptable1 20 delete lptable3 21 eid = -1 # escape id 22 gid = -1 # group id 23 aid = -1 # AVX id 24 tname = "" 25 } 26 27 BEGIN { 28 # Implementation error checking 29 awkchecked = check_awk_implement() 30 if (awkchecked != "") { 31 print "Error: " awkchecked > " 32 print "Please try to use gawk. 33 exit 1 34 } 35 36 # Setup generating tables 37 print "/* x86 opcode map generated fro 38 print "/* Do not change this code. */\ 39 ggid = 1 40 geid = 1 41 gaid = 0 42 delete etable 43 delete gtable 44 delete atable 45 46 opnd_expr = "^[A-Za-z/]" 47 ext_expr = "^\\(" 48 sep_expr = "^\\|$" 49 group_expr = "^Grp[0-9A-Za-z]+" 50 51 imm_expr = "^[IJAOL][a-z]" 52 imm_flag["Ib"] = "INAT_MAKE_IMM(INAT_I 53 imm_flag["Jb"] = "INAT_MAKE_IMM(INAT_I 54 imm_flag["Iw"] = "INAT_MAKE_IMM(INAT_I 55 imm_flag["Id"] = "INAT_MAKE_IMM(INAT_I 56 imm_flag["Iq"] = "INAT_MAKE_IMM(INAT_I 57 imm_flag["Ap"] = "INAT_MAKE_IMM(INAT_I 58 imm_flag["Iz"] = "INAT_MAKE_IMM(INAT_I 59 imm_flag["Jz"] = "INAT_MAKE_IMM(INAT_I 60 imm_flag["Iv"] = "INAT_MAKE_IMM(INAT_I 61 imm_flag["Ob"] = "INAT_MOFFSET" 62 imm_flag["Ov"] = "INAT_MOFFSET" 63 imm_flag["Lx"] = "INAT_MAKE_IMM(INAT_I 64 65 modrm_expr = "^([CDEGMNPQRSUVW/][a-z]+ 66 force64_expr = "\\([df]64\\)" 67 rex_expr = "^((REX(\\.[XRWB]+)+)|(REX$ 68 rex2_expr = "\\(REX2\\)" 69 no_rex2_expr = "\\(!REX2\\)" 70 fpu_expr = "^ESC" # TODO 71 72 lprefix1_expr = "\\((66|!F3)\\)" 73 lprefix2_expr = "\\(F3\\)" 74 lprefix3_expr = "\\((F2|!F3|66&F2)\\)" 75 lprefix_expr = "\\((66|F2|F3)\\)" 76 max_lprefix = 4 77 78 # All opcodes starting with lower-case 79 # accepts VEX prefix 80 vexok_opcode_expr = "^[vk].*" 81 vexok_expr = "\\(v1\\)" 82 # All opcodes with (v) superscript sup 83 vexonly_expr = "\\(v\\)" 84 # All opcodes with (ev) superscript su 85 evexonly_expr = "\\(ev\\)" 86 # (es) is the same as (ev) but also "S 87 evex_scalable_expr = "\\(es\\)" 88 89 prefix_expr = "\\(Prefix\\)" 90 prefix_num["Operand-Size"] = "INAT_PFX 91 prefix_num["REPNE"] = "INAT_PFX_REPNE" 92 prefix_num["REP/REPE"] = "INAT_PFX_REP 93 prefix_num["XACQUIRE"] = "INAT_PFX_REP 94 prefix_num["XRELEASE"] = "INAT_PFX_REP 95 prefix_num["LOCK"] = "INAT_PFX_LOCK" 96 prefix_num["SEG=CS"] = "INAT_PFX_CS" 97 prefix_num["SEG=DS"] = "INAT_PFX_DS" 98 prefix_num["SEG=ES"] = "INAT_PFX_ES" 99 prefix_num["SEG=FS"] = "INAT_PFX_FS" 100 prefix_num["SEG=GS"] = "INAT_PFX_GS" 101 prefix_num["SEG=SS"] = "INAT_PFX_SS" 102 prefix_num["Address-Size"] = "INAT_PFX 103 prefix_num["VEX+1byte"] = "INAT_PFX_VE 104 prefix_num["VEX+2byte"] = "INAT_PFX_VE 105 prefix_num["EVEX"] = "INAT_PFX_EVEX" 106 prefix_num["REX2"] = "INAT_PFX_REX2" 107 108 clear_vars() 109 } 110 111 function semantic_error(msg) { 112 print "Semantic error at " NR ": " msg 113 exit 1 114 } 115 116 function debug(msg) { 117 print "DEBUG: " msg 118 } 119 120 function array_size(arr, i,c) { 121 c = 0 122 for (i in arr) 123 c++ 124 return c 125 } 126 127 /^Table:/ { 128 print "/* " $0 " */" 129 if (tname != "") 130 semantic_error("Hit Table: bef 131 } 132 133 /^Referrer:/ { 134 if (NF != 1) { 135 # escape opcode table 136 ref = "" 137 for (i = 2; i <= NF; i++) 138 ref = ref $i 139 eid = escape[ref] 140 tname = sprintf("inat_escape_t 141 } 142 } 143 144 /^AVXcode:/ { 145 if (NF != 1) { 146 # AVX/escape opcode table 147 aid = $2 148 if (gaid <= aid) 149 gaid = aid + 1 150 if (tname == "") # AVX 151 tname = sprintf("inat_ 152 } 153 if (aid == -1 && eid == -1) # prim 154 tname = "inat_primary_table" 155 } 156 157 /^GrpTable:/ { 158 print "/* " $0 " */" 159 if (!($2 in group)) 160 semantic_error("No group: " $2 161 gid = group[$2] 162 tname = "inat_group_table_" gid 163 } 164 165 function print_table(tbl,name,fmt,n) 166 { 167 print "const insn_attr_t " name " = {" 168 for (i = 0; i < n; i++) { 169 id = sprintf(fmt, i) 170 if (tbl[id]) 171 print " [" id "] = " t 172 } 173 print "};" 174 } 175 176 /^EndTable/ { 177 if (gid != -1) { 178 # print group tables 179 if (array_size(table) != 0) { 180 print_table(table, tna 181 "0x%x", 8) 182 gtable[gid,0] = tname 183 } 184 if (array_size(lptable1) != 0) 185 print_table(lptable1, 186 "0x%x", 8) 187 gtable[gid,1] = tname 188 } 189 if (array_size(lptable2) != 0) 190 print_table(lptable2, 191 "0x%x", 8) 192 gtable[gid,2] = tname 193 } 194 if (array_size(lptable3) != 0) 195 print_table(lptable3, 196 "0x%x", 8) 197 gtable[gid,3] = tname 198 } 199 } else { 200 # print primary/escaped tables 201 if (array_size(table) != 0) { 202 print_table(table, tna 203 "0x%02x", 204 etable[eid,0] = tname 205 if (aid >= 0) 206 atable[aid,0] 207 } 208 if (array_size(lptable1) != 0) 209 print_table(lptable1,t 210 "0x%02x", 211 etable[eid,1] = tname 212 if (aid >= 0) 213 atable[aid,1] 214 } 215 if (array_size(lptable2) != 0) 216 print_table(lptable2,t 217 "0x%02x", 218 etable[eid,2] = tname 219 if (aid >= 0) 220 atable[aid,2] 221 } 222 if (array_size(lptable3) != 0) 223 print_table(lptable3,t 224 "0x%02x", 225 etable[eid,3] = tname 226 if (aid >= 0) 227 atable[aid,3] 228 } 229 } 230 print "" 231 clear_vars() 232 } 233 234 function add_flags(old,new) { 235 if (old && new) 236 return old " | " new 237 else if (old) 238 return old 239 else 240 return new 241 } 242 243 # convert operands to flags. 244 function convert_operands(count,opnd, i, 245 { 246 imm = null 247 mod = null 248 for (j = 1; j <= count; j++) { 249 i = opnd[j] 250 if (match(i, imm_expr) == 1) { 251 if (!imm_flag[i]) 252 semantic_error 253 if (imm) { 254 if (i != "Ib") 255 semant 256 imm = add_flag 257 } else 258 imm = imm_flag 259 } else if (match(i, modrm_expr 260 mod = "INAT_MODRM" 261 } 262 return add_flags(imm, mod) 263 } 264 265 /^[0-9a-f]+:/ { 266 if (NR == 1) 267 next 268 # get index 269 idx = "0x" substr($1, 1, index($1,":") 270 if (idx in table) 271 semantic_error("Redefine " idx 272 273 # check if escaped opcode 274 if ("escape" == $2) { 275 if ($3 != "#") 276 semantic_error("No esc 277 ref = "" 278 for (i = 4; i <= NF; i++) 279 ref = ref $i 280 if (ref in escape) 281 semantic_error("Redefi 282 escape[ref] = geid 283 geid++ 284 table[idx] = "INAT_MAKE_ESCAPE 285 next 286 } 287 288 variant = null 289 # converts 290 i = 2 291 while (i <= NF) { 292 opcode = $(i++) 293 delete opnds 294 ext = null 295 flags = null 296 opnd = null 297 # parse one opcode 298 if (match($i, opnd_expr)) { 299 opnd = $i 300 count = split($(i++), 301 flags = convert_operan 302 } 303 if (match($i, ext_expr)) 304 ext = $(i++) 305 if (match($i, sep_expr)) 306 i++ 307 else if (i < NF) 308 semantic_error($i " is 309 310 # check if group opcode 311 if (match(opcode, group_expr)) 312 if (!(opcode in group) 313 group[opcode] 314 ggid++ 315 } 316 flags = add_flags(flag 317 } 318 # check force(or default) 64bi 319 if (match(ext, force64_expr)) 320 flags = add_flags(flag 321 322 # check REX2 not allowed 323 if (match(ext, no_rex2_expr)) 324 flags = add_flags(flag 325 326 # check REX prefix 327 if (match(opcode, rex_expr)) 328 flags = add_flags(flag 329 330 # check coprocessor escape : T 331 if (match(opcode, fpu_expr)) 332 flags = add_flags(flag 333 334 # check VEX codes 335 if (match(ext, evexonly_expr)) 336 flags = add_flags(flag 337 else if (match(ext, evex_scala 338 flags = add_flags(flag 339 else if (match(ext, vexonly_ex 340 flags = add_flags(flag 341 else if (match(ext, vexok_expr 342 flags = add_flags(flag 343 344 # check prefixes 345 if (match(ext, prefix_expr)) { 346 if (!prefix_num[opcode 347 semantic_error 348 flags = add_flags(flag 349 } 350 if (length(flags) == 0) 351 continue 352 # check if last prefix 353 if (match(ext, lprefix1_expr)) 354 lptable1[idx] = add_fl 355 variant = "INAT_VARIAN 356 } 357 if (match(ext, lprefix2_expr)) 358 lptable2[idx] = add_fl 359 variant = "INAT_VARIAN 360 } 361 if (match(ext, lprefix3_expr)) 362 lptable3[idx] = add_fl 363 variant = "INAT_VARIAN 364 } 365 if (match(ext, rex2_expr)) 366 table[idx] = add_flags 367 if (!match(ext, lprefix_expr)) 368 table[idx] = add_flags 369 } 370 } 371 if (variant) 372 table[idx] = add_flags(table[i 373 } 374 375 END { 376 if (awkchecked != "") 377 exit 1 378 379 print "#ifndef __BOOT_COMPRESSED\n" 380 381 # print escape opcode map's array 382 print "/* Escape opcode map array */" 383 print "const insn_attr_t * const inat_ 384 "[INAT_LSTPFX_MAX + 1] = {" 385 for (i = 0; i < geid; i++) 386 for (j = 0; j < max_lprefix; j 387 if (etable[i,j]) 388 print " ["i"][ 389 print "};\n" 390 # print group opcode map's array 391 print "/* Group opcode map array */" 392 print "const insn_attr_t * const inat_ 393 "[INAT_LSTPFX_MAX + 1] = {" 394 for (i = 0; i < ggid; i++) 395 for (j = 0; j < max_lprefix; j 396 if (gtable[i,j]) 397 print " ["i"][ 398 print "};\n" 399 # print AVX opcode map's array 400 print "/* AVX opcode map array */" 401 print "const insn_attr_t * const inat_ 402 "[INAT_LSTPFX_MAX + 1] = {" 403 for (i = 0; i < gaid; i++) 404 for (j = 0; j < max_lprefix; j 405 if (atable[i,j]) 406 print " ["i"][ 407 print "};\n" 408 409 print "#else /* !__BOOT_COMPRESSED */\ 410 411 print "/* Escape opcode map array */" 412 print "static const insn_attr_t *inat_ 413 "[INAT_LSTPFX_MAX + 1];" 414 print "" 415 416 print "/* Group opcode map array */" 417 print "static const insn_attr_t *inat_ 418 "[INAT_LSTPFX_MAX + 1];" 419 print "" 420 421 print "/* AVX opcode map array */" 422 print "static const insn_attr_t *inat_ 423 "[INAT_LSTPFX_MAX + 1];" 424 print "" 425 426 print "static void inat_init_tables(vo 427 print "{" 428 429 # print escape opcode map's array 430 print "\t/* Print Escape opcode map ar 431 for (i = 0; i < geid; i++) 432 for (j = 0; j < max_lprefix; j 433 if (etable[i,j]) 434 print "\tinat_ 435 print "" 436 437 # print group opcode map's array 438 print "\t/* Print Group opcode map arr 439 for (i = 0; i < ggid; i++) 440 for (j = 0; j < max_lprefix; j 441 if (gtable[i,j]) 442 print "\tinat_ 443 print "" 444 # print AVX opcode map's array 445 print "\t/* Print AVX opcode map array 446 for (i = 0; i < gaid; i++) 447 for (j = 0; j < max_lprefix; j 448 if (atable[i,j]) 449 print "\tinat_ 450 451 print "}" 452 print "#endif" 453 } 454
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.