dpdk: Add support for Mellanox ConnectX-4 devices
[vpp.git] / vppinfra / vppinfra / asm_x86.c
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /* FIXME
16    opcode name remove to save table space; enum
17    x87
18    3dnow
19    cbw naming
20 */
21
22 #include <vppinfra/error.h>
23 #include <vppinfra/byte_order.h>
24 #include <vppinfra/asm_x86.h>
25
26 #define foreach_x86_gp_register                 \
27   _  (AX)  _ (CX)  _ (DX)  _ (BX)               \
28   _  (SP)  _ (BP)  _ (SI)  _ (DI)
29
30 typedef enum {
31 #define _(r) X86_INSN_GP_REG_##r,
32   foreach_x86_gp_register
33 #undef _
34 } x86_insn_gp_register_t;
35
36 typedef union {
37   struct {
38     u8 rm : 3;
39     u8 reg : 3;
40     u8 mode : 2;
41   };
42   u8 byte;
43 } x86_insn_modrm_byte_t;
44
45 typedef union {
46   struct {
47     u8 base : 3;
48     u8 index : 3;
49     u8 log2_scale : 2;
50   };
51   u8 byte;
52 } x86_insn_sib_byte_t;
53
54 always_inline uword
55 x86_insn_has_modrm_byte (x86_insn_t * insn)
56 {
57   int i;
58   for (i = 0; i < ARRAY_LEN (insn->operands); i++)
59     switch (insn->operands[i].code)
60       {
61       case 'G': case 'E': case 'M': case 'R':
62         return 1;
63       }
64   return 0;
65 }
66
67 always_inline uword
68 x86_insn_immediate_type (x86_insn_t * insn)
69 {
70   int i;
71   for (i = 0; i < ARRAY_LEN (insn->operands); i++)
72     switch (insn->operands[i].code)
73       {
74       case 'J':
75       case 'I':
76       case 'O':
77         return insn->operands[i].type;
78       }
79   return 0;
80 }
81
82 /* Opcode extension in modrm byte reg field. */
83 #define foreach_x86_insn_modrm_reg_group                \
84   _ (1) _ (1a) _ (2) _ (3) _ (4) _ (5) _ (6) _ (7)      \
85   _ (8) _ (9) _ (10) _ (11) _ (12) _ (13) _ (14)        \
86   _ (15) _ (16) _ (p)
87
88 #define foreach_x86_insn_sse_group                              \
89   _ (10) _ (28) _ (50) _ (58) _ (60) _ (68) _ (70) _ (78)       \
90   _ (c0) _ (d0) _ (d8) _ (e0) _ (e8) _ (f0) _ (f8)
91
92 enum {
93 #define _(x) X86_INSN_MODRM_REG_GROUP_##x,
94   foreach_x86_insn_modrm_reg_group
95 #undef _
96 #define _(x) X86_INSN_SSE_GROUP_##x,
97   foreach_x86_insn_sse_group
98 #undef _
99 };
100
101 enum {
102 #define _(x)                                                            \
103   X86_INSN_FLAG_MODRM_REG_GROUP_##x                                     \
104   = X86_INSN_FLAG_SET_MODRM_REG_GROUP (1 + X86_INSN_MODRM_REG_GROUP_##x),
105   foreach_x86_insn_modrm_reg_group
106 #undef _
107
108 #define _(x)                                                    \
109   X86_INSN_FLAG_SSE_GROUP_##x                                   \
110   = X86_INSN_FLAG_SET_SSE_GROUP (1 + X86_INSN_SSE_GROUP_##x),
111   foreach_x86_insn_sse_group
112 #undef _
113 };
114
115 #define foreach_x86_gp_reg                      \
116   _ (AX) _ (CX) _ (DX) _ (BX)                   \
117   _ (SP) _ (BP) _ (SI) _ (DI)
118
119 #define foreach_x86_condition                   \
120   _ (o) _ (no)  _ (b) _ (nb)                    \
121   _ (z) _ (nz) _ (be) _ (nbe)                   \
122   _ (s) _ (ns)  _ (p) _ (np)                    \
123   _ (l) _ (nl) _ (le) _ (nle)
124
125 #define _3f(x,f,o0,o1,o2)                       \
126 {                                               \
127   .name = #x,                                   \
128   .flags = (f),                                 \
129   .operands[0] = { .data = #o0 },               \
130   .operands[1] = { .data = #o1 },               \
131   .operands[2] = { .data = #o2 },               \
132 }
133
134 #define _2f(x,f,o0,o1)  _3f(x,f,o0,o1,__)
135 #define _1f(x,f,o0)     _2f(x,f,o0,__)
136 #define _0f(x,f)        _1f(x,f,__)
137
138 #define _3(x,o0,o1,o2)  _3f(x,0,o0,o1,o2)
139 #define _2(x,o0,o1)     _2f(x,0,o0,o1)
140 #define _1(x,o0)        _1f(x,0,o0)
141 #define _0(x)           _0f(x,0)
142
143 static x86_insn_t x86_insns_one_byte[256] = {
144
145 #define _(x)                                    \
146   _2 (x, Eb, Gb),                               \
147   _2 (x, Ev, Gv),                               \
148   _2 (x, Gb, Eb),                               \
149   _2 (x, Gv, Ev),                               \
150   _2 (x, AL, Ib),                               \
151   _2 (x, AX, Iz)
152
153   /* 0x00 */
154   _ (add),
155   _0 (push_es),
156   _0 (pop_es),
157   _ (or),
158   _0 (push_cs),
159   _0 (escape_two_byte),
160
161   /* 0x10 */
162   _ (adc),
163   _0 (push_ss),
164   _0 (pop_ss),
165   _ (sbb),
166   _0 (push_ds),
167   _0 (pop_ds),
168
169   /* 0x20 */
170   _ (and),
171   _0 (segment_es),
172   _0 (daa),
173   _ (sub),
174   _0 (segment_cs),
175   _0 (das),
176
177   /* 0x30 */
178   _ (xor),
179   _0 (segment_ss),
180   _0 (aaa),
181   _ (cmp),
182   _0 (segment_ds),
183   _0 (aas),
184
185 #undef _
186
187   /* 0x40 */
188 #define _(r) _1 (inc, r),
189   foreach_x86_gp_reg
190 #undef _
191 #define _(r) _1 (dec, r),
192   foreach_x86_gp_reg
193 #undef _
194
195   /* 0x50 */
196 #define _(r) _1f (push, X86_INSN_FLAG_DEFAULT_64_BIT, r),
197   foreach_x86_gp_reg
198 #undef _
199 #define _(r) _1f (pop, X86_INSN_FLAG_DEFAULT_64_BIT, r),
200   foreach_x86_gp_reg
201 #undef _
202
203   /* 0x60 */
204   _0 (pusha),
205   _0 (popa),
206   _2 (bound, Gv, Ma),
207   _2 (movsxd, Gv, Ed),
208   _0 (segment_fs),
209   _0 (segment_gs),
210   _0 (operand_type),
211   _0 (address_size),
212   _1f (push, X86_INSN_FLAG_DEFAULT_64_BIT, Iz),
213   _3 (imul, Gv, Ev, Iz),
214   _1f (push, X86_INSN_FLAG_DEFAULT_64_BIT, Ib),
215   _3 (imul, Gv, Ev, Ib),
216   _1 (insb, DX),
217   _1 (insw, DX),
218   _1 (outsb, DX),
219   _1 (outsw, DX),
220
221   /* 0x70 */
222 #define _(x) _1 (j##x, Jb),
223   foreach_x86_condition
224 #undef _
225
226   /* 0x80 */
227   _2f (modrm_group_1, X86_INSN_FLAG_MODRM_REG_GROUP_1, Eb, Ib),
228   _2f (modrm_group_1, X86_INSN_FLAG_MODRM_REG_GROUP_1, Ev, Iz),
229   _2f (modrm_group_1, X86_INSN_FLAG_MODRM_REG_GROUP_1, Eb, Ib),
230   _2f (modrm_group_1, X86_INSN_FLAG_MODRM_REG_GROUP_1, Ev, Ib),
231   _2 (test, Eb, Gb),
232   _2 (test, Ev, Gv),
233   _2 (xchg, Eb, Gb),
234   _2 (xchg, Ev, Gv),
235   _2 (mov, Eb, Gb),
236   _2 (mov, Ev, Gv),
237   _2 (mov, Gb, Eb),
238   _2 (mov, Gv, Ev),
239   _2 (mov, Ev, Sw),
240   _2 (lea, Gv, Ev),
241   _2 (mov, Sw, Ew),
242   _1f (modrm_group_1a, X86_INSN_FLAG_MODRM_REG_GROUP_1a, Ev),
243
244   /* 0x90 */
245   _0 (nop),
246   _1 (xchg, CX),
247   _1 (xchg, DX),
248   _1 (xchg, BX),
249   _1 (xchg, SP),
250   _1 (xchg, BP),
251   _1 (xchg, SI),
252   _1 (xchg, DI),
253   _0 (cbw),
254   _0 (cwd),
255   _1 (call, Ap),
256   _0 (wait),
257   _0 (pushf),
258   _0 (popf),
259   _0 (sahf),
260   _0 (lahf),
261
262   /* 0xa0 */
263   _2 (mov, AL, Ob),
264   _2 (mov, AX, Ov),
265   _2 (mov, Ob, AL),
266   _2 (mov, Ov, AX),
267   _0 (movsb),
268   _0 (movsw),
269   _0 (cmpsb),
270   _0 (cmpsw),
271   _2 (test, AL, Ib),
272   _2 (test, AX, Iz),
273   _1 (stosb, AL),
274   _1 (stosw, AX),
275   _1 (lodsb, AL),
276   _1 (lodsw, AX),
277   _1 (scasb, AL),
278   _1 (scasw, AX),
279
280   /* 0xb0 */
281   _2 (mov, AL, Ib),
282   _2 (mov, CL, Ib),
283   _2 (mov, DL, Ib),
284   _2 (mov, BL, Ib),
285   _2 (mov, AH, Ib),
286   _2 (mov, CH, Ib),
287   _2 (mov, DH, Ib),
288   _2 (mov, BH, Ib),
289 #define _(r) _2 (mov, r, Iv),
290   foreach_x86_gp_reg
291 #undef _
292
293   /* 0xc0 */
294   _2f (modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Eb, Ib),
295   _2f (modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Ev, Ib),
296   _1 (ret, Iw),
297   _0 (ret),
298   _2 (les, Gz, Mp),
299   _2 (lds, Gz, Mp),
300   _2f (modrm_group_11, X86_INSN_FLAG_MODRM_REG_GROUP_11, Eb, Ib),
301   _2f (modrm_group_11, X86_INSN_FLAG_MODRM_REG_GROUP_11, Ev, Iz),
302   _2 (enter, Iw, Ib),
303   _0 (leave),
304   _1 (ret, Iw),
305   _0 (ret),
306   _0 (int3),
307   _1 (int, Ib),
308   _0 (into),
309   _0 (iret),
310
311   /* 0xd0 */
312   _2f (modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Eb, 1b),
313   _2f (modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Ev, 1b),
314   _2f (modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Eb, CL),
315   _2f (modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Ev, CL),
316   _0 (aam),
317   _0 (aad),
318   _0 (salc),
319   _0 (xlat),
320   /* FIXME x87 */
321   _0 (bad),
322   _0 (bad),
323   _0 (bad),
324   _0 (bad),
325   _0 (bad),
326   _0 (bad),
327   _0 (bad),
328   _0 (bad),
329
330   /* 0xe0 */
331   _1 (loopnz, Jb),
332   _1 (loopz, Jb),
333   _1 (loop, Jb),
334   _1 (jcxz, Jb),
335   _2 (in, AL, Ib),
336   _2 (in, AX, Ib),
337   _2 (out, Ib, AL),
338   _2 (out, Ib, AX),
339   _1f (call, X86_INSN_FLAG_DEFAULT_64_BIT, Jz),
340   _1f ( jmp, X86_INSN_FLAG_DEFAULT_64_BIT, Jz),
341   _1 (jmp, Ap),
342   _1 (jmp, Jb),
343   _2 (in, AL, DX),
344   _2 (in, AX, DX),
345   _2 (out, DX, AL),
346   _2 (out, DX, AX),
347
348   /* 0xf0 */
349   _0 (lock),
350   _0 (int1),
351   _0 (repne),
352   _0 (rep),
353   _0 (hlt),
354   _0 (cmc),
355   _0f (modrm_group_3, X86_INSN_FLAG_MODRM_REG_GROUP_3),
356   _0f (modrm_group_3, X86_INSN_FLAG_MODRM_REG_GROUP_3),
357   _0 (clc),
358   _0 (stc),
359   _0 (cli),
360   _0 (sti),
361   _0 (cld),
362   _0 (std),
363   _1f (modrm_group_4, X86_INSN_FLAG_MODRM_REG_GROUP_4, Eb),
364   _0f (modrm_group_5, X86_INSN_FLAG_MODRM_REG_GROUP_5),
365 };
366
367 static x86_insn_t x86_insns_two_byte[256] = {
368   /* 0x00 */
369   _0f (modrm_group_6, X86_INSN_FLAG_MODRM_REG_GROUP_6),
370   _0f (modrm_group_7, X86_INSN_FLAG_MODRM_REG_GROUP_7),
371   _2 (lar, Gv, Ew),
372   _2 (lsl, Gv, Ew),
373   _0 (bad),
374   _0 (syscall),
375   _0 (clts),
376   _0 (sysret),
377   _0 (invd),
378   _0 (wbinvd),
379   _0 (bad),
380   _0 (ud2),
381   _0 (bad),
382   _0f (modrm_group_p, X86_INSN_FLAG_MODRM_REG_GROUP_p),
383   _0 (femms),
384   _0 (escape_3dnow),
385
386   /* 0x10 */
387   _2f (movups, X86_INSN_FLAG_SSE_GROUP_10, Gx, Ex),
388   _2f (movups, X86_INSN_FLAG_SSE_GROUP_10, Ex, Gx),
389   _2f (movlps, X86_INSN_FLAG_SSE_GROUP_10, Ex, Gx),
390   _2f (movlps, X86_INSN_FLAG_SSE_GROUP_10, Gx, Ex),
391   _2f (unpcklps, X86_INSN_FLAG_SSE_GROUP_10, Gx, Ex),
392   _2f (unpckhps, X86_INSN_FLAG_SSE_GROUP_10, Gx, Ex),
393   _2f (movhps, X86_INSN_FLAG_SSE_GROUP_10, Ex, Gx),
394   _2f (movhps, X86_INSN_FLAG_SSE_GROUP_10, Gx, Ex),
395   _0f (modrm_group_16, X86_INSN_FLAG_MODRM_REG_GROUP_16),
396   _0 (nop),
397   _0 (nop),
398   _0 (nop),
399   _0 (nop),
400   _0 (nop),
401   _0 (nop),
402   _0 (nop),
403
404   /* 0x20 */
405   _2 (mov, Rv, Cv),
406   _2 (mov, Rv, Dv),
407   _2 (mov, Cv, Rv),
408   _2 (mov, Dv, Rv),
409   _0 (bad),
410   _0 (bad),
411   _0 (bad),
412   _0 (bad),
413   _2f (movaps, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex),
414   _2f (movaps, X86_INSN_FLAG_SSE_GROUP_28, Ex, Gx),
415   _2f (cvtpi2ps, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex),
416   _2f (movntps, X86_INSN_FLAG_SSE_GROUP_28, Mx, Gx),
417   _2f (cvttps2pi, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex),
418   _2f (cvtps2pi, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex),
419   _2f (ucomiss, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex),
420   _2f (comiss, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex),
421
422   /* 0x30 */
423   _0 (wrmsr),
424   _0 (rdtsc),
425   _0 (rdmsr),
426   _0 (rdpmc),
427   _0 (sysenter),
428   _0 (sysexit),
429   _0 (bad),
430   _0 (bad),
431   _0 (bad),
432   _0 (bad),
433   _0 (bad),
434   _0 (bad),
435   _0 (bad),
436   _0 (bad),
437   _0 (bad),
438   _0 (bad),
439
440   /* 0x40 */
441 #define _(x) _2 (cmov##x, Gv, Ev),
442   foreach_x86_condition
443 #undef _
444
445   /* 0x50 */
446   _2f (movmskps, X86_INSN_FLAG_SSE_GROUP_50, Gd, Rx),
447   _2f (sqrtps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex),
448   _2f (rsqrtps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex),
449   _2f (rcpps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex),
450   _2f (andps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex),
451   _2f (andnps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex),
452   _2f (orps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex),
453   _2f (xorps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex),
454   _2f (addps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex),
455   _2f (mulps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex),
456   _2f (cvtps2pd, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex),
457   _2f (cvtdq2ps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex),
458   _2f (subps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex),
459   _2f (minps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex),
460   _2f (divps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex),
461   _2f (maxps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex),
462
463   /* 0x60 */
464   _2f (punpcklbw, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em),
465   _2f (punpcklwd, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em),
466   _2f (punpckldq, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em),
467   _2f (packsswb, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em),
468   _2f (pcmpgtb, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em),
469   _2f (pcmpgtw, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em),
470   _2f (pcmpgtd, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em),
471   _2f (packuswb, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em),
472   _2f (punpckhbw, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em),
473   _2f (punpckhwd, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em),
474   _2f (punpckhdq, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em),
475   _2f (packssdw, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em),
476   _0f (bad, X86_INSN_FLAG_SSE_GROUP_68),
477   _0f (bad, X86_INSN_FLAG_SSE_GROUP_68),
478   _2f (movd, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em),
479   _2f (movq, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em),
480
481   /* 0x70 */
482   _3f (pshufw, X86_INSN_FLAG_SSE_GROUP_70, Gm, Em, Ib),
483   _0f (modrm_group_12, X86_INSN_FLAG_MODRM_REG_GROUP_12),
484   _0f (modrm_group_13, X86_INSN_FLAG_MODRM_REG_GROUP_13),
485   _0f (modrm_group_14, X86_INSN_FLAG_MODRM_REG_GROUP_14),
486   _2f (pcmpeqb, X86_INSN_FLAG_SSE_GROUP_70, Gm, Em),
487   _2f (pcmpeqw, X86_INSN_FLAG_SSE_GROUP_70, Gm, Em),
488   _2f (pcmpeqd, X86_INSN_FLAG_SSE_GROUP_70, Gm, Em),
489   _0f (emms, X86_INSN_FLAG_SSE_GROUP_70),
490   _0f (bad, X86_INSN_FLAG_SSE_GROUP_78),
491   _0f (bad, X86_INSN_FLAG_SSE_GROUP_78),
492   _0f (bad, X86_INSN_FLAG_SSE_GROUP_78),
493   _0f (bad, X86_INSN_FLAG_SSE_GROUP_78),
494   _0f (bad, X86_INSN_FLAG_SSE_GROUP_78),
495   _0f (bad, X86_INSN_FLAG_SSE_GROUP_78),
496   _2f (movd, X86_INSN_FLAG_SSE_GROUP_78, Em, Gm),
497   _2f (movq, X86_INSN_FLAG_SSE_GROUP_78, Em, Gm),
498
499   /* 0x80 */
500 #define _(x) _1 (jmp##x, Jz),
501   foreach_x86_condition
502 #undef _
503
504   /* 0x90 */
505 #define _(x) _1 (set##x, Eb),
506   foreach_x86_condition
507 #undef _
508
509   /* 0xa0 */
510   _0 (push_fs),
511   _0 (pop_fs),
512   _0 (cpuid),
513   _2 (bt, Ev, Gv),
514   _3 (shld, Ev, Gv, Ib),
515   _3 (shld, Ev, Gv, CL),
516   _0 (bad),
517   _0 (bad),
518   _0 (push_gs),
519   _0 (pop_gs),
520   _0 (rsm),
521   _2 (bts, Ev, Gv),
522   _3 (shrd, Ev, Gv, Ib),
523   _3 (shrd, Ev, Gv, CL),
524   _0f (modrm_group_15, X86_INSN_FLAG_MODRM_REG_GROUP_15),
525   _2 (imul, Gv, Ev),
526
527   /* 0xb0 */
528   _2 (cmpxchg, Eb, Gb),
529   _2 (cmpxchg, Ev, Gv),
530   _2 (lss, Gz, Mp),
531   _2 (btr, Ev, Gv),
532   _2 (lfs, Gz, Mp),
533   _2 (lgs, Gz, Mp),
534   _2 (movzbl, Gv, Eb),
535   _2 (movzwl, Gv, Ew),
536   _0 (bad),
537   _0f (modrm_group_10, X86_INSN_FLAG_MODRM_REG_GROUP_10),
538   _2f (modrm_group_8, X86_INSN_FLAG_MODRM_REG_GROUP_8, Ev, Ib),
539   _2 (btc, Ev, Gv),
540   _2 (bsf, Gv, Ev),
541   _2 (bsr, Gv, Ev),
542   _2 (movsx, Gv, Eb),
543   _2 (movsx, Gv, Ew),
544
545   /* 0xc0 */
546   _2 (xadd, Eb, Gb),
547   _2 (xadd, Ev, Gv),
548   _3f (cmpps, X86_INSN_FLAG_SSE_GROUP_c0, Gx, Ex, Ib),
549   _2 (movnti, Mv, Gv),
550   _3f (pinsrw, X86_INSN_FLAG_SSE_GROUP_c0, Gm, Ew, Ib),
551   _3f (pextrw, X86_INSN_FLAG_SSE_GROUP_c0, Gd, Rm, Ib),
552   _3f (shufps, X86_INSN_FLAG_SSE_GROUP_c0, Gx, Ex, Ib),
553   _1f (modrm_group_9, X86_INSN_FLAG_MODRM_REG_GROUP_9, Mx),
554 #define _(r) _1 (bswap, r),
555   foreach_x86_gp_reg
556 #undef _
557
558   /* 0xd0 */
559   _0f (bad, X86_INSN_FLAG_SSE_GROUP_d0),
560   _2f (psrlw, X86_INSN_FLAG_SSE_GROUP_d0, Gm, Em),
561   _2f (psrld, X86_INSN_FLAG_SSE_GROUP_d0, Gm, Em),
562   _2f (psrlq, X86_INSN_FLAG_SSE_GROUP_d0, Gm, Em),
563   _2f (paddq, X86_INSN_FLAG_SSE_GROUP_d0, Gm, Em),
564   _2f (pmullw, X86_INSN_FLAG_SSE_GROUP_d0, Gm, Em),
565   _0f (bad, X86_INSN_FLAG_SSE_GROUP_d0),
566   _2f (pmovmskb, X86_INSN_FLAG_SSE_GROUP_d0, Gd, Rm),
567   _2f (psubusb, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em),
568   _2f (psubusw, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em),
569   _2f (pminub, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em),
570   _2f (pand, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em),
571   _2f (paddusb, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em),
572   _2f (paddusw, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em),
573   _2f (pmaxub, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em),
574   _2f (pandn, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em),
575
576   /* 0xe0 */
577   _2f (pavgb, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em),
578   _2f (psraw, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em),
579   _2f (psrad, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em),
580   _2f (pavgw, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em),
581   _2f (pmulhuw, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em),
582   _2f (pmulhw, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em),
583   _2f (bad, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em),
584   _2f (movntq, X86_INSN_FLAG_SSE_GROUP_e0, Mm, Gm),
585   _2f (psubsb, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em),
586   _2f (psubsw, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em),
587   _2f (pminsw, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em),
588   _2f (por, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em),
589   _2f (paddsb, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em),
590   _2f (paddsw, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em),
591   _2f (pmaxsw, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em),
592   _2f (pxor, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em),
593
594   /* 0xf0 */
595   _0f (bad, X86_INSN_FLAG_SSE_GROUP_f0),
596   _2f (psllw, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em),
597   _2f (pslld, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em),
598   _2f (psllq, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em),
599   _2f (pmuludq, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em),
600   _2f (pmaddwd, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em),
601   _2f (psadbw, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em),
602   _2f (maskmovq, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em),
603   _2f (psubb, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em),
604   _2f (psubw, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em),
605   _2f (psubd, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em),
606   _2f (psubq, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em),
607   _2f (paddb, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em),
608   _2f (paddw, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em),
609   _2f (paddd, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em),
610   _0f (bad, X86_INSN_FLAG_SSE_GROUP_f8),
611 };
612
613 typedef struct {
614   x86_insn_t insns[8];
615 } x86_insn_group8_t;
616
617 /* Escape groups are indexed by modrm reg field. */
618 static x86_insn_group8_t x86_insn_modrm_reg_groups[] = {
619   [X86_INSN_MODRM_REG_GROUP_1].insns = {
620     _0 (add), _0 ( or), _0 (adc), _0 (sbb),
621     _0 (and), _0 (sub), _0 (xor), _0 (cmp),
622   },
623
624   [X86_INSN_MODRM_REG_GROUP_1a].insns = {
625     _0f (pop, X86_INSN_FLAG_DEFAULT_64_BIT),
626     _0 (bad), _0 (bad), _0 (bad),
627     _0 (bad), _0 (bad), _0 (bad), _0 (bad),
628   },
629
630   [X86_INSN_MODRM_REG_GROUP_2].insns = {
631     _0 (rol), _0 (ror), _0 (rcl), _0 (rcr),
632     _0 (shl), _0 (shr), _0 (sal), _0 (sar),
633   },
634
635   [X86_INSN_MODRM_REG_GROUP_3].insns = {
636     _0 (test), _0 (test), _0 (not), _0 (neg),
637     _0 (mul), _0 (imul), _0 (div), _0 (idiv),
638   },
639
640   [X86_INSN_MODRM_REG_GROUP_4].insns = {
641     _0 (inc), _0 (dec), _0 (bad), _0 (bad),
642     _0 (bad), _0 (bad), _0 (bad), _0 (bad),
643   },
644
645   [X86_INSN_MODRM_REG_GROUP_5].insns = {
646     _1 (inc, Ev),
647     _1 (dec, Ev),
648     _1f (call, X86_INSN_FLAG_DEFAULT_64_BIT, Ev),
649     _1 (call, Mp),
650     _1f (jmp, X86_INSN_FLAG_DEFAULT_64_BIT, Ev),
651     _1 (jmp, Mp),
652     _1f (push, X86_INSN_FLAG_DEFAULT_64_BIT, Ev),
653     _0 (bad),
654   },
655
656   [X86_INSN_MODRM_REG_GROUP_6].insns = {
657     _1 (sldt, Ev),
658     _1 (str, Ev),
659     _1 (lldt, Ev),
660     _1 (ltr, Ev),
661     _1 (verr, Ev),
662     _1 (verw, Ev),
663     _0 (bad),
664     _0 (bad),
665   },
666
667   [X86_INSN_MODRM_REG_GROUP_7].insns = {
668     _1 (sgdt, Mv),
669     _1 (sidt, Mv),
670     _1 (lgdt, Mv),
671     _1 (lidt, Mv),
672     _1 (smsw, Ev),
673     _0 (bad),
674     _1 (lmsw, Ew),
675     _1 (invlpg, Mv),
676   },
677
678   [X86_INSN_MODRM_REG_GROUP_8].insns = {
679     _0 (bad),
680     _0 (bad),
681     _0 (bad),
682     _0 (bad),
683     _2 (bt, Ev, Ib),
684     _2 (bts, Ev, Ib),
685     _2 (btr, Ev, Ib),
686     _2 (btc, Ev, Ib),
687   },
688
689   [X86_INSN_MODRM_REG_GROUP_9].insns = {
690     _0 (bad),
691     _1 (cmpxchg, Mx),
692     _0 (bad),
693     _0 (bad),
694     _0 (bad),
695     _0 (bad),
696     _0 (bad),
697     _0 (bad),
698   },
699
700   [X86_INSN_MODRM_REG_GROUP_10].insns = {
701     _0 (bad), _0 (bad), _0 (bad), _0 (bad),
702     _0 (bad), _0 (bad), _0 (bad), _0 (bad),
703   },
704
705   [X86_INSN_MODRM_REG_GROUP_11].insns = {
706     _0 (mov), _0 (bad), _0 (bad), _0 (bad),
707     _0 (bad), _0 (bad), _0 (bad), _0 (bad),
708   },
709
710   [X86_INSN_MODRM_REG_GROUP_12].insns = {
711     _0 (bad),
712     _0 (bad),
713     _2 (psrlw, Rm, Ib),
714     _0 (bad),
715     _2 (psraw, Rm, Ib),
716     _0 (bad),
717     _2 (psllw, Rm, Ib),
718     _0 (bad),
719   },
720
721   [X86_INSN_MODRM_REG_GROUP_13].insns = {
722     _0 (bad),
723     _0 (bad),
724     _2 (psrld, Rm, Ib),
725     _0 (bad),
726     _2 (psrad, Rm, Ib),
727     _0 (bad),
728     _2 (pslld, Rm, Ib),
729     _0 (bad),
730   },
731
732   [X86_INSN_MODRM_REG_GROUP_14].insns = {
733     _0 (bad),
734     _0 (bad),
735     _2 (psrlq, Rm, Ib),
736     _0f (bad, 0),
737     _0 (bad),
738     _0 (bad),
739     _2 (psllq, Rm, Ib),
740     _0f (bad, 0),
741   },
742
743   [X86_INSN_MODRM_REG_GROUP_15].insns = {
744     _1 (fxsave, Mv),
745     _1 (fxrstor, Mv),
746     _1 (ldmxcsr, Mv),
747     _1 (stmxcsr, Mv),
748     _0 (bad),
749     _1 (lfence, Mv),
750     _1 (mfence, Mv),
751     _1 (sfence, Mv),
752   },
753
754   [X86_INSN_MODRM_REG_GROUP_16].insns = {
755     _1 (prefetch_nta, Mv),
756     _1 (prefetch_t0, Mv),
757     _1 (prefetch_t1, Mv),
758     _1 (prefetch_t2, Mv),
759     _1 (prefetch_nop, Mv),
760     _1 (prefetch_nop, Mv),
761     _1 (prefetch_nop, Mv),
762     _1 (prefetch_nop, Mv),
763   },
764
765   [X86_INSN_MODRM_REG_GROUP_p].insns = {
766     _1 (prefetch_exclusive, Mv),
767     _1 (prefetch_modified, Mv),
768     _1 (prefetch_nop, Mv),
769     _1 (prefetch_modified, Mv),
770     _1 (prefetch_nop, Mv),
771     _1 (prefetch_nop, Mv),
772     _1 (prefetch_nop, Mv),
773     _1 (prefetch_nop, Mv),
774   },
775 };
776
777 static x86_insn_group8_t x86_insn_sse_groups_repz[] = {
778   [X86_INSN_SSE_GROUP_10].insns = {
779     _2 (movss, Gx, Ex),
780     _2 (movss, Ex, Gx),
781     _2 (movsldup, Gx, Ex),
782     _0 (bad),
783     _0 (bad),
784     _0 (bad),
785     _2 (movshdup, Gx, Ex),
786     _0 (bad),
787   },
788
789   [X86_INSN_SSE_GROUP_28].insns = {
790     _0 (bad),
791     _0 (bad),
792     _2 (cvtsi2ss, Gx, Ev),
793     _0 (bad),
794     _2 (cvttss2si, Gv, Ex),
795     _2 (cvtss2si, Gv, Ex),
796     _0 (bad),
797     _0 (bad),
798   },
799
800   [X86_INSN_SSE_GROUP_50].insns = {
801     _0 (bad),
802     _2 (sqrtss, Gx, Ex),
803     _2 (rsqrtps, Gx, Ex),
804     _2 (rcpss, Gx, Ex),
805     _0 (bad),
806     _0 (bad),
807     _0 (bad),
808     _0 (bad),
809   },
810
811   [X86_INSN_SSE_GROUP_58].insns = {
812     _2 (addss, Gx, Ex),
813     _2 (mulss, Gx, Ex),
814     _2 (cvtss2sd, Gx, Ex),
815     _2 (cvttps2dq, Gx, Ex),
816     _2 (subss, Gx, Ex),
817     _2 (minss, Gx, Ex),
818     _2 (divss, Gx, Ex),
819     _2 (maxss, Gx, Ex),
820   },
821
822   [X86_INSN_SSE_GROUP_60].insns = {
823     _0 (bad),
824     _0 (bad),
825     _0 (bad),
826     _0 (bad),
827     _0 (bad),
828     _0 (bad),
829     _0 (bad),
830     _0 (bad),
831   },
832
833   [X86_INSN_SSE_GROUP_68].insns = {
834     _0 (bad),
835     _0 (bad),
836     _0 (bad),
837     _0 (bad),
838     _0 (bad),
839     _0 (bad),
840     _0 (bad),
841     _2 (movdqu, Gx, Ex),
842   },
843
844   [X86_INSN_SSE_GROUP_70].insns = {
845     _3 (pshufhw, Gx, Ex, Ib),
846     _0 (bad),
847     _0 (bad),
848     _0 (bad),
849     _0 (bad),
850     _0 (bad),
851     _0 (bad),
852     _0 (bad),
853   },
854
855   [X86_INSN_SSE_GROUP_78].insns = {
856     _0 (bad),
857     _0 (bad),
858     _0 (bad),
859     _0 (bad),
860     _0 (bad),
861     _0 (bad),
862     _2 (movq, Gx, Ex),
863     _2 (movdqu, Ex, Gx),
864   },
865
866   [X86_INSN_SSE_GROUP_c0].insns = {
867     _0 (bad),
868     _0 (bad),
869     _3 (cmpss, Gx, Ex, Ib),
870     _0 (bad),
871     _0 (bad),
872     _0 (bad),
873     _0 (bad),
874     _0 (bad),
875   },
876
877   [X86_INSN_SSE_GROUP_d0].insns = {
878     _0 (bad),
879     _0 (bad),
880     _0 (bad),
881     _0 (bad),
882     _0 (bad),
883     _0 (bad),
884     _2 (movq2dq, Gx, Em),
885     _0 (bad),
886   },
887
888   [X86_INSN_SSE_GROUP_d8].insns = {
889     _0 (bad),
890     _0 (bad),
891     _0 (bad),
892     _0 (bad),
893     _0 (bad),
894     _0 (bad),
895     _0 (bad),
896     _0 (bad),
897   },
898
899   [X86_INSN_SSE_GROUP_e0].insns = {
900     _0 (bad),
901     _0 (bad),
902     _0 (bad),
903     _0 (bad),
904     _0 (bad),
905     _0 (bad),
906     _2 (cvtdq2pd, Gx, Ex),
907     _0 (bad),
908   },
909
910   [X86_INSN_SSE_GROUP_e8].insns = {
911     _0 (bad),
912     _0 (bad),
913     _0 (bad),
914     _0 (bad),
915     _0 (bad),
916     _0 (bad),
917     _0 (bad),
918     _0 (bad),
919   },
920
921   [X86_INSN_SSE_GROUP_f0].insns = {
922     _0 (bad),
923     _0 (bad),
924     _0 (bad),
925     _0 (bad),
926     _0 (bad),
927     _0 (bad),
928     _0 (bad),
929     _0 (bad),
930   },
931
932   [X86_INSN_SSE_GROUP_f8].insns = {
933     _0 (bad),
934     _0 (bad),
935     _0 (bad),
936     _0 (bad),
937     _0 (bad),
938     _0 (bad),
939     _0 (bad),
940     _0 (bad),
941   },
942 };
943
944 static x86_insn_group8_t x86_insn_sse_groups_operand_size[] = {
945   [X86_INSN_SSE_GROUP_10].insns = {
946     _2 (movupd, Gx, Ex),
947     _2 (movupd, Ex, Gx),
948     _2 (movlpd, Gx, Ex),
949     _2 (movlpd, Ex, Gx),
950     _2 (unpcklpd, Gx, Ex),
951     _2 (unpckhpd, Gx, Ex),
952     _2 (movhpd, Gx, Mx),
953     _2 (movhpd, Mx, Gx),
954   },
955
956   [X86_INSN_SSE_GROUP_28].insns = {
957     _2 (movapd, Gx, Ex),
958     _2 (movapd, Ex, Gx),
959     _2 (cvtpi2pd, Gx, Ex),
960     _2 (movntpd, Mx, Gx),
961     _2 (cvttpd2pi, Gx, Mx),
962     _2 (cvtpd2pi, Gx, Mx),
963     _2 (ucomisd, Gx, Ex),
964     _2 (comisd, Gx, Ex),
965   },
966
967   [X86_INSN_SSE_GROUP_50].insns = {
968     _2 (movmskpd, Gd, Rx),
969     _2 (sqrtpd, Gx, Ex),
970     _0 (bad),
971     _0 (bad),
972     _2 (andpd, Gx, Ex),
973     _2 (andnpd, Gx, Ex),
974     _2 (orpd, Gx, Ex),
975     _2 (xorpd, Gx, Ex),
976   },
977
978   [X86_INSN_SSE_GROUP_58].insns = {
979     _2 (addpd, Gx, Ex),
980     _2 (mulpd, Gx, Ex),
981     _2 (cvtpd2ps, Gx, Ex),
982     _2 (cvtps2dq, Gx, Ex),
983     _2 (subpd, Gx, Ex),
984     _2 (minpd, Gx, Ex),
985     _2 (divpd, Gx, Ex),
986     _2 (maxpd, Gx, Ex),
987   },
988
989   [X86_INSN_SSE_GROUP_60].insns = {
990     _2 (punpcklbw, Gx, Ex),
991     _2 (punpcklwd, Gx, Ex),
992     _2 (punpckldq, Gx, Ex),
993     _2 (packsswb, Gx, Ex),
994     _2 (pcmpgtb, Gx, Ex),
995     _2 (pcmpgtw, Gx, Ex),
996     _2 (pcmpgtd, Gx, Ex),
997     _2 (packuswb, Gx, Ex),
998   },
999
1000   [X86_INSN_SSE_GROUP_68].insns = {
1001     _2 (punpckhbw, Gx, Ex),
1002     _2 (punpckhwd, Gx, Ex),
1003     _2 (punpckhdq, Gx, Ex),
1004     _2 (packssdw, Gx, Ex),
1005     _2 (punpcklqdq, Gx, Ex),
1006     _2 (punpckhqdq, Gx, Ex),
1007     _2 (movd, Gx, Ev),
1008     _2 (movdqa, Gx, Ex),
1009   },
1010
1011   [X86_INSN_SSE_GROUP_70].insns = {
1012     _3 (pshufd, Gx, Ex, Ib),
1013     _0f (modrm_group_12, X86_INSN_FLAG_MODRM_REG_GROUP_12),
1014     _0f (modrm_group_13, X86_INSN_FLAG_MODRM_REG_GROUP_13),
1015     _0f (modrm_group_14, X86_INSN_FLAG_MODRM_REG_GROUP_14),
1016     _2 (pcmpeqb, Gx, Ex),
1017     _2 (pcmpeqw, Gx, Ex),
1018     _2 (pcmpeqd, Gx, Ex),
1019     _0 (bad),
1020   },
1021
1022   [X86_INSN_SSE_GROUP_78].insns = {
1023     _0 (bad),
1024     _0 (bad),
1025     _0 (bad),
1026     _0 (bad),
1027     _2 (haddpd, Gx, Ex),
1028     _2 (hsubpd, Gx, Ex),
1029     _2 (movd, Ev, Gx),
1030     _2 (movdqa, Ex, Gx),
1031   },
1032
1033   [X86_INSN_SSE_GROUP_c0].insns = {
1034     _0 (bad),
1035     _0 (bad),
1036     _3 (cmppd, Gx, Ex, Ib),
1037     _0 (bad),
1038     _3 (pinsrw, Gx, Ew, Ib),
1039     _3 (pextrw, Gd, Gx, Ib),
1040     _3 (shufpd, Gx, Ex, Ib),
1041     _0 (bad),
1042   },
1043
1044   [X86_INSN_SSE_GROUP_d0].insns = {
1045     _2 (addsubpd, Gx, Ex),
1046     _2 (psrlw, Gx, Ex),
1047     _2 (psrld, Gx, Ex),
1048     _2 (psrlq, Gx, Ex),
1049     _2 (paddq, Gx, Ex),
1050     _2 (pmullw, Gx, Ex),
1051     _2 (movq, Ex, Gx),
1052     _2 (pmovmskb, Gd, Rx),
1053   },
1054
1055   [X86_INSN_SSE_GROUP_d8].insns = {
1056     _2 (psubusb, Gx, Ex),
1057     _2 (psubusw, Gx, Ex),
1058     _2 (pminub, Gx, Ex),
1059     _2 (pand, Gx, Ex),
1060     _2 (paddusb, Gx, Ex),
1061     _2 (paddusw, Gx, Ex),
1062     _2 (pmaxub, Gx, Ex),
1063     _2 (pandn, Gx, Ex),
1064   },
1065
1066   [X86_INSN_SSE_GROUP_e0].insns = {
1067     _2 (pavgb, Gx, Ex),
1068     _2 (psraw, Gx, Ex),
1069     _2 (psrad, Gx, Ex),
1070     _2 (pavgw, Gx, Ex),
1071     _2 (pmulhuw, Gx, Ex),
1072     _2 (pmulhw, Gx, Ex),
1073     _2 (cvttpd2dq, Gx, Ex),
1074     _2 (movntdq, Mx, Gx),
1075   },
1076
1077   [X86_INSN_SSE_GROUP_e8].insns = {
1078     _2 (psubsb, Gx, Ex),
1079     _2 (psubsw, Gx, Ex),
1080     _2 (pminsw, Gx, Ex),
1081     _2 (por, Gx, Ex),
1082     _2 (paddsb, Gx, Ex),
1083     _2 (paddsw, Gx, Ex),
1084     _2 (pmaxsw, Gx, Ex),
1085     _2 (pxor, Gx, Ex),
1086   },
1087
1088   [X86_INSN_SSE_GROUP_f0].insns = {
1089     _0 (bad),
1090     _2 (psllw, Gx, Ex),
1091     _2 (pslld, Gx, Ex),
1092     _2 (psllq, Gx, Ex),
1093     _2 (pmuludq, Gx, Ex),
1094     _2 (pmaddwd, Gx, Ex),
1095     _2 (psadbw, Gx, Ex),
1096     _2 (maskmovdqu, Gx, Ex),
1097   },
1098
1099   [X86_INSN_SSE_GROUP_f8].insns = {
1100     _2 (psubb, Gx, Ex),
1101     _2 (psubw, Gx, Ex),
1102     _2 (psubd, Gx, Ex),
1103     _2 (psubq, Gx, Ex),
1104     _2 (paddb, Gx, Ex),
1105     _2 (paddw, Gx, Ex),
1106     _2 (paddd, Gx, Ex),
1107     _0 (bad),
1108   },
1109 };
1110
1111 static x86_insn_group8_t x86_insn_sse_groups_repnz[] = {
1112   [X86_INSN_SSE_GROUP_10].insns = {
1113     _2 (movsd, Gx, Ex),
1114     _2 (movsd, Ex, Gx),
1115     _2 (movddup, Gx, Ex),
1116     _0 (bad),
1117     _0 (bad),
1118     _0 (bad),
1119     _0 (bad),
1120     _0 (bad),
1121   },
1122
1123   [X86_INSN_SSE_GROUP_28].insns = {
1124     _0 (bad),
1125     _0 (bad),
1126     _2 (cvtsi2sd, Gx, Ev),
1127     _0 (bad),
1128     _2 (cvttsd2si, Gv, Ex),
1129     _2 (cvtsd2si, Gv, Ex),
1130     _0 (bad),
1131     _0 (bad),
1132   },
1133
1134   [X86_INSN_SSE_GROUP_50].insns = {
1135     _0 (bad),
1136     _2 (sqrtsd, Gx, Ex),
1137     _0 (bad),
1138     _0 (bad),
1139     _0 (bad),
1140     _0 (bad),
1141     _0 (bad),
1142     _0 (bad),
1143   },
1144
1145   [X86_INSN_SSE_GROUP_58].insns = {
1146     _2 (addsd, Gx, Ex),
1147     _2 (mulsd, Gx, Ex),
1148     _2 (cvtsd2ss, Gx, Ex),
1149     _0 (bad),
1150     _2 (subsd, Gx, Ex),
1151     _2 (minsd, Gx, Ex),
1152     _2 (divsd, Gx, Ex),
1153     _2 (maxsd, Gx, Ex),
1154   },
1155
1156   [X86_INSN_SSE_GROUP_60].insns = {
1157     _0 (bad),
1158     _0 (bad),
1159     _0 (bad),
1160     _0 (bad),
1161     _0 (bad),
1162     _0 (bad),
1163     _0 (bad),
1164     _0 (bad),
1165   },
1166
1167   [X86_INSN_SSE_GROUP_68].insns = {
1168     _0 (bad),
1169     _0 (bad),
1170     _0 (bad),
1171     _0 (bad),
1172     _0 (bad),
1173     _0 (bad),
1174     _0 (bad),
1175     _0 (bad),
1176   },
1177
1178   [X86_INSN_SSE_GROUP_70].insns = {
1179     _3 (pshuflw, Gx, Ex, Ib),
1180     _0 (bad),
1181     _0 (bad),
1182     _0 (bad),
1183     _0 (bad),
1184     _0 (bad),
1185     _0 (bad),
1186     _0 (bad),
1187   },
1188
1189   [X86_INSN_SSE_GROUP_78].insns = {
1190     _0 (bad),
1191     _0 (bad),
1192     _0 (bad),
1193     _0 (bad),
1194     _2 (haddps, Gx, Ex),
1195     _2 (hsubps, Gx, Ex),
1196     _0 (bad),
1197     _0 (bad),
1198   },
1199
1200   [X86_INSN_SSE_GROUP_c0].insns = {
1201     _0 (bad),
1202     _0 (bad),
1203     _3 (cmpsd, Gx, Ex, Ib),
1204     _0 (bad),
1205     _0 (bad),
1206     _0 (bad),
1207     _0 (bad),
1208     _0 (bad),
1209   },
1210
1211   [X86_INSN_SSE_GROUP_d0].insns = {
1212     _2 (addsubps, Gx, Ex),
1213     _0 (bad),
1214     _0 (bad),
1215     _0 (bad),
1216     _0 (bad),
1217     _0 (bad),
1218     _2 (movdq2q, Gm, Ex),
1219     _0 (bad),
1220   },
1221
1222   [X86_INSN_SSE_GROUP_d8].insns = {
1223     _0 (bad),
1224     _0 (bad),
1225     _0 (bad),
1226     _0 (bad),
1227     _0 (bad),
1228     _0 (bad),
1229     _0 (bad),
1230     _0 (bad),
1231   },
1232
1233   [X86_INSN_SSE_GROUP_e0].insns = {
1234     _0 (bad),
1235     _0 (bad),
1236     _0 (bad),
1237     _0 (bad),
1238     _0 (bad),
1239     _0 (bad),
1240     _2 (cvtpd2dq, Gx, Ex),
1241     _0 (bad),
1242   },
1243
1244   [X86_INSN_SSE_GROUP_e8].insns = {
1245     _0 (bad),
1246     _0 (bad),
1247     _0 (bad),
1248     _0 (bad),
1249     _0 (bad),
1250     _0 (bad),
1251     _0 (bad),
1252     _0 (bad),
1253   },
1254
1255   [X86_INSN_SSE_GROUP_f0].insns = {
1256     _2 (lddqu, Gx, Mx),
1257     _0 (bad),
1258     _0 (bad),
1259     _0 (bad),
1260     _0 (bad),
1261     _0 (bad),
1262     _0 (bad),
1263     _0 (bad),
1264   },
1265
1266   [X86_INSN_SSE_GROUP_f8].insns = {
1267     _0 (bad),
1268     _0 (bad),
1269     _0 (bad),
1270     _0 (bad),
1271     _0 (bad),
1272     _0 (bad),
1273     _0 (bad),
1274     _0 (bad),
1275   },
1276 };
1277
1278 #undef _
1279
1280 /* Parses memory displacements and immediates. */
1281 static u8 * x86_insn_parse_number (u32 log2_n_bytes,
1282                                    u8 * code, u8 * code_end,
1283                                    i64 * result)
1284 {
1285   i64 x = 0;
1286
1287   if (code + (1 << log2_n_bytes) > code_end)
1288     return 0;
1289
1290   switch (log2_n_bytes)
1291     {
1292     case 3:
1293       x = clib_little_to_host_unaligned_mem_u64 ((u64 *) code);
1294       break;
1295
1296     case 2:
1297       x = (i32) clib_little_to_host_unaligned_mem_u32 ((u32 *) code);
1298       break;
1299
1300     case 1:
1301       x = (i16) clib_little_to_host_unaligned_mem_u16 ((u16 *) code);
1302       break;
1303
1304     case 0:
1305       x = (i8) code[0];
1306       break;
1307
1308     default:
1309       ASSERT (0);
1310     }
1311
1312   *result = x;
1313   return code + (1 << log2_n_bytes);
1314 }
1315
1316 static u32
1317 x86_insn_log2_immediate_bytes (x86_insn_parse_t * p, x86_insn_t * insn)
1318 {
1319   u32 i = ~0;
1320   switch (x86_insn_immediate_type (insn))
1321     {
1322     case 'b': i = 0; break;
1323     case 'w': i = 1; break;
1324     case 'd': i = 2; break;
1325     case 'q': i = 3; break;
1326
1327     case 'z':
1328       i = p->log2_effective_operand_bytes;
1329       if (i > 2) i = 2;
1330       break;
1331
1332     case 'v':
1333       i = p->log2_effective_operand_bytes;
1334       break;
1335
1336     default:
1337       i = ~0;
1338       break;
1339     }
1340
1341   return i;
1342 }
1343
1344 static u8 *
1345 x86_insn_parse_modrm_byte (x86_insn_parse_t * x,
1346                            x86_insn_modrm_byte_t modrm,
1347                            u32 parse_flags,
1348                            u8 * code,
1349                            u8 * code_end)
1350 {
1351   u8 effective_address_bits;
1352
1353   if (parse_flags & X86_INSN_PARSE_64_BIT)
1354     effective_address_bits = (x->flags & X86_INSN_ADDRESS_SIZE) ? 32 : 64;
1355   else if (parse_flags & X86_INSN_PARSE_32_BIT)
1356     effective_address_bits = (x->flags & X86_INSN_ADDRESS_SIZE) ? 16 : 32;
1357   else
1358     effective_address_bits = (x->flags & X86_INSN_ADDRESS_SIZE) ? 32 : 16;
1359
1360   x->log2_effective_address_bytes = 1;
1361   x->log2_effective_address_bytes += effective_address_bits > 16;
1362   x->log2_effective_address_bytes += effective_address_bits > 32;
1363
1364   x->regs[0] |= modrm.reg;
1365   if (modrm.mode == 3)
1366     x->regs[1] |= modrm.rm;
1367   else
1368     {
1369       u32 log2_disp_bytes = ~0;
1370
1371       x->flags |= X86_INSN_IS_ADDRESS;
1372
1373       if (effective_address_bits != 16)
1374         {
1375           u8 has_sib_byte = 0;
1376
1377           switch (modrm.mode)
1378             {
1379             case 0:
1380               /* When base is bp displacement is present for mode 0. */
1381               if (modrm.rm == X86_INSN_GP_REG_BP)
1382                 {
1383                   log2_disp_bytes = x->log2_effective_address_bytes;
1384                   break;
1385                 }
1386               else if (modrm.rm == X86_INSN_GP_REG_SP
1387                        && effective_address_bits != 16)
1388                 {
1389                   has_sib_byte = 1;
1390                   break;
1391                 }
1392               /* fall through */
1393             case 1:
1394             case 2:
1395               x->regs[1] |= modrm.rm;
1396               x->flags |= X86_INSN_HAS_BASE;
1397               if (modrm.mode != 0)
1398                 {
1399                   log2_disp_bytes = (modrm.mode == 1
1400                                      ? 0
1401                                      : x->log2_effective_address_bytes);
1402                   if (log2_disp_bytes > 2)
1403                     log2_disp_bytes = 2;
1404                 }
1405               break;
1406             }
1407
1408           if (has_sib_byte)
1409             {
1410               x86_insn_sib_byte_t sib;
1411
1412               if (code >= code_end)
1413                 return 0;
1414               sib.byte = *code++;
1415
1416               x->log2_index_scale = 1 << sib.log2_scale;
1417               x->regs[1] |= sib.base;
1418               x->flags |= X86_INSN_HAS_BASE;
1419
1420               if (sib.index != X86_INSN_GP_REG_SP)
1421                 {
1422                   x->regs[2] |= sib.index;
1423                   x->flags |= X86_INSN_HAS_INDEX;
1424                 }
1425             }
1426         }
1427       else
1428         {
1429           /* effective_address_bits == 16 */
1430           switch (modrm.mode)
1431             {
1432             case 0:
1433               if (modrm.rm == 6)
1434                 {
1435                   /* [disp16] */
1436                   log2_disp_bytes = 1;
1437                   break;
1438                 }
1439               /* fall through */
1440             case 1:
1441             case 2:
1442               switch (modrm.rm)
1443                 {
1444                 case 0:         /* [bx + si/di] */
1445                 case 1:
1446                   x->regs[1] = X86_INSN_GP_REG_BX;
1447                   x->regs[2] = X86_INSN_GP_REG_SI + (modrm.rm & 1);
1448                   x->flags |= X86_INSN_HAS_BASE | X86_INSN_HAS_INDEX;
1449                   break;
1450
1451                 case 2:         /* [bp + si/di] */
1452                 case 3:
1453                   x->regs[1] = X86_INSN_GP_REG_BP;
1454                   x->regs[2] = X86_INSN_GP_REG_SI + (modrm.rm & 1);
1455                   x->flags |= X86_INSN_HAS_BASE | X86_INSN_HAS_INDEX;
1456                   break;
1457
1458                 case 4:         /* [si/di] */
1459                 case 5:
1460                   x->regs[1] = X86_INSN_GP_REG_SI + (modrm.rm & 1);
1461                   x->flags |= X86_INSN_HAS_BASE;
1462                   break;
1463
1464                 case 6:         /* [bp + disp] */
1465                   x->regs[1] = X86_INSN_GP_REG_BP;
1466                   x->flags |= X86_INSN_HAS_BASE;
1467                   break;
1468
1469                 case 7:         /* [bx + disp] */
1470                   x->regs[1] = X86_INSN_GP_REG_BX;
1471                   x->flags |= X86_INSN_HAS_BASE;
1472                   break;
1473                 }
1474
1475               if (modrm.mode != 0)
1476                 log2_disp_bytes = modrm.mode == 1 ? 0 : 1;
1477               break;
1478             }
1479         }
1480       
1481       if (log2_disp_bytes != ~0)
1482         {
1483           i64 disp;
1484           code = x86_insn_parse_number (log2_disp_bytes, code, code_end,
1485                                         &disp);
1486           if (code)
1487             x->displacement = disp;
1488         }
1489     }
1490
1491   return code;
1492 }
1493
1494 u8 * x86_insn_parse (x86_insn_parse_t * p, u8 * code_start)
1495 {
1496   u8 i, * code, * code_end;
1497   x86_insn_t * insn, * group_insn;
1498   u8 default_operand_bits, effective_operand_bits;
1499   u32 opcode, parse_flags;
1500
1501   /* Preserve global parse flags. */
1502   parse_flags = p->flags & (X86_INSN_PARSE_32_BIT | X86_INSN_PARSE_64_BIT);
1503   memset (p, 0, sizeof (p[0]));
1504   p->flags = parse_flags;
1505
1506   /* 64 implies 32 bit parsing. */
1507   if (parse_flags & X86_INSN_PARSE_64_BIT)
1508     parse_flags |= X86_INSN_PARSE_32_BIT;
1509
1510   /* Instruction must be <= 15 bytes. */
1511   code = code_start;
1512   code_end = code + 15;
1513
1514   /* Parse legacy prefixes. */
1515   while (1)
1516     {
1517       if (code >= code_end)
1518         goto insn_too_long;
1519       i = code[0];
1520       code++;
1521       switch (i)
1522         {
1523         default: goto prefix_done;
1524
1525           /* Set flags based on prefix. */
1526 #define _(x,o) case o: p->flags |= X86_INSN_##x; break;
1527           foreach_x86_legacy_prefix;
1528 #undef _
1529         }
1530     }
1531  prefix_done:
1532
1533   /* REX prefix. */
1534   if ((parse_flags & X86_INSN_PARSE_64_BIT) && i >= 0x40 && i <= 0x4f)
1535     {
1536       p->regs[0] |= ((i & (1 << 2)) != 0) << 3; /* r bit */
1537       p->regs[1] |= ((i & (1 << 0)) != 0) << 3; /* b bit */
1538       p->regs[2] |= ((i & (1 << 1)) != 0) << 3; /* x bit */
1539       p->flags |= ((i & (1 << 3))               /* w bit */
1540                    ? X86_INSN_OPERAND_SIZE_64 : 0);
1541       if (code >= code_end)
1542         goto insn_too_long;
1543       i = *code++;
1544     }
1545
1546   opcode = i;
1547   if (opcode == 0x0f)
1548     {
1549       /* two byte opcode. */;
1550       if (code >= code_end)
1551         goto insn_too_long;
1552       i = *code++;
1553       opcode = (opcode << 8) | i;
1554       insn = x86_insns_two_byte + i;
1555     }
1556   else
1557     {
1558       static x86_insn_t arpl = {
1559         .name = "arpl",
1560         .operands[0].data = "Ew",
1561         .operands[1].data = "Gw",
1562       };
1563
1564       if (PREDICT_FALSE (i == 0x63
1565                          && ! (parse_flags & X86_INSN_PARSE_64_BIT)))
1566         insn = &arpl;
1567       else
1568         insn = x86_insns_one_byte + i;
1569     }
1570
1571   if ((i = X86_INSN_FLAG_GET_SSE_GROUP (insn->flags)) != 0)
1572     {
1573       x86_insn_group8_t * g8;
1574
1575       if (p->flags & X86_INSN_OPERAND_SIZE)
1576         g8 = x86_insn_sse_groups_operand_size;
1577       else if (p->flags & X86_INSN_REPZ)
1578         g8 = x86_insn_sse_groups_repz;
1579       else if (p->flags & X86_INSN_REPNZ)
1580         g8 = x86_insn_sse_groups_repnz;
1581       else
1582         g8 = 0;
1583
1584       /* insn flags have 1 + group so != 0 test above can work. */
1585       ASSERT ((i - 1) < ARRAY_LEN (x86_insn_sse_groups_operand_size));
1586       if (g8)
1587         insn = g8[i - 1].insns + (opcode & 7);
1588     }
1589
1590   /* Parse modrm and displacement if present. */
1591   if (x86_insn_has_modrm_byte (insn))
1592     {
1593       x86_insn_modrm_byte_t modrm;
1594
1595       if (code >= code_end)
1596         goto insn_too_long;
1597       modrm.byte = *code++;
1598
1599       /* Handle special 0x0f01 and 0x0fae encodings. */
1600       if (PREDICT_FALSE (modrm.mode == 3
1601                          && (opcode == 0x0f01
1602                              || opcode == 0x0fae)))
1603         {
1604           static x86_insn_t x86_insns_0f01_special[] = {
1605             _0 (swapgs), _0 (rdtscp), _0 (bad), _0 (bad),
1606             _0 (bad), _0 (bad), _0 (bad), _0 (bad),
1607           };
1608           static x86_insn_t x86_insns_0fae_special[] = {
1609             _0 (vmrun), _0 (vmmcall), _0 (vmload), _0 (vmsave),
1610             _0 (stgi), _0 (clgi), _0 (skinit), _0 (invlpga),
1611           };
1612
1613           if (opcode == 0x0f01)
1614             insn = x86_insns_0f01_special;
1615           else
1616             insn = x86_insns_0fae_special;
1617           insn += modrm.rm;
1618           opcode = (opcode << 8) | modrm.byte;
1619         }
1620       else
1621         {
1622           code = x86_insn_parse_modrm_byte (p, modrm, parse_flags,
1623                                             code, code_end);
1624           if (! code)
1625             goto insn_too_long;
1626         }
1627     }
1628
1629   group_insn = 0;
1630   if ((i = X86_INSN_FLAG_GET_MODRM_REG_GROUP (insn->flags)) != 0)
1631     {
1632       u32 g = i - 1;
1633       ASSERT (g < ARRAY_LEN (x86_insn_modrm_reg_groups));
1634       group_insn = x86_insn_modrm_reg_groups[g].insns + (p->regs[0] & 7);
1635     }
1636
1637   p->insn = insn[0];
1638   if (group_insn)
1639     {
1640       u32 k;
1641       p->insn.name = group_insn->name;
1642       p->insn.flags |= group_insn->flags;
1643       for (k = 0; k < ARRAY_LEN (group_insn->operands); k++)
1644         if (x86_insn_operand_is_valid (group_insn, k))
1645           p->insn.operands[k] = group_insn->operands[k];
1646     }
1647
1648   default_operand_bits
1649     = ((((parse_flags & X86_INSN_PARSE_32_BIT) != 0)
1650         ^ ((p->flags & X86_INSN_OPERAND_SIZE) != 0))
1651        ? BITS (u32) : BITS (u16));
1652
1653   if ((parse_flags & X86_INSN_PARSE_64_BIT)
1654       && (p->insn.flags & X86_INSN_FLAG_DEFAULT_64_BIT))
1655     default_operand_bits = BITS (u64);
1656
1657   effective_operand_bits = default_operand_bits;
1658   if (p->flags & X86_INSN_OPERAND_SIZE_64)
1659     effective_operand_bits = BITS (u64);
1660
1661   p->log2_effective_operand_bytes = 1;
1662   p->log2_effective_operand_bytes += effective_operand_bits > 16;
1663   p->log2_effective_operand_bytes += effective_operand_bits > 32;
1664
1665   /* Parse immediate if present. */
1666   {
1667     u32 l = x86_insn_log2_immediate_bytes (p, insn);
1668     if (l <= 3)
1669       {
1670         code = x86_insn_parse_number (l, code, code_end, &p->immediate);
1671         if (! code)
1672           goto insn_too_long;
1673       }
1674   }
1675
1676   return code;
1677
1678  insn_too_long:
1679   return 0;
1680 }
1681
1682 static u8 * format_x86_gp_reg_operand (u8 * s, va_list * va)
1683 {
1684   u32 r = va_arg (*va, u32);
1685   u32 log2_n_bytes = va_arg (*va, u32);
1686
1687   const char names8[8] = "acdbsbsd";
1688   const char names16[8] = "xxxxppii";
1689
1690   ASSERT (r < 16);
1691
1692   /* Add % register prefix. */
1693   vec_add1 (s, '%');
1694
1695   switch (log2_n_bytes)
1696     {
1697     case 0:
1698       {
1699
1700         if (r < 8)
1701           s = format (s, "%c%c", names8[r & 3], (r >> 2) ? 'l' : 'h');
1702         else
1703           s = format (s, "r%db", r);
1704       }
1705       break;
1706       
1707       case 2:
1708       case 3:
1709         s = format (s, "%c", log2_n_bytes == 2 ? 'e' : 'r');
1710         /* fall through */
1711       case 1:
1712         if (r < 8)
1713           s = format (s, "%c%c", names8[r], names16[r]);
1714         else
1715           {
1716             s = format (s, "%d", r);
1717             if (log2_n_bytes != 3)
1718               s = format (s, "%c", log2_n_bytes == 1 ? 'w' : 'd');
1719           }
1720         break;
1721
1722     default:
1723       ASSERT (0);
1724     }
1725
1726   return s;
1727 }
1728
1729 static u8 * format_x86_reg_operand (u8 * s, va_list * va)
1730 {
1731   u32 reg = va_arg (*va, u32);
1732   u32 log2_n_bytes = va_arg (*va, u32);
1733   u32 type = va_arg (*va, u32);
1734
1735   switch (type)
1736     {
1737     default:
1738       ASSERT (0);
1739       break;
1740
1741     case 'x':
1742       ASSERT (reg < 16);
1743       return format (s, "%%xmm%d", reg);
1744
1745     case 'm':
1746       ASSERT (reg < 8);
1747       return format (s, "%%mm%d", reg);
1748
1749       /* Explicit byte/word/double-word/quad-word */
1750     case 'b': log2_n_bytes = 0; break;
1751     case 'w': log2_n_bytes = 1; break;
1752     case 'd': log2_n_bytes = 2; break;
1753     case 'q': log2_n_bytes = 3; break;
1754
1755       /* Use effective operand size. */
1756     case 'v': break;
1757
1758       /* word or double-word depending on effective operand size. */
1759     case 'z':
1760       log2_n_bytes = clib_min (log2_n_bytes, 2);
1761       break;
1762     }
1763
1764   s = format (s, "%U", format_x86_gp_reg_operand, reg, log2_n_bytes);
1765   return s;
1766 }
1767
1768 static u8 * format_x86_mem_operand (u8 * s, va_list * va)
1769 {
1770   x86_insn_parse_t * p = va_arg (*va, x86_insn_parse_t *);
1771
1772   if (p->displacement != 0)
1773     s = format (s, "0x%x", p->displacement);
1774
1775   if (p->flags & X86_INSN_HAS_BASE)
1776     {
1777       s = format (s, "(%U",
1778                   format_x86_gp_reg_operand, p->regs[1],
1779                     p->log2_effective_address_bytes);
1780       if (p->flags & X86_INSN_HAS_INDEX)
1781         {
1782           s = format (s, ",%U",
1783                       format_x86_gp_reg_operand, p->regs[2],
1784                         p->log2_effective_address_bytes);
1785           if (p->log2_index_scale != 0)
1786             s = format (s, ",%d", 1 << p->log2_index_scale);
1787         }
1788       s = format (s, ")");
1789     }
1790
1791   /* [RIP+disp] PC relative addressing in 64 bit mode. */
1792   else if (p->flags & X86_INSN_PARSE_64_BIT)
1793     s = format (s, "(%%rip)");
1794
1795   return s;
1796 }
1797
1798 static u8 * format_x86_insn_operand (u8 * s, va_list * va)
1799 {
1800   x86_insn_parse_t * p = va_arg (*va, x86_insn_parse_t *);
1801   x86_insn_t * insn = &p->insn;
1802   u32 o = va_arg (*va, u32);
1803   u8 c, t;
1804
1805   ASSERT (o < ARRAY_LEN (insn->operands));
1806   c = insn->operands[o].code;
1807   t = insn->operands[o].type;
1808
1809   /* Register encoded in instruction. */
1810   if (c < 8)
1811     return format (s, "%U",
1812                    format_x86_gp_reg_operand, c,
1813                    p->log2_effective_operand_bytes);
1814
1815   switch (c)
1816     {
1817     /* Memory or reg field from modrm byte. */
1818     case 'M':
1819       ASSERT (p->flags & X86_INSN_IS_ADDRESS);
1820       /* FALLTHROUGH */
1821     case 'E':
1822       if (p->flags & X86_INSN_IS_ADDRESS)
1823         s = format (s, "%U", format_x86_mem_operand, p);
1824       else
1825         s = format (s, "%U",
1826                     format_x86_reg_operand, p->regs[1],
1827                     p->log2_effective_operand_bytes, t);
1828       break;
1829
1830     /* reg field from modrm byte. */
1831     case 'R':
1832     case 'G':
1833       s = format (s, "%U",
1834                   format_x86_reg_operand, p->regs[0],
1835                   p->log2_effective_operand_bytes, t);
1836       break;
1837
1838     case 'I':
1839       {
1840         u32 l = x86_insn_log2_immediate_bytes (p, insn);
1841         i64 mask = pow2_mask (8ULL << l);
1842         s = format (s, "$0x%Lx", p->immediate & mask);
1843       }
1844       break;
1845
1846     case 'J':
1847       if (p->immediate < 0)
1848         s = format (s, "- 0x%Lx", -p->immediate);
1849       else
1850         s = format (s, "+ 0x%Lx", p->immediate);
1851       break;
1852
1853     case 'O':
1854       s = format (s, "0x%Lx", p->immediate);
1855       break;
1856
1857     case 'A':
1858       /* AX/AL */
1859       s = format (s, "%U",
1860                   format_x86_gp_reg_operand, X86_INSN_GP_REG_AX,
1861                   t == 'L' ? 0 : p->log2_effective_operand_bytes);
1862       break;
1863
1864     case 'B':
1865       /* BX/BL/BP */
1866       s = format (s, "%U",
1867                   format_x86_gp_reg_operand,
1868                   t == 'P' ? X86_INSN_GP_REG_BP : X86_INSN_GP_REG_BX,
1869                   t == 'L' ? 0 : p->log2_effective_operand_bytes);
1870       break;
1871
1872     case 'C':
1873       /* CX/CL */
1874       s = format (s, "%U",
1875                   format_x86_gp_reg_operand, X86_INSN_GP_REG_CX,
1876                   t == 'L' ? 0 : p->log2_effective_operand_bytes);
1877       break;
1878
1879     case 'D':
1880       /* DX/DL/DI */
1881       s = format (s, "%U",
1882                   format_x86_gp_reg_operand,
1883                   t == 'I' ? X86_INSN_GP_REG_DI : X86_INSN_GP_REG_DX,
1884                   t == 'L' ? 0 : p->log2_effective_operand_bytes);
1885       break;
1886
1887     case 'S':
1888       /* SI/SP */
1889       s = format (s, "%U",
1890                   format_x86_gp_reg_operand,
1891                   t == 'I' ? X86_INSN_GP_REG_SI : X86_INSN_GP_REG_SP,
1892                   p->log2_effective_operand_bytes);
1893       break;
1894
1895     case '1':
1896       s = format (s, "1");
1897       break;
1898
1899     default:
1900       ASSERT (0);
1901     }
1902
1903   return s;
1904 }
1905
1906 u8 * format_x86_insn_parse (u8 * s, va_list * va)
1907 {
1908   x86_insn_parse_t * p = va_arg (*va, x86_insn_parse_t *);
1909   x86_insn_t * insn = &p->insn;
1910   u32 o, i, is_src_dst;
1911
1912   s = format (s, "%s", insn->name);
1913
1914   if (! x86_insn_operand_is_valid (insn, 0))
1915     goto done;
1916
1917   is_src_dst = x86_insn_operand_is_valid (insn, 1);
1918
1919   /* If instruction has immediate add suffix to opcode to
1920      indicate operand size. */
1921   if (is_src_dst)
1922     {
1923       u32 b;
1924
1925       b = x86_insn_log2_immediate_bytes (p, insn);
1926       if (b < p->log2_effective_operand_bytes
1927           && (p->flags & X86_INSN_IS_ADDRESS))
1928         s = format (s, "%c", "bwlq"[b]);
1929     }
1930
1931   for (i = 0; i < ARRAY_LEN (insn->operands); i++)
1932     {
1933       o = is_src_dst + i;
1934       if (! x86_insn_operand_is_valid (insn, o))
1935         break;
1936       s = format (s, "%s%U",
1937                   i == 0 ? " " : ", ",
1938                   format_x86_insn_operand, p, o);
1939     }
1940
1941   if (is_src_dst)
1942     s = format (s, ", %U",
1943                 format_x86_insn_operand, p, 0);
1944
1945  done:
1946   return s;
1947 }