Path: blob/master/runtime/compiler/aarch64/codegen/J9MemoryReference.cpp
6004 views
/*******************************************************************************1* Copyright (c) 2019, 2020 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/2122#include "codegen/ARM64Instruction.hpp"23#include "codegen/CodeGenerator.hpp"24#include "codegen/MemoryReference.hpp"25#include "codegen/Machine.hpp"26#include "codegen/Relocation.hpp"27#include "codegen/UnresolvedDataSnippet.hpp"2829J9::ARM64::MemoryReference::MemoryReference(30TR::Node *node,31TR::CodeGenerator *cg)32: OMR::MemoryReferenceConnector(node, cg), _j9Flags(0)33{34self()->setupCausesImplicitNullPointerException(cg);35if (self()->getUnresolvedSnippet())36self()->adjustForResolution(cg);37}3839J9::ARM64::MemoryReference::MemoryReference(40TR::Node *node,41TR::SymbolReference *symRef,42TR::CodeGenerator *cg)43: OMR::MemoryReferenceConnector(node, symRef, cg), _j9Flags(0)44{45self()->setupCausesImplicitNullPointerException(cg);46if (self()->getUnresolvedSnippet())47self()->adjustForResolution(cg);48}4950void J9::ARM64::MemoryReference::setupCausesImplicitNullPointerException(TR::CodeGenerator *cg)51{52auto topNode = cg->getCurrentEvaluationTreeTop()->getNode();53if (cg->getHasResumableTrapHandler() &&54(topNode->getOpCode().isNullCheck() || topNode->chkFoldedImplicitNULLCHK()))55{56self()->setCausesImplicitNullPointerException();57}58}5960void61J9::ARM64::MemoryReference::adjustForResolution(TR::CodeGenerator *cg)62{63self()->setExtraRegister(cg->allocateRegister());64}6566void67J9::ARM64::MemoryReference::assignRegisters(TR::Instruction *currentInstruction, TR::CodeGenerator *cg)68{69TR::Machine *machine = cg->machine();70TR::Register *baseRegister = self()->getBaseRegister();71TR::Register *indexRegister = self()->getIndexRegister();72TR::Register *extraRegister = self()->getExtraRegister();73TR::RealRegister *assignedBaseRegister;74TR::RealRegister *assignedIndexRegister;75TR::RealRegister *assignedExtraRegister;7677if (baseRegister != NULL)78{79assignedBaseRegister = baseRegister->getAssignedRealRegister();80if (indexRegister != NULL)81{82indexRegister->block();83}84if (extraRegister != NULL)85{86extraRegister->block();87}8889if (assignedBaseRegister == NULL)90{91if (baseRegister->getTotalUseCount() == baseRegister->getFutureUseCount())92{93if ((assignedBaseRegister = machine->findBestFreeRegister(currentInstruction, TR_GPR, true, baseRegister)) == NULL)94{95assignedBaseRegister = machine->freeBestRegister(currentInstruction, baseRegister);96}97}98else99{100assignedBaseRegister = machine->reverseSpillState(currentInstruction, baseRegister);101}102baseRegister->setAssignedRegister(assignedBaseRegister);103assignedBaseRegister->setAssignedRegister(baseRegister);104assignedBaseRegister->setState(TR::RealRegister::Assigned);105}106107if (indexRegister != NULL)108{109indexRegister->unblock();110}111if (extraRegister != NULL)112{113extraRegister->unblock();114}115}116117if (indexRegister != NULL)118{119if (baseRegister != NULL)120{121baseRegister->block();122}123if (extraRegister != NULL)124{125extraRegister->block();126}127128assignedIndexRegister = indexRegister->getAssignedRealRegister();129if (assignedIndexRegister == NULL)130{131if (indexRegister->getTotalUseCount() == indexRegister->getFutureUseCount())132{133if ((assignedIndexRegister = machine->findBestFreeRegister(currentInstruction, TR_GPR, false, indexRegister)) == NULL)134{135assignedIndexRegister = machine->freeBestRegister(currentInstruction, indexRegister);136}137}138else139{140assignedIndexRegister = machine->reverseSpillState(currentInstruction, indexRegister);141}142indexRegister->setAssignedRegister(assignedIndexRegister);143assignedIndexRegister->setAssignedRegister(indexRegister);144assignedIndexRegister->setState(TR::RealRegister::Assigned);145}146147if (baseRegister != NULL)148{149baseRegister->unblock();150}151if (extraRegister != NULL)152{153extraRegister->unblock();154}155}156157if (extraRegister != NULL)158{159if (baseRegister != NULL)160{161baseRegister->block();162}163if (indexRegister != NULL)164{165indexRegister->block();166}167168assignedExtraRegister = extraRegister->getAssignedRealRegister();169if (assignedExtraRegister == NULL)170{171if (extraRegister->getTotalUseCount() == extraRegister->getFutureUseCount())172{173if ((assignedExtraRegister = machine->findBestFreeRegister(currentInstruction, TR_GPR, false, extraRegister)) == NULL)174{175assignedExtraRegister = machine->freeBestRegister(currentInstruction, extraRegister);176}177}178else179{180assignedExtraRegister = machine->reverseSpillState(currentInstruction, extraRegister);181}182extraRegister->setAssignedRegister(assignedExtraRegister);183assignedExtraRegister->setAssignedRegister(extraRegister);184assignedExtraRegister->setState(TR::RealRegister::Assigned);185}186187if (baseRegister != NULL)188{189baseRegister->unblock();190}191if (indexRegister != NULL)192{193indexRegister->unblock();194}195}196197if (baseRegister != NULL)198{199machine->decFutureUseCountAndUnlatch(currentInstruction, baseRegister);200self()->setBaseRegister(assignedBaseRegister);201}202203if (indexRegister != NULL)204{205machine->decFutureUseCountAndUnlatch(currentInstruction, indexRegister);206self()->setIndexRegister(assignedIndexRegister);207}208209if (extraRegister != NULL)210{211machine->decFutureUseCountAndUnlatch(currentInstruction, extraRegister);212TR_ASSERT(extraRegister->getFutureUseCount() == 0, "Unexpected future use count for extraReg");213self()->setExtraRegister(assignedExtraRegister);214}215216if (self()->getUnresolvedSnippet() != NULL)217{218currentInstruction->ARM64NeedsGCMap(cg, 0xFFFFFFFF);219}220}221222uint8_t *223J9::ARM64::MemoryReference::generateBinaryEncoding(TR::Instruction *currentInstruction, uint8_t *cursor, TR::CodeGenerator *cg)224{225TR::UnresolvedDataSnippet *snippet = self()->getUnresolvedSnippet();226227if (snippet)228{229if (self()->getIndexRegister())230{231TR_ASSERT(false, "Unresolved indexed snippet is not supported");232return NULL;233}234else235{236uint32_t *wcursor = (uint32_t *)cursor;237uint32_t preserve = *wcursor; // original instruction238snippet->setAddressOfDataReference(cursor);239snippet->setMemoryReference(self());240cg->addRelocation(new (cg->trHeapMemory()) TR::LabelRelative32BitRelocation(cursor, snippet->getSnippetLabel()));241*wcursor = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::b); // b snippetLabel242wcursor++;243cursor += ARM64_INSTRUCTION_LENGTH;244245TR_ASSERT(self()->getExtraRegister(), "extraReg must have been allocated");246TR::RealRegister *extraReg = toRealRegister(self()->getExtraRegister());247248// insert instructions for computing the address of the resolved field;249// the actual immediate operands are patched in by L_mergedDataResolve250// in PicBuilder.spp251252// movk extraReg, #0, LSL #16253*wcursor = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::movkx) | (TR::MOV_LSL16 << 5);254extraReg->setRegisterFieldRD(wcursor);255wcursor++;256cursor += ARM64_INSTRUCTION_LENGTH;257258// movk extraReg, #0, LSL #32259*wcursor = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::movkx) | (TR::MOV_LSL32 << 5);260extraReg->setRegisterFieldRD(wcursor);261wcursor++;262cursor += ARM64_INSTRUCTION_LENGTH;263264// movk extraReg, #0, LSL #48265*wcursor = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::movkx) | (TR::MOV_LSL48 << 5);266extraReg->setRegisterFieldRD(wcursor);267wcursor++;268cursor += ARM64_INSTRUCTION_LENGTH;269270// finally, encode the original instruction271*wcursor = preserve;272TR::RealRegister *base = self()->getBaseRegister() ? toRealRegister(self()->getBaseRegister()) : NULL;273TR::InstOpCode::Mnemonic op = currentInstruction->getOpCodeValue();274if (op != TR::InstOpCode::addx)275{276// load/store instruction277if (op == TR::InstOpCode::ldrimmx || op == TR::InstOpCode::strimmx278|| op == TR::InstOpCode::ldrimmw || op == TR::InstOpCode::strimmw279|| op == TR::InstOpCode::ldrhimm || op == TR::InstOpCode::strhimm280|| op == TR::InstOpCode::ldrshimmx || op == TR::InstOpCode::ldrshimmw281|| op == TR::InstOpCode::ldrbimm || op == TR::InstOpCode::strbimm282|| op == TR::InstOpCode::ldrsbimmx || op == TR::InstOpCode::ldrsbimmw283|| op == TR::InstOpCode::vldrimmd || op == TR::InstOpCode::vstrimmd284|| op == TR::InstOpCode::vldrimms || op == TR::InstOpCode::vstrimms)285{286if (base)287{288// if the load or store had a base, add it in as an index.289base->setRegisterFieldRN(wcursor);290extraReg->setRegisterFieldRM(wcursor);291// Rewrite the instruction from "ldr Rt, [Rn, #imm]" to "ldr Rt, [Rn, Rm]"292cursor[1] |= 0x68; // Set bits 11, 13, 14293cursor[2] |= 0x20; // Set bit 21294cursor[3] &= 0xFE; // Clear bit 24295}296else297{298// ldr Rt, [Rn]299extraReg->setRegisterFieldRN(wcursor);300}301}302else303{304TR_ASSERT_FATAL(false, "Unsupported load/store instruction for unresolved data snippet");305}306}307else308{309// loadaddrEvaluator() uses addx in generateTrgMemInstruction310if (base)311{312// addx Rt, Rn, Rm313base->setRegisterFieldRN(wcursor);314extraReg->setRegisterFieldRM(wcursor);315}316else317{318extraReg->setRegisterFieldRN(wcursor);319// Rewrite the instruction from "addx Rd, Rn, Rm" to "addimmx Rd, Rn, #0"320cursor[3] = (uint8_t)0x91;321}322}323cursor += ARM64_INSTRUCTION_LENGTH;324325return cursor;326}327}328else329{330return OMR::MemoryReferenceConnector::generateBinaryEncoding(currentInstruction, cursor, cg);331}332}333334uint32_t335J9::ARM64::MemoryReference::estimateBinaryLength(TR::InstOpCode op)336{337if (self()->getUnresolvedSnippet())338{339if (self()->getIndexRegister())340{341TR_ASSERT(false, "Unresolved indexed snippet is not supported");342return 0;343}344else345{346return 5 * ARM64_INSTRUCTION_LENGTH;347}348}349else350{351return OMR::MemoryReferenceConnector::estimateBinaryLength(op);352}353}354355356