gen-insn-attr-x86.awk 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. #!/bin/awk -f
  2. # gen-insn-attr-x86.awk: Instruction attribute table generator
  3. # Written by Masami Hiramatsu <mhiramat@redhat.com>
  4. #
  5. # Usage: awk -f gen-insn-attr-x86.awk x86-opcode-map.txt > inat-tables.c
  6. BEGIN {
  7. print "/* x86 opcode map generated from x86-opcode-map.txt */"
  8. print "/* Do not change this code. */"
  9. ggid = 1
  10. geid = 1
  11. opnd_expr = "^[[:alpha:]]"
  12. ext_expr = "^\\("
  13. sep_expr = "^\\|$"
  14. group_expr = "^Grp[[:alnum:]]+"
  15. imm_expr = "^[IJAO][[:lower:]]"
  16. imm_flag["Ib"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
  17. imm_flag["Jb"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
  18. imm_flag["Iw"] = "INAT_MAKE_IMM(INAT_IMM_WORD)"
  19. imm_flag["Id"] = "INAT_MAKE_IMM(INAT_IMM_DWORD)"
  20. imm_flag["Iq"] = "INAT_MAKE_IMM(INAT_IMM_QWORD)"
  21. imm_flag["Ap"] = "INAT_MAKE_IMM(INAT_IMM_PTR)"
  22. imm_flag["Iz"] = "INAT_MAKE_IMM(INAT_IMM_VWORD32)"
  23. imm_flag["Jz"] = "INAT_MAKE_IMM(INAT_IMM_VWORD32)"
  24. imm_flag["Iv"] = "INAT_MAKE_IMM(INAT_IMM_VWORD)"
  25. imm_flag["Ob"] = "INAT_MOFFSET"
  26. imm_flag["Ov"] = "INAT_MOFFSET"
  27. modrm_expr = "^([CDEGMNPQRSUVW][[:lower:]]+|NTA|T[012])"
  28. force64_expr = "\\([df]64\\)"
  29. rex_expr = "^REX(\\.[XRWB]+)*"
  30. fpu_expr = "^ESC" # TODO
  31. lprefix1_expr = "\\(66\\)"
  32. delete lptable1
  33. lprefix2_expr = "\\(F2\\)"
  34. delete lptable2
  35. lprefix3_expr = "\\(F3\\)"
  36. delete lptable3
  37. max_lprefix = 4
  38. prefix_expr = "\\(Prefix\\)"
  39. prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ"
  40. prefix_num["REPNE"] = "INAT_PFX_REPNE"
  41. prefix_num["REP/REPE"] = "INAT_PFX_REPE"
  42. prefix_num["LOCK"] = "INAT_PFX_LOCK"
  43. prefix_num["SEG=CS"] = "INAT_PFX_CS"
  44. prefix_num["SEG=DS"] = "INAT_PFX_DS"
  45. prefix_num["SEG=ES"] = "INAT_PFX_ES"
  46. prefix_num["SEG=FS"] = "INAT_PFX_FS"
  47. prefix_num["SEG=GS"] = "INAT_PFX_GS"
  48. prefix_num["SEG=SS"] = "INAT_PFX_SS"
  49. prefix_num["Address-Size"] = "INAT_PFX_ADDRSZ"
  50. delete table
  51. delete etable
  52. delete gtable
  53. eid = -1
  54. gid = -1
  55. }
  56. function semantic_error(msg) {
  57. print "Semantic error at " NR ": " msg > "/dev/stderr"
  58. exit 1
  59. }
  60. function debug(msg) {
  61. print "DEBUG: " msg
  62. }
  63. function array_size(arr, i,c) {
  64. c = 0
  65. for (i in arr)
  66. c++
  67. return c
  68. }
  69. /^Table:/ {
  70. print "/* " $0 " */"
  71. }
  72. /^Referrer:/ {
  73. if (NF == 1) {
  74. # primary opcode table
  75. tname = "inat_primary_table"
  76. eid = -1
  77. } else {
  78. # escape opcode table
  79. ref = ""
  80. for (i = 2; i <= NF; i++)
  81. ref = ref $i
  82. eid = escape[ref]
  83. tname = sprintf("inat_escape_table_%d", eid)
  84. }
  85. }
  86. /^GrpTable:/ {
  87. print "/* " $0 " */"
  88. if (!($2 in group))
  89. semantic_error("No group: " $2 )
  90. gid = group[$2]
  91. tname = "inat_group_table_" gid
  92. }
  93. function print_table(tbl,name,fmt,n)
  94. {
  95. print "const insn_attr_t " name " = {"
  96. for (i = 0; i < n; i++) {
  97. id = sprintf(fmt, i)
  98. if (tbl[id])
  99. print " [" id "] = " tbl[id] ","
  100. }
  101. print "};"
  102. }
  103. /^EndTable/ {
  104. if (gid != -1) {
  105. # print group tables
  106. if (array_size(table) != 0) {
  107. print_table(table, tname "[INAT_GROUP_TABLE_SIZE]",
  108. "0x%x", 8)
  109. gtable[gid,0] = tname
  110. }
  111. if (array_size(lptable1) != 0) {
  112. print_table(lptable1, tname "_1[INAT_GROUP_TABLE_SIZE]",
  113. "0x%x", 8)
  114. gtable[gid,1] = tname "_1"
  115. }
  116. if (array_size(lptable2) != 0) {
  117. print_table(lptable2, tname "_2[INAT_GROUP_TABLE_SIZE]",
  118. "0x%x", 8)
  119. gtable[gid,2] = tname "_2"
  120. }
  121. if (array_size(lptable3) != 0) {
  122. print_table(lptable3, tname "_3[INAT_GROUP_TABLE_SIZE]",
  123. "0x%x", 8)
  124. gtable[gid,3] = tname "_3"
  125. }
  126. } else {
  127. # print primary/escaped tables
  128. if (array_size(table) != 0) {
  129. print_table(table, tname "[INAT_OPCODE_TABLE_SIZE]",
  130. "0x%02x", 256)
  131. etable[eid,0] = tname
  132. }
  133. if (array_size(lptable1) != 0) {
  134. print_table(lptable1,tname "_1[INAT_OPCODE_TABLE_SIZE]",
  135. "0x%02x", 256)
  136. etable[eid,1] = tname "_1"
  137. }
  138. if (array_size(lptable2) != 0) {
  139. print_table(lptable2,tname "_2[INAT_OPCODE_TABLE_SIZE]",
  140. "0x%02x", 256)
  141. etable[eid,2] = tname "_2"
  142. }
  143. if (array_size(lptable3) != 0) {
  144. print_table(lptable3,tname "_3[INAT_OPCODE_TABLE_SIZE]",
  145. "0x%02x", 256)
  146. etable[eid,3] = tname "_3"
  147. }
  148. }
  149. print ""
  150. delete table
  151. delete lptable1
  152. delete lptable2
  153. delete lptable3
  154. gid = -1
  155. eid = -1
  156. }
  157. function add_flags(old,new) {
  158. if (old && new)
  159. return old " | " new
  160. else if (old)
  161. return old
  162. else
  163. return new
  164. }
  165. # convert operands to flags.
  166. function convert_operands(opnd, i,imm,mod)
  167. {
  168. imm = null
  169. mod = null
  170. for (i in opnd) {
  171. i = opnd[i]
  172. if (match(i, imm_expr) == 1) {
  173. if (!imm_flag[i])
  174. semantic_error("Unknown imm opnd: " i)
  175. if (imm) {
  176. if (i != "Ib")
  177. semantic_error("Second IMM error")
  178. imm = add_flags(imm, "INAT_SCNDIMM")
  179. } else
  180. imm = imm_flag[i]
  181. } else if (match(i, modrm_expr))
  182. mod = "INAT_MODRM"
  183. }
  184. return add_flags(imm, mod)
  185. }
  186. /^[0-9a-f]+\:/ {
  187. if (NR == 1)
  188. next
  189. # get index
  190. idx = "0x" substr($1, 1, index($1,":") - 1)
  191. if (idx in table)
  192. semantic_error("Redefine " idx " in " tname)
  193. # check if escaped opcode
  194. if ("escape" == $2) {
  195. if ($3 != "#")
  196. semantic_error("No escaped name")
  197. ref = ""
  198. for (i = 4; i <= NF; i++)
  199. ref = ref $i
  200. if (ref in escape)
  201. semantic_error("Redefine escape (" ref ")")
  202. escape[ref] = geid
  203. geid++
  204. table[idx] = "INAT_MAKE_ESCAPE(" escape[ref] ")"
  205. next
  206. }
  207. variant = null
  208. # converts
  209. i = 2
  210. while (i <= NF) {
  211. opcode = $(i++)
  212. delete opnds
  213. ext = null
  214. flags = null
  215. opnd = null
  216. # parse one opcode
  217. if (match($i, opnd_expr)) {
  218. opnd = $i
  219. split($(i++), opnds, ",")
  220. flags = convert_operands(opnds)
  221. }
  222. if (match($i, ext_expr))
  223. ext = $(i++)
  224. if (match($i, sep_expr))
  225. i++
  226. else if (i < NF)
  227. semantic_error($i " is not a separator")
  228. # check if group opcode
  229. if (match(opcode, group_expr)) {
  230. if (!(opcode in group)) {
  231. group[opcode] = ggid
  232. ggid++
  233. }
  234. flags = add_flags(flags, "INAT_MAKE_GROUP(" group[opcode] ")")
  235. }
  236. # check force(or default) 64bit
  237. if (match(ext, force64_expr))
  238. flags = add_flags(flags, "INAT_FORCE64")
  239. # check REX prefix
  240. if (match(opcode, rex_expr))
  241. flags = add_flags(flags, "INAT_REXPFX")
  242. # check coprocessor escape : TODO
  243. if (match(opcode, fpu_expr))
  244. flags = add_flags(flags, "INAT_MODRM")
  245. # check prefixes
  246. if (match(ext, prefix_expr)) {
  247. if (!prefix_num[opcode])
  248. semantic_error("Unknown prefix: " opcode)
  249. flags = add_flags(flags, "INAT_MAKE_PREFIX(" prefix_num[opcode] ")")
  250. }
  251. if (length(flags) == 0)
  252. continue
  253. # check if last prefix
  254. if (match(ext, lprefix1_expr)) {
  255. lptable1[idx] = add_flags(lptable1[idx],flags)
  256. variant = "INAT_VARIANT"
  257. } else if (match(ext, lprefix2_expr)) {
  258. lptable2[idx] = add_flags(lptable2[idx],flags)
  259. variant = "INAT_VARIANT"
  260. } else if (match(ext, lprefix3_expr)) {
  261. lptable3[idx] = add_flags(lptable3[idx],flags)
  262. variant = "INAT_VARIANT"
  263. } else {
  264. table[idx] = add_flags(table[idx],flags)
  265. }
  266. }
  267. if (variant)
  268. table[idx] = add_flags(table[idx],variant)
  269. }
  270. END {
  271. # print escape opcode map's array
  272. print "/* Escape opcode map array */"
  273. print "const insn_attr_t const *inat_escape_tables[INAT_ESC_MAX + 1]" \
  274. "[INAT_LPREFIX_MAX + 1] = {"
  275. for (i = 0; i < geid; i++)
  276. for (j = 0; j < max_lprefix; j++)
  277. if (etable[i,j])
  278. print " ["i"]["j"] = "etable[i,j]","
  279. print "};\n"
  280. # print group opcode map's array
  281. print "/* Group opcode map array */"
  282. print "const insn_attr_t const *inat_group_tables[INAT_GRP_MAX + 1]"\
  283. "[INAT_LPREFIX_MAX + 1] = {"
  284. for (i = 0; i < ggid; i++)
  285. for (j = 0; j < max_lprefix; j++)
  286. if (gtable[i,j])
  287. print " ["i"]["j"] = "gtable[i,j]","
  288. print "};"
  289. }