Added support for AMD instructions to decoder
[dyninst.git] / dyninstAPI / src / arch-ia32.C
1 // $Id: arch-ia32.C,v 1.3 2002/06/13 00:37:06 gaburici Exp $
2
3 // Official documentation used:    - IA-32 Intel Architecture Software Developer Manual
4 //                                   volume 2: Instruction Set Reference
5 // Unofficial documentation used:  - www.sandpile.org/ia32
6 //                                 - NASM documentation
7
8 #include <assert.h>
9 #include <stdio.h>
10 #include "common/h/Types.h"
11 #include "arch-ia32.h"
12
13 // tables and pseudotables
14 enum {
15   t_ill=0, t_oneB, t_twoB, t_prefixedSSE, t_coprocEsc, t_grp, t_sse, t_grpsse, t_3dnow, t_done=99
16 };
17
18 #define oneB t_done, 0
19 #define twoB t_done, 0
20
21 // groups
22 enum {
23   Grp1=0, Grp2, Grp3a, Grp3b, Grp4, Grp5, Grp6, Grp7, Grp8, Grp9,
24   Grp11, Grp12, Grp13, Grp14, Grp15, Grp16, GrpAMD
25 };
26
27 // SSE
28 enum {
29   SSE10=0, SSE11, SSE12, SSE13, SSE14, SSE15, SSE16, SSE17,
30   SSE28, SSE29, SSE2A, SSE2B, SSE2C, SSE2D, SSE2E, SSE2F,
31   SSE50, SSE51, SSE52, SSE53, SSE54, SSE55, SSE56, SSE57,
32   SSE58, SSE59, SSE5A, SSE5B, SSE5C, SSE5D, SSE5E, SSE5F,
33   SSE60, SSE61, SSE62, SSE63, SSE64, SSE65, SSE66, SSE67,
34   SSE68, SSE69, SSE6A, SSE6B, SSE6C, SSE6D, SSE6E, SSE6F,
35   SSE70, SSE74, SSE75, SSE76,
36   SSE7E, SSE7F,
37   SSEC2, SSEC4, SSEC5, SSEC6,
38   SSED1, SSED2, SSED3, SSED4, SSED5, SSED6, SSED7,
39   SSED8, SSED9, SSEDA, SSEDB, SSEDC, SSEDD, SSEDE, SSEDF,
40   SSEE0, SSEE1, SSEE2, SSEE3, SSEE4, SSEE5, SSEE6, SSEE7,
41   SSEE8, SSEE9, SSEEA, SSEEB, SSEEC, SSEED, SSEEE, SSEEF,
42   SSEF1, SSEF2, SSEF3, SSEF4, SSEF5, SSEF6, SSEF7,
43   SSEF8, SSEF9, SSEFA, SSEFB, SSEFC, SSEFD, SSEFE
44 };
45
46 // SSE groups
47 enum {
48   G12SSE010B=0, G12SSE100B, G12SSE110B,
49   G13SSE010B, G13SSE100B, G13SSE110B,
50   G14SSE010B, G14SSE011B, G14SSE110B, G14SSE111B,
51 };
52
53 // addressing methods (see appendix A-2)
54 enum { am_A=1, am_C, am_D, am_E, am_F, am_G, am_I, am_J, am_M, am_O,
55        am_P, am_Q, am_R, am_S, am_T, am_V, am_W, am_X, am_Y, am_reg };
56
57 // operand types (idem, but I invented lea for consistency; op_ didn't seem a good idea)
58 // beware that not all operand types in the tables are explained!!! Guess what they mean...
59 enum { op_a=1, op_b, op_c, op_d, op_dq, op_p, op_pd, op_pi, op_ps, 
60        op_q, op_s,  op_sd, op_ss, op_si, op_v, op_w, op_lea };
61
62 // registers [only fancy names, not used right now]
63 enum { r_AH=100, r_BH, r_CH, r_DH, r_AL, r_BL, r_CL, r_DL, 
64        r_DX,
65        r_eAX, r_eBX, r_eCX, r_eDX,
66        r_EAX, r_EBX, r_ECX, r_EDX,
67        r_DS, r_ES, r_FS, r_GS, r_SS,
68        r_eSP, r_eBP, r_eSI, r_eDI,
69        r_ESP, r_EBP, r_ESI, r_EDI };
70
71 #define Zz   { 0, 0 }
72 #define Ap   { am_A, op_p }
73 #define Cd   { am_C, op_d }
74 #define Dd   { am_D, op_d }
75 #define Eb   { am_E, op_b }
76 #define Ed   { am_E, op_d }
77 #define Ep   { am_E, op_p }
78 #define Ev   { am_E, op_v }
79 #define Ew   { am_E, op_w }
80 #define Fv   { am_F, op_v }
81 #define Gb   { am_G, op_b }
82 #define Gd   { am_G, op_d }
83 #define Gv   { am_G, op_v }
84 #define Gw   { am_G, op_w }
85 #define Ib   { am_I, op_b }
86 #define Iv   { am_I, op_v }
87 #define Iw   { am_I, op_w }
88 #define Jb   { am_J, op_b }
89 #define Jv   { am_J, op_v }
90 #define Ma   { am_M, op_a }
91 #define Mlea { am_M, op_lea }
92 #define Mp   { am_M, op_p }
93 #define Ms   { am_M, op_s }
94 #define Mq   { am_M, op_q }
95 #define Ob   { am_O, op_b }
96 #define Ov   { am_O, op_v }
97 #define Pd   { am_P, op_d }
98 #define Pdq  { am_P, op_dq }
99 #define Ppi  { am_P, op_pi }
100 #define Pq   { am_P, op_q }
101 #define Qdq  { am_Q, op_dq }
102 #define Qd   { am_Q, op_d }
103 #define Qpi  { am_Q, op_pi }
104 #define Qq   { am_Q, op_q }
105 #define Rd   { am_R, op_d }
106 #define Td   { am_T, op_d }
107 #define Sw   { am_S, op_w }
108 #define Vdq  { am_V, op_dq }
109 #define Vpd  { am_V, op_pd }
110 #define Vps  { am_V, op_ps }
111 #define Vq   { am_V, op_q }
112 #define Vss  { am_V, op_ss }
113 #define Vsd  { am_V, op_sd }
114 #define Wdq  { am_W, op_dq }
115 #define Wpd  { am_W, op_pd }
116 #define Wps  { am_W, op_ps }
117 #define Wq   { am_W, op_q }
118 #define Ws   { am_W, op_s }
119 #define Wsd  { am_W, op_sd }
120 #define Wss  { am_W, op_ss }
121 #define Xb   { am_X, op_b }
122 #define Xv   { am_X, op_v }
123 #define Yb   { am_Y, op_b }
124 #define Yv   { am_Y, op_v }
125
126 #define AH  { am_reg, r_AH }
127 #define BH  { am_reg, r_BH }
128 #define CH  { am_reg, r_CH }
129 #define DH  { am_reg, r_DH }
130 #define AL  { am_reg, r_AL }
131 #define BL  { am_reg, r_BL }
132 #define CL  { am_reg, r_CL }
133 #define DL  { am_reg, r_DL }
134 #define DX  { am_reg, r_DX }
135 #define eAX { am_reg, r_eAX }
136 #define eBX { am_reg, r_eBX }
137 #define eCX { am_reg, r_eCX }
138 #define eDX { am_reg, r_eDX }
139 #define EAX { am_reg, r_EAX }
140 #define EBX { am_reg, r_EBX }
141 #define ECX { am_reg, r_ECX }
142 #define EDX { am_reg, r_EDX }
143 #define DS  { am_reg, r_DS }
144 #define ES  { am_reg, r_ES }
145 #define FS  { am_reg, r_FS }
146 #define GS  { am_reg, r_GS }
147 #define SS  { am_reg, r_SS }
148 #define eSP { am_reg, r_eSP }
149 #define eBP { am_reg, r_eBP }
150 #define eSI { am_reg, r_eSI }
151 #define eDI { am_reg, r_eDI }
152 #define ESP { am_reg, r_ESP }
153 #define EBP { am_reg, r_EBP }
154 #define ESI { am_reg, r_ESI }
155 #define EDI { am_reg, r_EDI }
156
157
158 struct ia32_operand {
159   unsigned int admet;  // addressing method
160   unsigned int optype; // operand type;
161 };
162
163 // An instruction table entry
164 struct ia32_entry {
165   char *name;                // name of the instruction (for debbuging only)
166   unsigned int otable;       // which opcode table is next; if t_done it is the current one
167   unsigned char tabidx;      // at what index to look, 0 if it easy to deduce from opcode
168   bool hasModRM;             // true if the instruction has a MOD/RM byte
169   ia32_operand operands[3];  // operand descriptors
170   unsigned legacyType;       // legacy type of the instruction (e.g. (IS_CALL | REL_W))
171 };
172
173
174 // oneByteMap: one byte opcode map
175 static ia32_entry oneByteMap[256] = {
176   /* 00 */
177   { "add",  t_done, 0, true, { Eb, Gb, Zz }, 0 },
178   { "add",  t_done, 0, true, { Ev, Gv, Zz }, 0 },
179   { "add",  t_done, 0, true, { Gb, Eb, Zz }, 0 },
180   { "add",  t_done, 0, true, { Gv, Ev, Zz }, 0 },
181   { "add",  t_done, 0, false, { AL, Ib, Zz }, 0 },
182   { "add",  t_done, 0, false, { eAX, Iv, Zz }, 0 },
183   { "push", t_done, 0, false, { ES, Zz, Zz }, 0 },
184   { "pop",  t_done, 0, false, { ES, Zz, Zz }, 0 },
185   /* 08 */
186   { "or",   t_done, 0, true, { Eb, Gb, Zz }, 0 },
187   { "or",   t_done, 0, true, { Ev, Gv, Zz }, 0 },
188   { "or",   t_done, 0, true, { Gb, Eb, Zz }, 0 },
189   { "or",   t_done, 0, true, { Gv, Ev, Zz }, 0 },
190   { "or",   t_done, 0, false, { AL, Ib, Zz }, 0 },
191   { "or",   t_done, 0, false, { eAX, Iv, Zz }, 0 },
192   { "push", t_done, 0, false, { ES, Zz, Zz }, 0 },
193   { 0,      t_twoB, 0, false, { Zz, Zz, Zz }, 0 },
194   /* 10 */
195   { "adc",  t_done, 0, true, { Eb, Gb, Zz }, 0 },
196   { "adc",  t_done, 0, true, { Ev, Gv, Zz }, 0 },
197   { "adc",  t_done, 0, true, { Gb, Eb, Zz }, 0 },
198   { "adc",  t_done, 0, true, { Gv, Ev, Zz }, 0 },
199   { "adc",  t_done, 0, false, { AL, Ib, Zz }, 0 },
200   { "adc",  t_done, 0, false, { eAX, Iv, Zz }, 0 },
201   { "push", t_done, 0, false, { SS, Zz, Zz }, 0 },
202   { "pop",  t_done, 0, false, { SS, Zz, Zz }, 0 },
203   /* 18 */
204   { "sbb",  t_done, 0, true, { Eb, Gb, Zz }, 0 },
205   { "sbb",  t_done, 0, true, { Ev, Gv, Zz }, 0 },
206   { "sbb",  t_done, 0, true, { Gb, Eb, Zz }, 0 },
207   { "sbb",  t_done, 0, true, { Gv, Ev, Zz }, 0 },
208   { "sbb",  t_done, 0, false, { AL, Ib, Zz }, 0 },
209   { "sbb",  t_done, 0, false, { eAX, Iv, Zz }, 0 },
210   { "push", t_done, 0, false, { DS, Zz, Zz }, 0 },
211   { "pop" , t_done, 0, false, { DS, Zz, Zz }, 0 },
212   /* 20 */
213   { "and", t_done, 0, true, { Eb, Gb, Zz }, 0 },
214   { "and", t_done, 0, true, { Ev, Gv, Zz }, 0 },
215   { "and", t_done, 0, true, { Gb, Eb, Zz }, 0 },
216   { "and", t_done, 0, true, { Gv, Ev, Zz }, 0 },
217   { "and", t_done, 0, false, { AL, Ib, Zz }, 0 },
218   { "and", t_done, 0, false, { eAX, Iv, Zz }, 0 },
219   { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 }, // PREFIX_SEG_OVR
220   { "daa", t_done, 0, false, { Zz, Zz, Zz }, 0 },
221   /* 28 */
222   { "sub", t_done, 0, true, { Eb, Gb, Zz }, 0 },
223   { "sub", t_done, 0, true, { Ev, Gv, Zz }, 0 },
224   { "sub", t_done, 0, true, { Gb, Eb, Zz }, 0 },
225   { "sub", t_done, 0, true, { Gv, Ev, Zz }, 0 },
226   { "sub", t_done, 0, false, { AL, Ib, Zz }, 0 },
227   { "sub", t_done, 0, false, { eAX, Iv, Zz }, 0 },
228   { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 }, // PREFIX_SEG_OVR
229   { "das" , t_done, 0, false, { Zz, Zz, Zz }, 0 },
230   /* 30 */
231   { "xor", t_done, 0, true, { Eb, Gb, Zz }, 0 },
232   { "xor", t_done, 0, true, { Ev, Gv, Zz }, 0 },
233   { "xor", t_done, 0, true, { Gb, Eb, Zz }, 0 },
234   { "xor", t_done, 0, true, { Gv, Ev, Zz }, 0 },
235   { "xor", t_done, 0, false, { AL, Ib, Zz }, 0 },
236   { "xor", t_done, 0, false, { eAX, Iv, Zz }, 0 },
237   { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 }, // PREFIX_SEG_OVR
238   { "aaa", t_done, 0, false, { Zz, Zz, Zz }, 0 },
239   /* 38 */
240   { "cmp", t_done, 0, true, { Eb, Gb, Zz }, 0 },
241   { "cmp", t_done, 0, true, { Ev, Gv, Zz }, 0 },
242   { "cmp", t_done, 0, true, { Gb, Eb, Zz }, 0 },
243   { "cmp", t_done, 0, true, { Gv, Ev, Zz }, 0 },
244   { "cmp", t_done, 0, false, { AL, Ib, Zz }, 0 },
245   { "cmp", t_done, 0, false, { eAX, Iv, Zz }, 0 },
246   { 0,     t_ill,  0, false, { Zz, Zz, Zz }, 0 }, // PREFIX_SEG_OVR
247   { "aas", t_done, 0, false, { Zz, Zz, Zz }, 0 },
248   /* 40 */
249   { "inc", t_done, 0, false, { eAX, Zz, Zz }, 0 }, 
250   { "inc", t_done, 0, false, { eCX, Zz, Zz }, 0 },
251   { "inc", t_done, 0, false, { eDX, Zz, Zz }, 0 },
252   { "inc", t_done, 0, false, { eBX, Zz, Zz }, 0 },
253   { "inc", t_done, 0, false, { eSP, Zz, Zz }, 0 },
254   { "inc", t_done, 0, false, { eBP, Zz, Zz }, 0 },
255   { "inc", t_done, 0, false, { eSI, Zz, Zz }, 0 },
256   { "inc", t_done, 0, false, { eDI, Zz, Zz }, 0 },
257   /* 48 */
258   { "dec", t_done, 0, false, { eAX, Zz, Zz }, 0 }, 
259   { "dec", t_done, 0, false, { eCX, Zz, Zz }, 0 },
260   { "dec", t_done, 0, false, { eDX, Zz, Zz }, 0 },
261   { "dec", t_done, 0, false, { eBX, Zz, Zz }, 0 },
262   { "dec", t_done, 0, false, { eSP, Zz, Zz }, 0 },
263   { "dec", t_done, 0, false, { eBP, Zz, Zz }, 0 },
264   { "dec", t_done, 0, false, { eSI, Zz, Zz }, 0 },
265   { "dec", t_done, 0, false, { eDI, Zz, Zz }, 0 },
266   /* 50 */
267   { "push", t_done, 0, false, { eAX, Zz, Zz }, 0 }, 
268   { "push", t_done, 0, false, { eCX, Zz, Zz }, 0 },
269   { "push", t_done, 0, false, { eDX, Zz, Zz }, 0 },
270   { "push", t_done, 0, false, { eBX, Zz, Zz }, 0 },
271   { "push", t_done, 0, false, { eSP, Zz, Zz }, 0 },
272   { "push", t_done, 0, false, { eBP, Zz, Zz }, 0 },
273   { "push", t_done, 0, false, { eSI, Zz, Zz }, 0 },
274   { "push", t_done, 0, false, { eDI, Zz, Zz }, 0 },
275   /* 58 */
276   { "pop", t_done, 0, false, { eAX, Zz, Zz }, 0 }, 
277   { "pop", t_done, 0, false, { eCX, Zz, Zz }, 0 },
278   { "pop", t_done, 0, false, { eDX, Zz, Zz }, 0 },
279   { "pop", t_done, 0, false, { eBX, Zz, Zz }, 0 },
280   { "pop", t_done, 0, false, { eSP, Zz, Zz }, 0 },
281   { "pop", t_done, 0, false, { eBP, Zz, Zz }, 0 },
282   { "pop", t_done, 0, false, { eSI, Zz, Zz }, 0 },
283   { "pop", t_done, 0, false, { eDI, Zz, Zz }, 0 },
284   /* 60 */
285   { "pusha(d)", t_done, 0, false, { Zz, Zz, Zz }, 0 }, 
286   { "popa(d)",  t_done, 0, false, { Zz, Zz, Zz }, 0 },
287   { "bound",    t_done, 0, true, { Gv, Ma, Zz }, 0 },
288   { "arpl",     t_done, 0, true, { Ew, Gw, Zz }, 0 },
289   { 0,          t_ill,  0, false, { Zz, Zz, Zz }, 0 }, // PREFIX_SEG_OVR
290   { 0,          t_ill,  0, false, { Zz, Zz, Zz }, 0 }, // PREFIX_SEG_OVR
291   { 0,   t_prefixedSSE, 2, false, { Zz, Zz, Zz }, 0 }, /* operand size prefix (PREFIX_OPR_SZ)*/
292   { 0,          t_ill,  0, false, { Zz, Zz, Zz }, 0 }, /* address size prefix (PREFIX_ADDR_SZ)*/
293   /* 68 */
294   { "push",    t_done, 0, false, { Iv, Zz, Zz }, 0 },
295   { "imul",    t_done, 0, true, { Gv, Ev, Iv }, 0 },
296   { "push",    t_done, 0, false, { Ib, Zz, Zz }, 0 },
297   { "imul",    t_done, 0, true, { Gv, Ev, Ib }, 0 },
298   { "insb",    t_done, 0, false, { Yb, DX, Zz }, 0 },
299   { "insw/d",  t_done, 0, false, { Yv, DX, Zz }, 0 },
300   { "outsb",   t_done, 0, false, { DX, Xb, Zz }, 0 },
301   { "outsw/d", t_done, 0, false, { DX, Xv, Zz }, 0 },
302   /* 70 */
303   { "jo",         t_done, 0, false, { Jb, Zz, Zz }, (IS_JCC | REL_B) },
304   { "jno",        t_done, 0, false, { Jb, Zz, Zz }, (IS_JCC | REL_B) },
305   { "jb/jnaej/j", t_done, 0, false, { Jb, Zz, Zz }, (IS_JCC | REL_B) },
306   { "jnb/jae/j",  t_done, 0, false, { Jb, Zz, Zz }, (IS_JCC | REL_B) },
307   { "jz",         t_done, 0, false, { Jb, Zz, Zz }, (IS_JCC | REL_B) },
308   { "jnz",        t_done, 0, false, { Jb, Zz, Zz }, (IS_JCC | REL_B) },
309   { "jbe",        t_done, 0, false, { Jb, Zz, Zz }, (IS_JCC | REL_B) },
310   { "jnbe",       t_done, 0, false, { Jb, Zz, Zz }, (IS_JCC | REL_B) },
311   /* 78 */
312   { "js",   t_done, 0, false, { Jb, Zz, Zz }, (IS_JCC | REL_B) },
313   { "jns",  t_done, 0, false, { Jb, Zz, Zz }, (IS_JCC | REL_B) },
314   { "jp",   t_done, 0, false, { Jb, Zz, Zz }, (IS_JCC | REL_B) },
315   { "jnp",  t_done, 0, false, { Jb, Zz, Zz }, (IS_JCC | REL_B) },
316   { "jl",   t_done, 0, false, { Jb, Zz, Zz }, (IS_JCC | REL_B) },
317   { "jnl",  t_done, 0, false, { Jb, Zz, Zz }, (IS_JCC | REL_B) },
318   { "jle",  t_done, 0, false, { Jb, Zz, Zz }, (IS_JCC | REL_B) },
319   { "jnle", t_done, 0, false, { Jb, Zz, Zz }, (IS_JCC | REL_B) },
320   /* 80 */
321   { 0, t_grp, Grp1, true, { Eb, Ib, Zz }, 0 },
322   { 0, t_grp, Grp1, true, { Ev, Iv, Zz }, 0 },
323   { 0, t_grp, Grp1, true, { Eb, Ib, Zz }, 0 }, // this was Ill in the old decoder and in gdb 5.2.
324                                                // the book says Grp1 however;sandpile.org agrees.
325   { 0, t_grp, Grp1, true, { Ev, Ib, Zz }, 0 },
326   { "test", t_done, 0, true, { Eb, Gb, Zz }, 0 },
327   { "test", t_done, 0, true, { Ev, Gv, Zz }, 0 },
328   { "xchg", t_done, 0, true, { Eb, Gb, Zz }, 0 },
329   { "xchg", t_done, 0, true, { Ev, Gv, Zz }, 0 },
330   /* 88 */
331   { "mov", t_done, 0, true, { Eb, Gb, Zz }, 0 },
332   { "mov", t_done, 0, true, { Ev, Gv, Zz }, 0 },
333   { "mov", t_done, 0, true, { Gb, Eb, Zz }, 0 },
334   { "mov", t_done, 0, true, { Gv, Ev, Zz }, 0 },
335   { "mov", t_done, 0, true, { Ew, Sw, Zz }, 0 },
336   { "lea", t_done, 0, true, { Gv, Mlea, Zz }, 0 }, // this is just M in the book
337   { "mov", t_done, 0, true, { Sw, Ew, Zz }, 0 },
338   { "pop", t_done, 0, true, { Ev, Zz, Zz }, 0 },
339   /* 90 */
340   { "nop",  t_done, 0, false, { Zz, Zz, Zz }, 0 },
341   { "xchg", t_done, 0, false, { eCX, Zz, Zz }, 0 },
342   { "xchg", t_done, 0, false, { eDX, Zz, Zz }, 0 },
343   { "xchg", t_done, 0, false, { eBX, Zz, Zz }, 0 },
344   { "xchg", t_done, 0, false, { eSP, Zz, Zz }, 0 },
345   { "xchg", t_done, 0, false, { eBP, Zz, Zz }, 0 },
346   { "xchg", t_done, 0, false, { eSI, Zz, Zz }, 0 },
347   { "xchg", t_done, 0, false, { eDI, Zz, Zz }, 0 },
348   /* 98 */
349   { "cbw",     t_done, 0, false, { Zz, Zz, Zz }, 0 },
350   { "cwd/cdq", t_done, 0, false, { Zz, Zz, Zz }, 0 },
351   { "call",    t_done, 0, false, { Ap, Zz, Zz }, IS_CALL | PTR_WX },
352   { "wait",    t_done, 0, false, { Zz, Zz, Zz }, 0 },
353   { "pushf",   t_done, 0, false, { Fv, Zz, Zz }, 0 },
354   { "pop",     t_done, 0, false, { Fv, Zz, Zz }, 0 },
355   { "sahf",    t_done, 0, false, { Zz, Zz, Zz }, 0 },
356   { "lahf",    t_done, 0, false, { Zz, Zz, Zz }, 0 },
357   /* A0 */
358   { "mov",   t_done, 0, false, { AL, Ob, Zz }, 0 },
359   { "mov",   t_done, 0, false, { eAX, Ov, Zz }, 0 },
360   { "mov",   t_done, 0, false, { Ob, AL, Zz }, 0 },
361   { "mov",   t_done, 0, false, { Ov, eAX, Zz }, 0 },
362   { "movsb", t_done, 0, false, { Xb, Yb, Zz }, 0 },
363   { "movsw", t_done, 0, false, { Xv, Yv, Zz }, 0 },
364   { "cmpsb", t_done, 0, false, { Xb, Yb, Zz }, 0 },
365   { "cmpsw", t_done, 0, false, { Xv, Yv, Zz }, 0 },
366   /* A8 */
367   { "test",     t_done, 0, false, { AL, Ib, Zz }, 0 },
368   { "test",     t_done, 0, false, { eAX, Iv, Zz }, 0 },
369   { "stopsb",   t_done, 0, false, { Yb, AL, Zz }, 0 },
370   { "stopsw/d", t_done, 0, false, { Yv, eAX, Zz }, 0 },
371   { "lodsb",    t_done, 0, false, { AL, Xb, Zz }, 0 },
372   { "lodsw",    t_done, 0, false, { eAX, Xv, Zz }, 0 },
373   { "scasb",    t_done, 0, false, { AL, Yb, Zz }, 0 },
374   { "scasw/d",  t_done, 0, false, { eAX, Yv, Zz }, 0 },
375   /* B0 */
376   { "mov", t_done, 0, false, { AL, Ib, Zz }, 0 },
377   { "mov", t_done, 0, false, { CL, Ib, Zz }, 0 },
378   { "mov", t_done, 0, false, { DL, Ib, Zz }, 0 },
379   { "mov", t_done, 0, false, { BL, Ib, Zz }, 0 },
380   { "mov", t_done, 0, false, { AH, Ib, Zz }, 0 },
381   { "mov", t_done, 0, false, { CH, Ib, Zz }, 0 },
382   { "mov", t_done, 0, false, { DH, Ib, Zz }, 0 },
383   { "mov", t_done, 0, false, { BH, Ib, Zz }, 0 },
384   /* B8 */
385   { "mov", t_done, 0, false, { eAX, Iv, Zz }, 0 },
386   { "mov", t_done, 0, false, { eCX, Iv, Zz }, 0 },
387   { "mov", t_done, 0, false, { eDX, Iv, Zz }, 0 },
388   { "mov", t_done, 0, false, { eBX, Iv, Zz }, 0 },
389   { "mov", t_done, 0, false, { eSP, Iv, Zz }, 0 },
390   { "mov", t_done, 0, false, { eBP, Iv, Zz }, 0 },
391   { "mov", t_done, 0, false, { eSI, Iv, Zz }, 0 },
392   { "mov", t_done, 0, false, { eDI, Iv, Zz }, 0 },
393   /* C0 */
394   { 0, t_grp, Grp2, true, { Eb, Ib, Zz }, 0 },
395   { 0, t_grp, Grp2, true, { Ev, Ib, Zz }, 0 },
396   { "ret near", t_done, 0, false, { Iw, Zz, Zz }, (IS_RET) },
397   { "ret near", t_done, 0, false, { Zz, Zz, Zz }, (IS_RET) },
398   { "les",      t_done, 0, true, { Gv, Mp, Zz }, 0 },
399   { "lds",      t_done, 0, true, { Gv, Mp, Zz }, 0 },
400   { 0, t_grp, Grp11, true, { Eb, Ib, Zz }, 0 },
401   { 0, t_grp, Grp11, true, { Ev, Iv, Zz }, 0 },
402   /* C8 */
403   { "enter",   t_done, 0, false, { Iw, Ib, Zz }, 0 },
404   { "leave",   t_done, 0, false, { Zz, Zz, Zz }, 0 },
405   { "ret far", t_done, 0, false, { Iw, Zz, Zz }, (IS_RETF) },
406   { "ret far", t_done, 0, false, { Zz, Zz, Zz }, (IS_RETF) },
407   { "int 3",   t_done, 0, false, { Zz, Zz, Zz }, 0 },
408   { "int",     t_done, 0, false, { Ib, Zz, Zz }, 0 },
409   { "into",    t_done, 0, false, { Zz, Zz, Zz }, 0 },
410   { "iret",    t_done, 0, false, { Zz, Zz, Zz }, (IS_RET) },
411   /* D0 */
412   { 0, t_grp, Grp2, true, { Eb, Zz, Zz }, 0 }, // const1
413   { 0, t_grp, Grp2, true, { Ev, Zz, Zz }, 0 }, // --"--
414   { 0, t_grp, Grp2, true, { Eb, CL, Zz }, 0 },
415   { 0, t_grp, Grp2, true, { Ev, CL, Zz }, 0 },
416   { "aam",  t_done, 0, false, { Zz, Zz, Zz }, 0 },
417   { "aad",  t_done, 0, false, { Zz, Zz, Zz }, 0 },
418   { "salc", t_done, 0, false, { Zz, Zz, Zz }, 0 }, // sandpile.org gives this as SALC; undocumeted
419   { "xlat", t_done, 0, false, { Zz, Zz, Zz }, 0 },
420   /* D8 */
421   { 0, t_coprocEsc, 0, true, { Zz, Zz, Zz }, 0 },
422   { 0, t_coprocEsc, 0, true, { Zz, Zz, Zz }, 0 },
423   { 0, t_coprocEsc, 0, true, { Zz, Zz, Zz }, 0 },
424   { 0, t_coprocEsc, 0, true, { Zz, Zz, Zz }, 0 },
425   { 0, t_coprocEsc, 0, true, { Zz, Zz, Zz }, 0 },
426   { 0, t_coprocEsc, 0, true, { Zz, Zz, Zz }, 0 },
427   { 0, t_coprocEsc, 0, true, { Zz, Zz, Zz }, 0 },
428   { 0, t_coprocEsc, 0, true, { Zz, Zz, Zz }, 0 },
429   /* E0 */
430   { "loopn",    t_done, 0, false, { Jb, Zz, Zz }, 0 },
431   { "loope",    t_done, 0, false, { Jb, Zz, Zz }, 0 },
432   { "loop",     t_done, 0, false, { Jb, Zz, Zz }, 0 },
433   { "jcxz/jec", t_done, 0, false, { Jb, Zz, Zz }, (IS_JCC | REL_B) },
434   { "in",       t_done, 0, false, { AL, Ib, Zz }, 0 },
435   { "in",       t_done, 0, false, { eAX, Ib, Zz }, 0 },
436   { "out",      t_done, 0, false, { Ib, AL, Zz }, 0 },
437   { "out",      t_done, 0, false, { Ib, eAX, Zz }, 0 },
438   /* E8 */
439   { "call", t_done, 0, false, { Jv, Zz, Zz }, (IS_CALL | REL_X) },
440   { "jmp",  t_done, 0, false, { Jv, Zz, Zz }, (IS_JUMP | REL_X) },
441   { "jmp",  t_done, 0, false, { Ap, Zz, Zz }, (IS_JUMP | PTR_WX) },
442   { "jmp",  t_done, 0, false, { Jb, Zz, Zz }, (IS_JUMP | REL_B) },
443   { "in",   t_done, 0, false, { AL, DX, Zz }, 0 },
444   { "in",   t_done, 0, false, { eAX, DX, Zz }, 0 },
445   { "out",  t_done, 0, false, { DX, AL, Zz }, 0 },
446   { "out",  t_done, 0, false, { DX, eAX, Zz }, 0 },
447   /* F0 */
448   { 0,      t_ill,  0, false, { Zz, Zz, Zz }, 0 }, // PREFIX_INSTR
449   { "int1", t_done, 0, false, { Zz, Zz, Zz }, 0 }, // INT1/ICEBP on sandpile; undocumented
450   { 0, t_prefixedSSE, 3, false, { Zz, Zz, Zz }, 0 },
451   { 0, t_prefixedSSE, 1, false, { Zz, Zz, Zz }, 0 },
452   { "hlt",  t_done, 0, false, { Zz, Zz, Zz }, 0 },
453   { "cmc",  t_done, 0, false, { Zz, Zz, Zz }, 0 },
454   { 0, t_grp, Grp3a, true, { Zz, Zz, Zz }, 0 },
455   { 0, t_grp, Grp3b, true, { Zz, Zz, Zz }, 0 },
456   /* F8 */
457   { "clc", t_done, 0, false, { Zz, Zz, Zz }, 0 },
458   { "stc", t_done, 0, false, { Zz, Zz, Zz }, 0 },
459   { "cli", t_done, 0, false, { Zz, Zz, Zz }, 0 },
460   { "sti", t_done, 0, false, { Zz, Zz, Zz }, 0 },
461   { "cld", t_done, 0, false, { Zz, Zz, Zz }, 0 },
462   { "std", t_done, 0, false, { Zz, Zz, Zz }, 0 },
463   { 0, t_grp, Grp4, true, { Zz, Zz, Zz }, 0 },
464   { 0, t_grp, Grp5, true, { Zz, Zz, Zz }, 0 }
465 };
466
467
468 // twoByteMap: two byte opcode instructions (first byte is 0x0F)
469 static ia32_entry twoByteMap[256] = {
470   /* 00 */
471   { 0, t_grp, Grp6, true, { Zz, Zz, Zz }, 0 },
472   { 0, t_grp, Grp7, false, { Zz, Zz, Zz }, 0 },
473   { "lar",        t_done, 0, true, { Gv, Ew, Zz }, 0  },
474   { "lsl",        t_done, 0, true, { Gv, Ew, Zz }, 0  },
475   { 0,            t_ill,  0, false, { Zz, Zz, Zz },0},
476   { "syscall",    t_done, 0, false, { Zz, Zz, Zz }, 0 }, // AMD
477   { "clts",       t_done, 0, false, { Zz, Zz, Zz }, 0 },
478   { "sysret",     t_done, 0, false, { Zz, Zz, Zz }, 0 }, // AMD
479   /* 08 */
480   { "invd",   t_done, 0, false, { Zz, Zz, Zz }, 0 },
481   { "wbinvd", t_done, 0, false, { Zz, Zz, Zz }, 0 },
482   { 0,        t_ill,  0, false, { Zz, Zz, Zz }, 0 },
483   { "ud2",    t_ill,  0, 0, { Zz, Zz, Zz }, 0 },
484   { 0,        t_ill,  0, 0, { Zz, Zz, Zz }, 0 },
485   { "prefetch(w)", t_done,  0, true,  { Zz, Zz, Zz }, 0 }, // AMD
486   { "femms",       t_done,  0, false, { Zz, Zz, Zz }, 0 }, // AMD 
487   { 0,             t_3dnow, 0, true,  { Zz, Zz, Zz }, 0 }, // AMD 3DNOW! suffixes
488   /* 10 */
489   { 0, t_sse, SSE10, true, { Zz, Zz, Zz }, 0 },
490   { 0, t_sse, SSE11, true, { Zz, Zz, Zz }, 0 },
491   { 0, t_sse, SSE12, true, { Zz, Zz, Zz }, 0 },
492   { 0, t_sse, SSE13, true, { Zz, Zz, Zz }, 0 },
493   { 0, t_sse, SSE14, true, { Zz, Zz, Zz }, 0 },
494   { 0, t_sse, SSE15, true, { Zz, Zz, Zz }, 0 },
495   { 0, t_sse, SSE16, true, { Zz, Zz, Zz }, 0 },
496   { 0, t_sse, SSE17, true, { Zz, Zz, Zz }, 0 },
497   /* 18 */
498   { 0, t_grp, Grp16, 0, { Zz, Zz, Zz }, 0 },
499   { 0, t_ill, 0, 0, { Zz, Zz, Zz }, 0 },
500   { 0, t_ill, 0, 0, { Zz, Zz, Zz }, 0 },
501   { 0, t_ill, 0, 0, { Zz, Zz, Zz }, 0 },
502   { 0, t_ill, 0, 0, { Zz, Zz, Zz }, 0 },
503   { 0, t_ill, 0, 0, { Zz, Zz, Zz }, 0 },
504   { 0, t_ill, 0, 0, { Zz, Zz, Zz }, 0 },
505   { 0, t_ill, 0, 0, { Zz, Zz, Zz }, 0 },
506   /* 20 */
507   { "mov", t_done, 0, true, { Rd, Cd, Zz }, 0 },
508   { "mov", t_done, 0, true, { Rd, Dd, Zz }, 0 },
509   { "mov", t_done, 0, true, { Cd, Rd, Zz }, 0 },
510   { "mov", t_done, 0, true, { Dd, Rd, Zz }, 0 },
511   { "mov", t_done, 0, true, { Rd, Td, Zz }, 0 },
512   { 0,     t_ill,  0, 0, { Zz, Zz, Zz }, 0 },
513   { "mov", t_done, 0, true, { Td, Rd, Zz }, 0 },
514   { 0,     t_ill,  0, 0, { Zz, Zz, Zz }, 0 },
515   /* 28 */
516   { 0, t_sse, SSE28, true, { Zz, Zz, Zz }, 0 },
517   { 0, t_sse, SSE29, true, { Zz, Zz, Zz }, 0 },
518   { 0, t_sse, SSE2A, true, { Zz, Zz, Zz }, 0 },
519   { 0, t_sse, SSE2B, true, { Zz, Zz, Zz }, 0 },
520   { 0, t_sse, SSE2C, true, { Zz, Zz, Zz }, 0 },
521   { 0, t_sse, SSE2D, true, { Zz, Zz, Zz }, 0 },
522   { 0, t_sse, SSE2E, true, { Zz, Zz, Zz }, 0 },
523   { 0, t_sse, SSE2F, true, { Zz, Zz, Zz }, 0 },
524   /* 30 */
525   { "wrmsr", t_done, 0, false, { Zz, Zz, Zz }, 0 },
526   { "rdtsc", t_done, 0, false, { Zz, Zz, Zz }, 0 },
527   { "rdmsr", t_done, 0, false, { Zz, Zz, Zz }, 0 },
528   { "rdpmc", t_done, 0, false, { Zz, Zz, Zz }, 0 },
529   { "sysenter", t_done, 0, false, { Zz, Zz, Zz }, 0 },
530   { "sysexit",  t_done, 0, false, { Zz, Zz, Zz }, 0 },
531   {0,t_ill, 0,0,{ Zz, Zz, Zz },0}, 
532   {0,t_ill, 0,0,{ Zz, Zz, Zz },0},
533   /* 38 */
534   {0,t_ill, 0,0,{ Zz, Zz, Zz },0},
535   {0,t_ill, 0,0,{ Zz, Zz, Zz },0}, 
536   {0,t_ill, 0,0,{ Zz, Zz, Zz },0}, 
537   {0,t_ill, 0,0,{ Zz, Zz, Zz },0},
538   {0,t_ill, 0,0,{ Zz, Zz, Zz },0},
539   {0,t_ill, 0,0,{ Zz, Zz, Zz },0},
540   {0,t_ill, 0,0,{ Zz, Zz, Zz },0},
541   {0,t_ill, 0,0,{ Zz, Zz, Zz },0},
542   /* 40 */
543   { "cmovo",   t_done, 0, true, { Gv, Ev, Zz }, 0 },
544   { "cmovno",  t_done, 0, true, { Gv, Ev, Zz }, 0 },
545   { "cmovnae", t_done, 0, true, { Gv, Ev, Zz }, 0 },
546   { "cmovnb",  t_done, 0, true, { Gv, Ev, Zz }, 0 },
547   { "cmove",   t_done, 0, true, { Gv, Ev, Zz }, 0 },
548   { "cmovne",  t_done, 0, true, { Gv, Ev, Zz }, 0 },
549   { "cmovbe",  t_done, 0, true, { Gv, Ev, Zz }, 0 },
550   { "cmovnbe", t_done, 0, true, { Gv, Ev, Zz }, 0 },
551   /* 48 */
552   { "cmovs",   t_done, 0, true, { Gv, Ev, Zz }, 0 },
553   { "cmovns",  t_done, 0, true, { Gv, Ev, Zz }, 0 },
554   { "cmovpe",  t_done, 0, true, { Gv, Ev, Zz }, 0 },
555   { "cmovpo",  t_done, 0, true, { Gv, Ev, Zz }, 0 },
556   { "cmovnge", t_done, 0, true, { Gv, Ev, Zz }, 0 },
557   { "cmovnl",  t_done, 0, true, { Gv, Ev, Zz }, 0 },
558   { "cmovng",  t_done, 0, true, { Gv, Ev, Zz }, 0 },
559   { "cmovnl",  t_done, 0, true, { Gv, Ev, Zz }, 0 },
560   /* 50 */
561   { 0, t_sse, SSE50, true, { Zz, Zz, Zz }, 0 },
562   { 0, t_sse, SSE51, true, { Zz, Zz, Zz }, 0 },
563   { 0, t_sse, SSE52, true, { Zz, Zz, Zz }, 0 },
564   { 0, t_sse, SSE53, true, { Zz, Zz, Zz }, 0 },
565   { 0, t_sse, SSE54, true, { Zz, Zz, Zz }, 0 },
566   { 0, t_sse, SSE55, true, { Zz, Zz, Zz }, 0 },
567   { 0, t_sse, SSE56, true, { Zz, Zz, Zz }, 0 },
568   { 0, t_sse, SSE57, true, { Zz, Zz, Zz }, 0 },
569   /* 58 */
570   { 0, t_sse, SSE58, true, { Zz, Zz, Zz }, 0 },
571   { 0, t_sse, SSE59, true, { Zz, Zz, Zz }, 0 },
572   { 0, t_sse, SSE5A, true, { Zz, Zz, Zz }, 0 },
573   { 0, t_sse, SSE5B, true, { Zz, Zz, Zz }, 0 },
574   { 0, t_sse, SSE5C, true, { Zz, Zz, Zz }, 0 },
575   { 0, t_sse, SSE5D, true, { Zz, Zz, Zz }, 0 },
576   { 0, t_sse, SSE5E, true, { Zz, Zz, Zz }, 0 },
577   { 0, t_sse, SSE5F, true, { Zz, Zz, Zz }, 0 },
578   /* 60 */
579   { 0, t_sse, SSE60, true, { Zz, Zz, Zz }, 0 },
580   { 0, t_sse, SSE61, true, { Zz, Zz, Zz }, 0 },
581   { 0, t_sse, SSE62, true, { Zz, Zz, Zz }, 0 },
582   { 0, t_sse, SSE63, true, { Zz, Zz, Zz }, 0 },
583   { 0, t_sse, SSE64, true, { Zz, Zz, Zz }, 0 },
584   { 0, t_sse, SSE65, true, { Zz, Zz, Zz }, 0 },
585   { 0, t_sse, SSE66, true, { Zz, Zz, Zz }, 0 },
586   { 0, t_sse, SSE67, true, { Zz, Zz, Zz }, 0 },
587   /* 68 */
588   { 0, t_sse, SSE68, true, { Zz, Zz, Zz }, 0 },
589   { 0, t_sse, SSE69, true, { Zz, Zz, Zz }, 0 },
590   { 0, t_sse, SSE6A, true, { Zz, Zz, Zz }, 0 },
591   { 0, t_sse, SSE6B, true, { Zz, Zz, Zz }, 0 },
592   { 0, t_sse, SSE6C, true, { Zz, Zz, Zz }, 0 },
593   { 0, t_sse, SSE6D, true, { Zz, Zz, Zz }, 0 },
594   { 0, t_sse, SSE6E, true, { Zz, Zz, Zz }, 0 },
595   { 0, t_sse, SSE6F, true, { Zz, Zz, Zz }, 0 },
596   /* 70 */
597   { 0, t_sse, SSE70, true, { Zz, Zz, Zz }, 0 },
598   { 0, t_grp, Grp12, false, { Zz, Zz, Zz }, 0 },
599   { 0, t_grp, Grp13, false, { Zz, Zz, Zz }, 0 },
600   { 0, t_grp, Grp14, false, { Zz, Zz, Zz }, 0 },
601   { 0, t_sse, SSE74, true, { Zz, Zz, Zz }, 0 },
602   { 0, t_sse, SSE75, true, { Zz, Zz, Zz }, 0 },
603   { 0, t_sse, SSE76, true, { Zz, Zz, Zz }, 0 },
604   { "emms", t_done, 0, false, { Zz, Zz, Zz }, 0 },
605   /* 78 */
606   { "mmxud", t_ill, 0, 0, { Zz, Zz, Zz }, 0},
607   { "mmxud", t_ill, 0, 0, { Zz, Zz, Zz }, 0},
608   { "mmxud", t_ill, 0, 0, { Zz, Zz, Zz }, 0},
609   { "mmxud", t_ill, 0, 0, { Zz, Zz, Zz }, 0},
610   { "mmxud", t_ill, 0, 0, { Zz, Zz, Zz }, 0},
611   { "mmxud", t_ill, 0, 0, { Zz, Zz, Zz }, 0},
612   { 0, t_sse, SSE7E, 0, { Zz, Zz, Zz }, 0 },
613   { 0, t_sse, SSE7F, 0, { Zz, Zz, Zz }, 0 },
614   /* 80 */
615   { "jo",   t_done, 0, false, { Jv, Zz, Zz }, (IS_JCC | REL_X) },
616   { "jno",  t_done, 0, false, { Jv, Zz, Zz }, (IS_JCC | REL_X) },
617   { "jb",   t_done, 0, false, { Jv, Zz, Zz }, (IS_JCC | REL_X) },
618   { "jnb",  t_done, 0, false, { Jv, Zz, Zz }, (IS_JCC | REL_X) },
619   { "jz",   t_done, 0, false, { Jv, Zz, Zz }, (IS_JCC | REL_X) },
620   { "jnz",  t_done, 0, false, { Jv, Zz, Zz }, (IS_JCC | REL_X) },
621   { "jbe",  t_done, 0, false, { Jv, Zz, Zz }, (IS_JCC | REL_X) },
622   { "jnbe", t_done, 0, false, { Jv, Zz, Zz }, (IS_JCC | REL_X) },
623   /* 88 */
624   { "js",   t_done, 0, false, { Jv, Zz, Zz }, (IS_JCC | REL_X) },
625   { "jns",  t_done, 0, false, { Jv, Zz, Zz }, (IS_JCC | REL_X) },
626   { "jp",   t_done, 0, false, { Jv, Zz, Zz }, (IS_JCC | REL_X) },
627   { "jnp",  t_done, 0, false, { Jv, Zz, Zz }, (IS_JCC | REL_X) },
628   { "jl",   t_done, 0, false, { Jv, Zz, Zz }, (IS_JCC | REL_X) },
629   { "jnl",  t_done, 0, false, { Jv, Zz, Zz }, (IS_JCC | REL_X) },
630   { "jle",  t_done, 0, false, { Jv, Zz, Zz }, (IS_JCC | REL_X) },
631   { "jnle", t_done, 0, false, { Jv, Zz, Zz }, (IS_JCC | REL_X) },
632   /* 90 */
633   { "seto",   t_done, 0, true, { Eb, Zz, Zz }, 0 },
634   { "setno",  t_done, 0, true, { Eb, Zz, Zz }, 0 },
635   { "setb",   t_done, 0, true, { Eb, Zz, Zz }, 0 },
636   { "setnb",  t_done, 0, true, { Eb, Zz, Zz }, 0 },
637   { "setz",   t_done, 0, true, { Eb, Zz, Zz }, 0 },
638   { "setnz",  t_done, 0, true, { Eb, Zz, Zz }, 0 },
639   { "setbe",  t_done, 0, true, { Eb, Zz, Zz }, 0 },
640   { "setnbe", t_done, 0, true, { Eb, Zz, Zz }, 0 },
641   /* 98 */
642   { "sets",   t_done, 0, true, { Eb, Zz, Zz }, 0 },
643   { "setns",  t_done, 0, true, { Eb, Zz, Zz }, 0 },
644   { "setp",   t_done, 0, true, { Eb, Zz, Zz }, 0 },
645   { "setnp",  t_done, 0, true, { Eb, Zz, Zz }, 0 },
646   { "setl",   t_done, 0, true, { Eb, Zz, Zz }, 0 },
647   { "setnl",  t_done, 0, true, { Eb, Zz, Zz }, 0 },
648   { "setle",  t_done, 0, true, { Eb, Zz, Zz }, 0 },
649   { "setnle", t_done, 0, true, { Eb, Zz, Zz }, 0 },
650   /* A0 */
651   { "push",   t_done, 0, false, { FS, Zz, Zz }, 0 },
652   { "pop",    t_done, 0, false, { FS, Zz, Zz }, 0 },
653   { "cpuid",  t_done, 0, false, { Zz, Zz, Zz }, 0 },
654   { "bt",     t_done, 0, true, { Ev, Gv, Zz }, 0 },
655   { "shld",   t_done, 0, true, { Ev, Gv, Ib }, 0 },
656   { "shld",   t_done, 0, true, { Ev, Gv, CL }, 0 },
657   { 0, t_ill, 0, 0, { Zz, Zz, Zz }, 0}, 
658   { 0, t_ill, 0, 0, { Zz, Zz, Zz }, 0},
659   /* A8 */
660   { "push", t_done, 0, false, { GS, Zz, Zz }, 0 },
661   { "pop",  t_done, 0, false, { GS, Zz, Zz }, 0 },
662   { "rsm",  t_done, 0, false, { Zz, Zz, Zz }, 0 },
663   { "bts",  t_done, 0, true, { Ev, Gv, Zz }, 0 },
664   { "shrd", t_done, 0, true, { Ev, Gv, Ib }, 0 },
665   { "shrd", t_done, 0, true, { Ev, Gv, CL }, 0 },
666   { 0, t_grp, Grp15, 0, { Zz, Zz, Zz }, 0 }, 
667   { "imul", t_done, 0, true, { Gv, Ev, Zz }, 0 },
668   /* B0 */
669   { "cmpxch", t_done, 0, true, { Eb, Gb, Zz }, 0 },
670   { "cmpxch", t_done, 0, true, { Ev, Gv, Zz }, 0 },
671   { "lss", t_done, 0, true, { Mp, Zz, Zz }, 0 },
672   { "btr", t_done, 0, true, { Ev, Gv, Zz }, 0 },
673   { "lfs", t_done, 0, true, { Mp, Zz, Zz }, 0 },
674   { "lgs", t_done, 0, true, { Mp, Zz, Zz }, 0 },
675   { "movzx", t_done, 0, true, { Gv, Eb, Zz }, 0 },
676   { "movzx", t_done, 0, true, { Gv, Ew, Zz }, 0 },
677   /* B8 */
678   {0,t_ill, 0,0,{ Zz, Zz, Zz },0},
679   { "ud2grp10", t_ill, 0, 0, { Zz, Zz, Zz }, 0 },
680   { 0, t_grp, Grp8, true, { Ev, Ib, Zz }, 0 },
681   { "btc", t_done, 0, true, { Ev, Gv, Zz }, 0 },
682   { "bsf", t_done, 0, true, { Gv, Ev, Zz }, 0 },
683   { "bsr", t_done, 0, true, { Gv, Ev, Zz }, 0 },
684   { "movsx", t_done, 0, true, { Gv, Eb, Zz }, 0 },
685   { "movsx", t_done, 0, true, { Gv, Ew, Zz }, 0 },
686   /* C0 */
687   { "xadd", t_done, 0, true, { Eb, Gb, Zz }, 0 },
688   { "xadd", t_done, 0, true, { Ev, Gv, Zz }, 0 },
689   { 0, t_sse, SSEC2, true, { Zz, Zz, Zz }, 0 },
690   { "movnti" , t_done, 0, 0, { Ed, Gd, Zz }, 0 },
691   { 0, t_sse, SSEC4, true, { Zz, Zz, Zz }, 0 },
692   { 0, t_sse, SSEC5, true, { Zz, Zz, Zz }, 0 },
693   { 0, t_sse, SSEC6, true, { Zz, Zz, Zz }, 0 },
694   { 0, t_grp, Grp9,  true, { Zz, Zz, Zz }, 0 },
695   /* C8 */
696   { "bswap", t_done, 0, false, { EAX, Zz, Zz }, 0 }, 
697   { "bswap", t_done, 0, false, { ECX, Zz, Zz }, 0 }, 
698   { "bswap", t_done, 0, false, { EDX, Zz, Zz }, 0 }, 
699   { "bswap", t_done, 0, false, { EBX, Zz, Zz }, 0 }, 
700   { "bswap", t_done, 0, false, { ESP, Zz, Zz }, 0 },
701   { "bswap", t_done, 0, false, { EBP, Zz, Zz }, 0 }, 
702   { "bswap", t_done, 0, false, { ESI, Zz, Zz }, 0 }, 
703   { "bswap", t_done, 0, false, { EDI, Zz, Zz }, 0 }, 
704   /* D0 */
705   { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
706   { 0, t_sse, SSED1, true, { Zz, Zz, Zz }, 0 },
707   { 0, t_sse, SSED2, true, { Zz, Zz, Zz }, 0 },
708   { 0, t_sse, SSED3, true, { Zz, Zz, Zz }, 0 },
709   { 0, t_sse, SSED4, true, { Zz, Zz, Zz }, 0 },
710   { 0, t_sse, SSED5, true, { Zz, Zz, Zz }, 0 },
711   { 0, t_sse, SSED6, true, { Zz, Zz, Zz }, 0 },
712   { 0, t_sse, SSED7, true, { Zz, Zz, Zz }, 0 },
713   /* D8 */
714   { 0, t_sse, SSED8, true, { Zz, Zz, Zz }, 0 },
715   { 0, t_sse, SSED9, true, { Zz, Zz, Zz }, 0 },
716   { 0, t_sse, SSEDA, true, { Zz, Zz, Zz }, 0 },
717   { 0, t_sse, SSEDB, true, { Zz, Zz, Zz }, 0 },
718   { 0, t_sse, SSEDC, true, { Zz, Zz, Zz }, 0 },
719   { 0, t_sse, SSEDD, true, { Zz, Zz, Zz }, 0 },
720   { 0, t_sse, SSEDE, true, { Zz, Zz, Zz }, 0 },
721   { 0, t_sse, SSEDF, true, { Zz, Zz, Zz }, 0 },
722   /* E0 */
723   { 0, t_sse, SSEE0, true, { Zz, Zz, Zz }, 0 },
724   { 0, t_sse, SSEE1, true, { Zz, Zz, Zz }, 0 },
725   { 0, t_sse, SSEE2, true, { Zz, Zz, Zz }, 0 },
726   { 0, t_sse, SSEE3, true, { Zz, Zz, Zz }, 0 },
727   { 0, t_sse, SSEE4, true, { Zz, Zz, Zz }, 0 },
728   { 0, t_sse, SSEE5, true, { Zz, Zz, Zz }, 0 },
729   { 0, t_sse, SSEE6, true, { Zz, Zz, Zz }, 0 },
730   { 0, t_sse, SSEE7, true, { Zz, Zz, Zz }, 0 },
731   /* E8 */
732   { 0, t_sse, SSEE8, true, { Zz, Zz, Zz }, 0 },
733   { 0, t_sse, SSEE9, true, { Zz, Zz, Zz }, 0 },
734   { 0, t_sse, SSEEA, true, { Zz, Zz, Zz }, 0 },
735   { 0, t_sse, SSEEB, true, { Zz, Zz, Zz }, 0 },
736   { 0, t_sse, SSEEC, true, { Zz, Zz, Zz }, 0 },
737   { 0, t_sse, SSEED, true, { Zz, Zz, Zz }, 0 },
738   { 0, t_sse, SSEEE, true, { Zz, Zz, Zz }, 0 },
739   { 0, t_sse, SSEEF, true, { Zz, Zz, Zz }, 0 },
740   /* F0 */
741   { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
742   { 0, t_sse, SSEF1, true, { Zz, Zz, Zz }, 0 },
743   { 0, t_sse, SSEF2, true, { Zz, Zz, Zz }, 0 },
744   { 0, t_sse, SSEF3, true, { Zz, Zz, Zz }, 0 },
745   { 0, t_sse, SSEF4, true, { Zz, Zz, Zz }, 0 },
746   { 0, t_sse, SSEF5, true, { Zz, Zz, Zz }, 0 },
747   { 0, t_sse, SSEF6, true, { Zz, Zz, Zz }, 0 },
748   { 0, t_sse, SSEF7, true, { Zz, Zz, Zz }, 0 },
749   /* F8 */
750   { 0, t_sse, SSEF8, true, { Zz, Zz, Zz }, 0 },
751   { 0, t_sse, SSEF9, true, { Zz, Zz, Zz }, 0 },
752   { 0, t_sse, SSEFA, true, { Zz, Zz, Zz }, 0 },
753   { 0, t_sse, SSEFB, true, { Zz, Zz, Zz }, 0 },
754   { 0, t_sse, SSEFC, true, { Zz, Zz, Zz }, 0 },
755   { 0, t_sse, SSEFD, true, { Zz, Zz, Zz }, 0 },
756   { 0, t_sse, SSEFE, true, { Zz, Zz, Zz }, 0 },
757   { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0}
758 };
759
760 static ia32_entry groupMap[][8] = {
761  { /* group 1 - only opcode is defined here,
762       operands are defined in the one or two byte maps below */
763   { "add", t_done, 0, true, { Zz, Zz, Zz }, 0 },
764   { "or",  t_done, 0, true, { Zz, Zz, Zz }, 0 },
765   { "adc", t_done, 0, true, { Zz, Zz, Zz }, 0 },
766   { "sbb", t_done, 0, true, { Zz, Zz, Zz }, 0 },
767   { "and", t_done, 0, true, { Zz, Zz, Zz }, 0 },
768   { "sub", t_done, 0, true, { Zz, Zz, Zz }, 0 },
769   { "xor", t_done, 0, true, { Zz, Zz, Zz }, 0 },
770   { "cmp", t_done, 0, true, { Zz, Zz, Zz }, 0 }
771  },
772
773  {  /* group 2 - only opcode is defined here, 
774        operands are defined in the one or two byte maps below */
775   { "rol", t_done, 0, true, { Zz, Zz, Zz }, 0 },
776   { "ror", t_done, 0, true, { Zz, Zz, Zz }, 0 },
777   { "rcl", t_done, 0, true, { Zz, Zz, Zz }, 0 },
778   { "rcr", t_done, 0, true, { Zz, Zz, Zz }, 0 },
779   { "shl/sal", t_done, 0, true, { Zz, Zz, Zz }, 0 },
780   { "shr", t_done, 0, true, { Zz, Zz, Zz }, 0 },
781   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
782   { "sar", t_done, 0, true, { Zz, Zz, Zz }, 0 }
783  },
784
785  { /* group 3a - operands are defined here */
786   { "test", t_done, 0, true, { Eb, Ib, Zz }, 0 },
787   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
788   { "not",  t_done, 0, true, { Eb, Zz, Zz }, 0 },
789   { "neg",  t_done, 0, true, { Eb, Zz, Zz }, 0 },
790   { "mul",  t_done, 0, true, { AL, Eb, Zz }, 0 },
791   { "imul", t_done, 0, true, { AL, Eb, Zz }, 0 },
792   { "div",  t_done, 0, true, { AL, Eb, Zz }, 0 },
793   { "idiv", t_done, 0, true, { AL, Eb, Zz }, 0 }
794  },
795
796  { /* group 3b - operands are defined here */
797   { "test", t_done, 0, true, { Ev, Iv, Zz }, 0 },
798   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
799   { "not",  t_done, 0, true, { Ev, Zz, Zz }, 0 },
800   { "neg",  t_done, 0, true, { Ev, Zz, Zz }, 0 },
801   { "mul",  t_done, 0, true, { eAX, Ev, Zz }, 0 },
802   { "imul", t_done, 0, true, { eAX, Ev, Zz }, 0 },
803   { "div",  t_done, 0, true, { eAX, Ev, Zz }, 0 },
804   { "idiv", t_done, 0, true, { eAX, Ev, Zz }, 0 }
805  },
806
807  { /* group 4 - operands are defined here */
808   { "inc", t_done, 0, true, { Eb, Zz, Zz }, 0 },
809   { "dec", t_done, 0, true, { Eb, Zz, Zz }, 0 },
810   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
811   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
812   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
813   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
814   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
815   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
816  },
817
818  { /* group 5 - operands are defined here */
819   { "inc",  t_done, 0, true, { Ev, Zz, Zz }, 0 },
820   { "dec",  t_done, 0, true, { Ev, Zz, Zz }, 0 },
821   { "call", t_done, 0, true, { Ev, Zz, Zz }, (IS_CALL | INDIR) },
822   { "call", t_done, 0, true, { Ep, Zz, Zz }, (IS_CALL | INDIR) },
823   { "jmp",  t_done, 0, true, { Ev, Zz, Zz }, (IS_JUMP | INDIR) },
824   { "jmp",  t_done, 0, true, { Ep, Zz, Zz }, (IS_JUMP | INDIR) },
825   { "push", t_done, 0, true, { Ev, Zz, Zz }, 0 },
826   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
827  },
828
829  { /* group 6 - operands are defined here */
830   { "sldt", t_done, 0, true, { Ew, Zz, Zz }, 0 },
831   { "str",  t_done, 0, true, { Ew, Zz, Zz }, 0 },
832   { "lldt", t_done, 0, true, { Ew, Zz, Zz }, 0 },
833   { "ltr",  t_done, 0, true, { Ew, Zz, Zz }, 0 },
834   { "verr", t_done, 0, true, { Ew, Zz, Zz }, 0 },
835   { "verw", t_done, 0, true, { Ew, Zz, Zz }, 0 },
836   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
837   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
838  },
839
840  { /* group 7 - operands are defined here */
841   { "sgdt", t_done, 0, true, { Ms, Zz, Zz }, 0 },
842   { "sidt", t_done, 0, true, { Ms, Zz, Zz }, 0 },
843   { "lgdt", t_done, 0, true, { Ms, Zz, Zz }, 0 },
844   { "lidt", t_done, 0, true, { Ms, Zz, Zz }, 0 },
845   { "smsw", t_done, 0, true, { Ew, Zz, Zz }, 0 },
846   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
847   { "lmsw", t_done, 0, true, { Ew, Zz, Zz }, 0 },
848   { "invlpg", t_done, 0, true, { Zz, Zz, Zz }, 0 },
849  },
850
851  { /* group 8 - only opcode is defined here, 
852      operands are defined in the one or two byte maps below */
853   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
854   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
855   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
856   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
857   { "bt",  t_done, 0, true, { Zz, Zz, Zz }, 0 },
858   { "bts", t_done, 0, true, { Zz, Zz, Zz }, 0 },
859   { "btr", t_done, 0, true, { Zz, Zz, Zz }, 0 },
860   { "btc", t_done, 0, true, { Zz, Zz, Zz }, 0 },
861  },
862
863  { /* group 9 - operands are defined here */
864   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
865   { "cmpxch8b", t_done, 0, true, { Mq, Zz, Zz }, 0 },
866   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
867   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
868   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
869   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
870   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
871   { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 }
872  },
873
874  /* group 10 is all illegal */
875
876  { /* group 11, opcodes defined in one byte map */
877    { "mov", t_done, 0, true, { Zz, Zz, Zz }, 0 },
878    { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
879    { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
880    { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
881    { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
882    { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
883    { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
884    { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
885  }
886
887 };
888
889
890 // Groups 12-16 are split by mod={mem,11}. Some spill over into SSE groups!
891 // Notation: G12SSE010B = group 12, SSE, reg=010; B means mod=11
892 // Use A if Intel decides to put SSE instructions for mod=mem
893 static ia32_entry groupMap2[][2][8] = {
894   { /* group 12 */
895     {
896       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
897       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
898       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
899       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
900       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
901       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
902       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
903       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
904     },
905     {
906       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
907       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
908       { 0, t_grpsse, G12SSE010B, true, { Zz, Zz, Zz }, 0 },
909       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
910       { 0, t_grpsse, G12SSE100B, true, { Zz, Zz, Zz }, 0 },
911       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
912       { 0, t_grpsse, G12SSE110B, true, { Zz, Zz, Zz }, 0 },
913       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
914     }
915   },
916   { /* group 13 */
917     {
918       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
919       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
920       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
921       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
922       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
923       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
924       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
925       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
926     },
927     {
928       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
929       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
930       { 0, t_grpsse, G13SSE010B, true, { Zz, Zz, Zz }, 0 },
931       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
932       { 0, t_grpsse, G13SSE100B, true, { Zz, Zz, Zz }, 0 },
933       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
934       { 0, t_grpsse, G13SSE110B, true, { Zz, Zz, Zz }, 0 },
935       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
936     }
937   },
938   { /* group 14 */
939     {
940       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
941       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
942       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
943       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
944       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
945       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
946       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
947       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
948     },
949     {
950       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
951       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
952       { 0, t_grpsse, G14SSE010B, true, { Zz, Zz, Zz }, 0 },
953       { 0, t_grpsse, G14SSE011B, true, { Zz, Zz, Zz }, 0 },
954       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
955       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
956       { 0, t_grpsse, G14SSE110B, true, { Zz, Zz, Zz }, 0 },
957       { 0, t_grpsse, G14SSE111B, true, { Zz, Zz, Zz }, 0 },
958     }
959   },
960   { /* group 15 */
961     {
962       { "fxsave",  t_done, 0, true, { Zz, Zz, Zz }, 0 },
963       { "fxrstor", t_done, 0, true, { Zz, Zz, Zz }, 0 },
964       { "ldmxcsr", t_done, 0, true, { Zz, Zz, Zz }, 0 },
965       { "stmxcsr", t_done, 0, true, { Zz, Zz, Zz }, 0 },
966       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
967       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
968       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
969       { "clflush", t_done, 0, true, { Zz, Zz, Zz }, 0 },
970     },
971     {
972       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
973       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
974       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
975       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
976       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
977       { "lfence", t_done, 0, true, { Zz, Zz, Zz }, 0 },
978       { "mfence", t_done, 0, true, { Zz, Zz, Zz }, 0 },
979       { "sfence", t_done, 0, true, { Zz, Zz, Zz }, 0 },
980     }
981   },
982   { /* group 16 */
983     {
984       { "prefetchNTA", t_done, 0, true, { Zz, Zz, Zz }, 0 },
985       { "prefetchT0",  t_done, 0, true, { Zz, Zz, Zz }, 0 },
986       { "prefetchT1",  t_done, 0, true, { Zz, Zz, Zz }, 0 },
987       { "prefetchT2",  t_done, 0, true, { Zz, Zz, Zz }, 0 },
988       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
989       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
990       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
991       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
992     },
993     {
994       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
995       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
996       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
997       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
998       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
999       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
1000       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
1001       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
1002     }
1003   },
1004   { /* AMD prefetch group */
1005     {
1006       { "prefetch",   t_done, 0, true, { Zz, Zz, Zz }, 0 },
1007       { "prefetchw",  t_done, 0, true, { Zz, Zz, Zz }, 0 },
1008       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 }, // this is reserved, not illegal, ugh...
1009       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 }, // this is reserved, not illegal, ugh...
1010       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 }, // this is reserved, not illegal, ugh...
1011       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 }, // this is reserved, not illegal, ugh...
1012       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 }, // this is reserved, not illegal, ugh...
1013       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 }, // this is reserved, not illegal, ugh...
1014     },
1015     {
1016       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
1017       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
1018       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
1019       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
1020       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
1021       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
1022       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
1023       { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
1024     }
1025   }
1026 };
1027
1028 /* rows are not, F3, 66, F2 prefixed in this order (see book) */
1029 static ia32_entry sseMap[][4] = {
1030   { /* SSE10 */
1031     { "movups", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1032     { "movss",  t_done, 0, true, { Vss, Wss, Zz }, 0 },
1033     { "movupd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1034     { "movsd",  t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1035   },
1036   { /* SSE11 */
1037     { "movups", t_done, 0, true, { Wps, Vps, Zz }, 0 },
1038     { "movss",  t_done, 0, true, { Wss, Vss, Zz }, 0 },
1039     { "movupd", t_done, 0, true, { Wpd, Vpd, Zz }, 0 },
1040     { "movsd",  t_done, 0, true, { Vsd, Wsd, Zz }, 0 }, // FIXME: bug in book?????
1041   },
1042   { /* SSE12 */
1043     { "movlps/movhlps", t_done, 0, true, { Wq, Vq, Zz }, 0 }, // FIXME: wierd 1st op
1044     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1045     { "movlpd", t_done, 0, true, { Vq, Ws, Zz }, 0 },
1046     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1047   },
1048   { /* SSE13 */
1049     { "movlps", t_done, 0, true, { Vq, Wq, Zz }, 0 },
1050     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1051     { "movlpd", t_done, 0, true, { Vq, Wq, Zz }, 0 },
1052     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1053   },
1054   { /* SSE14 */
1055     { "unpcklps", t_done, 0, true, { Vps, Wq, Zz }, 0 },
1056     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1057     { "unpcklpd", t_done, 0, true, { Vpd, Wq, Zz }, 0 },
1058     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1059   },
1060   { /* SSE15 */
1061     { "unpckhps", t_done, 0, true, { Vps, Wq, Zz }, 0 },
1062     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1063     { "unpckhpd", t_done, 0, true, { Vpd, Wq, Zz }, 0 },
1064     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1065   },
1066   { /* SSE16 */
1067     { "movhps/movlhps", t_done, 0, true, { Vq, Wq, Zz }, 0 }, // FIXME: wierd 2nd op
1068     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1069     { "movhpd", t_done, 0, true, { Vq, Wq, Zz }, 0 },
1070     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1071   },
1072   { /* SSE17 */
1073     { "movhps", t_done, 0, true, { Wq, Vq, Zz }, 0 },
1074     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1075     { "movhpd", t_done, 0, true, { Wq, Vq, Zz }, 0 },
1076     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1077   },
1078   { /* SSE28 */
1079     { "movaps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1080     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1081     { "movapd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1082     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1083   },
1084   { /* SSE29 */
1085     { "movaps", t_done, 0, true, { Wps, Vps, Zz }, 0 },
1086     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1087     { "movapd", t_done, 0, true, { Wpd, Vpd, Zz }, 0 },
1088     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1089   },
1090   { /* SSE2A */
1091     { "cvtpi2ps", t_done, 0, true, { Vps, Qq, Zz }, 0 },
1092     { "cvtsi2ss", t_done, 0, true, { Vss, Ed, Zz }, 0 },
1093     { "cvtpi2pd", t_done, 0, true, { Vpd, Qdq, Zz }, 0 },
1094     { "cvtsi2sd", t_done, 0, true, { Vsd, Ed, Zz }, 0 },
1095   },
1096   { /* SSE2B */
1097     { "movntps", t_done, 0, true, { Wps, Vps, Zz }, 0 },
1098     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1099     { "movntps", t_done, 0, true, { Wpd, Vpd, Zz }, 0 }, // should be movntpd ???
1100     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1101   },
1102   { /* SSE2C */
1103     { "cvttps2pi", t_done, 0, true, { Qq, Wps, Zz }, 0 },
1104     { "cvttss2si", t_done, 0, true, { Gd, Wss, Zz }, 0 },
1105     { "cvttpd2pi", t_done, 0, true, { Qdq, Wpd, Zz }, 0 },
1106     { "cvttsd2si", t_done, 0, true, { Gd, Wsd, Zz }, 0 },
1107   },
1108   { /* SSE2D */
1109     { "cvtps2pi", t_done, 0, true, { Qq, Wps, Zz }, 0 },
1110     { "cvtss2si", t_done, 0, true, { Gd, Wss, Zz }, 0 },
1111     { "cvtpd2pi", t_done, 0, true, { Qdq, Wpd, Zz }, 0 },
1112     { "cvtsd2si", t_done, 0, true, { Gd, Wsd, Zz }, 0 },
1113   },
1114   { /* SSE2E */
1115     { "ucomiss", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1116     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1117     { "ucomisd", t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1118     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1119   },
1120   { /* SSE2F */
1121     { "comiss", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1122     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1123     { "comisd", t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1124     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1125   },
1126   { /* SSE50 */
1127     { "movmskps", t_done, 0, true, { Ed, Vps, Zz }, 0 },
1128     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1129     { "movmskpd", t_done, 0, true, { Ed, Vpd, Zz }, 0 },
1130     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1131   },
1132   { /* SSE51 */
1133     { "sqrtps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1134     { "sqrtss", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1135     { "sqrtpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1136     { "sqrtsd", t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1137   },
1138   { /* SSE52 */
1139     { "rsqrtps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1140     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1141     { "rsqrtss", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1142     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1143   },
1144   { /* SSE53 */
1145     { "rcpps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1146     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1147     { "rcpss", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1148     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1149   },
1150   { /* SSE54 */
1151     { "andps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1152     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1153     { "andpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1154     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1155   },
1156   { /* SSE55 */
1157     { "andnps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1158     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1159     { "andnpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1160     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1161   },
1162   { /* SSE56 */
1163     { "orps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1164     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1165     { "orpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1166     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1167   },
1168   { /* SSE57 */
1169     { "xorps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1170     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1171     { "xorpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1172     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1173   },
1174   { /* SSE58 */
1175     { "addps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1176     { "addss", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1177     { "addpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1178     { "addsd", t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1179   },
1180   { /* SSE59 */
1181     { "mulps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1182     { "mulss", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1183     { "mulpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1184     { "mulsd", t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1185   },
1186   { /* SSE5A */
1187     { "cvtps2pd", t_done, 0, true, { Vpd, Wps, Zz }, 0 },
1188     { "cvtss2sd", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1189     { "cvtpd2ps", t_done, 0, true, { Vps, Wpd, Zz }, 0 }, // FIXME: book bug ???
1190     { "cvtsd2ss", t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1191   },
1192   { /* SSE5B */
1193     { "cvtdq2ps", t_done, 0, true, { Vps, Wdq, Zz }, 0 },
1194     { "cvttps2dq", t_done, 0, true, { Vdq, Wps, Zz }, 0 }, // book has this and next swapped!!! 
1195     { "cvtps2dq", t_done, 0, true, { Vdq, Wps, Zz }, 0 },  // FIXME: book bug ???
1196     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1197   },
1198   { /* SSE5C */
1199     { "subps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1200     { "subss", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1201     { "subpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1202     { "subsd", t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1203   },
1204   { /* SSE5D */
1205     { "minps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1206     { "minss", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1207     { "minpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1208     { "minsd", t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1209   },
1210   { /* SSE5E */
1211     { "divps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1212     { "divss", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1213     { "divpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1214     { "divsd", t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1215   },
1216   { /* SSE5F */
1217     { "maxps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1218     { "maxss", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1219     { "maxpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1220     { "maxsd", t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1221   },
1222   { /* SSE60 */
1223     { "punpcklbw", t_done, 0, true, { Pq, Qd, Zz }, 0 },
1224     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1225     { "punpcklbw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1226     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1227   },
1228   { /* SSE61 */
1229     { "punpcklwd", t_done, 0, true, { Pq, Qd, Zz }, 0 },
1230     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1231     { "punpcklwd", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1232     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1233   },
1234   { /* SSE62 */
1235     { "punpcklqd", t_done, 0, true, { Pq, Qd, Zz }, 0 },
1236     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1237     { "punpcklqd", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1238     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1239   },
1240   { /* SSE63 */
1241     { "packsswb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1242     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1243     { "packsswb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1244     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1245   },
1246   { /* SSE64 */
1247     { "pcmpgtb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1248     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1249     { "pcmpgtb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1250     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1251   },
1252   { /* SSE65 */
1253     { "pcmpgtw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1254     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1255     { "pcmpgtw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1256     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1257   },
1258   { /* SSE66 */
1259     { "pcmpgdt", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1260     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1261     { "pcmpgdt", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1262     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1263   },
1264   { /* SSE67 */
1265     { "packuswb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1266     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1267     { "packuswb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1268     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1269   },
1270   { /* SSE68 */
1271     { "punpckhbw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1272     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1273     { "punpckhbw", t_done, 0, true, { Pdq, Qdq, Zz }, 0 },
1274     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1275   },
1276   { /* SSE69 */
1277     { "punpckhwd", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1278     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1279     { "punpckhwd", t_done, 0, true, { Pdq, Qdq, Zz }, 0 },
1280     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1281   },
1282   { /* SSE6A */
1283     { "punpckhdq", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1284     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1285     { "punpckhdq", t_done, 0, true, { Pdq, Qdq, Zz }, 0 },
1286     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1287   },
1288   { /* SSE6B */
1289     { "packssdw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1290     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1291     { "packssdw", t_done, 0, true, { Pdq, Qdq, Zz }, 0 },
1292     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1293   },
1294   { /* SSE6C */
1295     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1296     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1297     { "punpcklqld", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1298     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1299   },
1300   { /* SSE6D */
1301     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1302     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1303     { "punpckhqd", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1304     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1305   },
1306   { /* SSE6E */
1307     { "movd", t_done, 0, true, { Pd, Ed, Zz }, 0 },
1308     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1309     { "movd", t_done, 0, true, { Vdq, Ed, Zz }, 0 },
1310     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1311   },
1312   { /* SSE6F */
1313     { "movq", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1314     { "movdqu", t_done, 0, false, { Vdq, Wdq, Zz }, 0 }, // book has this and next swapped!!!
1315     { "movdqa", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1316     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1317   },
1318   { /* SSE70 */
1319     { "pshufw", t_done, 0, true, { Pq, Qq, Ib }, 0 },
1320     { "pshufhw", t_done, 0, true, { Vdq, Wdq, Ib }, 0 }, // book has this and next swapped!!!
1321     { "pshufd", t_done, 0, true, { Vdq, Wdq, Ib }, 0 },
1322     { "pshuflw", t_done, 0, true, { Vdq, Wdq, Ib }, 0 },
1323   },
1324   { /* SSE74 */
1325     { "pcmpeqb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1326     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1327     { "pcmpeqb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1328     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1329   },
1330   { /* SSE75 */
1331     { "pcmpeqw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1332     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1333     { "pcmpeqw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1334     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1335   },
1336   { /* SSE76 */
1337     { "pcmpeqd", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1338     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1339     { "pcmpeqd", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1340     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1341   },
1342   { /* SSE7E */
1343     { "movd", t_done, 0, true, { Ed, Pd, Zz }, 0 },
1344     { "movq", t_done, 0, true, { Vq, Wq, Zz }, 0 }, // book has this and next swapped!!!
1345     { "movd", t_done, 0, true, { Ed, Vdq, Zz }, 0 },
1346     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1347   },
1348   { /* SSE7F */
1349     { "movq", t_done, 0, true, { Qq, Pq, Zz }, 0 },
1350     { "movdqu", t_done, 0, true, { Wdq, Vdq, Zz }, 0 }, // book has this and next swapped!!!
1351     { "movdqa", t_done, 0, true, { Wdq, Vdq, Zz }, 0 },
1352     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1353   },
1354   { /* SSEC2 */
1355     { "cmpps", t_done, 0, true, { Vps, Wps, Ib }, 0 },
1356     { "cmpss", t_done, 0, true, { Vss, Wss, Ib }, 0 },
1357     { "cmppd", t_done, 0, true, { Vpd, Wpd, Ib }, 0 },
1358     { "cmpsd", t_done, 0, true, { Vsd, Wsd, Ib }, 0 },
1359   },
1360   { /* SSEC4 */
1361     { "pinsrw", t_done, 0, true, { Pq, Ed, Ib }, 0 },
1362     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1363     { "pinsrw", t_done, 0, true, { Vdq, Ed, Ib }, 0 },
1364     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1365   },
1366   { /* SSEC5 */
1367     { "pextrw", t_done, 0, true, { Gd, Pq, Ib }, 0 },
1368     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1369     { "pextrw", t_done, 0, true, { Gd, Vdq, Ib }, 0 },
1370     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1371   },
1372   { /* SSEC6 */
1373     { "shufps", t_done, 0, true, { Vps, Wps, Ib }, 0 },
1374     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1375     { "shufpd", t_done, 0, true, { Vpd, Wpd, Ib }, 0 },
1376     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1377   },
1378   { /* SSED1 */
1379     { "psrlw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1380     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1381     { "psrlw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1382     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1383   },
1384   { /* SSED2 */
1385     { "psrld", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1386     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1387     { "psrld", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1388     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1389   },
1390   { /* SSED3 */
1391     { "psrlq", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1392     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1393     { "psrlq", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1394     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1395   },
1396   { /* SSED4 */
1397     { "paddq", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1398     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1399     { "psrlq", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1400     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1401   },
1402   { /* SSED5 */
1403     { "pmullw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1404     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1405     { "pmullw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1406     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1407   },
1408   { /* SSED6 */
1409     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1410     { "movq2dq", t_done, 0, true, { Vdq, Qq, Zz }, 0 }, // lines jumbled in book
1411     { "movq", t_done, 0, true, { Wq, Vq, Zz }, 0 },
1412     { "movdq2q", t_done, 0, true, { Pq, Wq, Zz }, 0 },
1413   },
1414   { /* SSED7 */
1415     { "pmovmskb", t_done, 0, true, { Gd, Pq, Zz }, 0 },
1416     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1417     { "pmovmskb", t_done, 0, true, { Gd, Vdq, Zz }, 0 },
1418     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1419   },
1420   { /* SSED8 */
1421     { "psubusb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1422     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1423     { "psubusb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1424     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1425   },
1426   { /* SSED9 */
1427     { "psubusw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1428     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1429     { "psubusw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1430     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1431   },
1432   { /* SSEDA */
1433     { "pminub", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1434     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1435     { "pminub", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1436     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1437   },
1438   { /* SSEDB */
1439     { "pand", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1440     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1441     { "pand", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1442     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1443   },
1444   { /* SSEDC */
1445     { "paddusb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1446     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1447     { "paddusb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1448     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1449   },
1450   { /* SSEDD */
1451     { "paddusw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1452     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1453     { "paddusw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1454     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1455   },
1456   { /* SSEDE */
1457     { "pmaxub", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1458     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1459     { "pmaxub", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1460     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1461   },
1462   { /* SSEDF */
1463     { "pandn", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1464     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1465     { "pandn", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1466     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1467   },
1468   { /* SSEE0 */
1469     { "pavgb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1470     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1471     { "pavgb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1472     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1473   },
1474   { /* SSEE1 */
1475     { "psraw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1476     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1477     { "psraw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1478     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1479   },
1480   { /* SSEE2 */
1481     { "psrad", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1482     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1483     { "psrad", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1484     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1485   },
1486   { /* SSEE3 */
1487     { "pavgw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1488     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1489     { "pavgw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1490     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1491   },
1492   { /* SSEE4 */
1493     { "pmulhuw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1494     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1495     { "pmulhuw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1496     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1497   },
1498   { /* SSEE5 */
1499     { "pmulhw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1500     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1501     { "pmulhw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1502     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1503   },
1504   { /* SSEE6 */
1505     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1506     { "cvtdq2pd", t_done, 0, true, { Vpd, Wdq, Zz }, 0 }, // lines jumbled in book
1507     { "cvttpd2dq", t_done, 0, true, { Vdq, Wpd, Zz }, 0 },
1508     { "cvtpd2dq", t_done, 0, true, { Vdq, Wpd, Zz }, 0 },
1509   },
1510   { /* SSEE7 */
1511     { "movntq", t_done, 0, true, { Wq, Vq, Zz }, 0 },
1512     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1513     { "movntdq", t_done, 0, true, { Wdq, Vdq, Zz }, 0 },
1514     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1515   },
1516   { /* SSEE8 */
1517     { "psubsb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1518     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1519     { "psubsb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1520     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1521   },
1522   { /* SSEE9 */
1523     { "psubsw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1524     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1525     { "psubsw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1526     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1527   },
1528   { /* SSEEA */
1529     { "pminsw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1530     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1531     { "pminsw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1532     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1533   },
1534   { /* SSEEB */
1535     { "por", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1536     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1537     { "por", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1538     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1539   },
1540   { /* SSEEC */
1541     { "paddsb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1542     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1543     { "paddsb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1544     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1545   },
1546   { /* SSEED */
1547     { "paddsw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1548     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1549     { "paddsw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1550     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1551   },
1552   { /* SSEEE */
1553     { "pmaxsw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1554     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1555     { "pmaxsw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1556     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1557   },
1558   { /* SSEEF */
1559     { "pxor", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1560     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1561     { "pxor", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1562     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1563   },
1564   { /* SSEF1 */
1565     { "psllw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1566     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1567     { "psllw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1568     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1569   },
1570   { /* SSEF2 */
1571     { "pslld", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1572     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1573     { "pslld", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1574     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1575   },
1576   { /* SSEF3 */
1577     { "psllq", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1578     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1579     { "psllq", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1580     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1581   },
1582   { /* SSEF4 */
1583     { "pmuludq", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1584     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1585     { "pmuludq", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1586     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1587   },
1588   { /* SSEF5 */
1589     { "pmaddwd", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1590     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1591     { "pmaddwd", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1592     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1593   },
1594   { /* SSEF6 */
1595     { "psadbw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1596     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1597     { "psadbw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1598     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1599   },
1600   { /* SSEF7 */
1601     { "maskmovq", t_done, 0, true, { Ppi, Qpi, Zz }, 0 },
1602     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1603     { "maskmovqu", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1604     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1605   },
1606   { /* SSEF8 */
1607     { "psubb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1608     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1609     { "psubb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1610     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1611   },
1612   { /* SSEF9 */
1613     { "psubw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1614     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1615     { "psubw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1616     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1617   },
1618   { /* SSEFA */
1619     { "psubd", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1620     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1621     { "psubd", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1622     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1623   },
1624   { /* SSEFB */ // FIXME: Same????
1625     { "psubd", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1626     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1627     { "psubd", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1628     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1629   },
1630   { /* SSEFC */
1631     { "paddb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1632     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1633     { "paddb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1634     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1635   },
1636   { /* SSEFD */
1637     { "paddw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1638     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1639     { "paddw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1640     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1641   },
1642   { /* SSEFE */
1643     { "paddd", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1644     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1645     { "paddd", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1646     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1647   }
1648 };
1649
1650 /* rows are none or 66 prefixed in this order (see book) */
1651 static ia32_entry ssegrpMap[][2] = {
1652   /* G12SSE010B */
1653   {
1654     { "psrlw", t_done, 0, true, { Pq, Ib, Zz }, 0 },
1655     { "psrlw", t_done, 0, true, { Pdq, Ib, Zz }, 0 }
1656   },
1657   /* G12SSE100B */
1658   {
1659     { "psraw", t_done, 0, true, { Pq, Ib, Zz }, 0 },
1660     { "psraw", t_done, 0, true, { Pdq, Ib, Zz }, 0 }
1661   },
1662   /* G12SSE110B */
1663   {
1664     { "psllw", t_done, 0, true, { Pq, Ib, Zz }, 0 },
1665     { "psllw", t_done, 0, true, { Pdq, Ib, Zz }, 0 }
1666   },
1667   /* G13SSE010B */
1668   {
1669     { "psrld", t_done, 0, true, { Pq, Ib, Zz }, 0 },
1670     { "psrld", t_done, 0, true, { Wdq, Ib, Zz }, 0 }
1671   },
1672   /* G13SSE100B */
1673   {
1674     { "psrad", t_done, 0, true, { Pq, Ib, Zz }, 0 },
1675     { "psrad", t_done, 0, true, { Wdq, Ib, Zz }, 0 }
1676   },
1677   /* G13SSE110B */
1678   {
1679     { "pslld", t_done, 0, true, { Pq, Ib, Zz }, 0 },
1680     { "pslld", t_done, 0, true, { Wdq, Ib, Zz }, 0 }
1681   },
1682   /* G14SSE010B */
1683   {
1684     { "psrlq", t_done, 0, true, { Pq, Ib, Zz }, 0 },
1685     { "psrlq", t_done, 0, true, { Wdq, Ib, Zz }, 0 }
1686   },
1687   /* G14SSE011B */
1688   {
1689     { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
1690     { "psrldq", t_done, 0, true, { Wdq, Ib, Zz }, 0 }
1691   },
1692   /* G14SSE110B */
1693   {
1694     { "psllq", t_done, 0, true, { Pq, Ib, Zz }, 0 },
1695     { "psllq", t_done, 0, true, { Wdq, Ib, Zz }, 0 }
1696   },
1697   /* G14SSE111B */
1698   {
1699     { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
1700     { "pslldq", t_done, 0, true, { Wdq, Ib, Zz }, 0 }
1701   }
1702 };
1703
1704 static unsigned int ia32_decode_modrm(const unsigned int addrSzAttr, const unsigned char* addr);
1705
1706
1707 template <unsigned int capa>
1708 ia32_instruction& ia32_decode(const unsigned char* addr, ia32_instruction& instruct)
1709 {
1710   ia32_prefixes& pref = instruct.prf;
1711   unsigned int table, nxtab;
1712   unsigned int idx, sseidx = 0;
1713   ia32_entry *gotit = NULL;
1714
1715   ia32_decode_prefixes(addr, pref);
1716   instruct.size = pref.getCount();
1717   addr += instruct.size;
1718
1719   table = t_oneB;
1720   idx = addr[0];
1721   gotit = &oneByteMap[idx];
1722   nxtab = gotit->otable;
1723   instruct.size += 1;
1724   addr += 1;
1725
1726   while(nxtab != t_done) {
1727     table = nxtab;
1728     switch(table) {
1729     case t_twoB:
1730       idx = addr[0];
1731       gotit = &twoByteMap[idx];
1732       nxtab = gotit->otable;
1733       instruct.size += 1;
1734       addr += 1;
1735       break;
1736     case t_prefixedSSE:
1737       sseidx = gotit->tabidx;
1738       assert(addr[0] == 0x0F);
1739       idx = addr[1];
1740       gotit = &twoByteMap[idx];
1741       nxtab = gotit->otable;
1742       instruct.size += 2;
1743       addr += 2;
1744       break;
1745     case t_sse:
1746       idx = gotit->tabidx;
1747       gotit = &sseMap[idx][sseidx];
1748       nxtab = gotit->otable;
1749       break;
1750     case t_grp: {
1751       idx = gotit->tabidx;
1752       unsigned int reg  = (addr[0] >> 3) & 7;
1753       if(idx < Grp12)
1754         switch(idx) {
1755         case Grp1:
1756         case Grp2:
1757         case Grp8:
1758         case Grp11:
1759           // leave table unchanged because operands are in not defined in group map
1760           nxtab = groupMap[idx][reg].otable;
1761           assert(nxtab==t_done || nxtab==t_ill);
1762           break;
1763         default:
1764           gotit = &groupMap[idx][reg];
1765           nxtab = gotit->otable;
1766         }
1767       else {
1768         unsigned int mod = addr[0] >> 6;
1769         gotit = &groupMap2[idx-Grp12][mod==3][reg];
1770       }
1771       break;
1772     }
1773     case t_grpsse:
1774       sseidx >>= 1;
1775       idx = gotit->tabidx;
1776       gotit = &ssegrpMap[idx][sseidx];
1777       break;
1778     case t_coprocEsc:
1779       instruct.legacy_type = 0;
1780       return ia32_decode_FP(pref, addr, instruct);
1781     case t_3dnow:
1782       // 3D now opcodes are given as suffix: ModRM [SIB] [displacement] opcode
1783       // Right now we don't care what the actual opcode is, so there's no table
1784       instruct.size += 1;
1785       break;
1786     case t_ill:
1787       instruct.legacy_type = ILLEGAL;
1788       return instruct;
1789     default:
1790       assert(!"wrong table");
1791     }
1792   }
1793
1794   // addr points after the opcode, and the size has been adjusted accordingly
1795   // also the SSE index is set; now 'table' points to the correct instruction map
1796
1797   assert(gotit != NULL);
1798   instruct.legacy_type = gotit->legacyType;
1799
1800   ia32_decode_operands(pref, *gotit, addr, instruct); // all but FP
1801
1802   return instruct;
1803 }
1804
1805 template ia32_instruction& ia32_decode<0>(const unsigned char* addr, ia32_instruction& instruct);
1806
1807 ia32_instruction& ia32_decode_FP(const ia32_prefixes& pref, const unsigned char* addr,
1808                                  ia32_instruction& instruct)
1809 {
1810   unsigned int nib = byteSzB; // modRM
1811   unsigned int addrSzAttr = (pref.getPrefix(3) == PREFIX_SZADDR ? 1 : 2); // 32-bit mode implicit
1812
1813   if (addr[0] <= 0xBF) { // modrm
1814     nib += ia32_decode_modrm(addrSzAttr, addr);
1815   }
1816   instruct.size += nib;
1817
1818   return instruct;
1819 }
1820
1821 static unsigned int ia32_decode_modrm(const unsigned int addrSzAttr, const unsigned char* addr)
1822 {
1823   unsigned char modrm = addr[0];
1824   unsigned char mod = modrm >> 6;
1825   unsigned char rm  = modrm & 7;
1826   //unsigned char reg = (modrm >> 3) & 7;
1827
1828   if(addrSzAttr == 1) { // 16-bit, cannot have SIB
1829     switch(mod) {
1830     case 0:
1831       return rm==6 ? wordSzB : 0;
1832     case 1:
1833       return byteSzB;
1834     case 2:
1835       return wordSzB;
1836     case 3:
1837       return 0; // register
1838     default:
1839       assert(0);
1840     }
1841   }
1842   else { // 32-bit, may have SIB
1843     if(mod == 3)
1844       return 0; // only registers, no SIB
1845     bool hassib = rm == 4;
1846     unsigned int nsib = 0;
1847     unsigned char sib;
1848     unsigned char base = 0;
1849     if(hassib) {
1850       nsib = byteSzB;
1851       sib = addr[1];
1852       base = sib & 7;
1853     }
1854     switch(mod) {
1855     case 0: {
1856       /* this is tricky: there is a disp32 iff (1) rm == 5  or  (2) rm == 4 && base == 5 */
1857       unsigned char check5 = hassib ? base : rm;
1858       return nsib + ((check5 == 5) ? dwordSzB : 0);
1859     }
1860     case 1:
1861       return nsib + byteSzB;
1862     case 2:
1863       return nsib + dwordSzB;
1864     default:
1865       assert(0);
1866     }
1867   }
1868 }
1869
1870
1871 unsigned int ia32_decode_operands (const ia32_prefixes& pref, const ia32_entry& gotit, 
1872                                    const unsigned char* addr, ia32_instruction& instruct)
1873 {
1874   unsigned int nib = 0; /* # of bytes in instruction */
1875   unsigned int addrSzAttr = (pref.getPrefix(3) == PREFIX_SZADDR ? 1 : 2); // 32-bit mode implicit
1876   unsigned int operSzAttr = (pref.getPrefix(2) == PREFIX_SZOPER ? 1 : 2); // 32-bit mode implicit
1877
1878   if(gotit.hasModRM)
1879     nib += byteSzB;
1880
1881   for(unsigned int i=0; i<3; ++i) {
1882     const ia32_operand& op = gotit.operands[i];
1883     if(op.admet) {
1884       switch(op.admet) {
1885       case am_A: /* address = segment + offset (word or dword) */
1886         nib += wordSzB;
1887       case am_O: /* operand offset */
1888         nib += wordSzB * addrSzAttr;
1889         break;
1890       case am_C:   /* control register */
1891       case am_D:   /* debug register */
1892       case am_F:   /* flags register */
1893       case am_G:   /* general purpose register, selecteb by reg field */
1894       case am_P:   /* MMX register */
1895       case am_R:   /* general purpose register, selected by mod field */
1896       case am_S:   /* segment register */
1897       case am_T:   /* test register */
1898       case am_V:   /* XMM register */
1899       case am_reg: /* register implicitely encoded in opcode */
1900         break;
1901       case am_E: /* register or memory location, so decoding needed */
1902       case am_M: /* memory operand, decoding needed; size includes modRM byte */
1903       case am_Q: /* MMX register or memory location */
1904       case am_W: /* XMM register or memory location */
1905         nib += ia32_decode_modrm(addrSzAttr, addr);
1906         break;
1907       case am_I: /* immediate data */
1908       case am_J: /* instruction pointer offset */
1909         switch(op.optype) {
1910         case op_b:
1911           nib += byteSzB;
1912           break;
1913         case op_v:
1914           nib += wordSzB * operSzAttr;
1915           break;
1916         case op_w:
1917           nib += wordSzB;
1918         }
1919         break;
1920         /* Don't forget these... */
1921       case am_X: /* memory at DS:(E)SI*/
1922       case am_Y: /* memory at ES:(E)DI*/
1923         break;
1924       default:
1925         assert(0);
1926       }
1927     }
1928     else
1929       break;
1930   }
1931   instruct.size += nib;
1932   return nib;
1933 }
1934
1935
1936 static const unsigned char sse_prefix[256] = {
1937   /*       0 1 2 3 4 5 6 7 8 9 A B C D E F  */
1938   /* 0x */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1939   /* 1x */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,
1940   /* 2x */ 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,
1941   /* 3x */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1942   /* 4x */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1943   /* 5x */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1944   /* 6x */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1945   /* 7x */ 1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1, // Grp12-14 are SSE groups
1946   /* 8x */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1947   /* 9x */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1948   /* Ax */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1949   /* Bx */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1950   /* Cx */ 0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,
1951   /* Dx */ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1952   /* Ex */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1953   /* Fx */ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0
1954 };
1955
1956
1957 // FIXME: lookahead might blow up...
1958 ia32_prefixes& ia32_decode_prefixes(const unsigned char* addr, ia32_prefixes& pref)
1959 {
1960   pref.count = 0;
1961   pref.prfx[0] = pref.prfx[1] = pref.prfx[2] = pref.prfx[3] = 0;
1962   bool in_prefix = true;
1963
1964   while(in_prefix) {
1965     switch(addr[0]) {
1966     case PREFIX_REPNZ:
1967     case PREFIX_REP:
1968       if(addr[1]==0x0F && sse_prefix[addr[2]])
1969         break;
1970     case PREFIX_LOCK:
1971       ++pref.count;
1972       pref.prfx[0] = addr[0];
1973       break;
1974     case PREFIX_SEGCS:
1975     case PREFIX_SEGSS:
1976     case PREFIX_SEGDS:
1977     case PREFIX_SEGES:
1978     case PREFIX_SEGFS:
1979     case PREFIX_SEGGS:
1980       ++pref.count;
1981       pref.prfx[1] = addr[0];
1982       break;
1983     case PREFIX_SZOPER:
1984       if(addr[1]==0x0F && sse_prefix[addr[2]])
1985         break;
1986       ++pref.count;
1987       pref.prfx[2] = addr[0];
1988       break;
1989     case PREFIX_SZADDR:
1990       ++pref.count;
1991       pref.prfx[3] = addr[0];
1992       break;
1993     default:
1994       in_prefix=false;
1995     }
1996     ++addr;
1997   }
1998   
1999   //printf("Got %d prefixes\n", pref.count);
2000   return pref;
2001 }
2002
2003 unsigned int ia32_emulate_old_type(ia32_instruction& instruct)
2004 {
2005   const ia32_prefixes& pref = instruct.prf;
2006   unsigned int& insnType = instruct.legacy_type;
2007   unsigned int operSzAttr = (pref.getPrefix(2) == PREFIX_SZOPER ? 1 : 2); // 32-bit mode implicit
2008
2009   if (pref.getPrefix(0)) // no distinction between these
2010     insnType |= PREFIX_INST;
2011   if (pref.getPrefix(3) == PREFIX_SZADDR)
2012     insnType |= PREFIX_ADDR;
2013   if (pref.getPrefix(2) == PREFIX_SZOPER)
2014     insnType |= PREFIX_OPR;
2015   if (pref.getPrefix(1))
2016     insnType |= PREFIX_SEG; // no distinction between segments
2017
2018   if (insnType & REL_X) {
2019     if (operSzAttr == 1)
2020       insnType |= REL_W;
2021     else
2022       insnType |= REL_D;
2023   }
2024   else if (insnType & PTR_WX) {
2025     if (operSzAttr == 1)
2026       insnType |= PTR_WW;
2027     else
2028       insnType |= PTR_WD;
2029   }
2030
2031   return insnType;
2032 }