mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-01 03:53:33 +00:00
23d333c090
This change includes many bug fixes, for the NT polyfills, strings, memory, boot, and math libraries which were discovered by adding more tools for recreational programming, such as PC emulation. Lemon has also been vendored because it works so well at parsing languages.
967 lines
31 KiB
C
967 lines
31 KiB
C
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
|
│ │
|
|
│ This program is free software; you can redistribute it and/or modify │
|
|
│ it under the terms of the GNU General Public License as published by │
|
|
│ the Free Software Foundation; version 2 of the License. │
|
|
│ │
|
|
│ This program is distributed in the hope that it will be useful, but │
|
|
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
|
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
|
│ General Public License for more details. │
|
|
│ │
|
|
│ You should have received a copy of the GNU General Public License │
|
|
│ along with this program; if not, write to the Free Software │
|
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
|
│ 02110-1301 USA │
|
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
|
#include "libc/str/str.h"
|
|
#include "third_party/xed/x86.h"
|
|
#include "tool/build/lib/case.h"
|
|
#include "tool/build/lib/modrm.h"
|
|
|
|
#define UNKNOWN "wut"
|
|
#define RCASE(x, y) CASE(x, return y)
|
|
|
|
static const char kFpuName[][8][8] = {
|
|
{"fadd", "fmul", "fcom", "fcomp", "fsub", "fsubr", "fdiv", "fdivr"},
|
|
{"fchs", "fabs", UNKNOWN, UNKNOWN, "ftst", "fxam", UNKNOWN, UNKNOWN},
|
|
{"fld1", "fldl2t", "fldl2e", "fldpi", "fldlg2", "fldln2", "fldz"},
|
|
{"f2xm1", "fyl2x", "fptan", "fpatan", "fxtract", "fprem1", "fdecstp",
|
|
"fincstp"},
|
|
{"fprem", "fyl2xp1", "fsqrt", "fsincos", "frndint", "fscale", "fsin",
|
|
"fcos"},
|
|
{"fneni", "fndisi", "fnclex", "fninit", "fnsetpm"},
|
|
};
|
|
|
|
char *DisOpFpu1(struct XedDecodedInst *x, char *p, const char *extra) {
|
|
stpcpy(stpcpy(p, kFpuName[0][ModrmReg(x->op.rde)]), extra);
|
|
return p;
|
|
}
|
|
|
|
char *DisOp66(struct XedDecodedInst *x, char *p, const char *s, const char *a,
|
|
const char *b) {
|
|
stpcpy(stpcpy(p, s), !Osz(x->op.rde) ? a : b);
|
|
return p;
|
|
}
|
|
|
|
char *DisOpVpsWpsVssWss(struct XedDecodedInst *x, char *p, const char *s) {
|
|
return DisOp66(x, p, s, "ps %Vps Wps", "ss %Vss Wss");
|
|
}
|
|
|
|
char *DisOpVpdWpdVpsWps(struct XedDecodedInst *x, char *p, const char *s) {
|
|
return DisOp66(x, p, s, "ps %Vps Wps", "pd %Vpd Wpd");
|
|
}
|
|
|
|
char *DisOpPqQqVdqWdq(struct XedDecodedInst *x, char *p, const char *s) {
|
|
return DisOp66(x, p, s, " %Pq Qq", " %Vdq Wdq");
|
|
}
|
|
|
|
char *DisOpPqQqIbVdqWdqIb(struct XedDecodedInst *x, char *p, const char *s) {
|
|
return DisOp66(x, p, s, " %Pq Qq Ib", " %Vdq Wdq Ib");
|
|
}
|
|
|
|
char *DisOpNqIbUdqIb(struct XedDecodedInst *x, char *p, const char *s) {
|
|
return DisOp66(x, p, s, " %Nq Ib", " %Udq Ib");
|
|
}
|
|
|
|
char *DisOpVpsWpsVssWssVpdWpdVsdWsd(struct XedDecodedInst *x, char *p,
|
|
const char *s) {
|
|
char *q = stpcpy(p, s);
|
|
if (Rep(x->op.rde) == 3) {
|
|
stpcpy(q, "ss %Vss Wss");
|
|
} else if (Rep(x->op.rde) == 2) {
|
|
stpcpy(q, "sd %Vsd Wsd");
|
|
} else if (Osz(x->op.rde)) {
|
|
stpcpy(q, "pd %Vpd Wpd");
|
|
} else {
|
|
stpcpy(q, "ps %Vps Wps");
|
|
}
|
|
return p;
|
|
}
|
|
|
|
const char *DisSpecFpu0(struct XedDecodedInst *x, int group) {
|
|
const char *s;
|
|
s = kFpuName[group][ModrmRm(x->op.rde)];
|
|
return *s ? s : UNKNOWN;
|
|
}
|
|
|
|
const char *DisSpecRegMem(struct XedDecodedInst *x, const char *a,
|
|
const char *b) {
|
|
if (IsModrmRegister(x->op.rde)) {
|
|
return a;
|
|
} else {
|
|
return b;
|
|
}
|
|
}
|
|
|
|
const char *DisSpecRegMemFpu0(struct XedDecodedInst *x, int group,
|
|
const char *b) {
|
|
return DisSpecRegMem(x, DisSpecFpu0(x, group), b);
|
|
}
|
|
|
|
const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
|
|
switch (x->op.opcode & 0xff) {
|
|
RCASE(0x00, "ALU Eb %Gb");
|
|
RCASE(0x01, "ALU Evqp %Gvqp");
|
|
RCASE(0x02, "ALU %Gb Eb");
|
|
RCASE(0x03, "ALU %Gvqp Evqp");
|
|
RCASE(0x04, "ALU %al Ib");
|
|
RCASE(0x05, "ALU %rAX Ivds");
|
|
RCASE(0x06, "push %es");
|
|
RCASE(0x07, "pop %es");
|
|
RCASE(0x08, "ALU Eb %Gb");
|
|
RCASE(0x09, "ALU Evqp %Gvqp");
|
|
RCASE(0x0a, "ALU %Gb Eb");
|
|
RCASE(0x0b, "ALU %Gvqp Evqp");
|
|
RCASE(0x0c, "ALU %al Ib");
|
|
RCASE(0x0d, "ALU %rAX Ivds");
|
|
RCASE(0x0e, "push %cs");
|
|
RCASE(0x0f, "pop %cs");
|
|
RCASE(0x10, "ALU Eb %Gb");
|
|
RCASE(0x11, "ALU Evqp %Gvqp");
|
|
RCASE(0x12, "ALU %Gb Eb");
|
|
RCASE(0x13, "ALU %Gvqp Evqp");
|
|
RCASE(0x14, "ALU %al Ib");
|
|
RCASE(0x15, "ALU %rAX Ivds");
|
|
RCASE(0x16, "push %ss");
|
|
RCASE(0x17, "pop %ss");
|
|
RCASE(0x18, "ALU Eb %Gb");
|
|
RCASE(0x19, "ALU Evqp %Gvqp");
|
|
RCASE(0x1a, "ALU %Gb Eb");
|
|
RCASE(0x1b, "ALU %Gvqp Evqp");
|
|
RCASE(0x1c, "ALU %al Ib");
|
|
RCASE(0x1d, "ALU %rAX Ivds");
|
|
RCASE(0x1e, "push %ds");
|
|
RCASE(0x1f, "pop %ds");
|
|
RCASE(0x20, "ALU Eb %Gb");
|
|
RCASE(0x21, "ALU Evqp %Gvqp");
|
|
RCASE(0x22, "ALU %Gb Eb");
|
|
RCASE(0x23, "ALU %Gvqp Evqp");
|
|
RCASE(0x24, "ALU %al Ib");
|
|
RCASE(0x25, "ALU %rAX Ivds");
|
|
RCASE(0x26, "push %es");
|
|
RCASE(0x27, "pop %es");
|
|
RCASE(0x28, "ALU Eb %Gb");
|
|
RCASE(0x29, "ALU Evqp %Gvqp");
|
|
RCASE(0x2a, "ALU %Gb Eb");
|
|
RCASE(0x2b, "ALU %Gvqp Evqp");
|
|
RCASE(0x2c, "ALU %al Ib");
|
|
RCASE(0x2d, "ALU %rAX Ivds");
|
|
RCASE(0x2F, "das");
|
|
RCASE(0x30, "ALU Eb %Gb");
|
|
RCASE(0x31, "ALU Evqp %Gvqp");
|
|
RCASE(0x32, "ALU %Gb Eb");
|
|
RCASE(0x33, "ALU %Gvqp Evqp");
|
|
RCASE(0x34, "ALU %al Ib");
|
|
RCASE(0x35, "ALU %rAX Ivds");
|
|
RCASE(0x37, "aaa");
|
|
RCASE(0x38, "ALU Eb %Gb");
|
|
RCASE(0x39, "ALU Evqp %Gvqp");
|
|
RCASE(0x3A, "ALU %Gb Eb");
|
|
RCASE(0x3B, "ALU %Gvqp Evqp");
|
|
RCASE(0x3C, "ALU %al Ib");
|
|
RCASE(0x3D, "ALU %rAX Ivds");
|
|
RCASE(0x3F, "aas");
|
|
RCASE(0x40 ... 0x47, "inc %Zv");
|
|
RCASE(0x48 ... 0x4f, "dec %Zv");
|
|
RCASE(0x50 ... 0x57, "push %Zvq");
|
|
RCASE(0x58 ... 0x5f, "pop %Zvq");
|
|
RCASE(0x60, "pusha");
|
|
RCASE(0x61, "popa");
|
|
RCASE(0x62, "bound");
|
|
RCASE(0x63, "movslLQ %Gdqp Ed");
|
|
RCASE(0x68, "pushWQ Ivs");
|
|
RCASE(0x69, "imul %Gvqp Evqp Ivds");
|
|
RCASE(0x6A, "pushWQ Ibss");
|
|
RCASE(0x6B, "imul %Gvqp Evqp Ibs");
|
|
RCASE(0x6C, "insb Yb %dx");
|
|
RCASE(0x6D, "insWL Yv %dx");
|
|
RCASE(0x6E, "outsb %dx Xb");
|
|
RCASE(0x6F, "outsWL %dx Xv");
|
|
RCASE(0x70 ... 0x7f, "jCC Jbs");
|
|
RCASE(0x80, "ALU2 Eb Ib");
|
|
RCASE(0x81, "ALU2 Evqp Ivds");
|
|
RCASE(0x82, "ALU2 Eb Ib");
|
|
RCASE(0x83, "ALU2 Evqp Ibs");
|
|
RCASE(0x84, "test Eb %Gb");
|
|
RCASE(0x85, "test %Gvqp Evqp");
|
|
RCASE(0x86, "xchg %Gb Eb");
|
|
RCASE(0x87, "xchg %Gvqp Evqp");
|
|
RCASE(0x88, "mov Eb %Gb");
|
|
RCASE(0x89, "mov Evqp %Gvqp");
|
|
RCASE(0x8A, "mov %Gb Eb");
|
|
RCASE(0x8B, "mov %Gvqp Evqp");
|
|
RCASE(0x8C, "mov Evqp %Sw");
|
|
RCASE(0x8D, "lea %Gvqp M");
|
|
RCASE(0x8E, "mov %Sw Evqp");
|
|
RCASE(0x90, "nop");
|
|
RCASE(0x91 ... 0x97, "xchg %Zvqp %rAX");
|
|
RCASE(0x98, "cwtl");
|
|
RCASE(0x99, "cltd");
|
|
RCASE(0x9A, "lcall Pvds Kvds");
|
|
RCASE(0x9B, "fwait");
|
|
RCASE(0x9C, "pushfWQ");
|
|
RCASE(0x9D, "popfWQ");
|
|
RCASE(0x9E, "sahf");
|
|
RCASE(0x9F, "lahf");
|
|
RCASE(0xA0, "movABS %al Ob");
|
|
RCASE(0xA1, "movABS %rAX Ovqp");
|
|
RCASE(0xA2, "movABS Ob %al");
|
|
RCASE(0xA3, "movABS Ovqp %rAX");
|
|
RCASE(0xA4, "movsb Yb Xb");
|
|
RCASE(0xA5, "movsWLQ Yvqp Xvqp");
|
|
RCASE(0xA6, "cmpsb Yb Xb");
|
|
RCASE(0xA7, "cmpsWLQ Yvqp Xvqp");
|
|
RCASE(0xA8, "test %al Ib");
|
|
RCASE(0xA9, "test %rAX Ivds");
|
|
RCASE(0xAA, "stosb Yb %al");
|
|
RCASE(0xAB, "stosWLQ Yvqp %rAX");
|
|
RCASE(0xAC, "lodsb %al Xb");
|
|
RCASE(0xAD, "lodsWLQ %rAX Xvqp");
|
|
RCASE(0xAE, "scasb %al Yb");
|
|
RCASE(0xAF, "scasWLQ %rAX Yvqp");
|
|
RCASE(0xB0 ... 0xb7, "mov %Zb Ib");
|
|
RCASE(0xB8 ... 0xbf, "movABS %Zvqp Ivqp");
|
|
RCASE(0xC0, "BIT Eb Ib");
|
|
RCASE(0xC1, "BIT Evqp Ib");
|
|
RCASE(0xC2, "ret Iw");
|
|
RCASE(0xC3, "ret");
|
|
RCASE(0xC4, "les %Gv Mp");
|
|
RCASE(0xC5, "lds %Gv Mp");
|
|
RCASE(0xC6, "mov Eb Ib");
|
|
RCASE(0xC7, "mov Evqp Ivds");
|
|
RCASE(0xC9, "leave");
|
|
RCASE(0xCA, "lret Iw");
|
|
RCASE(0xCB, "lret");
|
|
RCASE(0xCC, "int3");
|
|
RCASE(0xCD, "int Ib");
|
|
RCASE(0xD0, "BIT Eb $1");
|
|
RCASE(0xD1, "BIT Evqp $1");
|
|
RCASE(0xD2, "BIT Evqp %cl");
|
|
RCASE(0xD3, "BIT Evqp %cl");
|
|
RCASE(0xD4, x->op.uimm0 == 0x0a ? "aam" : "aam Ib");
|
|
RCASE(0xD5, x->op.uimm0 == 0x0a ? "aad" : "aad Ib");
|
|
RCASE(0xD6, "salc");
|
|
RCASE(0xD7, "xlat BBb");
|
|
RCASE(0xE0, "loopne Jbs");
|
|
RCASE(0xE1, "loope Jbs");
|
|
RCASE(0xE2, "loop Jbs");
|
|
RCASE(0xE3, "jcxz Jbs");
|
|
RCASE(0xE4, "in %al Ib");
|
|
RCASE(0xE5, "in %eAX Ib");
|
|
RCASE(0xE6, "out Ib %al");
|
|
RCASE(0xE7, "out Ib %eAX");
|
|
RCASE(0xE8, "call Jvds");
|
|
RCASE(0xE9, "jmp Jvds");
|
|
RCASE(0xEA, "ljmp Rvds Kvds");
|
|
RCASE(0xEB, "jmp Jbs");
|
|
RCASE(0xEC, "in %al %dx");
|
|
RCASE(0xED, "in %eAX %dx");
|
|
RCASE(0xEE, "out %dx %al");
|
|
RCASE(0xEF, "out %dx %eAX");
|
|
RCASE(0xF1, "int1");
|
|
RCASE(0xF4, "hlt");
|
|
RCASE(0xF5, "cmc");
|
|
RCASE(0xF8, "clc");
|
|
RCASE(0xF9, "stc");
|
|
RCASE(0xFA, "cli");
|
|
RCASE(0xFB, "sti");
|
|
RCASE(0xFC, "cld");
|
|
RCASE(0xFD, "std");
|
|
case 0x8F:
|
|
switch (ModrmReg(x->op.rde)) {
|
|
RCASE(0, "popWQ Evq");
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 0xD9:
|
|
switch (ModrmReg(x->op.rde)) {
|
|
RCASE(1, "fxch EST1");
|
|
RCASE(3, "fstps Msr %st");
|
|
RCASE(0, DisSpecRegMem(x, "fld EST", "flds Msr"));
|
|
RCASE(2, DisSpecRegMem(x, "fnop", "fsts Msr %st"));
|
|
RCASE(4, DisSpecRegMemFpu0(x, 1, "fldenv Me"));
|
|
RCASE(5, DisSpecRegMemFpu0(x, 2, "fldcw Mw"));
|
|
RCASE(6, DisSpecRegMemFpu0(x, 3, "fnstenv M"));
|
|
RCASE(7, DisSpecRegMemFpu0(x, 4, "fnstcw Mw"));
|
|
}
|
|
break;
|
|
case 0xDA:
|
|
switch (ModrmReg(x->op.rde)) {
|
|
RCASE(0, DisSpecRegMem(x, "fcmovb %st EST", "fiaddl Mdi"));
|
|
RCASE(1, DisSpecRegMem(x, "fcmove %st EST", "fimull Mdi"));
|
|
RCASE(2, DisSpecRegMem(x, "fcmovbe %st EST", "ficoml Mdi"));
|
|
RCASE(3, DisSpecRegMem(x, "fcmovu %st EST", "ficompl Mdi"));
|
|
RCASE(4, DisSpecRegMem(x, "fisubr Mdi", "fisubl Mdi"));
|
|
RCASE(5, DisSpecRegMem(x, "fucompp", "fisubrl Mdi"));
|
|
RCASE(6, DisSpecRegMem(x, "fidivl Mdi", "UNKNOWN"));
|
|
RCASE(7, DisSpecRegMem(x, "fidivrl Mdi", "UNKNOWN"));
|
|
}
|
|
break;
|
|
case 0xDB:
|
|
switch (ModrmReg(x->op.rde)) {
|
|
RCASE(0, DisSpecRegMem(x, "fcmovnb %st EST", "fildl Mdi"));
|
|
RCASE(1, DisSpecRegMem(x, "fcmovne %st EST", "fisttpl Mdi"));
|
|
RCASE(2, DisSpecRegMem(x, "fcmovnbe %st EST", "fistl Mdi"));
|
|
RCASE(3, DisSpecRegMem(x, "fcmovnu %st EST", "fistpl Mdi"));
|
|
RCASE(4, DisSpecFpu0(x, 5));
|
|
RCASE(5, DisSpecRegMem(x, "fucomi %st EST", "fldt Mer"));
|
|
RCASE(6, DisSpecRegMem(x, "fcomi %st EST", UNKNOWN));
|
|
RCASE(7, DisSpecRegMem(x, UNKNOWN, "fstpt Mer"));
|
|
}
|
|
break;
|
|
case 0xD8:
|
|
return DisOpFpu1(x, p, !IsModrmRegister(x->op.rde) ? "s Msr" : " EST1");
|
|
case 0xDC:
|
|
if (!IsModrmRegister(x->op.rde)) {
|
|
return DisOpFpu1(x, p, "l Mdr");
|
|
} else {
|
|
switch (ModrmReg(x->op.rde)) {
|
|
RCASE(0, "fadd EST %st");
|
|
RCASE(1, "fmul EST %st");
|
|
RCASE(2, "fcom %st EST");
|
|
RCASE(3, "fcomp %st EST");
|
|
RCASE(4, "fsub EST %st");
|
|
RCASE(5, "fsubr EST %st");
|
|
RCASE(6, "fdiv EST %st");
|
|
RCASE(7, "fdivr EST %st");
|
|
}
|
|
}
|
|
break;
|
|
case 0xDD:
|
|
if (!IsModrmRegister(x->op.rde)) {
|
|
switch (ModrmReg(x->op.rde)) {
|
|
RCASE(0, "fldl Mdr");
|
|
RCASE(1, "fisttpll Mqi");
|
|
RCASE(2, "fstl Mdr");
|
|
RCASE(3, "fstpl Mdr");
|
|
RCASE(4, "frstor Mdr");
|
|
RCASE(6, "fnsave Mst");
|
|
RCASE(7, "fnstsw Mst");
|
|
}
|
|
} else {
|
|
switch (ModrmReg(x->op.rde)) {
|
|
RCASE(0, "ffree EST");
|
|
RCASE(1, "fxch EST");
|
|
RCASE(2, "fst EST");
|
|
RCASE(3, "fstp EST");
|
|
RCASE(4, "fucom EST1");
|
|
RCASE(5, "fucomp EST1");
|
|
}
|
|
}
|
|
break;
|
|
case 0xDE:
|
|
if (!IsModrmRegister(x->op.rde)) {
|
|
switch (ModrmReg(x->op.rde)) {
|
|
RCASE(0, "fiadds Mwi");
|
|
RCASE(1, "fimuls Mwi");
|
|
RCASE(2, "ficoms Mwi");
|
|
RCASE(3, "ficomps Mwi");
|
|
RCASE(4, "fisubs Mwi");
|
|
RCASE(5, "fisubrs Mwi");
|
|
RCASE(6, "fidivs Mwi");
|
|
RCASE(7, "fidivrs Mwi");
|
|
}
|
|
} else {
|
|
switch (ModrmReg(x->op.rde)) {
|
|
RCASE(0, "faddp EST1");
|
|
RCASE(1, "fmulp EST1");
|
|
RCASE(2, "fcomp EST1");
|
|
RCASE(3, "fcompp");
|
|
RCASE(4, "fsubp EST1");
|
|
RCASE(5, "fsubrp EST1");
|
|
RCASE(6, "fdivp EST1");
|
|
RCASE(7, "fdivrp EST1");
|
|
}
|
|
}
|
|
break;
|
|
case 0xDF:
|
|
if (!IsModrmRegister(x->op.rde)) {
|
|
switch (ModrmReg(x->op.rde)) {
|
|
RCASE(0, "filds Mwi");
|
|
RCASE(1, "fisttps Mwi");
|
|
RCASE(2, "fists Mwi");
|
|
RCASE(3, "fistps Mwi");
|
|
RCASE(4, "fbld");
|
|
RCASE(5, "fildll Mqi");
|
|
RCASE(6, "fbstp");
|
|
RCASE(7, "fistpll Mqi");
|
|
}
|
|
} else {
|
|
switch (ModrmReg(x->op.rde)) {
|
|
RCASE(0, "ffreep EST");
|
|
RCASE(1, "fxch");
|
|
RCASE(2, "fstp EST");
|
|
RCASE(3, "fstp EST");
|
|
RCASE(4, "fnstsw");
|
|
RCASE(5, "fucomip EST");
|
|
RCASE(6, "fcomip EST");
|
|
}
|
|
}
|
|
break;
|
|
case 0xF6:
|
|
switch (ModrmReg(x->op.rde)) {
|
|
RCASE(0, "test Eb Ib");
|
|
RCASE(1, "test Eb Ib");
|
|
RCASE(2, "not Eb");
|
|
RCASE(3, "neg Eb");
|
|
RCASE(4, "mulb Eb");
|
|
RCASE(5, "imulb Eb");
|
|
RCASE(6, "divb Eb");
|
|
RCASE(7, "idivb Eb");
|
|
}
|
|
break;
|
|
case 0xF7:
|
|
switch (ModrmReg(x->op.rde)) {
|
|
RCASE(0, "test Evqp Ivds");
|
|
RCASE(1, "test Evqp Ivds");
|
|
RCASE(2, "not Evqp");
|
|
RCASE(3, "neg Evqp");
|
|
RCASE(4, "mul Evqp");
|
|
RCASE(5, "imul Evqp");
|
|
RCASE(6, "div Evqp");
|
|
RCASE(7, "idiv Evqp");
|
|
}
|
|
break;
|
|
case 0xFE:
|
|
switch (ModrmReg(x->op.rde)) {
|
|
RCASE(0, "inc Eb");
|
|
RCASE(1, "dec Eb");
|
|
}
|
|
break;
|
|
case 0xFF:
|
|
switch (ModrmReg(x->op.rde)) {
|
|
RCASE(0, "inc Evqp");
|
|
RCASE(1, "dec Evqp");
|
|
RCASE(2, "CALL Eq");
|
|
RCASE(4, "JMP Eq");
|
|
RCASE(6, "pushWQ Evq");
|
|
}
|
|
break;
|
|
}
|
|
return UNKNOWN;
|
|
}
|
|
|
|
const char *DisSpecMap1(struct XedDecodedInst *x, char *p) {
|
|
switch (x->op.opcode & 0xff) {
|
|
RCASE(0x05, "syscall");
|
|
RCASE(0x0B, "ud2");
|
|
RCASE(0x0D, "nop Ev");
|
|
RCASE(0x18, "nop Ev");
|
|
RCASE(0x19, "nop Ev");
|
|
RCASE(0x1A, "nop Ev");
|
|
RCASE(0x1B, "nop Ev");
|
|
RCASE(0x1C, "nop Ev");
|
|
RCASE(0x1D, "nop Ev");
|
|
RCASE(0x20, "mov %Hd %Cd");
|
|
RCASE(0x22, "mov %Cd %Hd");
|
|
RCASE(0x28, "movapSD %Vps Wps");
|
|
RCASE(0x29, "movapSD Wps %Vps");
|
|
RCASE(0x2B, "movntpSD Mps %Vps");
|
|
RCASE(0x2E, Osz(x->op.rde) ? "ucomisd %Vsd Wsd" : "ucomiss %Vss Wss");
|
|
RCASE(0x2F, Osz(x->op.rde) ? "comisd %Vsd Wsd" : "comiss %Vss Wss");
|
|
RCASE(0x31, "rdtsc");
|
|
RCASE(0x40 ... 0x4f, "cmovCC %Gvqp Evqp");
|
|
RCASE(0x52, DisOpVpsWpsVssWss(x, p, "rsqrt"));
|
|
RCASE(0x53, DisOpVpsWpsVssWss(x, p, "rcp"));
|
|
RCASE(0x54, DisOpVpdWpdVpsWps(x, p, "and"));
|
|
RCASE(0x55, DisOpVpdWpdVpsWps(x, p, "andn"));
|
|
RCASE(0x56, DisOpVpdWpdVpsWps(x, p, "or"));
|
|
RCASE(0x57, DisOpVpdWpdVpsWps(x, p, "xor"));
|
|
RCASE(0x58, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, "add"));
|
|
RCASE(0x59, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, "mul"));
|
|
RCASE(0x5C, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, "sub"));
|
|
RCASE(0x5D, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, "min"));
|
|
RCASE(0x5E, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, "div"));
|
|
RCASE(0x5F, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, "max"));
|
|
RCASE(0x60, DisOpPqQqVdqWdq(x, p, "punpcklbw"));
|
|
RCASE(0x61, DisOpPqQqVdqWdq(x, p, "punpcklwd"));
|
|
RCASE(0x62, DisOpPqQqVdqWdq(x, p, "punpckldq"));
|
|
RCASE(0x63, DisOpPqQqVdqWdq(x, p, "packsswb"));
|
|
RCASE(0x64, DisOpPqQqVdqWdq(x, p, "pcmpgtb"));
|
|
RCASE(0x65, DisOpPqQqVdqWdq(x, p, "pcmpgtw"));
|
|
RCASE(0x66, DisOpPqQqVdqWdq(x, p, "pcmpgtd"));
|
|
RCASE(0x67, DisOpPqQqVdqWdq(x, p, "packuswb"));
|
|
RCASE(0x68, DisOpPqQqVdqWdq(x, p, "punpckhbw"));
|
|
RCASE(0x69, DisOpPqQqVdqWdq(x, p, "punpckhwd"));
|
|
RCASE(0x6A, DisOpPqQqVdqWdq(x, p, "punpckhdq"));
|
|
RCASE(0x6B, DisOpPqQqVdqWdq(x, p, "packssdw"));
|
|
RCASE(0x6C, DisOpPqQqVdqWdq(x, p, "punpcklqdq"));
|
|
RCASE(0x6D, DisOpPqQqVdqWdq(x, p, "punpckhqdq"));
|
|
RCASE(0x74, DisOpPqQqVdqWdq(x, p, "pcmpeqb"));
|
|
RCASE(0x75, DisOpPqQqVdqWdq(x, p, "pcmpeqw"));
|
|
RCASE(0x76, DisOpPqQqVdqWdq(x, p, "pcmpeqd"));
|
|
RCASE(0x80 ... 0x8f, "jCC Jvds");
|
|
RCASE(0x90 ... 0x9f, "setCC Jvds");
|
|
RCASE(0xA0, "push %fs");
|
|
RCASE(0xA1, "pop %fs");
|
|
RCASE(0xA2, "cpuid");
|
|
RCASE(0xA3, "bt Evqp %Gvqp");
|
|
RCASE(0xA4, "shld Evqp %Gvqp Ib");
|
|
RCASE(0xA5, "shld Evqp %Gvqp %cl");
|
|
RCASE(0xA8, "push %gs");
|
|
RCASE(0xA9, "pop %gs");
|
|
RCASE(0xAB, "bts Evqp %Gvqp");
|
|
RCASE(0xAC, "shrd Evqp %Gvqp Ib");
|
|
RCASE(0xAD, "shrd Evqp %Gvqp %cl");
|
|
RCASE(0xAF, "imul %Gvqp Evqp");
|
|
RCASE(0xB0, "cmpxchg Eb %Gb");
|
|
RCASE(0xB1, "cmpxchg Evqp %Gvqp");
|
|
RCASE(0xB3, "btr Evqp %Gvqp");
|
|
RCASE(0xB6, "movzbWLQ %Gvqp Eb");
|
|
RCASE(0xB7, "movzwWLQ %Gvqp Ew");
|
|
RCASE(0xB9, "ud %Gvqp Evqp");
|
|
RCASE(0xBB, "btc Evqp %Gvqp");
|
|
RCASE(0xBC, "bsf %Gvqp Evqp");
|
|
RCASE(0xBD, "bsr %Gvqp Evqp");
|
|
RCASE(0xBE, "movsbWLQ %Gvqp Eb");
|
|
RCASE(0xBF, "movswWLQ %Gvqp Ew");
|
|
RCASE(0xC0, "xadd Eb %Gb");
|
|
RCASE(0xC1, "xadd Evqp %Gvqp");
|
|
RCASE(0xC2, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, "cmp"));
|
|
RCASE(0xC3, "movnti Mdqp %Gdqp");
|
|
RCASE(0xC8 ... 0xCF, "bswap %Zvqp");
|
|
RCASE(0xD1, DisOpPqQqVdqWdq(x, p, "psrlw"));
|
|
RCASE(0xD2, DisOpPqQqVdqWdq(x, p, "psrld"));
|
|
RCASE(0xD3, DisOpPqQqVdqWdq(x, p, "psrlq"));
|
|
RCASE(0xD4, DisOpPqQqVdqWdq(x, p, "paddq"));
|
|
RCASE(0xD5, DisOpPqQqVdqWdq(x, p, "pmullw"));
|
|
RCASE(0xD7, Osz(x->op.rde) ? "pmovmskb %Gdqp %Udq" : "pmovmskb %Gdqp %Nq");
|
|
RCASE(0xD8, DisOpPqQqVdqWdq(x, p, "psubusb"));
|
|
RCASE(0xD9, DisOpPqQqVdqWdq(x, p, "psubusw"));
|
|
RCASE(0xDA, DisOpPqQqVdqWdq(x, p, "pminub"));
|
|
RCASE(0xDB, DisOpPqQqVdqWdq(x, p, "pand"));
|
|
RCASE(0xDC, DisOpPqQqVdqWdq(x, p, "paddusb"));
|
|
RCASE(0xDD, DisOpPqQqVdqWdq(x, p, "paddusw"));
|
|
RCASE(0xDE, DisOpPqQqVdqWdq(x, p, "pmaxub"));
|
|
RCASE(0xDF, DisOpPqQqVdqWdq(x, p, "pandn"));
|
|
RCASE(0xE0, DisOpPqQqVdqWdq(x, p, "pavgb"));
|
|
RCASE(0xE1, DisOpPqQqVdqWdq(x, p, "psrawv"));
|
|
RCASE(0xE2, DisOpPqQqVdqWdq(x, p, "psradv"));
|
|
RCASE(0xE3, DisOpPqQqVdqWdq(x, p, "pavgw"));
|
|
RCASE(0xE4, DisOpPqQqVdqWdq(x, p, "pmulhuw"));
|
|
RCASE(0xE5, DisOpPqQqVdqWdq(x, p, "pmulhw"));
|
|
RCASE(0xE7, Osz(x->op.rde) ? "movntdq Mdq %Vdq" : "movntq Mq %Pq");
|
|
RCASE(0xE8, DisOpPqQqVdqWdq(x, p, "psubsb"));
|
|
RCASE(0xE9, DisOpPqQqVdqWdq(x, p, "psubsw"));
|
|
RCASE(0xEA, DisOpPqQqVdqWdq(x, p, "pminsw"));
|
|
RCASE(0xEB, DisOpPqQqVdqWdq(x, p, "por"));
|
|
RCASE(0xEC, DisOpPqQqVdqWdq(x, p, "paddsb"));
|
|
RCASE(0xED, DisOpPqQqVdqWdq(x, p, "paddsw"));
|
|
RCASE(0xEE, DisOpPqQqVdqWdq(x, p, "pmaxsw"));
|
|
RCASE(0xEF, DisOpPqQqVdqWdq(x, p, "pxor"));
|
|
RCASE(0xF0, "lddqu %Vdq Mdq");
|
|
RCASE(0xF1, DisOpPqQqVdqWdq(x, p, "psllwv"));
|
|
RCASE(0xF2, DisOpPqQqVdqWdq(x, p, "pslldv"));
|
|
RCASE(0xF3, DisOpPqQqVdqWdq(x, p, "psllqv"));
|
|
RCASE(0xF4, DisOpPqQqVdqWdq(x, p, "pmuludq"));
|
|
RCASE(0xF5, DisOpPqQqVdqWdq(x, p, "pmaddwd"));
|
|
RCASE(0xF6, DisOpPqQqVdqWdq(x, p, "psadbw"));
|
|
RCASE(0xF8, DisOpPqQqVdqWdq(x, p, "psubb"));
|
|
RCASE(0xF9, DisOpPqQqVdqWdq(x, p, "psubw"));
|
|
RCASE(0xFA, DisOpPqQqVdqWdq(x, p, "psubd"));
|
|
RCASE(0xFB, DisOpPqQqVdqWdq(x, p, "psubq"));
|
|
RCASE(0xFC, DisOpPqQqVdqWdq(x, p, "paddb"));
|
|
RCASE(0xFD, DisOpPqQqVdqWdq(x, p, "paddw"));
|
|
RCASE(0xFE, DisOpPqQqVdqWdq(x, p, "paddd"));
|
|
RCASE(0xFF, "ud0 %Gvqp Evqp");
|
|
case 0x01:
|
|
if (ModrmMod(x->op.rde) == 0b11 && ModrmReg(x->op.rde) == 0b111 &&
|
|
ModrmRm(x->op.rde) == 0b001) {
|
|
return "rdtscp";
|
|
} else if (!IsModrmRegister(x->op.rde) && ModrmReg(x->op.rde) == 0) {
|
|
return "sgdt Ms";
|
|
} else if (!IsModrmRegister(x->op.rde) && ModrmReg(x->op.rde) == 2) {
|
|
return "lgdt Ms";
|
|
} else {
|
|
return UNKNOWN;
|
|
}
|
|
break;
|
|
case 0x1F:
|
|
if (ModrmMod(x->op.rde) == 1 && ModrmReg(x->op.rde) == 0 &&
|
|
ModrmRm(x->op.rde) == 0b101) {
|
|
return "bofram Jb";
|
|
} else {
|
|
return "nop Ev";
|
|
}
|
|
break;
|
|
case 0x70:
|
|
switch (Rep(x->op.rde) | Osz(x->op.rde)) {
|
|
RCASE(0, "pshufw %Pq Qq Ib");
|
|
RCASE(1, "pshufd %Vdq Wdq Ib");
|
|
RCASE(2, "pshuflw %Vdq Wdq Ib");
|
|
RCASE(3, "pshufhw %Vdq Wdq Ib");
|
|
}
|
|
break;
|
|
case 0x71:
|
|
switch (ModrmReg(x->op.rde)) {
|
|
RCASE(2, DisOpNqIbUdqIb(x, p, "psrlw"));
|
|
RCASE(4, DisOpNqIbUdqIb(x, p, "psraw"));
|
|
RCASE(6, DisOpNqIbUdqIb(x, p, "psllw"));
|
|
}
|
|
break;
|
|
case 0x72:
|
|
switch (ModrmReg(x->op.rde)) {
|
|
RCASE(2, DisOpNqIbUdqIb(x, p, "psrld"));
|
|
RCASE(4, DisOpNqIbUdqIb(x, p, "psrad"));
|
|
RCASE(6, DisOpNqIbUdqIb(x, p, "pslld"));
|
|
}
|
|
break;
|
|
case 0x73:
|
|
switch (ModrmReg(x->op.rde)) {
|
|
RCASE(2, DisOpNqIbUdqIb(x, p, "psrlq"));
|
|
RCASE(3, DisOpNqIbUdqIb(x, p, "psrldq"));
|
|
RCASE(6, DisOpNqIbUdqIb(x, p, "psllq"));
|
|
RCASE(7, DisOpNqIbUdqIb(x, p, "pslldq"));
|
|
}
|
|
break;
|
|
case 0xAE:
|
|
switch (ModrmReg(x->op.rde)) {
|
|
RCASE(0, "fxsave Mstx %st %st(1)");
|
|
RCASE(1, "fxrstor Mstx %st %st(1)");
|
|
RCASE(2, "ldmxcsr Md");
|
|
RCASE(3, "stmxcsr Md");
|
|
RCASE(4, "xsave M %edx %eax");
|
|
RCASE(5, "lfence");
|
|
RCASE(6, "mfence");
|
|
case 7:
|
|
if (ModrmMod(x->op.rde) == 0b11 && ModrmReg(x->op.rde) == 0b111) {
|
|
return "sfence";
|
|
} else {
|
|
return "clflush";
|
|
}
|
|
}
|
|
break;
|
|
case 0xBA:
|
|
switch (ModrmReg(x->op.rde)) {
|
|
RCASE(4, "btWLQ Evqp Ib");
|
|
RCASE(5, "btsWLQ Evqp Ib");
|
|
RCASE(6, "btrWLQ Evqp Ib");
|
|
RCASE(7, "btcWLQ Evqp Ib");
|
|
}
|
|
break;
|
|
case 0x10:
|
|
if (Rep(x->op.rde) == 3) {
|
|
return "movss %Vss Wss";
|
|
} else if (Rep(x->op.rde) == 2) {
|
|
return "movsd %Vsd Wsd";
|
|
} else if (Osz(x->op.rde)) {
|
|
return "movupd %Vpd Wpd";
|
|
} else {
|
|
return "movups %Vps Wps";
|
|
}
|
|
break;
|
|
case 0x11:
|
|
if (Rep(x->op.rde) == 3) {
|
|
return "movss Wss %Vss";
|
|
} else if (Rep(x->op.rde) == 2) {
|
|
return "movsd Wsd %Vsd";
|
|
} else if (Osz(x->op.rde)) {
|
|
return "movupd Wpd %Vpd";
|
|
} else {
|
|
return "movups Wps %Vps";
|
|
}
|
|
break;
|
|
case 0xC4:
|
|
if (!Osz(x->op.rde)) {
|
|
if (IsModrmRegister(x->op.rde)) {
|
|
return "pinsrw %Pq %Rdqp Ib";
|
|
} else {
|
|
return "pinsrw %Pq Mw Ib";
|
|
}
|
|
} else {
|
|
if (IsModrmRegister(x->op.rde)) {
|
|
return "pinsrw %Vdq %Rdqp Ib";
|
|
} else {
|
|
return "pinsrw %Vdq Mw Ib";
|
|
}
|
|
}
|
|
break;
|
|
case 0xC5:
|
|
if (!Osz(x->op.rde)) {
|
|
return "pextrw %Gdqp %Nq Ib";
|
|
} else {
|
|
return "pextrw %Gdqp %Udq Ib";
|
|
}
|
|
break;
|
|
case 0xC6:
|
|
if (!Osz(x->op.rde)) {
|
|
return "shufps %Vps Wps Ib";
|
|
} else {
|
|
return "shufpd %Vpd Wpd Ib";
|
|
}
|
|
break;
|
|
case 0xC7:
|
|
if (Rexw(x->op.rde)) {
|
|
return "cmpxchg16b Mdq";
|
|
} else {
|
|
return "cmpxchg8b Mq";
|
|
}
|
|
break;
|
|
case 0xD6:
|
|
if (Osz(x->op.rde)) {
|
|
return "movq Wq %Vq";
|
|
} else if (Rep(x->op.rde) == 3) {
|
|
return "movq2dq %Vdq %Nq";
|
|
} else if (Rep(x->op.rde) == 2) {
|
|
return "movq2dq %Pq %Uq";
|
|
}
|
|
break;
|
|
case 0x12:
|
|
switch (Rep(x->op.rde) | Osz(x->op.rde)) {
|
|
case 0:
|
|
if (IsModrmRegister(x->op.rde)) {
|
|
return "movhlps %Vq %Uq";
|
|
} else {
|
|
return "movlps %Vq Mq";
|
|
}
|
|
break;
|
|
case 1:
|
|
return "movlpd %Vq Mq";
|
|
case 2:
|
|
return "movddup %Vq Wq";
|
|
case 3:
|
|
return "movsldup %Vq Wq";
|
|
default:
|
|
unreachable;
|
|
}
|
|
break;
|
|
case 0x13:
|
|
if (Osz(x->op.rde)) {
|
|
return "movlpd Mq %Vq";
|
|
} else {
|
|
return "movlps Mq %Vq";
|
|
}
|
|
break;
|
|
case 0x16:
|
|
switch (Rep(x->op.rde) | Osz(x->op.rde)) {
|
|
case 0:
|
|
if (IsModrmRegister(x->op.rde)) {
|
|
return "movlhps %Vq %Uq";
|
|
} else {
|
|
return "movhps %Vq Mq";
|
|
}
|
|
break;
|
|
case 1:
|
|
return "movhpd %Vq Mq";
|
|
case 3:
|
|
return "movshdup %Vq Wq";
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 0x17:
|
|
if (Osz(x->op.rde)) {
|
|
return "movhpd Mq %Vq";
|
|
} else {
|
|
return "movhps Mq %Vq";
|
|
}
|
|
break;
|
|
case 0x2A:
|
|
if (Rep(x->op.rde) == 3) {
|
|
return "cvtsi2ss %Vss Edqp";
|
|
} else if (Rep(x->op.rde) == 2) {
|
|
return "cvtsi2sd %Vsd Edqp";
|
|
} else if (Osz(x->op.rde)) {
|
|
return "cvtpi2pd %Vpd Qpi";
|
|
} else {
|
|
return "cvtpi2ps %Vps Qpi";
|
|
}
|
|
break;
|
|
case 0x2C:
|
|
if (Rep(x->op.rde) == 3) {
|
|
return "cvttss2si %Gdqp Wss";
|
|
} else if (Rep(x->op.rde) == 2) {
|
|
return "cvttsd2si %Gdqp Wsd";
|
|
} else if (Osz(x->op.rde)) {
|
|
return "cvttpd2pi %Ppi Wpd";
|
|
} else {
|
|
return "cvttps2pi %Ppi Wpsq";
|
|
}
|
|
break;
|
|
case 0x2D:
|
|
if (Rep(x->op.rde) == 3) {
|
|
return "cvtss2si %Gdqp Wss";
|
|
} else if (Rep(x->op.rde) == 2) {
|
|
return "cvtsd2si %Gdqp Wsd";
|
|
} else if (Osz(x->op.rde)) {
|
|
return "cvtpd2pi %Ppi Wpd";
|
|
} else {
|
|
return "cvtps2pi %Ppi Wpsq";
|
|
}
|
|
break;
|
|
case 0x5a:
|
|
if (Rep(x->op.rde) == 3) {
|
|
return "cvtss2sd %Vsd Wss";
|
|
} else if (Rep(x->op.rde) == 2) {
|
|
return "cvtsd2ss %Vss Wsd";
|
|
} else if (Osz(x->op.rde)) {
|
|
return "cvtpd2ps %Vps Wpd";
|
|
} else {
|
|
return "cvtps2pd %Vpd Wps";
|
|
}
|
|
break;
|
|
case 0x5b:
|
|
if (Rep(x->op.rde) == 3) {
|
|
return "cvttps2dq %Vdq Wps";
|
|
} else if (Osz(x->op.rde)) {
|
|
return "cvtps2dq %Vdq Wps";
|
|
} else {
|
|
return "cvtdq2ps %Vps Wdq";
|
|
}
|
|
break;
|
|
case 0x51:
|
|
if (Rep(x->op.rde) == 3) {
|
|
return "sqrtss %Vss Wss";
|
|
} else if (Rep(x->op.rde) == 2) {
|
|
return "sqrtsd %Vsd Wsd";
|
|
} else if (Osz(x->op.rde)) {
|
|
return "sqrtpd %Vpd Wpd";
|
|
} else {
|
|
return "sqrtps %Vps Wps";
|
|
}
|
|
break;
|
|
case 0x6E:
|
|
if (Osz(x->op.rde)) {
|
|
if (Rexw(x->op.rde)) {
|
|
return "movq %Vdq Eqp";
|
|
} else {
|
|
return "movd %Vdq Ed";
|
|
}
|
|
} else {
|
|
if (Rexw(x->op.rde)) {
|
|
return "movq %Pq Eqp";
|
|
} else {
|
|
return "movd %Pq Ed";
|
|
}
|
|
}
|
|
break;
|
|
case 0x6F:
|
|
if (Rep(x->op.rde) == 3) {
|
|
return "movdqu %Vdq Wdq";
|
|
} else if (Osz(x->op.rde)) {
|
|
return "movdqa %Vdq Wdq";
|
|
} else {
|
|
return "movq %Pq Qq";
|
|
}
|
|
break;
|
|
case 0x7E:
|
|
if (Rep(x->op.rde) == 3) {
|
|
return "movq %Vq Wq";
|
|
} else if (Osz(x->op.rde)) {
|
|
if (Rexw(x->op.rde)) {
|
|
return "movq Eqp %Vdq";
|
|
} else {
|
|
return "movd Ed %Vdq";
|
|
}
|
|
} else {
|
|
if (Rexw(x->op.rde)) {
|
|
return "movq Eqp %Pq";
|
|
} else {
|
|
return "movd Ed %Pq";
|
|
}
|
|
}
|
|
break;
|
|
case 0x7F:
|
|
if (Rep(x->op.rde) == 3) {
|
|
return "movdqu Wdq %Vdq";
|
|
} else if (Osz(x->op.rde)) {
|
|
return "movdqa Wdq %Vdq";
|
|
} else {
|
|
return "movq Qq %Pq";
|
|
}
|
|
break;
|
|
case 0xE6:
|
|
if (Rep(x->op.rde) == 2) {
|
|
return "cvtpd2dq %Vdq Wpd";
|
|
} else if (Osz(x->op.rde)) {
|
|
return "cvttpd2dq %Vdq Wpd";
|
|
} else if (Rep(x->op.rde) == 3) {
|
|
return "cvtdq2pd %Vpd Wdq";
|
|
}
|
|
break;
|
|
}
|
|
return UNKNOWN;
|
|
}
|
|
|
|
const char *DisSpecMap2(struct XedDecodedInst *x, char *p) {
|
|
switch (x->op.opcode & 0xff) {
|
|
RCASE(0x00, DisOpPqQqVdqWdq(x, p, "pshufb"));
|
|
RCASE(0x01, DisOpPqQqVdqWdq(x, p, "phaddw"));
|
|
RCASE(0x02, DisOpPqQqVdqWdq(x, p, "phaddd"));
|
|
RCASE(0x03, DisOpPqQqVdqWdq(x, p, "phaddsw"));
|
|
RCASE(0x04, DisOpPqQqVdqWdq(x, p, "pmaddubsw"));
|
|
RCASE(0x05, DisOpPqQqVdqWdq(x, p, "phsubw"));
|
|
RCASE(0x06, DisOpPqQqVdqWdq(x, p, "phsubd"));
|
|
RCASE(0x07, DisOpPqQqVdqWdq(x, p, "phsubsw"));
|
|
RCASE(0x08, DisOpPqQqVdqWdq(x, p, "psignb"));
|
|
RCASE(0x09, DisOpPqQqVdqWdq(x, p, "psignw"));
|
|
RCASE(0x0A, DisOpPqQqVdqWdq(x, p, "psignd"));
|
|
RCASE(0x0B, DisOpPqQqVdqWdq(x, p, "pmulhrsw"));
|
|
RCASE(0x10, "pblendvb %Vdq Wdq");
|
|
RCASE(0x14, "blendvps Vps Wps");
|
|
RCASE(0x15, "blendvpd Vpd Wpd");
|
|
RCASE(0x17, "ptest %Vdq Wdq");
|
|
RCASE(0x1C, DisOpPqQqVdqWdq(x, p, "pabsb"));
|
|
RCASE(0x1D, DisOpPqQqVdqWdq(x, p, "pabsw"));
|
|
RCASE(0x1E, DisOpPqQqVdqWdq(x, p, "pabsd"));
|
|
RCASE(0x20, "pmovsxbw %Vdq Mq");
|
|
RCASE(0x21, "pmovsxbd %Vdq Md");
|
|
RCASE(0x22, "pmovsxbq %Vdq Mw");
|
|
RCASE(0x23, "pmovsxwd %Vdq Mq");
|
|
RCASE(0x24, "pmovsxwq %Vdq Md");
|
|
RCASE(0x25, "pmovsxdq %Vdq Mq");
|
|
RCASE(0x28, "pmuldq %Vdq Wdq");
|
|
RCASE(0x29, "pcmpeqq %Vdq Wdq");
|
|
RCASE(0x2A, "movntdqa %Vdq Mdq");
|
|
RCASE(0x2B, "packusdw %Vdq Wdq");
|
|
RCASE(0x30, "pmovzxbw %Vdq Mq");
|
|
RCASE(0x31, "pmovzxbd %Vdq Md");
|
|
RCASE(0x32, "pmovzxbq %Vdq Mw");
|
|
RCASE(0x33, "pmovzxwd %Vdq Mq");
|
|
RCASE(0x34, "pmovzxwq %Vdq Md");
|
|
RCASE(0x35, "pmovzxdq %Vdq Mq");
|
|
RCASE(0x37, "pcmpgtq %Vdq Wdq");
|
|
RCASE(0x38, "pminsb %Vdq Wdq");
|
|
RCASE(0x39, "pminsd %Vdq Wdq");
|
|
RCASE(0x3A, "pminuw %Vdq Wdq");
|
|
RCASE(0x3B, "pminud %Vdq Wdq");
|
|
RCASE(0x3C, "pmaxsb %Vdq Wdq");
|
|
RCASE(0x3D, "pmaxsd %Vdq Wdq");
|
|
RCASE(0x3E, "pmaxuw %Vdq Wdq");
|
|
RCASE(0x3F, "pmaxud %Vdq Wdq");
|
|
RCASE(0x40, "pmulld %Vdq Wdq");
|
|
RCASE(0x41, "phminposuw %Vdq Wdq");
|
|
RCASE(0x80, "invept %Gq Mdq");
|
|
RCASE(0x81, "invvpid %Gq Mdq");
|
|
default:
|
|
return UNKNOWN;
|
|
}
|
|
}
|
|
|
|
const char *DisSpecMap3(struct XedDecodedInst *x, char *p) {
|
|
switch (x->op.opcode & 0xff) {
|
|
RCASE(0x0F, DisOpPqQqIbVdqWdqIb(x, p, "palignr"));
|
|
default:
|
|
return UNKNOWN;
|
|
}
|
|
}
|
|
|
|
const char *DisSpec(struct XedDecodedInst *x, char *p) {
|
|
switch (x->op.map & 7) {
|
|
case XED_ILD_MAP0:
|
|
return DisSpecMap0(x, p);
|
|
case XED_ILD_MAP1:
|
|
return DisSpecMap1(x, p);
|
|
case XED_ILD_MAP2:
|
|
return DisSpecMap2(x, p);
|
|
case XED_ILD_MAP3:
|
|
return DisSpecMap3(x, p);
|
|
default:
|
|
return UNKNOWN;
|
|
}
|
|
}
|