mirror of
https://github.com/herumi/xbyak
synced 2024-11-20 16:06:14 -07:00
apx supports 0x0f opecode with rex2
This commit is contained in:
parent
2e7b62d784
commit
b3e27734be
3 changed files with 44 additions and 16 deletions
|
@ -43,7 +43,7 @@
|
|||
static const uint64_t T_MAP6 = T_FP16 | T_0F38;
|
||||
static const uint64_t T_NF = 1ull << 32; // T_nf
|
||||
static const uint64_t T_CODE1_IF1 = 1ull << 33; // code|=1 if !r.isBit(8)
|
||||
|
||||
static const uint64_t T_REX2 = 1ull << 34;
|
||||
static const uint64_t T_ND1 = 1ull << 35; // ND=1
|
||||
static const uint64_t T_ZU = 1ull << 36; // ND=ZU
|
||||
static const uint64_t T_F2 = 1ull << 37; // pp = 3
|
||||
|
|
25
test/apx.cpp
25
test/apx.cpp
|
@ -1911,3 +1911,28 @@ CYBOZU_TEST_AUTO(sha)
|
|||
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
|
||||
}
|
||||
|
||||
CYBOZU_TEST_AUTO(0x0f_rex2)
|
||||
{
|
||||
struct Code : Xbyak::CodeGenerator {
|
||||
Code()
|
||||
{
|
||||
addps(xmm3, ptr [r30+r20*4+0x4]);
|
||||
movups(xmm5, ptr [r16]);
|
||||
movq(r31, xmm5);
|
||||
cvtsd2si(r20, ptr [r30]);
|
||||
bsr(r20, r30);
|
||||
}
|
||||
} c;
|
||||
const uint8_t tbl[] = {
|
||||
0xd5, 0xb1, 0x58, 0x5c, 0xa6, 0x04,
|
||||
0xd5, 0x90, 0x10, 0x28, 0x66,
|
||||
0xd5, 0x99, 0x7e, 0xef, 0xf2,
|
||||
0xd5, 0xd9, 0x2d, 0x26,
|
||||
0xd5, 0xd9, 0xbd, 0xe6,
|
||||
|
||||
};
|
||||
const size_t n = sizeof(tbl);
|
||||
CYBOZU_TEST_EQUAL(c.getSize(), n);
|
||||
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
|
||||
}
|
||||
|
||||
|
|
|
@ -1736,14 +1736,15 @@ private:
|
|||
db(0xD5);
|
||||
db((rexRXB(4, bit3, r, b, x) << 4) | rex4bit);
|
||||
}
|
||||
void rex(const Operand& op1, const Operand& op2 = Operand(), uint64_t type = 0)
|
||||
// return T_REX2 if rex2 is selected
|
||||
uint64_t rex(const Operand& op1, const Operand& op2 = Operand(), uint64_t type = 0)
|
||||
{
|
||||
if (op1.getNF() | op2.getNF()) XBYAK_THROW(ERR_INVALID_NF)
|
||||
if (op1.getZU() | op2.getZU()) XBYAK_THROW(ERR_INVALID_ZU)
|
||||
if (op1.getNF() | op2.getNF()) XBYAK_THROW_RET(ERR_INVALID_NF, 0)
|
||||
if (op1.getZU() | op2.getZU()) XBYAK_THROW_RET(ERR_INVALID_ZU, 0)
|
||||
uint8_t rex = 0;
|
||||
const Operand *p1 = &op1, *p2 = &op2;
|
||||
if (p1->isMEM()) std::swap(p1, p2);
|
||||
if (p1->isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION)
|
||||
if (p1->isMEM()) XBYAK_THROW_RET(ERR_BAD_COMBINATION, 0)
|
||||
// except movsx(16bit, 32/64bit)
|
||||
bool p66 = (op1.isBit(16) && !op2.isBit(i32e)) || (op2.isBit(16) && !op1.isBit(i32e));
|
||||
if ((type & T_66) || p66) db(0x66);
|
||||
|
@ -1753,6 +1754,7 @@ private:
|
|||
if (type & T_F3) {
|
||||
db(0xF3);
|
||||
}
|
||||
bool is0F = type & T_0F;
|
||||
if (p2->isMEM()) {
|
||||
const Reg& r = *static_cast<const Reg*>(p1);
|
||||
const Address& addr = p2->getAddress();
|
||||
|
@ -1762,9 +1764,9 @@ private:
|
|||
if (BIT == 64 && addr.is32bit()) db(0x67);
|
||||
rex = rexRXB(3, r.isREG(64), r, base, idx);
|
||||
if (r.hasRex2() || addr.hasRex2()) {
|
||||
if (type & (T_0F|T_0F38|T_0F3A)) XBYAK_THROW(ERR_CANT_USE_REX2)
|
||||
rex2(0, rex, r, base, idx);
|
||||
return;
|
||||
if (type & (T_0F38|T_0F3A)) XBYAK_THROW_RET(ERR_CANT_USE_REX2, 0)
|
||||
rex2(is0F, rex, r, base, idx);
|
||||
return T_REX2;
|
||||
}
|
||||
if (rex || r.isExt8bit()) rex |= 0x40;
|
||||
} else {
|
||||
|
@ -1773,13 +1775,14 @@ private:
|
|||
// ModRM(reg, base);
|
||||
rex = rexRXB(3, r1.isREG(64) || r2.isREG(64), r2, r1);
|
||||
if (r1.hasRex2() || r2.hasRex2()) {
|
||||
if (type & (T_0F38|T_0F3A)) XBYAK_THROW(ERR_CANT_USE_REX2)
|
||||
rex2((type & T_0F) ? 1 : 0, rex, r2, r1);
|
||||
return;
|
||||
if (type & (T_0F38|T_0F3A)) XBYAK_THROW_RET(ERR_CANT_USE_REX2, 0)
|
||||
rex2(is0F, rex, r2, r1);
|
||||
return T_REX2;
|
||||
}
|
||||
if (rex || r1.isExt8bit() || r2.isExt8bit()) rex |= 0x40;
|
||||
}
|
||||
if (rex) db(rex);
|
||||
return 0;
|
||||
}
|
||||
// @@@begin of avx_type_def.h
|
||||
static const uint64_t T_NONE = 0ull;
|
||||
|
@ -1826,7 +1829,7 @@ private:
|
|||
static const uint64_t T_MAP6 = T_FP16 | T_0F38;
|
||||
static const uint64_t T_NF = 1ull << 32; // T_nf
|
||||
static const uint64_t T_CODE1_IF1 = 1ull << 33; // code|=1 if !r.isBit(8)
|
||||
|
||||
static const uint64_t T_REX2 = 1ull << 34;
|
||||
static const uint64_t T_ND1 = 1ull << 35; // ND=1
|
||||
static const uint64_t T_ZU = 1ull << 36; // ND=ZU
|
||||
static const uint64_t T_F2 = 1ull << 37; // pp = 3
|
||||
|
@ -2024,7 +2027,7 @@ private:
|
|||
bool isInDisp16(uint32_t x) const { return 0xFFFF8000 <= x || x <= 0x7FFF; }
|
||||
void writeCode(uint64_t type, const Reg& r, int code)
|
||||
{
|
||||
if (!(type & T_APX)) {
|
||||
if (!(type & (T_APX|T_REX2))) {
|
||||
if (type & T_0F) {
|
||||
db(0x0F);
|
||||
} else if (type & T_0F38) {
|
||||
|
@ -2033,18 +2036,18 @@ private:
|
|||
db(0x0F); db(0x3A);
|
||||
}
|
||||
}
|
||||
db(code | ((type == 0 || (type & T_CODE1_IF1)) && !r.isBit(8)));
|
||||
db(code | (((type&~T_REX2) == 0 || (type & T_CODE1_IF1)) && !r.isBit(8)));
|
||||
}
|
||||
void opRR(const Reg& reg1, const Reg& reg2, uint64_t type, int code)
|
||||
{
|
||||
rex(reg2, reg1, type);
|
||||
type |= rex(reg2, reg1, type);
|
||||
writeCode(type, reg1, code);
|
||||
setModRM(3, reg1.getIdx(), reg2.getIdx());
|
||||
}
|
||||
void opMR(const Address& addr, const Reg& r, uint64_t type, int code, int immSize = 0)
|
||||
{
|
||||
if (addr.is64bitDisp()) XBYAK_THROW(ERR_CANT_USE_64BIT_DISP)
|
||||
rex(addr, r, type);
|
||||
type |= rex(addr, r, type);
|
||||
writeCode(type, r, code);
|
||||
opAddr(addr, r.getIdx(), immSize);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue