void emitter::emitIns_R_R_R()

in src/coreclr/jit/emitloongarch64.cpp [1456:1731]


void emitter::emitIns_R_R_R(
    instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
{
    code_t code = emitInsCode(ins);

    if (((INS_add_w <= ins) && (ins <= INS_crcc_w_d_w)) || ((INS_ldx_b <= ins) && (ins <= INS_ldle_d)) ||
        ((INS_stx_b <= ins) && (ins <= INS_stle_d)))
    {
#ifdef DEBUG
        switch (ins)
        {
            case INS_add_w:
            case INS_add_d:
            case INS_sub_w:
            case INS_sub_d:
            case INS_and:
            case INS_or:
            case INS_nor:
            case INS_xor:
            case INS_andn:
            case INS_orn:

            case INS_mul_w:
            case INS_mul_d:
            case INS_mulh_w:
            case INS_mulh_wu:
            case INS_mulh_d:
            case INS_mulh_du:
            case INS_mulw_d_w:
            case INS_mulw_d_wu:
            case INS_div_w:
            case INS_div_wu:
            case INS_div_d:
            case INS_div_du:
            case INS_mod_w:
            case INS_mod_wu:
            case INS_mod_d:
            case INS_mod_du:

            case INS_sll_w:
            case INS_srl_w:
            case INS_sra_w:
            case INS_rotr_w:
            case INS_sll_d:
            case INS_srl_d:
            case INS_sra_d:
            case INS_rotr_d:

            case INS_maskeqz:
            case INS_masknez:

            case INS_slt:
            case INS_sltu:

            case INS_ldx_b:
            case INS_ldx_h:
            case INS_ldx_w:
            case INS_ldx_d:
            case INS_ldx_bu:
            case INS_ldx_hu:
            case INS_ldx_wu:
            case INS_stx_b:
            case INS_stx_h:
            case INS_stx_w:
            case INS_stx_d:

            case INS_ldgt_b:
            case INS_ldgt_h:
            case INS_ldgt_w:
            case INS_ldgt_d:
            case INS_ldle_b:
            case INS_ldle_h:
            case INS_ldle_w:
            case INS_ldle_d:
            case INS_stgt_b:
            case INS_stgt_h:
            case INS_stgt_w:
            case INS_stgt_d:
            case INS_stle_b:
            case INS_stle_h:
            case INS_stle_w:
            case INS_stle_d:

            case INS_crc_w_b_w:
            case INS_crc_w_h_w:
            case INS_crc_w_w_w:
            case INS_crc_w_d_w:
            case INS_crcc_w_b_w:
            case INS_crcc_w_h_w:
            case INS_crcc_w_w_w:
            case INS_crcc_w_d_w:
                break;
            default:
                NYI_LOONGARCH64("illegal ins within emitIns_R_R_R --1!");
        }
#endif
        assert(isGeneralRegister(reg1));
        assert(isGeneralRegisterOrR0(reg2));
        assert(isGeneralRegisterOrR0(reg3));

        code |= (reg1 /*& 0x1f*/);       // rd
        code |= (reg2 /*& 0x1f*/) << 5;  // rj
        code |= (reg3 /*& 0x1f*/) << 10; // rk
    }
    else if ((INS_amswap_w <= ins) && (ins <= INS_ammin_db_du))
    {
#ifdef DEBUG
        switch (ins)
        {
            case INS_amswap_w:
            case INS_amswap_d:
            case INS_amswap_db_w:
            case INS_amswap_db_d:
            case INS_amadd_w:
            case INS_amadd_d:
            case INS_amadd_db_w:
            case INS_amadd_db_d:
            case INS_amand_w:
            case INS_amand_d:
            case INS_amand_db_w:
            case INS_amand_db_d:
            case INS_amor_w:
            case INS_amor_d:
            case INS_amor_db_w:
            case INS_amor_db_d:
            case INS_amxor_w:
            case INS_amxor_d:
            case INS_amxor_db_w:
            case INS_amxor_db_d:
            case INS_ammax_w:
            case INS_ammax_d:
            case INS_ammax_db_w:
            case INS_ammax_db_d:
            case INS_ammin_w:
            case INS_ammin_d:
            case INS_ammin_db_w:
            case INS_ammin_db_d:
            case INS_ammax_wu:
            case INS_ammax_du:
            case INS_ammax_db_wu:
            case INS_ammax_db_du:
            case INS_ammin_wu:
            case INS_ammin_du:
            case INS_ammin_db_wu:
            case INS_ammin_db_du:
                break;
            default:
                NYI_LOONGARCH64("illegal ins within emitIns_R_R_R --am!");
        }
#endif

        assert(isGeneralRegister(reg1));
        assert(isGeneralRegisterOrR0(reg2));
        assert(isGeneralRegisterOrR0(reg3));

        code |= (reg1 /*& 0x1f*/);       // rd
        code |= (reg2 /*& 0x1f*/) << 10; // rk
        code |= (reg3 /*& 0x1f*/) << 5;  // rj
    }
    else if ((INS_fadd_s <= ins) && (ins <= INS_fcopysign_d))
    {
#ifdef DEBUG
        switch (ins)
        {
            case INS_fadd_s:
            case INS_fadd_d:
            case INS_fsub_s:
            case INS_fsub_d:
            case INS_fmul_s:
            case INS_fmul_d:
            case INS_fdiv_s:
            case INS_fdiv_d:
            case INS_fmax_s:
            case INS_fmax_d:
            case INS_fmin_s:
            case INS_fmin_d:
            case INS_fmaxa_s:
            case INS_fmaxa_d:
            case INS_fmina_s:
            case INS_fmina_d:
            case INS_fscaleb_s:
            case INS_fscaleb_d:
            case INS_fcopysign_s:
            case INS_fcopysign_d:
                break;
            default:
                NYI_LOONGARCH64("illegal ins within emitIns_R_R_R --2!");
        }
#endif
        assert(isFloatReg(reg1));
        assert(isFloatReg(reg2));
        assert(isFloatReg(reg3));

        code |= (reg1 & 0x1f);       // fd
        code |= (reg2 & 0x1f) << 5;  // fj
        code |= (reg3 & 0x1f) << 10; // fk
    }
    else if ((INS_fldx_s <= ins) && (ins <= INS_fstle_d))
    {
#ifdef DEBUG
        switch (ins)
        {
            case INS_fldx_s:
            case INS_fldx_d:
            case INS_fstx_s:
            case INS_fstx_d:

            case INS_fldgt_s:
            case INS_fldgt_d:
            case INS_fldle_s:
            case INS_fldle_d:
            case INS_fstgt_s:
            case INS_fstgt_d:
            case INS_fstle_s:
            case INS_fstle_d:
                break;
            default:
                NYI_LOONGARCH64("illegal ins within emitIns_R_R_R --3!");
        }
#endif
        assert(isFloatReg(reg1));
        assert(isGeneralRegisterOrR0(reg2));
        assert(isGeneralRegisterOrR0(reg3));

        code |= reg1 & 0x1f; // fd
        code |= reg2 << 5;   // rj
        code |= reg3 << 10;  // rk
    }
#ifdef FEATURE_SIMD
    else if ((INS_vldx == ins) || (INS_vstx == ins) || (INS_xvldx == ins) || (INS_xvstx == ins))
    {
        assert(isVectorRegister(reg1));
        assert(isGeneralRegisterOrR0(reg2));
        assert(isGeneralRegisterOrR0(reg3));

        code |= reg1 & 0x1f; // vd(xd)
        code |= reg2 << 5;   // rj
        code |= reg3 << 10;  // rk
    }
    else if (((INS_vreplve_b <= ins) && (ins <= INS_vreplve_d)) || ((INS_xvreplve_b <= ins) && (ins <= INS_xvreplve_d)))
    {
        assert(isVectorRegister(reg1));
        assert(isVectorRegister(reg2));
        assert(isGeneralRegisterOrR0(reg3));

        code |= (reg1 & 0x1f);      // vd(xd)
        code |= (reg2 & 0x1f) << 5; // vj(xj)
        code |= reg3 << 10;         // rk
    }
    else if (((INS_vfcmp_caf_s <= ins) && (ins <= INS_vshuf_d)) || ((INS_xvfcmp_caf_s <= ins) && (ins <= INS_xvperm_w)))
    {
        assert(isVectorRegister(reg1));
        assert(isVectorRegister(reg2));
        assert(isVectorRegister(reg3));

        code |= (reg1 & 0x1f);       // vd(xd)
        code |= (reg2 & 0x1f) << 5;  // vj(xj)
        code |= (reg3 & 0x1f) << 10; // vk(xk)
    }
#endif
    else
    {
        NYI_LOONGARCH64("Unsupported instruction in emitIns_R_R_R");
    }

    instrDesc* id = emitNewInstr(attr);

    id->idIns(ins);
    id->idReg1(reg1);
    id->idReg2(reg2);
    id->idReg3(reg3);
    id->idAddr()->iiaSetInstrEncode(code);
    id->idCodeSize(4);

    appendToCurIG(id);
}