235{
236 const int NO = CodeGenerator::NONE;
237 {
240 if (v & 0xF) {
241 snprintf(
buf,
sizeof(
buf),
"%d.%02X%x", v >> 12, (v >> 4) & 0xFF, v & 0xF);
242 } else {
243 snprintf(
buf,
sizeof(
buf),
"%d.%02X", v >> 12, (v >> 4) & 0xFF);
244 }
245 printf(
"const char *getVersionString() const { return \"%s\"; }\n",
buf);
246 }
247 const int B = 1 << 0;
248 const int W = 1 << 1;
249 const int D = 1 << 2;
250 const int Q = 1 << 3;
251 {
252 const struct Tbl {
256
257 { 0x6B, "packssdw" },
258 { 0x63, "packsswb" },
259 { 0x67, "packuswb" },
260
261 { 0xDB, "pand" },
262 { 0xDF, "pandn" },
263
264 { 0xF5, "pmaddwd" },
265 { 0xE4, "pmulhuw" },
266 { 0xE5, "pmulhw" },
267 { 0xD5, "pmullw" },
268
269 { 0xEB, "por" },
270
271 { 0x68, "punpckhbw" },
272 { 0x69, "punpckhwd" },
273 { 0x6A, "punpckhdq" },
274
275 { 0x60, "punpcklbw" },
276 { 0x61, "punpcklwd" },
277 { 0x62, "punpckldq" },
278
279 { 0xEF, "pxor" },
280
281
282 { 0xE0, "pavgb" },
283 { 0xE3, "pavgw" },
284 { 0xEE, "pmaxsw" },
285 { 0xDE, "pmaxub" },
286 { 0xEA, "pminsw" },
287 { 0xDA, "pminub" },
288 { 0xF6, "psadbw" },
289
290 { 0xD4, "paddq" },
291 { 0xF4, "pmuludq" },
292 { 0xFB, "psubq" },
293 };
295 const Tbl *
p = &
tbl[i];
296 printf(
"void %s(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x%02X); }\n"
298 }
299 }
300
301 {
302 const struct Tbl {
304 int mode;
307 { 0xFC,
B|W|
D,
"padd" },
308 { 0xEC,
B|W ,
"padds" },
309 { 0xDC,
B|W ,
"paddus" },
310 { 0x74,
B|W|
D,
"pcmpeq" },
311 { 0x64,
B|W|
D,
"pcmpgt" },
312 { 0xF0, W|
D|Q,
"psll" },
313 { 0xE0, W|
D ,
"psra" },
314 { 0xD0, W|
D|Q,
"psrl" },
315 { 0xF8,
B|W|
D,
"psub" },
316 { 0xE8,
B|W ,
"psubs" },
317 { 0xD8,
B|W ,
"psubus" },
318 };
320 const Tbl *
p = &
tbl[i];
321 static const char modTbl[][4] = {
322 "b", "w", "d", "q"
323 };
324 for (
int j = 0;
j < 4;
j++) {
325
326 if (!(
p->mode & (1 <<
j)))
continue;
327 printf(
"void %s%s(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x%02X); }\n"
330 );
331 }
332 }
333 }
334
335 {
336 const struct Tbl {
338 int ext;
339 int mode;
342 { 0x70, 6, W|
D|Q,
"psll" },
343 { 0x70, 4, W|
D ,
"psra" },
344 { 0x70, 2, W|
D|Q,
"psrl" },
345 };
347 const Tbl *
p = &
tbl[i];
348 static const char modTbl[][4] = {
349 "b", "w", "d", "q"
350 };
351 for (
int j = 0;
j < 4;
j++) {
352
353 if (!(
p->mode & (1 <<
j)))
continue;
354 printf(
"void %s%s(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x%02X, %d); }\n"
358 );
359 }
360 }
361 printf(
"void pslldq(const Xmm& xmm, int imm8) { opMMX_IMM(xmm, imm8, 0x%02X, %d); }\n", 0x73, 7);
362 printf(
"void psrldq(const Xmm& xmm, int imm8) { opMMX_IMM(xmm, imm8, 0x%02X, %d); }\n", 0x73, 3);
363 }
364
365 {
366 const struct Tbl {
371 { 0x70, 0, "pshufw" },
372 { 0x70, 0xF2, "pshuflw" },
373 { 0x70, 0xF3, "pshufhw" },
374 { 0x70, 0x66, "pshufd" },
375 };
377 const Tbl *
p = &
tbl[i];
378 printf(
"void %s(const Mmx& mmx, const Operand& op, uint8 imm8) { opMMX(mmx, op, 0x%02X, 0x%02X, imm8); }\n",
p->name,
p->code,
p->pref);
379 }
380 }
381 {
382 const struct MmxTbl6 {
385 int pref;
387 } mmxTbl6[] = {
388 { 0x6F, 0x7F, 0x66, "movdqa" },
389 { 0x6F, 0x7F, 0xF3, "movdqu" },
390
391 { 0x28, 0x29, NO, "movaps" },
392 { 0x10, 0x11, 0xF3, "movss" },
393 { 0x10, 0x11, NO, "movups" },
394 { 0x28, 0x29, 0x66, "movapd" },
395 { 0x10, 0x11, 0xF2, "movsd" },
396 { 0x10, 0x11, 0x66, "movupd" },
397 };
399 const MmxTbl6 *
p = &mmxTbl6[i];
400 printf(
"void %s(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x%02X, 0x%02X); }\n",
p->name,
p->code,
p->pref);
401 printf(
"void %s(const Address& addr, const Xmm& xmm) { ",
p->name);
402 if (
p->pref != NO)
printf(
"db(0x%02X); ",
p->pref);
403 printf(
"opModM(addr, xmm, 0x0F, 0x%02X); }\n",
p->code2);
404 }
405 }
406 {
407 enum {
408 PS = 1 << 0,
409 SS = 1 << 1,
410 PD = 1 << 2,
411 SD = 1 << 3
412 };
413 const struct {
414 int code;
416 } sufTbl[] = {
417 { NO, "ps" },
418 { 0xF3, "ss" },
419 { 0x66, "pd" },
420 { 0xF2, "sd" },
421 };
422 const struct Tbl {
424 int mode;
426 bool hasImm;
428 { 0x58, PS|SS|PD|SD, "add" },
429 { 0x55, PS|PD , "andn" },
430 { 0x54, PS|PD , "and" },
431 { 0xC2, PS|SS|PD|SD, "cmp", true },
432 { 0x5E, PS|SS|PD|SD, "div" },
433 { 0x5F, PS|SS|PD|SD, "max" },
434 { 0x5D, PS|SS|PD|SD, "min" },
435 { 0x59, PS|SS|PD|SD, "mul" },
436 { 0x56, PS|PD , "or" },
437 { 0x53, PS|SS , "rcp" },
438 { 0x52, PS|SS , "rsqrt" },
439 { 0xC6, PS|PD , "shuf", true },
440 { 0x51, PS|SS|PD|SD, "sqrt" },
441 { 0x5C, PS|SS|PD|SD, "sub" },
442 { 0x15, PS|PD , "unpckh" },
443 { 0x14, PS|PD , "unpckl" },
444 { 0x57, PS|PD , "xor" },
445
446 };
448 const Tbl *
p = &
tbl[i];
450 if (!(
p->mode & (1 <<
j)))
continue;
452
453 printf(
"void %s%s(const Xmm& xmm, const Operand& op, uint8 imm8) { opGen(xmm, op, 0x%2X, 0x%02X, isXMM_XMMorMEM, imm8); }\n",
p->name, sufTbl[
j].name,
p->code, sufTbl[
j].code);
454 } else {
455 printf(
"void %s%s(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x%2X, 0x%02X, isXMM_XMMorMEM); }\n",
p->name, sufTbl[
j].name,
p->code, sufTbl[
j].code);
456 }
457 }
458 }
459 }
460 {
461
462 const struct Tbl {
467 { 0xF7, 0x66, "maskmovdqu" },
468 { 0x12, 0 , "movhlps" },
469 { 0x16, 0 , "movlhps" },
470 };
472 const Tbl *
p = &
tbl[i];
473 printf(
"void %s(const Xmm& reg1, const Xmm& reg2) { ",
p->name);
474 if (
p->pref)
printf(
"db(0x%02X); ",
p->pref);
475 printf(
" opModR(reg1, reg2, 0x0F, 0x%02X); }\n",
p->code);
476 }
477 }
478 {
479
480 const struct Tbl {
482 int pref;
485 { 0x6D, 0x66, "punpckhqdq" },
486 { 0x6C, 0x66, "punpcklqdq" },
487
488 { 0x2F, NO , "comiss" },
489 { 0x2E, NO , "ucomiss" },
490 { 0x2F, 0x66, "comisd" },
491 { 0x2E, 0x66, "ucomisd" },
492
493 { 0x5A, 0x66, "cvtpd2ps" },
494 { 0x5A, NO , "cvtps2pd" },
495 { 0x5A, 0xF2, "cvtsd2ss" },
496 { 0x5A, 0xF3, "cvtss2sd" },
497 { 0xE6, 0xF2, "cvtpd2dq" },
498 { 0xE6, 0x66, "cvttpd2dq" },
499 { 0xE6, 0xF3, "cvtdq2pd" },
500 { 0x5B, 0x66, "cvtps2dq" },
501 { 0x5B, 0xF3, "cvttps2dq" },
502 { 0x5B, NO , "cvtdq2ps" },
503 };
505 const Tbl *
p = &
tbl[i];
506 printf(
"void %s(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x%02X, 0x%02X, isXMM_XMMorMEM); }\n",
p->name,
p->code,
p->pref);
507 }
508 }
509
510 {
511
512 const struct Tbl {
514 int pref;
516 const char *cond;
518 { 0x2A, NO , "cvtpi2ps", "isXMM_MMXorMEM" },
519 { 0x2D, NO , "cvtps2pi", "isMMX_XMMorMEM" },
520 { 0x2A, 0xF3, "cvtsi2ss", "isXMM_REG32orMEM" },
521 { 0x2D, 0xF3, "cvtss2si", "isREG32_XMMorMEM" },
522 { 0x2C, NO , "cvttps2pi", "isMMX_XMMorMEM" },
523 { 0x2C, 0xF3, "cvttss2si", "isREG32_XMMorMEM" },
524 { 0x2A, 0x66, "cvtpi2pd", "isXMM_MMXorMEM" },
525 { 0x2D, 0x66, "cvtpd2pi", "isMMX_XMMorMEM" },
526 { 0x2A, 0xF2, "cvtsi2sd", "isXMM_REG32orMEM" },
527 { 0x2D, 0xF2, "cvtsd2si", "isREG32_XMMorMEM" },
528 { 0x2C, 0x66, "cvttpd2pi", "isMMX_XMMorMEM" },
529 { 0x2C, 0xF2, "cvttsd2si", "isREG32_XMMorMEM" },
530 };
532 const Tbl *
p = &
tbl[i];
533 printf(
"void %s(const Operand& reg, const Operand& op) { opGen(reg, op, 0x%02X, 0x%02X, %s); }\n",
p->name,
p->code,
p->pref,
p->cond);
534 }
535 }
536 {
537
538 const struct Tbl {
539 int ext;
541 int code;
543 { 1, "t0", 0x18},
544 { 2, "t1", 0x18},
545 { 3, "t2", 0x18},
546 { 0, "nta", 0x18},
547 { 2, "wt1", 0x0D},
548 { 1, "w", 0x0D},
549 };
551 const Tbl *
p = &
tbl[i];
552 printf(
"void prefetch%s(const Address& addr) { opModM(addr, Reg32(%d), 0x0F, 0x%02X); }\n",
p->name,
p->ext,
p->code);
553 }
554 }
555 {
556 const struct Tbl {
558 int pref;
561 { 0x16, NO, "movhps" },
562 { 0x12, NO, "movlps" },
563 { 0x16, 0x66, "movhpd" },
564 { 0x12, 0x66, "movlpd" },
565 };
567 const Tbl *
p = &
tbl[i];
568 printf(
"void %s(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x%02X, 0x%02X); }\n",
p->name,
p->code,
p->pref);
569 }
570 }
571 {
572
573 const struct Tbl {
577 { 0, "o" },
578 { 1, "no" },
579 { 2, "b" },
580 { 2, "c" },
581 { 2, "nae" },
582 { 3, "nb" },
583 { 3, "ae" },
584 { 3, "nc" },
585 { 4, "e" },
586 { 4, "z" },
587 { 5, "ne" },
588 { 5, "nz" },
589 { 6, "be" },
590 { 6, "na" },
591 { 7, "nbe" },
592 { 7, "a" },
593 { 8, "s" },
594 { 9, "ns" },
595 { 10, "p" },
596 { 10, "pe" },
597 { 11, "np" },
598 { 11, "po" },
599 { 12, "l" },
600 { 12, "nge" },
601 { 13, "nl" },
602 { 13, "ge" },
603 { 14, "le" },
604 { 14, "ng" },
605 { 15, "nle" },
606 { 15, "g" },
607 };
608 const char *msg = "//-V524";
610 const Tbl *
p = &
tbl[i];
611 printf(
"void cmov%s(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | %d); }%s\n",
p->name,
p->ext, msg);
612 printf(
"void j%s(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x%02X, 0x%02X, 0x%02X); }%s\n",
p->name,
p->ext | 0x70,
p->ext | 0x80, 0x0F, msg);
613 printf(
"void j%s(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x%02X, 0x%02X, 0x%02X); }%s\n",
p->name,
p->ext | 0x70,
p->ext | 0x80, 0x0F, msg);
614 printf(
"void j%s(const char *label, LabelType type = T_AUTO) { j%s(std::string(label), type); }%s\n",
p->name,
p->name, msg);
615 printf(
"void j%s(const void *addr) { opJmpAbs(addr, T_NEAR, 0x%02X, 0x%02X, 0x%02X); }%s\n",
p->name,
p->ext | 0x70,
p->ext | 0x80, 0x0F, msg);
616 printf(
"void set%s(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | %d); }%s\n",
p->name,
p->ext, msg);
617 }
618 }
620 {
622 { "bnd", 0xf2 },
623 { "cbw", 0x66, 0x98 },
624 { "cdq", 0x99 },
625 { "clc", 0xF8 },
626 { "cld", 0xFC },
627 { "cli", 0xFA },
628 { "cmc", 0xF5 },
629
630 { "cpuid", 0x0F, 0xA2 },
631 { "cwd", 0x66, 0x99 },
632 { "cwde", 0x98 },
633 { "movsb", 0xA4 },
634 { "movsw", 0x66, 0xA5 },
635 { "movsd", 0xA5 },
636 { "rep", 0xF3 },
637
638 { "lahf", 0x9F },
639 { "lock", 0xF0 },
640
641 { "sahf", 0x9E },
642 { "stc", 0xF9 },
643 { "std", 0xFD },
644 { "sti", 0xFB },
645
646 { "emms", 0x0F, 0x77 },
647 { "pause", 0xF3, 0x90 },
648 { "sfence", 0x0F, 0xAE, 0xF8 },
649 { "lfence", 0x0F, 0xAE, 0xE8 },
650 { "mfence", 0x0F, 0xAE, 0xF0 },
651 { "monitor", 0x0F, 0x01, 0xC8 },
652 { "mwait", 0x0F, 0x01, 0xC9 },
653
654 { "rdmsr", 0x0F, 0x32 },
655 { "rdpmc", 0x0F, 0x33 },
656 { "rdtsc", 0x0F, 0x31 },
657 { "rdtscp", 0x0F, 0x01, 0xF9 },
658 { "ud2", 0x0F, 0x0B },
659 { "wait", 0x9B },
660 { "fwait", 0x9B },
661 { "wbinvd", 0x0F, 0x09 },
662 { "wrmsr", 0x0F, 0x30 },
663 { "xlatb", 0xD7 },
664
665 { "popf", 0x9D },
666 { "pushf", 0x9C },
667 { "stac", 0x0F, 0x01, 0xCB },
668
669 { "vzeroall", 0xC5, 0xFC, 0x77 },
670 { "vzeroupper", 0xC5, 0xF8, 0x77 },
671 { "xgetbv", 0x0F, 0x01, 0xD0 },
672
673
674 { "f2xm1", 0xD9, 0xF0 },
675 { "fabs", 0xD9, 0xE1 },
676 { "faddp", 0xDE, 0xC1 },
677 { "fchs", 0xD9, 0xE0 },
678
679 { "fcom", 0xD8, 0xD1 },
680 { "fcomp", 0xD8, 0xD9 },
681 { "fcompp", 0xDE, 0xD9 },
682 { "fcos", 0xD9, 0xFF },
683 { "fdecstp", 0xD9, 0xF6 },
684 { "fdivp", 0xDE, 0xF9 },
685 { "fdivrp", 0xDE, 0xF1 },
686 { "fincstp", 0xD9, 0xF7 },
687 { "finit", 0x9B, 0xDB, 0xE3 },
688 { "fninit", 0xDB, 0xE3 },
689 { "fld1", 0xD9, 0xE8 },
690 { "fldl2t", 0xD9, 0xE9 },
691 { "fldl2e", 0xD9, 0xEA },
692 { "fldpi", 0xD9, 0xEB },
693 { "fldlg2", 0xD9, 0xEC },
694 { "fldln2", 0xD9, 0xED },
695 { "fldz", 0xD9, 0xEE },
696 { "fmulp", 0xDE, 0xC9 },
697 { "fnop", 0xD9, 0xD0 },
698 { "fpatan", 0xD9, 0xF3 },
699 { "fprem", 0xD9, 0xF8 },
700 { "fprem1", 0xD9, 0xF5 },
701 { "fptan", 0xD9, 0xF2 },
702 { "frndint", 0xD9, 0xFC },
703 { "fscale", 0xD9, 0xFD },
704 { "fsin", 0xD9, 0xFE },
705 { "fsincos", 0xD9, 0xFB },
706 { "fsqrt", 0xD9, 0xFA },
707 { "fsubp", 0xDE, 0xE9 },
708 { "fsubrp", 0xDE, 0xE1 },
709 { "ftst", 0xD9, 0xE4 },
710 { "fucom", 0xDD, 0xE1 },
711 { "fucomp", 0xDD, 0xE9 },
712 { "fucompp", 0xDA, 0xE9 },
713 { "fxam", 0xD9, 0xE5 },
714 { "fxch", 0xD9, 0xC9 },
715 { "fxtract", 0xD9, 0xF4 },
716 { "fyl2x", 0xD9, 0xF1 },
717 { "fyl2xp1", 0xD9, 0xF9 },
718 };
720 }
721 {
722 const struct Tbl {
727 { 0x10, 2, "adc" },
728 { 0x00, 0, "add" },
729 { 0x20, 4, "and_" },
730 { 0x38, 7, "cmp" },
731 { 0x08, 1, "or_" },
732 { 0x18, 3, "sbb" },
733 { 0x28, 5, "sub" },
734 { 0x30, 6, "xor_" },
735 };
737 const Tbl *
p = &
tbl[i];
738 printf(
"void %s(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x%02X); }\n",
p->name,
p->code);
739 printf(
"void %s(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x%02X, %d); }\n",
p->name,
p->code,
p->ext);
740 }
741 }
742
743 {
744 const struct Tbl {
749 { 0x48, 1, "dec" },
750 { 0x40, 0, "inc" },
751 };
753 const Tbl *
p = &
tbl[i];
754 printf(
"void %s(const Operand& op) { opIncDec(op, 0x%02X, %d); }\n",
p->name,
p->code,
p->ext);
755 }
756 }
757 {
758 const struct Tbl {
763 { 0xa3, 4, "bt" },
764 { 0xab, 5, "bts" },
765 { 0xb3, 6, "btr" },
766 { 0xbb, 7, "btc" },
767 };
769 const Tbl *
p = &
tbl[i];
770 printf(
"void %s(const Operand& op, const Reg& reg) { opModRM(reg, op, op.isREG(16|32|64) && op.getBit() == reg.getBit(), op.isMEM(), 0x0f, 0x%02X); }\n",
p->name,
p->code);
771 printf(
"void %s(const Operand& op, uint8 imm) { opR_ModM(op, 16|32|64, %d, 0x0f, 0xba, NONE, false, 1); db(imm); }\n",
p->name,
p->ext);
772 }
773 }
774 {
775 const struct Tbl {
780 { 0xF6, 6, "div" },
781 { 0xF6, 7, "idiv" },
782 { 0xF6, 5, "imul" },
783 { 0xF6, 4, "mul" },
784 { 0xF6, 3, "neg" },
785 { 0xF6, 2, "not_" },
786 };
788 const Tbl *
p = &
tbl[i];
789 const std::string
name =
p->name;
790 printf(
"void %s(const Operand& op) { opR_ModM(op, 0, %d, 0x%02X); }\n",
p->name,
p->ext,
p->code);
791 }
792 }
793 {
794 const struct Tbl {
798 { "rcl", 2 },
799 { "rcr", 3 },
800 { "rol", 0 },
801 { "ror", 1 },
802 { "sar", 7 },
803 { "shl", 4 },
804 { "shr", 5 },
805
806 { "sal", 4 },
807 };
809 const Tbl *
p = &
tbl[i];
810 printf(
"void %s(const Operand& op, int imm) { opShift(op, imm, %d); }\n",
p->name,
p->ext);
811 printf(
"void %s(const Operand& op, const Reg8& _cl) { opShift(op, _cl, %d); }\n",
p->name,
p->ext);
812 }
813 }
814 {
815 const struct Tbl {
819 { "shld", 0xA4 },
820 { "shrd", 0xAC },
821 };
823 const Tbl *
p = &
tbl[i];
824 printf(
"void %s(const Operand& op, const Reg& reg, uint8 imm) { opShxd(op, reg, imm, 0x%02X); }\n",
p->name,
p->code);
825 printf(
"void %s(const Operand& op, const Reg& reg, const Reg8& _cl) { opShxd(op, reg, 0, 0x%02X, &_cl); }\n",
p->name,
p->code);
826 }
827 }
828 {
829 const struct Tbl {
833 { "bsf", 0xBC },
834 { "bsr", 0xBD },
835 };
837 const Tbl *
p = &
tbl[i];
838 printf(
"void %s(const Reg®, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x%02X); }\n",
p->name,
p->code);
839 }
840 }
841 {
842 const struct Tbl {
846 { "popcnt", 0xB8 },
847 { "tzcnt", 0xBC },
848 { "lzcnt", 0xBD },
849 };
851 const Tbl *
p = &
tbl[i];
852 printf(
"void %s(const Reg®, const Operand& op) { opSp1(reg, op, 0xF3, 0x0F, 0x%02X); }\n",
p->name,
p->code);
853 }
854 }
855
856 {
857 const struct Tbl {
861 { 0x00, "pshufb" },
862 { 0x01, "phaddw" },
863 { 0x02, "phaddd" },
864 { 0x03, "phaddsw" },
865 { 0x04, "pmaddubsw" },
866 { 0x05, "phsubw" },
867 { 0x06, "phsubd" },
868 { 0x07, "phsubsw" },
869 { 0x08, "psignb" },
870 { 0x09, "psignw" },
871 { 0x0a, "psignd" },
872 { 0x0b, "pmulhrsw" },
873 { 0x1c, "pabsb" },
874 { 0x1d, "pabsw" },
875 { 0x1e, "pabsd" },
876 };
878 const Tbl *
p = &
tbl[i];
879 printf(
"void %s(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x%02X, 0x66, NONE, 0x38); }\n",
p->name,
p->code);
880 }
881 printf(
"void palignr(const Mmx& mmx, const Operand& op, int imm) { opMMX(mmx, op, 0x0f, 0x66, static_cast<uint8>(imm), 0x3a); }\n");
882 }
883 {
884 const struct Tbl {
888 { "pclmullqlqdq", 0 },
889 { "pclmulhqlqdq", 1 },
890 { "pclmullqhdq", 0x10 },
891 { "pclmulhqhdq", 0x11 },
892 };
894 const Tbl *
p = &
tbl[i];
895 printf(
"void %s(const Xmm& xmm, const Operand& op) { pclmulqdq(xmm, op, 0x%02X); }\n",
p->name,
p->code);
896 }
897 }
898 {
899 const struct Tbl {
901 int code2;
905 { 0x0F, 0xAE, 2, "ldmxcsr" },
906 { 0x0F, 0xAE, 3, "stmxcsr" },
907 { 0x0F, 0xAE, 7, "clflush" },
908 { 0xD9,
NONE, 5,
"fldcw" },
909
910 };
912 const Tbl *
p = &
tbl[i];
913 printf(
"void %s(const Address& addr) { opModM(addr, Reg32(%d), 0x%02X, 0x%02X); }\n",
p->name,
p->ext,
p->code1,
p->code2);
914 }
915 printf(
"void fstcw(const Address& addr) { db(0x9B); opModM(addr, Reg32(7), 0xD9, NONE); }\n");
916 }
917 {
918 const struct Tbl {
922 { 0x2B, "movntpd" },
923 { 0xE7, "movntdq" },
924 };
926 const Tbl *
p = &
tbl[i];
927
928 printf(
"void %s(const Address& addr, const Xmm& reg) { opModM(addr, Reg16(reg.getIdx()), 0x0F, 0x%02X); }\n",
p->name,
p->code);
929 }
930 }
931 {
932 const struct Tbl {
936 { 0xBE, "movsx" },
937 { 0xB6, "movzx" },
938 };
940 const Tbl *
p = &
tbl[i];
941 printf(
"void %s(const Reg& reg, const Operand& op) { opMovxx(reg, op, 0x%02X); }\n",
p->name,
p->code);
942 }
943 }
944
945 {
946 puts("void bndcl(const BoundsReg& bnd, const Operand& op) { db(0xF3); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); }");
947 puts("void bndcu(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); }");
948 puts("void bndcn(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1B, NONE, !op.isMEM()); }");
949 puts("void bndldx(const BoundsReg& bnd, const Address& addr) { opMIB(addr, bnd, 0x0F, 0x1A); }");
950 puts("void bndmk(const BoundsReg& bnd, const Address& addr) { db(0xF3); opModM(addr, bnd, 0x0F, 0x1B); }");
951 puts("void bndmov(const BoundsReg& bnd, const Operand& op) { db(0x66); opModRM(bnd, op, op.isBNDREG(), op.isMEM(), 0x0F, 0x1A); }");
952 puts("void bndmov(const Address& addr, const BoundsReg& bnd) { db(0x66); opModM(addr, bnd, 0x0F, 0x1B); }");
953 puts("void bndstx(const Address& addr, const BoundsReg& bnd) { opMIB(addr, bnd, 0x0F, 0x1B); }");
954 }
955
956 {
957 puts("void lea(const Reg& reg, const Address& addr) { if (!reg.isBit(16 | i32e)) throw Error(ERR_BAD_SIZE_OF_REGISTER); opModM(addr, reg, 0x8D); }");
958 puts("void bswap(const Reg32e& reg) { opModR(Reg32(1), reg, 0x0F); }");
959 puts("void ret(int imm = 0) { if (imm) { db(0xC2); dw(imm); } else { db(0xC3); } }");
960
961 puts("void xadd(const Operand& op, const Reg& reg) { opModRM(reg, op, (op.isREG() && reg.isREG() && op.getBit() == reg.getBit()), op.isMEM(), 0x0F, 0xC0 | (reg.isBit(8) ? 0 : 1)); }");
962 puts("void cmpxchg(const Operand& op, const Reg& reg) { opModRM(reg, op, (op.isREG() && reg.isREG() && op.getBit() == reg.getBit()), op.isMEM(), 0x0F, 0xB0 | (reg.isBit(8) ? 0 : 1)); }");
963 puts("void movbe(const Reg& reg, const Address& addr) { opModM(addr, reg, 0x0F, 0x38, 0xF0); }");
964 puts("void movbe(const Address& addr, const Reg& reg) { opModM(addr, reg, 0x0F, 0x38, 0xF1); }");
965 puts("void adcx(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0x66, isREG32_REG32orMEM, NONE, 0x38); }");
966 puts("void adox(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0xF3, isREG32_REG32orMEM, NONE, 0x38); }");
967 puts("void cmpxchg8b(const Address& addr) { opModM(addr, Reg32(1), 0x0F, 0xC7); }");
968
969 puts("void pextrw(const Operand& op, const Mmx& xmm, uint8 imm) { opExt(op, xmm, 0x15, imm, true); }");
970 puts("void pextrb(const Operand& op, const Xmm& xmm, uint8 imm) { opExt(op, xmm, 0x14, imm); }");
971 puts("void pextrd(const Operand& op, const Xmm& xmm, uint8 imm) { opExt(op, xmm, 0x16, imm); }");
972 puts("void extractps(const Operand& op, const Xmm& xmm, uint8 imm) { opExt(op, xmm, 0x17, imm); }");
973 puts("void pinsrw(const Mmx& mmx, const Operand& op, int imm) { if (!op.isREG(32) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opGen(mmx, op, 0xC4, mmx.isXMM() ? 0x66 : NONE, 0, imm); }");
974 puts("void insertps(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x21, 0x66, isXMM_XMMorMEM, imm, 0x3A); }");
975 puts("void pinsrb(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x20, 0x66, isXMM_REG32orMEM, imm, 0x3A); }");
976 puts("void pinsrd(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x22, 0x66, isXMM_REG32orMEM, imm, 0x3A); }");
977
978 puts("void pmovmskb(const Reg32e& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(reg, mmx, 0x0F, 0xD7); }");
979 puts("void maskmovq(const Mmx& reg1, const Mmx& reg2) { if (!reg1.isMMX() || !reg2.isMMX()) throw Error(ERR_BAD_COMBINATION); opModR(reg1, reg2, 0x0F, 0xF7); }");
980 puts("void movmskps(const Reg32e& reg, const Xmm& xmm) { opModR(reg, xmm, 0x0F, 0x50); }");
981 puts("void movmskpd(const Reg32e& reg, const Xmm& xmm) { db(0x66); movmskps(reg, xmm); }");
982 puts("void movntps(const Address& addr, const Xmm& xmm) { opModM(addr, Mmx(xmm.getIdx()), 0x0F, 0x2B); }");
983 puts("void movntdqa(const Xmm& xmm, const Address& addr) { db(0x66); opModM(addr, xmm, 0x0F, 0x38, 0x2A); }");
984 puts("void lddqu(const Xmm& xmm, const Address& addr) { db(0xF2); opModM(addr, xmm, 0x0F, 0xF0); }");
985 puts("void movnti(const Address& addr, const Reg32e& reg) { opModM(addr, reg, 0x0F, 0xC3); }");
986 puts("void movntq(const Address& addr, const Mmx& mmx) { if (!mmx.isMMX()) throw Error(ERR_BAD_COMBINATION); opModM(addr, mmx, 0x0F, 0xE7); }");
987
988 puts("void movd(const Address& addr, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, 0x7E); }");
989 puts("void movd(const Reg32& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x7E); }");
990 puts("void movd(const Mmx& mmx, const Address& addr) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, 0x6E); }");
991 puts("void movd(const Mmx& mmx, const Reg32& reg) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x6E); }");
992 puts("void movq2dq(const Xmm& xmm, const Mmx& mmx) { db(0xF3); opModR(xmm, mmx, 0x0F, 0xD6); }");
993 puts("void movdq2q(const Mmx& mmx, const Xmm& xmm) { db(0xF2); opModR(mmx, xmm, 0x0F, 0xD6); }");
994 puts("void movq(const Mmx& mmx, const Operand& op) { if (mmx.isXMM()) db(0xF3); opModRM(mmx, op, (mmx.getKind() == op.getKind()), op.isMEM(), 0x0F, mmx.isXMM() ? 0x7E : 0x6F); }");
995 puts("void movq(const Address& addr, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, mmx.isXMM() ? 0xD6 : 0x7F); }");
996 puts("void rdrand(const Reg& r) { if (r.isBit(8)) throw Error(ERR_BAD_SIZE_OF_REGISTER); opModR(Reg(6, Operand::REG, r.getBit()), r, 0x0F, 0xC7); }");
997 puts("void rdseed(const Reg& r) { if (r.isBit(8)) throw Error(ERR_BAD_SIZE_OF_REGISTER); opModR(Reg(7, Operand::REG, r.getBit()), r, 0x0F, 0xC7); }");
998 puts("void crc32(const Reg32e& reg, const Operand& op) { if (reg.isBit(32) && op.isBit(16)) db(0x66); db(0xF2); opModRM(reg, op, op.isREG(), op.isMEM(), 0x0F, 0x38, 0xF0 | (op.isBit(8) ? 0 : 1)); }");
999 }
1000 {
1001 const struct Tbl {
1009 { 0x00, 0xD8, 0xDC, 0, "fadd" },
1010 { 0xDE, 0xDA, 0x00, 0, "fiadd" },
1011 { 0x00, 0xD8, 0xDC, 2, "fcom" },
1012 { 0x00, 0xD8, 0xDC, 3, "fcomp" },
1013 { 0x00, 0xD8, 0xDC, 6, "fdiv" },
1014 { 0xDE, 0xDA, 0x00, 6, "fidiv" },
1015 { 0x00, 0xD8, 0xDC, 7, "fdivr" },
1016 { 0xDE, 0xDA, 0x00, 7, "fidivr" },
1017 { 0xDE, 0xDA, 0x00, 2, "ficom" },
1018 { 0xDE, 0xDA, 0x00, 3, "ficomp" },
1019 { 0xDF, 0xDB, 0xDF, 0, "fild", 5 },
1020 { 0xDF, 0xDB, 0x00, 2, "fist" },
1021 { 0xDF, 0xDB, 0xDF, 3, "fistp", 7 },
1022 { 0xDF, 0xDB, 0xDD, 1, "fisttp" },
1023 { 0x00, 0xD9, 0xDD, 0, "fld" },
1024 { 0x00, 0xD8, 0xDC, 1, "fmul" },
1025 { 0xDE, 0xDA, 0x00, 1, "fimul" },
1026 { 0x00, 0xD9, 0xDD, 2, "fst" },
1027 { 0x00, 0xD9, 0xDD, 3, "fstp" },
1028 { 0x00, 0xD8, 0xDC, 4, "fsub" },
1029 { 0xDE, 0xDA, 0x00, 4, "fisub" },
1030 { 0x00, 0xD8, 0xDC, 5, "fsubr" },
1031 { 0xDE, 0xDA, 0x00, 5, "fisubr" },
1032 };
1034 const Tbl *
p = &
tbl[i];
1035 printf(
"void %s(const Address& addr) { opFpuMem(addr, 0x%02X, 0x%02X, 0x%02X, %d, %d); }\n",
p->name,
p->m16,
p->m32,
p->m64,
p->ext,
p->m64ext);
1036 }
1037 }
1038 {
1039 const struct Tbl {
1044 { 0xD8C0, 0xDCC0, "fadd" },
1045 { 0x0000, 0xDEC0, "faddp" },
1046
1047 { 0xDAC0, 0x00C0, "fcmovb" },
1048 { 0xDAC8, 0x00C8, "fcmove" },
1049 { 0xDAD0, 0x00D0, "fcmovbe" },
1050 { 0xDAD8, 0x00D8, "fcmovu" },
1051 { 0xDBC0, 0x00C0, "fcmovnb" },
1052 { 0xDBC8, 0x00C8, "fcmovne" },
1053 { 0xDBD0, 0x00D0, "fcmovnbe" },
1054 { 0xDBD8, 0x00D8, "fcmovnu" },
1055
1056 { 0xDBF0, 0x00F0, "fcomi" },
1057 { 0xDFF0, 0x00F0, "fcomip" },
1058 { 0xDBE8, 0x00E8, "fucomi" },
1059 { 0xDFE8, 0x00E8, "fucomip" },
1060
1061 { 0xD8F0, 0xDCF8, "fdiv" },
1062 { 0x0000, 0xDEF8, "fdivp" },
1063 { 0xD8F8, 0xDCF0, "fdivr" },
1064 { 0x0000, 0xDEF0, "fdivrp" },
1065 { 0xD8C8, 0xDCC8, "fmul" },
1066 { 0x0000, 0xDEC8, "fmulp" },
1067 { 0xD8E0, 0xDCE8, "fsub" },
1068 { 0x0000, 0xDEE8, "fsubp" },
1069 { 0xD8E8, 0xDCE0, "fsubr" },
1070 { 0x0000, 0xDEE0, "fsubrp" },
1071 };
1073 const Tbl *
p = &
tbl[i];
1074 printf(
"void %s(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x%04X, 0x%04X); }\n",
p->name,
p->code1,
p->code2);
1075
1077 printf(
"void %s(const Fpu& reg1) { opFpuFpu(st0, reg1, 0x%04X, 0x%04X); }\n",
p->name,
p->code1,
p->code2);
1078 } else {
1079 printf(
"void %s(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x%04X, 0x%04X); }\n",
p->name,
p->code1,
p->code2);
1080 }
1081 }
1082 }
1083 {
1084 const struct Tbl {
1089 { 0xD8, 0xD0, "fcom" },
1090 { 0xD8, 0xD8, "fcomp" },
1091 { 0xDD, 0xC0, "ffree" },
1092 { 0xD9, 0xC0, "fld" },
1093 { 0xDD, 0xD0, "fst" },
1094 { 0xDD, 0xD8, "fstp" },
1095 { 0xDD, 0xE0, "fucom" },
1096 { 0xDD, 0xE8, "fucomp" },
1097 { 0xD9, 0xC8, "fxch" },
1098 };
1100 const Tbl *
p = &
tbl[i];
1101 printf(
"void %s(const Fpu& reg) { opFpu(reg, 0x%02X, 0x%02X); }\n",
p->name,
p->code1,
p->code2);
1102 }
1103 }
1104
1105 {
1106 const struct Tbl {
1109 bool only_pd_ps;
1111 { 0x58, "add", false },
1112 { 0x5C, "sub", false },
1113 { 0x59, "mul", false },
1114 { 0x5E, "div", false },
1115 { 0x5F, "max", false },
1116 { 0x5D, "min", false },
1117 { 0x54, "and", true },
1118 { 0x55, "andn", true },
1119 { 0x56, "or", true },
1120 { 0x57, "xor", true },
1121 };
1123 const Tbl *
p = &
tbl[i];
1124 printf(
"void v%spd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x%02X); }\n",
p->name,
p->code);
1125 printf(
"void v%sps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x%02X); }\n",
p->name,
p->code);
1126 if (
p->only_pd_ps)
continue;
1127 printf(
"void v%ssd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_Z | T_N8, 0x%02X); }\n",
p->name,
p->code);
1128 printf(
"void v%sss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_Z | T_N4, 0x%02X); }\n",
p->name,
p->code);
1129 }
1130 }
1132
1133
1134 {
1135 const struct Tbl {
1139 bool hasIMM;
1140 int mode;
1142 { 0x15,
"blendvpd",
T_0F38 |
T_66,
false, 1 },
1143 { 0x14,
"blendvps",
T_0F38 |
T_66,
false, 1 },
1144 { 0x10,
"pblendvb",
T_0F38 |
T_66,
false, 1 },
1145 { 0xDF,
"aeskeygenassist",
T_0F3A |
T_66,
true, 3 },
1151 { 0x61,
"pcmpestri",
T_0F3A |
T_66,
true, 3 },
1152 { 0x60,
"pcmpestrm",
T_0F3A |
T_66,
true, 3 },
1153 { 0x63,
"pcmpistri",
T_0F3A |
T_66,
true, 3 },
1154 { 0x62,
"pcmpistrm",
T_0F3A |
T_66,
true, 3 },
1171
1175 { 0x41,
"phminposuw",
T_0F38 |
T_66,
false, 3 },
1176
1183
1190
1194
1196 { 0x53,
"rcpps",
T_0F |
T_YMM,
false, 2 },
1197 { 0x52,
"rsqrtps",
T_0F |
T_YMM,
false, 2 },
1198
1201
1204
1205 { 0xCC,
"sha1rnds4",
T_0F3A,
true, 1 },
1206 { 0xC8,
"sha1nexte",
T_0F38,
false, 1 },
1207 { 0xC9,
"sha1msg1",
T_0F38,
false, 1 },
1208 { 0xCA,
"sha1msg2",
T_0F38,
false, 1 },
1209 { 0xCB,
"sha256rnds2",
T_0F38,
false, 1 },
1210 { 0xCC,
"sha256msg1",
T_0F38,
false, 1 },
1211 { 0xCD,
"sha256msg2",
T_0F38,
false, 1 },
1212 };
1214 const Tbl *
p = &
tbl[i];
1217 const char *immS1 =
p->hasIMM ?
", uint8 imm" :
"";
1218 const char *immS2 =
p->hasIMM ?
", imm" :
", NONE";
1219 const char *pref =
p->type &
T_66 ?
"0x66" :
p->type &
T_F2 ?
"0xF2" :
p->type &
T_F3 ?
"0xF3" :
"NONE";
1220 const char *suf =
p->type &
T_0F38 ?
"0x38" :
p->type &
T_0F3A ?
"0x3A" :
"NONE";
1221 printf(
"void %s(const Xmm& xmm, const Operand& op%s) { opGen(xmm, op, 0x%02X, %s, isXMM_XMMorMEM%s, %s); }\n",
p->name, immS1,
p->code, pref, immS2, suf);
1222 }
1224 printf(
"void v%s(const Xmm& xm, const Operand& op%s) { opAVX_X_XM_IMM(xm, op, %s, 0x%02X%s); }\n"
1225 ,
p->name,
p->hasIMM ?
", uint8 imm" :
"", type.c_str(),
p->code,
p->hasIMM ?
", imm" :
"");
1226 }
1227 }
1228 }
1229
1230 {
1231 const struct Tbl {
1242 };
1244 const Tbl *
p = &
tbl[i];
1246 printf(
"void v%s(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, %s, 0x%02X); }\n"
1247 ,
p->name, type.c_str(),
p->code);
1248 }
1249 }
1250
1251 {
1252 const struct Tbl {
1256 int mode;
1264
1269 };
1271 const Tbl *
p = &
tbl[i];
1275 printf(
"void %s(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x%02X, 0x%02X, isXMM_XMMorMEM%s); }\n",
p->name,
p->code, pref,
p->type &
T_0F38 ?
", NONE, 0x38" :
"");
1276 }
1278 printf(
"void v%s(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, %s, 0x%02X); }\n"
1279 ,
p->name, type.c_str(),
p->code);
1280 }
1281 }
1282 }
1283
1284 {
1285 const char suf[][8] = { "ps", "pd" };
1286 for (int i = 0; i < 2; i++) {
1287 printf(
"void vmaskmov%s(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x%02X); }\n", suf[i], 0x2C + i);
1288 printf(
"void vmaskmov%s(const Address& addr, const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x2, x1, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x%02X); }\n", suf[i], 0x2E + i);
1289 }
1290 }
1291
1292 {
1293 const char suf[][8] = { "d", "q" };
1294 for (int i = 0; i < 2; i++) {
1295 printf(
"void vpmaskmov%s(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_66 | T_W%d | T_YMM, 0x%02X); }\n", suf[i], i, 0x8C);
1296 printf(
"void vpmaskmov%s(const Address& addr, const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x2, x1, addr, T_0F38 | T_66 | T_W%d | T_YMM, 0x%02X); }\n", suf[i], i, 0x8E);
1297 }
1298 }
1299
1300 {
1301 const struct Tbl {
1310 };
1312 const Tbl&
p =
tbl[i];
1314 printf(
"void %s(const Ymm& y1, const Ymm& y2, const Operand& op) { opAVX_X_X_XM(y1, y2, op, %s, 0x%02X); }\n",
p.name, type.c_str(),
p.code);
1315 }
1316 }
1317
1318 {
1319 const struct Tbl {
1326 };
1328 const Tbl&
p =
tbl[i];
1330 printf(
"void %s(const Ymm& y, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(y, op, %s, 0x%02X, imm); }\n",
p.name, type.c_str(),
p.code);
1331 }
1332 }
1333
1334 {
1335 const char pred[32][16] = {
1336 "eq", "lt", "le", "unord", "neq", "nlt", "nle", "ord",
1337 "eq_uq", "nge", "ngt", "false", "neq_oq", "ge", "gt",
1338 "true", "eq_os", "lt_oq", "le_oq", "unord_s", "neq_us", "nlt_uq", "nle_uq", "ord_s",
1339 "eq_us", "nge_uq", "ngt_uq", "false_os", "neq_os", "ge_oq", "gt_oq", "true_us"
1340 };
1341 const char suf[][4] = { "pd", "ps", "sd", "ss" };
1342 for (int i = 0; i < 4; i++) {
1343 const char *
s = suf[i];
1344 for (
int j = 0;
j < 32;
j++) {
1346 printf(
"void cmp%s%s(const Xmm& x, const Operand& op) { cmp%s(x, op, %d); }\n", pred[
j],
s,
s,
j);
1347 }
1348 printf(
"void vcmp%s%s(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmp%s(x1, x2, op, %d); }\n", pred[
j],
s,
s,
j);
1349 }
1350 }
1351 }
1352
1353 {
1354 const struct Tbl {
1355 bool isH;
1356 bool isPd;
1359 { true, true, 0x16 },
1360 { true, false, 0x16 },
1361 { false, true, 0x12 },
1362 { false, false, 0x12 },
1363 };
1365 const Tbl&
p =
tbl[i];
1366 char c =
p.isH ?
'h' :
'l';
1367 const char *suf =
p.isPd ?
"pd" :
"ps";
1368 const char *type =
p.isPd ?
"T_0F | T_66 | T_EVEX | T_EW1 | T_N8" :
"T_0F | T_EVEX | T_EW0 | T_N8";
1369 printf(
"void vmov%c%s(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, op1, op2, %s, 0x%02X); }\n"
1370 , c, suf, type,
p.code);
1371 printf(
"void vmov%c%s(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, %s, 0x%02X); }\n"
1372 , c, suf, type,
p.code + 1);
1373 }
1374 }
1375
1376 {
1377 const struct Tbl {
1380 bool supportYMM;
1382 { 0x08, "vfmadd", true },
1383 { 0x09, "vfmadd", false },
1384 { 0x06, "vfmaddsub", true },
1385 { 0x07, "vfmsubadd", true },
1386 { 0x0A, "vfmsub", true },
1387 { 0x0B, "vfmsub", false },
1388 { 0x0C, "vfnmadd", true },
1389 { 0x0D, "vfnmadd", false },
1390 { 0x0E, "vfnmsub", true },
1391 { 0x0F, "vfnmsub", false },
1392 };
1394 for (
int j = 0;
j < 2;
j++) {
1395 const char sufTbl[][2][8] = {
1396 { "pd", "ps" },
1397 { "sd", "ss" },
1398 };
1399 for (int k = 0; k < 3; k++) {
1400 const struct Ord {
1403 } ord[] = {
1404 { "132", 0x90 },
1405 { "213", 0xA0 },
1406 { "231", 0xB0 },
1407 };
1411 const std::string suf = sufTbl[
tbl[i].supportYMM ? 0 : 1][
j];
1412 if (suf == "pd") {
1414 } else if (suf == "ps") {
1416 } else if (suf == "sd") {
1418 } else {
1420 }
1422 printf(
"void %s%s%s(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, %s, 0x%02X); }\n"
1423 ,
tbl[i].
name, ord[k].str, suf.c_str(), type.c_str(),
tbl[i].code + ord[k].code);
1424 }
1425 }
1426 }
1427 }
1428
1429 {
1430 printf(
"void vbroadcastf128(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x1A); }\n");
1431 printf(
"void vbroadcasti128(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x5A); }\n");
1432 printf(
"void vbroadcastsd(const Ymm& y, const Operand& op) { if (!op.isMEM() && !(y.isYMM() && op.isXMM()) && !(y.isZMM() && op.isXMM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(y, op, T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW1 | T_N8, 0x19); }\n");
1433 const struct Tbl {
1437 bool ew1;
1444 };
1446 const Tbl&
p =
tbl[i];
1448 printf(
"void %s(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(x, op, %s, 0x%02X); }\n",
p.name, type.c_str(),
p.code);
1449 }
1450
1451 puts("void vextractf128(const Operand& op, const Ymm& y, uint8 imm) { if (!(op.isXMEM() && y.isYMM())) throw Error(ERR_BAD_COMBINATION); opVex(y, 0, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x19, imm); }");
1452 puts("void vextracti128(const Operand& op, const Ymm& y, uint8 imm) { if (!(op.isXMEM() && y.isYMM())) throw Error(ERR_BAD_COMBINATION); opVex(y, 0, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x39, imm); }");
1453 puts("void vextractps(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(32) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_N4, 0x17, imm); }");
1454 puts("void vinsertf128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { if (!(y1.isYMM() && y2.isYMM() && op.isXMEM())) throw Error(ERR_BAD_COMBINATION); opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x18, imm); }");
1455 puts("void vinserti128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { if (!(y1.isYMM() && y2.isYMM() && op.isXMEM())) throw Error(ERR_BAD_COMBINATION); opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x38, imm); }");
1456 puts("void vperm2f128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { if (!(y1.isYMM() && y2.isYMM() && op.isYMEM())) throw Error(ERR_BAD_COMBINATION); opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x06, imm); }");
1457 puts("void vperm2i128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { if (!(y1.isYMM() && y2.isYMM() && op.isYMEM())) throw Error(ERR_BAD_COMBINATION); opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x46, imm); }");
1458
1459 puts("void vlddqu(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, cvtIdx0(x), addr, T_0F | T_F2 | T_W0 | T_YMM, 0xF0); }");
1460 puts("void vldmxcsr(const Address& addr) { opAVX_X_X_XM(xm2, xm0, addr, T_0F, 0xAE); }");
1461 puts("void vstmxcsr(const Address& addr) { opAVX_X_X_XM(xm3, xm0, addr, T_0F, 0xAE); }");
1462 puts("void vmaskmovdqu(const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x1, xm0, x2, T_0F | T_66, 0xF7); }");
1463
1464 puts("void vpextrb(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(8|16|i32e) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); opVex(x, 0, op, T_0F3A | T_66 | T_EVEX | T_N1, 0x14, imm); }");
1465 puts("void vpextrw(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(16|i32e) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); if (op.isREG() && x.getIdx() < 16) { opAVX_X_X_XM(Xmm(op.getIdx()), xm0, x, T_0F | T_66, 0xC5, imm); } else { opVex(x, 0, op, T_0F3A | T_66 | T_EVEX | T_N2, 0x15, imm); } }");
1466 puts("void vpextrd(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(32) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N4, 0x16, imm); }");
1467 puts("void vpextrq(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(64) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); opVex(x, 0, op, T_0F3A | T_66 | T_W1 | T_EVEX | T_EW1 | T_N8, 0x16, imm); }");
1468
1469 puts("void vpinsrb(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); opVex(x1, &x2, op, T_0F3A | T_66 | T_EVEX | T_N1, 0x20, imm); }");
1470 puts("void vpinsrw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); opVex(x1, &x2, op, T_0F | T_66 | T_EVEX | T_N2, 0xC4, imm); }");
1471 puts("void vpinsrd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); opVex(x1, &x2, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N4, 0x22, imm); }");
1472 puts("void vpinsrq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(64) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); opVex(x1, &x2, op, T_0F3A | T_66 | T_W1 | T_EVEX | T_EW1 | T_N8, 0x22, imm); }");
1473
1474 puts("void vpmovmskb(const Reg32e& r, const Xmm& x) { if (!x.is(Operand::XMM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(x.isYMM() ? Ymm(r.getIdx()) : Xmm(r.getIdx()), 0, x, T_0F | T_66 | T_YMM, 0xD7); }");
1475
1476 }
1477
1478 {
1479 const struct Tbl {
1482 int idx;
1495 };
1497 const Tbl&
p =
tbl[i];
1499 printf(
"void v%s(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), %d), x, op, %s, 0x%02X, imm); }\n",
p.name,
p.idx, type.c_str(),
p.code);
1500 }
1501 }
1502
1503 {
1504 const struct Tbl {
1508 { "vblendvpd", 0x4B },
1509 { "vblendvps", 0x4A },
1510 { "vpblendvb", 0x4C },
1511 };
1513 const Tbl&
p =
tbl[i];
1514 printf(
"void %s(const Xmm& x1, const Xmm& x2, const Operand& op, const Xmm& x4) { opAVX_X_X_XM(x1, x2, op, T_0F3A | T_66 | T_YMM, 0x%02X, x4.getIdx() << 4); }\n",
p.name,
p.code);
1515 }
1516 }
1517
1518 {
1519 printf(
"void vmovd(const Xmm& x, const Operand& op) { if (!op.isREG(32) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, xm0, op, T_0F | T_66 | T_W0 | T_EVEX | T_N4, 0x6E); }\n");
1520 printf(
"void vmovd(const Operand& op, const Xmm& x) { if (!op.isREG(32) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, xm0, op, T_0F | T_66 | T_W0 | T_EVEX | T_N4, 0x7E); }\n");
1521
1522 printf(
"void vmovq(const Xmm& x, const Address& addr) { int type, code; if (x.getIdx() < 16) { type = T_0F | T_F3; code = 0x7E; } else { type = T_0F | T_66 | T_EVEX | T_EW1 | T_N8; code = 0x6E; } opAVX_X_X_XM(x, xm0, addr, type, code); }\n");
1523 printf(
"void vmovq(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, x.getIdx() < 16 ? 0xD6 : 0x7E); }\n");
1524 printf(
"void vmovq(const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x1, xm0, x2, T_0F | T_F3 | T_EVEX | T_EW1 | T_N8, 0x7E); }\n");
1525
1526 printf(
"void vmovhlps(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x1, x2, op, T_0F | T_EVEX | T_EW0, 0x12); }\n");
1527 printf(
"void vmovlhps(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x1, x2, op, T_0F | T_EVEX | T_EW0, 0x16); }\n");
1528
1529 printf(
"void vmovmskpd(const Reg& r, const Xmm& x) { if (!r.isBit(i32e)) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x.isXMM() ? Xmm(r.getIdx()) : Ymm(r.getIdx()), cvtIdx0(x), x, T_0F | T_66 | T_W0 | T_YMM, 0x50); }\n");
1530 printf(
"void vmovmskps(const Reg& r, const Xmm& x) { if (!r.isBit(i32e)) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x.isXMM() ? Xmm(r.getIdx()) : Ymm(r.getIdx()), cvtIdx0(x), x, T_0F | T_W0 | T_YMM, 0x50); }\n");
1531
1532 puts("void vmovntdq(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_66 | T_YMM | T_EVEX | T_EW0, 0xE7); }");
1533 puts("void vmovntpd(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_66 | T_YMM | T_EVEX | T_EW1, 0x2B); }");
1534 puts("void vmovntps(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_YMM | T_EVEX | T_EW0, 0x2B); }");
1535 puts("void vmovntdqa(const Xmm& x, const Address& addr) { opVex(x, 0, addr, T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0, 0x2A); }");
1536
1537
1538 for (int i = 0; i < 2; i++) {
1539 char c1 = i == 0 ? 'd' : 's';
1543 printf(
"void vmovs%c(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x1, x2, op, %s, 0x10); }\n", c1,
s.c_str());
1544 printf(
"void vmovs%c(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, xm0, addr, %s, 0x10); }\n", c1,
s.c_str());
1545 printf(
"void vmovs%c(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, %s | T_M_K, 0x11); }\n", c1,
s.c_str());
1546 }
1547 }
1548
1549 {
1550 puts("void vcvtss2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W0 | T_EVEX | T_EW0 | T_ER_X | T_N8, 0x2D); }");
1551 puts("void vcvttss2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W0 | T_EVEX | T_EW0 | T_SAE_X | T_N8, 0x2C); }");
1552 puts("void vcvtsd2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W0 | T_EVEX | T_EW0 | T_N4 | T_ER_X, 0x2D); }");
1553 puts("void vcvttsd2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W0 | T_EVEX | T_EW0 | T_N4 | T_SAE_X, 0x2C); }");
1554
1555 puts("void vcvtsi2ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt3(x1, x2, op, T_0F | T_F3 | T_EVEX | T_ER_X, T_W1 | T_EW1 | T_N8, T_W0 | T_EW0 | T_N4, 0x2A); }");
1556 puts("void vcvtsi2sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt3(x1, x2, op, T_0F | T_F2 | T_EVEX, T_W1 | T_EW1 | T_ER_X | T_N8, T_W0 | T_EW0 | T_N4, 0x2A); }");
1557
1558
1559 puts("void vcvtps2pd(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_0F | T_YMM | T_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL | T_SAE_Y, 0x5A); }");
1560 puts("void vcvtdq2pd(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_0F | T_F3 | T_YMM | T_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL, 0xE6); }");
1561
1562 puts("void vcvtpd2ps(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64 | T_ER_Z, 0x5A); }");
1563 puts("void vcvtpd2dq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_F2 | T_YMM | T_EVEX | T_EW1 | T_B64 | T_ER_Z, 0xE6); }");
1564
1565 puts("void vcvttpd2dq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_66 | T_0F | T_YMM | T_EVEX |T_EW1 | T_B64 | T_ER_Z, 0xE6); }");
1566
1567 puts("void vcvtph2ps(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_0F38 | T_66 | T_W0 | T_EVEX | T_EW0 | T_N8 | T_N_VL | T_SAE_Y, 0x13); }");
1568 puts("void vcvtps2ph(const Operand& op, const Xmm& x, uint8 imm) { checkCvt1(x, op); opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N8 | T_N_VL | T_SAE_Y, 0x1D, imm); }");
1569
1570 }
1571
1572 {
1573 const struct Tbl {
1578 {
"andn",
T_0F38, 0xF2 },
1582 };
1584 const Tbl&
p =
tbl[i];
1585 printf(
"void %s(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opGpr(r1, r2, op, %s, 0x%x, true); }\n",
p.name,
type2String(
p.type).c_str(),
p.code);
1586 }
1587 }
1588
1589 {
1590 const struct Tbl {
1595 {
"bextr",
T_0F38, 0xF7 },
1596 {
"bzhi",
T_0F38, 0xF5 },
1600 };
1602 const Tbl&
p =
tbl[i];
1603 printf(
"void %s(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, %s, 0x%x, false); }\n",
p.name,
type2String(
p.type).c_str(),
p.code);
1604 }
1605 puts("void rorx(const Reg32e& r, const Operand& op, uint8 imm) { opGpr(r, op, Reg32e(0, r.getBit()), T_0F3A | T_F2, 0xF0, false, imm); }");
1606 }
1607
1608 {
1609 const struct Tbl {
1615 {
"blsi",
T_0F38, 0xF3, 3 },
1616 {
"blsmsk",
T_0F38, 0xF3, 2 },
1617 {
"blsr",
T_0F38, 0xF3, 1 },
1618 };
1620 const Tbl&
p =
tbl[i];
1621 printf(
"void %s(const Reg32e& r, const Operand& op) { opGpr(Reg32e(%d, r.getBit()), op, r, %s, 0x%x, false); }\n",
p.name,
p.idx,
type2String(
p.type).c_str(),
p.code);
1622 }
1623 }
1624
1625 {
1626 const int y_vx_y = 0;
1627 const int y_vy_y = 1;
1628 const int x_vy_x = 2;
1629 const struct Tbl {
1632 int w;
1633 int mode;
1635 { "vgatherdpd", 0x92, 1, y_vx_y },
1636 { "vgatherqpd", 0x93, 1, y_vy_y },
1637 { "vgatherdps", 0x92, 0, y_vy_y },
1638 { "vgatherqps", 0x93, 0, x_vy_x },
1639 { "vpgatherdd", 0x90, 0, y_vy_y },
1640 { "vpgatherqd", 0x91, 0, x_vy_x },
1641 { "vpgatherdq", 0x90, 1, y_vx_y },
1642 { "vpgatherqq", 0x91, 1, y_vy_y },
1643 };
1645 const Tbl&
p =
tbl[i];
1646 printf(
"void %s(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_W%d, 0x%x, %d); }\n",
p.name,
p.w,
p.code,
p.mode);
1647 }
1648 }
1649}
std::string type2String(int type)
#define D(var, file, col, who, lev,...)
void putGeneric(const GenericTbl *p, size_t n)
void putX_X_XM(bool omitOnly)
LOGGING_API void printf(Category category, const char *format,...)