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.
ASMJIT_ENUM(MemType) {
//! Memory operand is a combination of base register and optional index register
//! and displacement.
//! Memory operand is a combination of a base register, an optional index
//! register, and displacement.
//!
//! The `Assembler` interprets `kMemTypeBaseIndex` and `kMemTypeStackIndex`
//! types the same way, but `Compiler` interprets `kMemTypeBaseIndex` as
//! `[base + index]` and `kMemTypeStackIndex` as `[stack(base) + index]`.
kMemTypeBaseIndex = 0,
//! Memory operand is a combination of variable's memory location,
//! optional index register and displacement.
//! Memory operand is a combination of variable's memory location, an
//! optional index register, and displacement.
//!
//! 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]`.
kMemTypeStackIndex = 1,
//! Memory operand refers to the memory location specified by a label.
kMemTypeLabel = 2,
//! Memory operand is an absolute memory location.
//!
//! Supported mostly by x86, truncated to a 32-bit value when running in
//! 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;
sb.appendUInt(static_cast<uint32_t>(m->getDisplacement()), 16);
break;
case kMemTypeRip:
// [rip + displacement]
sb.appendString("rip", 3);
break;
default:
sb.appendFormat("<invalid %d>", m->getMemType());
break;
}
if (m->hasIndex()) {
@@ -3645,12 +3654,15 @@ _EmitSib:
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].
label = self->getLabelData(rmMem->_vmem.base);
relocId = self->_relocList.getLength();
{
RelocData rd;
rd.type = kRelocRelToAbs;
rd.size = 4;
@@ -3659,7 +3671,6 @@ _EmitSib:
if (self->_relocList.append(rd) != kErrorOk)
return self->setError(kErrorNoHeapMemory);
}
if (label->offset != -1) {
// Bound label.
@@ -3674,12 +3685,39 @@ _EmitSib:
}
}
else {
// [Disp32].
EMIT_DWORD(static_cast<int32_t>(dispOffset));
// RIP->Absolute [x86 mode].
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) */ {
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].
label = self->getLabelData(rmMem->_vmem.base);
@@ -3703,20 +3741,13 @@ _EmitSib:
}
}
else {
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);
// [RIP + Disp32].
uint32_t shift = rmMem->getShift();
EMIT_BYTE(x86EncodeSib(shift, mIndex, 5));
}
// Indexing is invalid.
if (mIndex < kInvalidReg)
goto _IllegalDisp;
EMIT_BYTE(x86EncodeMod(0, opReg, 5));
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);
}
//! \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 {
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);
}
//! \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 {
return x86::ptr_abs(pAbs, disp, _regSize);
}

View File

@@ -1145,6 +1145,11 @@ struct X86Mem : public BaseMem {
_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) {
_init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeBaseIndex,
_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) {
return X86Mem(base, index, shift, disp, size);
}
//! 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) {
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); \
}
//! 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.
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.
@@ -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) { \
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. */ \
static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, int32_t disp = 0) { \
return ptr_abs(pAbs, disp, _Size_); \