diff --git a/src/alloy/backend/ivm/ivm_intcode.cc b/src/alloy/backend/ivm/ivm_intcode.cc index 30edbee25..d21341e2b 100644 --- a/src/alloy/backend/ivm/ivm_intcode.cc +++ b/src/alloy/backend/ivm/ivm_intcode.cc @@ -1020,46 +1020,98 @@ int Translate_CONVERT(TranslationContext& ctx, Instr* i) { } uint32_t IntCode_ROUND_F32(IntCodeState& ics, const IntCode* i) { - if (i->flags == ROUND_TO_NEAREST) { - ics.rf[i->dest_reg].f32 = round(ics.rf[i->src1_reg].f32); - } else { - ics.rf[i->dest_reg].f32 = floor(ics.rf[i->src1_reg].f32); + float src1 = ics.rf[i->src1_reg].f32; + float dest = src1; + switch (i->flags) { + case ROUND_TO_ZERO: + dest = truncf(src1); + break; + case ROUND_TO_NEAREST: + dest = roundf(src1); + break; + case ROUND_TO_MINUS_INFINITY: + dest = floorf(src1); + break; + case ROUND_TO_POSITIVE_INFINITY: + dest = ceilf(src1); + break; } + ics.rf[i->dest_reg].f32 = dest; return IA_NEXT; } uint32_t IntCode_ROUND_F64(IntCodeState& ics, const IntCode* i) { - if (i->flags == ROUND_TO_NEAREST) { - ics.rf[i->dest_reg].f64 = round(ics.rf[i->src1_reg].f64); - } else { - ics.rf[i->dest_reg].f64 = floor(ics.rf[i->src1_reg].f64); + double src1 = ics.rf[i->src1_reg].f64; + double dest = src1; + switch (i->flags) { + case ROUND_TO_ZERO: + dest = trunc(src1); + break; + case ROUND_TO_NEAREST: + dest = round(src1); + break; + case ROUND_TO_MINUS_INFINITY: + dest = floor(src1); + break; + case ROUND_TO_POSITIVE_INFINITY: + dest = ceil(src1); + break; + } + ics.rf[i->dest_reg].f64 = dest; + return IA_NEXT; +} +uint32_t IntCode_ROUND_V128_ZERO(IntCodeState& ics, const IntCode* i) { + const vec128_t& src1 = ics.rf[i->src1_reg].v128; + vec128_t& dest = ics.rf[i->dest_reg].v128; + for (size_t n = 0; n < 4; n++) { + dest.f4[n] = truncf(src1.f4[n]); } return IA_NEXT; } -uint32_t IntCode_ROUND_V128(IntCodeState& ics, const IntCode* i) { +uint32_t IntCode_ROUND_V128_NEAREST(IntCodeState& ics, const IntCode* i) { const vec128_t& src1 = ics.rf[i->src1_reg].v128; vec128_t& dest = ics.rf[i->dest_reg].v128; - if (i->flags == ROUND_TO_NEAREST) { - for (size_t n = 0; n < 4; n++) { - dest.f4[n] = round(src1.f4[n]); - } - } else { - for (size_t n = 0; n < 4; n++) { - dest.f4[n] = floor(src1.f4[n]); - } + for (size_t n = 0; n < 4; n++) { + dest.f4[n] = roundf(src1.f4[n]); + } + return IA_NEXT; +} +uint32_t IntCode_ROUND_V128_MINUS_INFINITY(IntCodeState& ics, const IntCode* i) { + const vec128_t& src1 = ics.rf[i->src1_reg].v128; + vec128_t& dest = ics.rf[i->dest_reg].v128; + for (size_t n = 0; n < 4; n++) { + dest.f4[n] = floorf(src1.f4[n]); + } + return IA_NEXT; +} +uint32_t IntCode_ROUND_V128_POSITIVE_INFINTIY(IntCodeState& ics, const IntCode* i) { + const vec128_t& src1 = ics.rf[i->src1_reg].v128; + vec128_t& dest = ics.rf[i->dest_reg].v128; + for (size_t n = 0; n < 4; n++) { + dest.f4[n] = ceilf(src1.f4[n]); } return IA_NEXT; } int Translate_ROUND(TranslationContext& ctx, Instr* i) { - static IntCodeFn fns[] = { - IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - IntCode_INVALID_TYPE, - IntCode_ROUND_F32, - IntCode_ROUND_F64, - IntCode_ROUND_V128, - }; - return DispatchToC(ctx, i, fns[i->dest->type]); + if (i->dest->type == VEC128_TYPE) { + static IntCodeFn fns[] = { + IntCode_ROUND_V128_ZERO, + IntCode_ROUND_V128_NEAREST, + IntCode_ROUND_V128_MINUS_INFINITY, + IntCode_ROUND_V128_POSITIVE_INFINTIY, + }; + return DispatchToC(ctx, i, fns[i->flags]); + } else { + static IntCodeFn fns[] = { + IntCode_INVALID_TYPE, + IntCode_INVALID_TYPE, + IntCode_INVALID_TYPE, + IntCode_INVALID_TYPE, + IntCode_ROUND_F32, + IntCode_ROUND_F64, + IntCode_INVALID_TYPE, + }; + return DispatchToC(ctx, i, fns[i->dest->type]); + } } uint32_t IntCode_VECTOR_CONVERT_I2F(IntCodeState& ics, const IntCode* i) { diff --git a/src/alloy/frontend/ppc/ppc_emit_altivec.cc b/src/alloy/frontend/ppc/ppc_emit_altivec.cc index 01e4080cd..dec80b3ff 100644 --- a/src/alloy/frontend/ppc/ppc_emit_altivec.cc +++ b/src/alloy/frontend/ppc/ppc_emit_altivec.cc @@ -1183,13 +1183,17 @@ XEEMITTER(vrefp128, VX128_3(6, 1584), VX128_3)(PPCHIRBuilder& f, InstrData return InstrEmit_vrefp_(f, VX128_3_VD128, VX128_3_VB128); } +int InstrEmit_vrfim_(PPCHIRBuilder& f, uint32_t vd, uint32_t vb) { + // (VD) <- RndToFPInt32Floor(VB) + Value* v = f.Round(f.LoadVR(vb), ROUND_TO_MINUS_INFINITY); + f.StoreVR(vd, v); + return 0; +} XEEMITTER(vrfim, 0x100002CA, VX )(PPCHIRBuilder& f, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + return InstrEmit_vrfim_(f, i.VX.VD, i.VX.VB); } XEEMITTER(vrfim128, VX128_3(6, 816), VX128_3)(PPCHIRBuilder& f, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + return InstrEmit_vrfim_(f, VX128_3_VD128, VX128_3_VB128); } int InstrEmit_vrfin_(PPCHIRBuilder& f, uint32_t vd, uint32_t vb) { @@ -1205,22 +1209,30 @@ XEEMITTER(vrfin128, VX128_3(6, 880), VX128_3)(PPCHIRBuilder& f, InstrData return InstrEmit_vrfin_(f, VX128_3_VD128, VX128_3_VB128); } +int InstrEmit_vrfip_(PPCHIRBuilder& f, uint32_t vd, uint32_t vb) { + // (VD) <- RndToFPInt32Ceil(VB) + Value* v = f.Round(f.LoadVR(vb), ROUND_TO_POSITIVE_INFINITY); + f.StoreVR(vd, v); + return 0; +} XEEMITTER(vrfip, 0x1000028A, VX )(PPCHIRBuilder& f, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + return InstrEmit_vrfip_(f, i.VX.VD, i.VX.VB); } XEEMITTER(vrfip128, VX128_3(6, 944), VX128_3)(PPCHIRBuilder& f, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + return InstrEmit_vrfip_(f, VX128_3_VD128, VX128_3_VB128); } +int InstrEmit_vrfiz_(PPCHIRBuilder& f, uint32_t vd, uint32_t vb) { + // (VD) <- RndToFPInt32Trunc(VB) + Value* v = f.Round(f.LoadVR(vb), ROUND_TO_ZERO); + f.StoreVR(vd, v); + return 0; +} XEEMITTER(vrfiz, 0x1000024A, VX )(PPCHIRBuilder& f, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + return InstrEmit_vrfiz_(f, i.VX.VD, i.VX.VB); } XEEMITTER(vrfiz128, VX128_3(6, 1008), VX128_3)(PPCHIRBuilder& f, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + return InstrEmit_vrfiz_(f, VX128_3_VD128, VX128_3_VB128); } XEEMITTER(vrlb, 0x10000004, VX )(PPCHIRBuilder& f, InstrData& i) { diff --git a/src/alloy/hir/opcodes.h b/src/alloy/hir/opcodes.h index 67f49c8ee..a1beb23a6 100644 --- a/src/alloy/hir/opcodes.h +++ b/src/alloy/hir/opcodes.h @@ -28,6 +28,8 @@ enum RoundMode { // to zero/nearest/etc ROUND_TO_ZERO = 0, ROUND_TO_NEAREST, + ROUND_TO_MINUS_INFINITY, + ROUND_TO_POSITIVE_INFINITY, }; enum LoadFlags { LOAD_NO_ALIAS = (1 << 1),