diff options
author | Masami Hiramatsu <mhiramat@redhat.com> | 2009-10-27 16:42:27 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-10-29 03:47:46 -0400 |
commit | e0e492e99b372c6990a5daca9e4683c341f1330e (patch) | |
tree | 79704aa82391ff2f54d92fe11b1b7958b09a5bb8 /arch/x86/tools | |
parent | 82cb57028c864822c5a260f806d051e2ce28c86a (diff) |
x86: AVX instruction set decoder support
Add Intel AVX(Advanced Vector Extensions) instruction set
support to x86 instruction decoder. This adds insn.vex_prefix
field for storing VEX prefixes, and introduces some original
tags for expressing opcodes attributes.
Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Jim Keniston <jkenisto@us.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Frank Ch. Eigler <fche@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jason Baron <jbaron@redhat.com>
Cc: K.Prasad <prasad@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
LKML-Reference: <20091027204226.30545.23451.stgit@harusame>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/tools')
-rw-r--r-- | arch/x86/tools/gen-insn-attr-x86.awk | 94 |
1 files changed, 70 insertions, 24 deletions
diff --git a/arch/x86/tools/gen-insn-attr-x86.awk b/arch/x86/tools/gen-insn-attr-x86.awk index 7d5492951e22..e34e92a28eb6 100644 --- a/arch/x86/tools/gen-insn-attr-x86.awk +++ b/arch/x86/tools/gen-insn-attr-x86.awk | |||
@@ -13,6 +13,18 @@ function check_awk_implement() { | |||
13 | return "" | 13 | return "" |
14 | } | 14 | } |
15 | 15 | ||
16 | # Clear working vars | ||
17 | function clear_vars() { | ||
18 | delete table | ||
19 | delete lptable2 | ||
20 | delete lptable1 | ||
21 | delete lptable3 | ||
22 | eid = -1 # escape id | ||
23 | gid = -1 # group id | ||
24 | aid = -1 # AVX id | ||
25 | tname = "" | ||
26 | } | ||
27 | |||
16 | BEGIN { | 28 | BEGIN { |
17 | # Implementation error checking | 29 | # Implementation error checking |
18 | awkchecked = check_awk_implement() | 30 | awkchecked = check_awk_implement() |
@@ -24,11 +36,15 @@ BEGIN { | |||
24 | 36 | ||
25 | # Setup generating tables | 37 | # Setup generating tables |
26 | print "/* x86 opcode map generated from x86-opcode-map.txt */" | 38 | print "/* x86 opcode map generated from x86-opcode-map.txt */" |
27 | print "/* Do not change this code. */" | 39 | print "/* Do not change this code. */\n" |
28 | ggid = 1 | 40 | ggid = 1 |
29 | geid = 1 | 41 | geid = 1 |
42 | gaid = 0 | ||
43 | delete etable | ||
44 | delete gtable | ||
45 | delete atable | ||
30 | 46 | ||
31 | opnd_expr = "^[[:alpha:]]" | 47 | opnd_expr = "^[[:alpha:]/]" |
32 | ext_expr = "^\\(" | 48 | ext_expr = "^\\(" |
33 | sep_expr = "^\\|$" | 49 | sep_expr = "^\\|$" |
34 | group_expr = "^Grp[[:alnum:]]+" | 50 | group_expr = "^Grp[[:alnum:]]+" |
@@ -46,19 +62,19 @@ BEGIN { | |||
46 | imm_flag["Ob"] = "INAT_MOFFSET" | 62 | imm_flag["Ob"] = "INAT_MOFFSET" |
47 | imm_flag["Ov"] = "INAT_MOFFSET" | 63 | imm_flag["Ov"] = "INAT_MOFFSET" |
48 | 64 | ||
49 | modrm_expr = "^([CDEGMNPQRSUVW][[:lower:]]+|NTA|T[012])" | 65 | modrm_expr = "^([CDEGMNPQRSUVW/][[:lower:]]+|NTA|T[012])" |
50 | force64_expr = "\\([df]64\\)" | 66 | force64_expr = "\\([df]64\\)" |
51 | rex_expr = "^REX(\\.[XRWB]+)*" | 67 | rex_expr = "^REX(\\.[XRWB]+)*" |
52 | fpu_expr = "^ESC" # TODO | 68 | fpu_expr = "^ESC" # TODO |
53 | 69 | ||
54 | lprefix1_expr = "\\(66\\)" | 70 | lprefix1_expr = "\\(66\\)" |
55 | delete lptable1 | 71 | lprefix2_expr = "\\(F3\\)" |
56 | lprefix2_expr = "\\(F2\\)" | 72 | lprefix3_expr = "\\(F2\\)" |
57 | delete lptable2 | ||
58 | lprefix3_expr = "\\(F3\\)" | ||
59 | delete lptable3 | ||
60 | max_lprefix = 4 | 73 | max_lprefix = 4 |
61 | 74 | ||
75 | vexok_expr = "\\(VEX\\)" | ||
76 | vexonly_expr = "\\(oVEX\\)" | ||
77 | |||
62 | prefix_expr = "\\(Prefix\\)" | 78 | prefix_expr = "\\(Prefix\\)" |
63 | prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ" | 79 | prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ" |
64 | prefix_num["REPNE"] = "INAT_PFX_REPNE" | 80 | prefix_num["REPNE"] = "INAT_PFX_REPNE" |
@@ -71,12 +87,10 @@ BEGIN { | |||
71 | prefix_num["SEG=GS"] = "INAT_PFX_GS" | 87 | prefix_num["SEG=GS"] = "INAT_PFX_GS" |
72 | prefix_num["SEG=SS"] = "INAT_PFX_SS" | 88 | prefix_num["SEG=SS"] = "INAT_PFX_SS" |
73 | prefix_num["Address-Size"] = "INAT_PFX_ADDRSZ" | 89 | prefix_num["Address-Size"] = "INAT_PFX_ADDRSZ" |
90 | prefix_num["2bytes-VEX"] = "INAT_PFX_VEX2" | ||
91 | prefix_num["3bytes-VEX"] = "INAT_PFX_VEX3" | ||
74 | 92 | ||
75 | delete table | 93 | clear_vars() |
76 | delete etable | ||
77 | delete gtable | ||
78 | eid = -1 | ||
79 | gid = -1 | ||
80 | } | 94 | } |
81 | 95 | ||
82 | function semantic_error(msg) { | 96 | function semantic_error(msg) { |
@@ -97,14 +111,12 @@ function array_size(arr, i,c) { | |||
97 | 111 | ||
98 | /^Table:/ { | 112 | /^Table:/ { |
99 | print "/* " $0 " */" | 113 | print "/* " $0 " */" |
114 | if (tname != "") | ||
115 | semantic_error("Hit Table: before EndTable:."); | ||
100 | } | 116 | } |
101 | 117 | ||
102 | /^Referrer:/ { | 118 | /^Referrer:/ { |
103 | if (NF == 1) { | 119 | if (NF != 1) { |
104 | # primary opcode table | ||
105 | tname = "inat_primary_table" | ||
106 | eid = -1 | ||
107 | } else { | ||
108 | # escape opcode table | 120 | # escape opcode table |
109 | ref = "" | 121 | ref = "" |
110 | for (i = 2; i <= NF; i++) | 122 | for (i = 2; i <= NF; i++) |
@@ -114,6 +126,19 @@ function array_size(arr, i,c) { | |||
114 | } | 126 | } |
115 | } | 127 | } |
116 | 128 | ||
129 | /^AVXcode:/ { | ||
130 | if (NF != 1) { | ||
131 | # AVX/escape opcode table | ||
132 | aid = $2 | ||
133 | if (gaid <= aid) | ||
134 | gaid = aid + 1 | ||
135 | if (tname == "") # AVX only opcode table | ||
136 | tname = sprintf("inat_avx_table_%d", $2) | ||
137 | } | ||
138 | if (aid == -1 && eid == -1) # primary opcode table | ||
139 | tname = "inat_primary_table" | ||
140 | } | ||
141 | |||
117 | /^GrpTable:/ { | 142 | /^GrpTable:/ { |
118 | print "/* " $0 " */" | 143 | print "/* " $0 " */" |
119 | if (!($2 in group)) | 144 | if (!($2 in group)) |
@@ -162,30 +187,33 @@ function print_table(tbl,name,fmt,n) | |||
162 | print_table(table, tname "[INAT_OPCODE_TABLE_SIZE]", | 187 | print_table(table, tname "[INAT_OPCODE_TABLE_SIZE]", |
163 | "0x%02x", 256) | 188 | "0x%02x", 256) |
164 | etable[eid,0] = tname | 189 | etable[eid,0] = tname |
190 | if (aid >= 0) | ||
191 | atable[aid,0] = tname | ||
165 | } | 192 | } |
166 | if (array_size(lptable1) != 0) { | 193 | if (array_size(lptable1) != 0) { |
167 | print_table(lptable1,tname "_1[INAT_OPCODE_TABLE_SIZE]", | 194 | print_table(lptable1,tname "_1[INAT_OPCODE_TABLE_SIZE]", |
168 | "0x%02x", 256) | 195 | "0x%02x", 256) |
169 | etable[eid,1] = tname "_1" | 196 | etable[eid,1] = tname "_1" |
197 | if (aid >= 0) | ||
198 | atable[aid,1] = tname "_1" | ||
170 | } | 199 | } |
171 | if (array_size(lptable2) != 0) { | 200 | if (array_size(lptable2) != 0) { |
172 | print_table(lptable2,tname "_2[INAT_OPCODE_TABLE_SIZE]", | 201 | print_table(lptable2,tname "_2[INAT_OPCODE_TABLE_SIZE]", |
173 | "0x%02x", 256) | 202 | "0x%02x", 256) |
174 | etable[eid,2] = tname "_2" | 203 | etable[eid,2] = tname "_2" |
204 | if (aid >= 0) | ||
205 | atable[aid,2] = tname "_2" | ||
175 | } | 206 | } |
176 | if (array_size(lptable3) != 0) { | 207 | if (array_size(lptable3) != 0) { |
177 | print_table(lptable3,tname "_3[INAT_OPCODE_TABLE_SIZE]", | 208 | print_table(lptable3,tname "_3[INAT_OPCODE_TABLE_SIZE]", |
178 | "0x%02x", 256) | 209 | "0x%02x", 256) |
179 | etable[eid,3] = tname "_3" | 210 | etable[eid,3] = tname "_3" |
211 | if (aid >= 0) | ||
212 | atable[aid,3] = tname "_3" | ||
180 | } | 213 | } |
181 | } | 214 | } |
182 | print "" | 215 | print "" |
183 | delete table | 216 | clear_vars() |
184 | delete lptable1 | ||
185 | delete lptable2 | ||
186 | delete lptable3 | ||
187 | gid = -1 | ||
188 | eid = -1 | ||
189 | } | 217 | } |
190 | 218 | ||
191 | function add_flags(old,new) { | 219 | function add_flags(old,new) { |
@@ -284,6 +312,14 @@ function convert_operands(opnd, i,imm,mod) | |||
284 | if (match(opcode, fpu_expr)) | 312 | if (match(opcode, fpu_expr)) |
285 | flags = add_flags(flags, "INAT_MODRM") | 313 | flags = add_flags(flags, "INAT_MODRM") |
286 | 314 | ||
315 | # check VEX only code | ||
316 | if (match(ext, vexonly_expr)) | ||
317 | flags = add_flags(flags, "INAT_VEXOK | INAT_VEXONLY") | ||
318 | |||
319 | # check VEX only code | ||
320 | if (match(ext, vexok_expr)) | ||
321 | flags = add_flags(flags, "INAT_VEXOK") | ||
322 | |||
287 | # check prefixes | 323 | # check prefixes |
288 | if (match(ext, prefix_expr)) { | 324 | if (match(ext, prefix_expr)) { |
289 | if (!prefix_num[opcode]) | 325 | if (!prefix_num[opcode]) |
@@ -330,5 +366,15 @@ END { | |||
330 | for (j = 0; j < max_lprefix; j++) | 366 | for (j = 0; j < max_lprefix; j++) |
331 | if (gtable[i,j]) | 367 | if (gtable[i,j]) |
332 | print " ["i"]["j"] = "gtable[i,j]"," | 368 | print " ["i"]["j"] = "gtable[i,j]"," |
369 | print "};\n" | ||
370 | # print AVX opcode map's array | ||
371 | print "/* AVX opcode map array */" | ||
372 | print "const insn_attr_t const *inat_avx_tables[X86_VEX_M_MAX + 1]"\ | ||
373 | "[INAT_LSTPFX_MAX + 1] = {" | ||
374 | for (i = 0; i < gaid; i++) | ||
375 | for (j = 0; j < max_lprefix; j++) | ||
376 | if (atable[i,j]) | ||
377 | print " ["i"]["j"] = "atable[i,j]"," | ||
333 | print "};" | 378 | print "};" |
334 | } | 379 | } |
380 | |||