Exemple #1
0
void TR::ARMSystemLinkage::createEpilogue(TR::Instruction *cursor)
   {
   TR::CodeGenerator *codeGen = cg();
   const TR::ARMLinkageProperties& properties = getProperties();
   TR::Machine *machine = codeGen->machine();
   TR::Node *lastNode = cursor->getNode();
   TR::ResolvedMethodSymbol* bodySymbol = comp()->getJittedMethodSymbol();
   TR::RealRegister *stackPtr = machine->getRealRegister(properties.getStackPointerRegister());

   // restore link register (r14)
   auto *stackSlot = new (trHeapMemory()) TR::MemoryReference(stackPtr, bodySymbol->getLocalMappingCursor(), codeGen);
   cursor = generateMemSrc1Instruction(cg(), ARMOp_ldr, lastNode, stackSlot, machine->getRealRegister(TR::RealRegister::gr14), cursor);

   // restore all preserved registers
   for (int r = TR::RealRegister::gr4; r <= TR::RealRegister::gr11; ++r)
      {
      auto *stackSlot = new (trHeapMemory()) TR::MemoryReference(stackPtr, (TR::RealRegister::gr11 - r + 1)*4 + bodySymbol->getLocalMappingCursor(), codeGen);
      cursor = generateMemSrc1Instruction(cg(), ARMOp_ldr, lastNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)r), cursor);
      }

   // remove space for preserved registers
   auto frameSize = codeGen->getFrameSizeInBytes();
   cursor = generateTrg1Src1ImmInstruction(codeGen, ARMOp_add, lastNode, stackPtr, stackPtr, frameSize, 0, cursor);

   // return using `mov r15, r14`
   TR::RealRegister *gr14 = machine->getRealRegister(TR::RealRegister::gr14);
   TR::RealRegister *gr15 = machine->getRealRegister(TR::RealRegister::gr15);
   cursor = generateTrg1Src1Instruction(codeGen, ARMOp_mov, lastNode, gr15, gr14, cursor);
   }
Exemple #2
0
void TR::ARM64Trg1Src2Instruction::assignRegisters(TR_RegisterKinds kindToBeAssigned)
   {
   TR::Machine *machine = cg()->machine();
   TR::Register *target1Virtual = getTargetRegister();
   TR::Register *source1Virtual = getSource1Register();
   TR::Register *source2Virtual = getSource2Register();

   if (getDependencyConditions())
      getDependencyConditions()->assignPostConditionRegisters(this, kindToBeAssigned, cg());

   source1Virtual->block();
   target1Virtual->block();
   TR::RealRegister *assignedSource2Register = machine->assignOneRegister(this, source2Virtual);
   target1Virtual->unblock();
   source1Virtual->unblock();

   source2Virtual->block();
   target1Virtual->block();
   TR::RealRegister *assignedSource1Register = machine->assignOneRegister(this, source1Virtual);
   target1Virtual->unblock();
   source2Virtual->unblock();

   source2Virtual->block();
   source1Virtual->block();
   TR::RealRegister *assignedTarget1Register = machine->assignOneRegister(this, target1Virtual);
   source1Virtual->unblock();
   source2Virtual->unblock();

   if (getDependencyConditions())
      getDependencyConditions()->assignPreConditionRegisters(this->getPrev(), kindToBeAssigned, cg());

   setTargetRegister(assignedTarget1Register);
   setSource1Register(assignedSource1Register);
   setSource2Register(assignedSource2Register);
   }
Exemple #3
0
void TR::ARM64MemSrc1Instruction::assignRegisters(TR_RegisterKinds kindToBeAssigned)
   {
   TR::Machine *machine = cg()->machine();
   TR::MemoryReference *mref = getMemoryReference();
   TR::Register *sourceVirtual = getSource1Register();

   if (getDependencyConditions())
      getDependencyConditions()->assignPostConditionRegisters(this, kindToBeAssigned, cg());

   sourceVirtual->block();
   mref->assignRegisters(this, cg());
   sourceVirtual->unblock();

   mref->blockRegisters();
   TR::RealRegister *assignedRegister = sourceVirtual->getAssignedRealRegister();
   if (assignedRegister == NULL)
      {
      assignedRegister = machine->assignOneRegister(this, sourceVirtual);
      }
   mref->unblockRegisters();

   setSource1Register(assignedRegister);

   if (getDependencyConditions())
      getDependencyConditions()->assignPreConditionRegisters(this->getPrev(), kindToBeAssigned, cg());
   }
Exemple #4
0
void TR::ARM64Trg1Instruction::assignRegisters(TR_RegisterKinds kindToBeAssigned)
   {
   if (getDependencyConditions())
      getDependencyConditions()->assignPostConditionRegisters(this, kindToBeAssigned, cg());

   TR::Machine *machine = cg()->machine();
   TR::Register *targetVirtual = getTargetRegister();
   setTargetRegister(machine->assignOneRegister(this, targetVirtual));

   if (getDependencyConditions())
      getDependencyConditions()->assignPreConditionRegisters(this->getPrev(), kindToBeAssigned, cg());
   }
Exemple #5
0
TR::MemoryReference *OMR::Power::Linkage::getOutgoingArgumentMemRef(int32_t argSize, TR::Register *argReg, TR::InstOpCode::Mnemonic opCode, TR::PPCMemoryArgument &memArg, uint32_t length)
   {
   TR::Machine *machine = self()->machine();
   const TR::PPCLinkageProperties& properties = self()->getProperties();

   TR::MemoryReference *result = new (self()->trHeapMemory()) TR::MemoryReference(machine->getRealRegister(properties.getNormalStackPointerRegister()),
                                                                              argSize+properties.getOffsetToFirstParm(), length, self()->cg());
   memArg.argRegister = argReg;
   memArg.argMemory = result;
   memArg.opCode = opCode;
   return(result);
   }
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() + 8; // +8 for LR
   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);
   TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, bodySymbol->getLocalMappingCursor(), 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_ASSERT(false, "Not implemented yet.");
      }

   // return
   cursor = generateRegBranchInstruction(codeGen, TR::InstOpCode::ret, lastNode, lr, cursor);
   }
Exemple #7
0
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);
   }
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;
      }
   }
Exemple #9
0
void TR::ARM64Trg1MemInstruction::assignRegisters(TR_RegisterKinds kindToBeAssigned)
   {
   TR::Machine *machine = cg()->machine();
   TR::MemoryReference *mref = getMemoryReference();
   TR::Register *targetVirtual = getTargetRegister();

   if (getDependencyConditions())
      getDependencyConditions()->assignPostConditionRegisters(this, kindToBeAssigned, cg());

   mref->blockRegisters();
   setTargetRegister(machine->assignOneRegister(this, targetVirtual));
   mref->unblockRegisters();

   targetVirtual->block();
   mref->assignRegisters(this, cg());
   targetVirtual->unblock();

   if (getDependencyConditions())
      getDependencyConditions()->assignPreConditionRegisters(this->getPrev(), kindToBeAssigned, cg());
   }
Exemple #10
0
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);
      }
   }
void OMR::Power::RegisterDependencyConditions::bookKeepingRegisterUses(TR::Instruction *instr, TR::CodeGenerator *cg)
   {
   // *this    swipeable for debugging purposes
   TR::Register *virtReg;
   TR::RealRegister::RegNum regNum;
   TR::RegisterDependencyConditions *assoc;
   int numAssoc = 0;

   if (instr->getOpCodeValue() == TR::InstOpCode::assocreg)
      return;

   // Don't track associations or emit assocregs in outlined code
   // Register assigner can save/restore associations across outlined sections properly, however no such mechanism exists for instruction selection
   // so we don't want these associations to clobber the associations that were set in main line code, which are more important
   // TODO: Fix this by saving/restoring the associations in swapInstructionListsWithCompilation()
   bool isOOL = cg->getIsInOOLSection();

   TR::Machine *machine = cg->machine();
   assoc = !isOOL ? new (cg->trHeapMemory()) TR::RegisterDependencyConditions(0,_addCursorForPre, cg->trMemory()) : 0;

   for (int i = 0; i < _addCursorForPre; i++)
      {
      virtReg = _preConditions->getRegisterDependency(i)->getRegister();
      regNum  = _preConditions->getRegisterDependency(i)->getRealRegister();

      if (!isOOL)
         {
         // Add to the association condition when the association is changed
         // from one virtual register to another
         if (machine->getVirtualAssociatedWithReal(regNum) != virtReg && machine->getVirtualAssociatedWithReal(regNum) != 0)
            {
            assoc->addPostCondition(machine->getVirtualAssociatedWithReal(regNum), regNum);
            numAssoc++;
            }
         // Keep track of the virtual register map to real registers!
         machine->setVirtualAssociatedWithReal(regNum, virtReg);
         }

      instr->useRegister(virtReg);

      if (!isOOL)
         {
         cg->setRealRegisterAssociation(virtReg, regNum);
         if (_preConditions->getRegisterDependency(i)->getExcludeGPR0())
            cg->addRealRegisterInterference(virtReg, TR::RealRegister::gr0);
         }
      }

   if (numAssoc > 0)
      {
      // Emit an AssocRegs instruction to track the previous association
      assoc->setNumPostConditions(numAssoc, cg->trMemory());
      generateDepInstruction(cg, TR::InstOpCode::assocreg, instr->getNode(), assoc, instr->getPrev());
      }

   for (int j = 0; j < _addCursorForPost; j++)
      {
      virtReg = _postConditions->getRegisterDependency(j)->getRegister();
      regNum  = _postConditions->getRegisterDependency(j)->getRealRegister();

      instr->useRegister(virtReg);

      if (!isOOL)
         {
         cg->setRealRegisterAssociation(virtReg, regNum);
         if (_postConditions->getRegisterDependency(j)->getExcludeGPR0())
	    cg->addRealRegisterInterference(virtReg, TR::RealRegister::gr0);
         }
      }
   }
Exemple #12
0
void OMR::X86::Instruction::assignRegisters(TR_RegisterKinds kindsToBeAssigned)
   {
   if (!self()->getDependencyConditions())
      {
      // Fast path when there are no dependency conditions.
      //
      return;
      }

   if (self()->getOpCodeValue() != ASSOCREGS)
      {
      self()->aboutToAssignRegDeps();

      if ((self()->cg()->getAssignmentDirection() == self()->cg()->Backward))
         {
         self()->getDependencyConditions()->assignPostConditionRegisters(self(), kindsToBeAssigned, self()->cg());
         self()->getDependencyConditions()->assignPreConditionRegisters(self(), kindsToBeAssigned, self()->cg());
         }
      else
         {
         self()->getDependencyConditions()->assignPreConditionRegisters(self()->getPrev(), kindsToBeAssigned, self()->cg());
         self()->getDependencyConditions()->assignPostConditionRegisters(self(), kindsToBeAssigned, self()->cg());
         }
      }
   else if ((self()->getOpCodeValue() == ASSOCREGS) && self()->cg()->enableRegisterAssociations())
      {
      if (kindsToBeAssigned & TR_GPR_Mask)
         {
         TR::Machine *machine = self()->cg()->machine();

         // First traverse the existing associations and remove them
         // so that they don't interfere with the new ones
         //
         for (int i = TR::RealRegister::FirstGPR;
              i <= TR::RealRegister::LastAssignableGPR;
              ++i)
            {
            // Skip non-assignable registers
            //
            if (machine->getX86RealRegister((TR::RealRegister::RegNum)i)->getState() == TR::RealRegister::Locked)
               continue;

            TR::Register *virtReg = machine->getVirtualAssociatedWithReal((TR::RealRegister::RegNum)i);
            if (virtReg)
               {
               virtReg->setAssociation(TR::RealRegister::NoReg);
               }
            }

         // Next loop through and set up the new associations (both on the machine
         // and by associating the virtual registers with their real dependencies)
         //
         TR_X86RegisterDependencyGroup *depGroup = self()->getDependencyConditions()->getPostConditions();
         for (int j = 0; j < self()->getDependencyConditions()->getNumPostConditions(); ++j)
            {
            TR::RegisterDependency  *dep = depGroup->getRegisterDependency(j);
            machine->setVirtualAssociatedWithReal(dep->getRealRegister(), dep->getRegister());
            }

         machine->setGPRWeightsFromAssociations();
         }
      }
   }
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);
   }
Exemple #14
0
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);
   }
Exemple #15
0
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);
   }
Exemple #16
0
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);
   }
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_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);
         }
      }
   }
Exemple #19
0
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;
         }
      }
   }
Exemple #20
0
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.");
         }
      }
   }
Exemple #21
0
uint8_t *
TR::S390CallSnippet::S390flushArgumentsToStack(uint8_t * buffer, TR::Node * callNode, int32_t argSize, TR::CodeGenerator * cg)
   {
   int32_t intArgNum = 0, floatArgNum = 0, offset;
   TR::Machine *machine = cg->machine();
   TR::Linkage * linkage = cg->getLinkage(callNode->getSymbol()->castToMethodSymbol()->getLinkageConvention());

   int32_t argStart = callNode->getFirstArgumentIndex();
   bool rightToLeft = linkage->getRightToLeft() &&
	  //we want the arguments for induceOSR to be passed from left to right as in any other non-helper call
      !callNode->getSymbolReference()->isOSRInductionHelper();
   if (rightToLeft)
      {
      offset = linkage->getOffsetToFirstParm();
      }
   else
      {
      offset = argSize + linkage->getOffsetToFirstParm();
      }

   for (int32_t i = argStart; i < callNode->getNumChildren(); i++)
      {
      TR::Node * child = callNode->getChild(i);
      switch (child->getDataType())
         {
         case TR::Int8:
         case TR::Int16:
         case TR::Int32:
            if (!rightToLeft)
               {
               offset -= TR::Compiler->target.is64Bit() ? 8 : 4;
               }
            if (intArgNum < linkage->getNumIntegerArgumentRegisters())
               {
               buffer = storeArgumentItem(TR::InstOpCode::ST, buffer,
                           machine->getRealRegister(linkage->getIntegerArgumentRegister(intArgNum)), offset, cg);
               }
            intArgNum++;

            if (rightToLeft)
               {
               offset += TR::Compiler->target.is64Bit() ? 8 : 4;
               }
            break;
         case TR::Address:
            if (!rightToLeft)
               {
               offset -= TR::Compiler->target.is64Bit() ? 8 : 4;
               }
            if (intArgNum < linkage->getNumIntegerArgumentRegisters())
               {
               buffer = storeArgumentItem(TR::InstOpCode::getStoreOpCode(), buffer,
                           machine->getRealRegister(linkage->getIntegerArgumentRegister(intArgNum)), offset, cg);
               }
            intArgNum++;

            if (rightToLeft)
               {
               offset += TR::Compiler->target.is64Bit() ? 8 : 4;
               }
            break;

         case TR::Int64:
            if (!rightToLeft)
               {
               offset -= (TR::Compiler->target.is64Bit() ? 16 : 8);
               }
            if (intArgNum < linkage->getNumIntegerArgumentRegisters())
               {
               if (TR::Compiler->target.is64Bit())
                  {
                  buffer = storeArgumentItem(TR::InstOpCode::STG, buffer,
                              machine->getRealRegister(linkage->getIntegerArgumentRegister(intArgNum)), offset, cg);
                  }
               else
                  {
                  buffer = storeArgumentItem(TR::InstOpCode::ST, buffer,
                              machine->getRealRegister(linkage->getIntegerArgumentRegister(intArgNum)), offset, cg);
                  if (intArgNum < linkage->getNumIntegerArgumentRegisters() - 1)
                     {
                     buffer = storeArgumentItem(TR::InstOpCode::ST, buffer,
                                 machine->getRealRegister(linkage->getIntegerArgumentRegister(intArgNum + 1)), offset + 4, cg);
                     }
                  }
               }
            intArgNum += TR::Compiler->target.is64Bit() ? 1 : 2;
            if (rightToLeft)
               {
               offset += TR::Compiler->target.is64Bit() ? 16 : 8;
               }
            break;

         case TR::Float:
            if (!rightToLeft)
               {
               offset -= TR::Compiler->target.is64Bit() ? 8 : 4;
               }
            if (floatArgNum < linkage->getNumFloatArgumentRegisters())
               {
               buffer = storeArgumentItem(TR::InstOpCode::STE, buffer,
                           machine->getRealRegister(linkage->getFloatArgumentRegister(floatArgNum)), offset, cg);
               }
            floatArgNum++;
            if (rightToLeft)
               {
               offset += TR::Compiler->target.is64Bit() ? 8 : 4;
               }
            break;

         case TR::Double:
            if (!rightToLeft)
               {
               offset -= TR::Compiler->target.is64Bit() ? 16 : 8;
               }
            if (floatArgNum < linkage->getNumFloatArgumentRegisters())
               {
               buffer = storeArgumentItem(TR::InstOpCode::STD, buffer,
                           machine->getRealRegister(linkage->getFloatArgumentRegister(floatArgNum)), offset, cg);
               }
            floatArgNum++;
            if (rightToLeft)
               {
               offset += TR::Compiler->target.is64Bit() ? 16 : 8;
               }
            break;
         }
      }

   return buffer;
   }
Exemple #22
0
// Copies parameters from where they enter the method (either on stack or in a
// linkage register) to their "home location" where the method body will expect
// to find them (either on stack or in a global register).
//
TR::Instruction *
TR::X86SystemLinkage::copyParametersToHomeLocation(TR::Instruction *cursor)
   {
   TR::Machine *machine = cg()->machine();
   TR::RealRegister *framePointer = machine->getX86RealRegister(TR::RealRegister::vfp);

   TR::ResolvedMethodSymbol             *bodySymbol = comp()->getJittedMethodSymbol();
   ListIterator<TR::ParameterSymbol>  paramIterator(&(bodySymbol->getParameterList()));
   TR::ParameterSymbol               *paramCursor;

   const TR::RealRegister::RegNum noReg = TR::RealRegister::NoReg;
   TR_ASSERT(noReg == 0, "noReg must be zero so zero-initializing movStatus will work");

   TR::MovStatus movStatus[TR::RealRegister::NumRegisters] = {{(TR::RealRegister::RegNum)0,(TR::RealRegister::RegNum)0,(TR_MovDataTypes)0}};

   // We must always do the stores first, then the reg-reg copies, then the
   // loads, so that we never clobber a register we will need later.  However,
   // the logic is simpler if we do the loads and stores in the same loop.
   // Therefore, we maintain a separate instruction cursor for the loads.
   //
   // We defer the initialization of loadCursor until we generate the first
   // load.  Otherwise, if we happen to generate some stores first, then the
   // store cursor would get ahead of the loadCursor, and the instructions
   // would end up in the wrong order despite our efforts.
   //
   TR::Instruction *loadCursor = NULL;

   // Phase 1: generate RegMem and MemReg movs, and collect information about
   // the required RegReg movs.
   //
   for (paramCursor = paramIterator.getFirst();
       paramCursor != NULL;
       paramCursor = paramIterator.getNext())
      {
      int8_t lri = paramCursor->getLinkageRegisterIndex();     // How the parameter enters the method
      TR::RealRegister::RegNum ai                              // Where method body expects to find it
         = (TR::RealRegister::RegNum)paramCursor->getAllocatedIndex();
      int32_t offset = paramCursor->getParameterOffset();      // Location of the parameter's stack slot
      TR_MovDataTypes movDataType = paramMovType(paramCursor); // What sort of MOV instruction does it need?

      // Copy the parameter to wherever it should be
      //
      if (lri == NOT_LINKAGE) // It's on the stack
         {
         if (ai == NOT_ASSIGNED) // It only needs to be on the stack
            {
            // Nothing to do
            }
         else // Method body expects it to be in the ai register
            {
            if (loadCursor == NULL)
               loadCursor = cursor;

            if (debug("traceCopyParametersToHomeLocation"))
               diagnostic("copyParametersToHomeLocation: Loading %d\n", ai);
            // ai := stack
            loadCursor = generateRegMemInstruction(
               loadCursor,
               TR::Linkage::movOpcodes(RegMem, movDataType),
               machine->getX86RealRegister(ai),
               generateX86MemoryReference(framePointer, offset, cg()),
               cg()
               );
            }
         }
      else // It's in a linkage register
         {
         TR::RealRegister::RegNum sourceIndex = getProperties().getArgumentRegister(lri, isFloat(movDataType));

         // Copy to the stack if necessary
         //
         if (ai == NOT_ASSIGNED || hasToBeOnStack(paramCursor))
            {
            if (comp()->getOption(TR_TraceCG))
              traceMsg(comp(), "copyToHomeLocation param %p, linkage reg index %d, allocated index %d, parameter offset %d, hasToBeOnStack %d, parm->isParmHasToBeOnStack() %d.\n", paramCursor, lri, ai, offset, hasToBeOnStack(paramCursor), paramCursor->isParmHasToBeOnStack());
            if (debug("traceCopyParametersToHomeLocation"))
               diagnostic("copyParametersToHomeLocation: Storing %d\n", sourceIndex);
            // stack := lri
            cursor = generateMemRegInstruction(
               cursor,
               TR::Linkage::movOpcodes(MemReg, movDataType),
               generateX86MemoryReference(framePointer, offset, cg()),
               machine->getX86RealRegister(sourceIndex),
               cg()
               );
            }

         // Copy to the ai register if necessary
         //
         if (ai != NOT_ASSIGNED && ai != sourceIndex)
            {
            // This parameter needs a RegReg move.  We don't know yet whether
            // we need the value in the target register, so for now we just
            // remember that we need to do this and keep going.
            //
            TR_ASSERT(movStatus[ai         ].sourceReg == noReg, "Each target reg must have only one source");
            TR_ASSERT(movStatus[sourceIndex].targetReg == noReg, "Each source reg must have only one target");
            if (debug("traceCopyParametersToHomeLocation"))
               diagnostic("copyParametersToHomeLocation: Planning to move %d to %d\n", sourceIndex, ai);
            movStatus[ai].sourceReg                  = sourceIndex;
            movStatus[sourceIndex].targetReg         = ai;
            movStatus[sourceIndex].outgoingDataType  = movDataType;
            }

         if (debug("traceCopyParametersToHomeLocation") && ai == sourceIndex)
            {
            diagnostic("copyParametersToHomeLocation: Parameter #%d already in register %d\n", lri, ai);
            }
         }
      }

   // Phase 2: Iterate through the parameters again to insert the RegReg moves.
   //
   for (paramCursor = paramIterator.getFirst();
       paramCursor != NULL;
       paramCursor = paramIterator.getNext())
      {
      if (paramCursor->getLinkageRegisterIndex() == NOT_LINKAGE)
         continue;

      const TR::RealRegister::RegNum paramReg =
         getProperties().getArgumentRegister(paramCursor->getLinkageRegisterIndex(), isFloat(paramMovType(paramCursor)));

      if (movStatus[paramReg].targetReg == 0)
         {
         // This parameter does not need to be copied anywhere
         if (debug("traceCopyParametersToHomeLocation"))
            diagnostic("copyParametersToHomeLocation: Not moving %d\n", paramReg);
         }
      else
         {
         if (debug("traceCopyParametersToHomeLocation"))
            diagnostic("copyParametersToHomeLocation: Preparing to move %d\n", paramReg);

         // If a mov's target register is the source for another mov, we need
         // to do that other mov first.  The idea is to find the end point of
         // the chain of movs starting with paramReg and ending with a
         // register whose current value is not needed; then do that chain of
         // movs in reverse order.
         //
         TR_ASSERT(noReg == 0, "noReg must be zero (not %d) for zero-filled initialization to work", noReg);

         TR::RealRegister::RegNum regCursor;

         // Find the last target in the chain
         //
         regCursor = movStatus[paramReg].targetReg;
         while(movStatus[regCursor].targetReg != noReg)
            {
            // Haven't found the end yet
            regCursor = movStatus[regCursor].targetReg;
            TR_ASSERT(regCursor != paramReg, "Can't yet handle cyclic dependencies");

            // TODO:AMD64 Use scratch register to break cycles
            // A properly-written pickRegister should never
            // cause cycles to occur in the first place.  However, we may want
            // to consider adding cycle-breaking logic so that (1) pickRegister
            // has more flexibility, and (2) we're more robust against
            // otherwise harmless bugs in pickRegister.
            }

         // Work our way backward along the chain, generating all the necessary movs
         //
         while(movStatus[regCursor].sourceReg != noReg)
            {
            TR::RealRegister::RegNum source = movStatus[regCursor].sourceReg;
            if (debug("traceCopyParametersToHomeLocation"))
               diagnostic("copyParametersToHomeLocation: Moving %d to %d\n", source, regCursor);
            // regCursor := regCursor.sourceReg
            cursor = generateRegRegInstruction(
               cursor,
               TR::Linkage::movOpcodes(RegReg, movStatus[source].outgoingDataType),
               machine->getX86RealRegister(regCursor),
               machine->getX86RealRegister(source),
               cg()
               );
            // Update movStatus as we go so we don't generate redundant movs
            movStatus[regCursor].sourceReg = noReg;
            movStatus[source   ].targetReg = noReg;
            // Continue with the next register in the chain
            regCursor = source;
            }
         }
      }

   // Return the last instruction we inserted, whether or not it was a load.
   //
   return loadCursor? loadCursor : cursor;
   }
Exemple #23
0
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
            }
         }
      }
   }