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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 opcode name remove to save table space; enum
22 #include <vppinfra/error.h>
23 #include <vppinfra/byte_order.h>
24 #include <vppinfra/asm_x86.h>
26 #define foreach_x86_gp_register \
27 _ (AX) _ (CX) _ (DX) _ (BX) \
28 _ (SP) _ (BP) _ (SI) _ (DI)
31 #define _(r) X86_INSN_GP_REG_##r,
32 foreach_x86_gp_register
34 } x86_insn_gp_register_t;
43 } x86_insn_modrm_byte_t;
52 } x86_insn_sib_byte_t;
55 x86_insn_has_modrm_byte (x86_insn_t * insn)
58 for (i = 0; i < ARRAY_LEN (insn->operands); i++)
59 switch (insn->operands[i].code)
61 case 'G': case 'E': case 'M': case 'R':
68 x86_insn_immediate_type (x86_insn_t * insn)
71 for (i = 0; i < ARRAY_LEN (insn->operands); i++)
72 switch (insn->operands[i].code)
77 return insn->operands[i].type;
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) \
88 #define foreach_x86_insn_sse_group \
89 _ (10) _ (28) _ (50) _ (58) _ (60) _ (68) _ (70) _ (78) \
90 _ (c0) _ (d0) _ (d8) _ (e0) _ (e8) _ (f0) _ (f8)
93 #define _(x) X86_INSN_MODRM_REG_GROUP_##x,
94 foreach_x86_insn_modrm_reg_group
96 #define _(x) X86_INSN_SSE_GROUP_##x,
97 foreach_x86_insn_sse_group
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
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
115 #define foreach_x86_gp_reg \
116 _ (AX) _ (CX) _ (DX) _ (BX) \
117 _ (SP) _ (BP) _ (SI) _ (DI)
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)
125 #define _3f(x,f,o0,o1,o2) \
129 .operands[0] = { .data = #o0 }, \
130 .operands[1] = { .data = #o1 }, \
131 .operands[2] = { .data = #o2 }, \
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,__)
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)
143 static x86_insn_t x86_insns_one_byte[256] = {
159 _0 (escape_two_byte),
188 #define _(r) _1 (inc, r),
191 #define _(r) _1 (dec, r),
196 #define _(r) _1f (push, X86_INSN_FLAG_DEFAULT_64_BIT, r),
199 #define _(r) _1f (pop, X86_INSN_FLAG_DEFAULT_64_BIT, r),
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),
222 #define _(x) _1 (j##x, Jb),
223 foreach_x86_condition
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),
242 _1f (modrm_group_1a, X86_INSN_FLAG_MODRM_REG_GROUP_1a, Ev),
289 #define _(r) _2 (mov, r, Iv),
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),
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),
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),
339 _1f (call, X86_INSN_FLAG_DEFAULT_64_BIT, Jz),
340 _1f ( jmp, X86_INSN_FLAG_DEFAULT_64_BIT, Jz),
355 _0f (modrm_group_3, X86_INSN_FLAG_MODRM_REG_GROUP_3),
356 _0f (modrm_group_3, X86_INSN_FLAG_MODRM_REG_GROUP_3),
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),
367 static x86_insn_t x86_insns_two_byte[256] = {
369 _0f (modrm_group_6, X86_INSN_FLAG_MODRM_REG_GROUP_6),
370 _0f (modrm_group_7, X86_INSN_FLAG_MODRM_REG_GROUP_7),
382 _0f (modrm_group_p, X86_INSN_FLAG_MODRM_REG_GROUP_p),
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),
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),
441 #define _(x) _2 (cmov##x, Gv, Ev),
442 foreach_x86_condition
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),
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),
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),
500 #define _(x) _1 (jmp##x, Jz),
501 foreach_x86_condition
505 #define _(x) _1 (set##x, Eb),
506 foreach_x86_condition
514 _3 (shld, Ev, Gv, Ib),
515 _3 (shld, Ev, Gv, CL),
522 _3 (shrd, Ev, Gv, Ib),
523 _3 (shrd, Ev, Gv, CL),
524 _0f (modrm_group_15, X86_INSN_FLAG_MODRM_REG_GROUP_15),
528 _2 (cmpxchg, Eb, Gb),
529 _2 (cmpxchg, Ev, Gv),
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),
548 _3f (cmpps, X86_INSN_FLAG_SSE_GROUP_c0, Gx, Ex, Ib),
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),
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),
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),
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),
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),
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),
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),
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),
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),
645 [X86_INSN_MODRM_REG_GROUP_5].insns = {
648 _1f (call, X86_INSN_FLAG_DEFAULT_64_BIT, Ev),
650 _1f (jmp, X86_INSN_FLAG_DEFAULT_64_BIT, Ev),
652 _1f (push, X86_INSN_FLAG_DEFAULT_64_BIT, Ev),
656 [X86_INSN_MODRM_REG_GROUP_6].insns = {
667 [X86_INSN_MODRM_REG_GROUP_7].insns = {
678 [X86_INSN_MODRM_REG_GROUP_8].insns = {
689 [X86_INSN_MODRM_REG_GROUP_9].insns = {
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),
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),
710 [X86_INSN_MODRM_REG_GROUP_12].insns = {
721 [X86_INSN_MODRM_REG_GROUP_13].insns = {
732 [X86_INSN_MODRM_REG_GROUP_14].insns = {
743 [X86_INSN_MODRM_REG_GROUP_15].insns = {
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),
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),
777 static x86_insn_group8_t x86_insn_sse_groups_repz[] = {
778 [X86_INSN_SSE_GROUP_10].insns = {
781 _2 (movsldup, Gx, Ex),
785 _2 (movshdup, Gx, Ex),
789 [X86_INSN_SSE_GROUP_28].insns = {
792 _2 (cvtsi2ss, Gx, Ev),
794 _2 (cvttss2si, Gv, Ex),
795 _2 (cvtss2si, Gv, Ex),
800 [X86_INSN_SSE_GROUP_50].insns = {
803 _2 (rsqrtps, Gx, Ex),
811 [X86_INSN_SSE_GROUP_58].insns = {
814 _2 (cvtss2sd, Gx, Ex),
815 _2 (cvttps2dq, Gx, Ex),
822 [X86_INSN_SSE_GROUP_60].insns = {
833 [X86_INSN_SSE_GROUP_68].insns = {
844 [X86_INSN_SSE_GROUP_70].insns = {
845 _3 (pshufhw, Gx, Ex, Ib),
855 [X86_INSN_SSE_GROUP_78].insns = {
866 [X86_INSN_SSE_GROUP_c0].insns = {
869 _3 (cmpss, Gx, Ex, Ib),
877 [X86_INSN_SSE_GROUP_d0].insns = {
884 _2 (movq2dq, Gx, Em),
888 [X86_INSN_SSE_GROUP_d8].insns = {
899 [X86_INSN_SSE_GROUP_e0].insns = {
906 _2 (cvtdq2pd, Gx, Ex),
910 [X86_INSN_SSE_GROUP_e8].insns = {
921 [X86_INSN_SSE_GROUP_f0].insns = {
932 [X86_INSN_SSE_GROUP_f8].insns = {
944 static x86_insn_group8_t x86_insn_sse_groups_operand_size[] = {
945 [X86_INSN_SSE_GROUP_10].insns = {
950 _2 (unpcklpd, Gx, Ex),
951 _2 (unpckhpd, Gx, Ex),
956 [X86_INSN_SSE_GROUP_28].insns = {
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),
967 [X86_INSN_SSE_GROUP_50].insns = {
968 _2 (movmskpd, Gd, Rx),
978 [X86_INSN_SSE_GROUP_58].insns = {
981 _2 (cvtpd2ps, Gx, Ex),
982 _2 (cvtps2dq, Gx, Ex),
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),
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),
1008 _2 (movdqa, Gx, Ex),
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),
1022 [X86_INSN_SSE_GROUP_78].insns = {
1027 _2 (haddpd, Gx, Ex),
1028 _2 (hsubpd, Gx, Ex),
1030 _2 (movdqa, Ex, Gx),
1033 [X86_INSN_SSE_GROUP_c0].insns = {
1036 _3 (cmppd, Gx, Ex, Ib),
1038 _3 (pinsrw, Gx, Ew, Ib),
1039 _3 (pextrw, Gd, Gx, Ib),
1040 _3 (shufpd, Gx, Ex, Ib),
1044 [X86_INSN_SSE_GROUP_d0].insns = {
1045 _2 (addsubpd, Gx, Ex),
1050 _2 (pmullw, Gx, Ex),
1052 _2 (pmovmskb, Gd, Rx),
1055 [X86_INSN_SSE_GROUP_d8].insns = {
1056 _2 (psubusb, Gx, Ex),
1057 _2 (psubusw, Gx, Ex),
1058 _2 (pminub, Gx, Ex),
1060 _2 (paddusb, Gx, Ex),
1061 _2 (paddusw, Gx, Ex),
1062 _2 (pmaxub, Gx, Ex),
1066 [X86_INSN_SSE_GROUP_e0].insns = {
1071 _2 (pmulhuw, Gx, Ex),
1072 _2 (pmulhw, Gx, Ex),
1073 _2 (cvttpd2dq, Gx, Ex),
1074 _2 (movntdq, Mx, Gx),
1077 [X86_INSN_SSE_GROUP_e8].insns = {
1078 _2 (psubsb, Gx, Ex),
1079 _2 (psubsw, Gx, Ex),
1080 _2 (pminsw, Gx, Ex),
1082 _2 (paddsb, Gx, Ex),
1083 _2 (paddsw, Gx, Ex),
1084 _2 (pmaxsw, Gx, Ex),
1088 [X86_INSN_SSE_GROUP_f0].insns = {
1093 _2 (pmuludq, Gx, Ex),
1094 _2 (pmaddwd, Gx, Ex),
1095 _2 (psadbw, Gx, Ex),
1096 _2 (maskmovdqu, Gx, Ex),
1099 [X86_INSN_SSE_GROUP_f8].insns = {
1111 static x86_insn_group8_t x86_insn_sse_groups_repnz[] = {
1112 [X86_INSN_SSE_GROUP_10].insns = {
1115 _2 (movddup, Gx, Ex),
1123 [X86_INSN_SSE_GROUP_28].insns = {
1126 _2 (cvtsi2sd, Gx, Ev),
1128 _2 (cvttsd2si, Gv, Ex),
1129 _2 (cvtsd2si, Gv, Ex),
1134 [X86_INSN_SSE_GROUP_50].insns = {
1136 _2 (sqrtsd, Gx, Ex),
1145 [X86_INSN_SSE_GROUP_58].insns = {
1148 _2 (cvtsd2ss, Gx, Ex),
1156 [X86_INSN_SSE_GROUP_60].insns = {
1167 [X86_INSN_SSE_GROUP_68].insns = {
1178 [X86_INSN_SSE_GROUP_70].insns = {
1179 _3 (pshuflw, Gx, Ex, Ib),
1189 [X86_INSN_SSE_GROUP_78].insns = {
1194 _2 (haddps, Gx, Ex),
1195 _2 (hsubps, Gx, Ex),
1200 [X86_INSN_SSE_GROUP_c0].insns = {
1203 _3 (cmpsd, Gx, Ex, Ib),
1211 [X86_INSN_SSE_GROUP_d0].insns = {
1212 _2 (addsubps, Gx, Ex),
1218 _2 (movdq2q, Gm, Ex),
1222 [X86_INSN_SSE_GROUP_d8].insns = {
1233 [X86_INSN_SSE_GROUP_e0].insns = {
1240 _2 (cvtpd2dq, Gx, Ex),
1244 [X86_INSN_SSE_GROUP_e8].insns = {
1255 [X86_INSN_SSE_GROUP_f0].insns = {
1266 [X86_INSN_SSE_GROUP_f8].insns = {
1280 /* Parses memory displacements and immediates. */
1281 static u8 * x86_insn_parse_number (u32 log2_n_bytes,
1282 u8 * code, u8 * code_end,
1287 if (code + (1 << log2_n_bytes) > code_end)
1290 switch (log2_n_bytes)
1293 x = clib_little_to_host_unaligned_mem_u64 ((u64 *) code);
1297 x = (i32) clib_little_to_host_unaligned_mem_u32 ((u32 *) code);
1301 x = (i16) clib_little_to_host_unaligned_mem_u16 ((u16 *) code);
1313 return code + (1 << log2_n_bytes);
1317 x86_insn_log2_immediate_bytes (x86_insn_parse_t * p, x86_insn_t * insn)
1320 switch (x86_insn_immediate_type (insn))
1322 case 'b': i = 0; break;
1323 case 'w': i = 1; break;
1324 case 'd': i = 2; break;
1325 case 'q': i = 3; break;
1328 i = p->log2_effective_operand_bytes;
1333 i = p->log2_effective_operand_bytes;
1345 x86_insn_parse_modrm_byte (x86_insn_parse_t * x,
1346 x86_insn_modrm_byte_t modrm,
1351 u8 effective_address_bits;
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;
1358 effective_address_bits = (x->flags & X86_INSN_ADDRESS_SIZE) ? 32 : 16;
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;
1364 x->regs[0] |= modrm.reg;
1365 if (modrm.mode == 3)
1366 x->regs[1] |= modrm.rm;
1369 u32 log2_disp_bytes = ~0;
1371 x->flags |= X86_INSN_IS_ADDRESS;
1373 if (effective_address_bits != 16)
1375 u8 has_sib_byte = 0;
1380 /* When base is bp displacement is present for mode 0. */
1381 if (modrm.rm == X86_INSN_GP_REG_BP)
1383 log2_disp_bytes = x->log2_effective_address_bytes;
1386 else if (modrm.rm == X86_INSN_GP_REG_SP
1387 && effective_address_bits != 16)
1395 x->regs[1] |= modrm.rm;
1396 x->flags |= X86_INSN_HAS_BASE;
1397 if (modrm.mode != 0)
1399 log2_disp_bytes = (modrm.mode == 1
1401 : x->log2_effective_address_bytes);
1402 if (log2_disp_bytes > 2)
1403 log2_disp_bytes = 2;
1410 x86_insn_sib_byte_t sib;
1412 if (code >= code_end)
1416 x->log2_index_scale = 1 << sib.log2_scale;
1417 x->regs[1] |= sib.base;
1418 x->flags |= X86_INSN_HAS_BASE;
1420 if (sib.index != X86_INSN_GP_REG_SP)
1422 x->regs[2] |= sib.index;
1423 x->flags |= X86_INSN_HAS_INDEX;
1429 /* effective_address_bits == 16 */
1436 log2_disp_bytes = 1;
1444 case 0: /* [bx + si/di] */
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;
1451 case 2: /* [bp + si/di] */
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;
1458 case 4: /* [si/di] */
1460 x->regs[1] = X86_INSN_GP_REG_SI + (modrm.rm & 1);
1461 x->flags |= X86_INSN_HAS_BASE;
1464 case 6: /* [bp + disp] */
1465 x->regs[1] = X86_INSN_GP_REG_BP;
1466 x->flags |= X86_INSN_HAS_BASE;
1469 case 7: /* [bx + disp] */
1470 x->regs[1] = X86_INSN_GP_REG_BX;
1471 x->flags |= X86_INSN_HAS_BASE;
1475 if (modrm.mode != 0)
1476 log2_disp_bytes = modrm.mode == 1 ? 0 : 1;
1481 if (log2_disp_bytes != ~0)
1484 code = x86_insn_parse_number (log2_disp_bytes, code, code_end,
1487 x->displacement = disp;
1494 u8 * x86_insn_parse (x86_insn_parse_t * p, u8 * code_start)
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;
1501 /* Preserve global parse flags. */
1502 parse_flags = p->flags & (X86_INSN_PARSE_32_BIT | X86_INSN_PARSE_64_BIT);
1503 clib_memset (p, 0, sizeof (p[0]));
1504 p->flags = parse_flags;
1506 /* 64 implies 32 bit parsing. */
1507 if (parse_flags & X86_INSN_PARSE_64_BIT)
1508 parse_flags |= X86_INSN_PARSE_32_BIT;
1510 /* Instruction must be <= 15 bytes. */
1512 code_end = code + 15;
1514 /* Parse legacy prefixes. */
1517 if (code >= code_end)
1523 default: goto prefix_done;
1525 /* Set flags based on prefix. */
1526 #define _(x,o) case o: p->flags |= X86_INSN_##x; break;
1527 foreach_x86_legacy_prefix;
1534 if ((parse_flags & X86_INSN_PARSE_64_BIT) && i >= 0x40 && i <= 0x4f)
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)
1549 /* two byte opcode. */;
1550 if (code >= code_end)
1553 opcode = (opcode << 8) | i;
1554 insn = x86_insns_two_byte + i;
1558 static x86_insn_t arpl = {
1560 .operands[0].data = "Ew",
1561 .operands[1].data = "Gw",
1564 if (PREDICT_FALSE (i == 0x63
1565 && ! (parse_flags & X86_INSN_PARSE_64_BIT)))
1568 insn = x86_insns_one_byte + i;
1571 if ((i = X86_INSN_FLAG_GET_SSE_GROUP (insn->flags)) != 0)
1573 x86_insn_group8_t * g8;
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;
1584 /* insn flags have 1 + group so != 0 test above can work. */
1585 ASSERT ((i - 1) < ARRAY_LEN (x86_insn_sse_groups_operand_size));
1587 insn = g8[i - 1].insns + (opcode & 7);
1590 /* Parse modrm and displacement if present. */
1591 if (x86_insn_has_modrm_byte (insn))
1593 x86_insn_modrm_byte_t modrm;
1595 if (code >= code_end)
1597 modrm.byte = *code++;
1599 /* Handle special 0x0f01 and 0x0fae encodings. */
1600 if (PREDICT_FALSE (modrm.mode == 3
1601 && (opcode == 0x0f01
1602 || opcode == 0x0fae)))
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),
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),
1613 if (opcode == 0x0f01)
1614 insn = x86_insns_0f01_special;
1616 insn = x86_insns_0fae_special;
1618 opcode = (opcode << 8) | modrm.byte;
1622 code = x86_insn_parse_modrm_byte (p, modrm, parse_flags,
1630 if ((i = X86_INSN_FLAG_GET_MODRM_REG_GROUP (insn->flags)) != 0)
1633 ASSERT (g < ARRAY_LEN (x86_insn_modrm_reg_groups));
1634 group_insn = x86_insn_modrm_reg_groups[g].insns + (p->regs[0] & 7);
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];
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));
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);
1657 effective_operand_bits = default_operand_bits;
1658 if (p->flags & X86_INSN_OPERAND_SIZE_64)
1659 effective_operand_bits = BITS (u64);
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;
1665 /* Parse immediate if present. */
1667 u32 l = x86_insn_log2_immediate_bytes (p, insn);
1670 code = x86_insn_parse_number (l, code, code_end, &p->immediate);
1682 static u8 * format_x86_gp_reg_operand (u8 * s, va_list * va)
1684 u32 r = va_arg (*va, u32);
1685 u32 log2_n_bytes = va_arg (*va, u32);
1687 const char names8[8] = "acdbsbsd";
1688 const char names16[8] = "xxxxppii";
1692 /* Add % register prefix. */
1695 switch (log2_n_bytes)
1701 s = format (s, "%c%c", names8[r & 3], (r >> 2) ? 'l' : 'h');
1703 s = format (s, "r%db", r);
1709 s = format (s, "%c", log2_n_bytes == 2 ? 'e' : 'r');
1713 s = format (s, "%c%c", names8[r], names16[r]);
1716 s = format (s, "%d", r);
1717 if (log2_n_bytes != 3)
1718 s = format (s, "%c", log2_n_bytes == 1 ? 'w' : 'd');
1729 static u8 * format_x86_reg_operand (u8 * s, va_list * va)
1731 u32 reg = va_arg (*va, u32);
1732 u32 log2_n_bytes = va_arg (*va, u32);
1733 u32 type = va_arg (*va, u32);
1743 return format (s, "%%xmm%d", reg);
1747 return format (s, "%%mm%d", reg);
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;
1755 /* Use effective operand size. */
1758 /* word or double-word depending on effective operand size. */
1760 log2_n_bytes = clib_min (log2_n_bytes, 2);
1764 s = format (s, "%U", format_x86_gp_reg_operand, reg, log2_n_bytes);
1768 static u8 * format_x86_mem_operand (u8 * s, va_list * va)
1770 x86_insn_parse_t * p = va_arg (*va, x86_insn_parse_t *);
1772 if (p->displacement != 0)
1773 s = format (s, "0x%x", p->displacement);
1775 if (p->flags & X86_INSN_HAS_BASE)
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)
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);
1788 s = format (s, ")");
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)");
1798 static u8 * format_x86_insn_operand (u8 * s, va_list * va)
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);
1805 ASSERT (o < ARRAY_LEN (insn->operands));
1806 c = insn->operands[o].code;
1807 t = insn->operands[o].type;
1809 /* Register encoded in instruction. */
1811 return format (s, "%U",
1812 format_x86_gp_reg_operand, c,
1813 p->log2_effective_operand_bytes);
1817 /* Memory or reg field from modrm byte. */
1819 ASSERT (p->flags & X86_INSN_IS_ADDRESS);
1822 if (p->flags & X86_INSN_IS_ADDRESS)
1823 s = format (s, "%U", format_x86_mem_operand, p);
1825 s = format (s, "%U",
1826 format_x86_reg_operand, p->regs[1],
1827 p->log2_effective_operand_bytes, t);
1830 /* reg field from modrm byte. */
1833 s = format (s, "%U",
1834 format_x86_reg_operand, p->regs[0],
1835 p->log2_effective_operand_bytes, t);
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);
1847 if (p->immediate < 0)
1848 s = format (s, "- 0x%Lx", -p->immediate);
1850 s = format (s, "+ 0x%Lx", p->immediate);
1854 s = format (s, "0x%Lx", p->immediate);
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);
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);
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);
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);
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);
1896 s = format (s, "1");
1906 u8 * format_x86_insn_parse (u8 * s, va_list * va)
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;
1912 s = format (s, "%s", insn->name);
1914 if (! x86_insn_operand_is_valid (insn, 0))
1917 is_src_dst = x86_insn_operand_is_valid (insn, 1);
1919 /* If instruction has immediate add suffix to opcode to
1920 indicate operand size. */
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]);
1931 for (i = 0; i < ARRAY_LEN (insn->operands); i++)
1934 if (! x86_insn_operand_is_valid (insn, o))
1936 s = format (s, "%s%U",
1937 i == 0 ? " " : ", ",
1938 format_x86_insn_operand, p, o);
1942 s = format (s, ", %U",
1943 format_x86_insn_operand, p, 0);