void TR::RegDepCopyRemoval::readRegDeps() { for (int i = 0; i < _regDeps->getNumChildren(); i++) { TR::Node *depNode = _regDeps->getChild(i); TR::Node *depValue = depNode; if (depValue->getOpCodeValue() == TR::PassThrough) { do depValue = depValue->getFirstChild(); while (depValue->getOpCodeValue() == TR::PassThrough); } else { TR_ASSERT(depNode->getOpCode().isLoadReg(), "invalid GlRegDeps child opcode n%un %s\n", depNode->getGlobalIndex(), depNode->getOpCode().getName()); } // Avoid register pairs for simplicity, at least for now bool isRegPairDep = depNode->getHighGlobalRegisterNumber() != (TR_GlobalRegisterNumber)-1; bool valueNeedsRegPair = comp()->nodeNeeds2Regs(depValue); TR_ASSERT(isRegPairDep == valueNeedsRegPair, "mismatch on number of registers required for n%un\n", depNode->getGlobalIndex()); if (isRegPairDep) { ignoreRegister(depNode->getLowGlobalRegisterNumber()); ignoreRegister(depNode->getHighGlobalRegisterNumber()); continue; } // Only process integral and address-type nodes; they'll go into GPRs TR_GlobalRegisterNumber reg = depNode->getGlobalRegisterNumber(); TR::DataType depType = depValue->getType(); if (!depType.isIntegral() && !depType.isAddress()) { ignoreRegister(reg); continue; } RegDepInfo &dep = getRegDepInfo(reg); TR_ASSERT(dep.state == REGDEP_ABSENT, "register %s is multiply-specified\n", registerName(reg)); dep.node = depNode; dep.value = depValue; dep.state = REGDEP_UNDECIDED; dep.childIndex = i; } }
void OMR::SymbolReference::setSharedStaticAliases(TR_BitVector * aliases, TR::SymbolReferenceTable * symRefTab) { if (self()->reallySharesSymbol()) { TR::DataType type = self()->getSymbol()->getType(); TR_SymRefIterator i(type.isAddress() ? symRefTab->aliasBuilder.addressStaticSymRefs() : (type.isInt32() ? symRefTab->aliasBuilder.intStaticSymRefs() : symRefTab->aliasBuilder.nonIntPrimitiveStaticSymRefs()), symRefTab); TR::SymbolReference * symRef; while ((symRef = i.getNext())) if (symRef->getSymbol() == self()->getSymbol()) aliases->set(symRef->getReferenceNumber()); } else aliases->set(self()->getReferenceNumber()); *aliases |= symRefTab->aliasBuilder.unsafeSymRefNumbers(); }
void OMR::SymbolReference::setSharedShadowAliases(TR_BitVector * aliases, TR::SymbolReferenceTable * symRefTab) { if (self()->reallySharesSymbol() && !_symbol->isUnsafeShadowSymbol()) { TR::DataType type = self()->getSymbol()->getType(); TR_SymRefIterator i(type.isAddress() ? symRefTab->aliasBuilder.addressShadowSymRefs() : (type.isInt32() ? symRefTab->aliasBuilder.intShadowSymRefs() : symRefTab->aliasBuilder.nonIntPrimitiveShadowSymRefs()), symRefTab); TR::SymbolReference * symRef; while ((symRef = i.getNext())) if (symRef->getSymbol() == self()->getSymbol()) aliases->set(symRef->getReferenceNumber()); // include symbol reference's own shared alias bitvector if (symRefTab->getSharedAliases(self()) != NULL) *aliases |= *(symRefTab->getSharedAliases(self())); } else aliases->set(self()->getReferenceNumber()); *aliases |= symRefTab->aliasBuilder.unsafeSymRefNumbers(); }
int32_t TR::ARM64SystemLinkage::buildArgs(TR::Node *callNode, TR::RegisterDependencyConditions *dependencies) { const TR::ARM64LinkageProperties &properties = getProperties(); TR::ARM64MemoryArgument *pushToMemory = NULL; TR::Register *argMemReg; TR::Register *tempReg; int32_t argIndex = 0; int32_t numMemArgs = 0; int32_t argSize = 0; int32_t numIntegerArgs = 0; int32_t numFloatArgs = 0; int32_t totalSize; int32_t i; TR::Node *child; TR::DataType childType; TR::DataType resType = callNode->getType(); uint32_t firstArgumentChild = callNode->getFirstArgumentIndex(); /* Step 1 - figure out how many arguments are going to be spilled to memory i.e. not in registers */ for (i = firstArgumentChild; i < callNode->getNumChildren(); i++) { child = callNode->getChild(i); childType = child->getDataType(); switch (childType) { case TR::Int8: case TR::Int16: case TR::Int32: case TR::Int64: case TR::Address: if (numIntegerArgs >= properties.getNumIntArgRegs()) numMemArgs++; numIntegerArgs++; break; case TR::Float: case TR::Double: if (numFloatArgs >= properties.getNumFloatArgRegs()) numMemArgs++; numFloatArgs++; break; default: TR_ASSERT(false, "Argument type %s is not supported\n", childType.toString()); } } // From here, down, any new stack allocations will expire / die when the function returns TR::StackMemoryRegion stackMemoryRegion(*trMemory()); /* End result of Step 1 - determined number of memory arguments! */ if (numMemArgs > 0) { pushToMemory = new (trStackMemory()) TR::ARM64MemoryArgument[numMemArgs]; argMemReg = cg()->allocateRegister(); } totalSize = numMemArgs * 8; // align to 16-byte boundary totalSize = (totalSize + 15) & (~15); numIntegerArgs = 0; numFloatArgs = 0; for (i = firstArgumentChild; i < callNode->getNumChildren(); i++) { TR::MemoryReference *mref = NULL; TR::Register *argRegister; TR::InstOpCode::Mnemonic op; child = callNode->getChild(i); childType = child->getDataType(); switch (childType) { case TR::Int8: case TR::Int16: case TR::Int32: case TR::Int64: case TR::Address: if (childType == TR::Address) argRegister = pushAddressArg(child); else if (childType == TR::Int64) argRegister = pushLongArg(child); else argRegister = pushIntegerWordArg(child); if (numIntegerArgs < properties.getNumIntArgRegs()) { if (!cg()->canClobberNodesRegister(child, 0)) { if (argRegister->containsCollectedReference()) tempReg = cg()->allocateCollectedReferenceRegister(); else tempReg = cg()->allocateRegister(); generateMovInstruction(cg(), callNode, tempReg, argRegister); argRegister = tempReg; } if (numIntegerArgs == 0 && (resType.isAddress() || resType.isInt32() || resType.isInt64())) { TR::Register *resultReg; if (resType.isAddress()) resultReg = cg()->allocateCollectedReferenceRegister(); else resultReg = cg()->allocateRegister(); dependencies->addPreCondition(argRegister, TR::RealRegister::x0); dependencies->addPostCondition(resultReg, TR::RealRegister::x0); } else { addDependency(dependencies, argRegister, properties.getIntegerArgumentRegister(numIntegerArgs), TR_GPR, cg()); } } else { // numIntegerArgs >= properties.getNumIntArgRegs() if (childType == TR::Address || childType == TR::Int64) { op = TR::InstOpCode::strpostx; } else { op = TR::InstOpCode::strpostw; } mref = getOutgoingArgumentMemRef(argMemReg, argRegister, op, pushToMemory[argIndex++]); argSize += 8; // always 8-byte aligned } numIntegerArgs++; break; case TR::Float: case TR::Double: if (childType == TR::Float) argRegister = pushFloatArg(child); else argRegister = pushDoubleArg(child); if (numFloatArgs < properties.getNumFloatArgRegs()) { if (!cg()->canClobberNodesRegister(child, 0)) { tempReg = cg()->allocateRegister(TR_FPR); op = (childType == TR::Float) ? TR::InstOpCode::fmovs : TR::InstOpCode::fmovd; generateTrg1Src1Instruction(cg(), op, callNode, tempReg, argRegister); argRegister = tempReg; } if ((numFloatArgs == 0 && resType.isFloatingPoint())) { TR::Register *resultReg; if (resType.getDataType() == TR::Float) resultReg = cg()->allocateSinglePrecisionRegister(); else resultReg = cg()->allocateRegister(TR_FPR); dependencies->addPreCondition(argRegister, TR::RealRegister::v0); dependencies->addPostCondition(resultReg, TR::RealRegister::v0); } else { addDependency(dependencies, argRegister, properties.getFloatArgumentRegister(numFloatArgs), TR_FPR, cg()); } } else { // numFloatArgs >= properties.getNumFloatArgRegs() if (childType == TR::Double) { op = TR::InstOpCode::vstrpostd; } else { op = TR::InstOpCode::vstrposts; } mref = getOutgoingArgumentMemRef(argMemReg, argRegister, op, pushToMemory[argIndex++]); argSize += 8; // always 8-byte aligned } numFloatArgs++; break; } // end of switch } // end of for // NULL deps for non-preserved and non-system regs while (numIntegerArgs < properties.getNumIntArgRegs()) { if (numIntegerArgs == 0 && resType.isAddress()) { dependencies->addPreCondition(cg()->allocateRegister(), properties.getIntegerArgumentRegister(0)); dependencies->addPostCondition(cg()->allocateCollectedReferenceRegister(), properties.getIntegerArgumentRegister(0)); } else { addDependency(dependencies, NULL, properties.getIntegerArgumentRegister(numIntegerArgs), TR_GPR, cg()); } numIntegerArgs++; } int32_t floatRegsUsed = (numFloatArgs > properties.getNumFloatArgRegs()) ? properties.getNumFloatArgRegs() : numFloatArgs; for (i = (TR::RealRegister::RegNum)((uint32_t)TR::RealRegister::v0 + floatRegsUsed); i <= TR::RealRegister::LastFPR; i++) { if (!properties.getPreserved((TR::RealRegister::RegNum)i)) { // NULL dependency for non-preserved regs addDependency(dependencies, NULL, (TR::RealRegister::RegNum)i, TR_FPR, cg()); } } if (numMemArgs > 0) { TR::RealRegister *sp = cg()->machine()->getRealRegister(properties.getStackPointerRegister()); generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::subimmx, callNode, argMemReg, sp, totalSize); for (argIndex = 0; argIndex < numMemArgs; argIndex++) { TR::Register *aReg = pushToMemory[argIndex].argRegister; generateMemSrc1Instruction(cg(), pushToMemory[argIndex].opCode, callNode, pushToMemory[argIndex].argMemory, aReg); cg()->stopUsingRegister(aReg); } cg()->stopUsingRegister(argMemReg); } return totalSize; }
int32_t OMR::ConstantDataSnippet::addConstantRequest(void *v, TR::DataType type, TR::Instruction *nibble0, TR::Instruction *nibble1, TR::Instruction *nibble2, TR::Instruction *nibble3, TR::Node *node, bool isUnloadablePicSite) { TR::Compilation *comp = cg()->comp(); union { float fvalue; int32_t ivalue; } fin, fex; union { double dvalue; int64_t lvalue; } din, dex; intptrj_t ain, aex; int32_t ret = PTOC_FULL_INDEX; switch(type) { case TR::Float: { ListIterator< PPCConstant<float> > fiterator(&_floatConstants); PPCConstant<float> *fcursor=fiterator.getFirst(); fin.fvalue = *(float *)v; while (fcursor != NULL) { fex.fvalue = fcursor->getConstantValue(); if (fin.ivalue == fex.ivalue) break; fcursor = fiterator.getNext(); } if (fcursor == NULL) { fcursor = new (_cg->trHeapMemory()) PPCConstant<float>(_cg, fin.fvalue); _floatConstants.add(fcursor); if (TR::Compiler->target.is64Bit() && !comp->getOption(TR_DisableTOCForConsts)) { ret = TR_PPCTableOfConstants::lookUp(fin.fvalue, _cg); } fcursor->setTOCOffset(ret); } ret = fcursor->getTOCOffset(); if (TR::Compiler->target.is32Bit() || ret==PTOC_FULL_INDEX) fcursor->addValueRequest(nibble0, nibble1, nibble2, nibble3); } break; case TR::Double: { ListIterator< PPCConstant<double> > diterator(&_doubleConstants); PPCConstant<double> *dcursor=diterator.getFirst(); din.dvalue = *(double *)v; while (dcursor != NULL) { dex.dvalue = dcursor->getConstantValue(); if (din.lvalue == dex.lvalue) break; dcursor = diterator.getNext(); } if (dcursor == NULL) { dcursor = new (_cg->trHeapMemory()) PPCConstant<double>(_cg, din.dvalue); _doubleConstants.add(dcursor); if (TR::Compiler->target.is64Bit() && !comp->getOption(TR_DisableTOCForConsts)) { ret = TR_PPCTableOfConstants::lookUp(din.dvalue, _cg); } dcursor->setTOCOffset(ret); } ret = dcursor->getTOCOffset(); if (TR::Compiler->target.is32Bit() || ret==PTOC_FULL_INDEX) dcursor->addValueRequest(nibble0, nibble1, nibble2, nibble3); } break; case TR::Address: { ListIterator< PPCConstant<intptrj_t> > aiterator(&_addressConstants); PPCConstant<intptrj_t> *acursor=aiterator.getFirst(); ain = *(intptrj_t *)v; while (acursor != NULL) { aex = acursor->getConstantValue(); // if pointers require relocation, then not all pointers may be relocated for the same reason // so be conservative and do not combine them (e.g. HCR versus profiled inlined site enablement) if (ain == aex && (!cg()->profiledPointersRequireRelocation() || acursor->getNode() == node)) break; acursor = aiterator.getNext(); } if (acursor && acursor->isUnloadablePicSite()!=isUnloadablePicSite) { TR_ASSERT(0, "Existing address constant does not have a matching unloadable state.\n" ); acursor = NULL; // If asserts are turned off then we should just create a duplicate constant } if (acursor == NULL) { acursor = new (_cg->trHeapMemory()) PPCConstant<intptrj_t>(_cg, ain, node, isUnloadablePicSite); _addressConstants.add(acursor); } acursor->addValueRequest(nibble0, nibble1, nibble2, nibble3); } break; default: TR_ASSERT(0, "Only float and address constants are supported. Data type is %s.\n", type.toString()); } return(ret); }
TR::Instruction *OMR::Power::Linkage::saveArguments(TR::Instruction *cursor, bool fsd, bool saveOnly, List<TR::ParameterSymbol> &parmList) { #define REAL_REGISTER(ri) machine->getRealRegister(ri) #define REGNUM(ri) ((TR::RealRegister::RegNum)(ri)) const TR::PPCLinkageProperties& properties = self()->getProperties(); TR::Machine *machine = self()->machine(); TR::RealRegister *stackPtr = self()->cg()->getStackPointerRegister(); TR::ResolvedMethodSymbol *bodySymbol = self()->comp()->getJittedMethodSymbol(); ListIterator<TR::ParameterSymbol> paramIterator(&parmList); TR::ParameterSymbol *paramCursor; TR::Node *firstNode = self()->comp()->getStartTree()->getNode(); TR_BitVector freeScratchable; int32_t busyMoves[3][64]; int32_t busyIndex = 0, i1; bool all_saved = false; // the freeScratchable structure will not be used when saveOnly == true // no additional conditions were added with the intention of keeping the code easier to read // and not full of if conditions freeScratchable.init(TR::RealRegister::LastFPR + 1, self()->trMemory()); // first, consider all argument registers free for (i1=TR::RealRegister::FirstGPR; i1<=TR::RealRegister::LastFPR; i1++) { if (!properties.getReserved(REGNUM(i1))) { freeScratchable.set(i1); } } // second, go through all parameters and reset registers that are actually used for (paramCursor=paramIterator.getFirst(); paramCursor!=NULL; paramCursor=paramIterator.getNext()) { int32_t lri = paramCursor->getLinkageRegisterIndex(); TR::DataType type = paramCursor->getType(); if (lri >= 0) { TR::RealRegister::RegNum regNum; bool twoRegs = (TR::Compiler->target.is32Bit() && type.isInt64() && lri < properties.getNumIntArgRegs()-1); if (!type.isFloatingPoint()) { regNum = properties.getIntegerArgumentRegister(lri); if (paramCursor->isReferencedParameter()) freeScratchable.reset(regNum); if (twoRegs) if (paramCursor->isReferencedParameter()) freeScratchable.reset(regNum+1); } else { regNum = properties.getFloatArgumentRegister(lri); if (paramCursor->isReferencedParameter()) freeScratchable.reset(regNum); if (twoRegs) if (paramCursor->isReferencedParameter()) freeScratchable.reset(regNum+1); } } } for (paramCursor=paramIterator.getFirst(); paramCursor!=NULL; paramCursor=paramIterator.getNext()) { int32_t lri = paramCursor->getLinkageRegisterIndex(); int32_t ai = paramCursor->getAllocatedIndex(); int32_t offset = self()->calculateParameterRegisterOffset(paramCursor->getParameterOffset(), *paramCursor); TR::DataType type = paramCursor->getType(); int32_t dtype = type.getDataType(); // TODO: Is there an accurate assume to insert here ? if (lri >= 0) { if (!paramCursor->isReferencedParameter() && !paramCursor->isParmHasToBeOnStack()) continue; TR::RealRegister::RegNum regNum; bool twoRegs = (TR::Compiler->target.is32Bit() && type.isInt64() && lri < properties.getNumIntArgRegs()-1); if (type.isFloatingPoint()) regNum = properties.getFloatArgumentRegister(lri); else regNum = properties.getIntegerArgumentRegister(lri); // Do not save arguments to the stack if in Full Speed Debug and saveOnly is not set. // If not in Full Speed Debug, the arguments will be saved. if (((ai<0 || self()->hasToBeOnStack(paramCursor)) && !fsd) || (fsd && saveOnly)) { switch (dtype) { case TR::Int8: case TR::Int16: case TR::Int32: { TR::InstOpCode::Mnemonic op = TR::InstOpCode::stw; if (!all_saved) cursor = generateMemSrc1Instruction(self()->cg(), op, firstNode, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 4, self()->cg()), REAL_REGISTER(regNum), cursor); } break; case TR::Address: if (!all_saved) cursor = generateMemSrc1Instruction(self()->cg(),TR::InstOpCode::Op_st, firstNode, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, TR::Compiler->om.sizeofReferenceAddress(), self()->cg()), REAL_REGISTER(regNum), cursor); break; case TR::Int64: if (!all_saved) cursor = generateMemSrc1Instruction(self()->cg(),TR::InstOpCode::Op_st, firstNode, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, TR::Compiler->om.sizeofReferenceAddress(), self()->cg()), REAL_REGISTER(regNum), cursor); if (twoRegs) { if (!all_saved) cursor = generateMemSrc1Instruction(self()->cg(), TR::InstOpCode::stw, firstNode, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset+4, 4, self()->cg()), REAL_REGISTER(REGNUM(regNum+1)), cursor); if (ai<0) freeScratchable.set(regNum+1); } break; case TR::Float: cursor = generateMemSrc1Instruction(self()->cg(), TR::InstOpCode::stfs, firstNode, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 4, self()->cg()), REAL_REGISTER(regNum), cursor); break; case TR::Double: cursor = generateMemSrc1Instruction(self()->cg(), TR::InstOpCode::stfd, firstNode, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 8, self()->cg()), REAL_REGISTER(regNum), cursor); break; default: TR_ASSERT(false, "assertion failure"); break; } if (ai<0) freeScratchable.set(regNum); } // Global register is allocated to this argument. // Don't process if in Full Speed Debug and saveOnly is set if (ai>=0 && (!fsd || !saveOnly)) { if (regNum != ai) // Equal assignment: do nothing { if (freeScratchable.isSet(ai)) { cursor = generateTrg1Src1Instruction(self()->cg(), (type.isFloatingPoint()) ? TR::InstOpCode::fmr:TR::InstOpCode::mr, firstNode, REAL_REGISTER(REGNUM(ai)), REAL_REGISTER(regNum), cursor); freeScratchable.reset(ai); freeScratchable.set(regNum); } else // The status of target global register is unclear (i.e. it is a arg reg) { busyMoves[0][busyIndex] = regNum; busyMoves[1][busyIndex] = ai; busyMoves[2][busyIndex] = 0; busyIndex++; } } if (TR::Compiler->target.is32Bit() && type.isInt64()) { int32_t aiLow = paramCursor->getAllocatedLow(); if (!twoRegs) // Low part needs to come from memory { offset += 4; // We are dealing with the low part if (freeScratchable.isSet(aiLow)) { cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::lwz, firstNode, REAL_REGISTER(REGNUM(aiLow)), new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 4, self()->cg()), cursor); freeScratchable.reset(aiLow); } else { busyMoves[0][busyIndex] = offset; busyMoves[1][busyIndex] = aiLow; busyMoves[2][busyIndex] = 1; busyIndex++; } } else if (regNum+1 != aiLow) // Low part needs to be moved { if (freeScratchable.isSet(aiLow)) { cursor = generateTrg1Src1Instruction(self()->cg(), TR::InstOpCode::mr, firstNode, REAL_REGISTER(REGNUM(aiLow)), REAL_REGISTER(REGNUM(regNum+1)), cursor); freeScratchable.reset(aiLow); freeScratchable.set(regNum+1); } else { busyMoves[0][busyIndex] = regNum+1; busyMoves[1][busyIndex] = aiLow; busyMoves[2][busyIndex] = 0; busyIndex++; } } } } } // Don't process if in Full Speed Debug and saveOnly is set else if (ai >= 0 && (!fsd || !saveOnly)) // lri<0: arg needs to come from memory { switch (dtype) { case TR::Int8: case TR::Int16: case TR::Int32: if (freeScratchable.isSet(ai)) { cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::lwz, firstNode, REAL_REGISTER(REGNUM(ai)), new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 4, self()->cg()), cursor); freeScratchable.reset(ai); } else { busyMoves[0][busyIndex] = offset; busyMoves[1][busyIndex] = ai; busyMoves[2][busyIndex] = 1; busyIndex++; } break; case TR::Address: if (freeScratchable.isSet(ai)) { cursor = generateTrg1MemInstruction(self()->cg(),TR::InstOpCode::Op_load, firstNode, REAL_REGISTER(REGNUM(ai)), new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, TR::Compiler->om.sizeofReferenceAddress(), self()->cg()), cursor); freeScratchable.reset(ai); } else { busyMoves[0][busyIndex] = offset; busyMoves[1][busyIndex] = ai; if (TR::Compiler->target.is64Bit()) busyMoves[2][busyIndex] = 2; else busyMoves[2][busyIndex] = 1; busyIndex++; } break; case TR::Int64: if (TR::Compiler->target.is64Bit()) { if (freeScratchable.isSet(ai)) { cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::ld, firstNode, REAL_REGISTER(REGNUM(ai)), new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 8, self()->cg()), cursor); freeScratchable.reset(ai); } else { busyMoves[0][busyIndex] = offset; busyMoves[1][busyIndex] = ai; busyMoves[2][busyIndex] = 2; busyIndex++; } } else // 32-bit { if (freeScratchable.isSet(ai)) { cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::lwz, firstNode, REAL_REGISTER(REGNUM(ai)), new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 4, self()->cg()), cursor); freeScratchable.reset(ai); } else { busyMoves[0][busyIndex] = offset; busyMoves[1][busyIndex] = ai; busyMoves[2][busyIndex] = 1; busyIndex++; } ai = paramCursor->getAllocatedLow(); if (freeScratchable.isSet(ai)) { cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::lwz, firstNode, REAL_REGISTER(REGNUM(ai)), new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset+4, 4, self()->cg()), cursor); freeScratchable.reset(ai); } else { busyMoves[0][busyIndex] = offset+4; busyMoves[1][busyIndex] = ai; busyMoves[2][busyIndex] = 1; busyIndex++; } } break; case TR::Float: if (freeScratchable.isSet(ai)) { cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::lfs, firstNode, REAL_REGISTER(REGNUM(ai)), new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 4, self()->cg()), cursor); freeScratchable.reset(ai); } else { busyMoves[0][busyIndex] = offset; busyMoves[1][busyIndex] = ai; busyMoves[2][busyIndex] = 3; busyIndex++; } break; case TR::Double: if (freeScratchable.isSet(ai)) { cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::lfd, firstNode, REAL_REGISTER(REGNUM(ai)), new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 8, self()->cg()), cursor); freeScratchable.reset(ai); } else { busyMoves[0][busyIndex] = offset; busyMoves[1][busyIndex] = ai; busyMoves[2][busyIndex] = 4; busyIndex++; } break; default: break; } } } if (!fsd || !saveOnly) { bool freeMore = true; int32_t numMoves = busyIndex; while (freeMore && numMoves>0) { freeMore = false; for (i1=0; i1<busyIndex; i1++) { int32_t source = busyMoves[0][i1]; int32_t target = busyMoves[1][i1]; if (!(target<0) && freeScratchable.isSet(target)) { switch(busyMoves[2][i1]) { case 0: cursor = generateTrg1Src1Instruction(self()->cg(), (source<=TR::RealRegister::LastGPR)?TR::InstOpCode::mr:TR::InstOpCode::fmr, firstNode, REAL_REGISTER(REGNUM(target)), REAL_REGISTER(REGNUM(source)), cursor); freeScratchable.set(source); break; case 1: cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::lwz, firstNode, REAL_REGISTER(REGNUM(target)), new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, source, 4, self()->cg()), cursor); break; case 2: cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::ld, firstNode, REAL_REGISTER(REGNUM(target)), new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, source, 8, self()->cg()), cursor); break; case 3: cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::lfs, firstNode, REAL_REGISTER(REGNUM(target)), new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, source, 4, self()->cg()), cursor); break; case 4: cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::lfd, firstNode, REAL_REGISTER(REGNUM(target)), new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, source, 8, self()->cg()), cursor); break; } freeScratchable.reset(target); freeMore = true; busyMoves[0][i1] = busyMoves[1][i1] = -1; numMoves--; } } } TR_ASSERT(numMoves<=0, "Circular argument register dependency can and should be avoided."); } return(cursor); }