mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 13:56:59 +01:00
shader: add missing RDNA2 ALU opcodes
Add missing scalar and vector opcodes with compute tests. Original work by @Pouare514 in #176. Co-authored-by: Pouare514 <julienaulycee@gmail.com>
This commit is contained in:
@@ -76,9 +76,9 @@ void Translator::SUB_U32(const Decoder::Instruction& inst, bool vector, bool rev
|
||||
}
|
||||
}
|
||||
|
||||
void Translator::SUBB_U32(const Decoder::Instruction& inst, bool vector) {
|
||||
const auto lhs = ReadU32(vector ? inst.src1 : inst.src0);
|
||||
const auto rhs = ReadU32(vector ? inst.src0 : inst.src1);
|
||||
void Translator::SUBB_U32(const Decoder::Instruction& inst, bool vector, bool reverse) {
|
||||
const auto lhs = ReadU32(reverse ? inst.src1 : inst.src0);
|
||||
const auto rhs = ReadU32(reverse ? inst.src0 : inst.src1);
|
||||
const auto borrow_in = vector ? ConditionBit(inst.src2)
|
||||
: ConditionBit(ConditionOperand(Decoder::OperandKind::Scc));
|
||||
const auto partial = ir.ISub(lhs, rhs);
|
||||
@@ -94,6 +94,13 @@ void Translator::SUBB_U32(const Decoder::Instruction& inst, bool vector) {
|
||||
}
|
||||
}
|
||||
|
||||
void Translator::S_ABSDIFF_I32(const Decoder::Instruction& inst) {
|
||||
const auto difference = ir.ISub(ReadU32(inst.src0), ReadU32(inst.src1));
|
||||
const auto result = IR::U32(ir.Emit(IR::ValueOpcode::IAbs32, {difference}));
|
||||
WriteOperand(DestinationOperand(inst), result);
|
||||
ir.SetScc(ir.INotEqual(result, IR::U32(IR::Value(0u))));
|
||||
}
|
||||
|
||||
void Translator::S_ADD_SUB_I32(const Decoder::Instruction& inst, bool subtract) {
|
||||
const auto lhs = ReadU32(inst.src0);
|
||||
const auto rhs = ReadU32(inst.src1);
|
||||
|
||||
@@ -312,6 +312,22 @@ bool Translator::S_BITSET_B32(const Decoder::Instruction& inst, bool set) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Translator::S_BITSET_B64(const Decoder::Instruction& inst, bool set) {
|
||||
const auto offset = ir.BitwiseAnd(ReadU32(inst.src0), IR::U32(IR::Value(63u)));
|
||||
const auto word_bit = ir.BitwiseAnd(offset, IR::U32(IR::Value(31u)));
|
||||
const auto bit = ir.ShiftLeftLogical(IR::U32(IR::Value(1u)), word_bit);
|
||||
const auto old = ReadU32Pair(inst.dst);
|
||||
const auto low_value = set ? ir.BitwiseOr(old[0], bit)
|
||||
: ir.BitwiseAnd(old[0], ir.BitwiseNot(bit));
|
||||
const auto high_value = set ? ir.BitwiseOr(old[1], bit)
|
||||
: ir.BitwiseAnd(old[1], ir.BitwiseNot(bit));
|
||||
const auto high = IR::U1(ir.Emit(IR::ValueOpcode::UGreaterThanEqual32,
|
||||
{offset, IR::Value(32u)}));
|
||||
WriteU32Pair(inst.dst,
|
||||
{ir.Select(high, old[0], low_value), ir.Select(high, high_value, old[1])});
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Translator::V_BCNT_U32_B32(const Decoder::Instruction& inst) {
|
||||
const auto count = IR::U32(ir.Emit(IR::ValueOpcode::BitCount32, {ReadU32(inst.src0)}));
|
||||
WriteOperand(DestinationOperand(inst), ir.IAdd(count, ReadU32(inst.src1)));
|
||||
|
||||
@@ -34,7 +34,8 @@ bool Translator::EmitScalar(const Decoder::Instruction& inst) {
|
||||
case O::S_ADD_U32: ADD_U32(inst, false, false); return true;
|
||||
case O::S_ADDC_U32: ADD_U32(inst, false, true); return true;
|
||||
case O::S_SUB_U32: SUB_U32(inst, false, false); return true;
|
||||
case O::S_SUBB_U32: SUBB_U32(inst, false); return true;
|
||||
case O::S_SUBB_U32: SUBB_U32(inst, false, false); return true;
|
||||
case O::S_ABSDIFF_I32: S_ABSDIFF_I32(inst); return true;
|
||||
case O::S_ADD_I32: S_ADD_SUB_I32(inst, false); return true;
|
||||
case O::S_SUB_I32: S_ADD_SUB_I32(inst, true); return true;
|
||||
case O::S_LSHL1_ADD_U32: S_LSHL_ADD_U32(inst, 1u); return true;
|
||||
@@ -186,6 +187,8 @@ bool Translator::EmitScalar(const Decoder::Instruction& inst) {
|
||||
|
||||
case O::S_BITSET0_B32: return S_BITSET_B32(inst, false);
|
||||
case O::S_BITSET1_B32: return S_BITSET_B32(inst, true);
|
||||
case O::S_BITSET0_B64: return S_BITSET_B64(inst, false);
|
||||
case O::S_BITSET1_B64: return S_BITSET_B64(inst, true);
|
||||
case O::S_BITREPLICATE_B64_B32: return S_BITREPLICATE_B64_B32(inst);
|
||||
case O::S_QUADMASK_B64: return S_QUADMASK_B64(inst);
|
||||
case O::S_BFM_B32: return BFM_B32(inst);
|
||||
@@ -201,6 +204,7 @@ bool Translator::EmitScalar(const Decoder::Instruction& inst) {
|
||||
|
||||
case O::S_NOP:
|
||||
case O::S_SLEEP:
|
||||
case O::S_SETPRIO:
|
||||
case O::S_TRAP: EmitControlNop(); return true;
|
||||
case O::S_WAITCNT_DEPCTR: EmitWaitcnt(); return true;
|
||||
case O::S_BARRIER: S_BARRIER(); return true;
|
||||
|
||||
@@ -192,6 +192,7 @@ private:
|
||||
bool V_SAD_U32(const Decoder::Instruction& inst);
|
||||
bool V_ADD3_U32(const Decoder::Instruction& inst);
|
||||
bool S_BITSET_B32(const Decoder::Instruction& inst, bool set);
|
||||
bool S_BITSET_B64(const Decoder::Instruction& inst, bool set);
|
||||
bool V_BCNT_U32_B32(const Decoder::Instruction& inst);
|
||||
bool V_MBCNT_U32_B32(const Decoder::Instruction& inst, bool low);
|
||||
bool S_BITREPLICATE_B64_B32(const Decoder::Instruction& inst);
|
||||
@@ -218,7 +219,8 @@ private:
|
||||
bool negate_source, bool write_64);
|
||||
void ADD_U32(const Decoder::Instruction& inst, bool vector, bool use_carry_in);
|
||||
void SUB_U32(const Decoder::Instruction& inst, bool vector, bool reverse);
|
||||
void SUBB_U32(const Decoder::Instruction& inst, bool vector);
|
||||
void SUBB_U32(const Decoder::Instruction& inst, bool vector, bool reverse);
|
||||
void S_ABSDIFF_I32(const Decoder::Instruction& inst);
|
||||
void S_ADD_SUB_I32(const Decoder::Instruction& inst, bool subtract);
|
||||
void S_LSHL_ADD_U32(const Decoder::Instruction& inst, uint32_t shift_amount);
|
||||
void ScalarMinMax32(const Decoder::Instruction& inst, IR::ValueOpcode value_opcode,
|
||||
|
||||
@@ -10,7 +10,8 @@ bool Translator::EmitVector(const Decoder::Instruction& inst) {
|
||||
case O::V_ADDC_U32: ADD_U32(inst, true, true); return true;
|
||||
case O::V_SUB_I32: SUB_U32(inst, true, false); return true;
|
||||
case O::V_SUBREV_I32: SUB_U32(inst, true, true); return true;
|
||||
case O::V_SUBREV_CO_CI_U32: SUBB_U32(inst, true); return true;
|
||||
case O::V_SUB_CO_CI_U32: SUBB_U32(inst, true, false); return true;
|
||||
case O::V_SUBREV_CO_CI_U32: SUBB_U32(inst, true, true); return true;
|
||||
|
||||
case O::V_MOV_B32: MOV_B32(inst, true); return true;
|
||||
case O::V_MOVRELS_B32: V_MOVRELS_B32(inst); return true;
|
||||
|
||||
Reference in New Issue
Block a user