mirror of https://git.suyu.dev/suyu/suyu
glasm: Review all GLASM insts to be aware of register aliasing
This commit is contained in:
parent
c4fd6b55bc
commit
70fbede213
|
@ -41,10 +41,23 @@ template <typename ObjectType>
|
||||||
void CompositeInsert(EmitContext& ctx, IR::Inst& inst, Register composite, ObjectType object,
|
void CompositeInsert(EmitContext& ctx, IR::Inst& inst, Register composite, ObjectType object,
|
||||||
u32 index, char type) {
|
u32 index, char type) {
|
||||||
const Register ret{ctx.reg_alloc.Define(inst)};
|
const Register ret{ctx.reg_alloc.Define(inst)};
|
||||||
if (ret != composite) {
|
const char swizzle{"xyzw"[index]};
|
||||||
ctx.Add("MOV.{} {},{};", type, ret, composite);
|
if (ret != composite && ret == object) {
|
||||||
|
// The object is aliased with the return value, so we have to use a temporary to insert
|
||||||
|
ctx.Add("MOV.{} RC,{};"
|
||||||
|
"MOV.{} RC.{},{};"
|
||||||
|
"MOV.{} {},RC;",
|
||||||
|
type, composite, type, swizzle, object, type, ret);
|
||||||
|
} else if (ret != composite) {
|
||||||
|
// The input composite is not aliased with the return value so we have to copy it before
|
||||||
|
// hand. But the insert object is not aliased with the return value, so we don't have to
|
||||||
|
// worry about that
|
||||||
|
ctx.Add("MOV.{} {},{};MOV.{},{}.{},{};", type, ret, composite, type, ret, swizzle, object);
|
||||||
|
} else {
|
||||||
|
// The return value is alised so we can just insert the object, it doesn't matter if it's
|
||||||
|
// aliased
|
||||||
|
ctx.Add("MOV.{} {}.{},{};", type, ret, swizzle, object);
|
||||||
}
|
}
|
||||||
ctx.Add("MOV.{} {}.{},{};", type, ret, "xyzw"[index], object);
|
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
|
|
@ -38,9 +38,9 @@ template <typename InputType>
|
||||||
void Clamp(EmitContext& ctx, Register ret, InputType value, InputType min_value,
|
void Clamp(EmitContext& ctx, Register ret, InputType value, InputType min_value,
|
||||||
InputType max_value, std::string_view type) {
|
InputType max_value, std::string_view type) {
|
||||||
// Call MAX first to properly clamp nan to min_value instead
|
// Call MAX first to properly clamp nan to min_value instead
|
||||||
ctx.Add("MAX.{} {}.x,{},{};"
|
ctx.Add("MAX.{} RC.x,{},{};"
|
||||||
"MIN.{} {}.x,{}.x,{};",
|
"MIN.{} {}.x,RC.x,{};",
|
||||||
type, ret, min_value, value, type, ret, ret, max_value);
|
type, min_value, value, type, ret, max_value);
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
@ -159,7 +159,7 @@ void EmitFPRecipSqrt64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Regis
|
||||||
|
|
||||||
void EmitFPSqrt(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) {
|
void EmitFPSqrt(EmitContext& ctx, IR::Inst& inst, ScalarF32 value) {
|
||||||
const Register ret{ctx.reg_alloc.Define(inst)};
|
const Register ret{ctx.reg_alloc.Define(inst)};
|
||||||
ctx.Add("RSQ {}.x,{};RCP {}.x,{}.x;", ret, value, ret, ret);
|
ctx.Add("RSQ RC.x,{};RCP {}.x,RC.x;", value, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitFPSaturate16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) {
|
void EmitFPSaturate16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) {
|
||||||
|
|
|
@ -87,20 +87,38 @@ void EmitBitwiseXor32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b
|
||||||
|
|
||||||
void EmitBitFieldInsert(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, ScalarS32 insert,
|
void EmitBitFieldInsert(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, ScalarS32 insert,
|
||||||
ScalarS32 offset, ScalarS32 count) {
|
ScalarS32 offset, ScalarS32 count) {
|
||||||
ctx.Add("MOV.U RC.x,{};MOV.U RC.y,{};", count, offset);
|
const Register ret{ctx.reg_alloc.Define(inst)};
|
||||||
ctx.Add("BFI.S {},RC,{},{};", inst, insert, base);
|
if (count.type != Type::Register && offset.type != Type::Register) {
|
||||||
|
ctx.Add("BFI.S {},{{{},{},0,0}},{},{};", ret, count, offset, insert, base);
|
||||||
|
} else {
|
||||||
|
ctx.Add("MOV.S RC.x,{};MOV.U RC.y,{};"
|
||||||
|
"BFI.S {},RC,{},{};",
|
||||||
|
count, offset, ret, insert, base);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, ScalarS32 offset,
|
void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, ScalarS32 offset,
|
||||||
ScalarS32 count) {
|
ScalarS32 count) {
|
||||||
ctx.Add("MOV.U RC.x,{};MOV.U RC.y,{};", count, offset);
|
const Register ret{ctx.reg_alloc.Define(inst)};
|
||||||
ctx.Add("BFE.S {},RC,{};", inst, base);
|
if (count.type != Type::Register && offset.type != Type::Register) {
|
||||||
|
ctx.Add("BFE.S {},{{{},{},0,0}},{};", ret, count, offset, base);
|
||||||
|
} else {
|
||||||
|
ctx.Add("MOV.S RC.x,{};MOV.U RC.y,{};"
|
||||||
|
"BFE.S {},RC,{};",
|
||||||
|
count, offset, ret, base);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 offset,
|
void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 offset,
|
||||||
ScalarU32 count) {
|
ScalarU32 count) {
|
||||||
ctx.Add("MOV.U RC.x,{};MOV.U RC.y,{};", count, offset);
|
const Register ret{ctx.reg_alloc.Define(inst)};
|
||||||
ctx.Add("BFE.U {},RC,{};", inst, base);
|
if (count.type != Type::Register && offset.type != Type::Register) {
|
||||||
|
ctx.Add("BFE.U {},{{{},{},0,0}},{};", ret, count, offset, base);
|
||||||
|
} else {
|
||||||
|
ctx.Add("MOV.U RC.x,{};MOV.U RC.y,{};"
|
||||||
|
"BFE.U {},RC,{};",
|
||||||
|
count, offset, ret, base);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitBitReverse32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) {
|
void EmitBitReverse32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) {
|
||||||
|
@ -141,16 +159,16 @@ void EmitUMax32(EmitContext& ctx, IR::Inst& inst, ScalarU32 a, ScalarU32 b) {
|
||||||
|
|
||||||
void EmitSClamp32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value, ScalarS32 min, ScalarS32 max) {
|
void EmitSClamp32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value, ScalarS32 min, ScalarS32 max) {
|
||||||
const Register ret{ctx.reg_alloc.Define(inst)};
|
const Register ret{ctx.reg_alloc.Define(inst)};
|
||||||
ctx.Add("MIN.S {}.x,{},{};"
|
ctx.Add("MIN.S RC.x,{},{};"
|
||||||
"MAX.S {}.x,{},{};",
|
"MAX.S {}.x,RC.x,{};",
|
||||||
ret, max, value, ret, ret, min);
|
max, value, ret, min);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitUClamp32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 min, ScalarU32 max) {
|
void EmitUClamp32(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 min, ScalarU32 max) {
|
||||||
const Register ret{ctx.reg_alloc.Define(inst)};
|
const Register ret{ctx.reg_alloc.Define(inst)};
|
||||||
ctx.Add("MIN.U {}.x,{},{};"
|
ctx.Add("MIN.U RC.x,{},{};"
|
||||||
"MAX.U {}.x,{},{};",
|
"MAX.U {}.x,RC.x,{};",
|
||||||
ret, max, value, ret, ret, min);
|
max, value, ret, min);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitSLessThan(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs) {
|
void EmitSLessThan(EmitContext& ctx, IR::Inst& inst, ScalarS32 lhs, ScalarS32 rhs) {
|
||||||
|
|
|
@ -43,7 +43,7 @@ void EmitSelectU64(EmitContext& ctx, IR::Inst& inst, ScalarS32 cond, Register tr
|
||||||
cond, ret, true_value);
|
cond, ret, true_value);
|
||||||
} else {
|
} else {
|
||||||
ctx.Add("MOV.S.CC RC.x,{};"
|
ctx.Add("MOV.S.CC RC.x,{};"
|
||||||
"MOV.U64 {}.x(EQ.x),{};"
|
"MOV.U64 {}.x,{};"
|
||||||
"MOV.U64 {}.x(NE.x),{};",
|
"MOV.U64 {}.x(NE.x),{};",
|
||||||
cond, ret, false_value, ret, true_value);
|
cond, ret, false_value, ret, true_value);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue