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