shader: Add integer division opcodes
This commit is contained in:
parent
43aa695a04
commit
95761cc6a7
|
@ -304,6 +304,8 @@ void EmitIAdd64(EmitContext& ctx, IR::Inst& inst, Register a, Register b);
|
||||||
void EmitISub32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b);
|
void EmitISub32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b);
|
||||||
void EmitISub64(EmitContext& ctx, IR::Inst& inst, Register a, Register b);
|
void EmitISub64(EmitContext& ctx, IR::Inst& inst, Register a, Register b);
|
||||||
void EmitIMul32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b);
|
void EmitIMul32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b);
|
||||||
|
void EmitSDiv32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b);
|
||||||
|
void EmitUDiv32(EmitContext& ctx, IR::Inst& inst, ScalarU32 a, ScalarU32 b);
|
||||||
void EmitINeg32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value);
|
void EmitINeg32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value);
|
||||||
void EmitINeg64(EmitContext& ctx, IR::Inst& inst, Register value);
|
void EmitINeg64(EmitContext& ctx, IR::Inst& inst, Register value);
|
||||||
void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value);
|
void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value);
|
||||||
|
|
|
@ -90,6 +90,14 @@ void EmitIMul32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) {
|
||||||
ctx.Add("MUL.S {}.x,{},{};", inst, a, b);
|
ctx.Add("MUL.S {}.x,{},{};", inst, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmitSDiv32(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) {
|
||||||
|
ctx.Add("DIV.S {}.x,{},{};", inst, a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitUDiv32(EmitContext& ctx, IR::Inst& inst, ScalarU32 a, ScalarU32 b) {
|
||||||
|
ctx.Add("DIV.U {}.x,{},{};", inst, a, b);
|
||||||
|
}
|
||||||
|
|
||||||
void EmitINeg32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) {
|
void EmitINeg32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) {
|
||||||
if (value.type != Type::Register && static_cast<s32>(value.imm_u32) < 0) {
|
if (value.type != Type::Register && static_cast<s32>(value.imm_u32) < 0) {
|
||||||
ctx.Add("MOV.S {},{};", inst, -static_cast<s32>(value.imm_u32));
|
ctx.Add("MOV.S {},{};", inst, -static_cast<s32>(value.imm_u32));
|
||||||
|
|
|
@ -363,6 +363,8 @@ void EmitIAdd64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::strin
|
||||||
void EmitISub32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b);
|
void EmitISub32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b);
|
||||||
void EmitISub64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b);
|
void EmitISub64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b);
|
||||||
void EmitIMul32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b);
|
void EmitIMul32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b);
|
||||||
|
void EmitSDiv32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b);
|
||||||
|
void EmitUDiv32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b);
|
||||||
void EmitINeg32(EmitContext& ctx, IR::Inst& inst, std::string_view value);
|
void EmitINeg32(EmitContext& ctx, IR::Inst& inst, std::string_view value);
|
||||||
void EmitINeg64(EmitContext& ctx, IR::Inst& inst, std::string_view value);
|
void EmitINeg64(EmitContext& ctx, IR::Inst& inst, std::string_view value);
|
||||||
void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, std::string_view value);
|
void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, std::string_view value);
|
||||||
|
|
|
@ -78,6 +78,14 @@ void EmitIMul32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::strin
|
||||||
ctx.AddU32("{}=uint({}*{});", inst, a, b);
|
ctx.AddU32("{}=uint({}*{});", inst, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmitSDiv32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
|
||||||
|
ctx.AddU32("{}=uint(int({})/int({}));", inst, a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitUDiv32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
|
||||||
|
ctx.AddU32("{}={}/{};", inst, a, b);
|
||||||
|
}
|
||||||
|
|
||||||
void EmitINeg32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
|
void EmitINeg32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
|
||||||
ctx.AddU32("{}=uint(-({}));", inst, value);
|
ctx.AddU32("{}=uint(-({}));", inst, value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -284,6 +284,8 @@ Id EmitIAdd64(EmitContext& ctx, Id a, Id b);
|
||||||
Id EmitISub32(EmitContext& ctx, Id a, Id b);
|
Id EmitISub32(EmitContext& ctx, Id a, Id b);
|
||||||
Id EmitISub64(EmitContext& ctx, Id a, Id b);
|
Id EmitISub64(EmitContext& ctx, Id a, Id b);
|
||||||
Id EmitIMul32(EmitContext& ctx, Id a, Id b);
|
Id EmitIMul32(EmitContext& ctx, Id a, Id b);
|
||||||
|
Id EmitSDiv32(EmitContext& ctx, Id a, Id b);
|
||||||
|
Id EmitUDiv32(EmitContext& ctx, Id a, Id b);
|
||||||
Id EmitINeg32(EmitContext& ctx, Id value);
|
Id EmitINeg32(EmitContext& ctx, Id value);
|
||||||
Id EmitINeg64(EmitContext& ctx, Id value);
|
Id EmitINeg64(EmitContext& ctx, Id value);
|
||||||
Id EmitIAbs32(EmitContext& ctx, Id value);
|
Id EmitIAbs32(EmitContext& ctx, Id value);
|
||||||
|
|
|
@ -72,6 +72,14 @@ Id EmitIMul32(EmitContext& ctx, Id a, Id b) {
|
||||||
return ctx.OpIMul(ctx.U32[1], a, b);
|
return ctx.OpIMul(ctx.U32[1], a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Id EmitSDiv32(EmitContext& ctx, Id a, Id b) {
|
||||||
|
return ctx.OpSDiv(ctx.U32[1], a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitUDiv32(EmitContext& ctx, Id a, Id b) {
|
||||||
|
return ctx.OpUDiv(ctx.U32[1], a, b);
|
||||||
|
}
|
||||||
|
|
||||||
Id EmitINeg32(EmitContext& ctx, Id value) {
|
Id EmitINeg32(EmitContext& ctx, Id value) {
|
||||||
return ctx.OpSNegate(ctx.U32[1], value);
|
return ctx.OpSNegate(ctx.U32[1], value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1145,6 +1145,10 @@ U32 IREmitter::IMul(const U32& a, const U32& b) {
|
||||||
return Inst<U32>(Opcode::IMul32, a, b);
|
return Inst<U32>(Opcode::IMul32, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
U32 IREmitter::IDiv(const U32& a, const U32& b, bool is_signed) {
|
||||||
|
return Inst<U32>(is_signed ? Opcode::SDiv32 : Opcode::UDiv32, a, b);
|
||||||
|
}
|
||||||
|
|
||||||
U32U64 IREmitter::INeg(const U32U64& value) {
|
U32U64 IREmitter::INeg(const U32U64& value) {
|
||||||
switch (value.Type()) {
|
switch (value.Type()) {
|
||||||
case Type::U32:
|
case Type::U32:
|
||||||
|
|
|
@ -209,6 +209,7 @@ public:
|
||||||
[[nodiscard]] U32U64 IAdd(const U32U64& a, const U32U64& b);
|
[[nodiscard]] U32U64 IAdd(const U32U64& a, const U32U64& b);
|
||||||
[[nodiscard]] U32U64 ISub(const U32U64& a, const U32U64& b);
|
[[nodiscard]] U32U64 ISub(const U32U64& a, const U32U64& b);
|
||||||
[[nodiscard]] U32 IMul(const U32& a, const U32& b);
|
[[nodiscard]] U32 IMul(const U32& a, const U32& b);
|
||||||
|
[[nodiscard]] U32 IDiv(const U32& a, const U32& b, bool is_signed = false);
|
||||||
[[nodiscard]] U32U64 INeg(const U32U64& value);
|
[[nodiscard]] U32U64 INeg(const U32U64& value);
|
||||||
[[nodiscard]] U32 IAbs(const U32& value);
|
[[nodiscard]] U32 IAbs(const U32& value);
|
||||||
[[nodiscard]] U32U64 ShiftLeftLogical(const U32U64& base, const U32& shift);
|
[[nodiscard]] U32U64 ShiftLeftLogical(const U32U64& base, const U32& shift);
|
||||||
|
|
|
@ -287,6 +287,8 @@ OPCODE(IAdd64, U64, U64,
|
||||||
OPCODE(ISub32, U32, U32, U32, )
|
OPCODE(ISub32, U32, U32, U32, )
|
||||||
OPCODE(ISub64, U64, U64, U64, )
|
OPCODE(ISub64, U64, U64, U64, )
|
||||||
OPCODE(IMul32, U32, U32, U32, )
|
OPCODE(IMul32, U32, U32, U32, )
|
||||||
|
OPCODE(SDiv32, U32, U32, U32, )
|
||||||
|
OPCODE(UDiv32, U32, U32, U32, )
|
||||||
OPCODE(INeg32, U32, U32, )
|
OPCODE(INeg32, U32, U32, )
|
||||||
OPCODE(INeg64, U64, U64, )
|
OPCODE(INeg64, U64, U64, )
|
||||||
OPCODE(IAbs32, U32, U32, )
|
OPCODE(IAbs32, U32, U32, )
|
||||||
|
|
Loading…
Reference in a new issue