Ejemplo n.º 1
0
static TR::Register *addOrSubInteger(TR::Node *node, TR::CodeGenerator *cg)
   {
   TR::Node *firstChild = node->getFirstChild();
   TR::Register *src1Reg = cg->evaluate(firstChild);
   TR::Node *secondChild = node->getSecondChild();
   TR::Register *trgReg = cg->allocateRegister();
   bool isAdd = node->getOpCode().isAdd();

   if (secondChild->getOpCode().isLoadConst() && secondChild->getRegister() == NULL)
      {
      int32_t value = secondChild->getInt();
      if (constantIsUnsignedImm12(value))
         {
         generateTrg1Src1ImmInstruction(cg, isAdd ? TR::InstOpCode::addimmw : TR::InstOpCode::subimmw, node, trgReg, src1Reg, value);
         }
      else
         {
         TR::Register *tmpReg = cg->allocateRegister();
         loadConstant32(cg, node, value, tmpReg);
         generateTrg1Src2Instruction(cg, isAdd ? TR::InstOpCode::addw : TR::InstOpCode::subw, node, trgReg, src1Reg, tmpReg);
         cg->stopUsingRegister(tmpReg);
         }
      }
   else
      {
      TR::Register *src2Reg = cg->evaluate(secondChild);
      generateTrg1Src2Instruction(cg, isAdd ? TR::InstOpCode::addw : TR::InstOpCode::subw, node, trgReg, src1Reg, src2Reg);
      }

   node->setRegister(trgReg);
   firstChild->decReferenceCount();
   secondChild->decReferenceCount();
   return trgReg;
   }
Ejemplo n.º 2
0
TR::Register *
OMR::ARM64::TreeEvaluator::lmulhEvaluator(TR::Node *node, TR::CodeGenerator *cg)
   {
   TR::Node *firstChild = node->getFirstChild();
   TR::Register *src1Reg = cg->evaluate(firstChild);
   TR::Node *secondChild = node->getSecondChild();
   TR::Register *src2Reg;
   TR::Register *trgReg = cg->allocateRegister();
   TR::Register *tmpReg = NULL;

   // lmulh is generated for constant ldiv and the second child is the magic number
   // assume magic number is usually a large odd number with little optimization opportunity
   if (secondChild->getOpCode().isLoadConst() && secondChild->getRegister() == NULL)
      {
      int64_t value = secondChild->getLongInt();
      src2Reg = tmpReg = cg->allocateRegister();
      loadConstant64(cg, node, value, src2Reg);
      }
   else
      {
      src2Reg = cg->evaluate(secondChild);
      }

   generateTrg1Src2Instruction(cg, TR::InstOpCode::smulh, node, trgReg, src1Reg, src2Reg);

   if (tmpReg)
      {
      cg->stopUsingRegister(tmpReg);
      }

   firstChild->decReferenceCount();
   secondChild->decReferenceCount();
   node->setRegister(trgReg);
   return trgReg;
   }
Ejemplo n.º 3
0
static TR::Register *shiftHelper(TR::Node *node, TR::ARM64ShiftCode shiftType, TR::CodeGenerator *cg)
   {
   TR::Node *firstChild = node->getFirstChild();
   TR::Node *secondChild = node->getSecondChild();
   TR::ILOpCodes secondOp = secondChild->getOpCodeValue();
   TR::Register *srcReg = cg->evaluate(firstChild);
   TR::Register *trgReg = cg->allocateRegister();
   bool is64bit = node->getDataType().isInt64();
   TR::InstOpCode::Mnemonic op;

   if (secondOp == TR::iconst || secondOp == TR::iuconst)
      {
      int32_t value = secondChild->getInt();
      uint32_t shift = is64bit ? (value & 0x3F) : (value & 0x1F);
      switch (shiftType)
         {
         case TR::SH_LSL:
            generateLogicalShiftLeftImmInstruction(cg, node, trgReg, srcReg, shift);
            break;
         case TR::SH_LSR:
            generateLogicalShiftRightImmInstruction(cg, node, trgReg, srcReg, shift);
            break;
         case TR::SH_ASR:
            generateArithmeticShiftRightImmInstruction(cg, node, trgReg, srcReg, shift);
            break;
         default:
            TR_ASSERT(false, "Unsupported shift type.");
         }
      }
   else
      {
      TR::Register *shiftAmountReg = cg->evaluate(secondChild);
      switch (shiftType)
         {
         case TR::SH_LSL:
            op = is64bit ? TR::InstOpCode::lslvx : TR::InstOpCode::lslvw;
            break;
         case TR::SH_LSR:
            op = is64bit ? TR::InstOpCode::lsrvx : TR::InstOpCode::lsrvw;
            break;
         case TR::SH_ASR:
            op = is64bit ? TR::InstOpCode::asrvx : TR::InstOpCode::asrvw;
            break;
         default:
            TR_ASSERT(false, "Unsupported shift type.");
         }
      generateTrg1Src2Instruction(cg, op, node, trgReg, srcReg, shiftAmountReg);
      }

   node->setRegister(trgReg);
   firstChild->decReferenceCount();
   secondChild->decReferenceCount();
   return trgReg;
   }
Ejemplo n.º 4
0
static TR::Register *idivHelper(TR::Node *node, bool is64bit, TR::CodeGenerator *cg)
   {
   // TODO: Add checks for special cases

   TR::Node *firstChild = node->getFirstChild();
   TR::Register *src1Reg = cg->evaluate(firstChild);
   TR::Node *secondChild = node->getSecondChild();
   TR::Register *src2Reg = cg->evaluate(secondChild);
   TR::Register *trgReg = cg->allocateRegister();

   generateTrg1Src2Instruction(cg, is64bit ? TR::InstOpCode::sdivx : TR::InstOpCode::sdivw, node, trgReg, src1Reg, src2Reg);

   firstChild->decReferenceCount();
   secondChild->decReferenceCount();
   node->setRegister(trgReg);
   return trgReg;
   }
Ejemplo n.º 5
0
// also handles lrol
TR::Register *
OMR::ARM64::TreeEvaluator::irolEvaluator(TR::Node *node, TR::CodeGenerator *cg)
   {
   TR::Node *firstChild = node->getFirstChild();
   TR::Node *secondChild = node->getSecondChild();
   TR::Register *trgReg = cg->gprClobberEvaluate(firstChild);
   bool is64bit = node->getDataType().isInt64();
   TR::InstOpCode::Mnemonic op;

   if (secondChild->getOpCode().isLoadConst())
      {
      int32_t value = secondChild->getInt();
      uint32_t shift = is64bit ? (value & 0x3F) : (value & 0x1F);

      if (shift != 0)
         {
         shift = is64bit ? (64 - shift) : (32 - shift); // change ROL to ROR
         op = is64bit ? TR::InstOpCode::extrx : TR::InstOpCode::extrw; // ROR is an alias of EXTR
         generateTrg1Src2ShiftedInstruction(cg, op, node, trgReg, trgReg, trgReg, TR::SH_LSL, shift);
         }
      }
   else
      {
      TR::Register *shiftAmountReg = cg->evaluate(secondChild);
      generateNegInstruction(cg, node, shiftAmountReg, shiftAmountReg); // change ROL to ROR
      if (is64bit)
         {
         // 32->64 bit sign extension: SXTW is alias of SBFM
         uint32_t imm = 0x101F; // N=1, immr=0, imms=31
         generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::sbfmx, node, shiftAmountReg, shiftAmountReg, imm);
         }
      op = is64bit ? TR::InstOpCode::rorvx : TR::InstOpCode::rorvw;
      generateTrg1Src2Instruction(cg, op, node, trgReg, trgReg, shiftAmountReg);
      }

   node->setRegister(trgReg);
   firstChild->decReferenceCount();
   secondChild->decReferenceCount();
   return trgReg;
   }
Ejemplo n.º 6
0
OMR::Power::RegisterDependencyConditions::RegisterDependencyConditions(
                                       TR::CodeGenerator *cg,
                                       TR::Node          *node,
                                       uint32_t          extranum,
                                       TR::Instruction  **cursorPtr)
   {
   List<TR::Register>  regList(cg->trMemory());
   TR::Instruction    *iCursor = (cursorPtr==NULL)?NULL:*cursorPtr;
   int32_t totalNum = node->getNumChildren() + extranum;
   int32_t i;


   cg->comp()->incVisitCount();

   int32_t numLongs = 0;
   //
   // Pre-compute how many longs are global register candidates
   //
   for (i = 0; i < node->getNumChildren(); ++i)
      {
      TR::Node     *child = node->getChild(i);
      TR::Register *reg   = child->getRegister();

      if (reg!=NULL /* && reg->getKind()==TR_GPR */)
	 {
	 if (child->getHighGlobalRegisterNumber() > -1)
	    numLongs++;
	 }
      }

   totalNum = totalNum + numLongs;

   _preConditions = new (totalNum, cg->trMemory()) TR_PPCRegisterDependencyGroup;
   _postConditions = new (totalNum, cg->trMemory()) TR_PPCRegisterDependencyGroup;
   _numPreConditions = totalNum;
   _addCursorForPre = 0;
   _numPostConditions = totalNum;
   _addCursorForPost = 0;

   // First, handle dependencies that match current association
   for (i=0; i<node->getNumChildren(); i++)
      {
      TR::Node *child = node->getChild(i);
      TR::Register *reg = child->getRegister();
      TR::Register *highReg = NULL;
      TR::RealRegister::RegNum regNum = (TR::RealRegister::RegNum)cg->getGlobalRegister(child->getGlobalRegisterNumber());

      TR::RealRegister::RegNum highRegNum;

      if (child->getHighGlobalRegisterNumber() > -1)
         {
         highRegNum = (TR::RealRegister::RegNum)cg->getGlobalRegister(child->getHighGlobalRegisterNumber());

         TR::RegisterPair *regPair = reg->getRegisterPair();
         TR_ASSERT(regPair, "assertion failure");
	 highReg = regPair->getHighOrder();
	 reg = regPair->getLowOrder();

         if (highReg->getAssociation() != highRegNum ||
             reg->getAssociation() != regNum)
            continue;
         }
      else if (reg->getAssociation() != regNum)
         continue;

      TR_ASSERT(!regList.find(reg) && (!highReg || !regList.find(highReg)), "Should not happen\n");

      addPreCondition(reg, regNum);
      addPostCondition(reg, regNum);
      regList.add(reg);

      if (highReg)
	 {
	 addPreCondition(highReg, highRegNum);
	 addPostCondition(highReg, highRegNum);
         regList.add(highReg);
	 }
      }


   // Second pass to handle dependencies for which association does not exist
   // or does not match
   for (i=0; i<node->getNumChildren(); i++)
      {
      TR::Node *child = node->getChild(i);
      TR::Register *reg = child->getRegister();
      TR::Register *highReg = NULL;
      TR::Register *copyReg = NULL;
      TR::Register *highCopyReg = NULL;
      TR::RealRegister::RegNum regNum = (TR::RealRegister::RegNum)cg->getGlobalRegister(child->getGlobalRegisterNumber());


      TR::RealRegister::RegNum highRegNum;

      if (child->getHighGlobalRegisterNumber() > -1)
         {
         highRegNum = (TR::RealRegister::RegNum)cg->getGlobalRegister(child->getHighGlobalRegisterNumber());
         TR::RegisterPair *regPair = reg->getRegisterPair();
         TR_ASSERT(regPair, "assertion failure");
	 highReg = regPair->getHighOrder();
	 reg = regPair->getLowOrder();

         if (highReg->getAssociation() == highRegNum &&
             reg->getAssociation() == regNum)
            continue;

         }
      else  if (reg->getAssociation() == regNum)
             continue;

      if (regList.find(reg) || (highReg && regList.find(highReg)))
	 {
         TR::InstOpCode::Mnemonic    opCode;
         TR_RegisterKinds kind = reg->getKind();

         switch (kind)
	    {
            case TR_GPR:
               opCode = TR::InstOpCode::mr;
               break;
            case TR_FPR:
               opCode = TR::InstOpCode::fmr;
               break;
            case TR_VRF:
               opCode = TR::InstOpCode::vor;
               //TR_ASSERT(0, "VMX not fully supported.");
               break;
            case TR_VSX_VECTOR:
               opCode = TR::InstOpCode::xxlor;
               break;
            case TR_CCR:
               opCode = TR::InstOpCode::mcrf;
               break;
            default:
               TR_ASSERT(0, "Invalid register kind.");
	    }


         if (regList.find(reg))
            {
	    bool containsInternalPointer = false;
	    if (reg->getPinningArrayPointer())
	       containsInternalPointer = true;

	    copyReg = (reg->containsCollectedReference() && !containsInternalPointer) ?
	               cg->allocateCollectedReferenceRegister() : cg->allocateRegister(kind);

	    if (containsInternalPointer)
	       {
	       copyReg->setContainsInternalPointer();
	       copyReg->setPinningArrayPointer(reg->getPinningArrayPointer());
	       }
            if (opCode == TR::InstOpCode::vor || opCode == TR::InstOpCode::xxlor)
               iCursor = generateTrg1Src2Instruction(cg, opCode, node, copyReg, reg, reg, iCursor);
            else
               iCursor = generateTrg1Src1Instruction(cg, opCode, node, copyReg, reg, iCursor);

            reg = copyReg;
            }

	 if (highReg && regList.find(highReg))
	    {
	    bool containsInternalPointer = false;
	    if (highReg->getPinningArrayPointer())
	       containsInternalPointer = true;

	    highCopyReg = (highReg->containsCollectedReference() && !containsInternalPointer) ?
	                  cg->allocateCollectedReferenceRegister() : cg->allocateRegister(kind);

	    if (containsInternalPointer)
	       {
	       highCopyReg->setContainsInternalPointer();
	       highCopyReg->setPinningArrayPointer(highReg->getPinningArrayPointer());
	       }
            if (opCode == TR::InstOpCode::vor || opCode == TR::InstOpCode::xxlor)
               iCursor = generateTrg1Src2Instruction(cg, opCode, node, highCopyReg, highReg, highReg, iCursor);
            else
	       iCursor = generateTrg1Src1Instruction(cg, opCode, node, highCopyReg, highReg, iCursor);

	    highReg = highCopyReg;
	    }
	 }

      addPreCondition(reg, regNum);
      addPostCondition(reg, regNum);
      if (copyReg != NULL)
         cg->stopUsingRegister(copyReg);
      else
         regList.add(reg);

      if (highReg)
	 {
	 addPreCondition(highReg, highRegNum);
	 addPostCondition(highReg, highRegNum);
	 if (highCopyReg != NULL)
	    cg->stopUsingRegister(highCopyReg);
         else
            regList.add(highReg);
	 }
      }

   if (iCursor!=NULL && cursorPtr!=NULL)
      *cursorPtr = iCursor;
   }