aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/lib/insn.c
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@redhat.com>2009-10-27 16:42:27 -0400
committerIngo Molnar <mingo@elte.hu>2009-10-29 03:47:46 -0400
commite0e492e99b372c6990a5daca9e4683c341f1330e (patch)
tree79704aa82391ff2f54d92fe11b1b7958b09a5bb8 /arch/x86/lib/insn.c
parent82cb57028c864822c5a260f806d051e2ce28c86a (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/lib/insn.c')
-rw-r--r--arch/x86/lib/insn.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/arch/x86/lib/insn.c b/arch/x86/lib/insn.c
index 9f483179a8a6..9f33b984d0ef 100644
--- a/arch/x86/lib/insn.c
+++ b/arch/x86/lib/insn.c
@@ -28,6 +28,9 @@
28#define peek_next(t, insn) \ 28#define peek_next(t, insn) \
29 ({t r; r = *(t*)insn->next_byte; r; }) 29 ({t r; r = *(t*)insn->next_byte; r; })
30 30
31#define peek_nbyte_next(t, insn, n) \
32 ({t r; r = *(t*)((insn)->next_byte + n); r; })
33
31/** 34/**
32 * insn_init() - initialize struct insn 35 * insn_init() - initialize struct insn
33 * @insn: &struct insn to be initialized 36 * @insn: &struct insn to be initialized
@@ -107,6 +110,7 @@ found:
107 insn->prefixes.bytes[3] = lb; 110 insn->prefixes.bytes[3] = lb;
108 } 111 }
109 112
113 /* Decode REX prefix */
110 if (insn->x86_64) { 114 if (insn->x86_64) {
111 b = peek_next(insn_byte_t, insn); 115 b = peek_next(insn_byte_t, insn);
112 attr = inat_get_opcode_attribute(b); 116 attr = inat_get_opcode_attribute(b);
@@ -120,6 +124,39 @@ found:
120 } 124 }
121 } 125 }
122 insn->rex_prefix.got = 1; 126 insn->rex_prefix.got = 1;
127
128 /* Decode VEX prefix */
129 b = peek_next(insn_byte_t, insn);
130 attr = inat_get_opcode_attribute(b);
131 if (inat_is_vex_prefix(attr)) {
132 insn_byte_t b2 = peek_nbyte_next(insn_byte_t, insn, 1);
133 if (!insn->x86_64) {
134 /*
135 * In 32-bits mode, if the [7:6] bits (mod bits of
136 * ModRM) on the second byte are not 11b, it is
137 * LDS or LES.
138 */
139 if (X86_MODRM_MOD(b2) != 3)
140 goto vex_end;
141 }
142 insn->vex_prefix.bytes[0] = b;
143 insn->vex_prefix.bytes[1] = b2;
144 if (inat_is_vex3_prefix(attr)) {
145 b2 = peek_nbyte_next(insn_byte_t, insn, 2);
146 insn->vex_prefix.bytes[2] = b2;
147 insn->vex_prefix.nbytes = 3;
148 insn->next_byte += 3;
149 if (insn->x86_64 && X86_VEX_W(b2))
150 /* VEX.W overrides opnd_size */
151 insn->opnd_bytes = 8;
152 } else {
153 insn->vex_prefix.nbytes = 2;
154 insn->next_byte += 2;
155 }
156 }
157vex_end:
158 insn->vex_prefix.got = 1;
159
123 prefixes->got = 1; 160 prefixes->got = 1;
124 return; 161 return;
125} 162}
@@ -147,6 +184,18 @@ void insn_get_opcode(struct insn *insn)
147 op = get_next(insn_byte_t, insn); 184 op = get_next(insn_byte_t, insn);
148 opcode->bytes[0] = op; 185 opcode->bytes[0] = op;
149 opcode->nbytes = 1; 186 opcode->nbytes = 1;
187
188 /* Check if there is VEX prefix or not */
189 if (insn_is_avx(insn)) {
190 insn_byte_t m, p;
191 m = insn_vex_m_bits(insn);
192 p = insn_vex_p_bits(insn);
193 insn->attr = inat_get_avx_attribute(op, m, p);
194 if (!inat_accept_vex(insn->attr))
195 insn->attr = 0; /* This instruction is bad */
196 goto end; /* VEX has only 1 byte for opcode */
197 }
198
150 insn->attr = inat_get_opcode_attribute(op); 199 insn->attr = inat_get_opcode_attribute(op);
151 while (inat_is_escape(insn->attr)) { 200 while (inat_is_escape(insn->attr)) {
152 /* Get escaped opcode */ 201 /* Get escaped opcode */
@@ -155,6 +204,9 @@ void insn_get_opcode(struct insn *insn)
155 pfx = insn_last_prefix(insn); 204 pfx = insn_last_prefix(insn);
156 insn->attr = inat_get_escape_attribute(op, pfx, insn->attr); 205 insn->attr = inat_get_escape_attribute(op, pfx, insn->attr);
157 } 206 }
207 if (inat_must_vex(insn->attr))
208 insn->attr = 0; /* This instruction is bad */
209end:
158 opcode->got = 1; 210 opcode->got = 1;
159} 211}
160 212