Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
gen_code.cpp File Reference
#include <stdio.h>
#include <string.h>
#include "xbyak/xbyak.h"
#include "avx_type.hpp"
Include dependency graph for gen_code.cpp:

Go to the source code of this file.

Classes

struct  GenericTbl
 

Macros

#define XBYAK_DONT_READ_LIST
 
#define NUM_OF_ARRAY(x)
 

Functions

void put_jREGz (const char *reg, bool prefix)
 
void putGeneric (const GenericTbl *p, size_t n)
 
void putX_X_XM (bool omitOnly)
 
void put ()
 
void put32 ()
 
void put64 ()
 
void putFixed ()
 
void putOmit ()
 
int main (int argc, char *argv[])
 

Macro Definition Documentation

◆ NUM_OF_ARRAY

#define NUM_OF_ARRAY ( x)
Value:
(sizeof(x) / sizeof(x[0]))

Definition at line 5 of file gen_code.cpp.

◆ XBYAK_DONT_READ_LIST

#define XBYAK_DONT_READ_LIST

Definition at line 1 of file gen_code.cpp.

Function Documentation

◆ main()

int main ( int argc,
char * argv[] )

Definition at line 1777 of file gen_code.cpp.

1778{
1779 std::string mode = argc == 2 ? argv[1] : "";
1780 if (mode == "") {
1781 put();
1782 } else if (mode == "fixed") {
1783 putFixed();
1784 } else {
1785 putOmit();
1786 }
1787}
void put()
Definition gen_code.cpp:234
void putFixed()
void putOmit()
char ** argv
Here is the call graph for this function:

◆ put()

void put ( )

Definition at line 234 of file gen_code.cpp.

235{
236 const int NO = CodeGenerator::NONE;
237 {
238 char buf[16];
239 unsigned int v = VERSION;
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 {
253 uint8 code;
254 const char *name;
255 } tbl[] = {
256 // MMX
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 // MMX2
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 };
294 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
295 const Tbl *p = &tbl[i];
296 printf("void %s(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x%02X); }\n"
297 , p->name, p->code);
298 }
299 }
300
301 {
302 const struct Tbl {
303 uint8 code;
304 int mode;
305 const char *name;
306 } tbl[] = {
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 };
319 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 // B(0), W(1), D(2), Q(3)
326 if (!(p->mode & (1 << j))) continue;
327 printf("void %s%s(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x%02X); }\n"
328 , p->name, modTbl[j]
329 , p->code | j
330 );
331 }
332 }
333 }
334
335 {
336 const struct Tbl {
337 uint8 code;
338 int ext;
339 int mode;
340 const char *name;
341 } tbl[] = {
342 { 0x70, 6, W|D|Q, "psll" },
343 { 0x70, 4, W|D , "psra" },
344 { 0x70, 2, W|D|Q, "psrl" },
345 };
346 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 // B(0), W(1), D(2), Q(3)
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"
355 , p->name, modTbl[j]
356 , p->code | j
357 , p->ext
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 {
367 uint8 code;
368 uint8 pref;
369 const char *name;
370 } tbl[] = {
371 { 0x70, 0, "pshufw" },
372 { 0x70, 0xF2, "pshuflw" },
373 { 0x70, 0xF3, "pshufhw" },
374 { 0x70, 0x66, "pshufd" },
375 };
376 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 {
383 uint8 code; // for (reg, reg/[mem])
384 uint8 code2; // for ([mem], reg)
385 int pref;
386 const char *name;
387 } mmxTbl6[] = {
388 { 0x6F, 0x7F, 0x66, "movdqa" },
389 { 0x6F, 0x7F, 0xF3, "movdqu" },
390 // SSE2
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 };
398 for (size_t i = 0; i < NUM_OF_ARRAY(mmxTbl6); i++) {
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;
415 const char *name;
416 } sufTbl[] = {
417 { NO, "ps" },
418 { 0xF3, "ss" },
419 { 0x66, "pd" },
420 { 0xF2, "sd" },
421 };
422 const struct Tbl {
423 uint8 code;
424 int mode;
425 const char *name;
426 bool hasImm;
427 } tbl[] = {
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 };
447 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
448 const Tbl *p = &tbl[i];
449 for (size_t j = 0; j < NUM_OF_ARRAY(sufTbl); j++) {
450 if (!(p->mode & (1 << j))) continue;
451 if (p->hasImm) {
452 // don't change uint8 to int because NO is not in byte
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 // (XMM, XMM)
462 const struct Tbl {
463 uint8 code;
464 uint8 pref;
465 const char *name;
466 } tbl[] = {
467 { 0xF7, 0x66, "maskmovdqu" },
468 { 0x12, 0 , "movhlps" },
469 { 0x16, 0 , "movlhps" },
470 };
471 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 // (XMM, XMM|MEM)
480 const struct Tbl {
481 uint8 code;
482 int pref;
483 const char *name;
484 } tbl[] = {
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 };
504 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 // special type
512 const struct Tbl {
513 uint8 code;
514 int pref;
515 const char *name;
516 const char *cond;
517 } tbl[] = {
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 };
531 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 // prefetch
538 const struct Tbl {
539 int ext;
540 const char *name;
541 int code;
542 } tbl[] = {
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 };
550 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 {
557 uint8 code;
558 int pref;
559 const char *name;
560 } tbl[] = {
561 { 0x16, NO, "movhps" },
562 { 0x12, NO, "movlps" },
563 { 0x16, 0x66, "movhpd" },
564 { 0x12, 0x66, "movlpd" },
565 };
566 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 // cmov
573 const struct Tbl {
574 uint8 ext;
575 const char *name;
576 } 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"; // disable warning of PVS-Studio
609 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 {
621 const GenericTbl tbl[] = {
622 { "bnd", 0xf2 }, /* 0xf2 prefix for MPX */
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 // FPU
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 {
723 uint8 code; // (reg, reg)
724 uint8 ext; // (reg, imm)
725 const char *name;
726 } 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 };
736 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 {
745 uint8 code;
746 uint8 ext;
747 const char *name;
748 } tbl[] = {
749 { 0x48, 1, "dec" },
750 { 0x40, 0, "inc" },
751 };
752 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 {
759 uint8 code;
760 uint8 ext;
761 const char *name;
762 } tbl[] = {
763 { 0xa3, 4, "bt" },
764 { 0xab, 5, "bts" },
765 { 0xb3, 6, "btr" },
766 { 0xbb, 7, "btc" },
767 };
768 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 {
776 uint8 code;
777 uint8 ext;
778 const char *name;
779 } 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 };
787 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 {
795 const char *name;
796 uint8 ext;
797 } 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 };
808 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 {
816 const char *name;
817 uint8 code;
818 } tbl[] = {
819 { "shld", 0xA4 },
820 { "shrd", 0xAC },
821 };
822 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 {
830 const char *name;
831 uint8 code;
832 } tbl[] = {
833 { "bsf", 0xBC },
834 { "bsr", 0xBD },
835 };
836 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
837 const Tbl *p = &tbl[i];
838 printf("void %s(const Reg&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 {
843 const char *name;
844 uint8 code;
845 } tbl[] = {
846 { "popcnt", 0xB8 },
847 { "tzcnt", 0xBC },
848 { "lzcnt", 0xBD },
849 };
850 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
851 const Tbl *p = &tbl[i];
852 printf("void %s(const Reg&reg, const Operand& op) { opSp1(reg, op, 0xF3, 0x0F, 0x%02X); }\n", p->name, p->code);
853 }
854 }
855 // SSSE3
856 {
857 const struct Tbl {
858 uint8 code;
859 const char *name;
860 } 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 };
877 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 {
885 const char *name;
886 uint8 code;
887 } tbl[] = {
888 { "pclmullqlqdq", 0 },
889 { "pclmulhqlqdq", 1 },
890 { "pclmullqhdq", 0x10 },
891 { "pclmulhqhdq", 0x11 },
892 };
893 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 {
900 uint8 code1;
901 int code2;
902 uint8 ext;
903 const char *name;
904 } tbl[] = {
905 { 0x0F, 0xAE, 2, "ldmxcsr" },
906 { 0x0F, 0xAE, 3, "stmxcsr" },
907 { 0x0F, 0xAE, 7, "clflush" }, // 0x80 is bug of nasm ?
908 { 0xD9, NONE, 5, "fldcw" },
909// { 0x9B, 0xD9, 7, "fstcw" }, // not correct order for fstcw [eax] on 64bit OS
910 };
911 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 {
919 uint8 code;
920 const char *name;
921 } tbl[] = {
922 { 0x2B, "movntpd" },
923 { 0xE7, "movntdq" },
924 };
925 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
926 const Tbl *p = &tbl[i];
927 // cast xmm register to 16bit register to put 0x66
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 {
933 uint8 code;
934 const char *name;
935 } tbl[] = {
936 { 0xBE, "movsx" },
937 { 0xB6, "movzx" },
938 };
939 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 // mpx
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 // misc
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 {
1002 uint8 m16;
1003 uint8 m32;
1004 uint8 m64;
1005 uint8 ext;
1006 const char *name;
1007 uint8 m64ext;
1008 } 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 };
1033 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 {
1040 uint32 code1;
1041 uint32 code2;
1042 const char *name;
1043 } 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 };
1072 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 // omit st0 version(like nasm)
1076 if (p->code1) {
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 {
1085 uint8 code1;
1086 uint8 code2;
1087 const char *name;
1088 } 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 };
1099 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 // AVX
1105 { // pd, ps, sd, ss
1106 const struct Tbl {
1107 uint8 code;
1108 const char *name;
1109 bool only_pd_ps;
1110 } tbl[] = {
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 };
1122 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 }
1131 putX_X_XM(false);
1132
1133 // (x, x/m[, imm]) or (y, y/m[, imm])
1134 {
1135 const struct Tbl {
1136 uint8 code;
1137 const char *name;
1138 int type;
1139 bool hasIMM;
1140 int mode; // 1 : SSE, 2 : AVX, 3 : SSE + AVX
1141 } tbl[] = {
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 },
1146 { 0xDB, "aesimc", T_0F38 | T_66 | T_W0, false, 3 },
1147 { 0x09, "roundpd", T_0F3A | T_66 | T_YMM, true, 3 },
1148 { 0x08, "roundps", T_0F3A | T_66 | T_YMM, true, 3 },
1149 { 0x05, "permilpd", T_0F3A | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, true, 2 },
1150 { 0x04, "permilps", T_0F3A | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, true, 2 },
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 },
1155 { 0x0E, "testps", T_0F38 | T_66 | T_YMM, false, 2 },
1156 { 0x0F, "testpd", T_0F38 | T_66 | T_YMM, false, 2 },
1157 { 0x2F, "comisd", T_0F | T_66 | T_EVEX | T_EW1 | T_SAE_X | T_N8, false, 2 },
1158 { 0x2F, "comiss", T_0F | T_EVEX | T_EW0 | T_SAE_X | T_N4, false, 2 },
1159 { 0x5B, "cvtdq2ps", T_0F | T_YMM | T_EVEX | T_EW0 | T_B32 | T_ER_Z, false, 2 },
1160 { 0x5B, "cvtps2dq", T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32 | T_ER_Z, false, 2 },
1161 { 0x5B, "cvttps2dq", T_0F | T_F3 | T_YMM | T_EVEX | T_EW0 | T_B32 | T_SAE_Z, false, 2 },
1162 { 0x28, "movapd", T_0F | T_66 | T_YMM | T_EVEX | T_EW1, false, 2 },
1163 { 0x28, "movaps", T_0F | T_YMM | T_EVEX | T_EW0, false, 2 },
1164 { 0x12, "movddup", T_0F | T_F2 | T_YMM | T_EVEX | T_EW1 | T_ER_X | T_ER_Y | T_ER_Z | T_DUP, false, 3 },
1165 { 0x6F, "movdqa", T_0F | T_66 | T_YMM, false, 2 },
1166 { 0x6F, "movdqu", T_0F | T_F3 | T_YMM, false, 2 },
1167 { 0x16, "movshdup", T_0F | T_F3 | T_YMM | T_EVEX | T_EW0, false, 3 },
1168 { 0x12, "movsldup", T_0F | T_F3 | T_YMM | T_EVEX | T_EW0, false, 3 },
1169 { 0x10, "movupd", T_0F | T_66 | T_YMM | T_EVEX | T_EW1, false, 2 },
1170 { 0x10, "movups", T_0F | T_YMM | T_EVEX | T_EW0, false, 2 },
1171
1172 { 0x1C, "pabsb", T_0F38 | T_66 | T_YMM | T_EVEX, false, 2 },
1173 { 0x1D, "pabsw", T_0F38 | T_66 | T_YMM | T_EVEX, false, 2 },
1174 { 0x1E, "pabsd", T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, 2 },
1175 { 0x41, "phminposuw", T_0F38 | T_66, false, 3 },
1176
1177 { 0x20, "pmovsxbw", T_0F38 | T_66 | T_YMM | T_EVEX | T_N8 | T_N_VL, false, 3 },
1178 { 0x21, "pmovsxbd", T_0F38 | T_66 | T_YMM | T_EVEX | T_N4 | T_N_VL, false, 3 },
1179 { 0x22, "pmovsxbq", T_0F38 | T_66 | T_YMM | T_EVEX | T_N2 | T_N_VL, false, 3 },
1180 { 0x23, "pmovsxwd", T_0F38 | T_66 | T_YMM | T_EVEX | T_N8 | T_N_VL, false, 3 },
1181 { 0x24, "pmovsxwq", T_0F38 | T_66 | T_YMM | T_EVEX | T_N4 | T_N_VL, false, 3 },
1182 { 0x25, "pmovsxdq", T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0 | T_N8 | T_N_VL, false, 3 },
1183
1184 { 0x30, "pmovzxbw", T_0F38 | T_66 | T_YMM | T_EVEX | T_N8 | T_N_VL, false, 3 },
1185 { 0x31, "pmovzxbd", T_0F38 | T_66 | T_YMM | T_EVEX | T_N4 | T_N_VL, false, 3 },
1186 { 0x32, "pmovzxbq", T_0F38 | T_66 | T_YMM | T_EVEX | T_N2 | T_N_VL, false, 3 },
1187 { 0x33, "pmovzxwd", T_0F38 | T_66 | T_YMM | T_EVEX | T_N8 | T_N_VL, false, 3 },
1188 { 0x34, "pmovzxwq", T_0F38 | T_66 | T_YMM | T_EVEX | T_N4 | T_N_VL, false, 3 },
1189 { 0x35, "pmovzxdq", T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0 | T_N8 | T_N_VL, false, 3 },
1190
1191 { 0x70, "pshufd", T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, true, 2 },
1192 { 0x70, "pshufhw", T_0F | T_F3 | T_YMM | T_EVEX, true, 2 },
1193 { 0x70, "pshuflw", T_0F | T_F2 | T_YMM | T_EVEX, true, 2 },
1194
1195 { 0x17, "ptest", T_0F38 | T_66 | T_YMM, false, 3 },
1196 { 0x53, "rcpps", T_0F | T_YMM, false, 2 },
1197 { 0x52, "rsqrtps", T_0F | T_YMM, false, 2 },
1198
1199 { 0x51, "sqrtpd", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_ER_Z | T_B64, false, 2 },
1200 { 0x51, "sqrtps", T_0F | T_YMM | T_EVEX | T_EW0 | T_ER_Z | T_B32, false, 2 },
1201
1202 { 0x2E, "ucomisd", T_0F | T_66 | T_EVEX | T_EW1 | T_SAE_X | T_N8, false, 2 },
1203 { 0x2E, "ucomiss", T_0F | T_EVEX | T_EW0 | T_SAE_X | T_N4, false, 2 },
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 };
1213 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1214 const Tbl *p = &tbl[i];
1215 std::string type = type2String(p->type);
1216 if (p->mode & 1) {
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 }
1223 if (p->mode & 2) {
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 // (m, x), (m, y)
1230 {
1231 const struct Tbl {
1232 uint8 code;
1233 const char *name;
1234 int type;
1235 } tbl[] = {
1236 { 0x29, "movapd", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_M_K },
1237 { 0x29, "movaps", T_0F | T_YMM | T_EVEX | T_EW0 | T_M_K },
1238 { 0x7F, "movdqa", T_0F | T_66 | T_YMM },
1239 { 0x7F, "movdqu", T_0F | T_F3 | T_YMM },
1240 { 0x11, "movupd", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_M_K },
1241 { 0x11, "movups", T_0F | T_YMM | T_EVEX | T_EW0 | T_M_K },
1242 };
1243 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1244 const Tbl *p = &tbl[i];
1245 std::string type = type2String(p->type);
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 // (x, x/m), (y, y/m), (x, x, x/m), (y, y, y/m)
1251 {
1252 const struct Tbl {
1253 uint8 code;
1254 const char *name;
1255 int type;
1256 int mode; // 1 : sse, 2 : avx, 3 : sse + avx
1257 } tbl[] = {
1258 { 0xD0, "addsubpd", T_0F | T_66 | T_YMM, 3 },
1259 { 0xD0, "addsubps", T_0F | T_F2 | T_YMM, 3 },
1260 { 0x7C, "haddpd", T_0F | T_66 | T_YMM, 3 },
1261 { 0x7C, "haddps", T_0F | T_F2 | T_YMM, 3 },
1262 { 0x7D, "hsubpd", T_0F | T_66 | T_YMM, 3 },
1263 { 0x7D, "hsubps", T_0F | T_F2 | T_YMM, 3 },
1264
1265 { 0xDC, "aesenc", T_0F38 | T_66 | T_YMM | T_EVEX, 3 },
1266 { 0xDD, "aesenclast", T_0F38 | T_66 | T_YMM | T_EVEX, 3 },
1267 { 0xDE, "aesdec", T_0F38 | T_66 | T_YMM | T_EVEX, 3 },
1268 { 0xDF, "aesdeclast", T_0F38 | T_66 | T_YMM | T_EVEX, 3 },
1269 };
1270 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1271 const Tbl *p = &tbl[i];
1272 std::string type = type2String(p->type);
1273 if (p->mode & 1) {
1274 uint8 pref = p->type & T_66 ? 0x66 : p->type & T_F2 ? 0xF2 : p->type & T_F3 ? 0xF3 : 0;
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 }
1277 if (p->mode & 2) {
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 // vmaskmov
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 // vpmaskmov
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 // vpermd, vpermps
1300 {
1301 const struct Tbl {
1302 uint8 code;
1303 const char *name;
1304 int type;
1305 } tbl[] = {
1306 { 0x36, "vpermd", T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX | T_EW0 | T_B32 },
1307 { 0x36, "vpermq", T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX | T_EW1 | T_B64 },
1308 { 0x16, "vpermps", T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX | T_EW0 | T_B32 },
1309 { 0x16, "vpermpd", T_66 | T_0F38 | T_MUST_EVEX | T_EW1 | T_YMM | T_B64 },
1310 };
1311 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1312 const Tbl& p = tbl[i];
1313 std::string type = type2String(p.type);
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 // vpermq, vpermpd
1318 {
1319 const struct Tbl {
1320 uint8 code;
1321 const char *name;
1322 int type;
1323 } tbl[] = {
1324 { 0x00, "vpermq", T_0F3A | T_66 | T_W1 | T_YMM | T_EVEX | T_EW1 | T_B64 },
1325 { 0x01, "vpermpd", T_0F3A | T_66 | T_W1 | T_YMM | T_EVEX | T_EW1 | T_B64 },
1326 };
1327 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1328 const Tbl& p = tbl[i];
1329 std::string type = type2String(p.type);
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 // vcmpeqps
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++) {
1345 if (j < 8) {
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 // vmov(h|l)(pd|ps)
1353 {
1354 const struct Tbl {
1355 bool isH;
1356 bool isPd;
1357 uint8 code;
1358 } tbl[] = {
1359 { true, true, 0x16 },
1360 { true, false, 0x16 },
1361 { false, true, 0x12 },
1362 { false, false, 0x12 },
1363 };
1364 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 // FMA
1376 {
1377 const struct Tbl {
1378 uint8 code;
1379 const char *name;
1380 bool supportYMM;
1381 } tbl[] = {
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 };
1393 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 {
1401 const char *str;
1402 uint8 code;
1403 } ord[] = {
1404 { "132", 0x90 },
1405 { "213", 0xA0 },
1406 { "231", 0xB0 },
1407 };
1408 int t = T_0F38 | T_66 | T_EVEX;
1409 t |= (j == 0) ? (T_W1 | T_EW1) : (T_W0 | T_EW0);
1410 if (tbl[i].supportYMM) t |= T_YMM;
1411 const std::string suf = sufTbl[tbl[i].supportYMM ? 0 : 1][j];
1412 if (suf == "pd") {
1413 t |= T_B64;
1414 } else if (suf == "ps") {
1415 t |= T_B32;
1416 } else if (suf == "sd") {
1417 t |= T_ER_X | T_N8;
1418 } else { // ss
1419 t |= T_ER_X | T_N4;
1420 }
1421 std::string type = type2String(t);
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 // FMA others
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 {
1434 const char *name;
1435 uint8 code;
1436 int type;
1437 bool ew1;
1438 } tbl[] = {
1439 { "vbroadcastss", 0x18, T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_N4 },
1440 { "vpbroadcastb", 0x78, T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_N1 },
1441 { "vpbroadcastw", 0x79, T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_N2 },
1442 { "vpbroadcastd", 0x58, T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_N4 },
1443 { "vpbroadcastq", 0x59, T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW1 | T_N8 },
1444 };
1445 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1446 const Tbl& p = tbl[i];
1447 std::string type = type2String(p.type);
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 // (x, x, imm), (x, imm)
1478 {
1479 const struct Tbl {
1480 const char *name;
1481 uint8 code;
1482 int idx;
1483 int type;
1484 } tbl[] = {
1485 { "pslldq", 0x73, 7, T_0F | T_66 | T_YMM | T_EVEX },
1486 { "psrldq", 0x73, 3, T_0F | T_66 | T_YMM | T_EVEX },
1487 { "psllw", 0x71, 6, T_0F | T_66 | T_YMM | T_EVEX },
1488 { "pslld", 0x72, 6, T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32 },
1489 { "psllq", 0x73, 6, T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64 },
1490 { "psraw", 0x71, 4, T_0F | T_66 | T_YMM | T_EVEX },
1491 { "psrad", 0x72, 4, T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32 },
1492 { "psrlw", 0x71, 2, T_0F | T_66 | T_YMM | T_EVEX },
1493 { "psrld", 0x72, 2, T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32 },
1494 { "psrlq", 0x73, 2, T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64 },
1495 };
1496 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1497 const Tbl& p = tbl[i];
1498 std::string type = type2String(p.type);
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 // 4-op
1503 {
1504 const struct Tbl {
1505 const char *name;
1506 uint8 code;
1507 } tbl[] = {
1508 { "vblendvpd", 0x4B },
1509 { "vblendvps", 0x4A },
1510 { "vpblendvb", 0x4C },
1511 };
1512 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 // mov
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 // vmovsd, vmovss
1538 for (int i = 0; i < 2; i++) {
1539 char c1 = i == 0 ? 'd' : 's';
1540 int type = T_0F | T_EVEX;
1541 type |= i == 0 ? (T_F2 | T_EW1 | T_N8) : (T_F3 | T_EW0 | T_N4);
1542 std::string s = type2String(type);
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 // cvt
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 // haswell gpr(reg, reg, r/m)
1572 {
1573 const struct Tbl {
1574 const char *name;
1575 int type;
1576 uint8 code;
1577 } tbl[] = {
1578 { "andn", T_0F38, 0xF2 },
1579 { "mulx", T_F2 | T_0F38, 0xF6 },
1580 { "pdep", T_F2 | T_0F38, 0xF5 },
1581 { "pext", T_F3 | T_0F38, 0xF5 },
1582 };
1583 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 // gpr(reg, r/m, reg)
1589 {
1590 const struct Tbl {
1591 const char *name;
1592 int type;
1593 uint8 code;
1594 } tbl[] = {
1595 { "bextr", T_0F38, 0xF7 },
1596 { "bzhi", T_0F38, 0xF5 },
1597 { "sarx", T_0F38 | T_F3, 0xF7 },
1598 { "shlx", T_0F38 | T_66, 0xF7 },
1599 { "shrx", T_0F38 | T_F2, 0xF7 },
1600 };
1601 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 // gpr(reg, r/m)
1608 {
1609 const struct Tbl {
1610 const char *name;
1611 int type;
1612 uint8 code;
1613 uint8 idx;
1614 } tbl[] = {
1615 { "blsi", T_0F38, 0xF3, 3 },
1616 { "blsmsk", T_0F38, 0xF3, 2 },
1617 { "blsr", T_0F38, 0xF3, 1 },
1618 };
1619 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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 // gather
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 {
1630 const char *name;
1631 uint8 code;
1632 int w;
1633 int mode;
1634 } tbl[] = {
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 };
1644 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
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}
@ T_ER_Z
Definition avx_type.hpp:31
@ T_B32
Definition avx_type.hpp:36
@ T_W0
Definition avx_type.hpp:23
@ T_0F38
Definition avx_type.hpp:19
@ T_YMM
Definition avx_type.hpp:27
@ T_EW0
Definition avx_type.hpp:25
@ T_N2
Definition avx_type.hpp:6
@ T_MUST_EVEX
Definition avx_type.hpp:35
@ T_0F3A
Definition avx_type.hpp:20
@ T_ER_Y
Definition avx_type.hpp:30
@ T_SAE_Z
Definition avx_type.hpp:34
@ T_N_VL
Definition avx_type.hpp:13
@ T_SAE_X
Definition avx_type.hpp:32
@ T_F2
Definition avx_type.hpp:17
@ T_EVEX
Definition avx_type.hpp:28
@ T_EW1
Definition avx_type.hpp:26
@ T_DUP
Definition avx_type.hpp:14
@ T_N4
Definition avx_type.hpp:7
@ T_66
Definition avx_type.hpp:15
@ T_B64
Definition avx_type.hpp:37
@ T_M_K
Definition avx_type.hpp:38
@ T_F3
Definition avx_type.hpp:16
@ T_N1
Definition avx_type.hpp:5
@ T_0F
Definition avx_type.hpp:18
@ T_N8
Definition avx_type.hpp:8
@ T_W1
Definition avx_type.hpp:24
@ T_ER_X
Definition avx_type.hpp:29
std::string type2String(int type)
Definition avx_type.hpp:44
const int NONE
Definition avx_type.hpp:42
const mie::Vuint & p
Definition bn.cpp:27
std::string name
const struct Ptn tbl[]
#define D(var, file, col, who, lev,...)
Definition debug.h:44
#define NUM_OF_ARRAY(x)
Definition gen_code.cpp:5
void putGeneric(const GenericTbl *p, size_t n)
Definition gen_code.cpp:31
void putX_X_XM(bool omitOnly)
Definition gen_code.cpp:42
return str
Definition CLI11.hpp:1359
LOGGING_API void printf(Category category, const char *format,...)
Definition Logging.cpp:30
@ VERSION
Definition xbyak.h:108
unsigned char uint8
Xbyak::uint32 uint32
Definition quantize.cpp:52
yh_object_type type
Definition yubihsm.h:672
char * s
uint16_t j
uint8_t buf[2048]
Here is the call graph for this function:
Here is the caller graph for this function:

◆ put32()

void put32 ( )

Definition at line 1651 of file gen_code.cpp.

1652{
1653 put_jREGz("cx", true);
1654 put_jREGz("ecx", false);
1655
1656 const GenericTbl tbl[] = {
1657 { "aaa", 0x37 },
1658 { "aad", 0xD5, 0x0A },
1659 { "aam", 0xD4, 0x0A },
1660 { "aas", 0x3F },
1661 { "daa", 0x27 },
1662 { "das", 0x2F },
1663 { "popad", 0x61 },
1664 { "popfd", 0x9D },
1665 { "pusha", 0x60 },
1666 { "pushad", 0x60 },
1667 { "pushfd", 0x9C },
1668 { "popa", 0x61 },
1669 };
1671}
void put_jREGz(const char *reg, bool prefix)
Definition gen_code.cpp:18
Here is the call graph for this function:
Here is the caller graph for this function:

◆ put64()

void put64 ( )

Definition at line 1673 of file gen_code.cpp.

1674{
1675 put_jREGz("ecx", true);
1676 put_jREGz("rcx", false);
1677
1678 const GenericTbl tbl[] = {
1679 { "cdqe", 0x48, 0x98 },
1680 { "cqo", 0x48, 0x99 },
1681 { "movsq", 0x48, 0xA5 },
1682 };
1684
1685 puts("void cmpxchg16b(const Address& addr) { opModM(addr, Reg64(1), 0x0F, 0xC7); }");
1686 puts("void movq(const Reg64& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x7E); }");
1687 puts("void movq(const Mmx& mmx, const Reg64& reg) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x6E); }");
1688 puts("void movsxd(const Reg64& reg, const Operand& op) { if (!op.isBit(32)) throw Error(ERR_BAD_COMBINATION); opModRM(reg, op, op.isREG(), op.isMEM(), 0x63); }");
1689 puts("void pextrq(const Operand& op, const Xmm& xmm, uint8 imm) { if (!op.isREG(64) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opGen(Reg64(xmm.getIdx()), op, 0x16, 0x66, 0, imm, 0x3A); }");
1690 puts("void pinsrq(const Xmm& xmm, const Operand& op, uint8 imm) { if (!op.isREG(64) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opGen(Reg64(xmm.getIdx()), op, 0x22, 0x66, 0, imm, 0x3A); }");
1691
1692 puts("void vcvtss2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W1 | T_EVEX | T_EW1 | T_ER_X | T_N8, 0x2D); }");
1693 puts("void vcvttss2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W1 | T_EVEX | T_EW1 | T_SAE_X | T_N8, 0x2C); }");
1694 puts("void vcvtsd2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W1 | T_EVEX | T_EW1 | T_N4 | T_ER_X, 0x2D); }");
1695 puts("void vcvttsd2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W1 | T_EVEX | T_EW1 | T_N4 | T_SAE_X, 0x2C); }");
1696
1697 puts("void vmovq(const Xmm& x, const Reg64& r) { opAVX_X_X_XM(x, xm0, Xmm(r.getIdx()), T_66 | T_0F | T_W1 | T_EVEX | T_EW1, 0x6E); }");
1698 puts("void vmovq(const Reg64& r, const Xmm& x) { opAVX_X_X_XM(x, xm0, Xmm(r.getIdx()), T_66 | T_0F | T_W1 | T_EVEX | T_EW1, 0x7E); }");
1699}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ put_jREGz()

void put_jREGz ( const char * reg,
bool prefix )

Definition at line 18 of file gen_code.cpp.

19{
20 printf("void j%sz(std::string label) { %sopJmp(label, T_SHORT, 0xe3, 0, 0); }\n", reg, prefix ? "db(0x67); " : "");
21 printf("void j%sz(const Label& label) { %sopJmp(label, T_SHORT, 0xe3, 0, 0); }\n", reg, prefix ? "db(0x67); " : "");
22}
Here is the caller graph for this function:

◆ putFixed()

void putFixed ( )

Definition at line 1701 of file gen_code.cpp.

1702{
1703 puts("#ifdef XBYAK64");
1704 put64();
1705 puts("#else");
1706 put32();
1707 puts("#endif");
1708 puts("#ifndef XBYAK_NO_OP_NAMES");
1709 const char *tbl[] = {
1710 "and", "or", "xor",
1711 };
1712 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1713 const char *name = tbl[i];
1714 printf("void %s(const Operand& op1, const Operand& op2) { %s_(op1, op2); }\n", name, name);
1715 printf("void %s(const Operand& op, uint32 imm) { %s_(op, imm); }\n", name, name);
1716 }
1717 puts("void not(const Operand& op) { not_(op); }");
1718 puts("#endif");
1719}
void put64()
void put32()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ putGeneric()

void putGeneric ( const GenericTbl * p,
size_t n )

Definition at line 31 of file gen_code.cpp.

32{
33 for (size_t i = 0; i < n; i++) {
34 printf("void %s() { db(0x%02X); ", p->name, p->code1);
35 if (p->code2) printf("db(0x%02X); ", p->code2);
36 if (p->code3) printf("db(0x%02X); ", p->code3);
37 printf("}\n");
38 p++;
39 }
40}
Here is the caller graph for this function:

◆ putOmit()

void putOmit ( )

Definition at line 1721 of file gen_code.cpp.

1722{
1723 puts("void vpinsrb(const Xmm& x, const Operand& op, uint8 imm) { vpinsrb(x, x, op, imm); }");
1724 puts("void vpinsrd(const Xmm& x, const Operand& op, uint8 imm) { vpinsrd(x, x, op, imm); }");
1725 puts("void vpinsrq(const Xmm& x, const Operand& op, uint8 imm) { vpinsrq(x, x, op, imm); }");
1726 puts("void vpinsrw(const Xmm& x, const Operand& op, uint8 imm) { vpinsrw(x, x, op, imm); }");
1727
1728 puts("void vcvtsi2sd(const Xmm& x, const Operand& op) { vcvtsi2sd(x, x, op); }");
1729 puts("void vcvtsi2ss(const Xmm& x, const Operand& op) { vcvtsi2ss(x, x, op); }");
1730 {
1731 const char pred[32][16] = {
1732 "eq", "lt", "le", "unord", "neq", "nlt", "nle", "ord",
1733 "eq_uq", "nge", "ngt", "false", "neq_oq", "ge", "gt",
1734 "true", "eq_os", "lt_oq", "le_oq", "unord_s", "neq_us", "nlt_uq", "nle_uq", "ord_s",
1735 "eq_us", "nge_uq", "ngt_uq", "false_os", "neq_os", "ge_oq", "gt_oq", "true_us"
1736 };
1737 const char suf[][4] = { "pd", "ps", "sd", "ss" };
1738 for (int i = 0; i < 4; i++) {
1739 const char *s = suf[i];
1740 for (int j = 0; j < 32; j++) {
1741 printf("void vcmp%s%s(const Xmm& x, const Operand& op) { vcmp%s%s(x, x, op); }\n", pred[j], s, pred[j], s);
1742 }
1743 }
1744 }
1745 {
1746 const char *tbl[] = {
1747 "pslldq",
1748 "psrldq",
1749 "psllw",
1750 "pslld",
1751 "psllq",
1752 "psraw",
1753 "psrad",
1754 "psrlw",
1755 "psrld",
1756 "psrlq",
1757 };
1758 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1759 const char *name = tbl[i];
1760 printf("void v%s(const Xmm& x, uint8 imm) { v%s(x, x, imm); }\n", name, name);
1761 }
1762 }
1763 {
1764 const char *tbl[] = {
1765 "vblendvpd",
1766 "vblendvps",
1767 "vpblendvb",
1768 };
1769 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1770 const char *name = tbl[i];
1771 printf("void %s(const Xmm& x1, const Operand& op, const Xmm& x4) { %s(x1, x1, op, x4); }\n", name, name);
1772 }
1773 }
1774 putX_X_XM(true);
1775}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ putX_X_XM()

void putX_X_XM ( bool omitOnly)

Definition at line 42 of file gen_code.cpp.

43{
44 // (x, x, x/m[, imm]) or (y, y, y/m[, imm])
45 {
46 const struct Tbl {
47 uint8 code;
48 const char *name;
49 int type;
50 bool hasIMM;
51 bool enableOmit;
52 int mode; // 1 : sse, 2 : avx, 3 : sse + avx
53 } tbl[] = {
54 { 0x0D, "blendpd", T_0F3A | T_66 | T_W0 | T_YMM, true, true, 3 },
55 { 0x0C, "blendps", T_0F3A | T_66 | T_W0 | T_YMM, true, true, 3 },
56 { 0x41, "dppd", T_0F3A | T_66 | T_W0, true, true, 3 },
57 { 0x40, "dpps", T_0F3A | T_66 | T_W0 | T_YMM, true, true, 3 },
58 { 0x42, "mpsadbw", T_0F3A | T_66 | T_W0 | T_YMM, true, true, 3 },
59 { 0x0E, "pblendw", T_0F3A | T_66 | T_W0 | T_YMM, true, true, 3 },
60 { 0x02, "pblendd", T_0F3A | T_66 | T_W0 | T_YMM, true, true, 2 },
61 { 0x0B, "roundsd", T_0F3A | T_66 | T_W0, true, true, 3 },
62 { 0x0A, "roundss", T_0F3A | T_66 | T_W0, true, true, 3 },
63 { 0x44, "pclmulqdq", T_0F3A | T_66 | T_W0 | T_YMM | T_EVEX, true, true, 3 },
64 { 0x0C, "permilps", T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW0 | T_B32, false, false, 2 },
65 { 0x0D, "permilpd", T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW1 | T_B64, false, false, 2 },
66
67 { 0x47, "psllvd", T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW0 | T_B32, false, false, 2 },
68 { 0x47, "psllvq", T_0F38 | T_66 | T_W1 | T_YMM | T_EVEX | T_EW1 | T_B64, false, false, 2 },
69 { 0x46, "psravd", T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW0 | T_B32, false, false, 2 },
70 { 0x45, "psrlvd", T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW0 | T_B32, false, false, 2 },
71 { 0x45, "psrlvq", T_0F38 | T_66 | T_W1 | T_YMM | T_EVEX | T_EW1 | T_B64, false, false, 2 },
72
73 { 0xC2, "cmppd", T_0F | T_66 | T_YMM, true, true, 2 },
74 { 0xC2, "cmpps", T_0F | T_YMM, true, true, 2 },
75 { 0xC2, "cmpsd", T_0F | T_F2, true, true, 2 },
76 { 0xC2, "cmpss", T_0F | T_F3, true, true, 2 },
77 { 0x5A, "cvtsd2ss", T_0F | T_F2 | T_EVEX | T_EW1 | T_N8 | T_ER_X, false, true, 2 },
78 { 0x5A, "cvtss2sd", T_0F | T_F3 | T_EVEX | T_EW0 | T_N4 | T_SAE_X, false, true, 2 },
79 { 0x21, "insertps", T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0, true, true, 2 },
80 { 0x63, "packsswb", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
81 { 0x6B, "packssdw", T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 2 },
82 { 0x67, "packuswb", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
83 { 0x2B, "packusdw", T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 3 },
84
85 { 0xFC, "paddb", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
86 { 0xFD, "paddw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
87 { 0xFE, "paddd", T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 2 },
88 { 0xD4, "paddq", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, false, true, 2 },
89
90 { 0xEC, "paddsb", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
91 { 0xED, "paddsw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
92
93 { 0xDC, "paddusb", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
94 { 0xDD, "paddusw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
95
96 { 0x0F, "palignr", T_0F3A | T_66 | T_YMM | T_EVEX, true, true, 2 },
97
98 { 0xDB, "pand", T_0F | T_66 | T_YMM, false, true, 2 },
99 { 0xDF, "pandn", T_0F | T_66 | T_YMM, false, true, 2 },
100
101 { 0xE0, "pavgb", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
102 { 0xE3, "pavgw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
103
104 { 0x74, "pcmpeqb", T_0F | T_66 | T_YMM, false, true, 2 },
105 { 0x75, "pcmpeqw", T_0F | T_66 | T_YMM, false, true, 2 },
106 { 0x76, "pcmpeqd", T_0F | T_66 | T_YMM, false, true, 2 },
107 { 0x29, "pcmpeqq", T_0F38 | T_66 | T_YMM, false, true, 3 },
108
109 { 0x64, "pcmpgtb", T_0F | T_66 | T_YMM, false, true, 2 },
110 { 0x65, "pcmpgtw", T_0F | T_66 | T_YMM, false, true, 2 },
111 { 0x66, "pcmpgtd", T_0F | T_66 | T_YMM, false, true, 2 },
112 { 0x37, "pcmpgtq", T_0F38 | T_66 | T_YMM, false, true, 3 },
113
114 { 0x01, "phaddw", T_0F38 | T_66 | T_YMM, false, true, 2 },
115 { 0x02, "phaddd", T_0F38 | T_66 | T_YMM, false, true, 2 },
116 { 0x03, "phaddsw", T_0F38 | T_66 | T_YMM, false, true, 2 },
117
118 { 0x05, "phsubw", T_0F38 | T_66 | T_YMM, false, true, 2 },
119 { 0x06, "phsubd", T_0F38 | T_66 | T_YMM, false, true, 2 },
120 { 0x07, "phsubsw", T_0F38 | T_66 | T_YMM, false, true, 2 },
121 { 0xF5, "pmaddwd", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
122 { 0x04, "pmaddubsw", T_0F38 | T_66 | T_YMM | T_EVEX, false, true, 2 },
123
124 { 0x3C, "pmaxsb", T_0F38 | T_66 | T_YMM | T_EVEX, false, true, 3 },
125 { 0xEE, "pmaxsw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
126 { 0x3D, "pmaxsd", T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 3 },
127
128 { 0xDE, "pmaxub", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
129 { 0x3E, "pmaxuw", T_0F38 | T_66 | T_YMM | T_EVEX, false, true, 3 },
130 { 0x3F, "pmaxud", T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 3 },
131
132 { 0x38, "pminsb", T_0F38 | T_66 | T_YMM | T_EVEX, false, true, 3 },
133 { 0xEA, "pminsw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
134 { 0x39, "pminsd", T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 3 },
135
136 { 0xDA, "pminub", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
137 { 0x3A, "pminuw", T_0F38 | T_66 | T_YMM | T_EVEX, false, true, 3 },
138 { 0x3B, "pminud", T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 3 },
139
140 { 0xE4, "pmulhuw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
141 { 0x0B, "pmulhrsw", T_0F38 | T_66 | T_YMM | T_EVEX, false, true, 2 },
142 { 0xE5, "pmulhw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
143 { 0xD5, "pmullw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
144 { 0x40, "pmulld", T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 3 },
145
146 { 0xF4, "pmuludq", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, false, true, 2 },
147 { 0x28, "pmuldq", T_0F38 | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, false, true, 3 },
148
149 { 0xEB, "por", T_0F | T_66 | T_YMM, false, true, 2 },
150 { 0xF6, "psadbw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
151
152 { 0x00, "pshufb", T_0F38 | T_66 | T_YMM | T_EVEX, false, false, 2 },
153
154 { 0x08, "psignb", T_0F38 | T_66 | T_YMM, false, true, 2 },
155 { 0x09, "psignw", T_0F38 | T_66 | T_YMM, false, true, 2 },
156 { 0x0A, "psignd", T_0F38 | T_66 | T_YMM, false, true, 2 },
157
158 { 0xF1, "psllw", T_0F | T_66 | T_YMM | T_EVEX | T_N16, false, true, 2 },
159 { 0xF2, "pslld", T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_N16, false, true, 2 },
160 { 0xF3, "psllq", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_N16, false, true, 2 },
161
162 { 0xE1, "psraw", T_0F | T_66 | T_YMM | T_EVEX | T_N16, false, true, 2 },
163 { 0xE2, "psrad", T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_N16, false, true, 2 },
164 { 0xD1, "psrlw", T_0F | T_66 | T_YMM | T_EVEX | T_N16, false, true, 2 },
165 { 0xD2, "psrld", T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_N16, false, true, 2 },
166 { 0xD3, "psrlq", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_N16, false, true, 2 },
167
168 { 0xF8, "psubb", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
169 { 0xF9, "psubw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
170 { 0xFA, "psubd", T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 2 },
171 { 0xFB, "psubq", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, false, true, 2 },
172
173 { 0xE8, "psubsb", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
174 { 0xE9, "psubsw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
175
176 { 0xD8, "psubusb", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
177 { 0xD9, "psubusw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
178
179 { 0x68, "punpckhbw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
180 { 0x69, "punpckhwd", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
181 { 0x6A, "punpckhdq", T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 2 },
182 { 0x6D, "punpckhqdq", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, false, true, 2 },
183
184 { 0x60, "punpcklbw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
185 { 0x61, "punpcklwd", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
186 { 0x62, "punpckldq", T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 2 },
187 { 0x6C, "punpcklqdq", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, false, true, 2 },
188
189 { 0xEF, "pxor", T_0F | T_66 | T_YMM, false, true, 2 },
190
191 { 0x53, "rcpss", T_0F | T_F3, false, true, 2 },
192 { 0x52, "rsqrtss", T_0F | T_F3, false, true, 2 },
193
194 { 0xC6, "shufpd", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, true, true, 2 },
195 { 0xC6, "shufps", T_0F | T_YMM | T_EVEX | T_EW0 | T_B32, true, true, 2 },
196
197 { 0x51, "sqrtsd", T_0F | T_F2 | T_EVEX | T_EW1 | T_ER_X | T_N8, false, true, 2 },
198 { 0x51, "sqrtss", T_0F | T_F3 | T_EVEX | T_EW0 | T_ER_X | T_N4, false, true, 2 },
199
200 { 0x15, "unpckhpd", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, false, true, 2 },
201 { 0x15, "unpckhps", T_0F | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 2 },
202
203 { 0x14, "unpcklpd", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, false, true, 2 },
204 { 0x14, "unpcklps", T_0F | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 2 },
205
206 { 0xCF, "gf2p8affineinvqb", T_66 | T_0F3A | T_W1 | T_EVEX | T_YMM | T_EW1 | T_SAE_Z | T_B64, true, false, 3 },
207 { 0xCE, "gf2p8affineqb", T_66 | T_0F3A | T_W1 | T_EVEX | T_YMM | T_EW1 | T_SAE_Z | T_B64, true, false, 3 },
208 { 0xCF, "gf2p8mulb", T_66 | T_0F38 | T_W0 | T_EVEX | T_YMM | T_EW0 | T_SAE_Z, false, false, 3 },
209 };
210 for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
211 const Tbl *p = &tbl[i];
212 std::string type = type2String(p->type);
213 if (omitOnly) {
214 if (p->enableOmit) {
215 printf("void v%s(const Xmm& x, const Operand& op%s) { v%s(x, x, op%s); }\n", p->name, p->hasIMM ? ", uint8 imm" : "", p->name, p->hasIMM ? ", imm" : "");
216 }
217 } else {
218 if (p->mode & 1) {
219 if (p->hasIMM) {
220 printf("void %s(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x%02X, 0x66, isXMM_XMMorMEM, static_cast<uint8>(imm), 0x3A); }\n", p->name, p->code);
221 } else {
222 printf("void %s(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x%02X, 0x66, isXMM_XMMorMEM, NONE, 0x38); }\n", p->name, p->code);
223 }
224 }
225 if (p->mode & 2) {
226 printf("void v%s(const Xmm& x1, const Xmm& x2, const Operand& op%s) { opAVX_X_X_XM(x1, x2, op, %s, 0x%02X%s); }\n"
227 , p->name, p->hasIMM ? ", uint8 imm" : "", type.c_str(), p->code, p->hasIMM ? ", imm" : "");
228 }
229 }
230 }
231 }
232}
@ T_N16
Definition avx_type.hpp:9
Here is the call graph for this function:
Here is the caller graph for this function: