riscv: Implement simplest float ops.

This commit is contained in:
Unknown W. Brackets 2023-07-24 22:58:23 -07:00
parent bb6fdd0246
commit 05360d5c7a
3 changed files with 60 additions and 4 deletions

View file

@ -768,9 +768,11 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) {
mips->f[inst->dest] = mips->f[inst->src1] / mips->f[inst->src2];
break;
case IROp::FMin:
// TODO: This doesn't handle VFPU ordering right.
mips->f[inst->dest] = std::min(mips->f[inst->src1], mips->f[inst->src2]);
break;
case IROp::FMax:
// TODO: This doesn't handle VFPU ordering right.
mips->f[inst->dest] = std::max(mips->f[inst->src1], mips->f[inst->src2]);
break;

View file

@ -39,12 +39,37 @@ void RiscVJit::CompIR_FArith(IRInst inst) {
switch (inst.op) {
case IROp::FAdd:
fpr.MapDirtyInIn(inst.dest, inst.src1, inst.src2);
FADD(32, fpr.R(inst.dest), fpr.R(inst.src1), fpr.R(inst.src2));
break;
case IROp::FSub:
fpr.MapDirtyInIn(inst.dest, inst.src1, inst.src2);
FSUB(32, fpr.R(inst.dest), fpr.R(inst.src1), fpr.R(inst.src2));
break;
case IROp::FMul:
fpr.MapDirtyInIn(inst.dest, inst.src1, inst.src2);
if (inst.src1 != inst.src2) {
CompIR_Generic(inst);
} else {
FMUL(32, fpr.R(inst.dest), fpr.R(inst.src1), fpr.R(inst.src2));
}
break;
case IROp::FDiv:
fpr.MapDirtyInIn(inst.dest, inst.src1, inst.src2);
FDIV(32, fpr.R(inst.dest), fpr.R(inst.src1), fpr.R(inst.src2));
break;
case IROp::FSqrt:
fpr.MapDirtyIn(inst.dest, inst.src1);
FSQRT(32, fpr.R(inst.dest), fpr.R(inst.src1));
break;
case IROp::FNeg:
CompIR_Generic(inst);
fpr.MapDirtyIn(inst.dest, inst.src1);
FNEG(32, fpr.R(inst.dest), fpr.R(inst.src1));
break;
default:
@ -59,6 +84,7 @@ void RiscVJit::CompIR_FCondAssign(IRInst inst) {
switch (inst.op) {
case IROp::FMin:
case IROp::FMax:
// TODO: These are tricky, have to handle order correctly.
CompIR_Generic(inst);
break;
@ -73,7 +99,15 @@ void RiscVJit::CompIR_FAssign(IRInst inst) {
switch (inst.op) {
case IROp::FMov:
fpr.MapDirtyIn(inst.dest, inst.src1);
FMV(32, fpr.R(inst.dest), fpr.R(inst.src1));
break;
case IROp::FAbs:
fpr.MapDirtyIn(inst.dest, inst.src1);
FABS(32, fpr.R(inst.dest), fpr.R(inst.src1));
break;
case IROp::FSign:
CompIR_Generic(inst);
break;

View file

@ -50,7 +50,14 @@ void RiscVJit::CompIR_Basic(IRInst inst) {
break;
case IROp::SetConstF:
CompIR_Generic(inst);
fpr.MapReg(inst.dest, MIPSMap::NOINIT);
if (inst.constant == 0) {
FCVT(FConv::S, FConv::W, fpr.R(inst.dest), R_ZERO);
} else {
// TODO: In the future, could use FLI if it's approved.
LI(SCRATCH1, (int32_t)inst.constant);
FMV(FMv::W, FMv::X, fpr.R(inst.dest), SCRATCH1);
}
break;
case IROp::Downcount:
@ -93,7 +100,9 @@ void RiscVJit::CompIR_Transfer(IRInst inst) {
break;
case IROp::SetCtrlVFPUFReg:
CompIR_Generic(inst);
gpr.MapReg(IRREG_VFPU_CTRL_BASE + inst.dest, MIPSMap::NOINIT);
fpr.MapReg(inst.src1);
FMV(FMv::X, FMv::W, gpr.R(IRREG_VFPU_CTRL_BASE + inst.dest), fpr.R(inst.src1));
break;
case IROp::FpCondToReg:
@ -113,8 +122,19 @@ void RiscVJit::CompIR_Transfer(IRInst inst) {
break;
case IROp::FMovFromGPR:
fpr.MapReg(inst.dest, MIPSMap::NOINIT);
if (gpr.IsImm(inst.src1) && gpr.GetImm(inst.src1) == 0) {
FCVT(FConv::S, FConv::W, fpr.R(inst.dest), R_ZERO);
} else {
gpr.MapReg(inst.src1);
FMV(FMv::W, FMv::X, fpr.R(inst.dest), gpr.R(inst.src1));
}
break;
case IROp::FMovToGPR:
CompIR_Generic(inst);
gpr.MapReg(inst.dest, MIPSMap::NOINIT);
fpr.MapReg(inst.src1);
FMV(FMv::X, FMv::W, gpr.R(inst.dest), fpr.R(inst.src1));
break;
default: