genProduceReg(treeNode);
}
-//------------------------------------------------------------------------
-// genLockedInstructions: Generate code for the locked operations.
-//
-// Notes:
-// Handles GT_LOCKADD, GT_XCHG, GT_XADD nodes.
-//
-void CodeGen::genLockedInstructions(GenTreeOp* treeNode)
-{
- NYI("genLockedInstructions");
-}
-
//--------------------------------------------------------------------------------------
// genLclHeap: Generate code for localloc
//
GenTree* data = tree->gtOp1;
instruction ins = ins_Store(targetType);
emitAttr attr = emitTypeSize(targetType);
- if (data->isContainedIntOrIImmed())
- {
- assert(data->IsIntegralConst(0));
- NYI_ARM("st.lclFld contained operand");
- }
- else
- {
- assert(!data->isContained());
- genConsumeReg(data);
- emit->emitIns_S_R(ins, attr, data->gtRegNum, varNum, offset);
- }
+
+ assert(!data->isContained());
+ genConsumeReg(data);
+ emit->emitIns_S_R(ins, attr, data->gtRegNum, varNum, offset);
genUpdateLife(tree);
varDsc->lvRegNum = REG_STK;
{
genConsumeRegs(data);
- regNumber dataReg = REG_NA;
- if (data->isContainedIntOrIImmed())
- {
- assert(data->IsIntegralConst(0));
- NYI_ARM("st.lclVar contained operand");
- }
- else
- {
- assert(!data->isContained());
- dataReg = data->gtRegNum;
- }
+ assert(!data->isContained());
+ regNumber dataReg = data->gtRegNum;
assert(dataReg != REG_NA);
if (targetReg == REG_NA) // store into stack based LclVar
// registers are taken care of.
genConsumeOperands(tree);
-#if NOGC_WRITE_BARRIERS
- NYI_ARM("NOGC_WRITE_BARRIERS");
-#else
// At this point, we should not have any interference.
// That is, 'data' must not be in REG_ARG_0,
// as that is where 'addr' must go.
{
inst_RV_RV(INS_mov, REG_ARG_1, data->gtRegNum, data->TypeGet());
}
-#endif // NOGC_WRITE_BARRIERS
genGCWriteBarrier(tree, writeBarrierForm);
}
GenTree* loVal = op1->gtGetOp1();
GenTree* hiVal = op1->gtGetOp2();
- // NYI: Contained immediates.
- NYI_IF((loVal->gtRegNum == REG_NA) || (hiVal->gtRegNum == REG_NA),
- "Store of long lclVar with contained immediate");
+ noway_assert((loVal->gtRegNum != REG_NA) && (hiVal->gtRegNum != REG_NA));
emit->emitIns_S_R(ins_Store(TYP_INT), EA_4BYTE, loVal->gtRegNum, lclNum, 0);
emit->emitIns_S_R(ins_Store(TYP_INT), EA_4BYTE, hiVal->gtRegNum, lclNum, genTypeSize(TYP_INT));
#else // !_TARGET_ARM64_
if (varTypeIsFloating(treeNode))
{
- NYI_ARM("genRegCopy from 'int' to 'float'");
+ // GT_BITCAST on ARM is only used to cast floating-point arguments to integer
+ // registers. Nobody generates GT_BITCAST from int to float currently.
+ NYI_ARM("GT_BITCAST from 'int' to 'float'");
}
else
{
}
else
{
- regNumber otherReg = (regNumber)treeNode->AsMultiRegOp()->gtOtherReg;
+ assert(op1->TypeGet() == TYP_DOUBLE);
+ regNumber otherReg = treeNode->AsMultiRegOp()->gtOtherReg;
assert(otherReg != REG_NA);
inst_RV_RV_RV(INS_vmov_d2i, targetReg, otherReg, genConsumeReg(op1), EA_8BYTE);
}
case GT_PUTARG_SPLIT:
genPutArgSplit(treeNode->AsPutArgSplit());
break;
-#endif
+#endif // _TARGET_ARM_
case GT_CALL:
genCallInstruction(treeNode->AsCall());
break;
+ case GT_MEMORYBARRIER:
+ instGen_MemoryBarrier();
+ break;
+
+#ifdef _TARGET_ARM64_
case GT_LOCKADD:
case GT_XCHG:
case GT_XADD:
genLockedInstructions(treeNode->AsOp());
break;
- case GT_MEMORYBARRIER:
- instGen_MemoryBarrier();
- break;
-
case GT_CMPXCHG:
- NYI_ARM("GT_CMPXCHG");
-#ifdef _TARGET_ARM64_
genCodeForCmpXchg(treeNode->AsCmpXchg());
-#endif
break;
+#endif // _TARGET_ARM64_
case GT_RELOAD:
// do nothing - reload is just a marker.
genConsumeOperands(treeNode->AsOp());
getEmitter()->emitInsBinary(INS_frintm, emitActualTypeSize(treeNode), treeNode, srcNode);
break;
-#endif
+
case CORINFO_INTRINSIC_Round:
- NYI_ARM("genIntrinsic for round - not implemented yet");
genConsumeOperands(treeNode->AsOp());
- getEmitter()->emitInsBinary(INS_ROUND, emitActualTypeSize(treeNode), treeNode, srcNode);
+ getEmitter()->emitInsBinary(INS_frintn, emitActualTypeSize(treeNode), treeNode, srcNode);
break;
+#endif // _TARGET_ARM64_
case CORINFO_INTRINSIC_Sqrt:
genConsumeOperands(treeNode->AsOp());
#else // !_TARGET_ARM64_
if (varTypeIsFloating(treeNode))
{
+ // GT_COPY from 'int' to 'float' currently can't happen. Maybe if ARM SIMD is implemented
+ // it will happen, according to the comment above?
NYI_ARM("genRegCopy from 'int' to 'float'");
}
else
}
//------------------------------------------------------------------------
-// genCodeForSwap: Produce code for a GT_CMPXCHG node.
+// genCodeForCmpXchg: Produce code for a GT_CMPXCHG node.
//
// Arguments:
// tree - the GT_CMPXCHG node
GenTree* loVal = op1->gtGetOp1();
GenTree* hiVal = op1->gtGetOp2();
- // NYI: Contained immediates.
- NYI_IF((loVal->gtRegNum == REG_NA) || (hiVal->gtRegNum == REG_NA),
- "Store of long lclVar with contained immediate");
+ noway_assert((loVal->gtRegNum != REG_NA) && (hiVal->gtRegNum != REG_NA));
emit->emitIns_S_R(ins_Store(TYP_INT), EA_4BYTE, loVal->gtRegNum, lclNum, 0);
emit->emitIns_S_R(ins_Store(TYP_INT), EA_4BYTE, hiVal->gtRegNum, lclNum, genTypeSize(TYP_INT));
const instruction INS_SUBC = INS_sbb;
const instruction INS_NOT = INS_not;
-#endif
+#endif // _TARGET_XARCH_
#ifdef _TARGET_ARM_
const instruction INS_SUBC = INS_sbc;
const instruction INS_NOT = INS_mvn;
-const instruction INS_ABS = INS_vabs;
-const instruction INS_ROUND = INS_invalid;
-const instruction INS_SQRT = INS_vsqrt;
+const instruction INS_ABS = INS_vabs;
+const instruction INS_SQRT = INS_vsqrt;
-#endif
+#endif // _TARGET_ARM_
#ifdef _TARGET_ARM64_
const instruction INS_MULADD = INS_madd;
const instruction INS_BREAKPOINT = INS_bkpt;
-const instruction INS_ABS = INS_fabs;
-const instruction INS_ROUND = INS_frintn;
-const instruction INS_SQRT = INS_fsqrt;
+const instruction INS_ABS = INS_fabs;
+const instruction INS_SQRT = INS_fsqrt;
-#endif
+#endif // _TARGET_ARM64_
/*****************************************************************************/
if (varTypeIsFloating(srcType))
{
noway_assert(!tree->gtOverflow());
+ assert(!varTypeIsSmall(dstType)); // fgMorphCast creates intermediate casts when converting from float to small
+ // int.
}
assert(!varTypeIsSmall(srcType));
- // case of src is a floating point type and dst is a small type.
- if (varTypeIsFloating(srcType) && varTypeIsSmall(dstType))
- {
- NYI_ARM("Lowering for cast from float to small type"); // Not tested yet.
- tmpType = TYP_INT;
- }
-
if (tmpType != TYP_UNDEF)
{
GenTree* tmp = comp->gtNewCastNode(tmpType, op1, tree->IsUnsigned(), tmpType);
assert(info->dstCount == 1);
break;
default:
- NYI_ARM("LinearScan::Build for GT_INTRINSIC");
+ unreached();
break;
}
}
}
break;
- default:
-#ifdef DEBUG
- char message[256];
- _snprintf_s(message, _countof(message), _TRUNCATE, "NYI: Unimplemented node type %s",
- GenTree::OpName(tree->OperGet()));
- NYIRAW(message);
-#else
- NYI_ARM("BuildNode default case");
-#endif
case GT_LCL_FLD:
case GT_LCL_FLD_ADDR:
case GT_LCL_VAR:
info->srcCount = appendBinaryLocationInfoToList(tree->AsOp());
assert(info->srcCount == 2);
break;
+
+ default:
+#ifdef DEBUG
+ char message[256];
+ _snprintf_s(message, _countof(message), _TRUNCATE, "NYI: Unimplemented node type %s",
+ GenTree::OpName(tree->OperGet()));
+ NYIRAW(message);
+#endif
+ unreached();
} // end switch (tree->OperGet())
if (tree->IsUnusedValue() && (info->dstCount != 0))