summaryrefslogtreecommitdiff
path: root/erts/emulator/asmjit/arm/a64rapass.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/asmjit/arm/a64rapass.cpp')
-rw-r--r--erts/emulator/asmjit/arm/a64rapass.cpp52
1 files changed, 49 insertions, 3 deletions
diff --git a/erts/emulator/asmjit/arm/a64rapass.cpp b/erts/emulator/asmjit/arm/a64rapass.cpp
index ad78369eaa..aaec1c90f9 100644
--- a/erts/emulator/asmjit/arm/a64rapass.cpp
+++ b/erts/emulator/asmjit/arm/a64rapass.cpp
@@ -102,7 +102,7 @@ public:
// TODO: [ARM] This is just a workaround...
static InstControlFlow getControlFlowType(InstId instId) noexcept {
- switch (instId) {
+ switch (BaseInst::extractRealId(instId)) {
case Inst::kIdB:
case Inst::kIdBr:
if (BaseInst::extractARMCondCode(instId) == CondCode::kAL)
@@ -127,8 +127,8 @@ static InstControlFlow getControlFlowType(InstId instId) noexcept {
Error RACFGBuilder::onInst(InstNode* inst, InstControlFlow& controlType, RAInstBuilder& ib) noexcept {
InstRWInfo rwInfo;
- InstId instId = inst->id();
- if (Inst::isDefinedId(instId)) {
+ if (Inst::isDefinedId(inst->realId())) {
+ InstId instId = inst->id();
uint32_t opCount = inst->opCount();
const Operand* opArray = inst->operands();
ASMJIT_PROPAGATE(InstInternal::queryRWInfo(_arch, inst->baseInst(), opArray, opCount, &rwInfo));
@@ -136,6 +136,8 @@ Error RACFGBuilder::onInst(InstNode* inst, InstControlFlow& controlType, RAInstB
const InstDB::InstInfo& instInfo = InstDB::infoById(instId);
uint32_t singleRegOps = 0;
+ ib.addInstRWFlags(rwInfo.instFlags());
+
if (opCount) {
uint32_t consecutiveOffset = 0xFFFFFFFFu;
uint32_t consecutiveParent = Globals::kInvalidId;
@@ -715,6 +717,50 @@ ASMJIT_FAVOR_SPEED Error ARMRAPass::_rewrite(BaseNode* first, BaseNode* stop) no
}
}
}
+
+ // Rewrite `loadAddressOf()` construct.
+ if (inst->realId() == Inst::kIdAdr && inst->opCount() == 2 && inst->op(1).isMem()) {
+ BaseMem mem = inst->op(1).as<BaseMem>();
+ int64_t offset = mem.offset();
+
+ if (!mem.hasBaseOrIndex()) {
+ inst->setId(Inst::kIdMov);
+ inst->setOp(1, Imm(offset));
+ }
+ else {
+ if (mem.hasIndex())
+ return DebugUtils::errored(kErrorInvalidAddressIndex);
+
+ GpX dst(inst->op(0).as<Gp>().id());
+ GpX base(mem.baseId());
+
+ InstId arithInstId = offset < 0 ? Inst::kIdSub : Inst::kIdAdd;
+ uint64_t absOffset = offset < 0 ? Support::neg(uint64_t(offset)) : uint64_t(offset);
+
+ inst->setId(arithInstId);
+ inst->setOpCount(3);
+ inst->setOp(1, base);
+ inst->setOp(2, Imm(absOffset));
+
+ // Use two operations if the offset cannot be encoded with ADD/SUB.
+ if (absOffset > 0xFFFu && (absOffset & ~uint64_t(0xFFF000u)) != 0) {
+ if (absOffset <= 0xFFFFFFu) {
+ cc()->_setCursor(inst->prev());
+ ASMJIT_PROPAGATE(cc()->emit(arithInstId, dst, base, Imm(absOffset & 0xFFFu)));
+
+ inst->setOp(1, dst);
+ inst->setOp(2, Imm(absOffset & 0xFFF000u));
+ }
+ else {
+ cc()->_setCursor(inst->prev());
+ ASMJIT_PROPAGATE(cc()->emit(Inst::kIdMov, inst->op(0), Imm(absOffset)));
+
+ inst->setOp(1, base);
+ inst->setOp(2, dst);
+ }
+ }
+ }
+ }
}
node = next;