void TR::AMD64ABILinkage::mapIncomingParms( TR::ResolvedMethodSymbol *method, uint32_t &stackIndex) { ListIterator<TR::ParameterSymbol> parameterIterator(&method->getParameterList()); TR::ParameterSymbol *parmCursor = parameterIterator.getFirst(); if (!parmCursor) return; if (parmCursor->getLinkageRegisterIndex() < 0) { copyLinkageInfoToParameterSymbols(); } // 1st: handle parameters which are passed through stack // TR::X86SystemLinkage::mapIncomingParms(method); // 2nd: handle parameters which are passed through linkage registers, but are // not assigned any register after RA (or say, by their first usage point, // a MOV is needed to load it from stack to register). // // AMD64 SysV ABI says that: a parameter is placed either in registers or // pushed on the stack, but can't take both. So, for parms passed through // linkage registers but don't have physical registers assigned after RA, // we will allocate stack space in local variable region. // for (parmCursor = parameterIterator.getFirst(); parmCursor; parmCursor = parameterIterator.getNext()) { if ((parmCursor->getLinkageRegisterIndex() >= 0) && (parmCursor->getAllocatedIndex() < 0 || hasToBeOnStack(parmCursor))) { uint32_t align = getAlignment(parmCursor->getDataType()); uint32_t alignMinus1 = (align <= AMD64_STACK_SLOT_SIZE) ? (AMD64_STACK_SLOT_SIZE - 1) : (align - 1); uint32_t pos = -stackIndex; pos += parmCursor->getSize(); pos = (pos + alignMinus1) & (~alignMinus1); stackIndex = -pos; parmCursor->setParameterOffset(stackIndex); if (comp()->getOption(TR_TraceCG)) traceMsg(comp(), "mapIncomingParms setParameterOffset %d for param symbol (reg param without home location) %p, hasToBeOnStack() %d\n", parmCursor->getParameterOffset(), parmCursor, hasToBeOnStack(parmCursor)); } else if (parmCursor->getLinkageRegisterIndex() >=0 && parmCursor->getAllocatedIndex() >= 0) { //parmCursor->setDontHaveStackSlot(0); // this is a hack , so as we could print stack layout table in createPrologue if (comp()->getOption(TR_TraceCG)) traceMsg(comp(), "mapIncomingParms no need to set parm %p, for it has got register %d assigned\n", parmCursor, parmCursor->getAllocatedIndex()); } } }
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::ARM64SystemLinkage::mapStack(TR::ResolvedMethodSymbol *method) { TR::Machine *machine = cg()->machine(); uint32_t stackIndex = 0; ListIterator<TR::AutomaticSymbol> automaticIterator(&method->getAutomaticList()); TR::AutomaticSymbol *localCursor = automaticIterator.getFirst(); stackIndex = 8; // [sp+0] is for link register // map non-long/double automatics while (localCursor != NULL) { if (localCursor->getGCMapIndex() < 0 && localCursor->getDataType() != TR::Int64 && localCursor->getDataType() != TR::Double) { localCursor->setOffset(stackIndex); stackIndex += (localCursor->getSize() + 3) & (~3); } localCursor = automaticIterator.getNext(); } stackIndex += (stackIndex & 0x4) ? 4 : 0; // align to 8 bytes automaticIterator.reset(); localCursor = automaticIterator.getFirst(); // map long/double automatics while (localCursor != NULL) { if (localCursor->getDataType() == TR::Int64 || localCursor->getDataType() == TR::Double) { localCursor->setOffset(stackIndex); stackIndex += (localCursor->getSize() + 7) & (~7); } localCursor = automaticIterator.getNext(); } method->setLocalMappingCursor(stackIndex); // allocate space for preserved registers (x19-x28, v8-v15) for (int r = TR::RealRegister::x19; r <= TR::RealRegister::x28; r++) { TR::RealRegister *rr = machine->getRealRegister((TR::RealRegister::RegNum)r); if (rr->getHasBeenAssignedInMethod()) { stackIndex += 8; } } for (int r = TR::RealRegister::v8; r <= TR::RealRegister::v15; r++) { TR::RealRegister *rr = machine->getRealRegister((TR::RealRegister::RegNum)r); if (rr->getHasBeenAssignedInMethod()) { stackIndex += 8; } } /* * Because the rest of the code generator currently expects **all** arguments * to be passed on the stack, arguments passed in registers must be spilled * in the callee frame. To map the arguments correctly, we use two loops. The * first maps the arguments that will come in registers onto the callee stack. * At the end of this loop, the `stackIndex` is the the size of the frame. * The second loop then maps the remaining arguments onto the caller frame. */ int32_t nextIntArgReg = 0; int32_t nextFltArgReg = 0; ListIterator<TR::ParameterSymbol> parameterIterator(&method->getParameterList()); for (TR::ParameterSymbol *parameter = parameterIterator.getFirst(); parameter != NULL && (nextIntArgReg < getProperties().getNumIntArgRegs() || nextFltArgReg < getProperties().getNumFloatArgRegs()); parameter = parameterIterator.getNext()) { switch (parameter->getDataType()) { case TR::Int8: case TR::Int16: case TR::Int32: case TR::Int64: case TR::Address: if (nextIntArgReg < getProperties().getNumIntArgRegs()) { nextIntArgReg++; mapSingleParameter(parameter, stackIndex, true); } else { nextIntArgReg = getProperties().getNumIntArgRegs() + 1; } break; case TR::Float: case TR::Double: if (nextFltArgReg < getProperties().getNumFloatArgRegs()) { nextFltArgReg++; mapSingleParameter(parameter, stackIndex, true); } 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 the stack frame size, aligned to 16 bytes stackIndex = (stackIndex + 15) & (~15); cg()->setFrameSizeInBytes(stackIndex); nextIntArgReg = 0; nextFltArgReg = 0; parameterIterator.reset(); for (TR::ParameterSymbol *parameter = parameterIterator.getFirst(); parameter != NULL && (nextIntArgReg < getProperties().getNumIntArgRegs() || nextFltArgReg < getProperties().getNumFloatArgRegs()); parameter = parameterIterator.getNext()) { switch (parameter->getDataType()) { case TR::Int8: case TR::Int16: case TR::Int32: case TR::Int64: case TR::Address: if (nextIntArgReg < getProperties().getNumIntArgRegs()) { nextIntArgReg++; } else { mapSingleParameter(parameter, stackIndex, false); } break; case TR::Float: case TR::Double: if (nextFltArgReg < getProperties().getNumFloatArgRegs()) { nextFltArgReg++; } else { mapSingleParameter(parameter, stackIndex, false); } 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."); } } }
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); }
/** * @brief Maps symbols in the IL to locations on the stack * @param method is the method for which symbols are being stack mapped * * In general, the shape of a stack frame is as follows: * * +-----------------------------+ * | caller frame | * +-----------------------------+ * | stack arguments | * +=============================+ <-+ (start of callee frame) * | saved registers | | * +-----------------------------+ | frame size * | locals | | * +-----------------------------+ <-+- $sp * * A symbol is mapped onto the stack by assigning to it an offset from the stack * pointer. All symbols representing stack allocated values must be mapped, * including automatics (locals) on the callee frame and stack allocated * arguments on the caller frame * * The algorithm used to map symbols iterates over each symbol in ascending * address order. Using the frame shape depicted above as a general example: * locals are mapped first, registers second. The algorithm is: * * 1. Set stackIndex to 0 * 2. For each symbol that must be mapped onto the **callee** stack frame, * starting at the lowest address: * a. set stackIndex as the symbol offset * b. increment stackIndex by the size of the symbol's type * plus alignment requirements * 3. Increment stackIndex by the necessary amount to account for the stack * space required for saved registers * 4. Save stackIndex as the size of the callee stack frame * 5. For each symbol that must be mapped onto the **caller** stack frame, * starting at the lowest address: * a. set the symbol offset as the current stack index * b. increment the stack index by the size of the symbol's type, * plus alignment requirements */ void TR::ARMSystemLinkage::mapStack(TR::ResolvedMethodSymbol *method) { uint32_t stackIndex = 0; ListIterator<TR::AutomaticSymbol> automaticIterator(&method->getAutomaticList()); TR::AutomaticSymbol *localCursor = automaticIterator.getFirst(); // map non-double automatics while (localCursor != NULL) { if (localCursor->getGCMapIndex() < 0 && localCursor->getDataType() != TR::Double) { localCursor->setOffset(stackIndex); stackIndex += (localCursor->getSize()+3)&(~3); } localCursor = automaticIterator.getNext(); } stackIndex += (stackIndex & 0x4) ? 4 : 0; // align to 8 bytes automaticIterator.reset(); localCursor = automaticIterator.getFirst(); // map double automatics while (localCursor != NULL) { if (localCursor->getDataType() == TR::Double) { localCursor->setOffset(stackIndex); stackIndex += (localCursor->getSize()+7)&(~7); } localCursor = automaticIterator.getNext(); } method->setLocalMappingCursor(stackIndex); // allocate space for preserved registers and link register (9 registers total) stackIndex += 9*4; /* * Because the rest of the code generator currently expects **all** arguments * to be passed on the stack, arguments passed in registers must be spilled * in the callee frame. To map the arguments correctly, we use two loops. The * first maps the arguments that will come in registers onto the callee stack. * At the end of this loop, the `stackIndex` is the the size of the frame. * The second loop then maps the remaining arguments onto the caller frame. */ auto nextIntArgReg = 0; auto nextFltArgReg = 0; ListIterator<TR::ParameterSymbol> parameterIterator(&method->getParameterList()); for (TR::ParameterSymbol *parameter = parameterIterator.getFirst(); parameter!=NULL && (nextIntArgReg < getProperties().getNumIntArgRegs() || nextFltArgReg < getProperties().getNumFloatArgRegs()); parameter=parameterIterator.getNext()) { switch (parameter->getDataType()) { case TR::Int8: case TR::Int16: case TR::Int32: case TR::Address: if (nextIntArgReg < getProperties().getNumIntArgRegs()) { nextIntArgReg++; mapSingleParameter(parameter, stackIndex); } else { nextIntArgReg = getProperties().getNumIntArgRegs() + 1; } break; case TR::Int64: nextIntArgReg += nextIntArgReg & 0x1; // round to next even number if (nextIntArgReg + 1 < getProperties().getNumIntArgRegs()) { nextIntArgReg += 2; mapSingleParameter(parameter, stackIndex); } 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()) { nextFltArgReg += 1; mapSingleParameter(parameter, stackIndex); } else { nextFltArgReg = getProperties().getNumFloatArgRegs() + 1; } break; case TR::Aggregate: TR_ASSERT(false, "Function parameters of aggregate types are not currently supported on ARM."); } } // save the stack frame size, aligned to 8 bytes stackIndex = (stackIndex + 7)&(~7); cg()->setFrameSizeInBytes(stackIndex); nextIntArgReg = 0; nextFltArgReg = 0; parameterIterator.reset(); for (TR::ParameterSymbol *parameter = parameterIterator.getFirst(); parameter!=NULL && (nextIntArgReg < getProperties().getNumIntArgRegs() || nextFltArgReg < getProperties().getNumFloatArgRegs()); parameter=parameterIterator.getNext()) { switch (parameter->getDataType()) { case TR::Int8: case TR::Int16: case TR::Int32: case TR::Address: if (nextIntArgReg < getProperties().getNumIntArgRegs()) { nextIntArgReg++; } else { mapSingleParameter(parameter, stackIndex); } break; case TR::Int64: nextIntArgReg += stackIndex & 0x1; // round to next even number if (nextIntArgReg + 1 < getProperties().getNumIntArgRegs()) { nextIntArgReg += 2; } else { mapSingleParameter(parameter, stackIndex); } 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()) { nextFltArgReg += 1; } else { mapSingleParameter(parameter, stackIndex); } break; case TR::Aggregate: TR_ASSERT(false, "Function parameters of aggregate types are not currently supported on ARM."); } } }
TR::Instruction *OMR::Power::Linkage::flushArguments(TR::Instruction *cursor) { TR::Machine *machine = self()->machine(); TR::RealRegister *stackPtr = self()->cg()->getStackPointerRegister(); TR::ResolvedMethodSymbol *bodySymbol = self()->comp()->getJittedMethodSymbol(); ListIterator<TR::ParameterSymbol> paramIterator(&(bodySymbol->getParameterList())); TR::ParameterSymbol *paramCursor = paramIterator.getFirst(); TR::Node *firstNode = self()->comp()->getStartTree()->getNode(); int32_t numIntArgs = 0, numFloatArgs = 0; const TR::PPCLinkageProperties& properties = self()->getProperties(); while ( (paramCursor!=NULL) && ( (numIntArgs < properties.getNumIntArgRegs()) || (numFloatArgs < properties.getNumFloatArgRegs()) ) ) { TR::RealRegister *argRegister; int32_t offset = paramCursor->getParameterOffset(); // If parm is referenced or required to be on stack (i.e. FSD), we have to flush. bool hasToStoreToStack = paramCursor->isReferencedParameter() || paramCursor->isParmHasToBeOnStack(); switch (paramCursor->getDataType()) { case TR::Int8: case TR::Int16: case TR::Int32: if (hasToStoreToStack && numIntArgs<properties.getNumIntArgRegs()) { argRegister = machine->getRealRegister(properties.getIntegerArgumentRegister(numIntArgs)); cursor = generateMemSrc1Instruction(self()->cg(), TR::InstOpCode::stw, firstNode, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 4, self()->cg()), argRegister, cursor); } numIntArgs++; break; case TR::Address: if (numIntArgs<properties.getNumIntArgRegs()) { argRegister = machine->getRealRegister(properties.getIntegerArgumentRegister(numIntArgs)); cursor = generateMemSrc1Instruction(self()->cg(),TR::InstOpCode::Op_st, firstNode, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, TR::Compiler->om.sizeofReferenceAddress(), self()->cg()), argRegister, cursor); } numIntArgs++; break; case TR::Int64: if (hasToStoreToStack && numIntArgs<properties.getNumIntArgRegs()) { argRegister = machine->getRealRegister(properties.getIntegerArgumentRegister(numIntArgs)); if (TR::Compiler->target.is64Bit()) cursor = generateMemSrc1Instruction(self()->cg(),TR::InstOpCode::Op_st, firstNode, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 8, self()->cg()), argRegister, cursor); else { cursor = generateMemSrc1Instruction(self()->cg(), TR::InstOpCode::stw, firstNode, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 4, self()->cg()), argRegister, cursor); if (numIntArgs < properties.getNumIntArgRegs()-1) { argRegister = machine->getRealRegister(properties.getIntegerArgumentRegister(numIntArgs+1)); cursor = generateMemSrc1Instruction(self()->cg(), TR::InstOpCode::stw, firstNode, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset+4, 4, self()->cg()), argRegister, cursor); } } } if (TR::Compiler->target.is64Bit()) numIntArgs++; else numIntArgs+=2; break; case TR::Float: if (hasToStoreToStack && numFloatArgs<properties.getNumFloatArgRegs()) { argRegister = machine->getRealRegister(properties.getFloatArgumentRegister(numFloatArgs)); cursor = generateMemSrc1Instruction(self()->cg(), TR::InstOpCode::stfs, firstNode, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 4, self()->cg()), argRegister, cursor); } numFloatArgs++; break; case TR::Double: if (hasToStoreToStack && numFloatArgs<properties.getNumFloatArgRegs()) { argRegister = machine->getRealRegister(properties.getFloatArgumentRegister(numFloatArgs)); cursor = generateMemSrc1Instruction(self()->cg(), TR::InstOpCode::stfd, firstNode, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 8, self()->cg()), argRegister, cursor); } numFloatArgs++; break; } paramCursor = paramIterator.getNext(); } return(cursor); }
TR::Instruction *OMR::Power::Linkage::loadUpArguments(TR::Instruction *cursor) { if (!self()->cg()->buildInterpreterEntryPoint()) // would be better to use a different linkage for this purpose return cursor; TR::Machine *machine = self()->machine(); TR::RealRegister *stackPtr = self()->cg()->getStackPointerRegister(); TR::ResolvedMethodSymbol *bodySymbol = self()->comp()->getJittedMethodSymbol(); ListIterator<TR::ParameterSymbol> paramIterator(&(bodySymbol->getParameterList())); TR::ParameterSymbol *paramCursor = paramIterator.getFirst(); TR::Node *firstNode = self()->comp()->getStartTree()->getNode(); int32_t numIntArgs = 0, numFloatArgs = 0; const TR::PPCLinkageProperties& properties = self()->getProperties(); while ( (paramCursor!=NULL) && ( (numIntArgs < properties.getNumIntArgRegs()) || (numFloatArgs < properties.getNumFloatArgRegs()) ) ) { TR::RealRegister *argRegister; int32_t offset = paramCursor->getParameterOffset(); bool hasToLoadFromStack = paramCursor->isReferencedParameter() || paramCursor->isParmHasToBeOnStack(); switch (paramCursor->getDataType()) { case TR::Int8: case TR::Int16: case TR::Int32: if (hasToLoadFromStack && numIntArgs<properties.getNumIntArgRegs()) { argRegister = machine->getRealRegister(properties.getIntegerArgumentRegister(numIntArgs)); cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::lwz, firstNode, argRegister, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 4, self()->cg()), cursor); } numIntArgs++; break; case TR::Address: if (numIntArgs<properties.getNumIntArgRegs()) { argRegister = machine->getRealRegister(properties.getIntegerArgumentRegister(numIntArgs)); cursor = generateTrg1MemInstruction(self()->cg(),TR::InstOpCode::Op_load, firstNode, argRegister, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, TR::Compiler->om.sizeofReferenceAddress(), self()->cg()), cursor); } numIntArgs++; break; case TR::Int64: if (hasToLoadFromStack && numIntArgs<properties.getNumIntArgRegs()) { argRegister = machine->getRealRegister(properties.getIntegerArgumentRegister(numIntArgs)); if (TR::Compiler->target.is64Bit()) cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::ld, firstNode, argRegister, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 8, self()->cg()), cursor); else { cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::lwz, firstNode, argRegister, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 4, self()->cg()), cursor); if (numIntArgs < properties.getNumIntArgRegs()-1) { argRegister = machine->getRealRegister(properties.getIntegerArgumentRegister(numIntArgs+1)); cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::lwz, firstNode, argRegister, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset+4, 4, self()->cg()), cursor); } } } if (TR::Compiler->target.is64Bit()) numIntArgs++; else numIntArgs+=2; break; case TR::Float: if (hasToLoadFromStack && numFloatArgs<properties.getNumFloatArgRegs()) { argRegister = machine->getRealRegister(properties.getFloatArgumentRegister(numFloatArgs)); cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::lfs, firstNode, argRegister, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 4, self()->cg()), cursor); } numFloatArgs++; break; case TR::Double: if (hasToLoadFromStack && numFloatArgs<properties.getNumFloatArgRegs()) { argRegister = machine->getRealRegister(properties.getFloatArgumentRegister(numFloatArgs)); cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::lfd, firstNode, argRegister, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 8, self()->cg()), cursor); } numFloatArgs++; break; } paramCursor = paramIterator.getNext(); } return(cursor); }