Squashed 'externals/xbyak/' changes from d512551e..2794cde7

2794cde7 add xword, yword, etc. in Xbyak::util
fb9c04e4 fix document for vfpclassps
a51be78b fix test dependency
04fdfb1e update version
e6354f8b add vgf2p8mulb
09a12642 add gf2p8affineqb
d171ba0e add gf2p8affineinvqb
457f4fd0 add vpshufbitqmb
5af0ba39 add vpexpand{b,w}
e450f965 vpopcnt{d,q} supports ptr_b
48499eb1 add vpdpbusd(s), vpdpwssd(s)
9c745109 add vpdpbusd, vpdpbusds
0e1a11b4 add vpopcnt{b,w,d,q}
9acfc132 add vpshrd(v){w,d,q}
ac8de850 add vpshld(v){w,d,q}
f181c259 add vcompressb, vcompressw
5a402477 vpclmulqdq supports AVX-512
9e16b40b vaes* supports AVX-512
7fde08e0 add flags for intel's manual 319433-030.pdf
c5da3778 add test of v4fmaddps, vp4dpwssd, etc.
e4fc9d8a fix mpx encoding
d0b2fb62 add bnd(0xf2) prefix for MPX
f12b5678 use db for array
cd74ab44 remove bat file

git-subtree-dir: externals/xbyak
git-subtree-split: 2794cde79eb71e86490061cac9622ad0067b8d15
This commit is contained in:
MerryMage 2020-04-22 20:45:52 +01:00
parent 4ed09fda06
commit 9fb82036ca
16 changed files with 935 additions and 173 deletions

View file

@ -228,6 +228,9 @@ void putXM_X()
{ 0x8B, "vpcompressd", T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0 | T_N4 }, { 0x8B, "vpcompressd", T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0 | T_N4 },
{ 0x8B, "vpcompressq", T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1 | T_N8 }, { 0x8B, "vpcompressq", T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1 | T_N8 },
{ 0x63, "vcompressb", T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0 | T_N1 },
{ 0x63, "vcompressw", T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1 | T_N2 },
}; };
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) { for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i]; const Tbl *p = &tbl[i];
@ -343,6 +346,28 @@ void putX_X_XM_IMM()
{ 0xB4, "vpmadd52luq", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_B64, false }, { 0xB4, "vpmadd52luq", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_B64, false },
{ 0xB5, "vpmadd52huq", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_B64, false }, { 0xB5, "vpmadd52huq", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_B64, false },
{ 0x70, "vpshldw", T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW1 | T_SAE_Z, true },
{ 0x71, "vpshldd", T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW0 | T_SAE_Z | T_B32, true },
{ 0x71, "vpshldq", T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW1 | T_SAE_Z | T_B64, true },
{ 0x70, "vpshldvw", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_SAE_Z, false },
{ 0x71, "vpshldvd", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_SAE_Z | T_B32, false },
{ 0x71, "vpshldvq", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_SAE_Z | T_B64, false },
{ 0x72, "vpshrdw", T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW1 | T_SAE_Z, true },
{ 0x73, "vpshrdd", T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW0 | T_SAE_Z | T_B32, true },
{ 0x73, "vpshrdq", T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW1 | T_SAE_Z | T_B64, true },
{ 0x72, "vpshrdvw", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_SAE_Z, false },
{ 0x73, "vpshrdvd", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_SAE_Z | T_B32, false },
{ 0x73, "vpshrdvq", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_SAE_Z | T_B64, false },
{ 0x50, "vpdpbusd", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_SAE_Z | T_B32, false },
{ 0x51, "vpdpbusds", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_SAE_Z | T_B32, false },
{ 0x52, "vpdpwssd", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_SAE_Z | T_B32, false },
{ 0x53, "vpdpwssds", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_SAE_Z | T_B32, false },
}; };
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) { for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i]; const Tbl *p = &tbl[i];
@ -623,6 +648,14 @@ void putX_XM_IMM()
{ 0x56, "vreducepd", T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW1 | T_B64 | T_SAE_Z, true }, { 0x56, "vreducepd", T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW1 | T_B64 | T_SAE_Z, true },
{ 0x56, "vreduceps", T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW0 | T_B32 | T_SAE_Z, true }, { 0x56, "vreduceps", T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW0 | T_B32 | T_SAE_Z, true },
{ 0x54, "vpopcntb", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_SAE_Z, false },
{ 0x54, "vpopcntw", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_SAE_Z, false },
{ 0x55, "vpopcntd", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_SAE_Z | T_B32, false },
{ 0x55, "vpopcntq", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_SAE_Z | T_B64, false },
{ 0x62, "vpexpandb", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_SAE_Z | T_N1, false },
{ 0x62, "vpexpandw", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_SAE_Z | T_N2, false },
}; };
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) { for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i]; const Tbl *p = &tbl[i];
@ -661,6 +694,8 @@ void putMisc()
puts("void vfpclassps(const Opmask& k, const Operand& op, uint8 imm) { if (!op.isBit(128|256|512)) throw Error(ERR_BAD_MEM_SIZE); Reg x = k; x.setBit(op.getBit()); opVex(x, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_YMM | T_EW0 | T_B32, 0x66, imm); }"); puts("void vfpclassps(const Opmask& k, const Operand& op, uint8 imm) { if (!op.isBit(128|256|512)) throw Error(ERR_BAD_MEM_SIZE); Reg x = k; x.setBit(op.getBit()); opVex(x, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_YMM | T_EW0 | T_B32, 0x66, imm); }");
puts("void vfpclasssd(const Opmask& k, const Operand& op, uint8 imm) { if (!op.isXMEM()) throw Error(ERR_BAD_MEM_SIZE); opVex(k, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_EW1 | T_N8, 0x67, imm); }"); puts("void vfpclasssd(const Opmask& k, const Operand& op, uint8 imm) { if (!op.isXMEM()) throw Error(ERR_BAD_MEM_SIZE); opVex(k, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_EW1 | T_N8, 0x67, imm); }");
puts("void vfpclassss(const Opmask& k, const Operand& op, uint8 imm) { if (!op.isXMEM()) throw Error(ERR_BAD_MEM_SIZE); opVex(k, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_EW0 | T_N4, 0x67, imm); }"); puts("void vfpclassss(const Opmask& k, const Operand& op, uint8 imm) { if (!op.isXMEM()) throw Error(ERR_BAD_MEM_SIZE); opVex(k, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_EW0 | T_N4, 0x67, imm); }");
puts("void vpshufbitqmb(const Opmask& k, const Xmm& x, const Operand& op) { opVex(k, &x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8F); }");
} }
void putV4FMA() void putV4FMA()

View file

@ -60,7 +60,7 @@ void putX_X_XM(bool omitOnly)
{ 0x02, "pblendd", T_0F3A | T_66 | T_W0 | T_YMM, true, true, 2 }, { 0x02, "pblendd", T_0F3A | T_66 | T_W0 | T_YMM, true, true, 2 },
{ 0x0B, "roundsd", T_0F3A | T_66 | T_W0, true, true, 3 }, { 0x0B, "roundsd", T_0F3A | T_66 | T_W0, true, true, 3 },
{ 0x0A, "roundss", T_0F3A | T_66 | T_W0, true, true, 3 }, { 0x0A, "roundss", T_0F3A | T_66 | T_W0, true, true, 3 },
{ 0x44, "pclmulqdq", T_0F3A | T_66 | T_W0, true, true, 3 }, { 0x44, "pclmulqdq", T_0F3A | T_66 | T_W0 | T_YMM | T_EVEX, true, true, 3 },
{ 0x0C, "permilps", T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW0 | T_B32, false, false, 2 }, { 0x0C, "permilps", T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW0 | T_B32, false, false, 2 },
{ 0x0D, "permilpd", T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW1 | T_B64, false, false, 2 }, { 0x0D, "permilpd", T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW1 | T_B64, false, false, 2 },
@ -202,6 +202,10 @@ void putX_X_XM(bool omitOnly)
{ 0x14, "unpcklpd", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, false, true, 2 }, { 0x14, "unpcklpd", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, false, true, 2 },
{ 0x14, "unpcklps", T_0F | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 2 }, { 0x14, "unpcklps", T_0F | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 2 },
{ 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 },
}; };
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) { for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i]; const Tbl *p = &tbl[i];
@ -615,6 +619,7 @@ void put()
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
{ {
const GenericTbl tbl[] = { const GenericTbl tbl[] = {
{ "bnd", 0xf2 }, /* 0xf2 prefix for MPX */
{ "cbw", 0x66, 0x98 }, { "cbw", 0x66, 0x98 },
{ "cdq", 0x99 }, { "cdq", 0x99 },
{ "clc", 0xF8 }, { "clc", 0xF8 },
@ -941,11 +946,11 @@ void put()
puts("void bndcl(const BoundsReg& bnd, const Operand& op) { db(0xF3); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); }"); 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 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 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) { opModM(addr, bnd, 0x0F, 0x1A); }"); 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 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 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 bndmov(const Address& addr, const BoundsReg& bnd) { db(0x66); opModM(addr, bnd, 0x0F, 0x1B); }");
puts("void bndstx(const Address& addr, const BoundsReg& bnd) { opModM(addr, bnd, 0x0F, 0x1B); }"); puts("void bndstx(const Address& addr, const BoundsReg& bnd) { opMIB(addr, bnd, 0x0F, 0x1B); }");
} }
// misc // misc
{ {
@ -1257,10 +1262,10 @@ void put()
{ 0x7D, "hsubpd", T_0F | T_66 | T_YMM, 3 }, { 0x7D, "hsubpd", T_0F | T_66 | T_YMM, 3 },
{ 0x7D, "hsubps", T_0F | T_F2 | T_YMM, 3 }, { 0x7D, "hsubps", T_0F | T_F2 | T_YMM, 3 },
{ 0xDC, "aesenc", T_0F38 | T_66 | T_W0, 3 }, { 0xDC, "aesenc", T_0F38 | T_66 | T_YMM | T_EVEX, 3 },
{ 0xDD, "aesenclast", T_0F38 | T_66 | T_W0, 3 }, { 0xDD, "aesenclast", T_0F38 | T_66 | T_YMM | T_EVEX, 3 },
{ 0xDE, "aesdec", T_0F38 | T_66 | T_W0, 3 }, { 0xDE, "aesdec", T_0F38 | T_66 | T_YMM | T_EVEX, 3 },
{ 0xDF, "aesdeclast", T_0F38 | T_66 | T_W0, 3 }, { 0xDF, "aesdeclast", T_0F38 | T_66 | T_YMM | T_EVEX, 3 },
}; };
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) { for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i]; const Tbl *p = &tbl[i];

View file

@ -1,5 +1,5 @@
Xbyak 5.52 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++ Xbyak 5.601 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++
============= =============
Abstract Abstract
@ -128,7 +128,7 @@ vcvtpd2dq xmm19, [eax+32]{1to4} --> vcvtpd2dq(xmm19, yword_b [eax+32]);
vfpclassps k5{k3}, zword [rax+64], 5 --> vfpclassps(k5|k3, zword [rax+64], 5); // specify m512 vfpclassps k5{k3}, zword [rax+64], 5 --> vfpclassps(k5|k3, zword [rax+64], 5); // specify m512
vfpclasspd k5{k3}, [rax+64]{1to2}, 5 --> vfpclasspd(k5|k3, xword_b [rax+64], 5); // broadcast 64-bit to 128-bit vfpclasspd k5{k3}, [rax+64]{1to2}, 5 --> vfpclasspd(k5|k3, xword_b [rax+64], 5); // broadcast 64-bit to 128-bit
vfpclassps k5{k3}, [rax+64]{1to4}, 5 --> vfpclassps(k5|k3, xword_b [rax+64], 5); // broadcast 32-bit to 128-bit vfpclassps k5{k3}, [rax+64]{1to4}, 5 --> vfpclassps(k5|k3, yword_b [rax+64], 5); // broadcast 64-bit to 256-bit
``` ```
Remark Remark
* k1, ..., k7 are new opmask registers. * k1, ..., k7 are new opmask registers.
@ -333,6 +333,9 @@ The header files under xbyak/ are independent of cybozulib.
History History
------------- -------------
* 2018/Jan/24 ver 5.601 add xword, yword, etc. into Xbyak::util namespace
* 2018/Jan/05 ver 5.60 support AVX-512 for Ice lake(319433-030.pdf)
* 2017/Aug/22 ver 5.53 fix mpx encoding, add bnd() prefix
* 2017/Aug/18 ver 5.52 fix align (thanks to MerryMage) * 2017/Aug/18 ver 5.52 fix align (thanks to MerryMage)
* 2017/Aug/17 ver 5.51 add multi-byte nop and align() uses it(thanks to inolen) * 2017/Aug/17 ver 5.51 add multi-byte nop and align() uses it(thanks to inolen)
* 2017/Aug/08 ver 5.50 add mpx(thanks to magurosan) * 2017/Aug/08 ver 5.50 add mpx(thanks to magurosan)

View file

@ -1,5 +1,5 @@
C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 5.52 C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 5.601
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
◎概要 ◎概要
@ -155,7 +155,7 @@ vcvtpd2dq xmm19, [eax+32]{1to4} --> vcvtpd2dq(xmm19, yword_b [eax+32]);
vfpclassps k5{k3}, zword [rax+64], 5 --> vfpclassps(k5|k3, zword [rax+64], 5); // specify m512 vfpclassps k5{k3}, zword [rax+64], 5 --> vfpclassps(k5|k3, zword [rax+64], 5); // specify m512
vfpclasspd k5{k3}, [rax+64]{1to2}, 5 --> vfpclasspd(k5|k3, xword_b [rax+64], 5); // broadcast 64-bit to 128-bit vfpclasspd k5{k3}, [rax+64]{1to2}, 5 --> vfpclasspd(k5|k3, xword_b [rax+64], 5); // broadcast 64-bit to 128-bit
vfpclassps k5{k3}, [rax+64]{1to4}, 5 --> vfpclassps(k5|k3, xword_b [rax+64], 5); // broadcast 32-bit to 128-bit vfpclassps k5{k3}, [rax+64]{1to4}, 5 --> vfpclassps(k5|k3, xword_b [rax+64], 5); // broadcast 64-bit to 256-bit
注意 注意
@ -343,6 +343,9 @@ cybozulibは単体テストでのみ利用されていて、xbyak/ディレク
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
◎履歴 ◎履歴
2018/01/24 ver 5.601 xword, ywordなどをXbyak::util名前空間に追加
2018/01/05 ver 5.60 Ice lake系命令対応(319433-030.pdf)
2017/08/22 ver 5.53 mpxエンコーディングバグ修正, bnd()プレフィクス追加
2017/08/18 ver 5.52 align修正(thanks to MerryMage) 2017/08/18 ver 5.52 align修正(thanks to MerryMage)
2017/08/17 ver 5.51 multi-byte nop追加 align()はそれを使用する(thanks to inolen) 2017/08/17 ver 5.51 multi-byte nop追加 align()はそれを使用する(thanks to inolen)
2017/08/08 ver 5.50 mpx追加(thanks to magurosan) 2017/08/08 ver 5.50 mpx追加(thanks to magurosan)

View file

@ -61,15 +61,23 @@ void putCPUinfo()
{ Cpu::tMOVBE, "movbe" }, { Cpu::tMOVBE, "movbe" },
{ Cpu::tAVX512F, "avx512f" }, { Cpu::tAVX512F, "avx512f" },
{ Cpu::tAVX512DQ, "avx512dq" }, { Cpu::tAVX512DQ, "avx512dq" },
{ Cpu::tAVX512IFMA, "avx512ifma" }, { Cpu::tAVX512IFMA, "avx512_ifma" },
{ Cpu::tAVX512PF, "avx512pf" }, { Cpu::tAVX512PF, "avx512pf" },
{ Cpu::tAVX512ER, "avx512er" }, { Cpu::tAVX512ER, "avx512er" },
{ Cpu::tAVX512CD, "avx512cd" }, { Cpu::tAVX512CD, "avx512cd" },
{ Cpu::tAVX512BW, "avx512bw" }, { Cpu::tAVX512BW, "avx512bw" },
{ Cpu::tAVX512VL, "avx512vl" }, { Cpu::tAVX512VL, "avx512vl" },
{ Cpu::tAVX512VBMI, "avx512vbmi" }, { Cpu::tAVX512VBMI, "avx512_vbmi" },
{ Cpu::tAVX512_4VNNIW, "avx512_4vnniw" }, { Cpu::tAVX512_4VNNIW, "avx512_4vnniw" },
{ Cpu::tAVX512_4FMAPS, "avx512_4fmaps" }, { Cpu::tAVX512_4FMAPS, "avx512_4fmaps" },
{ Cpu::tAVX512_VBMI2, "avx512_vbmi2" },
{ Cpu::tGFNI, "gfni" },
{ Cpu::tVAES, "vaes" },
{ Cpu::tVPCLMULQDQ, "vpclmulqdq" },
{ Cpu::tAVX512_VNNI, "avx512_vnni" },
{ Cpu::tAVX512_BITALG, "avx512_bitalg" },
{ Cpu::tAVX512_VPOPCNTDQ, "avx512_vpopcntdq" },
}; };
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) { for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
if (cpu.has(tbl[i].type)) printf(" %s", tbl[i].str); if (cpu.has(tbl[i].type)) printf(" %s", tbl[i].str);

View file

@ -1,8 +0,0 @@
@echo off
rm a.lst b.lst
echo nasm
nasm -l a.lst -f win64 test.asm
cat a.lst
echo yasm
yasm -l b.lst -f win64 test.asm
cat b.lst

View file

@ -1,11 +1,11 @@
TARGET = make_nm normalize_prefix jmp address nm_frame bad_address misc TARGET = make_nm normalize_prefix jmp address bad_address misc
XBYAK_INC=../xbyak/xbyak.h XBYAK_INC=../xbyak/xbyak.h
BIT=32 BIT=32
ifeq ($(shell uname -m),x86_64) ifeq ($(shell uname -m),x86_64)
BIT=64 BIT=64
endif endif
ifeq ($(MODE_BIT),64) ifeq ($(BIT),64)
TARGET += jmp64 address64 TARGET += jmp64 address64
endif endif
@ -28,14 +28,12 @@ address: address.cpp ../xbyak/xbyak.h
$(CXX) $(CFLAGS) address.cpp -o $@ -m32 $(CXX) $(CFLAGS) address.cpp -o $@ -m32
address64: address.cpp ../xbyak/xbyak.h address64: address.cpp ../xbyak/xbyak.h
$(CXX) $(CFLAGS) address.cpp -o $@ -m64 $(CXX) $(CFLAGS) address.cpp -o $@ -m64
nm_frame: nm_frame.cpp ../xbyak/xbyak.h
$(CXX) $(CFLAGS) nm_frame.cpp -o $@ -m32
bad_address: bad_address.cpp ../xbyak/xbyak.h bad_address: bad_address.cpp ../xbyak/xbyak.h
$(CXX) $(CFLAGS) bad_address.cpp -o $@ $(CXX) $(CFLAGS) bad_address.cpp -o $@
misc: misc.cpp ../xbyak/xbyak.h misc: misc.cpp ../xbyak/xbyak.h
$(CXX) $(CFLAGS) misc.cpp -o $@ $(CXX) $(CFLAGS) misc.cpp -o $@
test: normalize_prefix jmp bad_address test: normalize_prefix jmp bad_address $(TARGET)
$(MAKE) -C ../gen $(MAKE) -C ../gen
./test_nm.sh ./test_nm.sh
./test_nm.sh Y ./test_nm.sh Y
@ -65,7 +63,7 @@ ifeq ($(BIT),64)
./test_avx512.sh 64 ./test_avx512.sh 64
endif endif
clean: clean:
rm -rf *.o $(TARGET) lib_run rm -rf *.o $(TARGET) lib_run nm.cpp nm_frame make_512
lib_run: lib_test.cpp lib_run.cpp lib.h lib_run: lib_test.cpp lib_run.cpp lib.h
$(CXX) $(CFLAGS) lib_run.cpp lib_test.cpp -o lib_run $(CXX) $(CFLAGS) lib_run.cpp lib_test.cpp -o lib_run

View file

@ -86,13 +86,15 @@ public:
} }
fflush(stdout); fflush(stdout);
if (msg.empty()) { if (msg.empty()) {
int err = ngCount_ + exceptionCount_;
int total = okCount_ + err;
std::cout << "ctest:name=" << getBaseName(*argv) std::cout << "ctest:name=" << getBaseName(*argv)
<< ", module=" << list_.size() << ", module=" << list_.size()
<< ", total=" << (okCount_ + ngCount_ + exceptionCount_) << ", total=" << total
<< ", ok=" << okCount_ << ", ok=" << okCount_
<< ", ng=" << ngCount_ << ", ng=" << ngCount_
<< ", exception=" << exceptionCount_ << std::endl; << ", exception=" << exceptionCount_ << std::endl;
return 0; return err > 0 ? 1 : 0;
} else { } else {
std::cout << msg << std::endl; std::cout << msg << std::endl;
return 1; return 1;
@ -128,6 +130,15 @@ bool isEqual(const T& lhs, const U& rhs)
return lhs == rhs; return lhs == rhs;
} }
// avoid warning of comparision of integers of different signs
inline bool isEqual(size_t lhs, int rhs)
{
return lhs == size_t(rhs);
}
inline bool isEqual(int lhs, size_t rhs)
{
return size_t(lhs) == rhs;
}
inline bool isEqual(const char *lhs, const char *rhs) inline bool isEqual(const char *lhs, const char *rhs)
{ {
return strcmp(lhs, rhs) == 0; return strcmp(lhs, rhs) == 0;
@ -188,9 +199,9 @@ int main(int argc, char *argv[])
@param y [in] @param y [in]
*/ */
#define CYBOZU_TEST_EQUAL(x, y) { \ #define CYBOZU_TEST_EQUAL(x, y) { \
bool eq = cybozu::test::isEqual(x, y); \ bool _cybozu_eq = cybozu::test::isEqual(x, y); \
cybozu::test::test(eq, "CYBOZU_TEST_EQUAL", #x ", " #y, __FILE__, __LINE__); \ cybozu::test::test(_cybozu_eq, "CYBOZU_TEST_EQUAL", #x ", " #y, __FILE__, __LINE__); \
if (!eq) { \ if (!_cybozu_eq) { \
std::cout << "ctest: lhs=" << (x) << std::endl; \ std::cout << "ctest: lhs=" << (x) << std::endl; \
std::cout << "ctest: rhs=" << (y) << std::endl; \ std::cout << "ctest: rhs=" << (y) << std::endl; \
} \ } \
@ -201,22 +212,39 @@ int main(int argc, char *argv[])
@param y [in] @param y [in]
*/ */
#define CYBOZU_TEST_NEAR(x, y, eps) { \ #define CYBOZU_TEST_NEAR(x, y, eps) { \
bool isNear = fabs((x) - (y)) < eps; \ bool _cybozu_isNear = fabs((x) - (y)) < eps; \
cybozu::test::test(isNear, "CYBOZU_TEST_NEAR", #x ", " #y, __FILE__, __LINE__); \ cybozu::test::test(_cybozu_isNear, "CYBOZU_TEST_NEAR", #x ", " #y, __FILE__, __LINE__); \
if (!isNear) { \ if (!_cybozu_isNear) { \
std::cout << "ctest: lhs=" << (x) << std::endl; \ std::cout << "ctest: lhs=" << (x) << std::endl; \
std::cout << "ctest: rhs=" << (y) << std::endl; \ std::cout << "ctest: rhs=" << (y) << std::endl; \
} \ } \
} }
#define CYBOZU_TEST_EQUAL_POINTER(x, y) { \ #define CYBOZU_TEST_EQUAL_POINTER(x, y) { \
bool eq = x == y; \ bool _cybozu_eq = x == y; \
cybozu::test::test(eq, "CYBOZU_TEST_EQUAL_POINTER", #x ", " #y, __FILE__, __LINE__); \ cybozu::test::test(_cybozu_eq, "CYBOZU_TEST_EQUAL_POINTER", #x ", " #y, __FILE__, __LINE__); \
if (!eq) { \ if (!_cybozu_eq) { \
std::cout << "ctest: lhs=" << static_cast<const void*>(x) << std::endl; \ std::cout << "ctest: lhs=" << static_cast<const void*>(x) << std::endl; \
std::cout << "ctest: rhs=" << static_cast<const void*>(y) << std::endl; \ std::cout << "ctest: rhs=" << static_cast<const void*>(y) << std::endl; \
} \ } \
} }
/**
alert if x[] != y[]
@param x [in]
@param y [in]
@param n [in]
*/
#define CYBOZU_TEST_EQUAL_ARRAY(x, y, n) { \
for (size_t _cybozu_test_i = 0, _cybozu_ie = (size_t)(n); _cybozu_test_i < _cybozu_ie; _cybozu_test_i++) { \
bool _cybozu_eq = cybozu::test::isEqual((x)[_cybozu_test_i], (y)[_cybozu_test_i]); \
cybozu::test::test(_cybozu_eq, "CYBOZU_TEST_EQUAL_ARRAY", #x ", " #y ", " #n, __FILE__, __LINE__); \
if (!_cybozu_eq) { \
std::cout << "ctest: i=" << _cybozu_test_i << std::endl; \
std::cout << "ctest: lhs=" << (x)[_cybozu_test_i] << std::endl; \
std::cout << "ctest: rhs=" << (y)[_cybozu_test_i] << std::endl; \
} \
} \
}
/** /**
always alert always alert
@ -229,25 +257,25 @@ int main(int argc, char *argv[])
*/ */
#define CYBOZU_TEST_EXCEPTION_MESSAGE(statement, Exception, msg) \ #define CYBOZU_TEST_EXCEPTION_MESSAGE(statement, Exception, msg) \
{ \ { \
int ret = 0; \ int _cybozu_ret = 0; \
std::string errMsg; \ std::string _cybozu_errMsg; \
try { \ try { \
statement; \ statement; \
ret = 1; \ _cybozu_ret = 1; \
} catch (const Exception& e) { \ } catch (const Exception& _cybozu_e) { \
errMsg = e.what(); \ _cybozu_errMsg = _cybozu_e.what(); \
if (errMsg.find(msg) == std::string::npos) { \ if (_cybozu_errMsg.find(msg) == std::string::npos) { \
ret = 2; \ _cybozu_ret = 2; \
} \ } \
} catch (...) { \ } catch (...) { \
ret = 3; \ _cybozu_ret = 3; \
} \ } \
if (ret) { \ if (_cybozu_ret) { \
cybozu::test::test(false, "CYBOZU_TEST_EXCEPTION_MESSAGE", #statement ", " #Exception ", " #msg, __FILE__, __LINE__); \ cybozu::test::test(false, "CYBOZU_TEST_EXCEPTION_MESSAGE", #statement ", " #Exception ", " #msg, __FILE__, __LINE__); \
if (ret == 1) { \ if (_cybozu_ret == 1) { \
std::cout << "ctest: no exception" << std::endl; \ std::cout << "ctest: no exception" << std::endl; \
} else if (ret == 2) { \ } else if (_cybozu_ret == 2) { \
std::cout << "ctest: bad exception msg:" << errMsg << std::endl; \ std::cout << "ctest: bad exception msg:" << _cybozu_errMsg << std::endl; \
} else { \ } else { \
std::cout << "ctest: unexpected exception" << std::endl; \ std::cout << "ctest: unexpected exception" << std::endl; \
} \ } \
@ -258,17 +286,17 @@ int main(int argc, char *argv[])
#define CYBOZU_TEST_EXCEPTION(statement, Exception) \ #define CYBOZU_TEST_EXCEPTION(statement, Exception) \
{ \ { \
int ret = 0; \ int _cybozu_ret = 0; \
try { \ try { \
statement; \ statement; \
ret = 1; \ _cybozu_ret = 1; \
} catch (const Exception&) { \ } catch (const Exception&) { \
} catch (...) { \ } catch (...) { \
ret = 2; \ _cybozu_ret = 2; \
} \ } \
if (ret) { \ if (_cybozu_ret) { \
cybozu::test::test(false, "CYBOZU_TEST_EXCEPTION", #statement ", " #Exception, __FILE__, __LINE__); \ cybozu::test::test(false, "CYBOZU_TEST_EXCEPTION", #statement ", " #Exception, __FILE__, __LINE__); \
if (ret == 1) { \ if (_cybozu_ret == 1) { \
std::cout << "ctest: no exception" << std::endl; \ std::cout << "ctest: no exception" << std::endl; \
} else { \ } else { \
std::cout << "ctest: unexpected exception" << std::endl; \ std::cout << "ctest: unexpected exception" << std::endl; \

View file

@ -1,6 +1,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <string> #include <string>
#define XBYAK_NO_OP_NAMES
#include <xbyak/xbyak.h> #include <xbyak/xbyak.h>
#include <cybozu/inttype.hpp> #include <cybozu/inttype.hpp>
#include <cybozu/test.hpp> #include <cybozu/test.hpp>
@ -401,7 +402,7 @@ CYBOZU_TEST_AUTO(test5)
using namespace Xbyak; using namespace Xbyak;
inLocalLabel(); inLocalLabel();
mov(ecx, count); mov(ecx, count);
xor(eax, eax); xor_(eax, eax);
L(".lp"); L(".lp");
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
L(Label::toStr(i)); L(Label::toStr(i));

View file

@ -1363,6 +1363,22 @@ class Test {
put("bndmk", BNDREG, MEM); put("bndmk", BNDREG, MEM);
put("bndmov", BNDREG, BNDREG|MEM); put("bndmov", BNDREG, BNDREG|MEM);
put("bndstx", MEM, BNDREG); put("bndstx", MEM, BNDREG);
put("bndstx", "ptr [eax]", "[eax]", BNDREG);
put("bndstx", "ptr [eax+5]", "[eax+5]", BNDREG);
put("bndstx", "ptr [eax+500]", "[eax+500]", BNDREG);
put("bndstx", "ptr [eax+ecx]", "[eax+ecx]", BNDREG);
put("bndstx", "ptr [ecx+eax]", "[ecx+eax]", BNDREG);
put("bndstx", "ptr [eax+esp]", "[eax+esp]", BNDREG);
put("bndstx", "ptr [esp+eax]", "[esp+eax]", BNDREG);
put("bndstx", "ptr [eax+ecx*2]", "[eax+ecx*2]", BNDREG);
put("bndstx", "ptr [ecx+ecx]", "[ecx+ecx]", BNDREG);
put("bndstx", "ptr [ecx*2]", "[ecx*2]", BNDREG);
put("bndstx", "ptr [eax+ecx*2+500]", "[eax+ecx*2+500]", BNDREG);
#ifdef XBYAK64
put("bndstx", "ptr [rax+rcx*2]", "[rax+rcx*2]", BNDREG);
put("bndstx", "ptr [r9*2]", "[r9*2]", BNDREG);
put("bndstx", "ptr [r9*2+r15]", "[r9*2+r15]", BNDREG);
#endif
} }
void putFpuMem16_32() const void putFpuMem16_32() const
{ {

View file

@ -103,3 +103,583 @@ CYBOZU_TEST_AUTO(align)
} }
} c; } c;
} }
#ifdef XBYAK64
CYBOZU_TEST_AUTO(vfmaddps)
{
struct Code : Xbyak::CodeGenerator {
Code()
{
v4fmaddps(zmm1, zmm8, ptr [rdx + 64]);
v4fmaddss(xmm15, xmm8, ptr [rax + 64]);
v4fnmaddps(zmm5 | k5, zmm2, ptr [rcx + 0x80]);
v4fnmaddss(xmm31, xmm2, ptr [rsp + 0x80]);
vp4dpwssd(zmm23 | k7 | T_z, zmm1, ptr [rax + 64]);
vp4dpwssds(zmm10 | k4, zmm3, ptr [rsp + rax * 4 + 64]);
}
} c;
const uint8_t tbl[] = {
0x62, 0xf2, 0x3f, 0x48, 0x9a, 0x4a, 0x04,
0x62, 0x72, 0x3f, 0x08, 0x9b, 0x78, 0x04,
0x62, 0xf2, 0x6f, 0x4d, 0xaa, 0x69, 0x08,
0x62, 0x62, 0x6f, 0x08, 0xab, 0x7c, 0x24, 0x08,
0x62, 0xe2, 0x77, 0xcf, 0x52, 0x78, 0x04,
0x62, 0x72, 0x67, 0x4c, 0x53, 0x54, 0x84, 0x04,
};
const size_t n = sizeof(tbl) / sizeof(tbl[0]);
CYBOZU_TEST_EQUAL(c.getSize(), n);
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
}
CYBOZU_TEST_AUTO(vaes)
{
struct Code : Xbyak::CodeGenerator {
Code()
{
vaesdec(xmm20, xmm30, ptr [rcx + 64]);
vaesdec(ymm1, ymm2, ptr [rcx + 64]);
vaesdec(zmm1, zmm2, ptr [rcx + 64]);
vaesdeclast(xmm20, xmm30, ptr [rax + 64]);
vaesdeclast(ymm20, ymm30, ptr [rax + 64]);
vaesdeclast(zmm20, zmm30, ptr [rax + 64]);
vaesenc(xmm20, xmm30, ptr [rcx + 64]);
vaesenc(ymm1, ymm2, ptr [rcx + 64]);
vaesenc(zmm1, zmm2, ptr [rcx + 64]);
vaesenclast(xmm20, xmm30, ptr [rax + 64]);
vaesenclast(ymm20, ymm30, ptr [rax + 64]);
vaesenclast(zmm20, zmm30, ptr [rax + 64]);
}
} c;
const uint8_t tbl[] = {
0x62, 0xE2, 0x0D, 0x00, 0xDE, 0x61, 0x04,
0xC4, 0xE2, 0x6D, 0xDE, 0x49, 0x40,
0x62, 0xF2, 0x6D, 0x48, 0xDE, 0x49, 0x01,
0x62, 0xE2, 0x0D, 0x00, 0xDF, 0x60, 0x04,
0x62, 0xE2, 0x0D, 0x20, 0xDF, 0x60, 0x02,
0x62, 0xE2, 0x0D, 0x40, 0xDF, 0x60, 0x01,
0x62, 0xE2, 0x0D, 0x00, 0xDC, 0x61, 0x04,
0xC4, 0xE2, 0x6D, 0xDC, 0x49, 0x40,
0x62, 0xF2, 0x6D, 0x48, 0xDC, 0x49, 0x01,
0x62, 0xE2, 0x0D, 0x00, 0xDD, 0x60, 0x04,
0x62, 0xE2, 0x0D, 0x20, 0xDD, 0x60, 0x02,
0x62, 0xE2, 0x0D, 0x40, 0xDD, 0x60, 0x01,
};
const size_t n = sizeof(tbl) / sizeof(tbl[0]);
CYBOZU_TEST_EQUAL(c.getSize(), n);
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
}
CYBOZU_TEST_AUTO(vpclmulqdq)
{
struct Code : Xbyak::CodeGenerator {
Code()
{
vpclmulqdq(xmm2, xmm3, ptr [rax + 64], 3);
vpclmulqdq(ymm2, ymm3, ptr [rax + 64], 3);
vpclmulqdq(zmm2, zmm3, ptr [rax + 64], 3);
vpclmulqdq(xmm20, xmm3, ptr [rax + 64], 3);
vpclmulqdq(ymm20, ymm3, ptr [rax + 64], 3);
vpclmulqdq(zmm20, zmm3, ptr [rax + 64], 3);
}
} c;
const uint8_t tbl[] = {
0xc4, 0xe3, 0x61, 0x44, 0x50, 0x40, 0x03,
0xc4, 0xe3, 0x65, 0x44, 0x50, 0x40, 0x03,
0x62, 0xf3, 0x65, 0x48, 0x44, 0x50, 0x01, 0x03,
0x62, 0xe3, 0x65, 0x08, 0x44, 0x60, 0x04, 0x03,
0x62, 0xe3, 0x65, 0x28, 0x44, 0x60, 0x02, 0x03,
0x62, 0xe3, 0x65, 0x48, 0x44, 0x60, 0x01, 0x03,
};
const size_t n = sizeof(tbl) / sizeof(tbl[0]);
CYBOZU_TEST_EQUAL(c.getSize(), n);
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
}
CYBOZU_TEST_AUTO(vcompressb_w)
{
struct Code : Xbyak::CodeGenerator {
Code()
{
vcompressb(ptr[rax + 64], xmm1);
vcompressb(xmm30 | k5, xmm1);
vcompressb(ptr[rax + 64], ymm1);
vcompressb(ymm30 | k3 |T_z, ymm1);
vcompressb(ptr[rax + 64], zmm1);
vcompressb(zmm30 | k2 |T_z, zmm1);
vcompressw(ptr[rax + 64], xmm1);
vcompressw(xmm30 | k5, xmm1);
vcompressw(ptr[rax + 64], ymm1);
vcompressw(ymm30 | k3 |T_z, ymm1);
vcompressw(ptr[rax + 64], zmm1);
vcompressw(zmm30 | k2 |T_z, zmm1);
}
} c;
const uint8_t tbl[] = {
0x62, 0xf2, 0x7d, 0x08, 0x63, 0x48, 0x40,
0x62, 0x92, 0x7d, 0x0d, 0x63, 0xce,
0x62, 0xf2, 0x7d, 0x28, 0x63, 0x48, 0x40,
0x62, 0x92, 0x7d, 0xab, 0x63, 0xce,
0x62, 0xf2, 0x7d, 0x48, 0x63, 0x48, 0x40,
0x62, 0x92, 0x7d, 0xca, 0x63, 0xce,
0x62, 0xf2, 0xfd, 0x08, 0x63, 0x48, 0x20,
0x62, 0x92, 0xfd, 0x0d, 0x63, 0xce,
0x62, 0xf2, 0xfd, 0x28, 0x63, 0x48, 0x20,
0x62, 0x92, 0xfd, 0xab, 0x63, 0xce,
0x62, 0xf2, 0xfd, 0x48, 0x63, 0x48, 0x20,
0x62, 0x92, 0xfd, 0xca, 0x63, 0xce,
};
const size_t n = sizeof(tbl) / sizeof(tbl[0]);
CYBOZU_TEST_EQUAL(c.getSize(), n);
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
}
CYBOZU_TEST_AUTO(shld)
{
struct Code : Xbyak::CodeGenerator {
Code()
{
vpshldw(xmm5|k3|T_z, xmm2, ptr [rax + 0x40], 5);
vpshldw(ymm5|k3|T_z, ymm2, ptr [rax + 0x40], 5);
vpshldw(zmm5|k3|T_z, zmm2, ptr [rax + 0x40], 5);
vpshldd(xmm5|k3|T_z, xmm2, ptr [rax + 0x40], 5);
vpshldd(ymm5|k3|T_z, ymm2, ptr [rax + 0x40], 5);
vpshldd(zmm5|k3|T_z, zmm2, ptr [rax + 0x40], 5);
vpshldq(xmm5|k3|T_z, xmm2, ptr [rax + 0x40], 5);
vpshldq(ymm5|k3|T_z, ymm2, ptr [rax + 0x40], 5);
vpshldq(zmm5|k3|T_z, zmm2, ptr [rax + 0x40], 5);
vpshldvw(xmm5|k3|T_z, xmm2, ptr [rax + 0x40]);
vpshldvw(ymm5|k3|T_z, ymm2, ptr [rax + 0x40]);
vpshldvw(zmm5|k3|T_z, zmm2, ptr [rax + 0x40]);
vpshldvd(xmm5|k3|T_z, xmm2, ptr [rax + 0x40]);
vpshldvd(ymm5|k3|T_z, ymm2, ptr [rax + 0x40]);
vpshldvd(zmm5|k3|T_z, zmm2, ptr [rax + 0x40]);
vpshldvq(xmm5|k3|T_z, xmm2, ptr [rax + 0x40]);
vpshldvq(ymm5|k3|T_z, ymm2, ptr [rax + 0x40]);
vpshldvq(zmm5|k3|T_z, zmm2, ptr [rax + 0x40]);
}
} c;
const uint8_t tbl[] = {
0x62, 0xf3, 0xed, 0x8b, 0x70, 0x68, 0x04, 0x05,
0x62, 0xf3, 0xed, 0xab, 0x70, 0x68, 0x02, 0x05,
0x62, 0xf3, 0xed, 0xcb, 0x70, 0x68, 0x01, 0x05,
0x62, 0xf3, 0x6d, 0x8b, 0x71, 0x68, 0x04, 0x05,
0x62, 0xf3, 0x6d, 0xab, 0x71, 0x68, 0x02, 0x05,
0x62, 0xf3, 0x6d, 0xcb, 0x71, 0x68, 0x01, 0x05,
0x62, 0xf3, 0xed, 0x8b, 0x71, 0x68, 0x04, 0x05,
0x62, 0xf3, 0xed, 0xab, 0x71, 0x68, 0x02, 0x05,
0x62, 0xf3, 0xed, 0xcb, 0x71, 0x68, 0x01, 0x05,
0x62, 0xf2, 0xed, 0x8b, 0x70, 0x68, 0x04,
0x62, 0xf2, 0xed, 0xab, 0x70, 0x68, 0x02,
0x62, 0xf2, 0xed, 0xcb, 0x70, 0x68, 0x01,
0x62, 0xf2, 0x6d, 0x8b, 0x71, 0x68, 0x04,
0x62, 0xf2, 0x6d, 0xab, 0x71, 0x68, 0x02,
0x62, 0xf2, 0x6d, 0xcb, 0x71, 0x68, 0x01,
0x62, 0xf2, 0xed, 0x8b, 0x71, 0x68, 0x04,
0x62, 0xf2, 0xed, 0xab, 0x71, 0x68, 0x02,
0x62, 0xf2, 0xed, 0xcb, 0x71, 0x68, 0x01,
};
const size_t n = sizeof(tbl) / sizeof(tbl[0]);
CYBOZU_TEST_EQUAL(c.getSize(), n);
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
}
CYBOZU_TEST_AUTO(shrd)
{
struct Code : Xbyak::CodeGenerator {
Code()
{
vpshrdw(xmm5|k3|T_z, xmm2, ptr [rax + 0x40], 5);
vpshrdw(ymm5|k3|T_z, ymm2, ptr [rax + 0x40], 5);
vpshrdw(zmm5|k3|T_z, zmm2, ptr [rax + 0x40], 5);
vpshrdd(xmm5|k3|T_z, xmm2, ptr [rax + 0x40], 5);
vpshrdd(ymm5|k3|T_z, ymm2, ptr [rax + 0x40], 5);
vpshrdd(zmm5|k3|T_z, zmm2, ptr [rax + 0x40], 5);
vpshrdq(xmm5|k3|T_z, xmm2, ptr [rax + 0x40], 5);
vpshrdq(ymm5|k3|T_z, ymm2, ptr [rax + 0x40], 5);
vpshrdq(zmm5|k3|T_z, zmm2, ptr [rax + 0x40], 5);
vpshrdvw(xmm5|k3|T_z, xmm2, ptr [rax + 0x40]);
vpshrdvw(ymm5|k3|T_z, ymm2, ptr [rax + 0x40]);
vpshrdvw(zmm5|k3|T_z, zmm2, ptr [rax + 0x40]);
vpshrdvd(xmm5|k3|T_z, xmm2, ptr [rax + 0x40]);
vpshrdvd(ymm5|k3|T_z, ymm2, ptr [rax + 0x40]);
vpshrdvd(zmm5|k3|T_z, zmm2, ptr [rax + 0x40]);
vpshrdvq(xmm5|k3|T_z, xmm2, ptr [rax + 0x40]);
vpshrdvq(ymm5|k3|T_z, ymm2, ptr [rax + 0x40]);
vpshrdvq(zmm5|k3|T_z, zmm2, ptr [rax + 0x40]);
vpshrdd(xmm5|k3|T_z, xmm2, ptr_b [rax + 0x40], 5);
vpshrdd(ymm5|k3|T_z, ymm2, ptr_b [rax + 0x40], 5);
vpshrdd(zmm5|k3|T_z, zmm2, ptr_b [rax + 0x40], 5);
vpshrdq(xmm5|k3|T_z, xmm2, ptr_b [rax + 0x40], 5);
vpshrdq(ymm5|k3|T_z, ymm2, ptr_b [rax + 0x40], 5);
vpshrdq(zmm5|k3|T_z, zmm2, ptr_b [rax + 0x40], 5);
vpshrdvd(xmm5|k3|T_z, xmm2, ptr_b [rax + 0x40]);
vpshrdvd(ymm5|k3|T_z, ymm2, ptr_b [rax + 0x40]);
vpshrdvd(zmm5|k3|T_z, zmm2, ptr_b [rax + 0x40]);
vpshrdvq(xmm5|k3|T_z, xmm2, ptr_b [rax + 0x40]);
vpshrdvq(ymm5|k3|T_z, ymm2, ptr_b [rax + 0x40]);
vpshrdvq(zmm5|k3|T_z, zmm2, ptr_b [rax + 0x40]);
}
} c;
const uint8_t tbl[] = {
0x62, 0xf3, 0xed, 0x8b, 0x72, 0x68, 0x04, 0x05,
0x62, 0xf3, 0xed, 0xab, 0x72, 0x68, 0x02, 0x05,
0x62, 0xf3, 0xed, 0xcb, 0x72, 0x68, 0x01, 0x05,
0x62, 0xf3, 0x6d, 0x8b, 0x73, 0x68, 0x04, 0x05,
0x62, 0xf3, 0x6d, 0xab, 0x73, 0x68, 0x02, 0x05,
0x62, 0xf3, 0x6d, 0xcb, 0x73, 0x68, 0x01, 0x05,
0x62, 0xf3, 0xed, 0x8b, 0x73, 0x68, 0x04, 0x05,
0x62, 0xf3, 0xed, 0xab, 0x73, 0x68, 0x02, 0x05,
0x62, 0xf3, 0xed, 0xcb, 0x73, 0x68, 0x01, 0x05,
0x62, 0xf2, 0xed, 0x8b, 0x72, 0x68, 0x04,
0x62, 0xf2, 0xed, 0xab, 0x72, 0x68, 0x02,
0x62, 0xf2, 0xed, 0xcb, 0x72, 0x68, 0x01,
0x62, 0xf2, 0x6d, 0x8b, 0x73, 0x68, 0x04,
0x62, 0xf2, 0x6d, 0xab, 0x73, 0x68, 0x02,
0x62, 0xf2, 0x6d, 0xcb, 0x73, 0x68, 0x01,
0x62, 0xf2, 0xed, 0x8b, 0x73, 0x68, 0x04,
0x62, 0xf2, 0xed, 0xab, 0x73, 0x68, 0x02,
0x62, 0xf2, 0xed, 0xcb, 0x73, 0x68, 0x01,
0x62, 0xf3, 0x6d, 0x9b, 0x73, 0x68, 0x10, 0x05,
0x62, 0xf3, 0x6d, 0xbb, 0x73, 0x68, 0x10, 0x05,
0x62, 0xf3, 0x6d, 0xdb, 0x73, 0x68, 0x10, 0x05,
0x62, 0xf3, 0xed, 0x9b, 0x73, 0x68, 0x08, 0x05,
0x62, 0xf3, 0xed, 0xbb, 0x73, 0x68, 0x08, 0x05,
0x62, 0xf3, 0xed, 0xdb, 0x73, 0x68, 0x08, 0x05,
0x62, 0xf2, 0x6d, 0x9b, 0x73, 0x68, 0x10,
0x62, 0xf2, 0x6d, 0xbb, 0x73, 0x68, 0x10,
0x62, 0xf2, 0x6d, 0xdb, 0x73, 0x68, 0x10,
0x62, 0xf2, 0xed, 0x9b, 0x73, 0x68, 0x08,
0x62, 0xf2, 0xed, 0xbb, 0x73, 0x68, 0x08,
0x62, 0xf2, 0xed, 0xdb, 0x73, 0x68, 0x08,
};
const size_t n = sizeof(tbl) / sizeof(tbl[0]);
CYBOZU_TEST_EQUAL(c.getSize(), n);
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
}
CYBOZU_TEST_AUTO(vpopcnt)
{
struct Code : Xbyak::CodeGenerator {
Code()
{
vpopcntb(xmm5|k3|T_z, ptr [rax + 0x40]);
vpopcntb(ymm5|k3|T_z, ptr [rax + 0x40]);
vpopcntb(zmm5|k3|T_z, ptr [rax + 0x40]);
vpopcntw(xmm5|k3|T_z, ptr [rax + 0x40]);
vpopcntw(ymm5|k3|T_z, ptr [rax + 0x40]);
vpopcntw(zmm5|k3|T_z, ptr [rax + 0x40]);
vpopcntd(xmm5|k3|T_z, ptr [rax + 0x40]);
vpopcntd(ymm5|k3|T_z, ptr [rax + 0x40]);
vpopcntd(zmm5|k3|T_z, ptr [rax + 0x40]);
vpopcntd(xmm5|k3|T_z, ptr_b [rax + 0x40]);
vpopcntd(ymm5|k3|T_z, ptr_b [rax + 0x40]);
vpopcntd(zmm5|k3|T_z, ptr_b [rax + 0x40]);
vpopcntq(xmm5|k3|T_z, ptr [rax + 0x40]);
vpopcntq(ymm5|k3|T_z, ptr [rax + 0x40]);
vpopcntq(zmm5|k3|T_z, ptr [rax + 0x40]);
vpopcntq(xmm5|k3|T_z, ptr_b [rax + 0x40]);
vpopcntq(ymm5|k3|T_z, ptr_b [rax + 0x40]);
vpopcntq(zmm5|k3|T_z, ptr_b [rax + 0x40]);
}
} c;
const uint8_t tbl[] = {
0x62, 0xf2, 0x7d, 0x8b, 0x54, 0x68, 0x04,
0x62, 0xf2, 0x7d, 0xab, 0x54, 0x68, 0x02,
0x62, 0xf2, 0x7d, 0xcb, 0x54, 0x68, 0x01,
0x62, 0xf2, 0xfd, 0x8b, 0x54, 0x68, 0x04,
0x62, 0xf2, 0xfd, 0xab, 0x54, 0x68, 0x02,
0x62, 0xf2, 0xfd, 0xcb, 0x54, 0x68, 0x01,
0x62, 0xf2, 0x7d, 0x8b, 0x55, 0x68, 0x04,
0x62, 0xf2, 0x7d, 0xab, 0x55, 0x68, 0x02,
0x62, 0xf2, 0x7d, 0xcb, 0x55, 0x68, 0x01,
0x62, 0xf2, 0x7d, 0x9b, 0x55, 0x68, 0x10,
0x62, 0xf2, 0x7d, 0xbb, 0x55, 0x68, 0x10,
0x62, 0xf2, 0x7d, 0xdb, 0x55, 0x68, 0x10,
0x62, 0xf2, 0xfd, 0x8b, 0x55, 0x68, 0x04,
0x62, 0xf2, 0xfd, 0xab, 0x55, 0x68, 0x02,
0x62, 0xf2, 0xfd, 0xcb, 0x55, 0x68, 0x01,
0x62, 0xf2, 0xfd, 0x9b, 0x55, 0x68, 0x08,
0x62, 0xf2, 0xfd, 0xbb, 0x55, 0x68, 0x08,
0x62, 0xf2, 0xfd, 0xdb, 0x55, 0x68, 0x08,
};
const size_t n = sizeof(tbl) / sizeof(tbl[0]);
CYBOZU_TEST_EQUAL(c.getSize(), n);
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
}
CYBOZU_TEST_AUTO(vpdpbus)
{
struct Code : Xbyak::CodeGenerator {
Code()
{
vpdpbusd(xmm5|k3|T_z, xmm20, ptr [rax + 0x40]);
vpdpbusd(ymm5|k3|T_z, ymm20, ptr [rax + 0x40]);
vpdpbusd(zmm5|k3|T_z, zmm20, ptr [rax + 0x40]);
vpdpbusd(xmm5|k3|T_z, xmm20, ptr_b [rax + 0x40]);
vpdpbusd(ymm5|k3|T_z, ymm20, ptr_b [rax + 0x40]);
vpdpbusd(zmm5|k3|T_z, zmm20, ptr_b [rax + 0x40]);
vpdpbusds(xmm5|k3|T_z, xmm20, ptr [rax + 0x40]);
vpdpbusds(ymm5|k3|T_z, ymm20, ptr [rax + 0x40]);
vpdpbusds(zmm5|k3|T_z, zmm20, ptr [rax + 0x40]);
vpdpbusds(xmm5|k3|T_z, xmm20, ptr_b [rax + 0x40]);
vpdpbusds(ymm5|k3|T_z, ymm20, ptr_b [rax + 0x40]);
vpdpbusds(zmm5|k3|T_z, zmm20, ptr_b [rax + 0x40]);
vpdpwssd(xmm5|k3|T_z, xmm20, ptr [rax + 0x40]);
vpdpwssd(ymm5|k3|T_z, ymm20, ptr [rax + 0x40]);
vpdpwssd(zmm5|k3|T_z, zmm20, ptr [rax + 0x40]);
vpdpwssd(xmm5|k3|T_z, xmm20, ptr_b [rax + 0x40]);
vpdpwssd(ymm5|k3|T_z, ymm20, ptr_b [rax + 0x40]);
vpdpwssd(zmm5|k3|T_z, zmm20, ptr_b [rax + 0x40]);
vpdpwssds(xmm5|k3|T_z, xmm20, ptr [rax + 0x40]);
vpdpwssds(ymm5|k3|T_z, ymm20, ptr [rax + 0x40]);
vpdpwssds(zmm5|k3|T_z, zmm20, ptr [rax + 0x40]);
vpdpwssds(xmm5|k3|T_z, xmm20, ptr_b [rax + 0x40]);
vpdpwssds(ymm5|k3|T_z, ymm20, ptr_b [rax + 0x40]);
vpdpwssds(zmm5|k3|T_z, zmm20, ptr_b [rax + 0x40]);
}
} c;
const uint8_t tbl[] = {
0x62, 0xf2, 0x5d, 0x83, 0x50, 0x68, 0x04,
0x62, 0xf2, 0x5d, 0xa3, 0x50, 0x68, 0x02,
0x62, 0xf2, 0x5d, 0xc3, 0x50, 0x68, 0x01,
0x62, 0xf2, 0x5d, 0x93, 0x50, 0x68, 0x10,
0x62, 0xf2, 0x5d, 0xb3, 0x50, 0x68, 0x10,
0x62, 0xf2, 0x5d, 0xd3, 0x50, 0x68, 0x10,
0x62, 0xf2, 0x5d, 0x83, 0x51, 0x68, 0x04,
0x62, 0xf2, 0x5d, 0xa3, 0x51, 0x68, 0x02,
0x62, 0xf2, 0x5d, 0xc3, 0x51, 0x68, 0x01,
0x62, 0xf2, 0x5d, 0x93, 0x51, 0x68, 0x10,
0x62, 0xf2, 0x5d, 0xb3, 0x51, 0x68, 0x10,
0x62, 0xf2, 0x5d, 0xd3, 0x51, 0x68, 0x10,
0x62, 0xf2, 0x5d, 0x83, 0x52, 0x68, 0x04,
0x62, 0xf2, 0x5d, 0xa3, 0x52, 0x68, 0x02,
0x62, 0xf2, 0x5d, 0xc3, 0x52, 0x68, 0x01,
0x62, 0xf2, 0x5d, 0x93, 0x52, 0x68, 0x10,
0x62, 0xf2, 0x5d, 0xb3, 0x52, 0x68, 0x10,
0x62, 0xf2, 0x5d, 0xd3, 0x52, 0x68, 0x10,
0x62, 0xf2, 0x5d, 0x83, 0x53, 0x68, 0x04,
0x62, 0xf2, 0x5d, 0xa3, 0x53, 0x68, 0x02,
0x62, 0xf2, 0x5d, 0xc3, 0x53, 0x68, 0x01,
0x62, 0xf2, 0x5d, 0x93, 0x53, 0x68, 0x10,
0x62, 0xf2, 0x5d, 0xb3, 0x53, 0x68, 0x10,
0x62, 0xf2, 0x5d, 0xd3, 0x53, 0x68, 0x10,
};
const size_t n = sizeof(tbl) / sizeof(tbl[0]);
CYBOZU_TEST_EQUAL(c.getSize(), n);
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
}
CYBOZU_TEST_AUTO(vexpand_vpshufbitqmb)
{
struct Code : Xbyak::CodeGenerator {
Code()
{
vpexpandb(xmm5|k3|T_z, xmm30);
vpexpandb(ymm5|k3|T_z, ymm30);
vpexpandb(zmm5|k3|T_z, zmm30);
vpexpandb(xmm5|k3|T_z, ptr [rax + 0x40]);
vpexpandb(ymm5|k3|T_z, ptr [rax + 0x40]);
vpexpandb(zmm5|k3|T_z, ptr [rax + 0x40]);
vpexpandw(xmm5|k3|T_z, xmm30);
vpexpandw(ymm5|k3|T_z, ymm30);
vpexpandw(zmm5|k3|T_z, zmm30);
vpexpandw(xmm5|k3|T_z, ptr [rax + 0x40]);
vpexpandw(ymm5|k3|T_z, ptr [rax + 0x40]);
vpexpandw(zmm5|k3|T_z, ptr [rax + 0x40]);
vpshufbitqmb(k1|k2, xmm2, ptr [rax + 0x40]);
vpshufbitqmb(k1|k2, ymm2, ptr [rax + 0x40]);
vpshufbitqmb(k1|k2, zmm2, ptr [rax + 0x40]);
}
} c;
const uint8_t tbl[] = {
0x62, 0x92, 0x7d, 0x8b, 0x62, 0xee,
0x62, 0x92, 0x7d, 0xab, 0x62, 0xee,
0x62, 0x92, 0x7d, 0xcb, 0x62, 0xee,
0x62, 0xf2, 0x7d, 0x8b, 0x62, 0x68, 0x40,
0x62, 0xf2, 0x7d, 0xab, 0x62, 0x68, 0x40,
0x62, 0xf2, 0x7d, 0xcb, 0x62, 0x68, 0x40,
0x62, 0x92, 0xfd, 0x8b, 0x62, 0xee,
0x62, 0x92, 0xfd, 0xab, 0x62, 0xee,
0x62, 0x92, 0xfd, 0xcb, 0x62, 0xee,
0x62, 0xf2, 0xfd, 0x8b, 0x62, 0x68, 0x20,
0x62, 0xf2, 0xfd, 0xab, 0x62, 0x68, 0x20,
0x62, 0xf2, 0xfd, 0xcb, 0x62, 0x68, 0x20,
0x62, 0xf2, 0x6d, 0x0a, 0x8f, 0x48, 0x04,
0x62, 0xf2, 0x6d, 0x2a, 0x8f, 0x48, 0x02,
0x62, 0xf2, 0x6d, 0x4a, 0x8f, 0x48, 0x01,
};
const size_t n = sizeof(tbl) / sizeof(tbl[0]);
CYBOZU_TEST_EQUAL(c.getSize(), n);
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
}
CYBOZU_TEST_AUTO(gf2)
{
struct Code : Xbyak::CodeGenerator {
Code()
{
///
gf2p8affineinvqb(xmm1, xmm2, 3);
gf2p8affineinvqb(xmm1, ptr [rax + 0x40], 3);
vgf2p8affineinvqb(xmm1, xmm5, xmm2, 3);
vgf2p8affineinvqb(ymm1, ymm5, ymm2, 3);
vgf2p8affineinvqb(xmm1, xmm5, ptr [rax + 0x40], 3);
vgf2p8affineinvqb(ymm1, ymm5, ptr [rax + 0x40], 3);
vgf2p8affineinvqb(xmm30, xmm31, xmm4, 5);
vgf2p8affineinvqb(ymm30, ymm31, ymm4, 5);
vgf2p8affineinvqb(zmm30, zmm31, zmm4, 5);
vgf2p8affineinvqb(xmm30|k1|T_z, xmm5, ptr [rax + 0x40], 5);
vgf2p8affineinvqb(ymm30|k1|T_z, ymm5, ptr [rax + 0x40], 5);
vgf2p8affineinvqb(zmm30|k1|T_z, zmm5, ptr [rax + 0x40], 5);
vgf2p8affineinvqb(xmm30|k1|T_z, xmm5, ptr_b [rax + 0x40], 5);
vgf2p8affineinvqb(ymm30|k1|T_z, ymm5, ptr_b [rax + 0x40], 5);
vgf2p8affineinvqb(zmm30|k1|T_z, zmm5, ptr_b [rax + 0x40], 5);
///
gf2p8affineqb(xmm1, xmm2, 3);
gf2p8affineqb(xmm1, ptr [rax + 0x40], 3);
vgf2p8affineqb(xmm1, xmm5, xmm2, 3);
vgf2p8affineqb(ymm1, ymm5, ymm2, 3);
vgf2p8affineqb(xmm1, xmm5, ptr [rax + 0x40], 3);
vgf2p8affineqb(ymm1, ymm5, ptr [rax + 0x40], 3);
vgf2p8affineqb(xmm30, xmm31, xmm4, 5);
vgf2p8affineqb(ymm30, ymm31, ymm4, 5);
vgf2p8affineqb(zmm30, zmm31, zmm4, 5);
vgf2p8affineqb(xmm30|k1|T_z, xmm5, ptr [rax + 0x40], 5);
vgf2p8affineqb(ymm30|k1|T_z, ymm5, ptr [rax + 0x40], 5);
vgf2p8affineqb(zmm30|k1|T_z, zmm5, ptr [rax + 0x40], 5);
vgf2p8affineqb(xmm30|k1|T_z, xmm5, ptr_b [rax + 0x40], 5);
vgf2p8affineqb(ymm30|k1|T_z, ymm5, ptr_b [rax + 0x40], 5);
vgf2p8affineqb(zmm30|k1|T_z, zmm5, ptr_b [rax + 0x40], 5);
///
gf2p8mulb(xmm1, xmm2);
gf2p8mulb(xmm1, ptr [rax + 0x40]);
vgf2p8mulb(xmm1, xmm5, xmm2);
vgf2p8mulb(ymm1, ymm5, ymm2);
vgf2p8mulb(xmm1, xmm5, ptr [rax + 0x40]);
vgf2p8mulb(ymm1, ymm5, ptr [rax + 0x40]);
vgf2p8mulb(xmm30, xmm31, xmm4);
vgf2p8mulb(ymm30, ymm31, ymm4);
vgf2p8mulb(zmm30, zmm31, zmm4);
vgf2p8mulb(xmm30|k1|T_z, xmm5, ptr [rax + 0x40]);
vgf2p8mulb(ymm30|k1|T_z, ymm5, ptr [rax + 0x40]);
vgf2p8mulb(zmm30|k1|T_z, zmm5, ptr [rax + 0x40]);
}
} c;
const uint8_t tbl[] = {
0x66, 0x0f, 0x3a, 0xcf, 0xca, 0x03,
0x66, 0x0f, 0x3a, 0xcf, 0x48, 0x40, 0x03,
0xc4, 0xe3, 0xd1, 0xcf, 0xca, 0x03,
0xc4, 0xe3, 0xd5, 0xcf, 0xca, 0x03,
0xc4, 0xe3, 0xd1, 0xcf, 0x48, 0x40, 0x03,
0xc4, 0xe3, 0xd5, 0xcf, 0x48, 0x40, 0x03,
0x62, 0x63, 0x85, 0x00, 0xcf, 0xf4, 0x05,
0x62, 0x63, 0x85, 0x20, 0xcf, 0xf4, 0x05,
0x62, 0x63, 0x85, 0x40, 0xcf, 0xf4, 0x05,
0x62, 0x63, 0xd5, 0x89, 0xcf, 0x70, 0x04, 0x05,
0x62, 0x63, 0xd5, 0xa9, 0xcf, 0x70, 0x02, 0x05,
0x62, 0x63, 0xd5, 0xc9, 0xcf, 0x70, 0x01, 0x05,
0x62, 0x63, 0xd5, 0x99, 0xcf, 0x70, 0x08, 0x05,
0x62, 0x63, 0xd5, 0xb9, 0xcf, 0x70, 0x08, 0x05,
0x62, 0x63, 0xd5, 0xd9, 0xcf, 0x70, 0x08, 0x05,
0x66, 0x0f, 0x3a, 0xce, 0xca, 0x03,
0x66, 0x0f, 0x3a, 0xce, 0x48, 0x40, 0x03,
0xc4, 0xe3, 0xd1, 0xce, 0xca, 0x03,
0xc4, 0xe3, 0xd5, 0xce, 0xca, 0x03,
0xc4, 0xe3, 0xd1, 0xce, 0x48, 0x40, 0x03,
0xc4, 0xe3, 0xd5, 0xce, 0x48, 0x40, 0x03,
0x62, 0x63, 0x85, 0x00, 0xce, 0xf4, 0x05,
0x62, 0x63, 0x85, 0x20, 0xce, 0xf4, 0x05,
0x62, 0x63, 0x85, 0x40, 0xce, 0xf4, 0x05,
0x62, 0x63, 0xd5, 0x89, 0xce, 0x70, 0x04, 0x05,
0x62, 0x63, 0xd5, 0xa9, 0xce, 0x70, 0x02, 0x05,
0x62, 0x63, 0xd5, 0xc9, 0xce, 0x70, 0x01, 0x05,
0x62, 0x63, 0xd5, 0x99, 0xce, 0x70, 0x08, 0x05,
0x62, 0x63, 0xd5, 0xb9, 0xce, 0x70, 0x08, 0x05,
0x62, 0x63, 0xd5, 0xd9, 0xce, 0x70, 0x08, 0x05,
0x66, 0x0f, 0x38, 0xcf, 0xca,
0x66, 0x0f, 0x38, 0xcf, 0x48, 0x40,
0xc4, 0xe2, 0x51, 0xcf, 0xca,
0xc4, 0xe2, 0x55, 0xcf, 0xca,
0xc4, 0xe2, 0x51, 0xcf, 0x48, 0x40,
0xc4, 0xe2, 0x55, 0xcf, 0x48, 0x40,
0x62, 0x62, 0x05, 0x00, 0xcf, 0xf4,
0x62, 0x62, 0x05, 0x20, 0xcf, 0xf4,
0x62, 0x62, 0x05, 0x40, 0xcf, 0xf4,
0x62, 0x62, 0x55, 0x89, 0xcf, 0x70, 0x04,
0x62, 0x62, 0x55, 0xa9, 0xcf, 0x70, 0x02,
0x62, 0x62, 0x55, 0xc9, 0xcf, 0x70, 0x01,
};
const size_t n = sizeof(tbl) / sizeof(tbl[0]);
CYBOZU_TEST_EQUAL(c.getSize(), n);
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
}
#endif

View file

@ -6,6 +6,7 @@ using namespace Xbyak;
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable : 4245) #pragma warning(disable : 4245)
#pragma warning(disable : 4312)
#endif #endif
class Sample : public CodeGenerator { class Sample : public CodeGenerator {
void operator=(const Sample&); void operator=(const Sample&);

View file

@ -1,5 +1,5 @@
@echo off @echo off
set FILTER=cat set FILTER=grep -v warning
if /i "%1"=="64" ( if /i "%1"=="64" (
set OPT2=-DXBYAK64 set OPT2=-DXBYAK64
set OPT3=win64 set OPT3=win64

View file

@ -105,7 +105,7 @@ namespace Xbyak {
enum { enum {
DEFAULT_MAX_CODE_SIZE = 4096, DEFAULT_MAX_CODE_SIZE = 4096,
VERSION = 0x5520 /* 0xABCD = A.BC(D) */ VERSION = 0x5601 /* 0xABCD = A.BC(D) */
}; };
#ifndef MIE_INTEGER_TYPE_DEFINED #ifndef MIE_INTEGER_TYPE_DEFINED
@ -177,6 +177,7 @@ enum {
ERR_INVALID_OPMASK_WITH_MEMORY, ERR_INVALID_OPMASK_WITH_MEMORY,
ERR_INVALID_ZERO, ERR_INVALID_ZERO,
ERR_INVALID_RIP_IN_AUTO_GROW, ERR_INVALID_RIP_IN_AUTO_GROW,
ERR_INVALID_MIB_ADDRESS,
ERR_INTERNAL ERR_INTERNAL
}; };
@ -237,6 +238,7 @@ public:
"invalid opmask with memory", "invalid opmask with memory",
"invalid zero", "invalid zero",
"invalid rip in AutoGrow", "invalid rip in AutoGrow",
"invalid mib address",
"internal error", "internal error",
}; };
assert((size_t)err_ < sizeof(errTbl) / sizeof(*errTbl)); assert((size_t)err_ < sizeof(errTbl) / sizeof(*errTbl));
@ -345,6 +347,9 @@ public:
}; };
#endif #endif
class Address;
class Reg;
class Operand { class Operand {
static const uint8 EXT8BIT = 0x20; static const uint8 EXT8BIT = 0x20;
unsigned int idx_:6; // 0..31 + EXT8BIT = 1 if spl/bpl/sil/dil unsigned int idx_:6; // 0..31 + EXT8BIT = 1 if spl/bpl/sil/dil
@ -497,6 +502,8 @@ public:
bool isEqualIfNotInherited(const Operand& rhs) const { return idx_ == rhs.idx_ && kind_ == rhs.kind_ && bit_ == rhs.bit_ && zero_ == rhs.zero_ && mask_ == rhs.mask_ && rounding_ == rhs.rounding_; } bool isEqualIfNotInherited(const Operand& rhs) const { return idx_ == rhs.idx_ && kind_ == rhs.kind_ && bit_ == rhs.bit_ && zero_ == rhs.zero_ && mask_ == rhs.mask_ && rounding_ == rhs.rounding_; }
bool operator==(const Operand& rhs) const; bool operator==(const Operand& rhs) const;
bool operator!=(const Operand& rhs) const { return !operator==(rhs); } bool operator!=(const Operand& rhs) const { return !operator==(rhs); }
const Address& getAddress() const;
const Reg& getReg() const;
}; };
class Label; class Label;
@ -530,6 +537,12 @@ public:
#endif #endif
}; };
inline const Reg& Operand::getReg() const
{
assert(!isMEM());
return static_cast<const Reg&>(*this);
}
struct Reg8 : public Reg { struct Reg8 : public Reg {
explicit Reg8(int idx = 0, bool ext8bit = false) : Reg(idx, Operand::REG, 8, ext8bit) { } explicit Reg8(int idx = 0, bool ext8bit = false) : Reg(idx, Operand::REG, 8, ext8bit) { }
}; };
@ -543,6 +556,13 @@ struct Mmx : public Reg {
}; };
struct EvexModifierRounding { struct EvexModifierRounding {
enum {
T_RN_SAE = 1,
T_RD_SAE = 2,
T_RU_SAE = 3,
T_RZ_SAE = 4,
T_SAE = 5
};
explicit EvexModifierRounding(int rounding) : rounding(rounding) {} explicit EvexModifierRounding(int rounding) : rounding(rounding) {}
int rounding; int rounding;
}; };
@ -689,13 +709,15 @@ public:
} }
} }
bool isVsib(int bit = 128 | 256 | 512) const { return index_.isBit(bit); } bool isVsib(int bit = 128 | 256 | 512) const { return index_.isBit(bit); }
void optimize() RegExp optimize() const
{ {
RegExp exp = *this;
// [reg * 2] => [reg + reg] // [reg * 2] => [reg + reg]
if (index_.isBit(i32e) && !base_.getBit() && index_.getBit() && scale_ == 2) { if (index_.isBit(i32e) && !base_.getBit() && scale_ == 2) {
base_ = index_; exp.base_ = index_;
scale_ = 1; exp.scale_ = 1;
} }
return exp;
} }
bool operator==(const RegExp& rhs) const bool operator==(const RegExp& rhs) const
{ {
@ -715,6 +737,11 @@ public:
} }
friend RegExp operator+(const RegExp& a, const RegExp& b); friend RegExp operator+(const RegExp& a, const RegExp& b);
friend RegExp operator-(const RegExp& e, size_t disp); friend RegExp operator-(const RegExp& e, size_t disp);
uint8 getRex() const
{
uint8 rex = index_.getRexX() | base_.getRexB();
return rex ? uint8(rex | 0x40) : 0;
}
private: private:
/* /*
[base_ + index_ * scale_ + disp_] [base_ + index_ * scale_ + disp_]
@ -975,7 +1002,6 @@ public:
: Operand(0, MEM, sizeBit), e_(e), label_(0), mode_(M_ModRM), permitVsib_(false), broadcast_(broadcast) : Operand(0, MEM, sizeBit), e_(e), label_(0), mode_(M_ModRM), permitVsib_(false), broadcast_(broadcast)
{ {
e_.verify(); e_.verify();
e_.optimize();
} }
#ifdef XBYAK64 #ifdef XBYAK64
explicit Address(size_t disp) explicit Address(size_t disp)
@ -984,7 +1010,10 @@ public:
: Operand(0, MEM, sizeBit), e_(addr.disp_), label_(addr.label_), mode_(addr.isAddr_ ? M_ripAddr : M_rip), permitVsib_(false), broadcast_(broadcast) { } : Operand(0, MEM, sizeBit), e_(addr.disp_), label_(addr.label_), mode_(addr.isAddr_ ? M_ripAddr : M_rip), permitVsib_(false), broadcast_(broadcast) { }
#endif #endif
void permitVsib() const { permitVsib_ = true; } void permitVsib() const { permitVsib_ = true; }
const RegExp& getRegExp() const { return e_; } RegExp getRegExp(bool optimize = true) const
{
return optimize ? e_.optimize() : e_;
}
Mode getMode() const { return mode_; } Mode getMode() const { return mode_; }
bool is32bit() const { verify(); return e_.getBase().getBit() == 32 || e_.getIndex().getBit() == 32; } bool is32bit() const { verify(); return e_.getBase().getBit() == 32 || e_.getIndex().getBit() == 32; }
bool isOnlyDisp() const { verify(); return !e_.getBase().getBit() && !e_.getIndex().getBit(); } // for mov eax bool isOnlyDisp() const { verify(); return !e_.getBase().getBit() && !e_.getIndex().getBit(); } // for mov eax
@ -993,9 +1022,7 @@ public:
{ {
verify(); verify();
if (mode_ != M_ModRM) return 0; if (mode_ != M_ModRM) return 0;
uint8 rex = e_.getIndex().getRexX() | e_.getBase().getRexB(); return getRegExp().getRex();
if (rex) rex |= 0x40;
return rex;
} }
bool is64bitDisp() const { verify(); return mode_ == M_64bitDisp; } // for moffset bool is64bitDisp() const { verify(); return mode_ == M_64bitDisp; } // for moffset
bool isBroadcast() const { return broadcast_; } bool isBroadcast() const { return broadcast_; }
@ -1014,9 +1041,15 @@ private:
void verify() const { if (e_.isVsib() && !permitVsib_) throw Error(ERR_BAD_VSIB_ADDRESSING); } void verify() const { if (e_.isVsib() && !permitVsib_) throw Error(ERR_BAD_VSIB_ADDRESSING); }
}; };
inline const Address& Operand::getAddress() const
{
assert(isMEM());
return static_cast<const Address&>(*this);
}
inline bool Operand::operator==(const Operand& rhs) const inline bool Operand::operator==(const Operand& rhs) const
{ {
if (isMEM() && rhs.isMEM()) return static_cast<const Address&>(*this) == static_cast<const Address&>(rhs); if (isMEM() && rhs.isMEM()) return this->getAddress() == rhs.getAddress();
return isEqualIfNotInherited(rhs); return isEqualIfNotInherited(rhs);
} }
@ -1363,12 +1396,12 @@ private:
if (p1->isMEM()) std::swap(p1, p2); if (p1->isMEM()) std::swap(p1, p2);
if (p1->isMEM()) throw Error(ERR_BAD_COMBINATION); if (p1->isMEM()) throw Error(ERR_BAD_COMBINATION);
if (p2->isMEM()) { if (p2->isMEM()) {
const Address& addr = static_cast<const Address&>(*p2); const Address& addr = p2->getAddress();
if (BIT == 64 && addr.is32bit()) db(0x67); if (BIT == 64 && addr.is32bit()) db(0x67);
rex = addr.getRex() | static_cast<const Reg&>(*p1).getRex(); rex = addr.getRex() | p1->getReg().getRex();
} else { } else {
// ModRM(reg, base); // ModRM(reg, base);
rex = static_cast<const Reg&>(op2).getRex(static_cast<const Reg&>(op1)); rex = op2.getReg().getRex(op1.getReg());
} }
// except movsx(16bit, 32/64bit) // except movsx(16bit, 32/64bit)
if ((op1.isBit(16) && !op2.isBit(i32e)) || (op2.isBit(16) && !op1.isBit(i32e))) db(0x66); if ((op1.isBit(16) && !op2.isBit(i32e)) || (op2.isBit(16) && !op1.isBit(i32e))) db(0x66);
@ -1447,13 +1480,6 @@ private:
if ((a > 0 && a != v) + (b > 0 && b != v) + (c > 0 && c != v) > 0) return Error(err); if ((a > 0 && a != v) + (b > 0 && b != v) + (c > 0 && c != v) > 0) return Error(err);
return v; return v;
} }
enum {
T_RN_SAE = 1,
T_RD_SAE = 2,
T_RU_SAE = 3,
T_RZ_SAE = 4,
T_SAE = 5
};
int evex(const Reg& reg, const Reg& base, const Operand *v, int type, int code, bool x = false, bool b = false, int aaa = 0, uint32 VL = 0) int evex(const Reg& reg, const Reg& base, const Operand *v, int type, int code, bool x = false, bool b = false, int aaa = 0, uint32 VL = 0)
{ {
if (!(type & (T_EVEX | T_MUST_EVEX))) throw Error(ERR_EVEX_IS_INVALID); if (!(type & (T_EVEX | T_MUST_EVEX))) throw Error(ERR_EVEX_IS_INVALID);
@ -1472,7 +1498,7 @@ private:
int rounding = verifyDuplicate(reg.getRounding(), base.getRounding(), v ? v->getRounding() : 0, ERR_ROUNDING_IS_ALREADY_SET); int rounding = verifyDuplicate(reg.getRounding(), base.getRounding(), v ? v->getRounding() : 0, ERR_ROUNDING_IS_ALREADY_SET);
int disp8N = 1; int disp8N = 1;
if (rounding) { if (rounding) {
if (rounding == T_SAE){ if (rounding == EvexModifierRounding::T_SAE) {
verifySAE(base, type); LL = 0; verifySAE(base, type); LL = 0;
} else { } else {
verifyER(base, type); LL = rounding - 1; verifyER(base, type); LL = rounding - 1;
@ -1581,6 +1607,17 @@ private:
db(code0 | (reg.isBit(8) ? 0 : 1)); if (code1 != NONE) db(code1); if (code2 != NONE) db(code2); db(code0 | (reg.isBit(8) ? 0 : 1)); if (code1 != NONE) db(code1); if (code2 != NONE) db(code2);
opAddr(addr, reg.getIdx(), immSize); opAddr(addr, reg.getIdx(), immSize);
} }
void opMIB(const Address& addr, const Reg& reg, int code0, int code1)
{
if (addr.is64bitDisp()) throw Error(ERR_CANT_USE_64BIT_DISP);
if (addr.getMode() != Address::M_ModRM) throw Error(ERR_INVALID_MIB_ADDRESS);
if (BIT == 64 && addr.is32bit()) db(0x67);
const RegExp& regExp = addr.getRegExp(false);
uint8 rex = regExp.getRex();
if (rex) db(rex);
db(code0); db(code1);
setSIB(regExp, reg.getIdx());
}
void makeJmp(uint32 disp, LabelType type, uint8 shortCode, uint8 longCode, uint8 longPref) void makeJmp(uint32 disp, LabelType type, uint8 shortCode, uint8 longCode, uint8 longPref)
{ {
const int shortJmpSize = 2; const int shortJmpSize = 2;
@ -1656,9 +1693,9 @@ private:
if (isValid && !isValid(reg, op)) throw Error(ERR_BAD_COMBINATION); if (isValid && !isValid(reg, op)) throw Error(ERR_BAD_COMBINATION);
if (pref != NONE) db(pref); if (pref != NONE) db(pref);
if (op.isMEM()) { if (op.isMEM()) {
opModM(static_cast<const Address&>(op), static_cast<const Reg&>(reg), 0x0F, preCode, code, (imm8 != NONE) ? 1 : 0); opModM(op.getAddress(), reg.getReg(), 0x0F, preCode, code, (imm8 != NONE) ? 1 : 0);
} else { } else {
opModR(static_cast<const Reg&>(reg), static_cast<const Reg&>(op), 0x0F, preCode, code); opModR(reg.getReg(), op.getReg(), 0x0F, preCode, code);
} }
if (imm8 != NONE) db(imm8); if (imm8 != NONE) db(imm8);
} }
@ -1676,9 +1713,9 @@ private:
{ {
if (pref != NONE) db(pref); if (pref != NONE) db(pref);
if (op1.isXMM() && op2.isMEM()) { if (op1.isXMM() && op2.isMEM()) {
opModM(static_cast<const Address&>(op2), static_cast<const Reg&>(op1), 0x0F, code); opModM(op2.getAddress(), op1.getReg(), 0x0F, code);
} else if (op1.isMEM() && op2.isXMM()) { } else if (op1.isMEM() && op2.isXMM()) {
opModM(static_cast<const Address&>(op1), static_cast<const Reg&>(op2), 0x0F, code | 1); opModM(op1.getAddress(), op2.getReg(), 0x0F, code | 1);
} else { } else {
throw Error(ERR_BAD_COMBINATION); throw Error(ERR_BAD_COMBINATION);
} }
@ -1687,7 +1724,7 @@ private:
{ {
if (hasMMX2 && op.isREG(i32e)) { /* pextrw is special */ if (hasMMX2 && op.isREG(i32e)) { /* pextrw is special */
if (mmx.isXMM()) db(0x66); if (mmx.isXMM()) db(0x66);
opModR(static_cast<const Reg&>(op), mmx, 0x0F, 0xC5); db(imm); opModR(op.getReg(), mmx, 0x0F, 0xC5); db(imm);
} else { } else {
opGen(mmx, op, code, 0x66, isXMM_REG32orMEM, imm, 0x3A); opGen(mmx, op, code, 0x66, isXMM_REG32orMEM, imm, 0x3A);
} }
@ -1697,9 +1734,9 @@ private:
int opBit = op.getBit(); int opBit = op.getBit();
if (disableRex && opBit == 64) opBit = 32; if (disableRex && opBit == 64) opBit = 32;
if (op.isREG(bit)) { if (op.isREG(bit)) {
opModR(Reg(ext, Operand::REG, opBit), static_cast<const Reg&>(op).changeBit(opBit), code0, code1, code2); opModR(Reg(ext, Operand::REG, opBit), op.getReg().changeBit(opBit), code0, code1, code2);
} else if (op.isMEM()) { } else if (op.isMEM()) {
opModM(static_cast<const Address&>(op), Reg(ext, Operand::REG, opBit), code0, code1, code2, immSize); opModM(op.getAddress(), Reg(ext, Operand::REG, opBit), code0, code1, code2, immSize);
} else { } else {
throw Error(ERR_BAD_COMBINATION); throw Error(ERR_BAD_COMBINATION);
} }
@ -1718,9 +1755,9 @@ private:
void opModRM(const Operand& op1, const Operand& op2, bool condR, bool condM, int code0, int code1 = NONE, int code2 = NONE, int immSize = 0) void opModRM(const Operand& op1, const Operand& op2, bool condR, bool condM, int code0, int code1 = NONE, int code2 = NONE, int immSize = 0)
{ {
if (condR) { if (condR) {
opModR(static_cast<const Reg&>(op1), static_cast<const Reg&>(op2), code0, code1, code2); opModR(op1.getReg(), op2.getReg(), code0, code1, code2);
} else if (condM) { } else if (condM) {
opModM(static_cast<const Address&>(op2), static_cast<const Reg&>(op1), code0, code1, code2, immSize); opModM(op2.getAddress(), op1.getReg(), code0, code1, code2, immSize);
} else { } else {
throw Error(ERR_BAD_COMBINATION); throw Error(ERR_BAD_COMBINATION);
} }
@ -1735,7 +1772,7 @@ private:
void opRM_RM(const Operand& op1, const Operand& op2, int code) void opRM_RM(const Operand& op1, const Operand& op2, int code)
{ {
if (op1.isREG() && op2.isMEM()) { if (op1.isREG() && op2.isMEM()) {
opModM(static_cast<const Address&>(op2), static_cast<const Reg&>(op1), code | 2); opModM(op2.getAddress(), op1.getReg(), code | 2);
} else { } else {
opModRM(op2, op1, op1.isREG() && op1.getKind() == op2.getKind(), op1.isMEM() && op2.isREG(), code); opModRM(op2, op1, op1.isREG() && op1.getKind() == op2.getKind(), op1.isMEM() && op2.isREG(), code);
} }
@ -1768,19 +1805,19 @@ private:
#endif #endif
code = 0xFE; code = 0xFE;
if (op.isREG()) { if (op.isREG()) {
opModR(Reg(ext, Operand::REG, op.getBit()), static_cast<const Reg&>(op), code); opModR(Reg(ext, Operand::REG, op.getBit()), op.getReg(), code);
} else { } else {
opModM(static_cast<const Address&>(op), Reg(ext, Operand::REG, op.getBit()), code); opModM(op.getAddress(), Reg(ext, Operand::REG, op.getBit()), code);
} }
} }
void opPushPop(const Operand& op, int code, int ext, int alt) void opPushPop(const Operand& op, int code, int ext, int alt)
{ {
if (op.isREG()) { if (op.isREG()) {
if (op.isBit(16)) db(0x66); if (op.isBit(16)) db(0x66);
if (static_cast<const Reg&>(op).getIdx() >= 8) db(0x41); if (op.getReg().getIdx() >= 8) db(0x41);
db(alt | (op.getIdx() & 7)); db(alt | (op.getIdx() & 7));
} else if (op.isMEM()) { } else if (op.isMEM()) {
opModM(static_cast<const Address&>(op), Reg(ext, Operand::REG, op.getBit()), code); opModM(op.getAddress(), Reg(ext, Operand::REG, op.getBit()), code);
} else { } else {
throw Error(ERR_BAD_COMBINATION); throw Error(ERR_BAD_COMBINATION);
} }
@ -1869,11 +1906,12 @@ private:
void opVex(const Reg& r, const Operand *p1, const Operand& op2, int type, int code, int imm8 = NONE) void opVex(const Reg& r, const Operand *p1, const Operand& op2, int type, int code, int imm8 = NONE)
{ {
if (op2.isMEM()) { if (op2.isMEM()) {
const Address& addr = static_cast<const Address&>(op2); const Address& addr = op2.getAddress();
const Reg& base = addr.getRegExp().getBase(); const RegExp& regExp = addr.getRegExp();
const Reg& base = regExp.getBase();
if (BIT == 64 && addr.is32bit()) db(0x67); if (BIT == 64 && addr.is32bit()) db(0x67);
int disp8N = 0; int disp8N = 0;
bool x = addr.getRegExp().getIndex().isExtIdx(); bool x = regExp.getIndex().isExtIdx();
if ((type & T_MUST_EVEX) || r.hasEvex() || (p1 && p1->hasEvex()) || addr.isBroadcast() || addr.getOpmaskIdx()) { if ((type & T_MUST_EVEX) || r.hasEvex() || (p1 && p1->hasEvex()) || addr.isBroadcast() || addr.getOpmaskIdx()) {
int aaa = addr.getOpmaskIdx(); int aaa = addr.getOpmaskIdx();
if (aaa && !(type & T_M_K)) throw Error(ERR_INVALID_OPMASK_WITH_MEMORY); if (aaa && !(type & T_M_K)) throw Error(ERR_INVALID_OPMASK_WITH_MEMORY);
@ -1882,14 +1920,14 @@ private:
if (!(type & (T_B32 | T_B64))) throw Error(ERR_INVALID_BROADCAST); if (!(type & (T_B32 | T_B64))) throw Error(ERR_INVALID_BROADCAST);
b = true; b = true;
} }
int VL = addr.getRegExp().isVsib() ? addr.getRegExp().getIndex().getBit() : 0; int VL = regExp.isVsib() ? regExp.getIndex().getBit() : 0;
disp8N = evex(r, base, p1, type, code, x, b, aaa, VL); disp8N = evex(r, base, p1, type, code, x, b, aaa, VL);
} else { } else {
vex(r, base, p1, type, code, x); vex(r, base, p1, type, code, x);
} }
opAddr(addr, r.getIdx(), (imm8 != NONE) ? 1 : 0, disp8N); opAddr(addr, r.getIdx(), (imm8 != NONE) ? 1 : 0, disp8N);
} else { } else {
const Reg& base = static_cast<const Reg&>(op2); const Reg& base = op2.getReg();
if ((type & T_MUST_EVEX) || r.hasEvex() || (p1 && p1->hasEvex()) || base.hasEvex()) { if ((type & T_MUST_EVEX) || r.hasEvex() || (p1 && p1->hasEvex()) || base.hasEvex()) {
evex(r, base, p1, type, code); evex(r, base, p1, type, code);
} else { } else {
@ -1971,11 +2009,12 @@ private:
} }
void opGather(const Xmm& x1, const Address& addr, const Xmm& x2, int type, uint8 code, int mode) void opGather(const Xmm& x1, const Address& addr, const Xmm& x2, int type, uint8 code, int mode)
{ {
if (!addr.getRegExp().isVsib(128 | 256)) throw Error(ERR_BAD_VSIB_ADDRESSING); const RegExp& regExp = addr.getRegExp();
if (!regExp.isVsib(128 | 256)) throw Error(ERR_BAD_VSIB_ADDRESSING);
const int y_vx_y = 0; const int y_vx_y = 0;
const int y_vy_y = 1; const int y_vy_y = 1;
// const int x_vy_x = 2; // const int x_vy_x = 2;
const bool isAddrYMM = addr.getRegExp().getIndex().getBit() == 256; const bool isAddrYMM = regExp.getIndex().getBit() == 256;
if (!x1.isXMM() || isAddrYMM || !x2.isXMM()) { if (!x1.isXMM() || isAddrYMM || !x2.isXMM()) {
bool isOK = false; bool isOK = false;
if (mode == y_vx_y) { if (mode == y_vx_y) {
@ -2174,13 +2213,13 @@ public:
const Address *addr = 0; const Address *addr = 0;
uint8 code = 0; uint8 code = 0;
if (reg1.isREG() && reg1.getIdx() == 0 && reg2.isMEM()) { // mov eax|ax|al, [disp] if (reg1.isREG() && reg1.getIdx() == 0 && reg2.isMEM()) { // mov eax|ax|al, [disp]
reg = &static_cast<const Reg&>(reg1); reg = &reg1.getReg();
addr= &static_cast<const Address&>(reg2); addr= &reg2.getAddress();
code = 0xA0; code = 0xA0;
} else } else
if (reg1.isMEM() && reg2.isREG() && reg2.getIdx() == 0) { // mov [disp], eax|ax|al if (reg1.isMEM() && reg2.isREG() && reg2.getIdx() == 0) { // mov [disp], eax|ax|al
reg = &static_cast<const Reg&>(reg2); reg = &reg2.getReg();
addr= &static_cast<const Address&>(reg1); addr= &reg1.getAddress();
code = 0xA2; code = 0xA2;
} }
#ifdef XBYAK64 #ifdef XBYAK64
@ -2207,7 +2246,7 @@ public:
void mov(const Operand& op, size_t imm) void mov(const Operand& op, size_t imm)
{ {
if (op.isREG()) { if (op.isREG()) {
const int size = mov_imm(static_cast<const Reg&>(op), imm); const int size = mov_imm(op.getReg(), imm);
db(imm, size); db(imm, size);
} else if (op.isMEM()) { } else if (op.isMEM()) {
verifyMemHasSize(op); verifyMemHasSize(op);
@ -2219,7 +2258,7 @@ public:
if (!inner::IsInInt32(imm)) throw Error(ERR_IMM_IS_TOO_BIG); if (!inner::IsInInt32(imm)) throw Error(ERR_IMM_IS_TOO_BIG);
immSize = 4; immSize = 4;
} }
opModM(static_cast<const Address&>(op), Reg(0, Operand::REG, op.getBit()), 0xC6, NONE, NONE, immSize); opModM(op.getAddress(), Reg(0, Operand::REG, op.getBit()), 0xC6, NONE, NONE, immSize);
db(static_cast<uint32>(imm), immSize); db(static_cast<uint32>(imm), immSize);
} else { } else {
throw Error(ERR_BAD_COMBINATION); throw Error(ERR_BAD_COMBINATION);
@ -2303,7 +2342,7 @@ public:
} }
void mov(const Segment& seg, const Operand& op) void mov(const Segment& seg, const Operand& op)
{ {
opModRM(Reg8(seg.getIdx()), op.isREG(16|i32e) ? static_cast<const Operand&>(static_cast<const Reg&>(op).cvt32()) : op, op.isREG(16|i32e), op.isMEM(), 0x8E); opModRM(Reg8(seg.getIdx()), op.isREG(16|i32e) ? static_cast<const Operand&>(op.getReg().cvt32()) : op, op.isREG(16|i32e), op.isMEM(), 0x8E);
} }
#endif #endif
@ -2328,7 +2367,7 @@ public:
, st0(0), st1(1), st2(2), st3(3), st4(4), st5(5), st6(6), st7(7) , st0(0), st1(1), st2(2), st3(3), st4(4), st5(5), st6(6), st7(7)
, k0(0), k1(1), k2(2), k3(3), k4(4), k5(5), k6(6), k7(7) , k0(0), k1(1), k2(2), k3(3), k4(4), k5(5), k6(6), k7(7)
, bnd0(0), bnd1(1), bnd2(2), bnd3(3) , bnd0(0), bnd1(1), bnd2(2), bnd3(3)
, T_sae(T_SAE), T_rn_sae(T_RN_SAE), T_rd_sae(T_RD_SAE), T_ru_sae(T_RU_SAE), T_rz_sae(T_RZ_SAE) , T_sae(EvexModifierRounding::T_SAE), T_rn_sae(EvexModifierRounding::T_RN_SAE), T_rd_sae(EvexModifierRounding::T_RD_SAE), T_ru_sae(EvexModifierRounding::T_RU_SAE), T_rz_sae(EvexModifierRounding::T_RZ_SAE)
, T_z() , T_z()
#ifdef XBYAK64 #ifdef XBYAK64
, rax(Operand::RAX), rcx(Operand::RCX), rdx(Operand::RDX), rbx(Operand::RBX), rsp(Operand::RSP), rbp(Operand::RBP), rsi(Operand::RSI), rdi(Operand::RDI), r8(Operand::R8), r9(Operand::R9), r10(Operand::R10), r11(Operand::R11), r12(Operand::R12), r13(Operand::R13), r14(Operand::R14), r15(Operand::R15) , rax(Operand::RAX), rcx(Operand::RCX), rdx(Operand::RDX), rbx(Operand::RBX), rsp(Operand::RSP), rbp(Operand::RBP), rsi(Operand::RSI), rdi(Operand::RDI), r8(Operand::R8), r9(Operand::R9), r10(Operand::R10), r11(Operand::R11), r12(Operand::R12), r13(Operand::R13), r14(Operand::R14), r15(Operand::R15)
@ -2423,9 +2462,7 @@ public:
while (size > 0) { while (size > 0) {
size_t len = (std::min)(n, size); size_t len = (std::min)(n, size);
const uint8 *seq = nopTbl[len - 1]; const uint8 *seq = nopTbl[len - 1];
for (size_t i = 0; i < len; i++) { db(seq, len);
db(seq[i]);
}
size -= len; size -= len;
} }
} }
@ -2456,10 +2493,13 @@ static const Zmm zmm0(0), zmm1(1), zmm2(2), zmm3(3), zmm4(4), zmm5(5), zmm6(6),
static const Reg32 eax(Operand::EAX), ecx(Operand::ECX), edx(Operand::EDX), ebx(Operand::EBX), esp(Operand::ESP), ebp(Operand::EBP), esi(Operand::ESI), edi(Operand::EDI); static const Reg32 eax(Operand::EAX), ecx(Operand::ECX), edx(Operand::EDX), ebx(Operand::EBX), esp(Operand::ESP), ebp(Operand::EBP), esi(Operand::ESI), edi(Operand::EDI);
static const Reg16 ax(Operand::AX), cx(Operand::CX), dx(Operand::DX), bx(Operand::BX), sp(Operand::SP), bp(Operand::BP), si(Operand::SI), di(Operand::DI); static const Reg16 ax(Operand::AX), cx(Operand::CX), dx(Operand::DX), bx(Operand::BX), sp(Operand::SP), bp(Operand::BP), si(Operand::SI), di(Operand::DI);
static const Reg8 al(Operand::AL), cl(Operand::CL), dl(Operand::DL), bl(Operand::BL), ah(Operand::AH), ch(Operand::CH), dh(Operand::DH), bh(Operand::BH); static const Reg8 al(Operand::AL), cl(Operand::CL), dl(Operand::DL), bl(Operand::BL), ah(Operand::AH), ch(Operand::CH), dh(Operand::DH), bh(Operand::BH);
static const AddressFrame ptr(0), byte(8), word(16), dword(32), qword(64); static const AddressFrame ptr(0), byte(8), word(16), dword(32), qword(64), xword(128), yword(256), zword(512);
static const AddressFrame ptr_b(0, true), xword_b(128, true), yword_b(256, true), zword_b(512, true);
static const Fpu st0(0), st1(1), st2(2), st3(3), st4(4), st5(5), st6(6), st7(7); static const Fpu st0(0), st1(1), st2(2), st3(3), st4(4), st5(5), st6(6), st7(7);
static const Opmask k0(0), k1(1), k2(2), k3(3), k4(4), k5(5), k6(6), k7(7); static const Opmask k0(0), k1(1), k2(2), k3(3), k4(4), k5(5), k6(6), k7(7);
static const BoundsReg bnd0(0), bnd1(1), bnd2(2), bnd3(3); static const BoundsReg bnd0(0), bnd1(1), bnd2(2), bnd3(3);
static const EvexModifierRounding T_sae(EvexModifierRounding::T_SAE), T_rn_sae(EvexModifierRounding::T_RN_SAE), T_rd_sae(EvexModifierRounding::T_RD_SAE), T_ru_sae(EvexModifierRounding::T_RU_SAE), T_rz_sae(EvexModifierRounding::T_RZ_SAE);
static const EvexModifierZero T_z;
#ifdef XBYAK64 #ifdef XBYAK64
static const Reg64 rax(Operand::RAX), rcx(Operand::RCX), rdx(Operand::RDX), rbx(Operand::RBX), rsp(Operand::RSP), rbp(Operand::RBP), rsi(Operand::RSI), rdi(Operand::RDI), r8(Operand::R8), r9(Operand::R9), r10(Operand::R10), r11(Operand::R11), r12(Operand::R12), r13(Operand::R13), r14(Operand::R14), r15(Operand::R15); static const Reg64 rax(Operand::RAX), rcx(Operand::RCX), rdx(Operand::RDX), rbx(Operand::RBX), rsp(Operand::RSP), rbp(Operand::RBP), rsi(Operand::RSI), rdi(Operand::RDI), r8(Operand::R8), r9(Operand::R9), r10(Operand::R10), r11(Operand::R11), r12(Operand::R12), r13(Operand::R13), r14(Operand::R14), r15(Operand::R15);
static const Reg32 r8d(8), r9d(9), r10d(10), r11d(11), r12d(12), r13d(13), r14d(14), r15d(15); static const Reg32 r8d(8), r9d(9), r10d(10), r11d(11), r12d(12), r13d(13), r14d(14), r15d(15);

View file

@ -1,4 +1,4 @@
const char *getVersionString() const { return "5.52"; } const char *getVersionString() const { return "5.601"; }
void adc(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x10, 2); } void adc(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x10, 2); }
void adc(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x10); } void adc(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x10); }
void adcx(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0x66, isREG32_REG32orMEM, NONE, 0x38); } void adcx(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0x66, isREG32_REG32orMEM, NONE, 0x38); }
@ -32,14 +32,15 @@ void blendvps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x14, 0x66, is
void blsi(const Reg32e& r, const Operand& op) { opGpr(Reg32e(3, r.getBit()), op, r, T_0F38, 0xf3, false); } void blsi(const Reg32e& r, const Operand& op) { opGpr(Reg32e(3, r.getBit()), op, r, T_0F38, 0xf3, false); }
void blsmsk(const Reg32e& r, const Operand& op) { opGpr(Reg32e(2, r.getBit()), op, r, T_0F38, 0xf3, false); } void blsmsk(const Reg32e& r, const Operand& op) { opGpr(Reg32e(2, r.getBit()), op, r, T_0F38, 0xf3, false); }
void blsr(const Reg32e& r, const Operand& op) { opGpr(Reg32e(1, r.getBit()), op, r, T_0F38, 0xf3, false); } void blsr(const Reg32e& r, const Operand& op) { opGpr(Reg32e(1, r.getBit()), op, r, T_0F38, 0xf3, false); }
void bnd() { db(0xF2); }
void bndcl(const BoundsReg& bnd, const Operand& op) { db(0xF3); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); } void bndcl(const BoundsReg& bnd, const Operand& op) { db(0xF3); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); }
void bndcn(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1B, NONE, !op.isMEM()); } void bndcn(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1B, NONE, !op.isMEM()); }
void bndcu(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); } void bndcu(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); }
void bndldx(const BoundsReg& bnd, const Address& addr) { opModM(addr, bnd, 0x0F, 0x1A); } void bndldx(const BoundsReg& bnd, const Address& addr) { opMIB(addr, bnd, 0x0F, 0x1A); }
void bndmk(const BoundsReg& bnd, const Address& addr) { db(0xF3); opModM(addr, bnd, 0x0F, 0x1B); } void bndmk(const BoundsReg& bnd, const Address& addr) { db(0xF3); opModM(addr, bnd, 0x0F, 0x1B); }
void bndmov(const Address& addr, const BoundsReg& bnd) { db(0x66); opModM(addr, bnd, 0x0F, 0x1B); } void bndmov(const Address& addr, const BoundsReg& bnd) { db(0x66); opModM(addr, bnd, 0x0F, 0x1B); }
void bndmov(const BoundsReg& bnd, const Operand& op) { db(0x66); opModRM(bnd, op, op.isBNDREG(), op.isMEM(), 0x0F, 0x1A); } void bndmov(const BoundsReg& bnd, const Operand& op) { db(0x66); opModRM(bnd, op, op.isBNDREG(), op.isMEM(), 0x0F, 0x1A); }
void bndstx(const Address& addr, const BoundsReg& bnd) { opModM(addr, bnd, 0x0F, 0x1B); } void bndstx(const Address& addr, const BoundsReg& bnd) { opMIB(addr, bnd, 0x0F, 0x1B); }
void bsf(const Reg&reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0xBC); } void bsf(const Reg&reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0xBC); }
void bsr(const Reg&reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0xBD); } void bsr(const Reg&reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0xBD); }
void bswap(const Reg32e& reg) { opModR(Reg32(1), reg, 0x0F); } void bswap(const Reg32e& reg) { opModR(Reg32(1), reg, 0x0F); }
@ -293,6 +294,9 @@ void fxch(const Fpu& reg) { opFpu(reg, 0xD9, 0xC8); }
void fxtract() { db(0xD9); db(0xF4); } void fxtract() { db(0xD9); db(0xF4); }
void fyl2x() { db(0xD9); db(0xF1); } void fyl2x() { db(0xD9); db(0xF1); }
void fyl2xp1() { db(0xD9); db(0xF9); } void fyl2xp1() { db(0xD9); db(0xF9); }
void gf2p8affineinvqb(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0xCF, 0x66, isXMM_XMMorMEM, static_cast<uint8>(imm), 0x3A); }
void gf2p8affineqb(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0xCE, 0x66, isXMM_XMMorMEM, static_cast<uint8>(imm), 0x3A); }
void gf2p8mulb(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCF, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
void haddpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7C, 0x66, isXMM_XMMorMEM); } void haddpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7C, 0x66, isXMM_XMMorMEM); }
void haddps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7C, 0xF2, isXMM_XMMorMEM); } void haddps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7C, 0xF2, isXMM_XMMorMEM); }
void hsubpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7D, 0x66, isXMM_XMMorMEM); } void hsubpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7D, 0x66, isXMM_XMMorMEM); }
@ -758,10 +762,10 @@ void vaddsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand())
void vaddss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_Z | T_N4, 0x58); } void vaddss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_Z | T_N4, 0x58); }
void vaddsubpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F | T_YMM, 0xD0); } void vaddsubpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F | T_YMM, 0xD0); }
void vaddsubps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_F2 | T_0F | T_YMM, 0xD0); } void vaddsubps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_F2 | T_0F | T_YMM, 0xD0); }
void vaesdec(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_W0, 0xDE); } void vaesdec(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_YMM | T_EVEX, 0xDE); }
void vaesdeclast(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_W0, 0xDF); } void vaesdeclast(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_YMM | T_EVEX, 0xDF); }
void vaesenc(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_W0, 0xDC); } void vaesenc(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_YMM | T_EVEX, 0xDC); }
void vaesenclast(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_W0, 0xDD); } void vaesenclast(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_YMM | T_EVEX, 0xDD); }
void vaesimc(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_W0, 0xDB); } void vaesimc(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_W0, 0xDB); }
void vaeskeygenassist(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0xDF, imm); } void vaeskeygenassist(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0xDF, imm); }
void vandnpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x55); } void vandnpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x55); }
@ -1001,6 +1005,9 @@ void vgatherdpd(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1
void vgatherdps(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_W0, 0x92, 1); } void vgatherdps(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_W0, 0x92, 1); }
void vgatherqpd(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_W1, 0x93, 1); } void vgatherqpd(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_W1, 0x93, 1); }
void vgatherqps(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_W0, 0x93, 2); } void vgatherqps(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_W0, 0x93, 2); }
void vgf2p8affineinvqb(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W1 | T_EW1 | T_YMM | T_EVEX | T_SAE_Z | T_B64, 0xCF, imm); }
void vgf2p8affineqb(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W1 | T_EW1 | T_YMM | T_EVEX | T_SAE_Z | T_B64, 0xCE, imm); }
void vgf2p8mulb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_SAE_Z, 0xCF); }
void vhaddpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F | T_YMM, 0x7C); } void vhaddpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F | T_YMM, 0x7C); }
void vhaddps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_F2 | T_0F | T_YMM, 0x7C); } void vhaddps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_F2 | T_0F | T_YMM, 0x7C); }
void vhsubpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F | T_YMM, 0x7D); } void vhsubpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F | T_YMM, 0x7D); }
@ -1099,7 +1106,7 @@ void vpbroadcastb(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isME
void vpbroadcastd(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX, 0x58); } void vpbroadcastd(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX, 0x58); }
void vpbroadcastq(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_W0 | T_EW1 | T_YMM | T_EVEX, 0x59); } void vpbroadcastq(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_W0 | T_EW1 | T_YMM | T_EVEX, 0x59); }
void vpbroadcastw(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(x, op, T_N2 | T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX, 0x79); } void vpbroadcastw(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(x, op, T_N2 | T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX, 0x79); }
void vpclmulqdq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0, 0x44, imm); } void vpclmulqdq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM | T_EVEX, 0x44, imm); }
void vpcmpeqb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x74); } void vpcmpeqb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x74); }
void vpcmpeqd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x76); } void vpcmpeqd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x76); }
void vpcmpeqq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x29); } void vpcmpeqq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x29); }
@ -1661,8 +1668,10 @@ void vcmppd(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX
void vcmpps(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_0F | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0xC2, imm); } void vcmpps(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_0F | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0xC2, imm); }
void vcmpsd(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_N8 | T_F2 | T_0F | T_EW1 | T_SAE_Z | T_MUST_EVEX, 0xC2, imm); } void vcmpsd(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_N8 | T_F2 | T_0F | T_EW1 | T_SAE_Z | T_MUST_EVEX, 0xC2, imm); }
void vcmpss(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_N4 | T_F3 | T_0F | T_EW0 | T_SAE_Z | T_MUST_EVEX, 0xC2, imm); } void vcmpss(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_N4 | T_F3 | T_0F | T_EW0 | T_SAE_Z | T_MUST_EVEX, 0xC2, imm); }
void vcompressb(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N1 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x63); }
void vcompresspd(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x8A); } void vcompresspd(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x8A); }
void vcompressps(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8A); } void vcompressps(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8A); }
void vcompressw(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N2 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x63); }
void vcvtpd2qq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x7B); } void vcvtpd2qq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x7B); }
void vcvtpd2udq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_YMM | T_MUST_EVEX | T_EW1 | T_B64 | T_ER_Z, 0x79); } void vcvtpd2udq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_YMM | T_MUST_EVEX | T_EW1 | T_B64 | T_ER_Z, 0x79); }
void vcvtpd2uqq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x79); } void vcvtpd2uqq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x79); }
@ -1784,6 +1793,10 @@ void vpcompressd(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N4 |
void vpcompressq(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x8B); } void vpcompressq(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x8B); }
void vpconflictd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xC4); } void vpconflictd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xC4); }
void vpconflictq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xC4); } void vpconflictq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xC4); }
void vpdpbusd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x50); }
void vpdpbusds(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x51); }
void vpdpwssd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x52); }
void vpdpwssds(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x53); }
void vpermb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8D); } void vpermb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8D); }
void vpermi2b(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x75); } void vpermi2b(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x75); }
void vpermi2d(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x76); } void vpermi2d(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x76); }
@ -1798,8 +1811,10 @@ void vpermt2ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x
void vpermt2q(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x7E); } void vpermt2q(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x7E); }
void vpermt2w(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x7D); } void vpermt2w(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x7D); }
void vpermw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x8D); } void vpermw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x8D); }
void vpexpandb(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N1 | T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x62); }
void vpexpandd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x89); } void vpexpandd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x89); }
void vpexpandq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x89); } void vpexpandq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x89); }
void vpexpandw(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N2 | T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x62); }
void vpgatherdd(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x90, 0); } void vpgatherdd(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x90, 0); }
void vpgatherdq(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x90, 1); } void vpgatherdq(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x90, 1); }
void vpgatherqd(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x91, 2); } void vpgatherqd(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x91, 2); }
@ -1840,6 +1855,10 @@ void vpmovw2m(const Opmask& k, const Xmm& x) { opVex(k, 0, x, T_F3 | T_0F38 | T_
void vpmovwb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x30, true); } void vpmovwb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x30, true); }
void vpmullq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x40); } void vpmullq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x40); }
void vpmultishiftqb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x83); } void vpmultishiftqb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x83); }
void vpopcntb(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x54); }
void vpopcntd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x55); }
void vpopcntq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x55); }
void vpopcntw(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x54); }
void vpord(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xEB); } void vpord(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xEB); }
void vporq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xEB); } void vporq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xEB); }
void vprold(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 1), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x72, imm); } void vprold(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 1), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x72, imm); }
@ -1854,6 +1873,19 @@ void vpscatterdd(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N4 |
void vpscatterdq(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_M_K, 0xA0, 1); } void vpscatterdq(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_M_K, 0xA0, 1); }
void vpscatterqd(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0xA1, 2); } void vpscatterqd(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0xA1, 2); }
void vpscatterqq(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_M_K, 0xA1, 0); } void vpscatterqq(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_M_K, 0xA1, 0); }
void vpshldd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x71, imm); }
void vpshldq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x71, imm); }
void vpshldvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x71); }
void vpshldvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x71); }
void vpshldvw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x70); }
void vpshldw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x70, imm); }
void vpshrdd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x73, imm); }
void vpshrdq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x73, imm); }
void vpshrdvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x73); }
void vpshrdvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x73); }
void vpshrdvw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x72); }
void vpshrdw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x72, imm); }
void vpshufbitqmb(const Opmask& k, const Xmm& x, const Operand& op) { opVex(k, &x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8F); }
void vpsllvw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x12); } void vpsllvw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x12); }
void vpsraq(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 4), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x72, imm); } void vpsraq(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 4), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x72, imm); }
void vpsraq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX, 0xE2); } void vpsraq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX, 0xE2); }

View file

@ -165,100 +165,120 @@ public:
static const Type tMOVBE = uint64(1) << 34; // mobve static const Type tMOVBE = uint64(1) << 34; // mobve
static const Type tAVX512F = uint64(1) << 35; static const Type tAVX512F = uint64(1) << 35;
static const Type tAVX512DQ = uint64(1) << 36; static const Type tAVX512DQ = uint64(1) << 36;
static const Type tAVX512IFMA = uint64(1) << 37; static const Type tAVX512_IFMA = uint64(1) << 37;
static const Type tAVX512IFMA = tAVX512_IFMA;
static const Type tAVX512PF = uint64(1) << 38; static const Type tAVX512PF = uint64(1) << 38;
static const Type tAVX512ER = uint64(1) << 39; static const Type tAVX512ER = uint64(1) << 39;
static const Type tAVX512CD = uint64(1) << 40; static const Type tAVX512CD = uint64(1) << 40;
static const Type tAVX512BW = uint64(1) << 41; static const Type tAVX512BW = uint64(1) << 41;
static const Type tAVX512VL = uint64(1) << 42; static const Type tAVX512VL = uint64(1) << 42;
static const Type tAVX512VBMI = uint64(1) << 43; static const Type tAVX512_VBMI = uint64(1) << 43;
static const Type tAVX512VBMI = tAVX512_VBMI; // changed by Intel's manual
static const Type tAVX512_4VNNIW = uint64(1) << 44; static const Type tAVX512_4VNNIW = uint64(1) << 44;
static const Type tAVX512_4FMAPS = uint64(1) << 45; static const Type tAVX512_4FMAPS = uint64(1) << 45;
static const Type tPREFETCHWT1 = uint64(1) << 46; static const Type tPREFETCHWT1 = uint64(1) << 46;
static const Type tPREFETCHW = uint64(1) << 47; static const Type tPREFETCHW = uint64(1) << 47;
static const Type tSHA = uint64(1) << 48; static const Type tSHA = uint64(1) << 48;
static const Type tMPX = uint64(1) << 49; static const Type tMPX = uint64(1) << 49;
static const Type tAVX512_VBMI2 = uint64(1) << 50;
static const Type tGFNI = uint64(1) << 51;
static const Type tVAES = uint64(1) << 52;
static const Type tVPCLMULQDQ = uint64(1) << 53;
static const Type tAVX512_VNNI = uint64(1) << 54;
static const Type tAVX512_BITALG = uint64(1) << 55;
static const Type tAVX512_VPOPCNTDQ = uint64(1) << 56;
Cpu() Cpu()
: type_(NONE) : type_(NONE)
{ {
unsigned int data[4]; unsigned int data[4];
const unsigned int& EAX = data[0];
const unsigned int& EBX = data[1];
const unsigned int& ECX = data[2];
const unsigned int& EDX = data[3];
getCpuid(0, data); getCpuid(0, data);
const unsigned int maxNum = data[0]; const unsigned int maxNum = EAX;
static const char intel[] = "ntel"; static const char intel[] = "ntel";
static const char amd[] = "cAMD"; static const char amd[] = "cAMD";
if (data[2] == get32bitAsBE(amd)) { if (ECX == get32bitAsBE(amd)) {
type_ |= tAMD; type_ |= tAMD;
getCpuid(0x80000001, data); getCpuid(0x80000001, data);
if (data[3] & (1U << 31)) type_ |= t3DN; if (EDX & (1U << 31)) type_ |= t3DN;
if (data[3] & (1U << 15)) type_ |= tCMOV; if (EDX & (1U << 15)) type_ |= tCMOV;
if (data[3] & (1U << 30)) type_ |= tE3DN; if (EDX & (1U << 30)) type_ |= tE3DN;
if (data[3] & (1U << 22)) type_ |= tMMX2; if (EDX & (1U << 22)) type_ |= tMMX2;
if (data[3] & (1U << 27)) type_ |= tRDTSCP; if (EDX & (1U << 27)) type_ |= tRDTSCP;
} }
if (data[2] == get32bitAsBE(intel)) { if (ECX == get32bitAsBE(intel)) {
type_ |= tINTEL; type_ |= tINTEL;
getCpuid(0x80000001, data); getCpuid(0x80000001, data);
if (data[3] & (1U << 27)) type_ |= tRDTSCP; if (EDX & (1U << 27)) type_ |= tRDTSCP;
if (data[2] & (1U << 5)) type_ |= tLZCNT; if (ECX & (1U << 5)) type_ |= tLZCNT;
if (data[2] & (1U << 8)) type_ |= tPREFETCHW; if (ECX & (1U << 8)) type_ |= tPREFETCHW;
} }
getCpuid(1, data); getCpuid(1, data);
if (data[2] & (1U << 0)) type_ |= tSSE3; if (ECX & (1U << 0)) type_ |= tSSE3;
if (data[2] & (1U << 9)) type_ |= tSSSE3; if (ECX & (1U << 9)) type_ |= tSSSE3;
if (data[2] & (1U << 19)) type_ |= tSSE41; if (ECX & (1U << 19)) type_ |= tSSE41;
if (data[2] & (1U << 20)) type_ |= tSSE42; if (ECX & (1U << 20)) type_ |= tSSE42;
if (data[2] & (1U << 22)) type_ |= tMOVBE; if (ECX & (1U << 22)) type_ |= tMOVBE;
if (data[2] & (1U << 23)) type_ |= tPOPCNT; if (ECX & (1U << 23)) type_ |= tPOPCNT;
if (data[2] & (1U << 25)) type_ |= tAESNI; if (ECX & (1U << 25)) type_ |= tAESNI;
if (data[2] & (1U << 1)) type_ |= tPCLMULQDQ; if (ECX & (1U << 1)) type_ |= tPCLMULQDQ;
if (data[2] & (1U << 27)) type_ |= tOSXSAVE; if (ECX & (1U << 27)) type_ |= tOSXSAVE;
if (data[2] & (1U << 30)) type_ |= tRDRAND; if (ECX & (1U << 30)) type_ |= tRDRAND;
if (data[2] & (1U << 29)) type_ |= tF16C; if (ECX & (1U << 29)) type_ |= tF16C;
if (data[3] & (1U << 15)) type_ |= tCMOV; if (EDX & (1U << 15)) type_ |= tCMOV;
if (data[3] & (1U << 23)) type_ |= tMMX; if (EDX & (1U << 23)) type_ |= tMMX;
if (data[3] & (1U << 25)) type_ |= tMMX2 | tSSE; if (EDX & (1U << 25)) type_ |= tMMX2 | tSSE;
if (data[3] & (1U << 26)) type_ |= tSSE2; if (EDX & (1U << 26)) type_ |= tSSE2;
if (type_ & tOSXSAVE) { if (type_ & tOSXSAVE) {
// check XFEATURE_ENABLED_MASK[2:1] = '11b' // check XFEATURE_ENABLED_MASK[2:1] = '11b'
uint64 bv = getXfeature(); uint64 bv = getXfeature();
if ((bv & 6) == 6) { if ((bv & 6) == 6) {
if (data[2] & (1U << 28)) type_ |= tAVX; if (ECX & (1U << 28)) type_ |= tAVX;
if (data[2] & (1U << 12)) type_ |= tFMA; if (ECX & (1U << 12)) type_ |= tFMA;
if (((bv >> 5) & 7) == 7) { if (((bv >> 5) & 7) == 7) {
getCpuidEx(7, 0, data); getCpuidEx(7, 0, data);
if (data[1] & (1U << 16)) type_ |= tAVX512F; if (EBX & (1U << 16)) type_ |= tAVX512F;
if (type_ & tAVX512F) { if (type_ & tAVX512F) {
if (data[1] & (1U << 17)) type_ |= tAVX512DQ; if (EBX & (1U << 17)) type_ |= tAVX512DQ;
if (data[1] & (1U << 21)) type_ |= tAVX512IFMA; if (EBX & (1U << 21)) type_ |= tAVX512_IFMA;
if (data[1] & (1U << 26)) type_ |= tAVX512PF; if (EBX & (1U << 26)) type_ |= tAVX512PF;
if (data[1] & (1U << 27)) type_ |= tAVX512ER; if (EBX & (1U << 27)) type_ |= tAVX512ER;
if (data[1] & (1U << 28)) type_ |= tAVX512CD; if (EBX & (1U << 28)) type_ |= tAVX512CD;
if (data[1] & (1U << 30)) type_ |= tAVX512BW; if (EBX & (1U << 30)) type_ |= tAVX512BW;
if (data[1] & (1U << 31)) type_ |= tAVX512VL; if (EBX & (1U << 31)) type_ |= tAVX512VL;
if (data[2] & (1U << 1)) type_ |= tAVX512VBMI; if (ECX & (1U << 1)) type_ |= tAVX512_VBMI;
if (data[3] & (1U << 2)) type_ |= tAVX512_4VNNIW; if (ECX & (1U << 6)) type_ |= tAVX512_VBMI2;
if (data[3] & (1U << 3)) type_ |= tAVX512_4FMAPS; if (ECX & (1U << 8)) type_ |= tGFNI;
if (ECX & (1U << 9)) type_ |= tVAES;
if (ECX & (1U << 10)) type_ |= tVPCLMULQDQ;
if (ECX & (1U << 11)) type_ |= tAVX512_VNNI;
if (ECX & (1U << 12)) type_ |= tAVX512_BITALG;
if (ECX & (1U << 14)) type_ |= tAVX512_VPOPCNTDQ;
if (EDX & (1U << 2)) type_ |= tAVX512_4VNNIW;
if (EDX & (1U << 3)) type_ |= tAVX512_4FMAPS;
} }
} }
} }
} }
if (maxNum >= 7) { if (maxNum >= 7) {
getCpuidEx(7, 0, data); getCpuidEx(7, 0, data);
if (type_ & tAVX && data[1] & 0x20) type_ |= tAVX2; if (type_ & tAVX && (EBX & (1U << 5))) type_ |= tAVX2;
if (data[1] & (1U << 3)) type_ |= tBMI1; if (EBX & (1U << 3)) type_ |= tBMI1;
if (data[1] & (1U << 8)) type_ |= tBMI2; if (EBX & (1U << 8)) type_ |= tBMI2;
if (data[1] & (1U << 9)) type_ |= tENHANCED_REP; if (EBX & (1U << 9)) type_ |= tENHANCED_REP;
if (data[1] & (1U << 18)) type_ |= tRDSEED; if (EBX & (1U << 18)) type_ |= tRDSEED;
if (data[1] & (1U << 19)) type_ |= tADX; if (EBX & (1U << 19)) type_ |= tADX;
if (data[1] & (1U << 20)) type_ |= tSMAP; if (EBX & (1U << 20)) type_ |= tSMAP;
if (data[1] & (1U << 4)) type_ |= tHLE; if (EBX & (1U << 4)) type_ |= tHLE;
if (data[1] & (1U << 11)) type_ |= tRTM; if (EBX & (1U << 11)) type_ |= tRTM;
if (data[1] & (1U << 14)) type_ |= tMPX; if (EBX & (1U << 14)) type_ |= tMPX;
if (data[1] & (1U << 29)) type_ |= tSHA; if (EBX & (1U << 29)) type_ |= tSHA;
if (data[2] & (1U << 0)) type_ |= tPREFETCHWT1; if (ECX & (1U << 0)) type_ |= tPREFETCHWT1;
} }
setFamily(); setFamily();
} }