aboutsummaryrefslogtreecommitdiffhomepage
path: root/externals/xbyak/gen/gen_code.cpp
diff options
context:
space:
mode:
authorMerry <[email protected]>2024-01-30 00:36:49 +0000
committerMerry <[email protected]>2024-01-30 00:39:19 +0000
commit213fe7a4526c529f0df8b2e14aa508159774da2c (patch)
treecd74e0cb02d4184130c0f627afb1cca635c75e8f /externals/xbyak/gen/gen_code.cpp
parent85177518d755f60f3fa812b36dc0deadffabaa4e (diff)
parentfdf626b74f35deedce0e6196c36b8c9f846c038a (diff)
downloaddynarmic-213fe7a4526c529f0df8b2e14aa508159774da2c.tar.gz
dynarmic-213fe7a4526c529f0df8b2e14aa508159774da2c.zip
externals: Update xbyak to v7.05
Merge commit 'fdf626b74f35deedce0e6196c36b8c9f846c038a'
Diffstat (limited to 'externals/xbyak/gen/gen_code.cpp')
-rw-r--r--externals/xbyak/gen/gen_code.cpp772
1 files changed, 457 insertions, 315 deletions
diff --git a/externals/xbyak/gen/gen_code.cpp b/externals/xbyak/gen/gen_code.cpp
index 95680536..3959cc5e 100644
--- a/externals/xbyak/gen/gen_code.cpp
+++ b/externals/xbyak/gen/gen_code.cpp
@@ -48,7 +48,7 @@ void putX_X_XM(bool omitOnly)
const struct Tbl {
uint8_t code;
const char *name;
- int type;
+ uint64_t type;
bool hasIMM;
bool enableOmit;
int mode; // 1 : sse, 2 : avx, 3 : sse + avx
@@ -208,10 +208,15 @@ void putX_X_XM(bool omitOnly)
{ 0xCF, "gf2p8affineinvqb", T_66 | T_0F3A | T_W1 | T_EVEX | T_YMM | T_EW1 | T_SAE_Z | T_B64, true, false, 3 },
{ 0xCE, "gf2p8affineqb", T_66 | T_0F3A | T_W1 | T_EVEX | T_YMM | T_EW1 | T_SAE_Z | T_B64, true, false, 3 },
{ 0xCF, "gf2p8mulb", T_66 | T_0F38 | T_W0 | T_EVEX | T_YMM | T_EW0 | T_SAE_Z, false, false, 3 },
+ { 0xDA, "sm3msg1", T_0F38 | T_W0 | T_EVEX | T_EW0, false, false, 2 },
+ { 0xDA, "sm3msg2", T_66 | T_0F38 | T_W0 | T_EVEX | T_EW0, false, false, 2 },
+ { 0xDE, "sm3rnds2", T_66 | T_0F3A | T_W0 | T_EVEX | T_EW0, true, false, 2 },
+ { 0xDA, "sm4key4", T_F3 | T_0F38 | T_W0 | T_EVEX | T_EW0, false, false, 2 },
+ { 0xDA, "sm4rnds4", T_F2 | T_0F38 | T_W0 | T_EVEX | T_EW0, false, false, 2 },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- std::string type = type2String(p->type);
+ std::string s = type2String(p->type);
if (omitOnly) {
if (p->enableOmit) {
printf("void v%s(const Xmm& x, const Operand& op%s) { v%s(x, x, op%s); }\n", p->name, p->hasIMM ? ", uint8_t imm" : "", p->name, p->hasIMM ? ", imm" : "");
@@ -219,35 +224,32 @@ void putX_X_XM(bool omitOnly)
} else {
if (p->mode & 1) {
if (p->hasIMM) {
- printf("void %s(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x%02X, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); }\n", p->name, p->code);
+ printf("void %s(const Xmm& xmm, const Operand& op, int imm) { opSSE(xmm, op, T_66 | T_0F3A, 0x%02X, isXMM_XMMorMEM, static_cast<uint8_t>(imm)); }\n", p->name, p->code);
} else {
- printf("void %s(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x%02X, 0x66, isXMM_XMMorMEM, NONE, 0x38); }\n", p->name, p->code);
+ printf("void %s(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_66 | T_0F38, 0x%02X, isXMM_XMMorMEM); }\n", p->name, p->code);
}
}
if (p->mode & 2) {
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"
- , p->name, p->hasIMM ? ", uint8_t imm" : "", type.c_str(), p->code, p->hasIMM ? ", imm" : "");
+ , p->name, p->hasIMM ? ", uint8_t imm" : "", s.c_str(), p->code, p->hasIMM ? ", imm" : "");
}
}
}
}
}
-void putMemOp(const char *name, uint8_t prefix, uint8_t ext, uint8_t code1, int code2, int bit = 32)
+void putMemOp(const char *name, const char *type, uint8_t ext, uint8_t code, int bit, int fwait = false)
{
- printf("void %s(const Address& addr) { ", name);
- if (prefix) printf("db(0x%02X); ", prefix);
- printf("opModM(addr, Reg%d(%d), 0x%02X, 0x%02X); }\n", bit, ext, code1, code2);
+ printf("void %s(const Address& addr) { %sopMR(addr, Reg%d(%d), %s, 0x%02X); }\n", name, fwait ? "db(0x9B); " : "", bit, ext, type, code);
}
-void putLoadSeg(const char *name, uint8_t code1, int code2 = NONE)
+void putLoadSeg(const char *name, uint64_t type, uint8_t code)
{
- printf("void %s(const Reg& reg, const Address& addr) { opLoadSeg(addr, reg, 0x%02X, 0x%02X); }\n", name, code1, code2);
+ printf("void %s(const Reg& reg, const Address& addr) { opLoadSeg(addr, reg, %s, 0x%02X); }\n", name, type ? "T_0F" : "T_NONE", code);
}
void put()
{
- const int NO = CodeGenerator::NONE;
{
char buf[16];
unsigned int v = VERSION;
@@ -378,43 +380,40 @@ void put()
{
const struct Tbl {
- uint8_t code;
- uint8_t pref;
+ const char *pref;
const char *name;
} tbl[] = {
- { 0x70, 0, "pshufw" },
- { 0x70, 0xF2, "pshuflw" },
- { 0x70, 0xF3, "pshufhw" },
- { 0x70, 0x66, "pshufd" },
+ { "T_NONE", "pshufw" },
+ { "T_F2", "pshuflw" },
+ { "T_F3", "pshufhw" },
+ { "T_66", "pshufd" },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- printf("void %s(const Mmx& mmx, const Operand& op, uint8_t imm8) { opMMX(mmx, op, 0x%02X, 0x%02X, imm8); }\n", p->name, p->code, p->pref);
+ printf("void %s(const Mmx& mmx, const Operand& op, uint8_t imm8) { opMMX(mmx, op, 0x70, T_0F, %s, imm8); }\n", p->name, p->pref);
}
}
{
const struct MmxTbl6 {
uint8_t code; // for (reg, reg/[mem])
uint8_t code2; // for ([mem], reg)
- int pref;
+ const char *pref;
const char *name;
} mmxTbl6[] = {
- { 0x6F, 0x7F, 0x66, "movdqa" },
- { 0x6F, 0x7F, 0xF3, "movdqu" },
+ { 0x6F, 0x7F, "T_66", "movdqa" },
+ { 0x6F, 0x7F, "T_F3", "movdqu" },
// SSE2
- { 0x28, 0x29, NO, "movaps" },
- { 0x10, 0x11, 0xF3, "movss" },
- { 0x10, 0x11, NO, "movups" },
- { 0x28, 0x29, 0x66, "movapd" },
- { 0x10, 0x11, 0xF2, "movsd" },
- { 0x10, 0x11, 0x66, "movupd" },
+ { 0x28, 0x29, "T_NONE", "movaps" },
+ { 0x10, 0x11, "T_F3", "movss" },
+ { 0x10, 0x11, "T_NONE", "movups" },
+ { 0x28, 0x29, "T_66", "movapd" },
+ { 0x10, 0x11, "T_F2", "movsd" },
+ { 0x10, 0x11, "T_66", "movupd" },
};
for (size_t i = 0; i < NUM_OF_ARRAY(mmxTbl6); i++) {
const MmxTbl6 *p = &mmxTbl6[i];
- printf("void %s(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x%02X, 0x%02X); }\n", p->name, p->code, p->pref);
- printf("void %s(const Address& addr, const Xmm& xmm) { ", p->name);
- if (p->pref != NO) printf("db(0x%02X); ", p->pref);
- printf("opModM(addr, xmm, 0x0F, 0x%02X); }\n", p->code2);
+ printf("void %s(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x%02X, T_0F, %s); }\n", p->name, p->code, p->pref);
+ printf("void %s(const Address& addr, const Xmm& xmm) { opMR(addr, xmm, T_0F|%s, 0x%02X); }\n", p->name, p->pref, p->code2);
}
}
{
@@ -425,13 +424,13 @@ void put()
SD = 1 << 3
};
const struct {
- int code;
+ const char *type;
const char *name;
} sufTbl[] = {
- { NO, "ps" },
- { 0xF3, "ss" },
- { 0x66, "pd" },
- { 0xF2, "sd" },
+ { "T_0F", "ps" },
+ { "T_0F | T_F3", "ss" },
+ { "T_0F | T_66", "pd" },
+ { "T_0F | T_F2", "sd" },
};
const struct Tbl {
uint8_t code;
@@ -464,9 +463,9 @@ void put()
if (!(p->mode & (1 << j))) continue;
if (p->hasImm) {
// don't change uint8_t to int because NO is not in byte
- printf("void %s%s(const Xmm& xmm, const Operand& op, uint8_t imm8) { opGen(xmm, op, 0x%2X, 0x%02X, isXMM_XMMorMEM, imm8); }\n", p->name, sufTbl[j].name, p->code, sufTbl[j].code);
+ printf("void %s%s(const Xmm& xmm, const Operand& op, uint8_t imm8) { opSSE(xmm, op, %s, 0x%02X, isXMM_XMMorMEM, imm8); }\n", p->name, sufTbl[j].name, sufTbl[j].type, p->code);
} else {
- 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);
+ printf("void %s%s(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, %s, 0x%02X, isXMM_XMMorMEM); }\n", p->name, sufTbl[j].name, sufTbl[j].type, p->code);
}
}
}
@@ -474,77 +473,77 @@ void put()
{
// (XMM, XMM)
const struct Tbl {
+ uint64_t type;
uint8_t code;
- uint8_t pref;
const char *name;
} tbl[] = {
- { 0xF7, 0x66, "maskmovdqu" },
- { 0x12, 0 , "movhlps" },
- { 0x16, 0 , "movlhps" },
+ { T_66 | T_0F, 0xF7, "maskmovdqu" },
+ { T_0F, 0x12, "movhlps" },
+ { T_0F, 0x16, "movlhps" },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- printf("void %s(const Xmm& reg1, const Xmm& reg2) { ", p->name);
- if (p->pref) printf("db(0x%02X); ", p->pref);
- printf(" opModR(reg1, reg2, 0x0F, 0x%02X); }\n", p->code);
+ std::string s = type2String(p->type);
+ printf("void %s(const Xmm& reg1, const Xmm& reg2) { opRR(reg1, reg2, %s, 0x%02X); }\n", p->name, s.c_str(), p->code);
}
}
{
// (XMM, XMM|MEM)
const struct Tbl {
uint8_t code;
- int pref;
+ uint64_t type;
const char *name;
} tbl[] = {
- { 0x6D, 0x66, "punpckhqdq" },
- { 0x6C, 0x66, "punpcklqdq" },
-
- { 0x2F, NO , "comiss" },
- { 0x2E, NO , "ucomiss" },
- { 0x2F, 0x66, "comisd" },
- { 0x2E, 0x66, "ucomisd" },
-
- { 0x5A, 0x66, "cvtpd2ps" },
- { 0x5A, NO , "cvtps2pd" },
- { 0x5A, 0xF2, "cvtsd2ss" },
- { 0x5A, 0xF3, "cvtss2sd" },
- { 0xE6, 0xF2, "cvtpd2dq" },
- { 0xE6, 0x66, "cvttpd2dq" },
- { 0xE6, 0xF3, "cvtdq2pd" },
- { 0x5B, 0x66, "cvtps2dq" },
- { 0x5B, 0xF3, "cvttps2dq" },
- { 0x5B, NO , "cvtdq2ps" },
+ { 0x6D, T_66, "punpckhqdq" },
+ { 0x6C, T_66, "punpcklqdq" },
+
+ { 0x2F, T_NONE, "comiss" },
+ { 0x2E, T_NONE, "ucomiss" },
+ { 0x2F, T_66, "comisd" },
+ { 0x2E, T_66, "ucomisd" },
+
+ { 0x5A, T_66, "cvtpd2ps" },
+ { 0x5A, T_NONE, "cvtps2pd" },
+ { 0x5A, T_F2, "cvtsd2ss" },
+ { 0x5A, T_F3, "cvtss2sd" },
+ { 0xE6, T_F2, "cvtpd2dq" },
+ { 0xE6, T_66, "cvttpd2dq" },
+ { 0xE6, T_F3, "cvtdq2pd" },
+ { 0x5B, T_66, "cvtps2dq" },
+ { 0x5B, T_F3, "cvttps2dq" },
+ { 0x5B, T_NONE, "cvtdq2ps" },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- 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);
+ std::string s = type2String(p->type | T_0F);
+ printf("void %s(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, %s, 0x%02X, isXMM_XMMorMEM); }\n", p->name, s.c_str(), p->code);
}
}
-
{
// special type
const struct Tbl {
uint8_t code;
- int pref;
+ uint64_t type;
const char *name;
const char *cond;
} tbl[] = {
- { 0x2A, NO , "cvtpi2ps", "isXMM_MMXorMEM" },
- { 0x2D, NO , "cvtps2pi", "isMMX_XMMorMEM" },
- { 0x2A, 0xF3, "cvtsi2ss", "isXMM_REG32orMEM" },
- { 0x2D, 0xF3, "cvtss2si", "isREG32_XMMorMEM" },
- { 0x2C, NO , "cvttps2pi", "isMMX_XMMorMEM" },
- { 0x2C, 0xF3, "cvttss2si", "isREG32_XMMorMEM" },
- { 0x2A, 0x66, "cvtpi2pd", "isXMM_MMXorMEM" },
- { 0x2D, 0x66, "cvtpd2pi", "isMMX_XMMorMEM" },
- { 0x2A, 0xF2, "cvtsi2sd", "isXMM_REG32orMEM" },
- { 0x2D, 0xF2, "cvtsd2si", "isREG32_XMMorMEM" },
- { 0x2C, 0x66, "cvttpd2pi", "isMMX_XMMorMEM" },
- { 0x2C, 0xF2, "cvttsd2si", "isREG32_XMMorMEM" },
+ { 0x2A, T_NONE , "cvtpi2ps", "isXMM_MMXorMEM" },
+ { 0x2D, T_NONE , "cvtps2pi", "isMMX_XMMorMEM" },
+ { 0x2A, T_F3, "cvtsi2ss", "isXMM_REG32orMEM" },
+ { 0x2D, T_F3, "cvtss2si", "isREG32_XMMorMEM" },
+ { 0x2C, T_NONE , "cvttps2pi", "isMMX_XMMorMEM" },
+ { 0x2C, T_F3, "cvttss2si", "isREG32_XMMorMEM" },
+ { 0x2A, T_66, "cvtpi2pd", "isXMM_MMXorMEM" },
+ { 0x2D, T_66, "cvtpd2pi", "isMMX_XMMorMEM" },
+ { 0x2A, T_F2, "cvtsi2sd", "isXMM_REG32orMEM" },
+ { 0x2D, T_F2, "cvtsd2si", "isREG32_XMMorMEM" },
+ { 0x2C, T_66, "cvttpd2pi", "isMMX_XMMorMEM" },
+ { 0x2C, T_F2, "cvttsd2si", "isREG32_XMMorMEM" },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- 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);
+ std::string s = type2String(p->type | T_0F);
+ printf("void %s(const Reg& reg, const Operand& op) { opSSE(reg, op, %s, 0x%02X, %s); }\n", p->name, s.c_str(), p->code, p->cond);
}
}
{
@@ -565,23 +564,24 @@ void put()
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- printf("void prefetch%s(const Address& addr) { opModM(addr, Reg32(%d), 0x0F, 0x%02X); }\n", p->name, p->ext, p->code);
+ printf("void prefetch%s(const Address& addr) { opMR(addr, Reg32(%d), T_0F, 0x%02X); }\n", p->name, p->ext, p->code);
}
}
{
const struct Tbl {
uint8_t code;
- int pref;
const char *name;
+ uint64_t type;
} tbl[] = {
- { 0x16, NO, "movhps" },
- { 0x12, NO, "movlps" },
- { 0x16, 0x66, "movhpd" },
- { 0x12, 0x66, "movlpd" },
+ { 0x16, "movhps", T_0F },
+ { 0x12, "movlps", T_0F },
+ { 0x16, "movhpd", T_0F | T_66 },
+ { 0x12, "movlpd", T_0F | T_66 },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- printf("void %s(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x%02X, 0x%02X); }\n", p->name, p->code, p->pref);
+ std::string s = type2String(p->type);
+ printf("void %s(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, %s, 0x%02X); }\n", p->name, s.c_str(), p->code);
}
}
{
@@ -624,12 +624,50 @@ void put()
const char *msg = "//-V524"; // disable warning of PVS-Studio
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- 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);
+ printf("void cmov%s(const Reg& reg, const Operand& op) { opRO(reg, op, T_0F, 0x40 | %d, op.isREG(16|i32e)); }%s\n", p->name, p->ext, msg);
+ printf("void cmov%s(const Reg& d, const Reg& reg, const Operand& op) { opROO(d, op, reg, T_APX|T_ND1, 0x40 | %d); }%s\n", p->name, p->ext, msg);
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);
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);
printf("void j%s(const char *label, LabelType type = T_AUTO) { j%s(std::string(label), type); }%s\n", p->name, p->name, msg);
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);
- printf("void set%s(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | %d); }%s\n", p->name, p->ext, msg);
+ printf("void set%s(const Operand& op) { opSetCC(op, %d); }%s\n", p->name, p->ext, msg);
+
+ // ccmpscc
+ // true if SCC = 0b1010, false if SCC = 0b1011 (see APX Architecture Specification p.266)
+ const char *s = p->ext == 10 ? "t" : p->ext == 11 ? "f" : p->name;
+ printf("void ccmp%s(const Operand& op1, const Operand& op2, int dfv = 0) { opCcmp(op1, op2, dfv, 0x38, %d); }\n", s, p->ext);
+ printf("void ccmp%s(const Operand& op, int imm, int dfv = 0) { opCcmpi(op, imm, dfv, %d); }\n", s, p->ext);
+ printf("void ctest%s(const Operand& op, const Reg& r, int dfv = 0) { opCcmp(op, r, dfv, 0x84, %d); }\n", s, p->ext);
+ printf("void ctest%s(const Operand& op, int imm, int dfv = 0) { opTesti(op, imm, dfv, %d); }\n", s, p->ext);
+ }
+ }
+ {
+ // cfcmov
+ const struct Tbl {
+ uint8_t code;
+ const char *suf;
+ } tbl[] = {
+ {0x40, "o"},
+ {0x41, "no"},
+ {0x42, "b"},
+ {0x43, "nb"},
+ {0x44, "z"},
+ {0x45, "nz"},
+ {0x46, "be"},
+ {0x47, "nbe"},
+ {0x48, "s"},
+ {0x49, "ns"},
+ {0x4A, "p"},
+ {0x4B, "np"},
+ {0x4C, "l"},
+ {0x4D, "nl"},
+ {0x4E, "le"},
+ {0x4F, "nle"},
+ };
+ for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
+ const Tbl *p = &tbl[i];
+ printf("void cfcmov%s(const Operand& op1, const Operand& op2) { opCfcmov(Reg(), op1, op2, 0x%02X); }\n", p->suf, p->code);
+ printf("void cfcmov%s(const Reg& d, const Reg& r, const Operand& op) { opCfcmov(d|T_nf, op, r, 0x%02X); }\n", p->suf, p->code);
}
}
{
@@ -720,6 +758,7 @@ void put()
{ "wbinvd", 0x0F, 0x09 },
{ "wrmsr", 0x0F, 0x30 },
{ "xlatb", 0xD7 },
+ { "xend", 0x0f, 0x01, 0xd5 },
{ "popf", 0x9D },
{ "pushf", 0x9C },
@@ -784,61 +823,65 @@ void put()
putGeneric(tbl, NUM_OF_ARRAY(tbl));
puts("void enter(uint16_t x, uint8_t y) { db(0xC8); dw(x); db(y); }");
puts("void int_(uint8_t x) { db(0xCD); db(x); }");
- putLoadSeg("lss", 0x0F, 0xB2);
- putLoadSeg("lfs", 0x0F, 0xB4);
- putLoadSeg("lgs", 0x0F, 0xB5);
+ putLoadSeg("lss", T_0F, 0xB2);
+ putLoadSeg("lfs", T_0F, 0xB4);
+ putLoadSeg("lgs", T_0F, 0xB5);
}
{
const struct Tbl {
uint8_t code; // (reg, reg)
uint8_t ext; // (reg, imm)
const char *name;
+ bool support3op;
+ uint64_t type;
} tbl[] = {
- { 0x10, 2, "adc" },
- { 0x00, 0, "add" },
- { 0x20, 4, "and_" },
- { 0x38, 7, "cmp" },
- { 0x08, 1, "or_" },
- { 0x18, 3, "sbb" },
- { 0x28, 5, "sub" },
- { 0x30, 6, "xor_" },
+ { 0x10, 2, "adc", true, T_NONE },
+ { 0x00, 0, "add", true, T_NF | T_CODE1_IF1 },
+ { 0x20, 4, "and_", true, T_NF | T_CODE1_IF1 },
+ { 0x38, 7, "cmp", false, T_NONE },
+ { 0x08, 1, "or_", true, T_NF | T_CODE1_IF1 },
+ { 0x18, 3, "sbb", true, T_NONE },
+ { 0x28, 5, "sub", true, T_NF | T_CODE1_IF1 },
+ { 0x30, 6, "xor_", true, T_NF | T_CODE1_IF1 },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- printf("void %s(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x%02X); }\n", p->name, p->code);
- printf("void %s(const Operand& op, uint32_t imm) { opRM_I(op, imm, 0x%02X, %d); }\n", p->name, p->code, p->ext);
+ printf("void %s(const Operand& op1, const Operand& op2) { opRO_MR(op1, op2, 0x%02X); }\n", p->name, p->code);
+ printf("void %s(const Operand& op, uint32_t imm) { opOI(op, imm, 0x%02X, %d); }\n", p->name, p->code, p->ext);
+ if (!p->support3op) continue;
+ std::string s = type2String(p->type);
+ printf("void %s(const Reg& d, const Operand& op1, const Operand& op2) { opROO(d, op1, op2, %s, 0x%02X); }\n", p->name, s.c_str(), p->code);
+ printf("void %s(const Reg& d, const Operand& op, uint32_t imm) { opROI(d, op, imm, %s, %d); }\n", p->name, s.c_str(), p->ext);
}
}
{
const struct Tbl {
const char *name;
- uint8_t prefix;
+ const char *prefix;
} tbl[] = {
- { "aadd", 0 },
- { "aand", 0x66 },
- { "aor", 0xF2 },
- { "axor", 0xF3 },
+ { "aadd", "" },
+ { "aand", "|T_66" },
+ { "aor", "|T_F2" },
+ { "axor", "|T_F3" },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- printf("void %s(const Address& addr, const Reg32e &reg) { ", p->name);
- if (p->prefix) printf("db(0x%02X); ", p->prefix);
- printf("opModM(addr, reg, 0x0F, 0x38, 0x0FC); }\n");
+ printf("void %s(const Address& addr, const Reg32e &reg) { opMR(addr, reg, T_0F38%s, 0x0FC, T_APX%s); }\n", p->name, p->prefix, p->prefix);
}
}
{
const struct Tbl {
- uint8_t code;
uint8_t ext;
const char *name;
} tbl[] = {
- { 0x48, 1, "dec" },
- { 0x40, 0, "inc" },
+ { 1, "dec" },
+ { 0, "inc" },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- printf("void %s(const Operand& op) { opIncDec(op, 0x%02X, %d); }\n", p->name, p->code, p->ext);
+ printf("void %s(const Operand& op) { opIncDec(Reg(), op, %d); }\n", p->name, p->ext);
+ printf("void %s(const Reg& d, const Operand& op) { opIncDec(d, op, %d); }\n", p->name, p->ext);
}
}
{
@@ -854,8 +897,8 @@ void put()
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- 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);
- printf("void %s(const Operand& op, uint8_t imm) { opR_ModM(op, 16|32|64, %d, 0x0f, 0xba, NONE, false, 1); db(imm); }\n", p->name, p->ext);
+ printf("void %s(const Operand& op, const Reg& reg) { opRO(reg, op, T_0F, 0x%02X, op.isREG(16|i32e) && op.getBit() == reg.getBit()); }\n", p->name, p->code);
+ printf("void %s(const Operand& op, uint8_t imm) { opRext(op, 16|i32e, %d, T_0F, 0xba, false, 1); db(imm); }\n", p->name, p->ext);
}
}
{
@@ -863,53 +906,70 @@ void put()
uint8_t code;
uint8_t ext;
const char *name;
+ bool NF;
+ int n; // # of op
} tbl[] = {
- { 0xF6, 6, "div" },
- { 0xF6, 7, "idiv" },
- { 0xF6, 5, "imul" },
- { 0xF6, 4, "mul" },
- { 0xF6, 3, "neg" },
- { 0xF6, 2, "not_" },
+ { 0xF6, 6, "div", true, 1 },
+ { 0xF6, 7, "idiv", true, 1 },
+ { 0xF6, 5, "imul", true ,3 },
+ { 0xF6, 4, "mul", true, 1 },
+ { 0xF6, 3, "neg", true, 2 },
+ { 0xF6, 2, "not_", false, 2 },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
const std::string name = p->name;
- printf("void %s(const Operand& op) { opR_ModM(op, 0, %d, 0x%02X); }\n", p->name, p->ext, p->code);
+ uint64_t type = T_APX|T_CODE1_IF1;
+ if (p->NF) type |= T_NF;
+ std::string s = type2String(type);
+ printf("void %s(const Operand& op) { opRext(op, 0, %d, %s, 0x%02X); }\n", p->name, p->ext, s.c_str(), p->code);
+ if (p->n == 2) {
+ type = T_APX|T_ND1|T_CODE1_IF1;
+ if (p->NF) type |= T_NF;
+ s = type2String(type);
+ printf("void %s(const Reg& d, const Operand& op) { opROO(d, op, Reg(%d, Operand::REG, d.getBit()), %s, 0xF6); }\n", p->name, p->ext, s.c_str());
+ }
}
+ printf("void imul(const Reg& reg, const Operand& op) { if (opROO(Reg(), op, reg, T_APX|T_NF, 0xAF)) return; opRO(reg, op, T_0F, 0xAF, reg.getKind() == op.getKind()); }\n");
}
{
const struct Tbl {
const char *name;
- uint8_t ext;
+ uint8_t ext; // |8 means supporting NF=1
} tbl[] = {
- { "rcl", 2 },
- { "rcr", 3 },
- { "rol", 0 },
- { "ror", 1 },
- { "sar", 7 },
- { "shl", 4 },
- { "shr", 5 },
-
- { "sal", 4 },
+ { "rcl", 2|0 },
+ { "rcr", 3|0 },
+ { "rol", 0|8 },
+ { "ror", 1|8 },
+ { "sar", 7|8 },
+ { "shl", 4|8 },
+ { "shr", 5|8 },
+
+ { "sal", 4|8 },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
printf("void %s(const Operand& op, int imm) { opShift(op, imm, %d); }\n", p->name, p->ext);
printf("void %s(const Operand& op, const Reg8& _cl) { opShift(op, _cl, %d); }\n", p->name, p->ext);
+ printf("void %s(const Reg& d, const Operand& op, int imm) { opShift(op, imm, %d, &d); }\n", p->name, p->ext);
+ printf("void %s(const Reg& d, const Operand& op, const Reg8& _cl) { opShift(op, _cl, %d, &d); }\n", p->name, p->ext);
}
}
{
const struct Tbl {
const char *name;
uint8_t code;
+ uint8_t code2;
} tbl[] = {
- { "shld", 0xA4 },
- { "shrd", 0xAC },
+ { "shld", 0xA4, 0x24 },
+ { "shrd", 0xAC, 0x2C },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- printf("void %s(const Operand& op, const Reg& reg, uint8_t imm) { opShxd(op, reg, imm, 0x%02X); }\n", p->name, p->code);
- printf("void %s(const Operand& op, const Reg& reg, const Reg8& _cl) { opShxd(op, reg, 0, 0x%02X, &_cl); }\n", p->name, p->code);
+ printf("void %s(const Operand& op, const Reg& reg, uint8_t imm) { opShxd(Reg(), op, reg, imm, 0x%02X, 0x%02X); }\n", p->name, p->code, p->code2);
+ printf("void %s(const Operand& op, const Reg& reg, const Reg8& _cl) { opShxd(Reg(), op, reg, 0, 0x%02X, 0x%02X, &_cl); }\n", p->name, p->code, p->code2);
+ printf("void %s(const Reg& d, const Operand& op, const Reg& reg, uint8_t imm) { opShxd(d, op, reg, imm, 0x%02X, 0x%02X); }\n", p->name, p->code, p->code2);
+ printf("void %s(const Reg& d, const Operand& op, const Reg& reg, const Reg8& _cl) { opShxd(d, op, reg, 0, 0x%02X, 0x%02X, &_cl); }\n", p->name, p->code, p->code2);
}
}
{
@@ -922,21 +982,26 @@ void put()
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- 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);
+ printf("void %s(const Reg&reg, const Operand& op) { opRO(reg, op, T_0F, 0x%02X, op.isREG(16|i32e)); }\n", p->name, p->code);
}
}
{
const struct Tbl {
const char *name;
uint8_t code;
+ uint8_t code2;
} tbl[] = {
- { "popcnt", 0xB8 },
- { "tzcnt", 0xBC },
- { "lzcnt", 0xBD },
+ { "popcnt", 0xB8, 0 },
+ { "tzcnt", 0xBC, 0xF4 },
+ { "lzcnt", 0xBD, 0xF5 },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- printf("void %s(const Reg&reg, const Operand& op) { opSp1(reg, op, 0xF3, 0x0F, 0x%02X); }\n", p->name, p->code);
+ if (p->code2) {
+ printf("void %s(const Reg&reg, const Operand& op) { if (opROO(Reg(), op, reg, T_APX|T_NF, 0x%02X)) return; opCnt(reg, op, 0x%02X); }\n", p->name, p->code2, p->code);
+ } else {
+ printf("void %s(const Reg&reg, const Operand& op) { opCnt(reg, op, 0x%02X); }\n", p->name, p->code);
+ }
}
}
// SSSE3
@@ -963,9 +1028,9 @@ void put()
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- printf("void %s(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x%02X, 0x66, NONE, 0x38); }\n", p->name, p->code);
+ printf("void %s(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x%02X, T_0F38, T_66); }\n", p->name, p->code);
}
- printf("void palignr(const Mmx& mmx, const Operand& op, int imm) { opMMX(mmx, op, 0x0f, 0x66, static_cast<uint8_t>(imm), 0x3a); }\n");
+ printf("void palignr(const Mmx& mmx, const Operand& op, int imm) { opMMX(mmx, op, 0x0F, T_0F3A, T_66, static_cast<uint8_t>(imm)); }\n");
}
{
const struct Tbl {
@@ -974,44 +1039,45 @@ void put()
} tbl[] = {
{ "pclmullqlqdq", 0 },
{ "pclmulhqlqdq", 1 },
- { "pclmullqhdq", 0x10 },
- { "pclmulhqhdq", 0x11 },
+ { "pclmullqhqdq", 0x10 },
+ { "pclmulhqhqdq", 0x11 },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
printf("void %s(const Xmm& xmm, const Operand& op) { pclmulqdq(xmm, op, 0x%02X); }\n", p->name, p->code);
+ printf("void v%s(const Xmm& x1, const Xmm& x2, const Operand& op) { vpclmulqdq(x1, x2, op, 0x%02X); }\n", p->name, p->code);
}
}
{
const struct Tbl {
- uint8_t code1;
- int code2;
+ const char *type;
+ uint8_t code;
uint8_t ext;
const char *name;
- uint8_t prefix;
+ bool fwait;
} tbl[] = {
- { 0x0F, 0xAE, 2, "ldmxcsr", 0 },
- { 0x0F, 0xAE, 3, "stmxcsr", 0 },
- { 0x0F, 0xAE, 7, "clflush", 0 },
- { 0x0F, 0xAE, 7, "clflushopt", 0x66 },
- { 0xDF, NONE, 4, "fbld", 0 },
- { 0xDF, NONE, 6, "fbstp", 0 },
- { 0xD9, NONE, 5, "fldcw", 0 },
- { 0xD9, NONE, 4, "fldenv", 0 },
- { 0xDD, NONE, 4, "frstor", 0 },
- { 0xDD, NONE, 6, "fsave", 0x9B },
- { 0xDD, NONE, 6, "fnsave", 0 },
- { 0xD9, NONE, 7, "fstcw", 0x9B },
- { 0xD9, NONE, 7, "fnstcw", 0 },
- { 0xD9, NONE, 6, "fstenv", 0x9B },
- { 0xD9, NONE, 6, "fnstenv", 0 },
- { 0xDD, NONE, 7, "fstsw", 0x9B },
- { 0xDD, NONE, 7, "fnstsw", 0 },
- { 0x0F, 0xAE, 1, "fxrstor", 0 },
+ { "T_0F", 0xAE, 2, "ldmxcsr", false },
+ { "T_0F", 0xAE, 3, "stmxcsr", false },
+ { "T_0F", 0xAE, 7, "clflush", false },
+ { "T_66 | T_0F", 0xAE, 7, "clflushopt", false},
+ { "0", 0xDF, 4, "fbld", false },
+ { "0", 0xDF, 6, "fbstp", false },
+ { "0", 0xD9, 5, "fldcw", false },
+ { "0", 0xD9, 4, "fldenv", false },
+ { "0", 0xDD, 4, "frstor", false },
+ { "0", 0xDD, 6, "fsave", true },
+ { "0", 0xDD, 6, "fnsave", false },
+ { "0", 0xD9, 7, "fstcw", true },
+ { "0", 0xD9, 7, "fnstcw", false },
+ { "0", 0xD9, 6, "fstenv", true },
+ { "0", 0xD9, 6, "fnstenv", false },
+ { "0", 0xDD, 7, "fstsw", true },
+ { "0", 0xDD, 7, "fnstsw", false },
+ { "T_0F", 0xAE, 1, "fxrstor", false },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- putMemOp(p->name, p->prefix, p->ext, p->code1, p->code2);
+ putMemOp(p->name, p->type, p->ext, p->code, 32, p->fwait);
}
puts("void fstsw(const Reg16& r) { if (r.getIdx() != Operand::AX) XBYAK_THROW(ERR_BAD_PARAMETER) db(0x9B); db(0xDF); db(0xE0); }");
puts("void fnstsw(const Reg16& r) { if (r.getIdx() != Operand::AX) XBYAK_THROW(ERR_BAD_PARAMETER) db(0xDF); db(0xE0); }");
@@ -1027,7 +1093,7 @@ void put()
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
// cast xmm register to 16bit register to put 0x66
- printf("void %s(const Address& addr, const Xmm& reg) { opModM(addr, Reg16(reg.getIdx()), 0x0F, 0x%02X); }\n", p->name, p->code);
+ printf("void %s(const Address& addr, const Xmm& reg) { opMR(addr, Reg16(reg.getIdx()), T_0F, 0x%02X); }\n", p->name, p->code);
}
}
{
@@ -1043,6 +1109,20 @@ void put()
printf("void %s(const Reg& reg, const Operand& op) { opMovxx(reg, op, 0x%02X); }\n", p->name, p->code);
}
}
+ {
+ const struct Tbl {
+ uint8_t prefix;
+ const char *name;
+ } tbl[] = {
+ { 0x66, "adcx" },
+ { 0xF3, "adox" },
+ };
+ for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
+ const Tbl *p = &tbl[i];
+ printf("void %s(const Reg32e& reg, const Operand& op) { if (!reg.isREG(16|i32e) && reg.getBit() == op.getBit()) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) if (opROO(Reg(), op, reg, T_%02X, 0x66)) return; opRO(reg, op, T_%02X | T_0F38, 0xF6); }\n", p->name, p->prefix, p->prefix);
+ printf("void %s(const Reg32e& d, const Reg32e& reg, const Operand& op) { opROO(d, op, reg, T_%02X, 0x66); }\n", p->name, p->prefix);
+ }
+ }
{ // in/out
puts("void in_(const Reg& a, uint8_t v) { opInOut(a, 0xE4, v); }");
puts("void in_(const Reg& a, const Reg& d) { opInOut(a, d, 0xEC); }");
@@ -1051,67 +1131,70 @@ void put()
}
// mpx
{
- puts("void bndcl(const BoundsReg& bnd, const Operand& op) { db(0xF3); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); }");
- puts("void bndcu(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); }");
- puts("void bndcn(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1B, NONE, !op.isMEM()); }");
- puts("void bndldx(const BoundsReg& bnd, const Address& addr) { opMIB(addr, bnd, 0x0F, 0x1A); }");
- puts("void bndmk(const BoundsReg& bnd, const Address& addr) { db(0xF3); opModM(addr, bnd, 0x0F, 0x1B); }");
- puts("void bndmov(const BoundsReg& bnd, const Operand& op) { db(0x66); opModRM(bnd, op, op.isBNDREG(), op.isMEM(), 0x0F, 0x1A); }");
- puts("void bndmov(const Address& addr, const BoundsReg& bnd) { db(0x66); opModM(addr, bnd, 0x0F, 0x1B); }");
- puts("void bndstx(const Address& addr, const BoundsReg& bnd) { opMIB(addr, bnd, 0x0F, 0x1B); }");
+ puts("void bndcl(const BoundsReg& bnd, const Operand& op) { opRext(op, i32e, bnd.getIdx(), T_F3 | T_0F, 0x1A, !op.isMEM()); }");
+ puts("void bndcu(const BoundsReg& bnd, const Operand& op) { opRext(op, i32e, bnd.getIdx(), T_F2 | T_0F, 0x1A, !op.isMEM()); }");
+ puts("void bndcn(const BoundsReg& bnd, const Operand& op) { opRext(op, i32e, bnd.getIdx(), T_F2 | T_0F, 0x1B, !op.isMEM()); }");
+ puts("void bndldx(const BoundsReg& bnd, const Address& addr) { opMIB(addr, bnd, T_0F, 0x1A); }");
+ puts("void bndmk(const BoundsReg& bnd, const Address& addr) { opMR(addr, bnd, T_F3 | T_0F, 0x1B); }");
+ puts("void bndmov(const BoundsReg& bnd, const Operand& op) { opRO(bnd, op, T_66 | T_0F, 0x1A, op.isBNDREG()); }");
+ puts("void bndmov(const Address& addr, const BoundsReg& bnd) { opMR(addr, bnd, T_66 | T_0F, 0x1B); }");
+ puts("void bndstx(const Address& addr, const BoundsReg& bnd) { opMIB(addr, bnd, T_0F, 0x1B); }");
}
// misc
{
- puts("void lea(const Reg& reg, const Address& addr) { if (!reg.isBit(16 | i32e)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) opModM(addr, reg, 0x8D); }");
- puts("void bswap(const Reg32e& reg) { opModR(Reg32(1), reg, 0x0F); }");
+ puts("void lea(const Reg& reg, const Address& addr) { if (!reg.isBit(16 | i32e)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) opMR(addr, reg, 0, 0x8D); }");
puts("void ret(int imm = 0) { if (imm) { db(0xC2); dw(imm); } else { db(0xC3); } }");
puts("void retf(int imm = 0) { if (imm) { db(0xCA); dw(imm); } else { db(0xCB); } }");
- 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)); }");
- 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)); }");
- puts("void movbe(const Reg& reg, const Address& addr) { opModM(addr, reg, 0x0F, 0x38, 0xF0); }");
- puts("void movbe(const Address& addr, const Reg& reg) { opModM(addr, reg, 0x0F, 0x38, 0xF1); }");
- puts("void movdiri(const Address& addr, const Reg32e& reg) { opModM(addr, reg, 0x0F, 0x38, 0xF9); }");
- puts("void movdir64b(const Reg& reg, const Address& addr) { db(0x66); opModM(addr, reg.cvt32(), 0x0F, 0x38, 0xF8); }");
- puts("void adcx(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0x66, isREG32_REG32orMEM, NONE, 0x38); }");
- puts("void adox(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0xF3, isREG32_REG32orMEM, NONE, 0x38); }");
- puts("void cmpxchg8b(const Address& addr) { opModM(addr, Reg32(1), 0x0F, 0xC7); }");
+ puts("void xadd(const Operand& op, const Reg& reg) { opRO(reg, op, T_0F, 0xC0 | (reg.isBit(8) ? 0 : 1), op.getBit() == reg.getBit()); }");
+ puts("void cmpxchg(const Operand& op, const Reg& reg) { opRO(reg, op, T_0F, 0xB0 | (reg.isBit(8) ? 0 : 1), op.getBit() == reg.getBit()); }");
+ puts("void movbe(const Reg& reg, const Address& addr) { opMR(addr, reg, T_0F38, 0xF0, T_APX, 0x60); }");
+ puts("void movbe(const Address& addr, const Reg& reg) { opMR(addr, reg, T_0F38, 0xF1, T_APX, 0x61); }");
+ puts("void movdiri(const Address& addr, const Reg32e& reg) { opMR(addr, reg, T_0F38, 0xF9, T_APX); }");
+ puts("void movdir64b(const Reg& reg, const Address& addr) { opMR(addr, reg.cvt32(), T_66|T_0F38, 0xF8, T_APX|T_66); }");
+ puts("void cmpxchg8b(const Address& addr) { opMR(addr, Reg32(1), T_0F, 0xC7); }");
puts("void pextrw(const Operand& op, const Mmx& xmm, uint8_t imm) { opExt(op, xmm, 0x15, imm, true); }");
puts("void pextrb(const Operand& op, const Xmm& xmm, uint8_t imm) { opExt(op, xmm, 0x14, imm); }");
puts("void pextrd(const Operand& op, const Xmm& xmm, uint8_t imm) { opExt(op, xmm, 0x16, imm); }");
puts("void extractps(const Operand& op, const Xmm& xmm, uint8_t imm) { opExt(op, xmm, 0x17, imm); }");
- puts("void pinsrw(const Mmx& mmx, const Operand& op, int imm) { if (!op.isREG(32) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opGen(mmx, op, 0xC4, mmx.isXMM() ? 0x66 : NONE, 0, imm); }");
- puts("void insertps(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x21, 0x66, isXMM_XMMorMEM, imm, 0x3A); }");
- puts("void pinsrb(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x20, 0x66, isXMM_REG32orMEM, imm, 0x3A); }");
- puts("void pinsrd(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x22, 0x66, isXMM_REG32orMEM, imm, 0x3A); }");
-
- puts("void pmovmskb(const Reg32e& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(reg, mmx, 0x0F, 0xD7); }");
- puts("void maskmovq(const Mmx& reg1, const Mmx& reg2) { if (!reg1.isMMX() || !reg2.isMMX()) XBYAK_THROW(ERR_BAD_COMBINATION) opModR(reg1, reg2, 0x0F, 0xF7); }");
- puts("void movmskps(const Reg32e& reg, const Xmm& xmm) { opModR(reg, xmm, 0x0F, 0x50); }");
+ puts("void pinsrw(const Mmx& mmx, const Operand& op, int imm) { if (!op.isREG(32) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opSSE(mmx, op, T_0F | (mmx.isXMM() ? T_66 : T_NONE), 0xC4, 0, imm); }");
+ puts("void insertps(const Xmm& xmm, const Operand& op, uint8_t imm) { opSSE(xmm, op, T_66 | T_0F3A, 0x21, isXMM_XMMorMEM, imm); }");
+ puts("void pinsrb(const Xmm& xmm, const Operand& op, uint8_t imm) { opSSE(xmm, op, T_66 | T_0F3A, 0x20, isXMM_REG32orMEM, imm); }");
+ puts("void pinsrd(const Xmm& xmm, const Operand& op, uint8_t imm) { opSSE(xmm, op, T_66 | T_0F3A, 0x22, isXMM_REG32orMEM, imm); }");
+
+ puts("void pmovmskb(const Reg32e& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opRR(reg, mmx, T_0F, 0xD7); }");
+ puts("void maskmovq(const Mmx& reg1, const Mmx& reg2) { if (!reg1.isMMX() || !reg2.isMMX()) XBYAK_THROW(ERR_BAD_COMBINATION) opRR(reg1, reg2, T_0F, 0xF7); }");
+ puts("void movmskps(const Reg32e& reg, const Xmm& xmm) { opRR(reg, xmm, T_0F, 0x50); }");
puts("void movmskpd(const Reg32e& reg, const Xmm& xmm) { db(0x66); movmskps(reg, xmm); }");
- puts("void movntps(const Address& addr, const Xmm& xmm) { opModM(addr, Mmx(xmm.getIdx()), 0x0F, 0x2B); }");
- puts("void movntdqa(const Xmm& xmm, const Address& addr) { db(0x66); opModM(addr, xmm, 0x0F, 0x38, 0x2A); }");
- puts("void lddqu(const Xmm& xmm, const Address& addr) { db(0xF2); opModM(addr, xmm, 0x0F, 0xF0); }");
- puts("void movnti(const Address& addr, const Reg32e& reg) { opModM(addr, reg, 0x0F, 0xC3); }");
- puts("void movntq(const Address& addr, const Mmx& mmx) { if (!mmx.isMMX()) XBYAK_THROW(ERR_BAD_COMBINATION) opModM(addr, mmx, 0x0F, 0xE7); }");
-
- puts("void movd(const Address& addr, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, 0x7E); }");
- puts("void movd(const Reg32& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x7E); }");
- puts("void movd(const Mmx& mmx, const Address& addr) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, 0x6E); }");
- puts("void movd(const Mmx& mmx, const Reg32& reg) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x6E); }");
- puts("void movq2dq(const Xmm& xmm, const Mmx& mmx) { db(0xF3); opModR(xmm, mmx, 0x0F, 0xD6); }");
- puts("void movdq2q(const Mmx& mmx, const Xmm& xmm) { db(0xF2); opModR(mmx, xmm, 0x0F, 0xD6); }");
- 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); }");
- puts("void movq(const Address& addr, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, mmx.isXMM() ? 0xD6 : 0x7F); }");
- puts("void rdrand(const Reg& r) { if (r.isBit(8)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) opModR(Reg(6, Operand::REG, r.getBit()), r, 0x0F, 0xC7); }");
- puts("void rdseed(const Reg& r) { if (r.isBit(8)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) opModR(Reg(7, Operand::REG, r.getBit()), r, 0x0F, 0xC7); }");
- 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)); }");
+ puts("void movntps(const Address& addr, const Xmm& xmm) { opMR(addr, Mmx(xmm.getIdx()), T_0F, 0x2B); }");
+ puts("void movntdqa(const Xmm& xmm, const Address& addr) { opMR(addr, xmm, T_66 | T_0F38, 0x2A); }");
+ puts("void lddqu(const Xmm& xmm, const Address& addr) { opMR(addr, xmm, T_F2 | T_0F, 0xF0); }");
+ puts("void movnti(const Address& addr, const Reg32e& reg) { opMR(addr, reg, T_0F, 0xC3); }");
+ puts("void movntq(const Address& addr, const Mmx& mmx) { if (!mmx.isMMX()) XBYAK_THROW(ERR_BAD_COMBINATION) opMR(addr, mmx, T_0F, 0xE7); }");
+
+ puts("void movd(const Address& addr, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opMR(addr, mmx, T_0F, 0x7E); }");
+ puts("void movd(const Reg32& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opRR(mmx, reg, T_0F, 0x7E); }");
+ puts("void movd(const Mmx& mmx, const Address& addr) { if (mmx.isXMM()) db(0x66); opMR(addr, mmx, T_0F, 0x6E); }");
+ puts("void movd(const Mmx& mmx, const Reg32& reg) { if (mmx.isXMM()) db(0x66); opRR(mmx, reg, T_0F, 0x6E); }");
+ puts("void movq2dq(const Xmm& xmm, const Mmx& mmx) { opRR(xmm, mmx, T_F3 | T_0F, 0xD6); }");
+ puts("void movdq2q(const Mmx& mmx, const Xmm& xmm) { opRR(mmx, xmm, T_F2 | T_0F, 0xD6); }");
+ puts("void movq(const Mmx& mmx, const Operand& op) { if (mmx.isXMM()) db(0xF3); opRO(mmx, op, T_0F, mmx.isXMM() ? 0x7E : 0x6F, mmx.getKind() == op.getKind()); }");
+ puts("void movq(const Address& addr, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opMR(addr, mmx, T_0F, mmx.isXMM() ? 0xD6 : 0x7F); }");
+ puts("void rdrand(const Reg& r) { if (r.isBit(8)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) opRR(Reg(6, Operand::REG, r.getBit()), r, T_0F, 0xC7); }");
+ puts("void rdseed(const Reg& r) { if (r.isBit(8)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) opRR(Reg(7, Operand::REG, r.getBit()), r, T_0F, 0xC7); }");
+ puts("void crc32(const Reg32e& r, const Operand& op) { if (!((r.isBit(32) && op.isBit(8|16|32)) || (r.isBit(64) && op.isBit(8|64)))) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) int code = 0xF0 | (op.isBit(8) ? 0 : 1); uint64_t type = op.isBit(16) ? T_66:0; if (opROO(Reg(), op, static_cast<const Reg&>(r), T_APX|type, code)) return; opRO(r, op, T_F2|T_0F38|type, code); }");
puts("void tpause(const Reg32& r) { int idx = r.getIdx(); if (idx > 7) XBYAK_THROW(ERR_BAD_PARAMETER) db(0x66); db(0x0F); db(0xAE); setModRM(3, 6, idx); }");
puts("void umonitor(const Reg& r) { int idx = r.getIdx(); if (idx > 7) XBYAK_THROW(ERR_BAD_PARAMETER) int bit = r.getBit(); if (BIT != bit) { if ((BIT == 32 && bit == 16) || (BIT == 64 && bit == 32)) { db(0x67); } else { XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) } } db(0xF3); db(0x0F); db(0xAE); setModRM(3, 6, idx); }");
puts("void umwait(const Reg32& r) { int idx = r.getIdx(); if (idx > 7) XBYAK_THROW(ERR_BAD_PARAMETER) db(0xF2); db(0x0F); db(0xAE); setModRM(3, 6, idx); }");
- puts("void clwb(const Address& addr) { db(0x66); opMIB(addr, esi, 0x0F, 0xAE); }");
- puts("void cldemote(const Address& addr) { opMIB(addr, eax, 0x0F, 0x1C); }");
+ puts("void clwb(const Address& addr) { opMR(addr, esi, T_66 | T_0F, 0xAE); }");
+ puts("void cldemote(const Address& addr) { opMR(addr, eax, T_0F, 0x1C); }");
+ puts("void xabort(uint8_t imm) { db(0xC6); db(0xF8); db(imm); }");
+ puts("void xbegin(uint32_t rel) { db(0xC7); db(0xF8); dd(rel); }");
+
+ puts("void vsha512msg1(const Ymm& y, const Xmm& x) { if (!(y.isYMM() && x.isXMM())) XBYAK_THROW(ERR_BAD_PARAMETER) opVex(y, 0, x, T_F2 | T_0F38 | T_W0 | T_YMM, 0xCC); }");
+ puts("void vsha512msg2(const Ymm& y1, const Ymm& y2) { if (!(y1.isYMM() && y2.isYMM())) XBYAK_THROW(ERR_BAD_PARAMETER) opVex(y1, 0, y2, T_F2 | T_0F38 | T_W0 | T_YMM, 0xCD); }");
+ puts("void vsha512rnds2(const Ymm& y1, const Ymm& y2, const Xmm& x) { if (!(y1.isYMM() && y2.isYMM() && x.isXMM())) XBYAK_THROW(ERR_BAD_PARAMETER) opVex(y1, &y2, x, T_F2 | T_0F38 | T_W0 | T_YMM, 0xCB); }");
}
{
const struct Tbl {
@@ -1251,7 +1334,7 @@ void put()
const struct Tbl {
uint8_t code;
const char *name;
- int type;
+ uint64_t type;
bool hasIMM;
int mode; // 1 : SSE, 2 : AVX, 3 : SSE + AVX
} tbl[] = {
@@ -1317,38 +1400,47 @@ void put()
{ 0x2E, "ucomisd", T_0F | T_66 | T_EVEX | T_EW1 | T_SAE_X | T_N8, false, 2 },
{ 0x2E, "ucomiss", T_0F | T_EVEX | T_EW0 | T_SAE_X | T_N4, false, 2 },
-
- { 0xCC, "sha1rnds4", T_0F3A, true, 1 },
- { 0xC8, "sha1nexte", T_0F38, false, 1 },
- { 0xC9, "sha1msg1", T_0F38, false, 1 },
- { 0xCA, "sha1msg2", T_0F38, false, 1 },
- { 0xCB, "sha256rnds2", T_0F38, false, 1 },
- { 0xCC, "sha256msg1", T_0F38, false, 1 },
- { 0xCD, "sha256msg2", T_0F38, false, 1 },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- std::string type = type2String(p->type);
+ std::string s = type2String(p->type);
if (p->mode & 1) {
const char *immS1 = p->hasIMM ? ", uint8_t imm" : "";
const char *immS2 = p->hasIMM ? ", imm" : ", NONE";
- const char *prefTbl[5] = { "NONE", "0x66", "0xF3", "0xF2" };
- const char *pref = prefTbl[getPP(p->type)];
- const char *suf = p->type & T_0F38 ? "0x38" : p->type & T_0F3A ? "0x3A" : "NONE";
- 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);
+ printf("void %s(const Xmm& xmm, const Operand& op%s) { opSSE(xmm, op, %s, 0x%02X, isXMM_XMMorMEM%s); }\n", p->name, immS1, s.c_str(), p->code, immS2);
}
if (p->mode & 2) {
printf("void v%s(const Xmm& xm, const Operand& op%s) { opAVX_X_XM_IMM(xm, op, %s, 0x%02X%s); }\n"
- , p->name, p->hasIMM ? ", uint8_t imm" : "", type.c_str(), p->code, p->hasIMM ? ", imm" : "");
+ , p->name, p->hasIMM ? ", uint8_t imm" : "", s.c_str(), p->code, p->hasIMM ? ", imm" : "");
}
}
}
+ // sha
+ {
+ const struct Tbl {
+ uint8_t code;
+ uint8_t code2;
+ const char *name;
+ } tbl[] = {
+ { 0xC8, 0xD8, "sha1nexte" },
+ { 0xC9, 0xD9, "sha1msg1" },
+ { 0xCA, 0xDA, "sha1msg2" },
+ { 0xCB, 0xDB, "sha256rnds2" },
+ { 0xCC, 0xDC, "sha256msg1" },
+ { 0xCD, 0xDD, "sha256msg2" },
+ };
+ for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
+ const Tbl *p = &tbl[i];
+ printf("void %s(const Xmm& x, const Operand& op) { opSSE_APX(x, op, T_0F38, 0x%02X, T_MUST_EVEX, 0x%02X); }\n", p->name, p->code, p->code2);
+ }
+ puts("void sha1rnds4(const Xmm& x, const Operand& op, uint8_t imm) { opSSE_APX(x, op, T_0F3A, 0xCC, T_MUST_EVEX, 0xD4, imm); }");
+ }
// (m, x), (m, y)
{
const struct Tbl {
uint8_t code;
const char *name;
- int type;
+ uint64_t type;
} tbl[] = {
{ 0x29, "movapd", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_M_K },
{ 0x29, "movaps", T_0F | T_YMM | T_EVEX | T_EW0 | T_M_K },
@@ -1359,9 +1451,9 @@ void put()
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- std::string type = type2String(p->type);
+ std::string s = type2String(p->type);
printf("void v%s(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, %s, 0x%02X); }\n"
- , p->name, type.c_str(), p->code);
+ , p->name, s.c_str(), p->code);
}
}
// (x, x/m), (y, y/m), (x, x, x/m), (y, y, y/m)
@@ -1369,7 +1461,7 @@ void put()
const struct Tbl {
uint8_t code;
const char *name;
- int type;
+ uint64_t type;
int mode; // 1 : sse, 2 : avx, 3 : sse + avx
} tbl[] = {
{ 0xD0, "addsubpd", T_0F | T_66 | T_YMM, 3 },
@@ -1384,17 +1476,15 @@ void put()
{ 0xDE, "aesdec", T_0F38 | T_66 | T_YMM | T_EVEX, 3 },
{ 0xDF, "aesdeclast", T_0F38 | T_66 | T_YMM | T_EVEX, 3 },
};
- const uint8_t ppTbl[] = { 0, 0x66, 0xf3, 0xf2 };
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- std::string type = type2String(p->type);
+ std::string s = type2String(p->type);
if (p->mode & 1) {
- uint8_t pref = ppTbl[getPP(p->type)];
- 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" : "");
+ printf("void %s(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, %s, 0x%02X, isXMM_XMMorMEM); }\n", p->name, s.c_str(), p->code);
}
if (p->mode & 2) {
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"
- , p->name, type.c_str(), p->code);
+ , p->name, s.c_str(), p->code);
}
}
}
@@ -1419,7 +1509,7 @@ void put()
const struct Tbl {
uint8_t code;
const char *name;
- int type;
+ uint64_t type;
} tbl[] = {
{ 0x36, "vpermd", T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX | T_EW0 | T_B32 },
{ 0x36, "vpermq", T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX | T_EW1 | T_B64 },
@@ -1428,8 +1518,8 @@ void put()
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl& p = tbl[i];
- std::string type = type2String(p.type);
- 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);
+ std::string s = type2String(p.type);
+ 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, s.c_str(), p.code);
}
}
// vpermq, vpermpd
@@ -1437,15 +1527,15 @@ void put()
const struct Tbl {
uint8_t code;
const char *name;
- int type;
+ uint64_t type;
} tbl[] = {
{ 0x00, "vpermq", T_0F3A | T_66 | T_W1 | T_YMM | T_EVEX | T_EW1 | T_B64 },
{ 0x01, "vpermpd", T_0F3A | T_66 | T_W1 | T_YMM | T_EVEX | T_EW1 | T_B64 },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl& p = tbl[i];
- std::string type = type2String(p.type);
- printf("void %s(const Ymm& y, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(y, op, %s, 0x%02X, imm); }\n", p.name, type.c_str(), p.code);
+ std::string s = type2String(p.type);
+ printf("void %s(const Ymm& y, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(y, op, %s, 0x%02X, imm); }\n", p.name, s.c_str(), p.code);
}
}
// vcmpeqps
@@ -1483,11 +1573,11 @@ void put()
const Tbl& p = tbl[i];
char c = p.isH ? 'h' : 'l';
const char *suf = p.isPd ? "pd" : "ps";
- const char *type = p.isPd ? "T_0F | T_66 | T_EVEX | T_EW1 | T_N8" : "T_0F | T_EVEX | T_EW0 | T_N8";
+ std::string s = type2String(p.isPd ? (T_0F | T_66 | T_EVEX | T_EW1 | T_N8) : (T_0F | T_EVEX | T_EW0 | T_N8));
printf("void vmov%c%s(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x, op1, op2, %s, 0x%02X); }\n"
- , c, suf, type, p.code);
+ , c, suf, s.c_str(), p.code);
printf("void vmov%c%s(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, %s, 0x%02X); }\n"
- , c, suf, type, p.code + 1);
+ , c, suf, s.c_str(), p.code + 1);
}
}
// FMA
@@ -1536,9 +1626,9 @@ void put()
} else { // ss
t |= T_ER_X | T_N4;
}
- std::string type = type2String(t);
+ std::string s = type2String(t);
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"
- , tbl[i].name, ord[k].str, suf.c_str(), type.c_str(), tbl[i].code + ord[k].code);
+ , tbl[i].name, ord[k].str, suf.c_str(), s.c_str(), tbl[i].code + ord[k].code);
}
}
}
@@ -1551,7 +1641,7 @@ void put()
const struct Tbl {
const char *name;
uint8_t code;
- int type;
+ uint64_t type;
bool ew1;
} tbl[] = {
{ "vbroadcastss", 0x18, T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_N4 },
@@ -1562,8 +1652,8 @@ void put()
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl& p = tbl[i];
- std::string type = type2String(p.type);
- printf("void %s(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_XM_IMM(x, op, %s, 0x%02X); }\n", p.name, type.c_str(), p.code);
+ std::string s = type2String(p.type);
+ printf("void %s(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_XM_IMM(x, op, %s, 0x%02X); }\n", p.name, s.c_str(), p.code);
}
puts("void vextractf128(const Operand& op, const Ymm& y, uint8_t imm) { if (!(op.isXMEM() && y.isYMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(y, 0, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x19, imm); }");
@@ -1598,7 +1688,7 @@ void put()
const char *name;
uint8_t code;
int idx;
- int type;
+ uint64_t type;
} tbl[] = {
{ "pslldq", 0x73, 7, T_0F | T_66 | T_YMM | T_EVEX | T_MEM_EVEX },
{ "psrldq", 0x73, 3, T_0F | T_66 | T_YMM | T_EVEX | T_MEM_EVEX },
@@ -1613,8 +1703,8 @@ void put()
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl& p = tbl[i];
- std::string type = type2String(p.type);
- printf("void v%s(const Xmm& x, const Operand& op, uint8_t 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);
+ std::string s = type2String(p.type);
+ printf("void v%s(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), %d), x, op, %s, 0x%02X, imm); }\n", p.name, p.idx, s.c_str(), p.code);
}
}
// 4-op
@@ -1637,7 +1727,7 @@ void put()
printf("void vmovd(const Xmm& x, const Operand& op) { if (!op.isREG(32) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x, xm0, op, T_0F | T_66 | T_W0 | T_EVEX | T_N4, 0x6E); }\n");
printf("void vmovd(const Operand& op, const Xmm& x) { if (!op.isREG(32) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x, xm0, op, T_0F | T_66 | T_W0 | T_EVEX | T_N4, 0x7E); }\n");
- 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");
+ printf("void vmovq(const Xmm& x, const Address& addr) { uint64_t type; uint8_t 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");
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");
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");
@@ -1655,7 +1745,7 @@ void put()
// vmovsd, vmovss
for (int i = 0; i < 2; i++) {
char c1 = i == 0 ? 'd' : 's';
- int type = T_0F | T_EVEX;
+ uint64_t type = T_0F | T_EVEX;
type |= i == 0 ? (T_F2 | T_EW1 | T_N8) : (T_F3 | T_EW0 | T_N4);
std::string s = type2String(type);
printf("void vmovs%c(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x1, x2, op, %s, 0x10); }\n", c1, s.c_str());
@@ -1689,7 +1779,7 @@ void put()
{
const struct Tbl {
const char *name;
- int type;
+ uint64_t type;
uint8_t code;
} tbl[] = {
{ "vbcstnebf162ps", T_F3 | T_0F38 | T_W0 | T_B16 | T_YMM, 0xB1 },
@@ -1703,59 +1793,59 @@ void put()
const Tbl& p = tbl[i];
printf("void %s(const Xmm& x, const Address& addr) { opVex(x, 0, addr, %s, 0x%02X); }\n", p.name, type2String(p.type).c_str(), p.code);
}
- puts("void vcvtneps2bf16(const Xmm& x, const Operand& op, PreferredEncoding encoding = DefaultEncoding) { opCvt2(x, op, T_F3 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_B32 | orEvexIf(encoding), 0x72); }");
+ printf("void vcvtneps2bf16(const Xmm& x, const Operand& op, PreferredEncoding encoding = DefaultEncoding) { opCvt2(x, op, %s|orEvexIf(encoding), 0x72); }\n", type2String(T_F3 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_B32).c_str());
}
// haswell gpr(reg, reg, r/m)
{
const struct Tbl {
const char *name;
- int type;
+ uint64_t type;
uint8_t code;
} tbl[] = {
- { "andn", T_0F38, 0xF2 },
- { "mulx", T_F2 | T_0F38, 0xF6 },
- { "pdep", T_F2 | T_0F38, 0xF5 },
- { "pext", T_F3 | T_0F38, 0xF5 },
+ { "andn", T_0F38 | T_APX | T_NF, 0xF2 },
+ { "mulx", T_F2 | T_0F38 | T_APX , 0xF6 },
+ { "pdep", T_F2 | T_0F38 | T_APX, 0xF5 },
+ { "pext", T_F3 | T_0F38 | T_APX, 0xF5 },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl& p = tbl[i];
- 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);
+ printf("void %s(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opRRO(r1, r2, op, %s, 0x%x); }\n", p.name, type2String(p.type).c_str(), p.code);
}
}
// gpr(reg, r/m, reg)
{
const struct Tbl {
const char *name;
- int type;
+ uint64_t type;
uint8_t code;
} tbl[] = {
- { "bextr", T_0F38, 0xF7 },
- { "bzhi", T_0F38, 0xF5 },
- { "sarx", T_0F38 | T_F3, 0xF7 },
- { "shlx", T_0F38 | T_66, 0xF7 },
- { "shrx", T_0F38 | T_F2, 0xF7 },
+ { "bextr", T_0F38 | T_APX | T_NF, 0xF7 },
+ { "bzhi", T_0F38 | T_APX | T_NF, 0xF5 },
+ { "sarx", T_0F38 | T_F3 | T_APX, 0xF7 },
+ { "shlx", T_0F38 | T_66 | T_APX, 0xF7 },
+ { "shrx", T_0F38 | T_F2 | T_APX, 0xF7 },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl& p = tbl[i];
- 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);
+ printf("void %s(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opRRO(r1, r2, op, %s, 0x%x); }\n", p.name, type2String(p.type).c_str(), p.code);
}
- puts("void rorx(const Reg32e& r, const Operand& op, uint8_t imm) { opGpr(r, op, Reg32e(0, r.getBit()), T_0F3A | T_F2, 0xF0, false, imm); }");
+ puts("void rorx(const Reg32e& r, const Operand& op, uint8_t imm) { opRRO(r, Reg32e(0, r.getBit()), op, T_0F3A|T_F2|T_APX, 0xF0, imm); }");
}
// gpr(reg, r/m)
{
const struct Tbl {
const char *name;
- int type;
+ uint64_t type;
uint8_t code;
uint8_t idx;
} tbl[] = {
- { "blsi", T_0F38, 0xF3, 3 },
- { "blsmsk", T_0F38, 0xF3, 2 },
- { "blsr", T_0F38, 0xF3, 1 },
+ { "blsi", T_0F38 | T_APX|T_NF, 0xF3, 3 },
+ { "blsmsk", T_0F38 | T_APX|T_NF, 0xF3, 2 },
+ { "blsr", T_0F38 | T_APX|T_NF, 0xF3, 1 },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl& p = tbl[i];
- 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);
+ printf("void %s(const Reg32e& r, const Operand& op) { opRRO(Reg32e(%d, r.getBit()), r, op, %s, 0x%x); }\n", p.name, p.idx, type2String(p.type).c_str(), p.code);
}
}
// gather
@@ -1788,7 +1878,7 @@ void put()
const struct Tbl {
uint8_t code;
const char *name;
- int type;
+ uint64_t type;
} tbl[] = {
{ 0x50, "vpdpbusd", T_66 | T_0F38 | T_YMM | T_EW0 | T_SAE_Z | T_B32},
{ 0x51, "vpdpbusds", T_66 | T_0F38 | T_YMM | T_EW0 | T_SAE_Z | T_B32},
@@ -1799,16 +1889,17 @@ void put()
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- std::string type = type2String(p->type);
- printf("void %s(const Xmm& x1, const Xmm& x2, const Operand& op, PreferredEncoding encoding = DefaultEncoding) { opEncoding(x1, x2, op, %s, 0x%02X, encoding); }\n", p->name, type.c_str(), p->code);
+ std::string s = type2String(p->type);
+ printf("void %s(const Xmm& x1, const Xmm& x2, const Operand& op, PreferredEncoding encoding = DefaultEncoding) { opEncoding(x1, x2, op, %s, 0x%02X, encoding); }\n", p->name, s.c_str(), p->code);
}
}
// avx-vnni-int8
+ // avx-vnni-int16
{
const struct Tbl {
uint8_t code;
const char *name;
- int type;
+ uint64_t type;
} tbl[] = {
{ 0x50, "vpdpbssd", T_F2 | T_0F38 | T_W0 | T_YMM },
{ 0x51, "vpdpbssds", T_F2 | T_0F38 | T_W0 | T_YMM },
@@ -1816,11 +1907,18 @@ void put()
{ 0x51, "vpdpbsuds", T_F3 | T_0F38 | T_W0 | T_YMM },
{ 0x50, "vpdpbuud", T_0F38 | T_W0 | T_YMM },
{ 0x51, "vpdpbuuds", T_0F38 | T_W0 | T_YMM },
+
+ { 0xD2, "vpdpwsud", T_F3 | T_0F38 | T_W0 | T_YMM },
+ { 0xD3, "vpdpwsuds", T_F3 | T_0F38 | T_W0 | T_YMM },
+ { 0xD2, "vpdpwusd", T_66 | T_0F38 | T_W0 | T_YMM },
+ { 0xD3, "vpdpwusds", T_66 | T_0F38 | T_W0 | T_YMM },
+ { 0xD2, "vpdpwuud", T_0F38 | T_W0 | T_YMM },
+ { 0xD3, "vpdpwuuds", T_0F38 | T_W0 | T_YMM },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- std::string type = type2String(p->type);
- printf("void %s(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, %s, 0x%02X); }\n", p->name, type.c_str(), p->code);
+ std::string s = type2String(p->type);
+ printf("void %s(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, %s, 0x%02X); }\n", p->name, s.c_str(), p->code);
}
}
}
@@ -1846,8 +1944,8 @@ void put32()
{ "popa", 0x61 },
};
putGeneric(tbl, NUM_OF_ARRAY(tbl));
- putLoadSeg("lds", 0xC5, NONE);
- putLoadSeg("les", 0xC4, NONE);
+ putLoadSeg("lds", 0, 0xC5);
+ putLoadSeg("les", 0, 0xC4);
}
void put64()
@@ -1855,28 +1953,35 @@ void put64()
put_jREGz("ecx", true);
put_jREGz("rcx", false);
- const GenericTbl tbl[] = {
- { "cdqe", 0x48, 0x98 },
- { "cqo", 0x48, 0x99 },
- { "cmpsq", 0x48, 0xA7 },
- { "popfq", 0x9D },
- { "pushfq", 0x9C },
- { "lodsq", 0x48, 0xAD },
- { "movsq", 0x48, 0xA5 },
- { "scasq", 0x48, 0xAF },
- { "stosq", 0x48, 0xAB },
- { "syscall", 0x0F, 0x05 },
- { "sysret", 0x0F, 0x07 },
- };
- putGeneric(tbl, NUM_OF_ARRAY(tbl));
+ {
+ const GenericTbl tbl[] = {
+ { "cdqe", 0x48, 0x98 },
+ { "cqo", 0x48, 0x99 },
+ { "cmpsq", 0x48, 0xA7 },
+ { "popfq", 0x9D },
+ { "pushfq", 0x9C },
+ { "lodsq", 0x48, 0xAD },
+ { "movsq", 0x48, 0xA5 },
+ { "scasq", 0x48, 0xAF },
+ { "stosq", 0x48, 0xAB },
+ { "syscall", 0x0F, 0x05 },
+ { "sysret", 0x0F, 0x07 },
+ { "clui", 0xF3, 0x0F, 0x01, 0xEE },
+ { "stui", 0xF3, 0x0F, 0x01, 0xEF },
+ { "testui", 0xF3, 0x0F, 0x01, 0xED },
+ { "uiret", 0xF3, 0x0F, 0x01, 0xEC },
+ };
+ putGeneric(tbl, NUM_OF_ARRAY(tbl));
+ }
- putMemOp("cmpxchg16b", 0, 1, 0x0F, 0xC7, 64);
- putMemOp("fxrstor64", 0, 1, 0x0F, 0xAE, 64);
- puts("void movq(const Reg64& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x7E); }");
- puts("void movq(const Mmx& mmx, const Reg64& reg) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x6E); }");
- puts("void movsxd(const Reg64& reg, const Operand& op) { if (!op.isBit(32)) XBYAK_THROW(ERR_BAD_COMBINATION) opModRM(reg, op, op.isREG(), op.isMEM(), 0x63); }");
- puts("void pextrq(const Operand& op, const Xmm& xmm, uint8_t imm) { if (!op.isREG(64) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opGen(Reg64(xmm.getIdx()), op, 0x16, 0x66, 0, imm, 0x3A); }");
- puts("void pinsrq(const Xmm& xmm, const Operand& op, uint8_t imm) { if (!op.isREG(64) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opGen(Reg64(xmm.getIdx()), op, 0x22, 0x66, 0, imm, 0x3A); }");
+ putMemOp("cmpxchg16b", "T_0F", 1, 0xC7, 64);
+ putMemOp("fxrstor64", "T_0F", 1, 0xAE, 64);
+ puts("void movq(const Reg64& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opRR(mmx, reg, T_0F, 0x7E); }");
+ puts("void movq(const Mmx& mmx, const Reg64& reg) { if (mmx.isXMM()) db(0x66); opRR(mmx, reg, T_0F, 0x6E); }");
+ puts("void movsxd(const Reg64& reg, const Operand& op) { if (!op.isBit(32)) XBYAK_THROW(ERR_BAD_COMBINATION) opRO(reg, op, 0, 0x63); }");
+ puts("void pextrq(const Operand& op, const Xmm& xmm, uint8_t imm) { if (!op.isREG(64) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opSSE(Reg64(xmm.getIdx()), op, T_66 | T_0F3A, 0x16, 0, imm); }");
+ puts("void pinsrq(const Xmm& xmm, const Operand& op, uint8_t imm) { if (!op.isREG(64) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opSSE(Reg64(xmm.getIdx()), op, T_66 | T_0F3A, 0x22, 0, imm); }");
+ puts("void senduipi(const Reg64& r) { opRR(Reg32(6), r.cvt32(), T_F3 | T_0F, 0xC7); }");
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); }");
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); }");
@@ -1885,6 +1990,11 @@ void put64()
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); }");
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); }");
+ puts("void jmpabs(uint64_t addr) { db(0xD5); db(0x00); db(0xA1); dq(addr); }");
+ puts("void push2(const Reg64& r1, const Reg64& r2) { opROO(r1, r2, Reg64(6), T_APX|T_ND1|T_W0, 0xFF); }");
+ puts("void push2p(const Reg64& r1, const Reg64& r2) { opROO(r1, r2, Reg64(6), T_APX|T_ND1|T_W1, 0xFF); }");
+ puts("void pop2(const Reg64& r1, const Reg64& r2) { opROO(r1, r2, Reg64(0), T_APX|T_ND1|T_W0, 0x8F); }");
+ puts("void pop2p(const Reg64& r1, const Reg64& r2) { opROO(r1, r2, Reg64(0), T_APX|T_ND1|T_W1, 0x8F); }");
// CMPccXADD
{
const struct Tbl {
@@ -1910,19 +2020,51 @@ void put64()
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
- printf("void cmp%sxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0x%02X, false); }\n", p->name, p->code);
+ printf("void cmp%sxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opRRO(r1, r2, addr, T_APX|T_66|T_0F38, 0x%02X); }\n", p->name, p->code);
+ }
+ }
+ // aes
+ {
+ const struct Tbl {
+ const char *name;
+ uint64_t type1;
+ uint64_t type2;
+ uint8_t code;
+ int idx;
+ } tbl[] = {
+ { "aesdec128kl", T_F3|T_0F38, T_MUST_EVEX|T_F3, 0xDD, 8 },
+ { "aesdec256kl", T_F3|T_0F38, T_MUST_EVEX|T_F3, 0xDF, 8 },
+ { "aesdecwide128kl", T_F3|T_0F38, T_MUST_EVEX|T_F3, 0xD8, 1 },
+ { "aesdecwide256kl", T_F3|T_0F38, T_MUST_EVEX|T_F3, 0xD8, 3 },
+ { "aesenc128kl", T_F3|T_0F38, T_MUST_EVEX|T_F3, 0xDC, 8 },
+ { "aesenc256kl", T_F3|T_0F38, T_MUST_EVEX|T_F3, 0xDE, 8 },
+ { "aesencwide128kl", T_F3|T_0F38, T_MUST_EVEX|T_F3, 0xD8, 0 },
+ { "aesencwide256kl", T_F3|T_0F38, T_MUST_EVEX|T_F3, 0xD8, 2 },
+ };
+ for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
+ const Tbl *p = &tbl[i];
+ std::string s1 = type2String(p->type1);
+ std::string s2 = type2String(p->type2);
+ if (p->idx == 8) {
+ printf("void %s(const Xmm& x, const Address& addr) { opSSE_APX(x, addr, %s, 0x%02X, %s, 0x%02X); }\n", p->name, s1.c_str(), p->code, s2.c_str(), p->code);
+ } else {
+ printf("void %s(const Address& addr) { opSSE_APX(xmm%d, addr, %s, 0x%02X, %s, 0x%02X); }\n", p->name, p->idx, s1.c_str(), p->code, s2.c_str(), p->code);
+ }
}
}
+ // encodekey
+ puts("void encodekey128(const Reg32& r1, const Reg32& r2) { opEncodeKey(r1, r2, 0xFA, 0xDA); }");
+ puts("void encodekey256(const Reg32& r1, const Reg32& r2) { opEncodeKey(r1, r2, 0xFB, 0xDB); }");
}
void putAMX_TILE()
{
- puts("void ldtilecfg(const Address& addr) { opVex(tmm0, &tmm0, addr, T_0F38 | T_W0, 0x49); }");
- puts("void sttilecfg(const Address& addr) { opVex(tmm0, &tmm0, addr, T_66 | T_0F38 | T_W0, 0x49); }");
- puts("void tileloadd(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_F2 | T_0F38 | T_W0, 0x4b); }");
- puts("void tileloaddt1(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_66 | T_0F38 | T_W0, 0x4b); }");
+ puts("void ldtilecfg(const Address& addr) { if (opROO(Reg(), addr, tmm0, T_APX|T_0F38|T_W0, 0x49)) return; opVex(tmm0, &tmm0, addr, T_0F38|T_W0, 0x49); }");
+ puts("void sttilecfg(const Address& addr) { if (opROO(Reg(), addr, tmm0, T_APX|T_66|T_0F38|T_W0, 0x49)) return; opVex(tmm0, &tmm0, addr, T_66|T_0F38 | T_W0, 0x49); }");
+ puts("void tileloadd(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_F2|T_0F38|T_W0, 0x4B); }");
+ puts("void tileloaddt1(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_66|T_0F38|T_W0, 0x4B); }");
puts("void tilerelease() { db(0xc4); db(0xe2); db(0x78); db(0x49); db(0xc0); }");
- puts("void tilestored(const Address& addr, const Tmm& tm) { opVex(tm, &tmm0, addr, T_F3 | T_0F38 | T_W0, 0x4b); }");
+ puts("void tilestored(const Address& addr, const Tmm& tm) { if (opROO(Reg(), addr, tm, T_APX|T_F3|T_0F38|T_W0, 0x4B)) return; opVex(tm, &tmm0, addr, T_F3|T_0F38|T_W0, 0x4B); }");
puts("void tilezero(const Tmm& Tmm) { opVex(Tmm, &tmm0, tmm0, T_F2 | T_0F38 | T_W0, 0x49); }");
}
void putAMX_INT8()