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; }
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; } }