void TR::ARMSystemLinkage::createEpilogue(TR::Instruction *cursor) { TR::CodeGenerator *codeGen = cg(); const TR::ARMLinkageProperties& properties = getProperties(); TR::Machine *machine = codeGen->machine(); TR::Node *lastNode = cursor->getNode(); TR::ResolvedMethodSymbol* bodySymbol = comp()->getJittedMethodSymbol(); TR::RealRegister *stackPtr = machine->getRealRegister(properties.getStackPointerRegister()); // restore link register (r14) auto *stackSlot = new (trHeapMemory()) TR::MemoryReference(stackPtr, bodySymbol->getLocalMappingCursor(), codeGen); cursor = generateMemSrc1Instruction(cg(), ARMOp_ldr, lastNode, stackSlot, machine->getRealRegister(TR::RealRegister::gr14), cursor); // restore all preserved registers for (int r = TR::RealRegister::gr4; r <= TR::RealRegister::gr11; ++r) { auto *stackSlot = new (trHeapMemory()) TR::MemoryReference(stackPtr, (TR::RealRegister::gr11 - r + 1)*4 + bodySymbol->getLocalMappingCursor(), codeGen); cursor = generateMemSrc1Instruction(cg(), ARMOp_ldr, lastNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)r), cursor); } // remove space for preserved registers auto frameSize = codeGen->getFrameSizeInBytes(); cursor = generateTrg1Src1ImmInstruction(codeGen, ARMOp_add, lastNode, stackPtr, stackPtr, frameSize, 0, cursor); // return using `mov r15, r14` TR::RealRegister *gr14 = machine->getRealRegister(TR::RealRegister::gr14); TR::RealRegister *gr15 = machine->getRealRegister(TR::RealRegister::gr15); cursor = generateTrg1Src1Instruction(codeGen, ARMOp_mov, lastNode, gr15, gr14, cursor); }
void TR::ARM64SystemLinkage::createEpilogue(TR::Instruction *cursor) { TR::CodeGenerator *codeGen = cg(); const TR::ARM64LinkageProperties& properties = getProperties(); TR::Machine *machine = codeGen->machine(); TR::Node *lastNode = cursor->getNode(); TR::ResolvedMethodSymbol *bodySymbol = comp()->getJittedMethodSymbol(); TR::RealRegister *sp = machine->getRealRegister(properties.getStackPointerRegister()); // restore callee-saved registers uint32_t offset = bodySymbol->getLocalMappingCursor(); for (int r = TR::RealRegister::x19; r <= TR::RealRegister::x28; r++) { TR::RealRegister *rr = machine->getRealRegister((TR::RealRegister::RegNum)r); if (rr->getHasBeenAssignedInMethod()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, offset, codeGen); cursor = generateTrg1MemInstruction(cg(), TR::InstOpCode::ldrimmx, lastNode, rr, stackSlot, cursor); offset += 8; } } for (int r = TR::RealRegister::v8; r <= TR::RealRegister::v15; r++) { TR::RealRegister *rr = machine->getRealRegister((TR::RealRegister::RegNum)r); if (rr->getHasBeenAssignedInMethod()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, offset, codeGen); cursor = generateTrg1MemInstruction(cg(), TR::InstOpCode::vldrimmd, lastNode, rr, stackSlot, cursor); offset += 8; } } // restore link register (x30) TR::RealRegister *lr = machine->getRealRegister(TR::RealRegister::lr); if (machine->getLinkRegisterKilled()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, 0, codeGen); cursor = generateTrg1MemInstruction(cg(), TR::InstOpCode::ldrimmx, lastNode, lr, stackSlot, cursor); } // remove space for preserved registers uint32_t frameSize = codeGen->getFrameSizeInBytes(); if (constantIsUnsignedImm12(frameSize)) { cursor = generateTrg1Src1ImmInstruction(codeGen, TR::InstOpCode::addimmx, lastNode, sp, sp, frameSize, cursor); } else { TR_UNIMPLEMENTED(); } // return cursor = generateRegBranchInstruction(codeGen, TR::InstOpCode::ret, lastNode, lr, cursor); }
TR::Instruction * TR_X86SystemLinkage::savePreservedRegisters(TR::Instruction *cursor) { // For IA32, if disableShrinkWrapping, usePushForPreservedRegs will be true; otherwise false; // For X64, shrinkWraping is always on, and usePushForPreservedRegs always false; // TR_ASSERT(!getProperties().getUsesPushesForPreservedRegs(), "assertion failure"); TR::ResolvedMethodSymbol *bodySymbol = comp()->getJittedMethodSymbol(); const int32_t localSize = getProperties().getOffsetToFirstLocal() - bodySymbol->getLocalMappingCursor(); const int32_t pointerSize = getProperties().getPointerSize(); int32_t offsetCursor = -localSize + getProperties().getOffsetToFirstLocal() - pointerSize; if (_properties.getUsesPushesForPreservedRegs()) { for (int32_t pindex = _properties.getMaxRegistersPreservedInPrologue()-1; pindex >= 0; pindex--) { TR::RealRegister::RegNum idx = _properties.getPreservedRegister((uint32_t)pindex); TR::RealRegister *reg = machine()->getX86RealRegister(idx); if (reg->getHasBeenAssignedInMethod() && reg->getState() != TR::RealRegister::Locked) { cursor = new (trHeapMemory()) TR::X86RegInstruction(cursor, PUSHReg, reg, cg()); } } } else { TR_BitVector *p = cg()->getPreservedRegsInPrologue(); for (int32_t pindex = getProperties().getMaxRegistersPreservedInPrologue()-1; pindex >= 0; pindex--) { TR::RealRegister::RegNum idx = _properties.getPreservedRegister((uint32_t)pindex); TR::RealRegister *reg = machine()->getX86RealRegister(getProperties().getPreservedRegister((uint32_t)pindex)); if(reg->getHasBeenAssignedInMethod() && reg->getState() != TR::RealRegister::Locked) { if (!p || p->get(idx)) { cursor = generateMemRegInstruction( cursor, movOpcodes[MemReg][fullRegisterMovType(reg)], generateX86MemoryReference(machine()->getX86RealRegister(TR::RealRegister::vfp), offsetCursor, cg()), reg, cg() ); } offsetCursor -= pointerSize; } } } return cursor; }
TR::Instruction * TR::X86SystemLinkage::savePreservedRegisters(TR::Instruction *cursor) { // For IA32 usePushForPreservedRegs will be true; // For X64, usePushForPreservedRegs always false; TR::ResolvedMethodSymbol *bodySymbol = comp()->getJittedMethodSymbol(); const int32_t localSize = getProperties().getOffsetToFirstLocal() - bodySymbol->getLocalMappingCursor(); const int32_t pointerSize = getProperties().getPointerSize(); int32_t offsetCursor = -localSize + getProperties().getOffsetToFirstLocal() - pointerSize; if (_properties.getUsesPushesForPreservedRegs()) { for (int32_t pindex = _properties.getMaxRegistersPreservedInPrologue()-1; pindex >= 0; pindex--) { TR::RealRegister::RegNum idx = _properties.getPreservedRegister((uint32_t)pindex); TR::RealRegister *reg = machine()->getX86RealRegister(idx); if (reg->getHasBeenAssignedInMethod() && reg->getState() != TR::RealRegister::Locked) { cursor = new (trHeapMemory()) TR::X86RegInstruction(cursor, PUSHReg, reg, cg()); } } } else { for (int32_t pindex = getProperties().getMaxRegistersPreservedInPrologue()-1; pindex >= 0; pindex--) { TR::RealRegister::RegNum idx = _properties.getPreservedRegister((uint32_t)pindex); TR::RealRegister *reg = machine()->getX86RealRegister(getProperties().getPreservedRegister((uint32_t)pindex)); if(reg->getHasBeenAssignedInMethod() && reg->getState() != TR::RealRegister::Locked) { cursor = generateMemRegInstruction( cursor, TR::Linkage::movOpcodes(MemReg, fullRegisterMovType(reg)), generateX86MemoryReference(machine()->getX86RealRegister(TR::RealRegister::vfp), offsetCursor, cg()), reg, cg() ); offsetCursor -= pointerSize; } } } return cursor; }
TR::MemoryReference *TR::ARMSystemLinkage::getOutgoingArgumentMemRef(int32_t totalSize, int32_t offset, TR::Register *argReg, TR_ARMOpCodes opCode, TR::ARMMemoryArgument &memArg) { int32_t spOffset = offset - (getProperties().getNumIntArgRegs() * TR::Compiler->om.sizeofReferenceAddress()); TR::RealRegister *sp = cg()->machine()->getRealRegister(properties.getStackPointerRegister()); TR::MemoryReference *result = new (trHeapMemory()) TR::MemoryReference(sp, spOffset, cg()); memArg.argRegister = argReg; memArg.argMemory = result; memArg.opCode = opCode; return result; }
TR::Register *TR::ARM64SystemLinkage::buildDirectDispatch(TR::Node *callNode) { TR::SymbolReference *callSymRef = callNode->getSymbolReference(); const TR::ARM64LinkageProperties &pp = getProperties(); TR::RealRegister *sp = cg()->machine()->getRealRegister(pp.getStackPointerRegister()); TR::RegisterDependencyConditions *dependencies = new (trHeapMemory()) TR::RegisterDependencyConditions( pp.getNumberOfDependencyGPRegisters(), pp.getNumberOfDependencyGPRegisters(), trMemory()); int32_t totalSize = buildArgs(callNode, dependencies); if (totalSize > 0) { if (constantIsUnsignedImm12(totalSize)) { generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::subimmx, callNode, sp, sp, totalSize); } else { TR_ASSERT_FATAL(false, "Too many arguments."); } } TR::MethodSymbol *callSymbol = callSymRef->getSymbol()->castToMethodSymbol(); generateImmSymInstruction(cg(), TR::InstOpCode::bl, callNode, (uintptr_t)callSymbol->getMethodAddress(), dependencies, callSymRef ? callSymRef : callNode->getSymbolReference(), NULL); cg()->machine()->setLinkRegisterKilled(true); if (totalSize > 0) { if (constantIsUnsignedImm12(totalSize)) { generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::addimmx, callNode, sp, sp, totalSize); } else { TR_ASSERT_FATAL(false, "Too many arguments."); } } TR::Register *retReg; switch(callNode->getOpCodeValue()) { case TR::icall: case TR::iucall: retReg = dependencies->searchPostConditionRegister( pp.getIntegerReturnRegister()); break; case TR::lcall: case TR::lucall: case TR::acall: retReg = dependencies->searchPostConditionRegister( pp.getLongReturnRegister()); break; case TR::fcall: case TR::dcall: retReg = dependencies->searchPostConditionRegister( pp.getFloatReturnRegister()); break; case TR::call: retReg = NULL; break; default: retReg = NULL; TR_ASSERT(false, "Unsupported direct call Opcode."); } callNode->setRegister(retReg); return retReg; }
void TR::ARM64SystemLinkage::createPrologue(TR::Instruction *cursor, List<TR::ParameterSymbol> &parmList) { TR::CodeGenerator *codeGen = cg(); TR::Machine *machine = codeGen->machine(); TR::ResolvedMethodSymbol *bodySymbol = comp()->getJittedMethodSymbol(); const TR::ARM64LinkageProperties& properties = getProperties(); TR::RealRegister *sp = machine->getRealRegister(properties.getStackPointerRegister()); TR::Node *firstNode = comp()->getStartTree()->getNode(); // allocate stack space uint32_t frameSize = (uint32_t)codeGen->getFrameSizeInBytes(); if (constantIsUnsignedImm12(frameSize)) { cursor = generateTrg1Src1ImmInstruction(codeGen, TR::InstOpCode::subimmx, firstNode, sp, sp, frameSize, cursor); } else { TR_UNIMPLEMENTED(); } // save link register (x30) if (machine->getLinkRegisterKilled()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, 0, codeGen); cursor = generateMemSrc1Instruction(cg(), TR::InstOpCode::strimmx, firstNode, stackSlot, machine->getRealRegister(TR::RealRegister::x30), cursor); } // spill argument registers int32_t nextIntArgReg = 0; int32_t nextFltArgReg = 0; ListIterator<TR::ParameterSymbol> parameterIterator(&parmList); for (TR::ParameterSymbol *parameter = parameterIterator.getFirst(); parameter != NULL && (nextIntArgReg < getProperties().getNumIntArgRegs() || nextFltArgReg < getProperties().getNumFloatArgRegs()); parameter = parameterIterator.getNext()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, parameter->getParameterOffset(), codeGen); TR::InstOpCode::Mnemonic op; switch (parameter->getDataType()) { case TR::Int8: case TR::Int16: case TR::Int32: case TR::Int64: case TR::Address: if (nextIntArgReg < getProperties().getNumIntArgRegs()) { op = (parameter->getSize() == 8) ? TR::InstOpCode::strimmx : TR::InstOpCode::strimmw; cursor = generateMemSrc1Instruction(cg(), op, firstNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)(TR::RealRegister::x0 + nextIntArgReg)), cursor); nextIntArgReg++; } else { nextIntArgReg = getProperties().getNumIntArgRegs() + 1; } break; case TR::Float: case TR::Double: if (nextFltArgReg < getProperties().getNumFloatArgRegs()) { op = (parameter->getSize() == 8) ? TR::InstOpCode::vstrimmd : TR::InstOpCode::vstrimms; cursor = generateMemSrc1Instruction(cg(), op, firstNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)(TR::RealRegister::v0 + nextFltArgReg)), cursor); nextFltArgReg++; } else { nextFltArgReg = getProperties().getNumFloatArgRegs() + 1; } break; case TR::Aggregate: TR_ASSERT(false, "Function parameters of aggregate types are not currently supported on AArch64."); break; default: TR_ASSERT(false, "Unknown parameter type."); } } // save callee-saved registers uint32_t offset = bodySymbol->getLocalMappingCursor(); for (int r = TR::RealRegister::x19; r <= TR::RealRegister::x28; r++) { TR::RealRegister *rr = machine->getRealRegister((TR::RealRegister::RegNum)r); if (rr->getHasBeenAssignedInMethod()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, offset, codeGen); cursor = generateMemSrc1Instruction(cg(), TR::InstOpCode::strimmx, firstNode, stackSlot, rr, cursor); offset += 8; } } for (int r = TR::RealRegister::v8; r <= TR::RealRegister::v15; r++) { TR::RealRegister *rr = machine->getRealRegister((TR::RealRegister::RegNum)r); if (rr->getHasBeenAssignedInMethod()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, offset, codeGen); cursor = generateMemSrc1Instruction(cg(), TR::InstOpCode::vstrimmd, firstNode, stackSlot, rr, cursor); offset += 8; } } }
void TR::ARMSystemLinkage::createPrologue(TR::Instruction *cursor) { TR::CodeGenerator *codeGen = cg(); const TR::ARMLinkageProperties& properties = getProperties(); TR::Machine *machine = codeGen->machine(); TR::ResolvedMethodSymbol* bodySymbol = comp()->getJittedMethodSymbol(); TR::Node *firstNode = comp()->getStartTree()->getNode(); TR::RealRegister *stackPtr = machine->getRealRegister(properties.getStackPointerRegister()); // Entry breakpoint // if (comp()->getOption(TR_EntryBreakPoints)) { cursor = new (trHeapMemory()) TR::Instruction(cursor, ARMOp_bad, firstNode, cg()); } // allocate stack space auto frameSize = codeGen->getFrameSizeInBytes(); cursor = generateTrg1Src1ImmInstruction(codeGen, ARMOp_sub, firstNode, stackPtr, stackPtr, frameSize, 0, cursor); // spill argument registers auto nextIntArgReg = 0; auto nextFltArgReg = 0; ListIterator<TR::ParameterSymbol> parameterIterator(&bodySymbol->getParameterList()); for (TR::ParameterSymbol *parameter = parameterIterator.getFirst(); parameter!=NULL && (nextIntArgReg < getProperties().getNumIntArgRegs() || nextFltArgReg < getProperties().getNumFloatArgRegs()); parameter=parameterIterator.getNext()) { auto *stackSlot = new (trHeapMemory()) TR::MemoryReference(stackPtr, parameter->getParameterOffset(), codeGen); switch (parameter->getDataType()) { case TR::Int8: case TR::Int16: case TR::Int32: case TR::Address: if (nextIntArgReg < getProperties().getNumIntArgRegs()) { cursor = generateMemSrc1Instruction(cg(), ARMOp_str, firstNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)(TR::RealRegister::gr0 + nextIntArgReg)), cursor); nextIntArgReg++; } else { nextIntArgReg = getProperties().getNumIntArgRegs() + 1; } break; case TR::Int64: nextIntArgReg += nextIntArgReg & 0x1; // round to next even number if (nextIntArgReg + 1 < getProperties().getNumIntArgRegs()) { cursor = generateMemSrc1Instruction(cg(), ARMOp_str, firstNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)(TR::RealRegister::gr0 + nextIntArgReg)), cursor); stackSlot = new (trHeapMemory()) TR::MemoryReference(stackPtr, parameter->getParameterOffset() + 4, codeGen); cursor = generateMemSrc1Instruction(cg(), ARMOp_str, firstNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)(TR::RealRegister::gr0 + nextIntArgReg + 1)), cursor); nextIntArgReg += 2; } else { nextIntArgReg = getProperties().getNumIntArgRegs() + 1; } break; case TR::Float: comp()->failCompilation<UnsupportedParameterType>("Compiling methods with a single precision floating point parameter is not supported"); break; case TR::Double: if (nextFltArgReg < getProperties().getNumFloatArgRegs()) { cursor = generateMemSrc1Instruction(cg(), ARMOp_fstd, firstNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)(TR::RealRegister::fp0 + nextFltArgReg)), cursor); nextFltArgReg += 1; } else { nextFltArgReg = getProperties().getNumFloatArgRegs() + 1; } break; case TR::Aggregate: TR_ASSERT(false, "Function parameters of aggregate types are not currently supported on ARM."); } } // save all preserved registers for (int r = TR::RealRegister::gr4; r <= TR::RealRegister::gr11; ++r) { auto *stackSlot = new (trHeapMemory()) TR::MemoryReference(stackPtr, (TR::RealRegister::gr11 - r + 1)*4 + bodySymbol->getLocalMappingCursor(), codeGen); cursor = generateMemSrc1Instruction(cg(), ARMOp_str, firstNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)r), cursor); } // save link register (r14) auto *stackSlot = new (trHeapMemory()) TR::MemoryReference(stackPtr, bodySymbol->getLocalMappingCursor(), codeGen); cursor = generateMemSrc1Instruction(cg(), ARMOp_str, firstNode, stackSlot, machine->getRealRegister(TR::RealRegister::gr14), cursor); }