mirror of https://github.com/PCSX2/pcsx2.git
x86emitter: Remove virtual methods from register types
Allows methods to generate variable-sized registers
This commit is contained in:
parent
f33a6076dc
commit
096bb8bf74
|
@ -201,8 +201,18 @@ class xAddressVoid;
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
class OperandSizedObject
|
class OperandSizedObject
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
uint _operandSize = 0;
|
||||||
|
OperandSizedObject() = default;
|
||||||
|
OperandSizedObject(uint operandSize)
|
||||||
|
: _operandSize(operandSize)
|
||||||
|
{
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
virtual uint GetOperandSize() const = 0;
|
uint GetOperandSize() const {
|
||||||
|
pxAssertDev(_operandSize != 0, "Attempted to use operand size of uninitialized or void object");
|
||||||
|
return _operandSize;
|
||||||
|
}
|
||||||
|
|
||||||
bool Is8BitOp() const { return GetOperandSize() == 1; }
|
bool Is8BitOp() const { return GetOperandSize() == 1; }
|
||||||
u8 GetPrefix16() const { return GetOperandSize() == 2 ? 0x66 : 0; }
|
u8 GetPrefix16() const { return GetOperandSize() == 2 ? 0x66 : 0; }
|
||||||
|
@ -258,20 +268,20 @@ static const int xRegId_Invalid = -2;
|
||||||
//
|
//
|
||||||
class xRegisterBase : public OperandSizedObject
|
class xRegisterBase : public OperandSizedObject
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
xRegisterBase(uint operandSize, int regId)
|
||||||
|
: OperandSizedObject(operandSize), Id(regId)
|
||||||
|
{
|
||||||
|
// Note: to avoid tons of ifdef, the 32 bits build will instantiate
|
||||||
|
// all 16x64 bits registers.
|
||||||
|
pxAssert((Id >= xRegId_Empty) && (Id < 16));
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
int Id;
|
int Id;
|
||||||
|
|
||||||
xRegisterBase()
|
xRegisterBase()
|
||||||
|
: OperandSizedObject(0), Id(xRegId_Invalid)
|
||||||
{
|
{
|
||||||
Id = xRegId_Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit xRegisterBase(int regId)
|
|
||||||
{
|
|
||||||
Id = regId;
|
|
||||||
// Note: to avoid tons of ifdef, the 32 bits build will instantiate
|
|
||||||
// all 16x64 bits registers.
|
|
||||||
pxAssert((Id >= xRegId_Empty) && (Id < 16));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsEmpty() const { return Id < 0; }
|
bool IsEmpty() const { return Id < 0; }
|
||||||
|
@ -301,9 +311,6 @@ public:
|
||||||
// return true if the register is a valid YMM register
|
// return true if the register is a valid YMM register
|
||||||
bool IsWideSIMD() const { return GetOperandSize() == 32; }
|
bool IsWideSIMD() const { return GetOperandSize() == 32; }
|
||||||
|
|
||||||
bool operator==(const xRegisterBase &src) const { return (Id == src.Id); }
|
|
||||||
bool operator!=(const xRegisterBase &src) const { return (Id != src.Id); }
|
|
||||||
|
|
||||||
// Diagnostics -- returns a string representation of this register. Return string
|
// Diagnostics -- returns a string representation of this register. Return string
|
||||||
// is a valid non-null string for any Id, valid or invalid. No assertions are generated.
|
// is a valid non-null string for any Id, valid or invalid. No assertions are generated.
|
||||||
const char *GetName();
|
const char *GetName();
|
||||||
|
@ -314,19 +321,35 @@ class xRegisterInt : public xRegisterBase
|
||||||
{
|
{
|
||||||
typedef xRegisterBase _parent;
|
typedef xRegisterBase _parent;
|
||||||
|
|
||||||
public:
|
protected:
|
||||||
xRegisterInt() {}
|
explicit xRegisterInt(uint operandSize, int regId)
|
||||||
explicit xRegisterInt(const xRegisterBase &src)
|
: _parent(operandSize, regId)
|
||||||
: _parent(src)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
explicit xRegisterInt(int regId)
|
public:
|
||||||
: _parent(regId)
|
xRegisterInt() = default;
|
||||||
|
|
||||||
|
/// IDs in [4, 8) are h registers in 8-bit
|
||||||
|
int isIDSameInAllSizes() const
|
||||||
{
|
{
|
||||||
|
return Id < 4 || Id >= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if mapping the ID directly would be a good idea
|
||||||
|
bool canMapIDTo(int otherSize) const
|
||||||
|
{
|
||||||
|
if ((otherSize == 1) == GetOperandSize() == 1)
|
||||||
|
return true;
|
||||||
|
return isIDSameInAllSizes();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a non-wide version of the register (for use with e.g. mov, where `mov eax, 3` and `mov rax, 3` are functionally identical but `mov eax, 3` is shorter)
|
/// Get a non-wide version of the register (for use with e.g. mov, where `mov eax, 3` and `mov rax, 3` are functionally identical but `mov eax, 3` is shorter)
|
||||||
virtual const xRegisterInt& GetNonWide() const = 0;
|
xRegisterInt GetNonWide() const
|
||||||
|
{
|
||||||
|
return GetOperandSize() == 8 ? xRegisterInt(4, Id) : *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
xRegisterInt MatchSizeTo(xRegisterInt other) const;
|
||||||
|
|
||||||
bool operator==(const xRegisterInt &src) const { return Id == src.Id && (GetOperandSize() == src.GetOperandSize()); }
|
bool operator==(const xRegisterInt &src) const { return Id == src.Id && (GetOperandSize() == src.GetOperandSize()); }
|
||||||
bool operator!=(const xRegisterInt &src) const { return !operator==(src); }
|
bool operator!=(const xRegisterInt &src) const { return !operator==(src); }
|
||||||
|
@ -340,17 +363,16 @@ class xRegister8 : public xRegisterInt
|
||||||
typedef xRegisterInt _parent;
|
typedef xRegisterInt _parent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
xRegister8()
|
xRegister8() = default;
|
||||||
: _parent()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
explicit xRegister8(int regId)
|
explicit xRegister8(int regId)
|
||||||
: _parent(regId)
|
: _parent(1, regId)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
explicit xRegister8(const xRegisterInt& other)
|
||||||
virtual uint GetOperandSize() const override { return 1; }
|
: _parent(1, other.Id)
|
||||||
virtual const xRegisterInt& GetNonWide() const override { return *this; }
|
{
|
||||||
|
pxAssertDev(other.canMapIDTo(1), "spl, bpl, sil, dil not yet supported");
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(const xRegister8 &src) const { return Id == src.Id; }
|
bool operator==(const xRegister8 &src) const { return Id == src.Id; }
|
||||||
bool operator!=(const xRegister8 &src) const { return Id != src.Id; }
|
bool operator!=(const xRegister8 &src) const { return Id != src.Id; }
|
||||||
|
@ -361,17 +383,16 @@ class xRegister16 : public xRegisterInt
|
||||||
typedef xRegisterInt _parent;
|
typedef xRegisterInt _parent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
xRegister16()
|
xRegister16() = default;
|
||||||
: _parent()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
explicit xRegister16(int regId)
|
explicit xRegister16(int regId)
|
||||||
: _parent(regId)
|
: _parent(2, regId)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
explicit xRegister16(const xRegisterInt& other)
|
||||||
virtual uint GetOperandSize() const override { return 2; }
|
: _parent(2, other.Id)
|
||||||
virtual const xRegisterInt& GetNonWide() const override { return *this; }
|
{
|
||||||
|
pxAssertDev(other.canMapIDTo(2), "Mapping h registers to higher registers can produce unexpected values");
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(const xRegister16 &src) const { return this->Id == src.Id; }
|
bool operator==(const xRegister16 &src) const { return this->Id == src.Id; }
|
||||||
bool operator!=(const xRegister16 &src) const { return this->Id != src.Id; }
|
bool operator!=(const xRegister16 &src) const { return this->Id != src.Id; }
|
||||||
|
@ -382,17 +403,16 @@ class xRegister32 : public xRegisterInt
|
||||||
typedef xRegisterInt _parent;
|
typedef xRegisterInt _parent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
xRegister32()
|
xRegister32() = default;
|
||||||
: _parent()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
explicit xRegister32(int regId)
|
explicit xRegister32(int regId)
|
||||||
: _parent(regId)
|
: _parent(4, regId)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
explicit xRegister32(const xRegisterInt& other)
|
||||||
virtual uint GetOperandSize() const override { return 4; }
|
: _parent(4, other.Id)
|
||||||
virtual const xRegisterInt& GetNonWide() const override { return *this; }
|
{
|
||||||
|
pxAssertDev(other.canMapIDTo(4), "Mapping h registers to higher registers can produce unexpected values");
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(const xRegister32 &src) const { return this->Id == src.Id; }
|
bool operator==(const xRegister32 &src) const { return this->Id == src.Id; }
|
||||||
bool operator!=(const xRegister32 &src) const { return this->Id != src.Id; }
|
bool operator!=(const xRegister32 &src) const { return this->Id != src.Id; }
|
||||||
|
@ -402,21 +422,17 @@ class xRegister64 : public xRegisterInt
|
||||||
{
|
{
|
||||||
typedef xRegisterInt _parent;
|
typedef xRegisterInt _parent;
|
||||||
|
|
||||||
xRegister32 m_nonWide;
|
|
||||||
public:
|
public:
|
||||||
xRegister64()
|
xRegister64() = default;
|
||||||
: _parent()
|
|
||||||
, m_nonWide()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
explicit xRegister64(int regId)
|
explicit xRegister64(int regId)
|
||||||
: _parent(regId)
|
: _parent(8, regId)
|
||||||
, m_nonWide(regId)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
explicit xRegister64(const xRegisterInt& other)
|
||||||
virtual uint GetOperandSize() const override { return 8; }
|
: _parent(8, other.Id)
|
||||||
virtual const xRegisterInt& GetNonWide() const override { return m_nonWide; }
|
{
|
||||||
|
pxAssertDev(other.canMapIDTo(8), "Mapping h registers to higher registers can produce unexpected values");
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(const xRegister64 &src) const { return this->Id == src.Id; }
|
bool operator==(const xRegister64 &src) const { return this->Id == src.Id; }
|
||||||
bool operator!=(const xRegister64 &src) const { return this->Id != src.Id; }
|
bool operator!=(const xRegister64 &src) const { return this->Id != src.Id; }
|
||||||
|
@ -433,34 +449,15 @@ class xRegisterSSE : public xRegisterBase
|
||||||
typedef xRegisterBase _parent;
|
typedef xRegisterBase _parent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
xRegisterSSE()
|
xRegisterSSE() = default;
|
||||||
: _parent()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
explicit xRegisterSSE(int regId)
|
explicit xRegisterSSE(int regId)
|
||||||
: _parent(regId)
|
: _parent(16, regId)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual uint GetOperandSize() const { return 16; }
|
|
||||||
|
|
||||||
bool operator==(const xRegisterSSE &src) const { return this->Id == src.Id; }
|
bool operator==(const xRegisterSSE &src) const { return this->Id == src.Id; }
|
||||||
bool operator!=(const xRegisterSSE &src) const { return this->Id != src.Id; }
|
bool operator!=(const xRegisterSSE &src) const { return this->Id != src.Id; }
|
||||||
|
|
||||||
xRegisterSSE &operator++()
|
|
||||||
{
|
|
||||||
++Id;
|
|
||||||
Id &= (iREGCNT_XMM - 1);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
xRegisterSSE &operator--()
|
|
||||||
{
|
|
||||||
--Id;
|
|
||||||
Id &= (iREGCNT_XMM - 1);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const inline xRegisterSSE &GetInstance(uint id);
|
static const inline xRegisterSSE &GetInstance(uint id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -494,20 +491,9 @@ static const int wordsize = sizeof(sptr);
|
||||||
class xAddressReg : public xRegisterLong
|
class xAddressReg : public xRegisterLong
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
xAddressReg()
|
xAddressReg() = default;
|
||||||
: xRegisterLong()
|
explicit xAddressReg(xRegisterInt other)
|
||||||
{
|
: xRegisterLong(other)
|
||||||
}
|
|
||||||
xAddressReg(const xAddressReg &src)
|
|
||||||
: xRegisterLong(src.Id)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
xAddressReg(const xRegister32 &src)
|
|
||||||
: xRegisterLong(src.Id)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
xAddressReg(const xRegister64 &src)
|
|
||||||
: xRegisterLong(src.Id)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
explicit xAddressReg(int regId)
|
explicit xAddressReg(int regId)
|
||||||
|
@ -885,8 +871,6 @@ public:
|
||||||
explicit xIndirectVoid(sptr disp);
|
explicit xIndirectVoid(sptr disp);
|
||||||
explicit xIndirectVoid(const xAddressVoid &src);
|
explicit xIndirectVoid(const xAddressVoid &src);
|
||||||
xIndirectVoid(xAddressReg base, xAddressReg index, int scale = 0, sptr displacement = 0);
|
xIndirectVoid(xAddressReg base, xAddressReg index, int scale = 0, sptr displacement = 0);
|
||||||
|
|
||||||
virtual uint GetOperandSize() const;
|
|
||||||
xIndirectVoid &Add(sptr imm);
|
xIndirectVoid &Add(sptr imm);
|
||||||
|
|
||||||
bool IsByteSizeDisp() const { return is_s8(Displacement); }
|
bool IsByteSizeDisp() const { return is_s8(Displacement); }
|
||||||
|
@ -916,17 +900,22 @@ public:
|
||||||
explicit xIndirect(sptr disp)
|
explicit xIndirect(sptr disp)
|
||||||
: _parent(disp)
|
: _parent(disp)
|
||||||
{
|
{
|
||||||
|
_operandSize = sizeof(OperandType);
|
||||||
}
|
}
|
||||||
explicit xIndirect(const xAddressInfo<OperandType> &src)
|
explicit xIndirect(const xAddressInfo<OperandType> &src)
|
||||||
: _parent(src)
|
: _parent(src)
|
||||||
{
|
{
|
||||||
|
_operandSize = sizeof(OperandType);
|
||||||
}
|
}
|
||||||
xIndirect(xAddressReg base, xAddressReg index, int scale = 0, sptr displacement = 0)
|
xIndirect(xAddressReg base, xAddressReg index, int scale = 0, sptr displacement = 0)
|
||||||
: _parent(base, index, scale, displacement)
|
: _parent(base, index, scale, displacement)
|
||||||
|
{
|
||||||
|
_operandSize = sizeof(OperandType);
|
||||||
|
}
|
||||||
|
explicit xIndirect(const xIndirectVoid& other)
|
||||||
|
: _parent(other)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual uint GetOperandSize() const { return sizeof(OperandType); }
|
|
||||||
|
|
||||||
xIndirect<OperandType> &Add(sptr imm)
|
xIndirect<OperandType> &Add(sptr imm)
|
||||||
{
|
{
|
||||||
|
@ -970,42 +959,21 @@ class xIndirect64orLess : public xIndirectVoid
|
||||||
{
|
{
|
||||||
typedef xIndirectVoid _parent;
|
typedef xIndirectVoid _parent;
|
||||||
|
|
||||||
protected:
|
|
||||||
uint m_OpSize;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
xIndirect64orLess(const xIndirect8 &src)
|
xIndirect64orLess(const xIndirect8 &src)
|
||||||
: _parent(src)
|
: _parent(src)
|
||||||
{
|
{
|
||||||
m_OpSize = src.GetOperandSize();
|
|
||||||
}
|
}
|
||||||
xIndirect64orLess(const xIndirect16 &src)
|
xIndirect64orLess(const xIndirect16 &src)
|
||||||
: _parent(src)
|
: _parent(src)
|
||||||
{
|
{
|
||||||
m_OpSize = src.GetOperandSize();
|
|
||||||
}
|
}
|
||||||
xIndirect64orLess(const xIndirect32 &src)
|
xIndirect64orLess(const xIndirect32 &src)
|
||||||
: _parent(src)
|
: _parent(src)
|
||||||
{
|
{
|
||||||
m_OpSize = src.GetOperandSize();
|
|
||||||
}
|
}
|
||||||
xIndirect64orLess(const xIndirect64 &src)
|
xIndirect64orLess(const xIndirect64 &src)
|
||||||
: _parent(src)
|
: _parent(src)
|
||||||
{
|
|
||||||
m_OpSize = src.GetOperandSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint GetOperandSize() const { return m_OpSize; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//xIndirect64orLess( const xAddressVoid& src ) : _parent( src ) {}
|
|
||||||
|
|
||||||
explicit xIndirect64orLess(sptr disp)
|
|
||||||
: _parent(disp)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
xIndirect64orLess(xAddressReg base, xAddressReg index, int scale = 0, sptr displacement = 0)
|
|
||||||
: _parent(base, index, scale, displacement)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -55,17 +55,17 @@ void prepareRegsForFastcall(const Reg1 &a1, const Reg2 &a2) {
|
||||||
|
|
||||||
// Make sure we don't mess up if someone tries to fastcall with a1 in arg2reg and a2 in arg1reg
|
// Make sure we don't mess up if someone tries to fastcall with a1 in arg2reg and a2 in arg1reg
|
||||||
if (a2.Id != arg1reg.Id) {
|
if (a2.Id != arg1reg.Id) {
|
||||||
xMOV(Reg1(arg1reg.Id), a1);
|
xMOV(Reg1(arg1reg), a1);
|
||||||
if (!a2.IsEmpty()) {
|
if (!a2.IsEmpty()) {
|
||||||
xMOV(Reg2(arg2reg.Id), a2);
|
xMOV(Reg2(arg2reg), a2);
|
||||||
}
|
}
|
||||||
} else if (a1.Id != arg2reg.Id) {
|
} else if (a1.Id != arg2reg.Id) {
|
||||||
xMOV(Reg2(arg2reg.Id), a2);
|
xMOV(Reg2(arg2reg), a2);
|
||||||
xMOV(Reg1(arg1reg.Id), a1);
|
xMOV(Reg1(arg1reg), a1);
|
||||||
} else {
|
} else {
|
||||||
xPUSH(a1);
|
xPUSH(a1);
|
||||||
xMOV(Reg2(arg2reg.Id), a2);
|
xMOV(Reg2(arg2reg), a2);
|
||||||
xPOP(Reg1(arg1reg.Id));
|
xPOP(Reg1(arg1reg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -578,6 +578,16 @@ __emitinline void xAdvancePtr(uint bytes)
|
||||||
x86Ptr += bytes;
|
x86Ptr += bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// xRegisterInt (method implementations)
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
xRegisterInt xRegisterInt::MatchSizeTo(xRegisterInt other) const
|
||||||
|
{
|
||||||
|
return other.GetOperandSize() == 1
|
||||||
|
? xRegisterInt(xRegister8(*this))
|
||||||
|
: xRegisterInt(other.GetOperandSize(), Id);
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// xAddressReg (operator overloads)
|
// xAddressReg (operator overloads)
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -824,12 +834,6 @@ void xIndirectVoid::Reduce()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint xIndirectVoid::GetOperandSize() const
|
|
||||||
{
|
|
||||||
pxFailDev("Invalid operation on xIndirectVoid");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
xIndirectVoid &xIndirectVoid::Add(sptr imm)
|
xIndirectVoid &xIndirectVoid::Add(sptr imm)
|
||||||
{
|
{
|
||||||
Displacement += imm;
|
Displacement += imm;
|
||||||
|
@ -851,10 +855,6 @@ static void EmitLeaMagic(const xRegisterInt &to, const xIndirectVoid &src, bool
|
||||||
|
|
||||||
// See EmitSibMagic for commenting on SIB encoding.
|
// See EmitSibMagic for commenting on SIB encoding.
|
||||||
|
|
||||||
// We should allow native-sized addressing regs (e.g. lea eax, [rax])
|
|
||||||
const xRegisterInt& sizeMatchedIndex = to.IsWide() ? src.Index : src.Index.GetNonWide();
|
|
||||||
const xRegisterInt& sizeMatchedBase = to.IsWide() ? src.Base : src.Base.GetNonWide();
|
|
||||||
|
|
||||||
if (!NeedsSibMagic(src) && src.Displacement == (s32)src.Displacement) {
|
if (!NeedsSibMagic(src) && src.Displacement == (s32)src.Displacement) {
|
||||||
// LEA Land: means we have either 1-register encoding or just an offset.
|
// LEA Land: means we have either 1-register encoding or just an offset.
|
||||||
// offset is encodable as an immediate MOV, and a register is encodable
|
// offset is encodable as an immediate MOV, and a register is encodable
|
||||||
|
@ -865,13 +865,13 @@ static void EmitLeaMagic(const xRegisterInt &to, const xIndirectVoid &src, bool
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (displacement_size == 0) {
|
else if (displacement_size == 0) {
|
||||||
_xMovRtoR(to, sizeMatchedIndex);
|
_xMovRtoR(to, src.Index.MatchSizeTo(to));
|
||||||
return;
|
return;
|
||||||
} else if (!preserve_flags) {
|
} else if (!preserve_flags) {
|
||||||
// encode as MOV and ADD combo. Make sure to use the immediate on the
|
// encode as MOV and ADD combo. Make sure to use the immediate on the
|
||||||
// ADD since it can encode as an 8-bit sign-extended value.
|
// ADD since it can encode as an 8-bit sign-extended value.
|
||||||
|
|
||||||
_xMovRtoR(to, sizeMatchedIndex);
|
_xMovRtoR(to, src.Index.MatchSizeTo(to));
|
||||||
xADD(to, src.Displacement);
|
xADD(to, src.Displacement);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -894,20 +894,20 @@ static void EmitLeaMagic(const xRegisterInt &to, const xIndirectVoid &src, bool
|
||||||
if (!preserve_flags) {
|
if (!preserve_flags) {
|
||||||
if (src.Index == rsp) {
|
if (src.Index == rsp) {
|
||||||
// ESP is not encodable as an index (ix86 ignores it), thus:
|
// ESP is not encodable as an index (ix86 ignores it), thus:
|
||||||
_xMovRtoR(to, sizeMatchedBase); // will do the trick!
|
_xMovRtoR(to, src.Base.MatchSizeTo(to)); // will do the trick!
|
||||||
if (src.Displacement)
|
if (src.Displacement)
|
||||||
xADD(to, src.Displacement);
|
xADD(to, src.Displacement);
|
||||||
return;
|
return;
|
||||||
} else if (src.Displacement == 0) {
|
} else if (src.Displacement == 0) {
|
||||||
_xMovRtoR(to, sizeMatchedBase);
|
_xMovRtoR(to, src.Base.MatchSizeTo(to));
|
||||||
_g1_EmitOp(G1Type_ADD, to, sizeMatchedIndex);
|
_g1_EmitOp(G1Type_ADD, to, src.Index.MatchSizeTo(to));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if ((src.Index == rsp) && (src.Displacement == 0)) {
|
} else if ((src.Index == rsp) && (src.Displacement == 0)) {
|
||||||
// special case handling of ESP as Index, which is replaceable with
|
// special case handling of ESP as Index, which is replaceable with
|
||||||
// a single MOV even when preserve_flags is set! :D
|
// a single MOV even when preserve_flags is set! :D
|
||||||
|
|
||||||
_xMovRtoR(to, sizeMatchedBase);
|
_xMovRtoR(to, src.Base.MatchSizeTo(to));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -206,7 +206,7 @@ namespace vtlb_private
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
static void DynGen_DirectWrite( u32 bits )
|
static void DynGen_DirectWrite( u32 bits )
|
||||||
{
|
{
|
||||||
// TODO: x86Emitter can't use dil (and xRegister8(rdi.Id) is not dil)
|
// TODO: x86Emitter can't use dil
|
||||||
switch(bits)
|
switch(bits)
|
||||||
{
|
{
|
||||||
//8 , 16, 32 : data on EDX
|
//8 , 16, 32 : data on EDX
|
||||||
|
@ -216,7 +216,7 @@ namespace vtlb_private
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 16:
|
case 16:
|
||||||
xMOV( ptr[arg1reg], xRegister16(arg2reg.Id) );
|
xMOV( ptr[arg1reg], xRegister16(arg2reg) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 32:
|
case 32:
|
||||||
|
@ -543,7 +543,7 @@ void vtlb_DynGenWrite_Const( u32 bits, u32 addr_const )
|
||||||
auto vmv = vtlbdata.vmap[addr_const>>VTLB_PAGE_BITS];
|
auto vmv = vtlbdata.vmap[addr_const>>VTLB_PAGE_BITS];
|
||||||
if( !vmv.isHandler(addr_const) )
|
if( !vmv.isHandler(addr_const) )
|
||||||
{
|
{
|
||||||
// TODO: x86Emitter can't use dil (and xRegister8(rdi.Id) is not dil)
|
// TODO: x86Emitter can't use dil
|
||||||
auto ppf = vmv.assumePtr(addr_const);
|
auto ppf = vmv.assumePtr(addr_const);
|
||||||
switch(bits)
|
switch(bits)
|
||||||
{
|
{
|
||||||
|
@ -554,7 +554,7 @@ void vtlb_DynGenWrite_Const( u32 bits, u32 addr_const )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 16:
|
case 16:
|
||||||
xMOV( ptr[(void*)ppf], xRegister16(arg2reg.Id) );
|
xMOV( ptr[(void*)ppf], xRegister16(arg2reg) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 32:
|
case 32:
|
||||||
|
|
|
@ -939,10 +939,10 @@ mVUop(mVU_ISW) {
|
||||||
if (!_Is_)
|
if (!_Is_)
|
||||||
xXOR(gprT2, gprT2);
|
xXOR(gprT2, gprT2);
|
||||||
xADD(gprT2, _Imm11_);
|
xADD(gprT2, _Imm11_);
|
||||||
mVUaddrFix (mVU, gprT2);
|
mVUaddrFix (mVU, gprT2q);
|
||||||
|
|
||||||
mVUallocVIa(mVU, gprT1, _It_);
|
mVUallocVIa(mVU, gprT1, _It_);
|
||||||
writeBackISW(mVU, ptr, gprT2);
|
writeBackISW(mVU, ptr, gprT2q);
|
||||||
mVU.profiler.EmitOp(opISW);
|
mVU.profiler.EmitOp(opISW);
|
||||||
}
|
}
|
||||||
pass3 { mVUlog("ISW.%s vi%02d, vi%02d + %d", _XYZW_String, _Ft_, _Fs_, _Imm11_); }
|
pass3 { mVUlog("ISW.%s vi%02d, vi%02d + %d", _XYZW_String, _Ft_, _Fs_, _Imm11_); }
|
||||||
|
|
Loading…
Reference in New Issue