@@ -12598,6 +12598,377 @@ TR::Register *J9::Power::TreeEvaluator::directCallEvaluator(TR::Node *node, TR::
12598
12598
}
12599
12599
12600
12600
12601
+ TR::Register *J9::Power::TreeEvaluator::setmemoryEvaluator(TR::Node *node, TR::CodeGenerator *cg)
12602
+ {
12603
+ TR::Compilation *comp = cg->comp();
12604
+ TR::Node *dstBaseAddrNode, *dstOffsetNode, *dstAddrNode, *lengthNode, *valueNode;
12605
+
12606
+ bool arrayCheckNeeded;
12607
+
12608
+ // IL tree structure depends on whether or not it's been determined that a runtime arrayCHK is needed:
12609
+ // if node has four children (i.e.: object base address and offset are separate), need array check
12610
+ // if node three children (i.e.: object base address and offset have already been added together), don't need array check
12611
+ if (node->getNumChildren() == 4)
12612
+ {
12613
+ arrayCheckNeeded = true;
12614
+
12615
+ dstBaseAddrNode = node->getChild(0);
12616
+ dstOffsetNode = node->getChild(1);
12617
+ dstAddrNode = NULL;
12618
+ lengthNode = node->getChild(2);
12619
+ valueNode = node->getChild(3);
12620
+ }
12621
+ else //i.e.: node->getNumChildren() == 3
12622
+ {
12623
+ arrayCheckNeeded = false;
12624
+
12625
+ dstBaseAddrNode = NULL;
12626
+ dstOffsetNode = NULL;
12627
+ dstAddrNode = node->getChild(0);
12628
+ lengthNode = node->getChild(1);
12629
+ valueNode = node->getChild(2);
12630
+ }
12631
+
12632
+ TR::Register *dstBaseAddrReg, *dstOffsetReg, *dstAddrReg, *lengthReg, *valueReg;
12633
+
12634
+ // if the offset is a constant value less than 16 bits, then we dont need a separate register for it
12635
+ bool useOffsetAsImmVal = dstOffsetNode && dstOffsetNode->getOpCode().isLoadConst() &&
12636
+ (dstOffsetNode->getConstValue() >= LOWER_IMMED) && (dstOffsetNode->getConstValue() <= UPPER_IMMED);
12637
+
12638
+ bool stopUsingCopyRegBase = dstBaseAddrNode ? TR::TreeEvaluator::stopUsingCopyReg(dstBaseAddrNode, dstBaseAddrReg, cg) : false;
12639
+ bool stopUsingCopyRegAddr = dstAddrNode ? TR::TreeEvaluator::stopUsingCopyReg(dstAddrNode, dstAddrReg, cg) : false ;
12640
+
12641
+ bool stopUsingCopyRegOffset, stopUsingCopyRegLen, stopUsingCopyRegVal;
12642
+
12643
+ //dstOffsetNode (type: long)
12644
+ if (dstOffsetNode && !useOffsetAsImmVal) //only want to allocate a register for dstoffset if we're using it for the array check AND it isn't a constant
12645
+ {
12646
+ if (!cg->canClobberNodesRegister(lengthNode)) //only need to copy dstOffset into another register if the current one isn't clobberable
12647
+ {
12648
+ if (cg->comp()->target().is32Bit()) //on 32-bit systems, need to grab the lower 32 bits of offset from the register pair
12649
+ {
12650
+ dstOffsetReg = cg->evaluate(dstOffsetNode);
12651
+ TR::Register *offsetCopyReg = cg->allocateRegister();
12652
+ generateTrg1Src1Instruction(cg, TR::InstOpCode::mr, dstOffsetNode, offsetCopyReg, dstOffsetReg->getLowOrder());
12653
+
12654
+ dstOffsetReg = offsetCopyReg;
12655
+ stopUsingCopyRegOffset = true;
12656
+ }
12657
+ else
12658
+ {
12659
+ stopUsingCopyRegOffset = TR::TreeEvaluator::stopUsingCopyReg(dstOffsetNode, dstOffsetReg, cg);
12660
+ }
12661
+ }
12662
+ else
12663
+ {
12664
+ dstOffsetReg = cg->evaluate(dstOffsetNode);
12665
+
12666
+ if (cg->comp()->target().is32Bit()) //on 32-bit systems, need to grab the lower 32 bits of offset from the register pair
12667
+ dstOffsetReg = dstOffsetReg->getLowOrder();
12668
+
12669
+ stopUsingCopyRegOffset = false;
12670
+ }
12671
+ }
12672
+ else
12673
+ {
12674
+ stopUsingCopyRegOffset = false;
12675
+ }
12676
+
12677
+ //lengthNode (type: long)
12678
+ lengthReg = cg->evaluate(lengthNode);
12679
+ if (!cg->canClobberNodesRegister(lengthNode))
12680
+ {
12681
+ TR::Register *lenCopyReg = cg->allocateRegister();
12682
+
12683
+ if (cg->comp()->target().is32Bit()) //on 32-bit systems, need to grab the lower 32 bits of length from the register pair
12684
+ generateTrg1Src1Instruction(cg, TR::InstOpCode::mr, lengthNode, lenCopyReg, lengthReg->getLowOrder());
12685
+ else //on 64-bit system, can just do a normal copy
12686
+ generateTrg1Src1Instruction(cg, TR::InstOpCode::mr, lengthNode, lenCopyReg, lengthReg);
12687
+
12688
+ lengthReg = lenCopyReg;
12689
+ stopUsingCopyRegLen = true;
12690
+ }
12691
+ else
12692
+ {
12693
+ if (cg->comp()->target().is32Bit()) //on 32-bit system, need to grab lower 32 bits of length from the register pair
12694
+ lengthReg = lengthReg->getLowOrder();
12695
+
12696
+ stopUsingCopyRegLen = false;
12697
+ }
12698
+
12699
+ //valueNode (type: byte)
12700
+ valueReg = cg->evaluate(valueNode);
12701
+ if (cg->comp()->target().cpu.isAtLeast(OMR_PROCESSOR_PPC_P8))
12702
+ {
12703
+ //on P8 or higher, we can use vector instructions to cut down on loop iterations and residual tests -> need to copy valueReg into a VSX register
12704
+ TR::Register *valVectorReg = cg->allocateRegister(TR_VRF);
12705
+ generateTrg1Src1Instruction(cg, TR::InstOpCode::mtvsrd, valueNode, valVectorReg, valueReg);
12706
+
12707
+ valueReg = valVectorReg;
12708
+ stopUsingCopyRegVal = true;
12709
+ }
12710
+ else if (!cg->canClobberNodesRegister(valueNode))
12711
+ {
12712
+ TR::Register *valCopyReg = cg->allocateRegister();
12713
+ generateTrg1Src1Instruction(cg, TR::InstOpCode::mr, valueNode, valCopyReg, valueReg);
12714
+
12715
+ valueReg = valCopyReg;
12716
+ stopUsingCopyRegVal = true;
12717
+ }
12718
+
12719
+ TR::LabelSymbol * residualLabel = generateLabelSymbol(cg);
12720
+ TR::LabelSymbol * loopStartLabel = generateLabelSymbol(cg);
12721
+ TR::LabelSymbol * doneLabel = generateLabelSymbol(cg);
12722
+
12723
+ //these labels are not needed for the vector approach to storing to residual bytes (i.e.: P10+)
12724
+ TR::LabelSymbol *label8aligned, *label4aligned, *label2aligned, *label1aligned;
12725
+
12726
+ if (!cg->comp()->target().cpu.isAtLeast(OMR_PROCESSOR_PPC_P10))
12727
+ {
12728
+ label8aligned = generateLabelSymbol(cg);
12729
+ label4aligned = generateLabelSymbol(cg);
12730
+ label2aligned = generateLabelSymbol(cg);
12731
+ label1aligned = generateLabelSymbol(cg);
12732
+ }
12733
+
12734
+ TR::RegisterDependencyConditions *conditions;
12735
+ int32_t numDeps = 6;
12736
+
12737
+ //need extra register for offset only if it isn't already included in the destination address AND it isn't a constant
12738
+ if (arrayCheckNeeded && !useOffsetAsImmVal)
12739
+ numDeps++;
12740
+
12741
+ conditions = new (cg->trHeapMemory()) TR::RegisterDependencyConditions(numDeps, numDeps, cg->trMemory());
12742
+ TR::Register *cndReg = cg->allocateRegister(TR_CCR);
12743
+ TR::addDependency(conditions, cndReg, TR::RealRegister::cr0, TR_CCR, cg);
12744
+
12745
+ if (arrayCheckNeeded)
12746
+ {
12747
+ //dstBaseAddrReg holds the address of the object being written to, so need to exclude GPR0
12748
+ TR::addDependency(conditions, dstBaseAddrReg, TR::RealRegister::NoReg, TR_GPR, cg);
12749
+ conditions->getPostConditions()->getRegisterDependency(conditions->getAddCursorForPost() - 1)->setExcludeGPR0();
12750
+
12751
+ if (!useOffsetAsImmVal)
12752
+ TR::addDependency(conditions, dstOffsetReg, TR::RealRegister::NoReg, TR_GPR, cg);
12753
+ }
12754
+ else
12755
+ {
12756
+ //dstAddrReg holds the address of the object being written to, so need to exclude GPR0
12757
+ TR::addDependency(conditions, dstAddrReg, TR::RealRegister::NoReg, TR_GPR, cg);
12758
+ conditions->getPostConditions()->getRegisterDependency(1)->setExcludeGPR0();
12759
+ }
12760
+
12761
+ TR::addDependency(conditions, lengthReg, TR::RealRegister::NoReg, TR_GPR, cg);
12762
+ TR::addDependency(conditions, valueReg, TR::RealRegister::NoReg, TR_GPR, cg);
12763
+
12764
+ //temp1Reg will later be used to hold the J9Class flags for the object at dst, so need to exclude GPR0
12765
+ TR::Register * temp1Reg = cg->allocateRegister();
12766
+ TR::addDependency(conditions, temp1Reg, TR::RealRegister::NoReg, TR_GPR, cg);
12767
+ conditions->getPostConditions()->getRegisterDependency(conditions->getAddCursorForPost() - 1)->setExcludeGPR0();
12768
+
12769
+ TR::Register * temp2Reg = cg->allocateRegister();
12770
+ TR::addDependency(conditions, temp2Reg, TR::RealRegister::NoReg, TR_GPR, cg);
12771
+
12772
+
12773
+ #if defined (J9VM_GC_ENABLE_SPARSE_HEAP_ALLOCATION)
12774
+
12775
+ if (arrayCheckNeeded) // CASE (3)
12776
+ {
12777
+ // There are two scenarios in which we DON'T want to modify the dest base address:
12778
+ // 1.) If the object is NULL (since we can't load dataAddr from a NULL pointer)
12779
+ // 2.) If the object is a non-array object
12780
+ // So two checks are required (NULL, Array) to determine whether dataAddr should be loaded or not
12781
+ TR::LabelSymbol *noDataAddr = generateLabelSymbol(cg);
12782
+
12783
+ // We only want to generate a runtime NULL check if the status of the object (i.e.: whether it is NULL or non-NULL)
12784
+ // is NOT known. Note that if the object is known to be NULL, arrayCheckNeeded will be false, so there is no need to check
12785
+ // that condition here.
12786
+ if (!dstBaseAddrNode->isNonNull())
12787
+ {
12788
+ //generate NULL test
12789
+ generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::Op_cmpi, node, cndReg, dstBaseAddrReg, 0);
12790
+ generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, node, noDataAddr, cndReg);
12791
+ }
12792
+
12793
+ //Array Check
12794
+ TR::Register *dstClassInfoReg = temp1Reg;
12795
+ TR::Register *arrayFlagReg = temp2Reg;
12796
+
12797
+ //load dst class info into temp1Reg
12798
+ if (TR::Compiler->om.compressObjectReferences())
12799
+ generateTrg1MemInstruction(cg, TR::InstOpCode::lwz, node, dstClassInfoReg,
12800
+ TR::MemoryReference::createWithDisplacement(cg, dstBaseAddrReg, static_cast<int32_t>(TR::Compiler->om.offsetOfObjectVftField()), 4));
12801
+ else
12802
+ generateTrg1MemInstruction(cg,TR::InstOpCode::Op_load, node, dstClassInfoReg,
12803
+ TR::MemoryReference::createWithDisplacement(cg, dstBaseAddrReg, static_cast<int32_t>(TR::Compiler->om.offsetOfObjectVftField()), TR::Compiler->om.sizeofReferenceAddress()));
12804
+
12805
+ TR::TreeEvaluator::generateVFTMaskInstruction(cg, node, dstClassInfoReg);
12806
+
12807
+ TR::MemoryReference *dstClassMR = TR::MemoryReference::createWithDisplacement(cg, dstClassInfoReg, offsetof(J9Class, classDepthAndFlags), TR::Compiler->om.sizeofReferenceAddress());
12808
+ generateTrg1MemInstruction(cg, TR::InstOpCode::Op_load, node, dstClassInfoReg, dstClassMR);
12809
+
12810
+ //generate array check
12811
+ int32_t arrayFlagValue = comp->fej9()->getFlagValueForArrayCheck();
12812
+ generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::andis_r, node, arrayFlagReg, dstClassInfoReg, arrayFlagValue >> 16);
12813
+
12814
+ //if object is not an array (i.e.: temp1Reg & temp2Reg == 0), skip adjusting dstBaseAddr and dstOffset
12815
+ generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, node, noDataAddr, cndReg);
12816
+
12817
+ //load dataAddr if object is array:
12818
+ TR::MemoryReference *dataAddrSlotMR = TR::MemoryReference::createWithDisplacement(cg, dstBaseAddrReg, comp->fej9()->getOffsetOfContiguousDataAddrField(), TR::Compiler->om.sizeofReferenceAddress());
12819
+ generateTrg1MemInstruction(cg, TR::InstOpCode::Op_load, node, dstBaseAddrReg, dataAddrSlotMR);
12820
+
12821
+ //arrayCHK will skip to here if object is not an array
12822
+ generateLabelInstruction(cg, TR::InstOpCode::label, node, noDataAddr);
12823
+
12824
+ //calculate dstAddr = dstBaseAddr + dstOffset
12825
+ dstAddrReg = dstBaseAddrReg;
12826
+
12827
+ if (useOffsetAsImmVal)
12828
+ {
12829
+ int offsetImmVal = dstOffsetNode->getConstValue();
12830
+ generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, dstAddrReg, dstBaseAddrReg, offsetImmVal);
12831
+ }
12832
+ else
12833
+ generateTrg1Src2Instruction(cg, TR::InstOpCode::add, node, dstAddrReg, dstBaseAddrReg, dstOffsetReg);
12834
+ }
12835
+
12836
+ #endif /* J9VM_GC_ENABLE_SPARSE_HEAP_ALLOCATION */
12837
+
12838
+ // assemble the double word value from byte value
12839
+ if (cg->comp()->target().cpu.isAtLeast(OMR_PROCESSOR_PPC_P8))
12840
+ {
12841
+ generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::vspltb, valueNode, valueReg, valueReg, 7);
12842
+ }
12843
+ else
12844
+ {
12845
+ generateTrg1Src1Imm2Instruction(cg, TR::InstOpCode::rldimi, node, valueReg, valueReg, 8, CONSTANT64(0x000000000000FF00));
12846
+ generateTrg1Src1Imm2Instruction(cg, TR::InstOpCode::rldimi, node, valueReg, valueReg, 16, CONSTANT64(0x00000000FFFF0000));
12847
+ generateTrg1Src1Imm2Instruction(cg, TR::InstOpCode::rldimi, node, valueReg, valueReg, 32, CONSTANT64(0xFFFFFFFF00000000));
12848
+ }
12849
+
12850
+ generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::Op_cmpli, node, cndReg, lengthReg, 32);
12851
+ generateConditionalBranchInstruction(cg, TR::InstOpCode::blt, node, residualLabel, cndReg);
12852
+
12853
+ generateTrg1Src1ImmInstruction(cg, lengthNode->getType().isInt32() ? TR::InstOpCode::srawi : TR::InstOpCode::sradi, node, temp1Reg, lengthReg, 5);
12854
+ generateSrc1Instruction(cg, TR::InstOpCode::mtctr, node, temp1Reg);
12855
+ generateLabelInstruction(cg, TR::InstOpCode::label, node, loopStartLabel);
12856
+
12857
+ //store designated value to memory in chunks of 32 bytes
12858
+ if (cg->comp()->target().cpu.isAtLeast(OMR_PROCESSOR_PPC_P8))
12859
+ {
12860
+ //on P8 and higher, we can use vector instructions to cut down on loop iterations/number of stores
12861
+ generateMemSrc1Instruction(cg, TR::InstOpCode::stxvd2x, node, TR::MemoryReference::createWithIndexReg(cg, NULL, dstAddrReg, 16), valueReg);
12862
+ generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, dstAddrReg, dstAddrReg, 16);
12863
+ generateMemSrc1Instruction(cg, TR::InstOpCode::stxvd2x, node, TR::MemoryReference::createWithIndexReg(cg, NULL, dstAddrReg, 16), valueReg);
12864
+ generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, dstAddrReg, dstAddrReg, 16);
12865
+ }
12866
+ else
12867
+ {
12868
+ generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, TR::MemoryReference::createWithDisplacement(cg, dstAddrReg, 0, 8), valueReg);
12869
+ generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, TR::MemoryReference::createWithDisplacement(cg, dstAddrReg, 8, 8), valueReg);
12870
+ generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, TR::MemoryReference::createWithDisplacement(cg, dstAddrReg, 16, 8), valueReg);
12871
+ generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, TR::MemoryReference::createWithDisplacement(cg, dstAddrReg, 24, 8), valueReg);
12872
+ generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, dstAddrReg, dstAddrReg, 32);
12873
+ }
12874
+
12875
+ //decrement counter and return to start of loop
12876
+ generateConditionalBranchInstruction(cg, TR::InstOpCode::bdnz, node, loopStartLabel, cndReg);
12877
+
12878
+ //loop exit
12879
+ generateLabelInstruction(cg, TR::InstOpCode::label, node, residualLabel);
12880
+
12881
+ //Set residual bytes (max number of residual bytes = 31 = 0x1F)
12882
+ if (cg->comp()->target().cpu.isAtLeast(OMR_PROCESSOR_PPC_P10)) //on P10, we can use stxvl to store all residual bytes efficiently
12883
+ {
12884
+ //First 16 byte segment
12885
+ generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::andi_r, node, temp1Reg, lengthReg, 16); //get first hex char (can only be 0 or 1)
12886
+ generateTrg1Src1Instruction(cg, TR::InstOpCode::mr, node, temp2Reg, temp1Reg); //keep a copy of first hex char
12887
+
12888
+ //store to memory
12889
+ //NOTE: due to a quirk of the stxvl instruction on P10, the number of residual bytes must be shifted over before it can be used
12890
+ generateTrg1Src1Imm2Instruction(cg, TR::InstOpCode::rldicr, node, temp1Reg, temp1Reg, 56, CONSTANT64(0xFF00000000000000));
12891
+ generateSrc3Instruction(cg, TR::InstOpCode::stxvl, node, valueReg, dstAddrReg, temp1Reg);
12892
+
12893
+ //advance to next 16 byte chunk IF number of residual bytes >= 16
12894
+ generateTrg1Src2Instruction(cg, TR::InstOpCode::add, node, dstAddrReg, dstAddrReg, temp2Reg);
12895
+
12896
+ //Second 16 byte segment
12897
+ generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::andi_r, node, temp1Reg, lengthReg, 15); //get second hex char
12898
+ generateTrg1Src1Imm2Instruction(cg, TR::InstOpCode::rldicr, node, temp1Reg, temp1Reg, 56, CONSTANT64(0xFF00000000000000)); //shift num residual bytes
12899
+ generateSrc3Instruction(cg, TR::InstOpCode::stxvl, node, valueReg, dstAddrReg, temp1Reg); //store to memory
12900
+ }
12901
+ else
12902
+ {
12903
+ TR::Register *valueResidueReg;
12904
+
12905
+ if (cg->comp()->target().cpu.isAtLeast(OMR_PROCESSOR_PPC_P8))
12906
+ {
12907
+ //since P8 and P9 used the vector approach, we first need to copy valueReg back into a GPR
12908
+ generateTrg1Src1Instruction(cg, TR::InstOpCode::mfvsrd, node, temp2Reg, valueReg);
12909
+ valueResidueReg = temp2Reg;
12910
+ }
12911
+ else
12912
+ valueResidueReg = valueReg;
12913
+
12914
+ //check if residual < 16
12915
+ generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::andi_r, node, temp1Reg, lengthReg, 16);
12916
+ generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, node, label8aligned, cndReg);
12917
+ generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, TR::MemoryReference::createWithDisplacement(cg, dstAddrReg, 0, 8), valueResidueReg);
12918
+ generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, TR::MemoryReference::createWithDisplacement(cg, dstAddrReg, 8, 8), valueResidueReg);
12919
+ generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, dstAddrReg, dstAddrReg, 16);
12920
+
12921
+ generateLabelInstruction(cg, TR::InstOpCode::label, node, label8aligned); //check if residual < 8
12922
+ generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::andi_r, node, temp1Reg, lengthReg, 8);
12923
+ generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, node, label4aligned, cndReg);
12924
+ generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, TR::MemoryReference::createWithDisplacement(cg, dstAddrReg, 0, 8), valueResidueReg);
12925
+ generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, dstAddrReg, dstAddrReg, 8);
12926
+
12927
+ generateLabelInstruction(cg, TR::InstOpCode::label, node, label4aligned); //check if residual < 4
12928
+ generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::andi_r, node, temp1Reg, lengthReg, 4);
12929
+ generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, node, label2aligned, cndReg);
12930
+ generateMemSrc1Instruction(cg, TR::InstOpCode::stw, node, TR::MemoryReference::createWithDisplacement(cg, dstAddrReg, 0, 4), valueResidueReg);
12931
+ generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, dstAddrReg, dstAddrReg, 4);
12932
+
12933
+ generateLabelInstruction(cg, TR::InstOpCode::label, node, label2aligned); //check if residual < 2
12934
+ generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::andi_r, node, temp1Reg, lengthReg, 2);
12935
+ generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, node, label1aligned, cndReg);
12936
+ generateMemSrc1Instruction(cg, TR::InstOpCode::sth, node, TR::MemoryReference::createWithDisplacement(cg, dstAddrReg, 0, 2), valueResidueReg);
12937
+ generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, dstAddrReg, dstAddrReg, 2);
12938
+
12939
+ generateLabelInstruction(cg, TR::InstOpCode::label, node, label1aligned); //residual <= 1
12940
+ generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::andi_r, node, temp1Reg, lengthReg, 1);
12941
+ generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, node, doneLabel, cndReg);
12942
+ generateMemSrc1Instruction(cg, TR::InstOpCode::stb, node, TR::MemoryReference::createWithDisplacement(cg, dstAddrReg, 0, 1), valueResidueReg);
12943
+ }
12944
+
12945
+ generateDepLabelInstruction(cg, TR::InstOpCode::label, node, doneLabel, conditions);
12946
+
12947
+ if (stopUsingCopyRegBase)
12948
+ cg->stopUsingRegister(dstBaseAddrReg);
12949
+ if (stopUsingCopyRegOffset)
12950
+ cg->stopUsingRegister(dstOffsetReg);
12951
+ if (stopUsingCopyRegAddr)
12952
+ cg->stopUsingRegister(dstAddrReg);
12953
+ if (stopUsingCopyRegLen)
12954
+ cg->stopUsingRegister(lengthReg);
12955
+ if (stopUsingCopyRegVal)
12956
+ cg->stopUsingRegister(valueReg);
12957
+
12958
+ cg->stopUsingRegister(cndReg);
12959
+ cg->stopUsingRegister(temp1Reg);
12960
+ cg->stopUsingRegister(temp2Reg);
12961
+
12962
+ if (dstBaseAddrNode) cg->decReferenceCount(dstBaseAddrNode);
12963
+ if (dstOffsetNode) cg->decReferenceCount(dstOffsetNode);
12964
+ if (dstAddrNode) cg->decReferenceCount(dstAddrNode);
12965
+ cg->decReferenceCount(lengthNode);
12966
+ cg->decReferenceCount(valueNode);
12967
+
12968
+ return(NULL);
12969
+ }
12970
+
12971
+
12601
12972
TR::Register *J9::Power::TreeEvaluator::tstartEvaluator(TR::Node *node, TR::CodeGenerator *cg)
12602
12973
{
12603
12974
// tstart
0 commit comments