mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-01 18:40:57 -06:00
Merge 5978035675 into deb8c66ffb
This commit is contained in:
commit
af2b5991bb
@ -3,6 +3,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include "common/assert.h"
|
||||
#include "core/libraries/kernel/process.h"
|
||||
#include "shader_recompiler/frontend/decode.h"
|
||||
|
||||
#include <magic_enum/magic_enum.hpp>
|
||||
@ -131,6 +132,7 @@ GcnInst GcnDecodeContext::decodeInstruction(GcnCodeSlice& code) {
|
||||
// Note: Literal constant decode must be performed after meta info updated.
|
||||
if (encodingLen == sizeof(u32)) {
|
||||
decodeLiteralConstant(encoding, code);
|
||||
decodeSubDwordAddressing(encoding, code);
|
||||
}
|
||||
|
||||
repairOperandType();
|
||||
@ -423,6 +425,78 @@ void GcnDecodeContext::decodeLiteralConstant(InstEncoding encoding, GcnCodeSlice
|
||||
}
|
||||
}
|
||||
|
||||
void GcnDecodeContext::decodeSubDwordAddressing(InstEncoding encoding, GcnCodeSlice& code) {
|
||||
// Find if the instruction contains SDWA (it's legal only as src0)
|
||||
if (m_instruction.src[0].field == OperandField::Sdwa) {
|
||||
ASSERT_MSG(Libraries::Kernel::sceKernelIsNeoMode(), "SDWA is not supported in Base mode");
|
||||
|
||||
m_instruction.src[0].code = code.readu32();
|
||||
m_instruction.length += sizeof(u32);
|
||||
|
||||
if (encoding == InstEncoding::VOPC) {
|
||||
SdwaVopc sdwa = *reinterpret_cast<SdwaVopc*>(&m_instruction.src[0].code);
|
||||
m_instruction.src[0].field =
|
||||
sdwa.s0 == 0 ? OperandField::VectorGPR : OperandField::ScalarGPR;
|
||||
m_instruction.src[0].code = sdwa.src0;
|
||||
m_instruction.src[0].sdwa_sel = SdwaSelector(sdwa.src0_sel);
|
||||
|
||||
m_instruction.src[0].input_modifier.neg = sdwa.src0_neg;
|
||||
m_instruction.src[0].input_modifier.abs = sdwa.src0_abs;
|
||||
m_instruction.src[0].input_modifier.sext = sdwa.src0_sext;
|
||||
|
||||
m_instruction.src[1].field =
|
||||
sdwa.s1 == 0 ? OperandField::VectorGPR : OperandField::ScalarGPR;
|
||||
m_instruction.src[1].sdwa_sel = SdwaSelector(sdwa.src1_sel);
|
||||
|
||||
m_instruction.src[1].input_modifier.neg = sdwa.src1_neg;
|
||||
m_instruction.src[1].input_modifier.abs = sdwa.src1_abs;
|
||||
m_instruction.src[1].input_modifier.sext = sdwa.src1_sext;
|
||||
|
||||
m_instruction.dst[0].sdwa_sel = SdwaSelector(sdwa.dst_sel);
|
||||
m_instruction.dst[0].sdwa_dst = SdwaDstUnused(sdwa.dst_u);
|
||||
m_instruction.dst[0].output_modifier.clamp = sdwa.clamp;
|
||||
|
||||
switch (sdwa.omod) {
|
||||
case 0:
|
||||
m_instruction.dst[0].output_modifier.multiplier = 0.f;
|
||||
break;
|
||||
case 1:
|
||||
m_instruction.dst[0].output_modifier.multiplier = 2.0f;
|
||||
break;
|
||||
case 2:
|
||||
m_instruction.dst[0].output_modifier.multiplier = 4.0f;
|
||||
break;
|
||||
case 3:
|
||||
m_instruction.dst[0].output_modifier.multiplier = 0.5f;
|
||||
break;
|
||||
}
|
||||
} else if (encoding == InstEncoding::VOP1 || encoding == InstEncoding::VOP2) {
|
||||
SdwaVop12 sdwa = *reinterpret_cast<SdwaVop12*>(&m_instruction.src[0].code);
|
||||
m_instruction.src[0].field =
|
||||
sdwa.s0 == 0 ? OperandField::VectorGPR : OperandField::ScalarGPR;
|
||||
m_instruction.src[0].code = sdwa.src0;
|
||||
m_instruction.src[0].sdwa_sel = SdwaSelector(sdwa.src0_sel);
|
||||
|
||||
m_instruction.src[0].input_modifier.neg = sdwa.src0_neg;
|
||||
m_instruction.src[0].input_modifier.abs = sdwa.src0_abs;
|
||||
m_instruction.src[0].input_modifier.sext = sdwa.src0_sext;
|
||||
|
||||
m_instruction.src[1].field =
|
||||
sdwa.s1 == 0 ? OperandField::VectorGPR : OperandField::ScalarGPR;
|
||||
m_instruction.src[1].sdwa_sel = SdwaSelector(sdwa.src1_sel);
|
||||
|
||||
m_instruction.src[1].input_modifier.neg = sdwa.src1_neg;
|
||||
m_instruction.src[1].input_modifier.abs = sdwa.src1_abs;
|
||||
m_instruction.src[1].input_modifier.sext = sdwa.src1_sext;
|
||||
|
||||
m_instruction.dst[0].field = OperandField::ScalarGPR;
|
||||
m_instruction.dst[0].code = sdwa.sdst;
|
||||
} else {
|
||||
UNREACHABLE_MSG("illegal instruction: SDWA used outside VOP1/VOP2/VOPC");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GcnDecodeContext::decodeInstructionSOP1(u32 hexInstruction) {
|
||||
u32 ssrc0 = bit::extract(hexInstruction, 7, 0);
|
||||
u32 op = bit::extract(hexInstruction, 15, 8);
|
||||
|
||||
@ -70,6 +70,7 @@ private:
|
||||
void decodeInstruction32(InstEncoding encoding, GcnCodeSlice& code);
|
||||
void decodeInstruction64(InstEncoding encoding, GcnCodeSlice& code);
|
||||
void decodeLiteralConstant(InstEncoding encoding, GcnCodeSlice& code);
|
||||
void decodeSubDwordAddressing(InstEncoding encoding, GcnCodeSlice& code);
|
||||
|
||||
// 32 bits encodings
|
||||
void decodeInstructionSOP1(uint32_t hexInstruction);
|
||||
|
||||
@ -26,6 +26,7 @@ enum OperandFieldRange {
|
||||
struct InputModifiers {
|
||||
bool neg = false;
|
||||
bool abs = false;
|
||||
bool sext = false;
|
||||
};
|
||||
|
||||
/// These are applied before storing an operand register.
|
||||
@ -34,11 +35,31 @@ struct OutputModifiers {
|
||||
float multiplier = 0.f;
|
||||
};
|
||||
|
||||
enum class SdwaSelector : u32 {
|
||||
Byte0 = 0,
|
||||
Byte1 = 1,
|
||||
Byte2 = 2,
|
||||
Byte3 = 3,
|
||||
Word0 = 4,
|
||||
Word1 = 5,
|
||||
Dword = 6,
|
||||
Invalid = 7,
|
||||
};
|
||||
|
||||
enum class SdwaDstUnused : u32 {
|
||||
Pad = 0,
|
||||
Sext = 1,
|
||||
Preserve = 2,
|
||||
Invalid = 3,
|
||||
};
|
||||
|
||||
struct InstOperand {
|
||||
OperandField field = OperandField::Undefined;
|
||||
ScalarType type = ScalarType::Undefined;
|
||||
InputModifiers input_modifier = {};
|
||||
OutputModifiers output_modifier = {};
|
||||
SdwaDstUnused sdwa_dst = SdwaDstUnused::Invalid;
|
||||
SdwaSelector sdwa_sel = SdwaSelector::Invalid;
|
||||
u32 code = 0xFFFFFFFF;
|
||||
};
|
||||
|
||||
@ -183,6 +204,51 @@ union InstControl {
|
||||
InstControlEXP exp;
|
||||
};
|
||||
|
||||
struct SdwaVopc {
|
||||
u32 src0 : 8;
|
||||
u32 dst_sel : 3;
|
||||
u32 dst_u : 2;
|
||||
u32 clamp : 1;
|
||||
u32 omod : 2;
|
||||
u32 src0_sel : 3;
|
||||
u32 src0_sext : 1;
|
||||
u32 src0_neg : 1;
|
||||
u32 src0_abs : 1;
|
||||
u32 : 1;
|
||||
u32 s0 : 1;
|
||||
|
||||
u32 src1_sel : 3;
|
||||
u32 src1_sext : 1;
|
||||
u32 src1_neg : 1;
|
||||
u32 src1_abs : 1;
|
||||
u32 : 1;
|
||||
u32 s1 : 1;
|
||||
};
|
||||
|
||||
struct SdwaVop12 {
|
||||
u32 src0 : 8;
|
||||
u32 sdst : 7;
|
||||
u32 sd : 1;
|
||||
u32 src0_sel : 3;
|
||||
u32 src0_sext : 1;
|
||||
u32 src0_neg : 1;
|
||||
u32 src0_abs : 1;
|
||||
u32 : 1;
|
||||
u32 s0 : 1;
|
||||
|
||||
u32 src1_sel : 3;
|
||||
u32 src1_sext : 1;
|
||||
u32 src1_neg : 1;
|
||||
u32 src1_abs : 1;
|
||||
u32 : 1;
|
||||
u32 s1 : 1;
|
||||
};
|
||||
|
||||
union Sdwa {
|
||||
SdwaVopc vopc;
|
||||
SdwaVop12 vop12;
|
||||
};
|
||||
|
||||
struct GcnInst {
|
||||
Opcode opcode;
|
||||
InstEncoding encoding;
|
||||
|
||||
@ -2391,6 +2391,9 @@ enum class OperandField : u32 {
|
||||
ConstFloatNeg_2_0,
|
||||
ConstFloatPos_4_0,
|
||||
ConstFloatNeg_4_0,
|
||||
Inv2Pi,
|
||||
Sdwa,
|
||||
Dpp,
|
||||
VccZ = 251,
|
||||
ExecZ = 252,
|
||||
Scc = 253,
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include "common/io_file.h"
|
||||
#include "common/path_util.h"
|
||||
#include "core/emulator_settings.h"
|
||||
#include "core/libraries/kernel/process.h"
|
||||
#include "shader_recompiler/frontend/decode.h"
|
||||
#include "shader_recompiler/frontend/fetch_shader.h"
|
||||
#include "shader_recompiler/frontend/translate/translate.h"
|
||||
@ -339,8 +340,22 @@ T Translator::GetSrc(const InstOperand& operand) {
|
||||
value = ir.BitCast<IR::U32>(ir.GetScc());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
default: {
|
||||
if (Libraries::Kernel::sceKernelIsNeoMode()) {
|
||||
switch (operand.field) {
|
||||
case OperandField::Inv2Pi:
|
||||
value = get_imm(static_cast<float>(1.0f / (2.0f * std::numbers::pi)));
|
||||
break;
|
||||
case OperandField::Sdwa:
|
||||
UNREACHABLE_MSG("unhandled SDWA");
|
||||
case OperandField::Dpp:
|
||||
UNREACHABLE_MSG("unhandled DPP");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
UNREACHABLE_MSG("unexpected operand: {}", std::to_underlying(operand.field));
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (is_float) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user