mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-29 23:41:19 -06:00
Parse Data Parallel Primitive (#4331)
This commit is contained in:
parent
09c20d4636
commit
7755e98a2f
@ -133,6 +133,7 @@ GcnInst GcnDecodeContext::decodeInstruction(GcnCodeSlice& code) {
|
||||
if (encodingLen == sizeof(u32)) {
|
||||
decodeLiteralConstant(encoding, code);
|
||||
decodeSubDwordAddressing(encoding, code);
|
||||
decodeDataParallelPrimitive(encoding, code);
|
||||
}
|
||||
|
||||
repairOperandType();
|
||||
@ -505,6 +506,41 @@ void GcnDecodeContext::decodeSubDwordAddressing(InstEncoding encoding, GcnCodeSl
|
||||
}
|
||||
}
|
||||
|
||||
void GcnDecodeContext::decodeDataParallelPrimitive(InstEncoding encoding, GcnCodeSlice& code) {
|
||||
// Find if the instruction contains DPP
|
||||
if (m_instruction.src[0].field == OperandField::Dpp) {
|
||||
m_instruction.src[0].code = code.readu32();
|
||||
m_instruction.length += sizeof(u32);
|
||||
|
||||
Dpp dpp = *reinterpret_cast<Dpp*>(&m_instruction.src[0].code);
|
||||
|
||||
m_instruction.src[0].field = OperandField::VectorGPR;
|
||||
m_instruction.src[0].code = dpp.src0;
|
||||
|
||||
if (dpp.src0_abs) {
|
||||
m_instruction.src[0].input_modifier.abs = true;
|
||||
}
|
||||
if (dpp.src0_neg) {
|
||||
m_instruction.src[0].input_modifier.neg = true;
|
||||
}
|
||||
if (dpp.src1_abs) {
|
||||
m_instruction.src[1].input_modifier.abs = true;
|
||||
}
|
||||
if (dpp.src1_neg) {
|
||||
m_instruction.src[1].input_modifier.neg = true;
|
||||
}
|
||||
|
||||
auto op = dpp.GetOperation();
|
||||
LOG_ERROR(
|
||||
Render_Recompiler,
|
||||
"unhandled DPP operation: {} ({:#x}), value {}, bc {}, row_mask {:#b}, bank_mask {:#b}",
|
||||
magic_enum::enum_name(op.op), u32(op.op), op.value, bool(dpp.bc), u8(dpp.row_mask),
|
||||
u8(dpp.bank_mask));
|
||||
|
||||
m_instruction.src[0].dpp = op;
|
||||
}
|
||||
}
|
||||
|
||||
void GcnDecodeContext::decodeInstructionSOP1(u32 hexInstruction) {
|
||||
u32 ssrc0 = bit::extract(hexInstruction, 7, 0);
|
||||
u32 op = bit::extract(hexInstruction, 15, 8);
|
||||
|
||||
@ -71,6 +71,7 @@ private:
|
||||
void decodeInstruction64(InstEncoding encoding, GcnCodeSlice& code);
|
||||
void decodeLiteralConstant(InstEncoding encoding, GcnCodeSlice& code);
|
||||
void decodeSubDwordAddressing(InstEncoding encoding, GcnCodeSlice& code);
|
||||
void decodeDataParallelPrimitive(InstEncoding encoding, GcnCodeSlice& code);
|
||||
|
||||
// 32 bits encodings
|
||||
void decodeInstructionSOP1(uint32_t hexInstruction);
|
||||
|
||||
@ -60,6 +60,23 @@ enum class SdwaDstUnused : u32 {
|
||||
Invalid = 3,
|
||||
};
|
||||
|
||||
enum class DppCtrl : u16 {
|
||||
DppQuadPerm = 0,
|
||||
DppRowShl = 0x101,
|
||||
DppRowShr = 0x111,
|
||||
DppRowRor = 0x121,
|
||||
DppRowMirror = 0x140,
|
||||
DppRowHalfMirror = 0x141,
|
||||
};
|
||||
|
||||
struct DppOperation {
|
||||
DppCtrl op;
|
||||
u16 value;
|
||||
bool bc;
|
||||
u8 row_mask;
|
||||
u8 bank_mask;
|
||||
};
|
||||
|
||||
struct InstOperand {
|
||||
OperandField field = OperandField::Undefined;
|
||||
ScalarType type = ScalarType::Undefined;
|
||||
@ -69,6 +86,7 @@ struct InstOperand {
|
||||
OperandSelection op_sel = {};
|
||||
SdwaDstUnused sdwa_dst = SdwaDstUnused::Invalid;
|
||||
SdwaSelector sdwa_sel = SdwaSelector::Invalid;
|
||||
std::optional<DppOperation> dpp = {};
|
||||
u32 code = 0xFFFFFFFF;
|
||||
};
|
||||
|
||||
@ -286,6 +304,39 @@ union Sdwa {
|
||||
SdwaVop12 vop12;
|
||||
};
|
||||
|
||||
struct Dpp {
|
||||
u32 src0 : 8;
|
||||
u32 dpp_ctrl : 9;
|
||||
u32 : 1;
|
||||
u32 fi : 1;
|
||||
u32 bc : 1;
|
||||
u32 src0_neg : 1;
|
||||
u32 src0_abs : 1;
|
||||
u32 src1_neg : 1;
|
||||
u32 src1_abs : 1;
|
||||
u32 bank_mask : 4;
|
||||
u32 row_mask : 4;
|
||||
|
||||
DppOperation GetOperation() const {
|
||||
if (dpp_ctrl >= u32(DppCtrl::DppQuadPerm) && dpp_ctrl < 0x100) {
|
||||
return {DppCtrl::DppQuadPerm, u16(dpp_ctrl & 0xFF), bool(bc), u8(row_mask),
|
||||
u8(bank_mask)};
|
||||
} else if (dpp_ctrl >= u32(DppCtrl::DppRowShl) && dpp_ctrl < 0x110) {
|
||||
return {DppCtrl::DppRowShl, u16(dpp_ctrl & 0xF), bool(bc), u8(row_mask), u8(bank_mask)};
|
||||
} else if (dpp_ctrl >= u32(DppCtrl::DppRowShr) && dpp_ctrl < 0x120) {
|
||||
return {DppCtrl::DppRowShr, u16(dpp_ctrl & 0xF), bool(bc), u8(row_mask), u8(bank_mask)};
|
||||
} else if (dpp_ctrl >= u32(DppCtrl::DppRowRor) && dpp_ctrl < 0x130) {
|
||||
return {DppCtrl::DppRowRor, u16(dpp_ctrl & 0xF), bool(bc), u8(row_mask), u8(bank_mask)};
|
||||
} else if (dpp_ctrl == u32(DppCtrl::DppRowMirror)) {
|
||||
return {DppCtrl::DppRowMirror, 0, bool(bc), u8(row_mask), u8(bank_mask)};
|
||||
} else if (dpp_ctrl == u32(DppCtrl::DppRowHalfMirror)) {
|
||||
return {DppCtrl::DppRowHalfMirror, 0, bool(bc), u8(row_mask), u8(bank_mask)};
|
||||
} else {
|
||||
UNREACHABLE_MSG("malformed dpp_ctrl");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct GcnInst {
|
||||
Opcode opcode;
|
||||
InstEncoding encoding;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user