Example #1
0
void CodeGen::genFloatMath(GenTree *tree, RegSet::RegisterPreference *pref)
{
    assert(tree->OperGet() == GT_INTRINSIC);

    GenTreePtr op1 = tree->gtOp.gtOp1;

    // get tree into a register
    genCodeForTreeFloat(op1, pref);

    instruction ins;

    switch (tree->gtIntrinsic.gtIntrinsicId)
    {
    case CORINFO_INTRINSIC_Sin:
        ins = INS_invalid; 
        break;
    case CORINFO_INTRINSIC_Cos:
        ins = INS_invalid; 
        break;
    case CORINFO_INTRINSIC_Sqrt:
        ins = INS_vsqrt; 
        break;
    case CORINFO_INTRINSIC_Abs:
        ins = INS_vabs; 
        break;
    case CORINFO_INTRINSIC_Round:
    {
        regNumber reg = regSet.PickRegFloat(tree->TypeGet(), pref);
        genMarkTreeInReg(tree, reg);
        // convert it to a long and back
        inst_RV_RV(ins_FloatConv(TYP_LONG,tree->TypeGet()), 
                   reg, op1->gtRegNum, tree->TypeGet());
        inst_RV_RV(ins_FloatConv(tree->TypeGet(), TYP_LONG), reg, reg);
        genCodeForTreeFloat_DONE(tree, op1->gtRegNum);
        return;
    }
    break;
    default:
        unreached();
    }

    if (ins != INS_invalid)
    {
        regNumber reg = regSet.PickRegFloat(tree->TypeGet(), pref);
        genMarkTreeInReg(tree, reg);
        inst_RV_RV(ins, reg, op1->gtRegNum, tree->TypeGet());
        // mark register that holds tree
        genCodeForTreeFloat_DONE(tree, reg);
    }
    else
    {
        unreached();
        // If unreached is removed, mark register that holds tree
        // genCodeForTreeFloat_DONE(tree, op1->gtRegNum);
    }
            
    return;            
}
Example #2
0
void CodeGen::genFloatConst(GenTree* tree, RegSet::RegisterPreference* pref)
{
    assert(tree->gtOper == GT_CNS_DBL);
    var_types type       = tree->gtType;
    double    constValue = tree->gtDblCon.gtDconVal;
    size_t*   cv         = (size_t*)&constValue;

    regNumber dst = regSet.PickRegFloat(type, pref);

    if (type == TYP_FLOAT)
    {
        regNumber reg = regSet.rsPickReg();

        float f = forceCastToFloat(constValue);
        genSetRegToIcon(reg, *((int*)(&f)));
        getEmitter()->emitIns_R_R(INS_vmov_i2f, EA_4BYTE, dst, reg);
    }
    else
    {
        assert(type == TYP_DOUBLE);
        regNumber reg1 = regSet.rsPickReg();
        regNumber reg2 = regSet.rsGrabReg(RBM_ALLINT & ~genRegMask(reg1));

        genSetRegToIcon(reg1, cv[0]);
        regSet.rsLockReg(genRegMask(reg1));
        genSetRegToIcon(reg2, cv[1]);
        regSet.rsUnlockReg(genRegMask(reg1));

        getEmitter()->emitIns_R_R_R(INS_vmov_i2d, EA_8BYTE, dst, reg1, reg2);
    }
    genMarkTreeInReg(tree, dst);

    return;
}
Example #3
0
void        CodeGen::genComputeAddressableFloat(GenTreePtr tree, 
                                                regMaskTP addrRegInt,
                                                regMaskTP addrRegFlt,
                                                RegSet::KeepReg keptReg,
                                                regMaskTP needReg,
                                                RegSet::KeepReg keepReg,
                                                bool freeOnly /* = false */)
{
    noway_assert(genStillAddressable(tree));
    noway_assert(varTypeIsFloating(tree->TypeGet()));

    genDoneAddressableFloat(tree, addrRegInt, addrRegFlt, keptReg);

    regNumber reg;
    if (tree->gtFlags & GTF_REG_VAL)
    {
        reg = tree->gtRegNum;
        if (freeOnly && !(genRegMaskFloat(reg, tree->TypeGet()) & regSet.RegFreeFloat()))
        {
            goto LOAD_REG;
        }
    }
    else
    {
        LOAD_REG:
            RegSet::RegisterPreference pref(needReg, RBM_NONE);
            reg = regSet.PickRegFloat(tree->TypeGet(), &pref);
            genLoadFloat(tree, reg);
    }

    genMarkTreeInReg(tree, reg);

    if (keepReg == RegSet::KEEP_REG)
    {
        regSet.SetUsedRegFloat(tree, true);
    }
}
Example #4
0
void CodeGen::genFloatSimple(GenTree *tree, RegSet::RegisterPreference *pref)
{
    assert(tree->OperKind() & GTK_SMPOP);
    var_types type = tree->TypeGet();

    RegSet::RegisterPreference defaultPref(RBM_ALLFLOAT, RBM_NONE);
    if (pref == NULL)
    {
        pref = &defaultPref;
    }

    switch (tree->OperGet())
    {
        // Assignment
        case GT_ASG:
        {        
            genFloatAssign(tree);
            break;
        }

        // Arithmetic binops
        case GT_ADD:
        case GT_SUB:
        case GT_MUL:
        case GT_DIV:
        {
            genFloatArith(tree, pref);
            break;
        }
     
        case GT_NEG:
        {
            GenTreePtr op1 = tree->gtOp.gtOp1;

            // get the tree into a register
            genCodeForTreeFloat(op1, pref);

            // change the sign
            regNumber reg = regSet.PickRegFloat(type, pref);
            genMarkTreeInReg(tree, reg);
            inst_RV_RV(ins_MathOp(tree->OperGet(), type), 
                       reg, op1->gtRegNum, type);
            
            // mark register that holds tree
            genCodeForTreeFloat_DONE(tree, reg);
            return;
        }

        case GT_IND:
        {
            regMaskTP       addrReg;
            
            // Make sure the address value is 'addressable' */
            addrReg = genMakeAddressable(tree, 0, RegSet::FREE_REG);

            // Load the value onto the FP stack 
            regNumber reg = regSet.PickRegFloat(type, pref);
            genLoadFloat(tree, reg);

            genDoneAddressable(tree, addrReg, RegSet::FREE_REG);

            genCodeForTreeFloat_DONE(tree, reg);

            break;
        }
        case GT_CAST:
        {
            genCodeForTreeCastFloat(tree, pref);
            break;
        }

        // Asg-Arithmetic ops
        case GT_ASG_ADD:
        case GT_ASG_SUB:
        case GT_ASG_MUL:
        case GT_ASG_DIV:
        {
            genFloatAsgArith(tree);
            break;
        }
        case GT_INTRINSIC:
            genFloatMath(tree, pref);
            break;

        case GT_RETURN:
        {
            GenTreePtr op1 = tree->gtOp.gtOp1;
            assert(op1);

            pref->best = (type==TYP_DOUBLE) ? RBM_DOUBLERET : RBM_FLOATRET;

            // Compute the result
            genCodeForTreeFloat(op1, pref);

            inst_RV_TT(ins_FloatConv(tree->TypeGet(), op1->TypeGet()), REG_FLOATRET, op1);
            if (compiler->info.compIsVarArgs)
            {
                if (tree->TypeGet() == TYP_FLOAT)
                {
                    inst_RV_RV(INS_vmov_f2i, REG_INTRET, REG_FLOATRET, TYP_FLOAT, EA_4BYTE);
                }
                else
                {
                    assert(tree->TypeGet() == TYP_DOUBLE);
                    inst_RV_RV_RV(INS_vmov_d2i, REG_INTRET, REG_NEXT(REG_INTRET), REG_FLOATRET, EA_8BYTE);
                }
            }
            break;
        }
        case GT_ARGPLACE:
            break;

        case GT_COMMA:
        {
            GenTreePtr op1 = tree->gtOp.gtOp1;
            GenTreePtr op2 = tree->gtGetOp2();
 
            if (tree->gtFlags & GTF_REVERSE_OPS)
            {
                genCodeForTreeFloat(op2, pref);

                regSet.SetUsedRegFloat(op2, true);
                genEvalSideEffects(op1);
                regSet.SetUsedRegFloat(op2, false);
            }
            else
            {
                genEvalSideEffects(op1);
                genCodeForTreeFloat(op2, pref);
            }
            
            genCodeForTreeFloat_DONE(tree, op2->gtRegNum);
            break;
        }

        case GT_CKFINITE:
            genFloatCheckFinite(tree, pref);
            break;

        default:
            NYI("Unhandled register FP codegen");
    }
}