Various rounding instructions.
This commit is contained in:
parent
35ef6df1fc
commit
478781e0dc
|
@ -1020,36 +1020,87 @@ int Translate_CONVERT(TranslationContext& ctx, Instr* i) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t IntCode_ROUND_F32(IntCodeState& ics, const IntCode* i) {
|
uint32_t IntCode_ROUND_F32(IntCodeState& ics, const IntCode* i) {
|
||||||
if (i->flags == ROUND_TO_NEAREST) {
|
float src1 = ics.rf[i->src1_reg].f32;
|
||||||
ics.rf[i->dest_reg].f32 = round(ics.rf[i->src1_reg].f32);
|
float dest = src1;
|
||||||
} else {
|
switch (i->flags) {
|
||||||
ics.rf[i->dest_reg].f32 = floor(ics.rf[i->src1_reg].f32);
|
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;
|
return IA_NEXT;
|
||||||
}
|
}
|
||||||
uint32_t IntCode_ROUND_F64(IntCodeState& ics, const IntCode* i) {
|
uint32_t IntCode_ROUND_F64(IntCodeState& ics, const IntCode* i) {
|
||||||
if (i->flags == ROUND_TO_NEAREST) {
|
double src1 = ics.rf[i->src1_reg].f64;
|
||||||
ics.rf[i->dest_reg].f64 = round(ics.rf[i->src1_reg].f64);
|
double dest = src1;
|
||||||
} else {
|
switch (i->flags) {
|
||||||
ics.rf[i->dest_reg].f64 = floor(ics.rf[i->src1_reg].f64);
|
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;
|
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;
|
const vec128_t& src1 = ics.rf[i->src1_reg].v128;
|
||||||
vec128_t& dest = ics.rf[i->dest_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++) {
|
for (size_t n = 0; n < 4; n++) {
|
||||||
dest.f4[n] = round(src1.f4[n]);
|
dest.f4[n] = roundf(src1.f4[n]);
|
||||||
}
|
}
|
||||||
} else {
|
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++) {
|
for (size_t n = 0; n < 4; n++) {
|
||||||
dest.f4[n] = floor(src1.f4[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;
|
return IA_NEXT;
|
||||||
}
|
}
|
||||||
int Translate_ROUND(TranslationContext& ctx, Instr* i) {
|
int Translate_ROUND(TranslationContext& ctx, Instr* i) {
|
||||||
|
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[] = {
|
static IntCodeFn fns[] = {
|
||||||
IntCode_INVALID_TYPE,
|
IntCode_INVALID_TYPE,
|
||||||
IntCode_INVALID_TYPE,
|
IntCode_INVALID_TYPE,
|
||||||
|
@ -1057,9 +1108,10 @@ int Translate_ROUND(TranslationContext& ctx, Instr* i) {
|
||||||
IntCode_INVALID_TYPE,
|
IntCode_INVALID_TYPE,
|
||||||
IntCode_ROUND_F32,
|
IntCode_ROUND_F32,
|
||||||
IntCode_ROUND_F64,
|
IntCode_ROUND_F64,
|
||||||
IntCode_ROUND_V128,
|
IntCode_INVALID_TYPE,
|
||||||
};
|
};
|
||||||
return DispatchToC(ctx, i, fns[i->dest->type]);
|
return DispatchToC(ctx, i, fns[i->dest->type]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t IntCode_VECTOR_CONVERT_I2F(IntCodeState& ics, const IntCode* i) {
|
uint32_t IntCode_VECTOR_CONVERT_I2F(IntCodeState& ics, const IntCode* i) {
|
||||||
|
|
|
@ -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);
|
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) {
|
XEEMITTER(vrfim, 0x100002CA, VX )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
return InstrEmit_vrfim_(f, i.VX.VD, i.VX.VB);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
XEEMITTER(vrfim128, VX128_3(6, 816), VX128_3)(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(vrfim128, VX128_3(6, 816), VX128_3)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
return InstrEmit_vrfim_(f, VX128_3_VD128, VX128_3_VB128);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int InstrEmit_vrfin_(PPCHIRBuilder& f, uint32_t vd, uint32_t vb) {
|
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);
|
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) {
|
XEEMITTER(vrfip, 0x1000028A, VX )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
return InstrEmit_vrfip_(f, i.VX.VD, i.VX.VB);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
XEEMITTER(vrfip128, VX128_3(6, 944), VX128_3)(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(vrfip128, VX128_3(6, 944), VX128_3)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
return InstrEmit_vrfip_(f, VX128_3_VD128, VX128_3_VB128);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
XEEMITTER(vrfiz, 0x1000024A, VX )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
return InstrEmit_vrfiz_(f, i.VX.VD, i.VX.VB);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
XEEMITTER(vrfiz128, VX128_3(6, 1008), VX128_3)(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(vrfiz128, VX128_3(6, 1008), VX128_3)(PPCHIRBuilder& f, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
return InstrEmit_vrfiz_(f, VX128_3_VD128, VX128_3_VB128);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(vrlb, 0x10000004, VX )(PPCHIRBuilder& f, InstrData& i) {
|
XEEMITTER(vrlb, 0x10000004, VX )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
|
|
|
@ -28,6 +28,8 @@ enum RoundMode {
|
||||||
// to zero/nearest/etc
|
// to zero/nearest/etc
|
||||||
ROUND_TO_ZERO = 0,
|
ROUND_TO_ZERO = 0,
|
||||||
ROUND_TO_NEAREST,
|
ROUND_TO_NEAREST,
|
||||||
|
ROUND_TO_MINUS_INFINITY,
|
||||||
|
ROUND_TO_POSITIVE_INFINITY,
|
||||||
};
|
};
|
||||||
enum LoadFlags {
|
enum LoadFlags {
|
||||||
LOAD_NO_ALIAS = (1 << 1),
|
LOAD_NO_ALIAS = (1 << 1),
|
||||||
|
|
Loading…
Reference in New Issue