Fixed MMX register addressing mode
[dyninst.git] / dyninstAPI / src / arch-ia32.C
1 // $Id: arch-ia32.C,v 1.2 2002/06/07 20:17:54 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_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
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   { "syscallAMD", t_done, 0, false, { Zz, Zz, Zz }, 0 },
477   { "clts",       t_done, 0, false, { Zz, Zz, Zz }, 0 },
478   { "sysretAMD",  t_done, 0, false, { Zz, Zz, Zz }, 0 },
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   {0, t_ill, 0,0, { Zz, Zz, Zz },0}, // FIXME: AMD 3DNOW
486   {0, t_ill, 0,0 ,{ Zz, Zz, Zz },0}, // FIXME: AMD 3DNOW
487   {0, t_ill, 0,0 ,{ Zz, Zz, Zz },0}, // FIXME: AMD 3DNOW
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 };
1005
1006 /* rows are not, F3, 66, F2 prefixed in this order (see book) */
1007 static ia32_entry sseMap[][4] = {
1008   { /* SSE10 */
1009     { "movups", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1010     { "movss",  t_done, 0, true, { Vss, Wss, Zz }, 0 },
1011     { "movupd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1012     { "movsd",  t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1013   },
1014   { /* SSE11 */
1015     { "movups", t_done, 0, true, { Wps, Vps, Zz }, 0 },
1016     { "movss",  t_done, 0, true, { Wss, Vss, Zz }, 0 },
1017     { "movupd", t_done, 0, true, { Wpd, Vpd, Zz }, 0 },
1018     { "movsd",  t_done, 0, true, { Vsd, Wsd, Zz }, 0 }, // FIXME: bug in book?????
1019   },
1020   { /* SSE12 */
1021     { "movlps/movhlps", t_done, 0, true, { Wq, Vq, Zz }, 0 }, // FIXME: wierd 1st op
1022     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1023     { "movlpd", t_done, 0, true, { Vq, Ws, Zz }, 0 },
1024     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1025   },
1026   { /* SSE13 */
1027     { "movlps", t_done, 0, true, { Vq, Wq, Zz }, 0 },
1028     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1029     { "movlpd", t_done, 0, true, { Vq, Wq, Zz }, 0 },
1030     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1031   },
1032   { /* SSE14 */
1033     { "unpcklps", t_done, 0, true, { Vps, Wq, Zz }, 0 },
1034     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1035     { "unpcklpd", t_done, 0, true, { Vpd, Wq, Zz }, 0 },
1036     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1037   },
1038   { /* SSE15 */
1039     { "unpckhps", t_done, 0, true, { Vps, Wq, Zz }, 0 },
1040     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1041     { "unpckhpd", t_done, 0, true, { Vpd, Wq, Zz }, 0 },
1042     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1043   },
1044   { /* SSE16 */
1045     { "movhps/movlhps", t_done, 0, true, { Vq, Wq, Zz }, 0 }, // FIXME: wierd 2nd op
1046     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1047     { "movhpd", t_done, 0, true, { Vq, Wq, Zz }, 0 },
1048     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1049   },
1050   { /* SSE17 */
1051     { "movhps", t_done, 0, true, { Wq, Vq, Zz }, 0 },
1052     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1053     { "movhpd", t_done, 0, true, { Wq, Vq, Zz }, 0 },
1054     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1055   },
1056   { /* SSE28 */
1057     { "movaps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1058     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1059     { "movapd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1060     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1061   },
1062   { /* SSE29 */
1063     { "movaps", t_done, 0, true, { Wps, Vps, Zz }, 0 },
1064     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1065     { "movapd", t_done, 0, true, { Wpd, Vpd, Zz }, 0 },
1066     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1067   },
1068   { /* SSE2A */
1069     { "cvtpi2ps", t_done, 0, true, { Vps, Qq, Zz }, 0 },
1070     { "cvtsi2ss", t_done, 0, true, { Vss, Ed, Zz }, 0 },
1071     { "cvtpi2pd", t_done, 0, true, { Vpd, Qdq, Zz }, 0 },
1072     { "cvtsi2sd", t_done, 0, true, { Vsd, Ed, Zz }, 0 },
1073   },
1074   { /* SSE2B */
1075     { "movntps", t_done, 0, true, { Wps, Vps, Zz }, 0 },
1076     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1077     { "movntps", t_done, 0, true, { Wpd, Vpd, Zz }, 0 }, // should be movntpd ???
1078     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1079   },
1080   { /* SSE2C */
1081     { "cvttps2pi", t_done, 0, true, { Qq, Wps, Zz }, 0 },
1082     { "cvttss2si", t_done, 0, true, { Gd, Wss, Zz }, 0 },
1083     { "cvttpd2pi", t_done, 0, true, { Qdq, Wpd, Zz }, 0 },
1084     { "cvttsd2si", t_done, 0, true, { Gd, Wsd, Zz }, 0 },
1085   },
1086   { /* SSE2D */
1087     { "cvtps2pi", t_done, 0, true, { Qq, Wps, Zz }, 0 },
1088     { "cvtss2si", t_done, 0, true, { Gd, Wss, Zz }, 0 },
1089     { "cvtpd2pi", t_done, 0, true, { Qdq, Wpd, Zz }, 0 },
1090     { "cvtsd2si", t_done, 0, true, { Gd, Wsd, Zz }, 0 },
1091   },
1092   { /* SSE2E */
1093     { "ucomiss", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1094     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1095     { "ucomisd", t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1096     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1097   },
1098   { /* SSE2F */
1099     { "comiss", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1100     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1101     { "comisd", t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1102     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1103   },
1104   { /* SSE50 */
1105     { "movmskps", t_done, 0, true, { Ed, Vps, Zz }, 0 },
1106     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1107     { "movmskpd", t_done, 0, true, { Ed, Vpd, Zz }, 0 },
1108     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1109   },
1110   { /* SSE51 */
1111     { "sqrtps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1112     { "sqrtss", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1113     { "sqrtpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1114     { "sqrtsd", t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1115   },
1116   { /* SSE52 */
1117     { "rsqrtps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1118     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1119     { "rsqrtss", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1120     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1121   },
1122   { /* SSE53 */
1123     { "rcpps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1124     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1125     { "rcpss", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1126     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1127   },
1128   { /* SSE54 */
1129     { "andps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1130     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1131     { "andpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1132     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1133   },
1134   { /* SSE55 */
1135     { "andnps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1136     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1137     { "andnpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1138     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1139   },
1140   { /* SSE56 */
1141     { "orps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1142     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1143     { "orpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1144     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1145   },
1146   { /* SSE57 */
1147     { "xorps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1148     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1149     { "xorpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1150     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1151   },
1152   { /* SSE58 */
1153     { "addps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1154     { "addss", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1155     { "addpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1156     { "addsd", t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1157   },
1158   { /* SSE59 */
1159     { "mulps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1160     { "mulss", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1161     { "mulpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1162     { "mulsd", t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1163   },
1164   { /* SSE5A */
1165     { "cvtps2pd", t_done, 0, true, { Vpd, Wps, Zz }, 0 },
1166     { "cvtss2sd", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1167     { "cvtpd2ps", t_done, 0, true, { Vps, Wpd, Zz }, 0 }, // FIXME: book bug ???
1168     { "cvtsd2ss", t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1169   },
1170   { /* SSE5B */
1171     { "cvtdq2ps", t_done, 0, true, { Vps, Wdq, Zz }, 0 },
1172     { "cvttps2dq", t_done, 0, true, { Vdq, Wps, Zz }, 0 }, // book has this and next swapped!!! 
1173     { "cvtps2dq", t_done, 0, true, { Vdq, Wps, Zz }, 0 },  // FIXME: book bug ???
1174     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1175   },
1176   { /* SSE5C */
1177     { "subps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1178     { "subss", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1179     { "subpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1180     { "subsd", t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1181   },
1182   { /* SSE5D */
1183     { "minps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1184     { "minss", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1185     { "minpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1186     { "minsd", t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1187   },
1188   { /* SSE5E */
1189     { "divps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1190     { "divss", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1191     { "divpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1192     { "divsd", t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1193   },
1194   { /* SSE5F */
1195     { "maxps", t_done, 0, true, { Vps, Wps, Zz }, 0 },
1196     { "maxss", t_done, 0, true, { Vss, Wss, Zz }, 0 },
1197     { "maxpd", t_done, 0, true, { Vpd, Wpd, Zz }, 0 },
1198     { "maxsd", t_done, 0, true, { Vsd, Wsd, Zz }, 0 },
1199   },
1200   { /* SSE60 */
1201     { "punpcklbw", t_done, 0, true, { Pq, Qd, Zz }, 0 },
1202     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1203     { "punpcklbw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1204     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1205   },
1206   { /* SSE61 */
1207     { "punpcklwd", t_done, 0, true, { Pq, Qd, Zz }, 0 },
1208     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1209     { "punpcklwd", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1210     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1211   },
1212   { /* SSE62 */
1213     { "punpcklqd", t_done, 0, true, { Pq, Qd, Zz }, 0 },
1214     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1215     { "punpcklqd", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1216     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1217   },
1218   { /* SSE63 */
1219     { "packsswb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1220     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1221     { "packsswb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1222     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1223   },
1224   { /* SSE64 */
1225     { "pcmpgtb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1226     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1227     { "pcmpgtb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1228     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1229   },
1230   { /* SSE65 */
1231     { "pcmpgtw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1232     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1233     { "pcmpgtw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1234     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1235   },
1236   { /* SSE66 */
1237     { "pcmpgdt", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1238     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1239     { "pcmpgdt", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1240     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1241   },
1242   { /* SSE67 */
1243     { "packuswb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1244     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1245     { "packuswb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1246     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1247   },
1248   { /* SSE68 */
1249     { "punpckhbw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1250     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1251     { "punpckhbw", t_done, 0, true, { Pdq, Qdq, Zz }, 0 },
1252     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1253   },
1254   { /* SSE69 */
1255     { "punpckhwd", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1256     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1257     { "punpckhwd", t_done, 0, true, { Pdq, Qdq, Zz }, 0 },
1258     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1259   },
1260   { /* SSE6A */
1261     { "punpckhdq", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1262     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1263     { "punpckhdq", t_done, 0, true, { Pdq, Qdq, Zz }, 0 },
1264     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1265   },
1266   { /* SSE6B */
1267     { "packssdw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1268     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1269     { "packssdw", t_done, 0, true, { Pdq, Qdq, Zz }, 0 },
1270     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1271   },
1272   { /* SSE6C */
1273     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1274     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1275     { "punpcklqld", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1276     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1277   },
1278   { /* SSE6D */
1279     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1280     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1281     { "punpckhqd", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1282     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1283   },
1284   { /* SSE6E */
1285     { "movd", t_done, 0, true, { Pd, Ed, Zz }, 0 },
1286     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1287     { "movd", t_done, 0, true, { Vdq, Ed, Zz }, 0 },
1288     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1289   },
1290   { /* SSE6F */
1291     { "movq", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1292     { "movdqu", t_done, 0, false, { Vdq, Wdq, Zz }, 0 }, // book has this and next swapped!!!
1293     { "movdqa", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1294     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1295   },
1296   { /* SSE70 */
1297     { "pshufw", t_done, 0, true, { Pq, Qq, Ib }, 0 },
1298     { "pshufhw", t_done, 0, true, { Vdq, Wdq, Ib }, 0 }, // book has this and next swapped!!!
1299     { "pshufd", t_done, 0, true, { Vdq, Wdq, Ib }, 0 },
1300     { "pshuflw", t_done, 0, true, { Vdq, Wdq, Ib }, 0 },
1301   },
1302   { /* SSE74 */
1303     { "pcmpeqb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1304     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1305     { "pcmpeqb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1306     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1307   },
1308   { /* SSE75 */
1309     { "pcmpeqw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1310     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1311     { "pcmpeqw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1312     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1313   },
1314   { /* SSE76 */
1315     { "pcmpeqd", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1316     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1317     { "pcmpeqd", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1318     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1319   },
1320   { /* SSE7E */
1321     { "movd", t_done, 0, true, { Ed, Pd, Zz }, 0 },
1322     { "movq", t_done, 0, true, { Vq, Wq, Zz }, 0 }, // book has this and next swapped!!!
1323     { "movd", t_done, 0, true, { Ed, Vdq, Zz }, 0 },
1324     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1325   },
1326   { /* SSE7F */
1327     { "movq", t_done, 0, true, { Qq, Pq, Zz }, 0 },
1328     { "movdqu", t_done, 0, true, { Wdq, Vdq, Zz }, 0 }, // book has this and next swapped!!!
1329     { "movdqa", t_done, 0, true, { Wdq, Vdq, Zz }, 0 },
1330     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1331   },
1332   { /* SSEC2 */
1333     { "cmpps", t_done, 0, true, { Vps, Wps, Ib }, 0 },
1334     { "cmpss", t_done, 0, true, { Vss, Wss, Ib }, 0 },
1335     { "cmppd", t_done, 0, true, { Vpd, Wpd, Ib }, 0 },
1336     { "cmpsd", t_done, 0, true, { Vsd, Wsd, Ib }, 0 },
1337   },
1338   { /* SSEC4 */
1339     { "pinsrw", t_done, 0, true, { Pq, Ed, Ib }, 0 },
1340     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1341     { "pinsrw", t_done, 0, true, { Vdq, Ed, Ib }, 0 },
1342     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1343   },
1344   { /* SSEC5 */
1345     { "pextrw", t_done, 0, true, { Gd, Pq, Ib }, 0 },
1346     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1347     { "pextrw", t_done, 0, true, { Gd, Vdq, Ib }, 0 },
1348     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1349   },
1350   { /* SSEC6 */
1351     { "shufps", t_done, 0, true, { Vps, Wps, Ib }, 0 },
1352     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1353     { "shufpd", t_done, 0, true, { Vpd, Wpd, Ib }, 0 },
1354     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1355   },
1356   { /* SSED1 */
1357     { "psrlw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1358     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1359     { "psrlw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1360     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1361   },
1362   { /* SSED2 */
1363     { "psrld", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1364     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1365     { "psrld", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1366     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1367   },
1368   { /* SSED3 */
1369     { "psrlq", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1370     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1371     { "psrlq", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1372     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1373   },
1374   { /* SSED4 */
1375     { "paddq", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1376     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1377     { "psrlq", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1378     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1379   },
1380   { /* SSED5 */
1381     { "pmullw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1382     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1383     { "pmullw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1384     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1385   },
1386   { /* SSED6 */
1387     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1388     { "movq2dq", t_done, 0, true, { Vdq, Qq, Zz }, 0 }, // lines jumbled in book
1389     { "movq", t_done, 0, true, { Wq, Vq, Zz }, 0 },
1390     { "movdq2q", t_done, 0, true, { Pq, Wq, Zz }, 0 },
1391   },
1392   { /* SSED7 */
1393     { "pmovmskb", t_done, 0, true, { Gd, Pq, Zz }, 0 },
1394     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1395     { "pmovmskb", t_done, 0, true, { Gd, Vdq, Zz }, 0 },
1396     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1397   },
1398   { /* SSED8 */
1399     { "psubusb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1400     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1401     { "psubusb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1402     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1403   },
1404   { /* SSED9 */
1405     { "psubusw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1406     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1407     { "psubusw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1408     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1409   },
1410   { /* SSEDA */
1411     { "pminub", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1412     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1413     { "pminub", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1414     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1415   },
1416   { /* SSEDB */
1417     { "pand", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1418     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1419     { "pand", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1420     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1421   },
1422   { /* SSEDC */
1423     { "paddusb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1424     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1425     { "paddusb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1426     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1427   },
1428   { /* SSEDD */
1429     { "paddusw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1430     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1431     { "paddusw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1432     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1433   },
1434   { /* SSEDE */
1435     { "pmaxub", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1436     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1437     { "pmaxub", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1438     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1439   },
1440   { /* SSEDF */
1441     { "pandn", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1442     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1443     { "pandn", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1444     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1445   },
1446   { /* SSEE0 */
1447     { "pavgb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1448     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1449     { "pavgb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1450     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1451   },
1452   { /* SSEE1 */
1453     { "psraw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1454     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1455     { "psraw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1456     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1457   },
1458   { /* SSEE2 */
1459     { "psrad", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1460     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1461     { "psrad", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1462     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1463   },
1464   { /* SSEE3 */
1465     { "pavgw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1466     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1467     { "pavgw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1468     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1469   },
1470   { /* SSEE4 */
1471     { "pmulhuw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1472     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1473     { "pmulhuw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1474     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1475   },
1476   { /* SSEE5 */
1477     { "pmulhw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1478     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1479     { "pmulhw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1480     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1481   },
1482   { /* SSEE6 */
1483     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1484     { "cvtdq2pd", t_done, 0, true, { Vpd, Wdq, Zz }, 0 }, // lines jumbled in book
1485     { "cvttpd2dq", t_done, 0, true, { Vdq, Wpd, Zz }, 0 },
1486     { "cvtpd2dq", t_done, 0, true, { Vdq, Wpd, Zz }, 0 },
1487   },
1488   { /* SSEE7 */
1489     { "movntq", t_done, 0, true, { Wq, Vq, Zz }, 0 },
1490     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1491     { "movntdq", t_done, 0, true, { Wdq, Vdq, Zz }, 0 },
1492     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1493   },
1494   { /* SSEE8 */
1495     { "psubsb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1496     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1497     { "psubsb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1498     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1499   },
1500   { /* SSEE9 */
1501     { "psubsw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1502     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1503     { "psubsw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1504     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1505   },
1506   { /* SSEEA */
1507     { "pminsw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1508     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1509     { "pminsw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1510     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1511   },
1512   { /* SSEEB */
1513     { "por", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1514     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1515     { "por", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1516     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1517   },
1518   { /* SSEEC */
1519     { "paddsb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1520     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1521     { "paddsb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1522     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1523   },
1524   { /* SSEED */
1525     { "paddsw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1526     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1527     { "paddsw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1528     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1529   },
1530   { /* SSEEE */
1531     { "pmaxsw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1532     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1533     { "pmaxsw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1534     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1535   },
1536   { /* SSEEF */
1537     { "pxor", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1538     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1539     { "pxor", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1540     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1541   },
1542   { /* SSEF1 */
1543     { "psllw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1544     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1545     { "psllw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1546     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1547   },
1548   { /* SSEF2 */
1549     { "pslld", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1550     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1551     { "pslld", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1552     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1553   },
1554   { /* SSEF3 */
1555     { "psllq", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1556     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1557     { "psllq", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1558     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1559   },
1560   { /* SSEF4 */
1561     { "pmuludq", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1562     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1563     { "pmuludq", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1564     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1565   },
1566   { /* SSEF5 */
1567     { "pmaddwd", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1568     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1569     { "pmaddwd", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1570     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1571   },
1572   { /* SSEF6 */
1573     { "psadbw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1574     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1575     { "psadbw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1576     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1577   },
1578   { /* SSEF7 */
1579     { "maskmovq", t_done, 0, true, { Ppi, Qpi, Zz }, 0 },
1580     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1581     { "maskmovqu", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1582     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1583   },
1584   { /* SSEF8 */
1585     { "psubb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1586     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1587     { "psubb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1588     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1589   },
1590   { /* SSEF9 */
1591     { "psubw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1592     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1593     { "psubw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1594     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1595   },
1596   { /* SSEFA */
1597     { "psubd", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1598     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1599     { "psubd", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1600     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1601   },
1602   { /* SSEFB */ // FIXME: Same????
1603     { "psubd", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1604     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1605     { "psubd", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1606     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1607   },
1608   { /* SSEFC */
1609     { "paddb", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1610     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1611     { "paddb", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1612     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1613   },
1614   { /* SSEFD */
1615     { "paddw", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1616     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1617     { "paddw", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1618     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1619   },
1620   { /* SSEFE */
1621     { "paddd", t_done, 0, true, { Pq, Qq, Zz }, 0 },
1622     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1623     { "paddd", t_done, 0, true, { Vdq, Wdq, Zz }, 0 },
1624     { 0, t_ill, 0, false, { Zz, Zz, Zz }, 0 },
1625   }
1626 };
1627
1628 /* rows are none or 66 prefixed in this order (see book) */
1629 static ia32_entry ssegrpMap[][2] = {
1630   /* G12SSE010B */
1631   {
1632     { "psrlw", t_done, 0, true, { Pq, Ib, Zz }, 0 },
1633     { "psrlw", t_done, 0, true, { Pdq, Ib, Zz }, 0 }
1634   },
1635   /* G12SSE100B */
1636   {
1637     { "psraw", t_done, 0, true, { Pq, Ib, Zz }, 0 },
1638     { "psraw", t_done, 0, true, { Pdq, Ib, Zz }, 0 }
1639   },
1640   /* G12SSE110B */
1641   {
1642     { "psllw", t_done, 0, true, { Pq, Ib, Zz }, 0 },
1643     { "psllw", t_done, 0, true, { Pdq, Ib, Zz }, 0 }
1644   },
1645   /* G13SSE010B */
1646   {
1647     { "psrld", t_done, 0, true, { Pq, Ib, Zz }, 0 },
1648     { "psrld", t_done, 0, true, { Wdq, Ib, Zz }, 0 }
1649   },
1650   /* G13SSE100B */
1651   {
1652     { "psrad", t_done, 0, true, { Pq, Ib, Zz }, 0 },
1653     { "psrad", t_done, 0, true, { Wdq, Ib, Zz }, 0 }
1654   },
1655   /* G13SSE110B */
1656   {
1657     { "pslld", t_done, 0, true, { Pq, Ib, Zz }, 0 },
1658     { "pslld", t_done, 0, true, { Wdq, Ib, Zz }, 0 }
1659   },
1660   /* G14SSE010B */
1661   {
1662     { "psrlq", t_done, 0, true, { Pq, Ib, Zz }, 0 },
1663     { "psrlq", t_done, 0, true, { Wdq, Ib, Zz }, 0 }
1664   },
1665   /* G14SSE011B */
1666   {
1667     { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
1668     { "psrldq", t_done, 0, true, { Wdq, Ib, Zz }, 0 }
1669   },
1670   /* G14SSE110B */
1671   {
1672     { "psllq", t_done, 0, true, { Pq, Ib, Zz }, 0 },
1673     { "psllq", t_done, 0, true, { Wdq, Ib, Zz }, 0 }
1674   },
1675   /* G14SSE111B */
1676   {
1677     { 0, t_ill, 0, true, { Zz, Zz, Zz }, 0 },
1678     { "pslldq", t_done, 0, true, { Wdq, Ib, Zz }, 0 }
1679   }
1680 };
1681
1682 static unsigned int ia32_decode_modrm(const unsigned int addrSzAttr, const unsigned char* addr);
1683
1684
1685 template <unsigned int capa>
1686 ia32_instruction& ia32_decode(const unsigned char* addr, ia32_instruction& instruct)
1687 {
1688   ia32_prefixes& pref = instruct.prf;
1689   unsigned int table, nxtab;
1690   unsigned int idx, sseidx = 0;
1691   ia32_entry *gotit = NULL;
1692
1693   ia32_decode_prefixes(addr, pref);
1694   instruct.size = pref.getCount();
1695   addr += instruct.size;
1696
1697   table = t_oneB;
1698   idx = addr[0];
1699   gotit = &oneByteMap[idx];
1700   nxtab = gotit->otable;
1701   instruct.size += 1;
1702   addr += 1;
1703
1704   while(nxtab != t_done) {
1705     table = nxtab;
1706     switch(table) {
1707     case t_twoB:
1708       idx = addr[0];
1709       gotit = &twoByteMap[idx];
1710       nxtab = gotit->otable;
1711       instruct.size += 1;
1712       addr += 1;
1713       break;
1714     case t_prefixedSSE:
1715       sseidx = gotit->tabidx;
1716       assert(addr[0] == 0x0F);
1717       idx = addr[1];
1718       gotit = &twoByteMap[idx];
1719       nxtab = gotit->otable;
1720       instruct.size += 2;
1721       addr += 2;
1722       break;
1723     case t_sse:
1724       idx = gotit->tabidx;
1725       gotit = &sseMap[idx][sseidx];
1726       nxtab = gotit->otable;
1727       break;
1728     case t_grp: {
1729       idx = gotit->tabidx;
1730       unsigned int reg  = (addr[0] >> 3) & 7;
1731       if(idx < Grp12)
1732         switch(idx) {
1733         case Grp1:
1734         case Grp2:
1735         case Grp8:
1736         case Grp11:
1737           // leave table unchanged because operands are in not defined in group map
1738           nxtab = groupMap[idx][reg].otable;
1739           assert(nxtab==t_done || nxtab==t_ill);
1740           break;
1741         default:
1742           gotit = &groupMap[idx][reg];
1743           nxtab = gotit->otable;
1744         }
1745       else {
1746         unsigned int mod = addr[0] >> 6;
1747         gotit = &groupMap2[idx-Grp12][mod==3][reg];
1748       }
1749       break;
1750     }
1751     case t_grpsse:
1752       sseidx >>= 1;
1753       idx = gotit->tabidx;
1754       gotit = &ssegrpMap[idx][sseidx];
1755       break;
1756     case t_coprocEsc:
1757       instruct.legacy_type = 0;
1758       return ia32_decode_FP(pref, addr, instruct);
1759     case t_ill:
1760       instruct.legacy_type = ILLEGAL;
1761       return instruct;
1762     default:
1763       assert(!"wrong table");
1764     }
1765   }
1766
1767   // addr points after the opcode, and the size has been adjusted accordingly
1768   // also the SSE index is set; now 'table' points to the correct instruction map
1769
1770   assert(gotit != NULL);
1771   instruct.legacy_type = gotit->legacyType;
1772
1773   ia32_decode_operands(pref, *gotit, addr, instruct); // all but FP
1774
1775   return instruct;
1776 }
1777
1778 template ia32_instruction& ia32_decode<0>(const unsigned char* addr, ia32_instruction& instruct);
1779
1780 ia32_instruction& ia32_decode_FP(const ia32_prefixes& pref, const unsigned char* addr,
1781                                  ia32_instruction& instruct)
1782 {
1783   unsigned int nib = byteSzB; // modRM
1784   unsigned int addrSzAttr = (pref.getPrefix(3) == PREFIX_SZADDR ? 1 : 2); // 32-bit mode implicit
1785
1786   if (addr[0] <= 0xBF) { // modrm
1787     nib += ia32_decode_modrm(addrSzAttr, addr);
1788   }
1789   instruct.size += nib;
1790
1791   return instruct;
1792 }
1793
1794 static unsigned int ia32_decode_modrm(const unsigned int addrSzAttr, const unsigned char* addr)
1795 {
1796   unsigned char modrm = addr[0];
1797   unsigned char mod = modrm >> 6;
1798   unsigned char rm  = modrm & 7;
1799   //unsigned char reg = (modrm >> 3) & 7;
1800
1801   if(addrSzAttr == 1) { // 16-bit, cannot have SIB
1802     switch(mod) {
1803     case 0:
1804       return rm==6 ? wordSzB : 0;
1805     case 1:
1806       return byteSzB;
1807     case 2:
1808       return wordSzB;
1809     case 3:
1810       return 0; // register
1811     default:
1812       assert(0);
1813     }
1814   }
1815   else { // 32-bit, may have SIB
1816     if(mod == 3)
1817       return 0; // only registers, no SIB
1818     bool hassib = rm == 4;
1819     unsigned int nsib = 0;
1820     unsigned char sib;
1821     unsigned char base = 0;
1822     if(hassib) {
1823       nsib = byteSzB;
1824       sib = addr[1];
1825       base = sib & 7;
1826     }
1827     switch(mod) {
1828     case 0: {
1829       /* this is tricky: there is a disp32 iff (1) rm == 5  or  (2) rm == 4 && base == 5 */
1830       unsigned char check5 = hassib ? base : rm;
1831       return nsib + ((check5 == 5) ? dwordSzB : 0);
1832     }
1833     case 1:
1834       return nsib + byteSzB;
1835     case 2:
1836       return nsib + dwordSzB;
1837     default:
1838       assert(0);
1839     }
1840   }
1841 }
1842
1843
1844 unsigned int ia32_decode_operands (const ia32_prefixes& pref, const ia32_entry& gotit, 
1845                                    const unsigned char* addr, ia32_instruction& instruct)
1846 {
1847   unsigned int nib = 0; /* # of bytes in instruction */
1848   unsigned int addrSzAttr = (pref.getPrefix(3) == PREFIX_SZADDR ? 1 : 2); // 32-bit mode implicit
1849   unsigned int operSzAttr = (pref.getPrefix(2) == PREFIX_SZOPER ? 1 : 2); // 32-bit mode implicit
1850
1851   if(gotit.hasModRM)
1852     nib += byteSzB;
1853
1854   for(unsigned int i=0; i<3; ++i) {
1855     const ia32_operand& op = gotit.operands[i];
1856     if(op.admet) {
1857       switch(op.admet) {
1858       case am_A: /* address = segment + offset (word or dword) */
1859         nib += wordSzB;
1860       case am_O: /* operand offset */
1861         nib += wordSzB * addrSzAttr;
1862         break;
1863       case am_C:   /* control register */
1864       case am_D:   /* debug register */
1865       case am_F:   /* flags register */
1866       case am_G:   /* general purpose register, selecteb by reg field */
1867       case am_P:   /* MMX register */
1868       case am_R:   /* general purpose register, selected by mod field */
1869       case am_S:   /* segment register */
1870       case am_T:   /* test register */
1871       case am_V:   /* XMM register */
1872       case am_reg: /* register implicitely encoded in opcode */
1873         break;
1874       case am_E: /* register or memory location, so decoding needed */
1875       case am_M: /* memory operand, decoding needed; size includes modRM byte */
1876       case am_Q: /* MMX register or memory location */
1877       case am_W: /* XMM register or memory location */
1878         nib += ia32_decode_modrm(addrSzAttr, addr);
1879         break;
1880       case am_I: /* immediate data */
1881       case am_J: /* instruction pointer offset */
1882         switch(op.optype) {
1883         case op_b:
1884           nib += byteSzB;
1885           break;
1886         case op_v:
1887           nib += wordSzB * operSzAttr;
1888           break;
1889         case op_w:
1890           nib += wordSzB;
1891         }
1892         break;
1893         /* Don't forget these... */
1894       case am_X: /* memory at DS:(E)SI*/
1895       case am_Y: /* memory at ES:(E)DI*/
1896         break;
1897       default:
1898         assert(0);
1899       }
1900     }
1901     else
1902       break;
1903   }
1904   instruct.size += nib;
1905   return nib;
1906 }
1907
1908
1909 static const unsigned char sse_prefix[256] = {
1910   /*       0 1 2 3 4 5 6 7 8 9 A B C D E F  */
1911   /* 0x */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1912   /* 1x */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,
1913   /* 2x */ 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,
1914   /* 3x */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1915   /* 4x */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1916   /* 5x */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1917   /* 6x */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1918   /* 7x */ 1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1, // Grp12-14 are SSE groups
1919   /* 8x */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1920   /* 9x */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1921   /* Ax */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1922   /* Bx */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1923   /* Cx */ 0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,
1924   /* Dx */ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1925   /* Ex */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1926   /* Fx */ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0
1927 };
1928
1929
1930 // FIXME: lookahead might blow up...
1931 ia32_prefixes& ia32_decode_prefixes(const unsigned char* addr, ia32_prefixes& pref)
1932 {
1933   pref.count = 0;
1934   pref.prfx[0] = pref.prfx[1] = pref.prfx[2] = pref.prfx[3] = 0;
1935   bool in_prefix = true;
1936
1937   while(in_prefix) {
1938     switch(addr[0]) {
1939     case PREFIX_REPNZ:
1940     case PREFIX_REP:
1941       if(addr[1]==0x0F && sse_prefix[addr[2]])
1942         break;
1943     case PREFIX_LOCK:
1944       ++pref.count;
1945       pref.prfx[0] = addr[0];
1946       break;
1947     case PREFIX_SEGCS:
1948     case PREFIX_SEGSS:
1949     case PREFIX_SEGDS:
1950     case PREFIX_SEGES:
1951     case PREFIX_SEGFS:
1952     case PREFIX_SEGGS:
1953       ++pref.count;
1954       pref.prfx[1] = addr[0];
1955       break;
1956     case PREFIX_SZOPER:
1957       if(addr[1]==0x0F && sse_prefix[addr[2]])
1958         break;
1959       ++pref.count;
1960       pref.prfx[2] = addr[0];
1961       break;
1962     case PREFIX_SZADDR:
1963       ++pref.count;
1964       pref.prfx[3] = addr[0];
1965       break;
1966     default:
1967       in_prefix=false;
1968     }
1969     ++addr;
1970   }
1971   
1972   //printf("Got %d prefixes\n", pref.count);
1973   return pref;
1974 }
1975
1976 unsigned int ia32_emulate_old_type(ia32_instruction& instruct)
1977 {
1978   const ia32_prefixes& pref = instruct.prf;
1979   unsigned int& insnType = instruct.legacy_type;
1980   unsigned int operSzAttr = (pref.getPrefix(2) == PREFIX_SZOPER ? 1 : 2); // 32-bit mode implicit
1981
1982   if (pref.getPrefix(0)) // no distinction between these
1983     insnType |= PREFIX_INST;
1984   if (pref.getPrefix(3) == PREFIX_SZADDR)
1985     insnType |= PREFIX_ADDR;
1986   if (pref.getPrefix(2) == PREFIX_SZOPER)
1987     insnType |= PREFIX_OPR;
1988   if (pref.getPrefix(1))
1989     insnType |= PREFIX_SEG; // no distinction between segments
1990
1991   if (insnType & REL_X) {
1992     if (operSzAttr == 1)
1993       insnType |= REL_W;
1994     else
1995       insnType |= REL_D;
1996   }
1997   else if (insnType & PTR_WX) {
1998     if (operSzAttr == 1)
1999       insnType |= PTR_WW;
2000     else
2001       insnType |= PTR_WD;
2002   }
2003
2004   return insnType;
2005 }