Added a possibility to use RIP addressing.

This commit is contained in:
kobalicek
2015-03-27 01:12:41 +01:00
parent 9b48ec0f1e
commit 9001d2f2b7
5 changed files with 93 additions and 35 deletions

View File

@@ -96,29 +96,33 @@ ASMJIT_ENUM(SizeDefs) {
//! Type of memory operand. //! Type of memory operand.
ASMJIT_ENUM(MemType) { ASMJIT_ENUM(MemType) {
//! Memory operand is a combination of base register and optional index register //! Memory operand is a combination of a base register, an optional index
//! and displacement. //! register, and displacement.
//! //!
//! The `Assembler` interprets `kMemTypeBaseIndex` and `kMemTypeStackIndex` //! The `Assembler` interprets `kMemTypeBaseIndex` and `kMemTypeStackIndex`
//! types the same way, but `Compiler` interprets `kMemTypeBaseIndex` as //! types the same way, but `Compiler` interprets `kMemTypeBaseIndex` as
//! `[base + index]` and `kMemTypeStackIndex` as `[stack(base) + index]`. //! `[base + index]` and `kMemTypeStackIndex` as `[stack(base) + index]`.
kMemTypeBaseIndex = 0, kMemTypeBaseIndex = 0,
//! Memory operand is a combination of variable's memory location, //! Memory operand is a combination of variable's memory location, an
//! optional index register and displacement. //! optional index register, and displacement.
//! //!
//! The `Assembler` interprets `kMemTypeBaseIndex` and `kMemTypeStackIndex` //! The `Assembler` interprets `kMemTypeBaseIndex` and `kMemTypeStackIndex`
//! types in the same way, but `Compiler` interprets `kMemTypeBaseIndex` as //! types the same way, but `Compiler` interprets `kMemTypeBaseIndex` as
//! `[base + index]` and `kMemTypeStackIndex` as `[stack(base) + index]`. //! `[base + index]` and `kMemTypeStackIndex` as `[stack(base) + index]`.
kMemTypeStackIndex = 1, kMemTypeStackIndex = 1,
//! Memory operand refers to the memory location specified by a label.
kMemTypeLabel = 2,
//! Memory operand is an absolute memory location. //! Memory operand is an absolute memory location.
//! //!
//! Supported mostly by x86, truncated to a 32-bit value when running in //! Supported mostly by x86, truncated to a 32-bit value when running in
//! 64-bit mode (x64). //! 64-bit mode (x64).
kMemTypeAbsolute = 3 kMemTypeAbsolute = 2,
//! Memory operand refers to the memory location specified by a label.
kMemTypeLabel = 3,
//! Memory operand is an address specified by RIP.
kMemTypeRip = 4
}; };
// ============================================================================ // ============================================================================

View File

@@ -808,6 +808,15 @@ static void X86Assembler_dumpOperand(StringBuilder& sb, uint32_t arch, const Ope
isAbsolute = true; isAbsolute = true;
sb.appendUInt(static_cast<uint32_t>(m->getDisplacement()), 16); sb.appendUInt(static_cast<uint32_t>(m->getDisplacement()), 16);
break; break;
case kMemTypeRip:
// [rip + displacement]
sb.appendString("rip", 3);
break;
default:
sb.appendFormat("<invalid %d>", m->getMemType());
break;
} }
if (m->hasIndex()) { if (m->hasIndex()) {
@@ -3645,12 +3654,15 @@ _EmitSib:
EMIT_BYTE(x86EncodeSib(shift, mIndex, 5)); EMIT_BYTE(x86EncodeSib(shift, mIndex, 5));
} }
if (rmMem->getMemType() == kMemTypeLabel) { if (rmMem->getMemType() == kMemTypeAbsolute) {
// [Disp32].
EMIT_DWORD(static_cast<int32_t>(dispOffset));
}
else if (rmMem->getMemType() == kMemTypeLabel) {
// Relative->Absolute [x86 mode]. // Relative->Absolute [x86 mode].
label = self->getLabelData(rmMem->_vmem.base); label = self->getLabelData(rmMem->_vmem.base);
relocId = self->_relocList.getLength(); relocId = self->_relocList.getLength();
{
RelocData rd; RelocData rd;
rd.type = kRelocRelToAbs; rd.type = kRelocRelToAbs;
rd.size = 4; rd.size = 4;
@@ -3659,7 +3671,6 @@ _EmitSib:
if (self->_relocList.append(rd) != kErrorOk) if (self->_relocList.append(rd) != kErrorOk)
return self->setError(kErrorNoHeapMemory); return self->setError(kErrorNoHeapMemory);
}
if (label->offset != -1) { if (label->offset != -1) {
// Bound label. // Bound label.
@@ -3674,12 +3685,39 @@ _EmitSib:
} }
} }
else { else {
// [Disp32]. // RIP->Absolute [x86 mode].
EMIT_DWORD(static_cast<int32_t>(dispOffset)); relocId = self->_relocList.getLength();
RelocData rd;
rd.type = kRelocRelToAbs;
rd.size = 4;
rd.from = static_cast<Ptr>((uintptr_t)(cursor - self->_buffer));
rd.data = rd.from + static_cast<SignedPtr>(dispOffset);
if (self->_relocList.append(rd) != kErrorOk)
return self->setError(kErrorNoHeapMemory);
EMIT_DWORD(0);
} }
} }
else /* if (Arch === kArchX64) */ { else /* if (Arch === kArchX64) */ {
if (rmMem->getMemType() == kMemTypeLabel) { if (rmMem->getMemType() == kMemTypeAbsolute) {
EMIT_BYTE(x86EncodeMod(0, opReg, 4));
if (mIndex >= kInvalidReg) {
// [Disp32].
EMIT_BYTE(x86EncodeSib(0, 4, 5));
}
else {
// [Disp32 + Index * Scale].
mIndex &= 0x7;
ASMJIT_ASSERT(mIndex != kX86RegIndexSp);
uint32_t shift = rmMem->getShift();
EMIT_BYTE(x86EncodeSib(shift, mIndex, 5));
}
EMIT_DWORD(static_cast<int32_t>(dispOffset));
}
else if (rmMem->getMemType() == kMemTypeLabel) {
// [RIP + Disp32]. // [RIP + Disp32].
label = self->getLabelData(rmMem->_vmem.base); label = self->getLabelData(rmMem->_vmem.base);
@@ -3703,20 +3741,13 @@ _EmitSib:
} }
} }
else { else {
EMIT_BYTE(x86EncodeMod(0, opReg, 4)); // [RIP + Disp32].
if (mIndex >= kInvalidReg) {
// [Disp32].
EMIT_BYTE(x86EncodeSib(0, 4, 5));
}
else {
// [Disp32 + Index * Scale].
mIndex &= 0x7;
ASMJIT_ASSERT(mIndex != kX86RegIndexSp);
uint32_t shift = rmMem->getShift(); // Indexing is invalid.
EMIT_BYTE(x86EncodeSib(shift, mIndex, 5)); if (mIndex < kInvalidReg)
} goto _IllegalDisp;
EMIT_BYTE(x86EncodeMod(0, opReg, 5));
EMIT_DWORD(static_cast<int32_t>(dispOffset)); EMIT_DWORD(static_cast<int32_t>(dispOffset));
} }
} }

View File

@@ -422,6 +422,10 @@ struct ASMJIT_VCLASS X86Assembler : public Assembler {
return x86::ptr(label, index, shift, disp, _regSize); return x86::ptr(label, index, shift, disp, _regSize);
} }
//! \overload //! \overload
ASMJIT_INLINE X86Mem intptr_ptr(const X86RipReg& rip, int32_t disp = 0) const {
return x86::ptr(rip, disp, _regSize);
}
//! \overload
ASMJIT_INLINE X86Mem intptr_ptr_abs(Ptr pAbs, int32_t disp = 0) const { ASMJIT_INLINE X86Mem intptr_ptr_abs(Ptr pAbs, int32_t disp = 0) const {
return x86::ptr_abs(pAbs, disp, _regSize); return x86::ptr_abs(pAbs, disp, _regSize);
} }

View File

@@ -2083,6 +2083,10 @@ struct ASMJIT_VCLASS X86Compiler : public Compiler {
return x86::ptr(label, index, shift, disp, _regSize); return x86::ptr(label, index, shift, disp, _regSize);
} }
//! \overload //! \overload
ASMJIT_INLINE X86Mem intptr_ptr(const X86RipReg& rip, int32_t disp = 0) const {
return x86::ptr(rip, disp, _regSize);
}
//! \overload
ASMJIT_INLINE X86Mem intptr_ptr_abs(Ptr pAbs, int32_t disp = 0) const { ASMJIT_INLINE X86Mem intptr_ptr_abs(Ptr pAbs, int32_t disp = 0) const {
return x86::ptr_abs(pAbs, disp, _regSize); return x86::ptr_abs(pAbs, disp, _regSize);
} }

View File

@@ -1145,6 +1145,11 @@ struct X86Mem : public BaseMem {
_vmem.displacement = disp; _vmem.displacement = disp;
} }
ASMJIT_INLINE X86Mem(const X86RipReg& rip, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) {
_init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeRip, 0, kInvalidValue);
_init_packed_d2_d3(kInvalidValue, disp);
}
ASMJIT_INLINE X86Mem(const X86GpReg& base, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) { ASMJIT_INLINE X86Mem(const X86GpReg& base, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) {
_init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeBaseIndex, _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeBaseIndex,
_getGpdFlags(base) _getGpdFlags(base)
@@ -1870,6 +1875,7 @@ static ASMJIT_INLINE X86Mem ptr(const X86GpReg& base, const X86XmmReg& index, ui
static ASMJIT_INLINE X86Mem ptr(const X86GpReg& base, const X86YmmReg& index, uint32_t shift = 0, int32_t disp = 0, uint32_t size = 0) { static ASMJIT_INLINE X86Mem ptr(const X86GpReg& base, const X86YmmReg& index, uint32_t shift = 0, int32_t disp = 0, uint32_t size = 0) {
return X86Mem(base, index, shift, disp, size); return X86Mem(base, index, shift, disp, size);
} }
//! Create `[label + disp]` memory operand with no/custom size information. //! Create `[label + disp]` memory operand with no/custom size information.
static ASMJIT_INLINE X86Mem ptr(const Label& label, int32_t disp = 0, uint32_t size = 0) { static ASMJIT_INLINE X86Mem ptr(const Label& label, int32_t disp = 0, uint32_t size = 0) {
return X86Mem(label, disp, size); return X86Mem(label, disp, size);
@@ -1879,6 +1885,11 @@ static ASMJIT_INLINE X86Mem ptr(const Label& label, const X86GpReg& index, uint3
return X86Mem(label, index, shift, disp, size); \ return X86Mem(label, index, shift, disp, size); \
} }
//! Create `[RIP + disp]` memory operand with no/custom size information.
static ASMJIT_INLINE X86Mem ptr(const X86RipReg& rip, int32_t disp = 0, uint32_t size = 0) {
return X86Mem(rip, disp, size);
}
//! Create `[pAbs + disp]` absolute memory operand with no/custom size information. //! Create `[pAbs + disp]` absolute memory operand with no/custom size information.
ASMJIT_API X86Mem ptr_abs(Ptr pAbs, int32_t disp = 0, uint32_t size = 0); ASMJIT_API X86Mem ptr_abs(Ptr pAbs, int32_t disp = 0, uint32_t size = 0);
//! Create `[pAbs + (index.reg << shift) + disp]` absolute memory operand with no/custom size information. //! Create `[pAbs + (index.reg << shift) + disp]` absolute memory operand with no/custom size information.
@@ -1910,6 +1921,10 @@ ASMJIT_API X86Mem ptr_abs(Ptr pAbs, const X86Reg& index, uint32_t shift = 0, int
static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const Label& label, const X86GpReg& index, uint32_t shift, int32_t disp = 0) { \ static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const Label& label, const X86GpReg& index, uint32_t shift, int32_t disp = 0) { \
return ptr(label, index, shift, disp, _Size_); \ return ptr(label, index, shift, disp, _Size_); \
} \ } \
/*! Create `[RIP + disp]` memory operand. */ \
static ASMJIT_INLINE X86Mem _Prefix_##ptr(const X86RipReg& rip, int32_t disp = 0) { \
return ptr(rip, disp, _Size_); \
} \
/*! Create `[pAbs + disp]` memory operand. */ \ /*! Create `[pAbs + disp]` memory operand. */ \
static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, int32_t disp = 0) { \ static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, int32_t disp = 0) { \
return ptr_abs(pAbs, disp, _Size_); \ return ptr_abs(pAbs, disp, _Size_); \