Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/asmjit/asmjit.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkobalicek <kobalicek.petr@gmail.com>2022-03-27 23:33:35 +0300
committerkobalicek <kobalicek.petr@gmail.com>2022-03-27 23:33:35 +0300
commit7342f7d78d8cd3088bb7b475c3f7ec52f7619980 (patch)
treef1faff61e9dbb8d67264384c0351ffec6dc3f57b
parent21a31b8a338da3341d2b423f85913597b8ec3d63 (diff)
Added a pseudo instruction 'loadAddressOf()' to load a memory address into a register (Compiler/AArch64)
-rw-r--r--src/asmjit/arm/a64compiler.h12
-rw-r--r--src/asmjit/arm/a64rapass.cpp42
2 files changed, 54 insertions, 0 deletions
diff --git a/src/asmjit/arm/a64compiler.h b/src/asmjit/arm/a64compiler.h
index ebed549..bed408a 100644
--- a/src/asmjit/arm/a64compiler.h
+++ b/src/asmjit/arm/a64compiler.h
@@ -169,6 +169,18 @@ public:
//! \}
+ //! \name Compiler specific
+ //! \{
+
+ //! Special pseudo-instruction that can be used to load a memory address into `o0` GP register.
+ //!
+ //! \note At the moment this instruction is only useful to load a stack allocated address into a GP register
+ //! for further use. It makes very little sense to use it for anything else. The semantics of this instruction
+ //! is the same as X86 `LEA` (load effective address) instruction.
+ inline Error loadAddressOf(const Gp& o0, const Mem& o1) { return _emitter()->_emitI(Inst::kIdAdr, o0, o1); }
+
+ //! \}
+
//! \name Function Call & Ret Intrinsics
//! \{
diff --git a/src/asmjit/arm/a64rapass.cpp b/src/asmjit/arm/a64rapass.cpp
index 597ae5c..9e81473 100644
--- a/src/asmjit/arm/a64rapass.cpp
+++ b/src/asmjit/arm/a64rapass.cpp
@@ -713,6 +713,48 @@ ASMJIT_FAVOR_SPEED Error ARMRAPass::_rewrite(BaseNode* first, BaseNode* stop) no
mem.clearRegHome();
mem.addOffsetLo32(offset);
}
+
+ // Rewrite `loadAddressOf()` construct.
+ if (node->type() == NodeType::kInst) {
+ InstNode* inst = node->as<InstNode>();
+ if (inst->realId() == Inst::kIdAdr && inst->opCount() == 2) {
+ int64_t offset = mem.offset();
+ if (!mem.hasBase()) {
+ inst->setId(Inst::kIdMov);
+ inst->setOp(1, Imm(offset));
+ }
+ else {
+ InstId op = offset < 0 ? Inst::kIdSub : Inst::kIdAdd;
+ uint64_t val = offset < 0 ? Support::neg(uint64_t(offset)) : uint64_t(offset);
+
+ GpX base = GpX(mem.baseId());
+
+ inst->setId(op);
+ inst->setOpCount(3);
+ inst->setOp(1, base);
+ inst->setOp(2, Imm(val));
+
+ if (val > 0xFFFu && (val & ~uint64_t(0xFFF000u)) != 0) {
+ const Operand_& dst = inst->op(0);
+ // Use two operations if the stack address is greater than 4095.
+ if (val <= 0xFFFFFFu) {
+ cc()->_setCursor(inst->prev());
+ cc()->_emitI(op, dst, base, Imm(val & 0xFFFu));
+
+ inst->setOp(1, dst);
+ inst->setOp(2, Imm(val & 0xFFF000u));
+ }
+ else {
+ cc()->_setCursor(inst->prev());
+ cc()->_emitI(Inst::kIdMov, inst->op(0), Imm(val));
+
+ inst->setOp(1, base);
+ inst->setOp(2, dst);
+ }
+ }
+ }
+ }
+ }
}
}
}