Ejemplo n.º 1
0
uint32_t TR::AMD64FPConversionSnippet::getLength(int32_t estimatedSnippetStart)
   {
   // *this    swipeable for debugging purposes
   uint32_t length = 11;
   TR::Machine *machine = cg()->machine();


   if (toRealRegister(_convertInstruction->getTargetRegister())->getRegisterNumber() != TR::RealRegister::eax)
      {
      // MOV   R, rax
      // XCHG  R, rax
      //
      // 3 instruction/modRM bytes + 2 REX prefixes
      //
      length += (3 + 2);
      }

   TR::X86RegRegInstruction *instr = _convertInstruction->getIA32RegRegInstruction();
   TR_ASSERT(instr != NULL, "f2i conversion instruction must be either L4RegMem or CVTTSS2SIRegReg\n");
   TR::RealRegister *sourceRegister = toRealRegister(instr->getSourceRegister());
   if (sourceRegister->getRegisterNumber() != TR::RealRegister::xmm0)
      {
      length +=
           sizeof(pushBinary) + sizeof(popBinary)             // push and pop
         + 4 + (sourceRegister->rexBits(TR::RealRegister::REX_B, false)? 1 : 0) // MOVSD xmm0, source
         ;
      }

   return length + estimateRestartJumpLength(estimatedSnippetStart + length);
   }
Ejemplo n.º 2
0
uint32_t TR::X86FPConvertToIntSnippet::getLength(int32_t estimatedSnippetStart)
   {
   uint32_t length = 11;
   TR::Machine * machine = cg()->machine();


   if (toRealRegister(_convertInstruction->getTargetRegister())->getRegisterNumber() != TR::RealRegister::eax)
      {
      // MOV   R, eax
      // XCHG  R, eax
      //
      length += 3;
      }

   if (_convertInstruction->getIA32RegMemInstruction())
      {
      // FST [esp], st0
      length += 3;
      }
   else
      {
      // MOVSS [esp], R
      length += 5;
      }

   return length + estimateRestartJumpLength(estimatedSnippetStart + length);
   }
Ejemplo n.º 3
0
uint8_t *TR::PPCTrg1Src1Instruction::generateBinaryEncoding()
   {
   uint8_t *instructionStart = cg()->getBinaryBufferCursor();
   uint8_t *cursor           = instructionStart;

   if (isRegCopy() && (toRealRegister(getTargetRegister()) == toRealRegister(getSource1Register())))
      {
      }
   else
      {
      cursor = getOpCode().copyBinaryToBuffer(instructionStart);
      insertTargetRegister(toPPCCursor(cursor));
      insertSource1Register(toPPCCursor(cursor));
      cursor += PPC_INSTRUCTION_LENGTH;
      }
   setBinaryLength(cursor - instructionStart);
   cg()->addAccumulatedInstructionLengthError(getEstimatedBinaryLength() - getBinaryLength());
   setBinaryEncoding(instructionStart);
   return cursor;
   }
Ejemplo n.º 4
0
void TR::X86FPConvertToLongSnippet::analyseLongConversion()
   {
   // The current assumption is that register assignment will occur prior
   // to the snippets being sized and emitted.
   //
   TR_ASSERT(((_loadHighInstruction && _loadHighInstruction->getTargetRegister()) &&
            (_loadLowInstruction && _loadLowInstruction->getTargetRegister()) &&
            (_clobberInstruction && _clobberInstruction->getSourceRegister())),
           "analyseLongConversion() ==> register assignment is a prerequisite!\n");

   _action = 0;

   _lowRegister = toRealRegister(_loadLowInstruction->getTargetRegister());
   _highRegister = toRealRegister(_loadHighInstruction->getTargetRegister());
   _doubleRegister = toRealRegister(_clobberInstruction->getSourceRegister());

   TR::Machine * machine = cg()->machine();

   _action |= ((_doubleRegister->getRegisterNumber() != TR::RealRegister::st0) << 7);
   _action |= ((_lowRegister->getRegisterNumber() == TR::RealRegister::eax) << 3);
   _action |= ((_lowRegister->getRegisterNumber() == TR::RealRegister::edx) << 2);
   _action |= ((_highRegister->getRegisterNumber() == TR::RealRegister::eax) << 1);
   _action |= (_highRegister->getRegisterNumber() == TR::RealRegister::edx);
   }
Ejemplo n.º 5
0
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;
      }
   }
Ejemplo n.º 6
0
 // Initialize the LUTs using this (we don't do it in the ctor because
 // in many places we already traverse the dep list and we can call
 // this method there and save an extra loop).
 void addDependency(TR::RegisterDependency& dep, uint32_t index)
    {
    TR_ASSERT(&deps[index] == &dep, "Dep pointer/index mismatch");
    TR::RealRegister::RegNum rr = dep.getRealRegister();
    if (rr != TR::RealRegister::NoReg && rr != TR::RealRegister::SpilledReg)
       {
       TR_ASSERT(rr >= 0 && rr < TR::RealRegister::NumRegisters, "Register number %d used as index but out of range", rr);
       TR_ASSERT(targetTable[rr] == MAP_NIL || // TODO: Figure out where the same dep is being added more than once!
              deps[targetTable[rr]].getRegister() == deps[index].getRegister(),
              "Multiple virtual registers depend on a single real register %d", rr);
       targetTable[rr] = index;
       }
    TR::RealRegister *assignedReg = dep.getRegister()->getAssignedRealRegister();
    if (assignedReg)
       {
       rr = toRealRegister(assignedReg)->getRegisterNumber();
       TR_ASSERT(rr >= 0 && rr < TR::RealRegister::NumRegisters, "Register number %d used as index but out of range", rr);
       TR_ASSERT(assignedTable[rr] == MAP_NIL || // TODO: Figure out where the same dep is being added more than once!
              deps[assignedTable[rr]].getRegister() == deps[index].getRegister(),
              "Multiple virtual registers assigned to a single real register %d", rr);
       assignedTable[rr] = index;
       }
    }
Ejemplo n.º 7
0
TR::Register *OMR::X86::AMD64::TreeEvaluator::l2dEvaluator(TR::Node *node, TR::CodeGenerator *cg)
   {
   return l2fd(node, toRealRegister(cg->allocateRegister(TR_FPR)), CVTSI2SDRegMem8, CVTSI2SDRegReg8, cg);
   }
Ejemplo n.º 8
0
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);
         }
      }
   }
Ejemplo n.º 9
0
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;
      }

   }
Ejemplo n.º 10
0
uint8_t *TR::X86FPConvertToIntSnippet::genFPConversion(uint8_t *buffer)
   {
   TR::ILOpCodes              opcode          = _convertInstruction->getNode()->getOpCodeValue();
   TR::RealRegister          *targetRegister  = toRealRegister(_convertInstruction->getTargetRegister());
   TR::RealRegister::RegNum   targetReg       = targetRegister->getRegisterNumber();

   TR::Machine *machine = cg()->machine();

   TR_ASSERT(cg()->getProperties().getIntegerReturnRegister() == TR::RealRegister::eax, "Only support integer return in eax");

   if (targetReg != TR::RealRegister::eax)
      {
      // MOV R, eax
      //
      *buffer++ = 0x8b;
      *buffer = 0xc0;
      targetRegister->setRegisterFieldInModRM(buffer);
      buffer++;
      }

   // Push the floating-point value on to the stack before calling the helper.
   //
   // SUB esp, 4/8
   //
   *buffer++ = 0x83;
   *buffer++ = 0xec;
   if (opcode == TR::f2i)
      *buffer++ = 0x04;
   else
      *buffer++ = 0x08;

   if (_convertInstruction->getIA32RegMemInstruction())
      {
      // FST [esp], st0
      //
      if (opcode == TR::f2i)
         *buffer++ = 0xd9;
      else
         *buffer++ = 0xdd;
      *buffer++ = 0x14;
      *buffer++ = 0x24;
      }
   else
      {
      TR::X86RegRegInstruction  *instr = _convertInstruction->getIA32RegRegInstruction();
      TR_ASSERT(instr != NULL, "f2i conversion instruction must be either L4RegMem or CVTTSS2SIRegReg\n");

      TR::RealRegister *sourceRegister = toRealRegister(instr->getSourceRegister());

      // MOVSS/MOVSD [esp], source
      //
      if (opcode == TR::f2i)
         *buffer++ = 0xf3;
      else
         *buffer++ = 0xf2;
      *buffer++ = 0x0f;
      *buffer++ = 0x11;
      *buffer = 0x04;
      sourceRegister->setRegisterFieldInModRM(buffer);
      buffer++;
      *buffer++ = 0x24;
      }

   // Call the helper
   //
   buffer = emitCallToConversionHelper(buffer);

   // ADD esp, 4/8
   //
   *buffer++ = 0x83;
   *buffer++ = 0xc4;
   if (opcode == TR::f2i)
      *buffer++ = 0x04;
   else
      *buffer++ = 0x08;

   if (targetReg != TR::RealRegister::eax)
      {
      // XCHG R, eax
      //
      *buffer = 0x90;
      targetRegister->setRegisterFieldInOpcode(buffer);
      buffer++;
      }

   return buffer;
   }
Ejemplo n.º 11
0
void
TR_Debug::print(TR::FILE *pOutFile, TR::X86FPConvertToIntSnippet  * snippet)
   {
   if (pOutFile == NULL)
      return;

   uint8_t *bufferPos = snippet->getSnippetLabel()->getCodeLocation();

   printSnippetLabel(pOutFile, snippet->getSnippetLabel(), bufferPos, getName(snippet));

   TR::RealRegister *targetRegister = toRealRegister(snippet->getConvertInstruction()->getTargetRegister());
   uint8_t              reg = targetRegister->getRegisterNumber();

   if (reg != TR::RealRegister::eax)
      {
      printPrefix(pOutFile, NULL, bufferPos, 2);
      trfprintf(pOutFile, "mov\t");
      print(pOutFile, targetRegister, TR_WordReg);
      trfprintf(pOutFile, ", eax\t\t%s preserve helper return reg",
                    commentString());
      bufferPos += 2;
      }

   printPrefix(pOutFile, NULL, bufferPos, 3);
   trfprintf(pOutFile, "sub\tesp, 4\t\t%s push parameter",
                 commentString());
   bufferPos += 3;

   TR::X86RegRegInstruction  *instr = snippet->getConvertInstruction()->getIA32RegRegInstruction();

   if (instr)
      {
      printPrefix(pOutFile, NULL, bufferPos, 5);
      trfprintf(pOutFile, "movss\t dword ptr [esp], ");
      print(pOutFile, toRealRegister(instr->getSourceRegister()), TR_QuadWordReg);
      bufferPos += 5;
      }
   else
      {
      printPrefix(pOutFile, NULL, bufferPos, 3);
      trfprintf(pOutFile, "fst\tdword ptr [esp]");
      bufferPos += 3;
      }

   printPrefix(pOutFile, NULL, bufferPos, 5);
   trfprintf(pOutFile, "call\t%s", getName(snippet->getHelperSymRef()));
   bufferPos += 5;

   printPrefix(pOutFile, NULL, bufferPos, 3);
   trfprintf(pOutFile, "add\tesp, 4\t\t%s pop parameter",
                 commentString());
   bufferPos += 3;

   if (reg != TR::RealRegister::eax)
      {
      printPrefix(pOutFile, NULL, bufferPos, 1);
      trfprintf(pOutFile, "xchg\teax, ");
      print(pOutFile, targetRegister, TR_WordReg);
      trfprintf(pOutFile, "\t\t%s restore eax",
                    commentString());
      bufferPos++;
      }

   printRestartJump(pOutFile, snippet, bufferPos);
   }
Ejemplo n.º 12
0
uint8_t *TR::AMD64FPConversionSnippet::genFPConversion(uint8_t *buffer)
   {
   // *this    swipeable for debugging purposes

   // This didn't end up as clean as I thought.  TODO:AMD64: Separate out the 64-bit code into another class.

   TR::ILOpCodes              opCode          = _convertInstruction->getNode()->getOpCodeValue();
   TR::RealRegister          *targetRegister  = toRealRegister(_convertInstruction->getTargetRegister());
   TR::RealRegister::RegNum   targetReg       = targetRegister->getRegisterNumber();
   TR::Machine               *machine         = cg()->machine();
   const TR::X86LinkageProperties &properties = cg()->getProperties();

   uint8_t *originalBuffer = buffer;

   TR_ASSERT(properties.getIntegerReturnRegister() == TR::RealRegister::eax, "Only support integer return in eax");

   if (targetReg != TR::RealRegister::eax)
      {
      // MOV R, rax
      //
      *buffer++ = TR::RealRegister::REX | TR::RealRegister::REX_W | targetRegister->rexBits(TR::RealRegister::REX_R, false);
      *buffer++ = 0x8b;
      *buffer = 0xc0;
      targetRegister->setRegisterFieldInModRM(buffer);
      buffer++;
      }

   TR_ASSERT(properties.getFloatArgumentRegister(0) == TR::RealRegister::xmm0, "Only support 1st FP arg in xmm0");
   TR::X86RegRegInstruction *instr = _convertInstruction->getIA32RegRegInstruction();
   TR_ASSERT(instr != NULL, "conversion instruction must be CVTTSS2SIRegReg\n");

   TR::RealRegister         *sourceRegister = toRealRegister(instr->getSourceRegister());
   TR::RealRegister::RegNum  sourceReg      = sourceRegister->getRegisterNumber();

   // Save xmm0 if necessary
   //
   if (sourceReg != TR::RealRegister::xmm0)
      {
      TR_ASSERT(TR::Compiler->target.is64Bit(), "This push sequence only works on AMD64");
      memcpy(buffer, pushBinary, sizeof(pushBinary));
      buffer += sizeof(pushBinary);

      // MOVSD xmm0, source
      //
      *buffer++ = 0xf2;
      if( (*buffer = sourceRegister->rexBits(TR::RealRegister::REX_B, false)) )
         buffer++;
      *buffer++ = 0x0f;
      *buffer++ = 0x10;
      *buffer   = 0xc0;
      sourceRegister->setRegisterFieldInOpcode(buffer);
      buffer++;
      }

   // Call the helper
   //
   buffer = emitCallToConversionHelper(buffer);

   // Restore xmm0 if necessary
   //
   if (sourceReg != TR::RealRegister::xmm0)
      {
      TR_ASSERT(TR::Compiler->target.is64Bit(), "This pop sequence only works on AMD64");
      memcpy(buffer, popBinary, sizeof(popBinary));
      buffer += sizeof(popBinary);
      }

   if (targetReg != TR::RealRegister::eax)
      {
      // XCHG R, rax
      //
      *buffer++ = TR::RealRegister::REX | TR::RealRegister::REX_W | targetRegister->rexBits(TR::RealRegister::REX_B, false);
      *buffer = 0x90;
      targetRegister->setRegisterFieldInOpcode(buffer);
      buffer++;
      }

   return buffer;
   }
Ejemplo n.º 13
0
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);
   }
Ejemplo n.º 14
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
            }
         }
      }
   }