Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RISC-V] Flush-to-zero behavior for float-to-int conversion #94762

Merged
merged 14 commits into from
Dec 7, 2023
8 changes: 8 additions & 0 deletions src/coreclr/jit/codegenriscv64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3374,8 +3374,16 @@ void CodeGen::genFloatToIntCast(GenTree* treeNode)
}

genConsumeOperands(treeNode->AsOp());
regNumber tmpReg = rsGetRsvdReg();
denis-paranichev marked this conversation as resolved.
Show resolved Hide resolved

GetEmitter()->emitIns_R_R(ins, EA_8BYTE, treeNode->GetRegNum(), op1->GetRegNum());

// This part emulates the "flush to zero" option because the RISC-V specification does not provide it.
GetEmitter()->emitIns_R_I_I(INS_csrrci, EA_8BYTE, tmpReg, 22, 1);
denis-paranichev marked this conversation as resolved.
Show resolved Hide resolved
denis-paranichev marked this conversation as resolved.
Show resolved Hide resolved
GetEmitter()->emitIns_R_R_I(INS_andi, EA_8BYTE, tmpReg, tmpReg, 22);
denis-paranichev marked this conversation as resolved.
Show resolved Hide resolved
GetEmitter()->emitIns_R_R_I(INS_beq, EA_8BYTE, tmpReg, REG_R0, 8);
denis-paranichev marked this conversation as resolved.
Show resolved Hide resolved
GetEmitter()->emitIns_R_R_I(INS_addiw, EA_8BYTE, treeNode->GetRegNum(), REG_R0, 0);
denis-paranichev marked this conversation as resolved.
Show resolved Hide resolved

if (dstSize == EA_4BYTE)

{
Expand Down
78 changes: 78 additions & 0 deletions src/coreclr/jit/emitriscv64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,12 @@ void emitter::emitIns_R_R_I(
code |= ((imm >> 5) & 0x3f) << 25;
code |= ((imm >> 12) & 0x1) << 31;
}
else if (ins == INS_csrrs || ins == INS_csrrw || ins == INS_csrrc)
denis-paranichev marked this conversation as resolved.
Show resolved Hide resolved
{
code |= reg1 << 7;
code |= reg2 << 15;
code |= imm << 20;
}
else
{
NYI_RISCV64("illegal ins within emitIns_R_R_I!");
Expand All @@ -715,6 +721,36 @@ void emitter::emitIns_R_R_I(
appendToCurIG(id);
}

/*****************************************************************************
*
* Add an instruction referencing register and two constants.
*/

void emitter::emitIns_R_I_I(
instruction ins, emitAttr attr, regNumber reg1, ssize_t imm1, ssize_t imm2, insOpts opt) /* = INS_OPTS_NONE */
denis-paranichev marked this conversation as resolved.
Show resolved Hide resolved
{
code_t code = emitInsCode(ins);

if (INS_csrrwi <= ins && ins <= INS_csrrci)
{
code |= reg1 << 7;
code |= imm1 << 15;
code |= imm2 << 20;
denis-paranichev marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
NYI_RISCV64("illegal ins within emitIns_R_I_I!");
}
instrDesc* id = emitNewInstr(attr);

id->idIns(ins);
id->idReg1(reg1);
id->idAddr()->iiaSetInstrEncode(code);
id->idCodeSize(4);

appendToCurIG(id);
}

/*****************************************************************************
*
* Add an instruction referencing three registers.
Expand Down Expand Up @@ -3360,6 +3396,48 @@ void emitter::emitDisInsName(code_t code, const BYTE* addr, instrDesc* id)
}
case 0x73:
{
unsigned int opcode2 = (code >> 12) & 0x7;
const char* rd = RegNames[(code >> 7) & 0x1f];
int csrtype = (((int)code) >> 20);
if (opcode2 <= 0x3)
{
const char* rs1 = RegNames[(code >> 15) & 0x1f];
switch (opcode2)
{
case 0x1: // CSRRW
printf("csrrw %s, %d, %s\n", rd, csrtype, rs1);
return;
case 0x2: // CSRRS
printf("csrrs %s, %d, %s\n", rd, csrtype, rs1);
return;
case 0x3: // CSRRC
printf("csrrc %s, %d, %s\n", rd, csrtype, rs1);
return;
default:
printf("RISCV64 illegal instruction: 0x%08X\n", code);
denis-paranichev marked this conversation as resolved.
Show resolved Hide resolved
break;
}
}
else
{
int imm12 = (((int)code) >> 15);
denis-paranichev marked this conversation as resolved.
Show resolved Hide resolved
switch (opcode2)
{
case 0x5: // CSRRW
denis-paranichev marked this conversation as resolved.
Show resolved Hide resolved
printf("csrrwi %s, %d, %s\n", rd, csrtype, imm12);
return;
case 0x6: // CSRRS
printf("csrrsi %s, %d, %s\n", rd, csrtype, imm12);
return;
case 0x7: // CSRRC
printf("csrrci %s, %d, %s\n", rd, csrtype, imm12);
return;
default:
printf("RISCV64 illegal instruction: 0x%08X\n", code);
break;
}
}

if (code == emitInsCode(INS_ebreak))
{
printf("ebreak\n");
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/jit/emitriscv64.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ void emitIns_R_R(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2,
void emitIns_R_R_I(
instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt = INS_OPTS_NONE);

void emitIns_R_I_I(
instruction ins, emitAttr attr, regNumber reg1, ssize_t imm1, ssize_t imm2, insOpts opt = INS_OPTS_NONE);

void emitIns_R_R_R(
instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt = INS_OPTS_NONE);

Expand Down
Loading