diff --git a/src/asmjit/base/operand.h b/src/asmjit/base/operand.h index 1adc6e2..c56559a 100644 --- a/src/asmjit/base/operand.h +++ b/src/asmjit/base/operand.h @@ -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 + //! 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 + //! The `Assembler` interprets `kMemTypeBaseIndex` and `kMemTypeStackIndex` + //! 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 }; // ============================================================================ diff --git a/src/asmjit/x86/x86assembler.cpp b/src/asmjit/x86/x86assembler.cpp index d60ae64..ece4e46 100644 --- a/src/asmjit/x86/x86assembler.cpp +++ b/src/asmjit/x86/x86assembler.cpp @@ -808,6 +808,15 @@ static void X86Assembler_dumpOperand(StringBuilder& sb, uint32_t arch, const Ope isAbsolute = true; sb.appendUInt(static_cast(m->getDisplacement()), 16); break; + + case kMemTypeRip: + // [rip + displacement] + sb.appendString("rip", 3); + break; + + default: + sb.appendFormat("", m->getMemType()); + break; } if (m->hasIndex()) { @@ -3645,21 +3654,23 @@ _EmitSib: EMIT_BYTE(x86EncodeSib(shift, mIndex, 5)); } - if (rmMem->getMemType() == kMemTypeLabel) { + if (rmMem->getMemType() == kMemTypeAbsolute) { + // [Disp32]. + EMIT_DWORD(static_cast(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; - rd.from = static_cast((uintptr_t)(cursor - self->_buffer)); - rd.data = static_cast(dispOffset); + RelocData rd; + rd.type = kRelocRelToAbs; + rd.size = 4; + rd.from = static_cast((uintptr_t)(cursor - self->_buffer)); + rd.data = static_cast(dispOffset); - if (self->_relocList.append(rd) != kErrorOk) - return self->setError(kErrorNoHeapMemory); - } + 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(dispOffset)); + // RIP->Absolute [x86 mode]. + relocId = self->_relocList.getLength(); + + RelocData rd; + rd.type = kRelocRelToAbs; + rd.size = 4; + rd.from = static_cast((uintptr_t)(cursor - self->_buffer)); + rd.data = rd.from + static_cast(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(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(dispOffset)); } } diff --git a/src/asmjit/x86/x86assembler.h b/src/asmjit/x86/x86assembler.h index 32f0bd5..c301903 100644 --- a/src/asmjit/x86/x86assembler.h +++ b/src/asmjit/x86/x86assembler.h @@ -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); } diff --git a/src/asmjit/x86/x86compiler.h b/src/asmjit/x86/x86compiler.h index aa2d0ab..1f0038c 100644 --- a/src/asmjit/x86/x86compiler.h +++ b/src/asmjit/x86/x86compiler.h @@ -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); } diff --git a/src/asmjit/x86/x86operand.h b/src/asmjit/x86/x86operand.h index d0cbcee..d1b9ec9 100644 --- a/src/asmjit/x86/x86operand.h +++ b/src/asmjit/x86/x86operand.h @@ -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_); \