Skip to content

Commit

Permalink
refactoring rex
Browse files Browse the repository at this point in the history
  • Loading branch information
herumi committed Oct 13, 2023
1 parent acd7971 commit d7a7ea9
Showing 1 changed file with 31 additions and 37 deletions.
68 changes: 31 additions & 37 deletions xbyak/xbyak.h
Original file line number Diff line number Diff line change
Expand Up @@ -763,16 +763,6 @@ class Reg : public Operand {
XBYAK_CONSTEXPR Reg(int idx, Kind kind, int bit = 0, bool ext8bit = false) : Operand(idx, kind, bit, ext8bit) { }
// convert to Reg8/Reg16/Reg32/Reg64/XMM/YMM/ZMM
Reg changeBit(int bit) const { Reg r(*this); r.setBit(bit); return r; }
uint8_t getRexW() const { return isREG(64) ? 8 : 0; }
uint8_t getRexR() const { return isExtIdx() ? 4 : 0; }
uint8_t getRexX() const { return isExtIdx() ? 2 : 0; }
uint8_t getRexB() const { return isExtIdx() ? 1 : 0; }
uint8_t getRex(const Reg& base = Reg()) const
{
uint8_t rex = getRexW() | getRexR() | base.getRexW() | base.getRexB();
if (rex || isExt8bit() || base.isExt8bit()) rex |= 0x40;
return rex;
}
Reg8 cvt8() const;
Reg16 cvt16() const;
Reg32 cvt32() const;
Expand Down Expand Up @@ -982,11 +972,6 @@ class RegExp {
}
friend RegExp operator+(const RegExp& a, const RegExp& b);
friend RegExp operator-(const RegExp& e, size_t disp);
uint8_t getRex() const
{
uint8_t rex = index_.getRexX() | base_.getRexB();
return rex ? uint8_t(rex | 0x40) : 0;
}
private:
/*
[base_ + index_ * scale_ + disp_]
Expand Down Expand Up @@ -1298,11 +1283,6 @@ class Address : public Operand {
bool is32bit() const { return e_.getBase().getBit() == 32 || e_.getIndex().getBit() == 32; }
bool isOnlyDisp() const { return !e_.getBase().getBit() && !e_.getIndex().getBit(); } // for mov eax
size_t getDisp() const { return e_.getDisp(); }
uint8_t getRex() const
{
if (mode_ != M_ModRM) return 0;
return getRegExp().getRex();
}
bool is64bitDisp() const { return mode_ == M_64bitDisp; } // for moffset
bool isBroadcast() const { return broadcast_; }
bool hasRex2() const { return e_.getBase().getIdx() >= 16 || e_.getIndex().getIdx() >= 16; }
Expand Down Expand Up @@ -1703,7 +1683,16 @@ class CodeGenerator : public CodeArray {
// SSE instructions do not support XMM16 - XMM31
return !(op1.isXMM() && op1.getIdx() >= 16);
}
void rex(const Operand& op1, const Operand& op2 = Operand())
static inline uint8_t rexRXB(int bit, int bit3, const Reg& r, const Reg& b, const Reg& x = Reg())
{
int v = bit3 ? 8 : 0;
if (r.hasIdxBit(bit)) v |= 4;
if (x.hasIdxBit(bit)) v |= 2;
if (b.hasIdxBit(bit)) v |= 1;
return uint8_t(v);
}
// optimize = false is a special case for bnd*
void rex(const Operand& op1, const Operand& op2 = Operand(), bool optimize = true)
{
uint8_t rex = 0;
const Operand *p1 = &op1, *p2 = &op2;
Expand All @@ -1715,26 +1704,30 @@ class CodeGenerator : public CodeArray {
if (p2->isMEM()) {
const Reg& r = *static_cast<const Reg*>(p1);
const Address& addr = p2->getAddress();
const RegExp e = addr.getRegExp(optimize);
const Reg& base = e.getBase();
const Reg& idx = e.getIndex();
if (BIT == 64 && addr.is32bit()) db(0x67);
rex = rexRXB(3, r.isREG(64), r, base, idx);
if (r.getIdx() >= 16 || addr.hasRex2()) {
const RegExp e = addr.getRegExp();
const Reg& base = e.getBase();
const Reg& idx = e.getIndex();
db(0xD5);
// rex2 : R = r, X = idx, B = base
db(rex2p(0, r.hasIdxBit(4),idx.hasIdxBit(4), base.hasIdxBit(4), r.isREG(64), r.hasIdxBit(3), idx.hasIdxBit(3), base.hasIdxBit(3)));
// rex2 : R = r, B = base, X = idx
db((rexRXB(4, 0, r, base, idx) << 4) | rex);
return;
}
rex = addr.getRex() | r.getRex();
if (rex || r.isExt8bit()) rex |= 0x40;
} else {
if (op1.getIdx() >= 16 || op2.getIdx() >= 16) {
// rex2 : R = op2, X = None, B = op1
const Reg& r1 = static_cast<const Reg&>(op1);
const Reg& r2 = static_cast<const Reg&>(op2);
// ModRM(reg, base);
rex = rexRXB(3, r1.isREG(64) || r2.isREG(64), r2, r1);
if (r1.getIdx() >= 16 || r2.getIdx() >= 16) {
// rex2 : R = op2, B = op1, X = None
db(0xD5);
db(rex2p(0, op2.hasIdxBit(4),0, op1.hasIdxBit(4), op1.isREG(64), op2.hasIdxBit(3), 0, op1.hasIdxBit(3)));
db((rexRXB(4, 0, r2, r1) << 4) | rex);
return;
}
// ModRM(reg, base);
rex = op2.getReg().getRex(op1.getReg());
if (rex || r1.isExt8bit() || r2.isExt8bit()) rex |= 0x40;
}
if (rex) db(rex);
}
Expand Down Expand Up @@ -1956,22 +1949,23 @@ class CodeGenerator : public CodeArray {
db(code0 | (reg.isBit(8) ? 0 : 1)); if (code1 != NONE) db(code1); if (code2 != NONE) db(code2);
opAddr(addr, reg.getIdx(), immSize);
}
void opLoadSeg(const Address& addr, const Reg& reg, int code0, int code1 = NONE)
void opLoadSeg(const Address& addr, const Reg& reg, int code0, int code1)
{
if (addr.is64bitDisp()) XBYAK_THROW(ERR_CANT_USE_64BIT_DISP)
if (reg.isBit(8)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER)
if (addr.is64bitDisp()) XBYAK_THROW(ERR_CANT_USE_64BIT_DISP)
// can't use opModM
rex(addr, reg);
db(code0); if (code1 != NONE) db(code1);
opAddr(addr, reg.getIdx());
}
// for only MPX(bnd*)
void opMIB(const Address& addr, const Reg& reg, int code0, int code1)
{
if (addr.is64bitDisp()) XBYAK_THROW(ERR_CANT_USE_64BIT_DISP)
if (addr.getMode() != Address::M_ModRM) XBYAK_THROW(ERR_INVALID_MIB_ADDRESS)
if (BIT == 64 && addr.is32bit()) db(0x67);
// can't use opModM
const RegExp& regExp = addr.getRegExp(false);
uint8_t rex = regExp.getRex();
if (rex) db(rex);
rex(addr, reg, false);
db(code0); db(code1);
setSIB(regExp, reg.getIdx());
}
Expand Down

0 comments on commit d7a7ea9

Please sign in to comment.