in src/coreclr/jit/emitloongarch64.cpp [952:1449]
void emitter::emitIns_R_R_I(
instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
{
code_t code = emitInsCode(ins);
if ((INS_slli_w <= ins) && (ins <= INS_rotri_w))
{
#ifdef DEBUG
switch (ins)
{
case INS_slli_w:
case INS_srli_w:
case INS_srai_w:
case INS_rotri_w:
break;
default:
NYI_LOONGARCH64("illegal ins within emitIns_R_R_I --1!");
}
#endif
assert(isGeneralRegister(reg1));
assert(isGeneralRegisterOrR0(reg2));
assert((0 <= imm) && (imm <= 0x1f));
code |= reg1; // rd
code |= reg2 << 5; // rj
code |= (imm & 0x1f) << 10; // ui5
}
else if ((INS_slli_d <= ins) && (ins <= INS_rotri_d))
{
#ifdef DEBUG
switch (ins)
{
case INS_slli_d:
case INS_srli_d:
case INS_srai_d:
case INS_rotri_d:
break;
default:
NYI_LOONGARCH64("illegal ins within emitIns_R_R_I --2!");
}
#endif
assert(isGeneralRegister(reg1));
assert(isGeneralRegisterOrR0(reg2));
assert((0 <= imm) && (imm <= 0x3f));
code |= reg1; // rd
code |= reg2 << 5; // rj
code |= (imm & 0x3f) << 10; // ui6
}
else if (((INS_addi_w <= ins) && (ins <= INS_xori)) || ((INS_ld_b <= ins) && (ins <= INS_ld_wu)) ||
((INS_st_b <= ins) && (ins <= INS_st_d)))
{
#ifdef DEBUG
assert(isGeneralRegister(reg1));
assert(isGeneralRegisterOrR0(reg2));
if (((INS_addi_w <= ins) && (ins <= INS_slti)) || ((INS_ld_b <= ins) && (ins <= INS_ld_wu)) ||
((INS_st_b <= ins) && (ins <= INS_st_d)))
{
switch (ins)
{
case INS_addi_w:
case INS_addi_d:
case INS_lu52i_d:
case INS_slti:
case INS_ld_b:
case INS_ld_h:
case INS_ld_w:
case INS_ld_d:
case INS_ld_bu:
case INS_ld_hu:
case INS_ld_wu:
case INS_st_b:
case INS_st_h:
case INS_st_w:
case INS_st_d:
break;
default:
NYI_LOONGARCH64("illegal ins within emitIns_R_R_I --3!");
}
assert((-2048 <= imm) && (imm <= 2047));
}
else if (ins == INS_sltui)
{
assert((0 <= imm) && (imm <= 0x7ff));
}
else
{
switch (ins)
{
case INS_andi:
case INS_ori:
case INS_xori:
break;
default:
NYI_LOONGARCH64("illegal ins within emitIns_R_R_I --4!");
}
assert((0 <= imm) && (imm <= 0xfff));
}
#endif
code |= reg1; // rd
code |= reg2 << 5; // rj
code |= (imm & 0xfff) << 10; // si12 or ui12
}
else if ((INS_fld_s <= ins) && (ins <= INS_fst_d))
{
#ifdef DEBUG
switch (ins)
{
case INS_fld_s:
case INS_fld_d:
case INS_fst_s:
case INS_fst_d:
break;
default:
NYI_LOONGARCH64("illegal ins within emitIns_R_R_I --5!");
}
#endif
assert(isFloatReg(reg1));
assert(isGeneralRegisterOrR0(reg2));
assert((-2048 <= imm) && (imm <= 2047));
code |= reg1 & 0x1f; // fd
code |= reg2 << 5; // rj
code |= (imm & 0xfff) << 10; // si12
}
else if (((INS_ll_d >= ins) && (ins >= INS_ldptr_w)) || ((INS_sc_d >= ins) && (ins >= INS_stptr_w)))
{
#ifdef DEBUG
switch (ins)
{
case INS_ldptr_w:
case INS_ldptr_d:
case INS_ll_w:
case INS_ll_d:
case INS_stptr_w:
case INS_stptr_d:
case INS_sc_w:
case INS_sc_d:
break;
default:
NYI_LOONGARCH64("illegal ins within emitIns_R_R_I --6!");
}
#endif
assert(isGeneralRegister(reg1));
assert(isGeneralRegisterOrR0(reg2));
assert((-8192 <= imm) && (imm <= 8191));
code |= reg1; // rd
code |= reg2 << 5; // rj
code |= (imm & 0x3fff) << 10; // si14
}
else if ((INS_beq <= ins) && (ins <= INS_bgeu))
{
#ifdef DEBUG
switch (ins)
{
case INS_beq:
case INS_bne:
case INS_blt:
case INS_bltu:
case INS_bge:
case INS_bgeu:
break;
default:
NYI_LOONGARCH64("illegal ins within emitIns_R_R_I --7!");
}
#endif
assert(isGeneralRegisterOrR0(reg1));
assert(isGeneralRegisterOrR0(reg2));
assert(!(imm & 0x3));
assert((-32768 <= (imm >> 2)) && ((imm >> 2) <= 32767));
code |= reg1 << 5; // rj
code |= reg2; // rd
code |= ((imm >> 2) & 0xffff) << 10; // offs16
}
else if ((INS_fcmp_caf_s <= ins) && (ins <= INS_fcmp_sune_s))
{
#ifdef DEBUG
switch (ins)
{
case INS_fcmp_caf_s:
case INS_fcmp_cun_s:
case INS_fcmp_ceq_s:
case INS_fcmp_cueq_s:
case INS_fcmp_clt_s:
case INS_fcmp_cult_s:
case INS_fcmp_cle_s:
case INS_fcmp_cule_s:
case INS_fcmp_cne_s:
case INS_fcmp_cor_s:
case INS_fcmp_cune_s:
case INS_fcmp_saf_d:
case INS_fcmp_sun_d:
case INS_fcmp_seq_d:
case INS_fcmp_sueq_d:
case INS_fcmp_slt_d:
case INS_fcmp_sult_d:
case INS_fcmp_sle_d:
case INS_fcmp_sule_d:
case INS_fcmp_sne_d:
case INS_fcmp_sor_d:
case INS_fcmp_sune_d:
case INS_fcmp_caf_d:
case INS_fcmp_cun_d:
case INS_fcmp_ceq_d:
case INS_fcmp_cueq_d:
case INS_fcmp_clt_d:
case INS_fcmp_cult_d:
case INS_fcmp_cle_d:
case INS_fcmp_cule_d:
case INS_fcmp_cne_d:
case INS_fcmp_cor_d:
case INS_fcmp_cune_d:
case INS_fcmp_saf_s:
case INS_fcmp_sun_s:
case INS_fcmp_seq_s:
case INS_fcmp_sueq_s:
case INS_fcmp_slt_s:
case INS_fcmp_sult_s:
case INS_fcmp_sle_s:
case INS_fcmp_sule_s:
case INS_fcmp_sne_s:
case INS_fcmp_sor_s:
case INS_fcmp_sune_s:
break;
default:
NYI_LOONGARCH64("illegal ins within emitIns_R_R_I --8!");
}
#endif
assert(isFloatReg(reg1));
assert(isFloatReg(reg2));
assert((0 <= imm) && (imm <= 7));
code |= (reg1 & 0x1f) << 5; // fj
code |= (reg2 & 0x1f) << 10; // fk
code |= imm & 0x7; // cc
}
else if (INS_addu16i_d == ins)
{
assert(isGeneralRegister(reg1));
assert(isGeneralRegisterOrR0(reg2));
assert((-32768 <= imm) && (imm < 32768));
code |= reg1; // rd
code |= reg2 << 5; // rj
code |= (imm & 0xffff) << 10; // si16
}
else if (INS_jirl == ins)
{
assert(isGeneralRegister(reg1));
assert(isGeneralRegisterOrR0(reg2));
assert((-32768 <= imm) && (imm < 32768));
code |= reg1; // rd
code |= reg2 << 5; // rj
code |= (imm & 0xffff) << 10; // offs16
}
#ifdef FEATURE_SIMD
else if (((INS_vseqi_b <= ins) && (ins <= INS_vmini_d)) || ((INS_xvseqi_b <= ins) && (ins <= INS_xvmin_d)))
{
assert(isVectorRegister(reg1));
assert(isVectorRegister(reg2));
assert((-16 <= imm) && (imm <= 15));
code |= reg1 & 0x1f; // vd/xd
code |= (reg2 & 0x1f) << 5; // vj/xj
code |= (imm & 0x1f) << 10; // si5
}
else if ((INS_vldrepl_d == ins) || (INS_xvldrepl_d == ins))
{
assert(isVectorRegister(reg1));
assert(isGeneralRegisterOrR0(reg2));
assert((-256 <= imm) && (imm <= 255));
code |= reg1 & 0x1f; // vd/xd
code |= (reg2 & 0x1f) << 5; // rj
code |= (imm & 0x1ff) << 10; // si9
}
else if ((INS_vldrepl_w == ins) || (INS_xvldrepl_w == ins))
{
assert(isVectorRegister(reg1));
assert(isGeneralRegisterOrR0(reg2));
assert((-512 <= imm) && (imm <= 511));
code |= reg1 & 0x1f; // vd/xd
code |= (reg2 & 0x1f) << 5; // rj
code |= (imm & 0x3ff) << 10; // si10
}
else if ((INS_vldrepl_h == ins) || (INS_xvldrepl_h == ins))
{
assert(isVectorRegister(reg1));
assert(isGeneralRegisterOrR0(reg2));
assert((-1024 <= imm) && (imm <= 1023));
code |= reg1 & 0x1f; // vd/xd
code |= (reg2 & 0x1f) << 5; // rj
code |= (imm & 0x7ff) << 10; // si11
}
else if (((INS_vld <= ins) && (ins <= INS_vst)) || ((INS_xvld <= ins) && (ins <= INS_xvst)))
{
assert(isVectorRegister(reg1));
assert(isGeneralRegisterOrR0(reg2));
assert((-2048 <= imm) && (imm <= 2047));
code |= reg1 & 0x1f; // vd(xd)
code |= (reg2 & 0x1f) << 5; // rj
code |= (imm & 0xfff) << 10; // si12
}
else if (((INS_vinsgr2vr_d <= ins) && (ins <= INS_vreplvei_d)) || (INS_xvrepl128vei_d == ins))
{
#ifdef DEBUG
if (INS_vinsgr2vr_d == ins)
{
assert(isVectorRegister(reg1)); // xd
assert(isGeneralRegisterOrR0(reg2)); // rj
}
else if ((INS_vreplvei_d == ins) || (INS_xvrepl128vei_d == ins))
{
assert(isVectorRegister(reg1)); // vd/xd
assert(isVectorRegister(reg2)); // vj/xj
}
else
{
assert(isGeneralRegisterOrR0(reg1)); // rd
assert(isVectorRegister(reg2)); // vj/xj
}
assert((0 <= imm) && (imm <= 1));
#endif
code |= reg1 & 0x1f;
code |= (reg2 & 0x1f) << 5;
code |= (imm & 0x1) << 10; // ui1
}
else if (((INS_vinsgr2vr_w <= ins) && (ins <= INS_vreplvei_w)) ||
((INS_xvinsve0_d <= ins) && (ins <= INS_xvpickve2gr_du)))
{
#ifdef DEBUG
if (INS_vinsgr2vr_w == ins)
{
assert(isVectorRegister(reg1)); // vd
assert(isGeneralRegisterOrR0(reg2)); // rj
}
else if ((INS_vpickve2gr_w <= ins) && (ins <= INS_vpickve2gr_wu))
{
assert(isGeneralRegisterOrR0(reg1)); // rd
assert(isVectorRegister(reg2)); // vj
}
else if (INS_vreplvei_w == ins)
{
assert(isVectorRegister(reg1)); // vd
assert(isVectorRegister(reg2)); // vj
}
else if ((INS_xvinsve0_d <= ins) && (ins <= INS_xvpickve_d))
{
assert(isVectorRegister(reg1)); // xd
assert(isVectorRegister(reg2)); // xj
}
else if (INS_xvinsgr2vr_d == ins)
{
assert(isVectorRegister(reg1)); // xd
assert(isGeneralRegisterOrR0(reg2)); // rj
}
else if ((INS_xvpickve2gr_d <= ins) && (ins <= INS_xvpickve2gr_du))
{
assert(isGeneralRegisterOrR0(reg1)); // rd
assert(isVectorRegister(reg2)); // xj
}
else
{
assert(isVectorRegister(reg1)); // xd/vd
assert(isVectorRegister(reg2)); // xj/vj
}
#endif
assert((0 <= imm) && (imm <= 3));
code |= reg1 & 0x1f; // xd/vd/rd
code |= (reg2 & 0x1f) << 5; // xj/vj/rj
code |= (imm & 0x3) << 10; // ui2
}
else if (((INS_vslli_b <= ins) && (ins <= INS_vreplvei_h)) || ((INS_xvslli_b <= ins) && (ins <= INS_xvsat_bu)))
{
#ifdef DEBUG
if ((INS_vinsgr2vr_h == ins) || (INS_xvinsgr2vr_w == ins))
{
// vd/xd, rj, ui3
assert(isVectorRegister(reg1)); // vd/xd
assert(isGeneralRegisterOrR0(reg2)); // rj
}
else if ((INS_vpickve2gr_h == ins) || (INS_vpickve2gr_hu == ins) || (INS_xvpickve2gr_w == ins) ||
(INS_xvpickve2gr_wu == ins))
{
// rd, vj/xj, ui3
assert(isGeneralRegisterOrR0(reg1)); // rd
assert(isVectorRegister(reg2)); // vj/xj
}
else
{
assert(isVectorRegister(reg1)); // vd/xd
assert(isVectorRegister(reg2)); // vj/xj
}
#endif
assert((0 <= imm) && (imm <= 7));
code |= reg1 & 0x1f; // vd(xd)
code |= (reg2 & 0x1f) << 5; // vj(xj)
code |= (imm & 0x7) << 10; // ui3
}
else if (((INS_vslli_h <= ins) && (ins <= INS_vreplvei_b)) || ((INS_xvslli_h <= ins) && (ins <= INS_xvsat_hu)))
{
#ifdef DEBUG
if (INS_vinsgr2vr_b == ins)
{
assert(isVectorRegister(reg1)); // vd/xd
assert(isGeneralRegisterOrR0(reg2)); // rj
}
else if (INS_vpickve2gr_b == ins)
{
assert(isGeneralRegisterOrR0(reg1)); // rd
assert(isVectorRegister(reg2)); // vj/xj
}
else if (INS_vpickve2gr_bu == ins)
{
assert(isGeneralRegisterOrR0(reg1)); // rd
assert(isVectorRegister(reg2)); // vj/xj
}
else
{
assert(isVectorRegister(reg1)); // vd/xd
assert(isVectorRegister(reg2)); // vj/xj
}
#endif
assert((0 <= imm) && (imm <= 15));
code |= reg1 & 0x1f; // vd
code |= (reg2 & 0x1f) << 5; // vj
code |= (imm & 0xf) << 10; // ui4
}
else if (((INS_vslei_bu <= ins) && (ins <= INS_vsat_wu)) || ((INS_xvslei_bu <= ins) && (ins <= INS_xvsat_wu)))
{
assert(isVectorRegister(reg1)); // vd/xd
assert(isVectorRegister(reg2)); // vj/xj
assert((0 <= imm) && (imm <= 31));
code |= reg1 & 0x1f; // vd
code |= (reg2 & 0x1f) << 5; // vj
code |= (imm & 0x1f) << 10; // ui5
}
else if (((INS_vslli_d <= ins) && (ins <= INS_vsat_du)) || ((INS_xvslli_d <= ins) && (ins <= INS_xvsat_du)))
{
assert(isVectorRegister(reg1)); // vd/xd
assert(isVectorRegister(reg2)); // vj/xj
assert((0 <= imm) && (imm <= 63));
code |= reg1 & 0x1f; // vd
code |= (reg2 & 0x1f) << 5; // vj
code |= (imm & 0x3f) << 10; // ui6
}
else if (((INS_vsrlni_d_q <= ins) && (ins <= INS_vssrarni_du_q)) ||
((INS_xvsrlni_d_q <= ins) && (ins <= INS_xvssrarni_du_q)))
{
assert(isVectorRegister(reg1)); // vd/xd
assert(isVectorRegister(reg2)); // vj/xj
assert((0 <= imm) && (imm <= 127));
code |= reg1 & 0x1f; // vd
code |= (reg2 & 0x1f) << 5; // vj
code |= (imm & 0x7f) << 10; // ui7
}
else if (((INS_vextrins_d <= ins) && (ins <= INS_vpermi_w)) || ((INS_xvextrins_d <= ins) && (ins <= INS_xvpermi_q)))
{
assert(isVectorRegister(reg1)); // vd/xd
assert(isVectorRegister(reg2)); // vj/xj
assert((0 <= imm) && (imm <= 255));
code |= reg1 & 0x1f; // vd
code |= (reg2 & 0x1f) << 5; // vj
code |= (imm & 0xff) << 10; // ui8
}
#endif
else
{
unreached();
}
instrDesc* id = emitNewInstr(attr);
id->idIns(ins);
id->idReg1(reg1);
id->idReg2(reg2);
id->idAddr()->iiaSetInstrEncode(code);
id->idCodeSize(4);
appendToCurIG(id);
}