uint32_t TR::AMD64FPConversionSnippet::getLength(int32_t estimatedSnippetStart) { // *this swipeable for debugging purposes uint32_t length = 11; TR::Machine *machine = cg()->machine(); if (toRealRegister(_convertInstruction->getTargetRegister())->getRegisterNumber() != TR::RealRegister::eax) { // MOV R, rax // XCHG R, rax // // 3 instruction/modRM bytes + 2 REX prefixes // length += (3 + 2); } TR::X86RegRegInstruction *instr = _convertInstruction->getIA32RegRegInstruction(); TR_ASSERT(instr != NULL, "f2i conversion instruction must be either L4RegMem or CVTTSS2SIRegReg\n"); TR::RealRegister *sourceRegister = toRealRegister(instr->getSourceRegister()); if (sourceRegister->getRegisterNumber() != TR::RealRegister::xmm0) { length += sizeof(pushBinary) + sizeof(popBinary) // push and pop + 4 + (sourceRegister->rexBits(TR::RealRegister::REX_B, false)? 1 : 0) // MOVSD xmm0, source ; } return length + estimateRestartJumpLength(estimatedSnippetStart + length); }
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); }
uint8_t * TR::S390CallSnippet::storeArgumentItem(TR::InstOpCode::Mnemonic op, uint8_t * buffer, TR::RealRegister * reg, int32_t offset, TR::CodeGenerator * cg) { TR::RealRegister * stackPtr = cg->getStackPointerRealRegister(); TR::InstOpCode opCode(op); opCode.copyBinaryToBuffer(buffer); reg->setRegisterField(toS390Cursor(buffer)); stackPtr->setBaseRegisterField(toS390Cursor(buffer)); TR_ASSERT((offset & 0xfffff000) == 0, "CallSnippet: Unexpected displacement %d for storeArgumentItem", offset); *toS390Cursor(buffer) |= offset & 0x00000fff; return buffer + opCode.getInstructionLength(); }
static void assignFreeRegisters(TR::Instruction *currentInstruction, TR::RegisterDependency *dep, TR_PPCRegisterDependencyMap& map, TR::CodeGenerator *cg) { // *this swipeable for debugging purposes TR::Machine *machine = cg->machine(); // Assign a chain of dependencies where the head of the chain depends on a free reg while (dep) { TR_ASSERT(machine->getPPCRealRegister(dep->getRealRegister())->getState() == TR::RealRegister::Free, "Expecting free target register"); TR::RealRegister *assignedReg = dep->getRegister()->getAssignedRealRegister() ? toRealRegister(dep->getRegister()->getAssignedRealRegister()) : NULL; machine->coerceRegisterAssignment(currentInstruction, dep->getRegister(), dep->getRealRegister()); dep->getRegister()->block(); dep = assignedReg ? map.getDependencyWithTarget(assignedReg->getRegisterNumber()) : NULL; } }
uint8_t * OMR::Power::Instruction::generateBinaryEncoding() { uint8_t *instructionStart = self()->cg()->getBinaryBufferCursor(); uint8_t *cursor = instructionStart; if (self()->getOpCodeValue() == TR::InstOpCode::depend || self()->getOpCodeValue() == TR::InstOpCode::assocreg) { } else { cursor = self()->getOpCode().copyBinaryToBuffer(instructionStart); if (self()->getOpCodeValue() == TR::InstOpCode::genop) { TR::RealRegister::RegNum nopreg = TR::Compiler->target.cpu.id() > TR_PPCp6 ? TR::RealRegister::gr2 : TR::RealRegister::gr1; TR::RealRegister *r = self()->cg()->machine()->getRealRegister(nopreg); r->setRegisterFieldRS((uint32_t *) cursor); r->setRegisterFieldRA((uint32_t *) cursor); } cursor += PPC_INSTRUCTION_LENGTH; } self()->setBinaryLength(cursor - instructionStart); self()->setBinaryEncoding(instructionStart); return cursor; }
uint8_t *TR::PPCArrayCopyCallSnippet::emitSnippetBody() { TR::Node *node = getNode(); TR_ASSERT(node->getOpCodeValue() == TR::arraycopy && node->getChild(2)->getOpCode().isLoadConst(), "only valid for arraycopies with a constant length\n"); uint8_t *buffer = cg()->getBinaryBufferCursor(); getSnippetLabel()->setCodeLocation(buffer); TR::RealRegister *lengthReg = cg()->machine()->getRealRegister(_lengthRegNum); TR::Node *lengthNode = node->getChild(2); int64_t byteLen = (lengthNode->getType().isInt32() ? lengthNode->getInt() : lengthNode->getLongInt()); TR::InstOpCode opcode; // li lengthReg, #byteLen opcode.setOpCodeValue(TR::InstOpCode::li); buffer = opcode.copyBinaryToBuffer(buffer); lengthReg->setRegisterFieldRT((uint32_t *)buffer); TR_ASSERT(byteLen <= UPPER_IMMED,"byteLen too big to encode\n"); *(int32_t *)buffer |= byteLen; buffer += 4; return TR::PPCHelperCallSnippet::genHelperCall(buffer); }
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; }
void TR::ARM64SystemLinkage::initARM64RealRegisterLinkage() { TR::Machine *machine = cg()->machine(); TR::RealRegister *reg; int icount; reg = machine->getRealRegister(TR::RealRegister::RegNum::x16); // IP0 reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); reg = machine->getRealRegister(TR::RealRegister::RegNum::x17); // IP1 reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); reg = machine->getRealRegister(TR::RealRegister::RegNum::x29); // FP reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); reg = machine->getRealRegister(TR::RealRegister::RegNum::x30); // LR reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); reg = machine->getRealRegister(TR::RealRegister::RegNum::sp); // SP reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); reg = machine->getRealRegister(TR::RealRegister::RegNum::xzr); // zero reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); // assign "maximum" weight to registers x0-x15 for (icount = TR::RealRegister::x0; icount <= TR::RealRegister::x15; icount++) machine->getRealRegister((TR::RealRegister::RegNum)icount)->setWeight(0xf000); // assign "maximum" weight to registers x18-x28 for (icount = TR::RealRegister::x18; icount <= TR::RealRegister::x28; icount++) machine->getRealRegister((TR::RealRegister::RegNum)icount)->setWeight(0xf000); // assign "maximum" weight to registers v0-v31 for (icount = TR::RealRegister::v0; icount <= TR::RealRegister::v31; icount++) machine->getRealRegister((TR::RealRegister::RegNum)icount)->setWeight(0xf000); }
void TR_PPCRegisterDependencyGroup::assignRegisters(TR::Instruction *currentInstruction, TR_RegisterKinds kindToBeAssigned, uint32_t numberOfRegisters, TR::CodeGenerator *cg) { // *this swipeable for debugging purposes TR::Machine *machine = cg->machine(); TR::Register *virtReg; TR::RealRegister::RegNum dependentRegNum; TR::RealRegister *dependentRealReg, *assignedRegister, *realReg; int i, j; TR::Compilation *comp = cg->comp(); int num_gprs = 0; int num_fprs = 0; int num_vrfs = 0; // Use to do lookups using real register numbers TR_PPCRegisterDependencyMap map(_dependencies, numberOfRegisters); if (!comp->getOption(TR_DisableOOL)) { for (i = 0; i< numberOfRegisters; i++) { virtReg = _dependencies[i].getRegister(); dependentRegNum = _dependencies[i].getRealRegister(); if (dependentRegNum == TR::RealRegister::SpilledReg) { TR_ASSERT(virtReg->getBackingStorage(),"should have a backing store if dependentRegNum == spillRegIndex()\n"); if (virtReg->getAssignedRealRegister()) { // this happens when the register was first spilled in main line path then was reverse spilled // and assigned to a real register in OOL path. We protected the backing store when doing // the reverse spill so we could re-spill to the same slot now traceMsg (comp,"\nOOL: Found register spilled in main line and re-assigned inside OOL"); TR::Node *currentNode = currentInstruction->getNode(); TR::RealRegister *assignedReg = toRealRegister(virtReg->getAssignedRegister()); TR::MemoryReference *tempMR = new (cg->trHeapMemory()) TR::MemoryReference(currentNode, (TR::SymbolReference*)virtReg->getBackingStorage()->getSymbolReference(), sizeof(uintptr_t), cg); TR::InstOpCode::Mnemonic opCode; TR_RegisterKinds rk = virtReg->getKind(); switch (rk) { case TR_GPR: opCode =TR::InstOpCode::Op_load; break; case TR_FPR: opCode = virtReg->isSinglePrecision() ? TR::InstOpCode::lfs : TR::InstOpCode::lfd; break; default: TR_ASSERT(0, "\nRegister kind not supported in OOL spill\n"); break; } TR::Instruction *inst = generateTrg1MemInstruction(cg, opCode, currentNode, assignedReg, tempMR, currentInstruction); assignedReg->setAssignedRegister(NULL); virtReg->setAssignedRegister(NULL); assignedReg->setState(TR::RealRegister::Free); if (comp->getDebug()) cg->traceRegisterAssignment("Generate reload of virt %s due to spillRegIndex dep at inst %p\n",comp->getDebug()->getName(virtReg),currentInstruction); cg->traceRAInstruction(inst); } if (!(std::find(cg->getSpilledRegisterList()->begin(), cg->getSpilledRegisterList()->end(), virtReg) != cg->getSpilledRegisterList()->end())) cg->getSpilledRegisterList()->push_front(virtReg); } // we also need to free up all locked backing storage if we are exiting the OOL during backwards RA assignment else if (currentInstruction->isLabel() && virtReg->getAssignedRealRegister()) { TR::PPCLabelInstruction *labelInstr = (TR::PPCLabelInstruction *)currentInstruction; TR_BackingStore * location = virtReg->getBackingStorage(); TR_RegisterKinds rk = virtReg->getKind(); int32_t dataSize; if (labelInstr->getLabelSymbol()->isStartOfColdInstructionStream() && location) { traceMsg (comp,"\nOOL: Releasing backing storage (%p)\n", location); if (rk == TR_GPR) dataSize = TR::Compiler->om.sizeofReferenceAddress(); else dataSize = 8; location->setMaxSpillDepth(0); cg->freeSpill(location,dataSize,0); virtReg->setBackingStorage(NULL); } } } } for (i = 0; i < numberOfRegisters; i++) { map.addDependency(_dependencies[i], i); virtReg = _dependencies[i].getRegister(); dependentRegNum = _dependencies[i].getRealRegister(); if (dependentRegNum != TR::RealRegister::SpilledReg) { if (virtReg->getKind() == TR_GPR) num_gprs++; else if (virtReg->getKind() == TR_FPR) num_fprs++; else if (virtReg->getKind() == TR_VRF) num_vrfs++; } } #ifdef DEBUG int locked_gprs = 0; int locked_fprs = 0; int locked_vrfs = 0; // count up how many registers are locked for each type for(i = TR::RealRegister::FirstGPR; i <= TR::RealRegister::LastGPR; i++) { realReg = machine->getPPCRealRegister((TR::RealRegister::RegNum)i); if (realReg->getState() == TR::RealRegister::Locked) locked_gprs++; } for(i = TR::RealRegister::FirstFPR; i <= TR::RealRegister::LastFPR; i++) { realReg = machine->getPPCRealRegister((TR::RealRegister::RegNum)i); if (realReg->getState() == TR::RealRegister::Locked) locked_fprs++; } for(i = TR::RealRegister::FirstVRF; i <= TR::RealRegister::LastVRF; i++) { realReg = machine->getPPCRealRegister((TR::RealRegister::RegNum)i); if (realReg->getState() == TR::RealRegister::Locked) locked_vrfs++; } TR_ASSERT( locked_gprs == machine->getNumberOfLockedRegisters(TR_GPR),"Inconsistent number of locked GPRs"); TR_ASSERT( locked_fprs == machine->getNumberOfLockedRegisters(TR_FPR),"Inconsistent number of locked FPRs"); TR_ASSERT( locked_vrfs == machine->getNumberOfLockedRegisters(TR_VRF), "Inconsistent number of locked VRFs"); #endif // To handle circular dependencies, we block a real register if (1) it is already assigned to a correct // virtual register and (2) if it is assigned to one register in the list but is required by another. // However, if all available registers are requested, we do not block in case (2) to avoid all registers // being blocked. bool block_gprs = true; bool block_fprs = true; bool block_vrfs = true; TR_ASSERT(num_gprs <= (TR::RealRegister::LastGPR - TR::RealRegister::FirstGPR + 1 - machine->getNumberOfLockedRegisters(TR_GPR)), "Too many GPR dependencies, unable to assign" ); TR_ASSERT(num_fprs <= (TR::RealRegister::LastFPR - TR::RealRegister::FirstFPR + 1 - machine->getNumberOfLockedRegisters(TR_FPR)), "Too many FPR dependencies, unable to assign" ); TR_ASSERT(num_vrfs <= (TR::RealRegister::LastVRF - TR::RealRegister::FirstVRF + 1 - machine->getNumberOfLockedRegisters(TR_VRF)), "Too many VRF dependencies, unable to assign" ); if (num_gprs == (TR::RealRegister::LastGPR - TR::RealRegister::FirstGPR + 1 - machine->getNumberOfLockedRegisters(TR_GPR))) block_gprs = false; if (num_fprs == (TR::RealRegister::LastFPR - TR::RealRegister::FirstFPR + 1 - machine->getNumberOfLockedRegisters(TR_FPR))) block_fprs = false; if (num_vrfs == (TR::RealRegister::LastVRF - TR::RealRegister::FirstVRF + 1 - machine->getNumberOfLockedRegisters(TR_VRF))) block_vrfs = false; for (i = 0; i < numberOfRegisters; i++) { virtReg = _dependencies[i].getRegister(); if (virtReg->getAssignedRealRegister()!=NULL) { if (_dependencies[i].getRealRegister() == TR::RealRegister::NoReg) { virtReg->block(); } else { TR::RealRegister::RegNum assignedRegNum; assignedRegNum = toRealRegister(virtReg->getAssignedRealRegister())->getRegisterNumber(); // always block if required register and assigned register match; // block if assigned register is required by other dependency but only if // any spare registers are left to avoid blocking all existing registers if (_dependencies[i].getRealRegister() == assignedRegNum || (map.getDependencyWithTarget(assignedRegNum) && ((virtReg->getKind() != TR_GPR || block_gprs) && (virtReg->getKind() != TR_FPR || block_fprs) && (virtReg->getKind() != TR_VRF || block_vrfs)))) { virtReg->block(); } } } } // Assign all virtual regs that depend on a specific real reg that is free for (i = 0; i < numberOfRegisters; i++) { virtReg = _dependencies[i].getRegister(); dependentRegNum = _dependencies[i].getRealRegister(); dependentRealReg = machine->getPPCRealRegister(dependentRegNum); if (dependentRegNum != TR::RealRegister::NoReg && dependentRegNum != TR::RealRegister::SpilledReg && dependentRealReg->getState() == TR::RealRegister::Free) { assignFreeRegisters(currentInstruction, &_dependencies[i], map, cg); } } // Assign all virtual regs that depend on a specfic real reg that is not free for (i = 0; i < numberOfRegisters; i++) { virtReg = _dependencies[i].getRegister(); assignedRegister = NULL; if (virtReg->getAssignedRealRegister() != NULL) { assignedRegister = toRealRegister(virtReg->getAssignedRealRegister()); } dependentRegNum = _dependencies[i].getRealRegister(); dependentRealReg = machine->getPPCRealRegister(dependentRegNum); if (dependentRegNum != TR::RealRegister::NoReg && dependentRegNum != TR::RealRegister::SpilledReg && dependentRealReg != assignedRegister) { bool depsBlocked = false; switch (_dependencies[i].getRegister()->getKind()) { case TR_GPR: depsBlocked = block_gprs; break; case TR_FPR: depsBlocked = block_fprs; break; case TR_VRF: depsBlocked = block_vrfs; break; } assignContendedRegisters(currentInstruction, &_dependencies[i], map, depsBlocked, cg); } } // Assign all virtual regs that depend on NoReg but exclude gr0 for (i=0; i<numberOfRegisters; i++) { if (_dependencies[i].getRealRegister() == TR::RealRegister::NoReg && _dependencies[i].getExcludeGPR0()) { TR::RealRegister *realOne; virtReg = _dependencies[i].getRegister(); realOne = virtReg->getAssignedRealRegister(); if (realOne!=NULL && toRealRegister(realOne)->getRegisterNumber()==TR::RealRegister::gr0) { if ((assignedRegister = machine->findBestFreeRegister(currentInstruction, virtReg->getKind(), true, false, virtReg)) == NULL) { assignedRegister = machine->freeBestRegister(currentInstruction, virtReg, NULL, true); } machine->coerceRegisterAssignment(currentInstruction, virtReg, assignedRegister->getRegisterNumber()); } else if (realOne == NULL) { machine->assignOneRegister(currentInstruction, virtReg, true); } virtReg->block(); } } // Assign all virtual regs that depend on NoReg for (i=0; i<numberOfRegisters; i++) { if (_dependencies[i].getRealRegister() == TR::RealRegister::NoReg && !_dependencies[i].getExcludeGPR0()) { TR::RealRegister *realOne; virtReg = _dependencies[i].getRegister(); realOne = virtReg->getAssignedRealRegister(); if (!realOne) { machine->assignOneRegister(currentInstruction, virtReg, false); } virtReg->block(); } } unblockRegisters(numberOfRegisters); for (i = 0; i < numberOfRegisters; i++) { TR::Register *dependentRegister = getRegisterDependency(i)->getRegister(); // dependentRegister->getAssignedRegister() is NULL if the reg has already been spilled due to a spilledReg dep if (comp->getOption(TR_DisableOOL) || (!(cg->isOutOfLineColdPath()) && !(cg->isOutOfLineHotPath()))) { TR_ASSERT(dependentRegister->getAssignedRegister(), "assignedRegister can not be NULL"); } if (dependentRegister->getAssignedRegister()) { TR::RealRegister *assignedRegister = dependentRegister->getAssignedRegister()->getRealRegister(); if (getRegisterDependency(i)->getRealRegister() == TR::RealRegister::NoReg) getRegisterDependency(i)->setRealRegister(toRealRegister(assignedRegister)->getRegisterNumber()); machine->decFutureUseCountAndUnlatch(dependentRegister); } } }
static void assignContendedRegisters(TR::Instruction *currentInstruction, TR::RegisterDependency *dep, TR_PPCRegisterDependencyMap& map, bool depsBlocked, TR::CodeGenerator *cg) { // *this swipeable for debugging purposes TR::Machine *machine = cg->machine(); dep = findDependencyChainHead(dep, map); TR::Register *virtReg = dep->getRegister(); TR::RealRegister::RegNum targetRegNum = dep->getRealRegister(); TR::RealRegister *targetReg = machine->getPPCRealRegister(targetRegNum); TR::RealRegister *assignedReg = virtReg->getAssignedRealRegister() ? toRealRegister(virtReg->getAssignedRealRegister()) : NULL; // Chain of length 1 if (!assignedReg || !map.getDependencyWithTarget(assignedReg->getRegisterNumber())) { machine->coerceRegisterAssignment(currentInstruction, virtReg, targetRegNum); virtReg->block(); return; } // Chain of length 2, handled here instead of below to get 3*xor exchange on GPRs if (map.getDependencyWithTarget(assignedReg->getRegisterNumber()) == map.getDependencyWithAssigned(targetRegNum)) { TR::Register *targetVirtReg = targetReg->getAssignedRegister(); machine->coerceRegisterAssignment(currentInstruction, virtReg, targetRegNum); virtReg->block(); targetVirtReg->block(); return; } // Grab a spare reg in order to free the target of the first dep // At this point the first dep's target could be blocked, assigned, or NoReg // If it's blocked or assigned we allocate a spare and assign the target's virtual to it // If it's NoReg, the spare reg will be used as the first dep's actual target TR::RealRegister *spareReg = machine->findBestFreeRegister(currentInstruction, virtReg->getKind(), targetRegNum == TR::RealRegister::NoReg ? dep->getExcludeGPR0() : false, false, targetRegNum == TR::RealRegister::NoReg ? virtReg : targetReg->getAssignedRegister()); bool haveFreeSpare = spareReg != NULL; if (!spareReg) { // If the regs in this dep group are not blocked we need to make sure we don't spill a reg that's in the middle of the chain if (!depsBlocked) { if (targetRegNum == TR::RealRegister::NoReg) spareReg = machine->freeBestRegister(currentInstruction, map.getDependencyWithTarget(assignedReg->getRegisterNumber())->getRegister(), assignedReg, false); else spareReg = machine->freeBestRegister(currentInstruction, virtReg, targetReg, false); } else { if (targetRegNum == TR::RealRegister::NoReg) spareReg = machine->freeBestRegister(currentInstruction, virtReg, NULL, dep->getExcludeGPR0()); else spareReg = machine->freeBestRegister(currentInstruction, targetReg->getAssignedRegister(), NULL, false); } } if (targetRegNum != TR::RealRegister::NoReg && spareReg != targetReg) { machine->coerceRegisterAssignment(currentInstruction, targetReg->getAssignedRegister(), spareReg->getRegisterNumber()); } TR_ASSERT(targetRegNum == TR::RealRegister::NoReg || targetReg->getState() == TR::RealRegister::Free, "Expecting free target register"); if (depsBlocked || targetRegNum != TR::RealRegister::NoReg || haveFreeSpare) { machine->coerceRegisterAssignment(currentInstruction, virtReg, targetRegNum == TR::RealRegister::NoReg ? spareReg->getRegisterNumber() : targetRegNum); virtReg->block(); } dep = map.getDependencyWithTarget(assignedReg->getRegisterNumber()); while (dep) { virtReg = dep->getRegister(); targetRegNum = dep->getRealRegister(); targetReg = machine->getPPCRealRegister(targetRegNum); assignedReg = virtReg->getAssignedRealRegister() ? toRealRegister(virtReg->getAssignedRealRegister()) : NULL; TR_ASSERT(targetReg->getState() == TR::RealRegister::Free || targetReg == spareReg, "Expecting free target register or target to have been filled to free spare register"); machine->coerceRegisterAssignment(currentInstruction, virtReg, targetRegNum); virtReg->block(); dep = assignedReg ? map.getDependencyWithTarget(assignedReg->getRegisterNumber()) : NULL; } }
void TR::ARMSystemLinkage::initARMRealRegisterLinkage() { TR::Machine *machine = cg()->machine(); // make r15 (PC) unavailable for RA TR::RealRegister *reg = machine->getRealRegister(TR::RealRegister::gr15); reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); // make r14 (LR) unavailable for RA reg = machine->getRealRegister(TR::RealRegister::gr14); reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); // make r13 (SP) unavailable for RA reg = machine->getRealRegister(TR::RealRegister::gr13); reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); // make r12 (IP) unavailable for RA reg = machine->getRealRegister(TR::RealRegister::gr12); reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); // make r9 unavailable for RA (just in case, because it's meaning is platform defined) reg = machine->getRealRegister(TR::RealRegister::gr9); reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); /* * Note: we can assign the same weight to all registers because loads/stores * can be done on multiple registers simultaneously. */ // assign "maximum" weight to registers r0-r8 for (int32_t r = TR::RealRegister::gr0; r <= TR::RealRegister::gr8; ++r) { machine->getRealRegister(static_cast<TR::RealRegister::RegNum>(r))->setWeight(0xf000); } // assign "maximum" weight to registers r10-r12 for (int32_t r = TR::RealRegister::gr10; r <= TR::RealRegister::gr12; ++r) { machine->getRealRegister(static_cast<TR::RealRegister::RegNum>(r))->setWeight(0xf000); } }
uint8_t *TR::AMD64FPConversionSnippet::genFPConversion(uint8_t *buffer) { // *this swipeable for debugging purposes // This didn't end up as clean as I thought. TODO:AMD64: Separate out the 64-bit code into another class. TR::ILOpCodes opCode = _convertInstruction->getNode()->getOpCodeValue(); TR::RealRegister *targetRegister = toRealRegister(_convertInstruction->getTargetRegister()); TR::RealRegister::RegNum targetReg = targetRegister->getRegisterNumber(); TR::Machine *machine = cg()->machine(); const TR::X86LinkageProperties &properties = cg()->getProperties(); uint8_t *originalBuffer = buffer; TR_ASSERT(properties.getIntegerReturnRegister() == TR::RealRegister::eax, "Only support integer return in eax"); if (targetReg != TR::RealRegister::eax) { // MOV R, rax // *buffer++ = TR::RealRegister::REX | TR::RealRegister::REX_W | targetRegister->rexBits(TR::RealRegister::REX_R, false); *buffer++ = 0x8b; *buffer = 0xc0; targetRegister->setRegisterFieldInModRM(buffer); buffer++; } TR_ASSERT(properties.getFloatArgumentRegister(0) == TR::RealRegister::xmm0, "Only support 1st FP arg in xmm0"); TR::X86RegRegInstruction *instr = _convertInstruction->getIA32RegRegInstruction(); TR_ASSERT(instr != NULL, "conversion instruction must be CVTTSS2SIRegReg\n"); TR::RealRegister *sourceRegister = toRealRegister(instr->getSourceRegister()); TR::RealRegister::RegNum sourceReg = sourceRegister->getRegisterNumber(); // Save xmm0 if necessary // if (sourceReg != TR::RealRegister::xmm0) { TR_ASSERT(TR::Compiler->target.is64Bit(), "This push sequence only works on AMD64"); memcpy(buffer, pushBinary, sizeof(pushBinary)); buffer += sizeof(pushBinary); // MOVSD xmm0, source // *buffer++ = 0xf2; if( (*buffer = sourceRegister->rexBits(TR::RealRegister::REX_B, false)) ) buffer++; *buffer++ = 0x0f; *buffer++ = 0x10; *buffer = 0xc0; sourceRegister->setRegisterFieldInOpcode(buffer); buffer++; } // Call the helper // buffer = emitCallToConversionHelper(buffer); // Restore xmm0 if necessary // if (sourceReg != TR::RealRegister::xmm0) { TR_ASSERT(TR::Compiler->target.is64Bit(), "This pop sequence only works on AMD64"); memcpy(buffer, popBinary, sizeof(popBinary)); buffer += sizeof(popBinary); } if (targetReg != TR::RealRegister::eax) { // XCHG R, rax // *buffer++ = TR::RealRegister::REX | TR::RealRegister::REX_W | targetRegister->rexBits(TR::RealRegister::REX_B, false); *buffer = 0x90; targetRegister->setRegisterFieldInOpcode(buffer); buffer++; } return buffer; }
void TR_Debug::print(TR::FILE *pOutFile, TR::AMD64FPConversionSnippet * snippet) { if (pOutFile == NULL) return; uint8_t *bufferPos = snippet->getSnippetLabel()->getCodeLocation(); printSnippetLabel(pOutFile, snippet->getSnippetLabel(), bufferPos, getName(snippet)); TR::Machine *machine = _cg->machine(); TR::RealRegister *sourceRegister = toRealRegister(snippet->getConvertInstruction()->getSourceRegister()); TR::RealRegister *targetRegister = toRealRegister(snippet->getConvertInstruction()->getTargetRegister()); uint8_t sreg = sourceRegister->getRegisterNumber(); uint8_t treg = targetRegister->getRegisterNumber(); TR::ILOpCodes opCode = snippet->getConvertInstruction()->getNode()->getOpCodeValue(); TR_RegisterSizes size = TR_DoubleWordReg; if (treg != TR::RealRegister::eax) { int instrSize = IS_REX(*bufferPos)? 3 : 2; printPrefix(pOutFile, NULL, bufferPos, instrSize); trfprintf(pOutFile, "mov \t"); print(pOutFile, targetRegister, size); trfprintf(pOutFile, ", "); print(pOutFile, machine->getX86RealRegister(TR::RealRegister::eax), size); trfprintf(pOutFile, "\t%s preserve helper return reg", commentString()); bufferPos += instrSize; } if (sreg != TR::RealRegister::xmm0) { printPrefix(pOutFile, NULL, bufferPos, 4); trfprintf(pOutFile, "sub \trsp, 8"); printPrefix(pOutFile, NULL, bufferPos, 5); trfprintf(pOutFile, "movsd\t[rsp], xmm0\t%s save xmm0", commentString()); bufferPos += 9; int instrSize = IS_REX(*bufferPos)? 5 : 4; printPrefix(pOutFile, NULL, bufferPos, instrSize); trfprintf(pOutFile, "movsd\txmm0, "); print(pOutFile, sourceRegister, TR_QuadWordReg); trfprintf(pOutFile, "\t%s load parameter", commentString()); bufferPos += instrSize; } printPrefix(pOutFile, NULL, bufferPos, 5); trfprintf(pOutFile, "call\t%s", getName(snippet->getHelperSymRef())); bufferPos += 5; if (sreg != TR::RealRegister::xmm0) { printPrefix(pOutFile, NULL, bufferPos, 5); trfprintf(pOutFile, "movsd\txmm0, [rsp]\t%s restore xmm0", commentString()); printPrefix(pOutFile, NULL, bufferPos, 4); trfprintf(pOutFile, "add \trsp, 8"); bufferPos += 9; } if (treg != TR::RealRegister::eax) { int instrSize = IS_REX(*bufferPos)? 2 : 1; printPrefix(pOutFile, NULL, bufferPos, instrSize); trfprintf(pOutFile, "xchg\t"); print(pOutFile, targetRegister, size); trfprintf(pOutFile, ", "); print(pOutFile, machine->getX86RealRegister(TR::RealRegister::eax), size); trfprintf(pOutFile, "\t%s restore result reg & put result in target reg", commentString()); bufferPos += instrSize; } printRestartJump(pOutFile, snippet, bufferPos); }
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::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_Debug::print(TR::FILE *pOutFile, TR::X86FPConvertToIntSnippet * snippet) { if (pOutFile == NULL) return; uint8_t *bufferPos = snippet->getSnippetLabel()->getCodeLocation(); printSnippetLabel(pOutFile, snippet->getSnippetLabel(), bufferPos, getName(snippet)); TR::RealRegister *targetRegister = toRealRegister(snippet->getConvertInstruction()->getTargetRegister()); uint8_t reg = targetRegister->getRegisterNumber(); if (reg != TR::RealRegister::eax) { printPrefix(pOutFile, NULL, bufferPos, 2); trfprintf(pOutFile, "mov\t"); print(pOutFile, targetRegister, TR_WordReg); trfprintf(pOutFile, ", eax\t\t%s preserve helper return reg", commentString()); bufferPos += 2; } printPrefix(pOutFile, NULL, bufferPos, 3); trfprintf(pOutFile, "sub\tesp, 4\t\t%s push parameter", commentString()); bufferPos += 3; TR::X86RegRegInstruction *instr = snippet->getConvertInstruction()->getIA32RegRegInstruction(); if (instr) { printPrefix(pOutFile, NULL, bufferPos, 5); trfprintf(pOutFile, "movss\t dword ptr [esp], "); print(pOutFile, toRealRegister(instr->getSourceRegister()), TR_QuadWordReg); bufferPos += 5; } else { printPrefix(pOutFile, NULL, bufferPos, 3); trfprintf(pOutFile, "fst\tdword ptr [esp]"); bufferPos += 3; } printPrefix(pOutFile, NULL, bufferPos, 5); trfprintf(pOutFile, "call\t%s", getName(snippet->getHelperSymRef())); bufferPos += 5; printPrefix(pOutFile, NULL, bufferPos, 3); trfprintf(pOutFile, "add\tesp, 4\t\t%s pop parameter", commentString()); bufferPos += 3; if (reg != TR::RealRegister::eax) { printPrefix(pOutFile, NULL, bufferPos, 1); trfprintf(pOutFile, "xchg\teax, "); print(pOutFile, targetRegister, TR_WordReg); trfprintf(pOutFile, "\t\t%s restore eax", commentString()); bufferPos++; } printRestartJump(pOutFile, snippet, bufferPos); }
uint8_t *TR::X86FPConvertToIntSnippet::genFPConversion(uint8_t *buffer) { TR::ILOpCodes opcode = _convertInstruction->getNode()->getOpCodeValue(); TR::RealRegister *targetRegister = toRealRegister(_convertInstruction->getTargetRegister()); TR::RealRegister::RegNum targetReg = targetRegister->getRegisterNumber(); TR::Machine *machine = cg()->machine(); TR_ASSERT(cg()->getProperties().getIntegerReturnRegister() == TR::RealRegister::eax, "Only support integer return in eax"); if (targetReg != TR::RealRegister::eax) { // MOV R, eax // *buffer++ = 0x8b; *buffer = 0xc0; targetRegister->setRegisterFieldInModRM(buffer); buffer++; } // Push the floating-point value on to the stack before calling the helper. // // SUB esp, 4/8 // *buffer++ = 0x83; *buffer++ = 0xec; if (opcode == TR::f2i) *buffer++ = 0x04; else *buffer++ = 0x08; if (_convertInstruction->getIA32RegMemInstruction()) { // FST [esp], st0 // if (opcode == TR::f2i) *buffer++ = 0xd9; else *buffer++ = 0xdd; *buffer++ = 0x14; *buffer++ = 0x24; } else { TR::X86RegRegInstruction *instr = _convertInstruction->getIA32RegRegInstruction(); TR_ASSERT(instr != NULL, "f2i conversion instruction must be either L4RegMem or CVTTSS2SIRegReg\n"); TR::RealRegister *sourceRegister = toRealRegister(instr->getSourceRegister()); // MOVSS/MOVSD [esp], source // if (opcode == TR::f2i) *buffer++ = 0xf3; else *buffer++ = 0xf2; *buffer++ = 0x0f; *buffer++ = 0x11; *buffer = 0x04; sourceRegister->setRegisterFieldInModRM(buffer); buffer++; *buffer++ = 0x24; } // Call the helper // buffer = emitCallToConversionHelper(buffer); // ADD esp, 4/8 // *buffer++ = 0x83; *buffer++ = 0xc4; if (opcode == TR::f2i) *buffer++ = 0x04; else *buffer++ = 0x08; if (targetReg != TR::RealRegister::eax) { // XCHG R, eax // *buffer = 0x90; targetRegister->setRegisterFieldInOpcode(buffer); buffer++; } return buffer; }
void TR_ARMRegisterDependencyGroup::assignRegisters(TR::Instruction *currentInstruction, TR_RegisterKinds kindToBeAssigned, uint32_t numberOfRegisters, TR::CodeGenerator *cg) { TR::Compilation *comp = cg->comp(); TR::Machine *machine = cg->machine(); TR::Register *virtReg; TR::RealRegister::RegNum dependentRegNum; TR::RealRegister *dependentRealReg, *assignedRegister; uint32_t i, j; bool changed; if (!comp->getOption(TR_DisableOOL)) { for (i = 0; i< numberOfRegisters; i++) { virtReg = dependencies[i].getRegister(); dependentRegNum = dependencies[i].getRealRegister(); if (dependentRegNum == TR::RealRegister::SpilledReg) { TR_ASSERT(virtReg->getBackingStorage(),"should have a backing store if dependentRegNum == spillRegIndex()\n"); if (virtReg->getAssignedRealRegister()) { // this happens when the register was first spilled in main line path then was reverse spilled // and assigned to a real register in OOL path. We protected the backing store when doing // the reverse spill so we could re-spill to the same slot now traceMsg (comp,"\nOOL: Found register spilled in main line and re-assigned inside OOL"); TR::Node *currentNode = currentInstruction->getNode(); TR::RealRegister *assignedReg = toRealRegister(virtReg->getAssignedRegister()); TR::MemoryReference *tempMR = new (cg->trHeapMemory()) TR::MemoryReference(currentNode, (TR::SymbolReference*)virtReg->getBackingStorage()->getSymbolReference(), sizeof(uintptr_t), cg); TR_ARMOpCodes opCode; TR_RegisterKinds rk = virtReg->getKind(); switch (rk) { case TR_GPR: opCode = ARMOp_ldr; break; case TR_FPR: opCode = virtReg->isSinglePrecision() ? ARMOp_ldfs : ARMOp_ldfd; break; default: TR_ASSERT(0, "\nRegister kind not supported in OOL spill\n"); break; } TR::Instruction *inst = generateTrg1MemInstruction(cg, opCode, currentNode, assignedReg, tempMR, currentInstruction); assignedReg->setAssignedRegister(NULL); virtReg->setAssignedRegister(NULL); assignedReg->setState(TR::RealRegister::Free); if (comp->getDebug()) cg->traceRegisterAssignment("Generate reload of virt %s due to spillRegIndex dep at inst %p\n", cg->comp()->getDebug()->getName(virtReg),currentInstruction); cg->traceRAInstruction(inst); } if (!(std::find(cg->getSpilledRegisterList()->begin(), cg->getSpilledRegisterList()->end(), virtReg) != cg->getSpilledRegisterList()->end())) cg->getSpilledRegisterList()->push_front(virtReg); } // we also need to free up all locked backing storage if we are exiting the OOL during backwards RA assignment else if (currentInstruction->isLabel() && virtReg->getAssignedRealRegister()) { TR::ARMLabelInstruction *labelInstr = (TR::ARMLabelInstruction *)currentInstruction; TR_BackingStore *location = virtReg->getBackingStorage(); TR_RegisterKinds rk = virtReg->getKind(); int32_t dataSize; if (labelInstr->getLabelSymbol()->isStartOfColdInstructionStream() && location) { traceMsg (comp,"\nOOL: Releasing backing storage (%p)\n", location); if (rk == TR_GPR) dataSize = TR::Compiler->om.sizeofReferenceAddress(); else dataSize = 8; location->setMaxSpillDepth(0); cg->freeSpill(location,dataSize,0); virtReg->setBackingStorage(NULL); } } } } for (i = 0; i < numberOfRegisters; i++) { virtReg = dependencies[i].getRegister(); if (virtReg->getAssignedRealRegister()!=NULL) { if (dependencies[i].getRealRegister() == TR::RealRegister::NoReg) { virtReg->block(); } else { dependentRegNum = toRealRegister(virtReg->getAssignedRealRegister())->getRegisterNumber(); for (j=0; j<numberOfRegisters; j++) { if (dependentRegNum == dependencies[j].getRealRegister()) { virtReg->block(); break; } } } } } do { changed = false; for (i = 0; i < numberOfRegisters; i++) { virtReg = dependencies[i].getRegister(); dependentRegNum = dependencies[i].getRealRegister(); dependentRealReg = machine->getRealRegister(dependentRegNum); if (dependentRegNum != TR::RealRegister::NoReg && dependentRegNum != TR::RealRegister::SpilledReg && dependentRealReg->getState() == TR::RealRegister::Free) { machine->coerceRegisterAssignment(currentInstruction, virtReg, dependentRegNum); virtReg->block(); changed = true; } } } while (changed == true); do { changed = false; for (i = 0; i < numberOfRegisters; i++) { virtReg = dependencies[i].getRegister(); assignedRegister = NULL; if (virtReg->getAssignedRealRegister() != NULL) { assignedRegister = toRealRegister(virtReg->getAssignedRealRegister()); } dependentRegNum = dependencies[i].getRealRegister(); dependentRealReg = machine->getRealRegister(dependentRegNum); if (dependentRegNum != TR::RealRegister::NoReg && dependentRegNum != TR::RealRegister::SpilledReg && dependentRealReg != assignedRegister) { machine->coerceRegisterAssignment(currentInstruction, virtReg, dependentRegNum); virtReg->block(); changed = true; } } } while (changed == true); for (i=0; i<numberOfRegisters; i++) { if (dependencies[i].getRealRegister() == TR::RealRegister::NoReg) { bool excludeGPR0 = dependencies[i].getExcludeGPR0()?true:false; TR::RealRegister *realOne; virtReg = dependencies[i].getRegister(); realOne = virtReg->getAssignedRealRegister(); if (realOne!=NULL && excludeGPR0 && toRealRegister(realOne)->getRegisterNumber()==TR::RealRegister::gr0) { if ((assignedRegister = machine->findBestFreeRegister(virtReg->getKind(), true)) == NULL) { assignedRegister = machine->freeBestRegister(currentInstruction, virtReg->getKind(), NULL, true); } machine->coerceRegisterAssignment(currentInstruction, virtReg, assignedRegister->getRegisterNumber()); } else if (realOne == NULL) { if (virtReg->getTotalUseCount() == virtReg->getFutureUseCount()) { if ((assignedRegister = machine->findBestFreeRegister(virtReg->getKind(), excludeGPR0, true)) == NULL) { assignedRegister = machine->freeBestRegister(currentInstruction, virtReg->getKind(), NULL, excludeGPR0); } } else { assignedRegister = machine->reverseSpillState(currentInstruction, virtReg, NULL, excludeGPR0); } virtReg->setAssignedRegister(assignedRegister); assignedRegister->setAssignedRegister(virtReg); assignedRegister->setState(TR::RealRegister::Assigned); virtReg->block(); } } } unblockRegisters(numberOfRegisters); for (i = 0; i < numberOfRegisters; i++) { TR::Register *dependentRegister = getRegisterDependency(i)->getRegister(); if (dependentRegister->getAssignedRegister()) { TR::RealRegister *assignedRegister = dependentRegister->getAssignedRegister()->getRealRegister(); if (getRegisterDependency(i)->getRealRegister() == TR::RealRegister::NoReg) getRegisterDependency(i)->setRealRegister(toRealRegister(assignedRegister)->getRegisterNumber()); if (dependentRegister->decFutureUseCount() == 0) { dependentRegister->setAssignedRegister(NULL); assignedRegister->setAssignedRegister(NULL); assignedRegister->setState(TR::RealRegister::Unlatched); // Was setting to Free } } } }