Merge pull request #437 from adriadam10/feat/vop3-qsad-mqsad

feat(shader): implement v_qsad_pk_u16_u8, v_mqsad_pk_u16_u8 and v_mqsad_u32_u8
This commit is contained in:
Dean 2026-10-04 19:41:53 +13:00 committed by GitHub
commit ec720a351c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 230 additions and 4 deletions

View File

@ -0,0 +1,170 @@
#include "prx/libSceAgcDriver/Execution/include/VulkanDevice.hpp"
#include "prx/libSceAgcDriver/Graphics/include/Draw.hpp"
#include "Recompiler.hpp"
#include "VulkanTestDevice.hpp"
#include <algorithm>
#include <array>
#include <bit>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
namespace {
using AgcDriver::Graphics::Require;
using ShaderRecompiler::ShaderStage;
constexpr std::uint32_t Threads = 32;
constexpr std::uint32_t Inputs = 4;
constexpr std::uint32_t Results = 16;
alignas(256) std::array<std::uint32_t, Threads * Inputs> Input{};
alignas(256) std::array<std::uint32_t, Threads * Results> Output{};
alignas(256) constexpr std::array<std::uint32_t, 50> Code{
0x34020084, 0x34060086, 0xe0381000, 0x80000401, 0xbf8c3f70, 0xd572000a, 0x041a0d04, 0xd573000c,
0x041a0d04, 0xd575000e, 0x04120d04, 0xd5720012, 0x02020906, 0xd5750014, 0x04120b06, 0xd5730018,
0x04120b06, 0xe0701000, 0x80010a03, 0xe0701004, 0x80010b03, 0xe0701008, 0x80010c03, 0xe070100c,
0x80010d03, 0xe0701010, 0x80010e03, 0xe0701014, 0x80010f03, 0xe0701018, 0x80011003, 0xe070101c,
0x80011103, 0xe0701020, 0x80011203, 0xe0701024, 0x80011303, 0xe0701028, 0x80011403, 0xe070102c,
0x80011503, 0xe0701030, 0x80011603, 0xe0701034, 0x80011703, 0xe0701038, 0x80011803, 0xe070103c,
0x80011903, 0xbf810000,
};
constexpr std::uint32_t Rows[32][4] = {
{0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u},
{0xffffffffu, 0xffffffffu, 0x00000000u, 0x00000000u},
{0x00000000u, 0x00000000u, 0xffffffffu, 0xffffffffu},
{0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu},
{0x01020304u, 0x05060708u, 0x00ff00ffu, 0xfffefffdu},
{0xff00ff00u, 0x00ff00ffu, 0x00000000u, 0xffffffffu},
{0x12345678u, 0x9abcdef0u, 0x00010203u, 0xffff0000u},
{0xffffffffu, 0x00000000u, 0x00ff0000u, 0xfffffff0u},
{0x80808080u, 0x7f7f7f7fu, 0x01000001u, 0x00010000u},
{0xfffffff0u, 0xfffffff0u, 0xffffffffu, 0xffff0001u},
{0xecc3f80cu, 0xc7859faeu, 0xf2d7d40fu, 0x4a37fa2du},
{0xe47682e6u, 0xd46375dcu, 0x156393d8u, 0x045f21dau},
{0x978f18a7u, 0x4e86c4fau, 0x6c7ab5c9u, 0x611244c0u},
{0x87b3d90eu, 0x5bab1eecu, 0x215b8892u, 0xb9d8249eu},
{0x3126b9c3u, 0x44732494u, 0x71cf92e3u, 0x039a7b88u},
{0x389605feu, 0x9ec2d776u, 0x747d0a2bu, 0xe6d30f0au},
{0x065720ceu, 0x1b1c3f27u, 0x15f54a5cu, 0xfb34ccc5u},
{0xb5c318e9u, 0x7f8cb6d1u, 0x6bd6eed6u, 0x05032a7eu},
{0x833bfa03u, 0xa0aeb4e5u, 0xbbf5204au, 0x6e6944d3u},
{0x5be72f6eu, 0xc55176d5u, 0x0ebbe4d0u, 0x34a3f451u},
{0xc8796571u, 0x090a0e01u, 0x96d0cbffu, 0x5e7db530u},
{0xa86cf7b4u, 0x2c03a513u, 0x9ef94bdau, 0x374ebe5au},
{0xf8821a96u, 0xbc36c297u, 0x5cdff86du, 0x90c68e93u},
{0xc2816017u, 0xdc3260fdu, 0x5e620fe9u, 0xf7f3a683u},
{0x9271a86fu, 0x4801920eu, 0xa918a1dcu, 0xf9810e12u},
{0x507bef95u, 0x92af2f03u, 0x15f2cd71u, 0xd0745cc1u},
{0x795c6ad3u, 0x2d794610u, 0xb7c93640u, 0x7bab67bcu},
{0x97323268u, 0xca9f211eu, 0x728c2f7bu, 0xacfc4403u},
{0xa472ea5fu, 0x29e0b1f5u, 0x2e99777fu, 0xcc8ba3e3u},
{0x2db4cb47u, 0x8899230bu, 0x52cb26d8u, 0xac61e3a6u},
{0xd0dd15d6u, 0x85232575u, 0x32135b34u, 0x951179a0u},
{0x1d42d810u, 0x15136429u, 0x193e1ff7u, 0x6d17abfbu}
};
constexpr std::uint32_t Expected[32][16] = {
{0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u},
{0x03fc03fcu, 0x03fc03fcu, 0x00000000u, 0x00000000u, 0xffffffffu, 0xffffffffu, 0x00000000u, 0x00000000u, 0x03fc03fcu, 0x03fc03fcu, 0x000003fbu, 0x000003fbu, 0x000003fcu, 0x000003fcu, 0x03fb03fbu, 0x03fb03fbu},
{0x03fb03fbu, 0x03fb03fbu, 0x03fb03fbu, 0x03fb03fbu, 0x000003fcu, 0x000003fcu, 0x000003fbu, 0x000003fbu, 0x03fc03fcu, 0x03fc03fcu, 0x00000000u, 0x00000000u, 0xffffffffu, 0xffffffffu, 0x00000000u, 0x00000000u},
{0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0x00000000u, 0x00000000u, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu},
{0x030302fbu, 0x020201f9u, 0x02f902f7u, 0x01f401f1u, 0x010204fcu, 0x05060902u, 0x00ff02f3u, 0xffff01f3u, 0x01fe01fcu, 0x02f802f7u, 0x01020500u, 0x05060906u, 0x00ff03eeu, 0xffff02edu, 0x03000500u, 0x07f609f7u},
{0x02fd01feu, 0x02fc01fdu, 0x00000000u, 0xffffffffu, 0xff00ff00u, 0x00ff00ffu, 0x00000000u, 0xffffffffu, 0x00ff01feu, 0x00ff01feu, 0xff0100feu, 0x00ff02fdu, 0x000000ffu, 0x000000feu, 0x00fe00feu, 0x01fe01feu},
{0x01870311u, 0x0295020eu, 0x009702ffu, 0x01d90130u, 0x12345774u, 0x9abcdf86u, 0x00010333u, 0xffff01dau, 0x0111010eu, 0x01ef0113u, 0x12345996u, 0x9abce211u, 0x00010526u, 0xffff02efu, 0x15555996u, 0x9dabe213u},
{0x02fd02fdu, 0x01fd02edu, 0x00ff0000u, 0x00fe00efu, 0xffffffffu, 0x00000000u, 0x00ff00ffu, 0x000000efu, 0x020d02fdu, 0x010e010eu, 0xffffffffu, 0x00000000u, 0x00ff0000u, 0xfffffff0u, 0xffffffffu, 0x00000000u},
{0x02fd01ffu, 0x01fc01fcu, 0x01fd00ffu, 0x00fe00fdu, 0x8080817eu, 0x7f7f807cu, 0x010000feu, 0x000100fdu, 0x01ff01feu, 0x01fe01ffu, 0x8080827au, 0x7f7f817au, 0x010001fcu, 0x000101fau, 0x827b827au, 0x8179817au},
{0x000e000eu, 0x000e0010u, 0x000e000eu, 0x000e0010u, 0xffffffffu, 0xffffffffu, 0x0000000eu, 0xffff0010u, 0x010d000fu, 0x020c020cu, 0xffffffffu, 0x000000fdu, 0x0000020bu, 0xffff020du, 0x010cffffu, 0x020b01fcu},
{0xf42ad450u, 0x4bdffb75u, 0xf42ad450u, 0x4bdffb75u, 0xecc3f84du, 0xc785a101u, 0xf2d7d557u, 0x4a37fbd5u, 0x01d70041u, 0x029d0175u, 0xecc3f95du, 0xc785a113u, 0xf2d7d516u, 0x4a37fbe8u, 0xee28f95du, 0xc940a0b5u},
{0x171e94d9u, 0x05142366u, 0x171e94d9u, 0x05142366u, 0xe47683e7u, 0xd4637797u, 0x15639564u, 0x045f228fu, 0x00dd0101u, 0x02030217u, 0xe47683c7u, 0xd463768bu, 0x156395dbu, 0x045f23bdu, 0xe52583c7u, 0xd64677dfu},
{0x6dfcb6c8u, 0x61ed45f0u, 0x6dfcb6c8u, 0x61ed45f0u, 0x978f19a6u, 0x4e86c67cu, 0x6c7ab6f9u, 0x6112459bu, 0x00bc00ffu, 0x01b30105u, 0x978f1911u, 0x4e86c615u, 0x6c7ab6e5u, 0x611245d0u, 0x98aa1911u, 0x4f96c616u},
{0x22c48a25u, 0xbb0e2554u, 0x22c48a25u, 0xbb0e2554u, 0x87b3daa1u, 0x5bab2055u, 0x215b8948u, 0xb9d825d4u, 0x01a10193u, 0x012e017du, 0x87b3da5cu, 0x5bab205au, 0x215b896au, 0xb9d826edu, 0x8921da5cu, 0x5dfa1fc4u},
{0x73269413u, 0x04fb7d2eu, 0x73269413u, 0x04fb7d2eu, 0x3126baf3u, 0x447325ebu, 0x71cf9489u, 0x039a7ce9u, 0x00e90130u, 0x01410100u, 0x3126bb09u, 0x44732587u, 0x71cf93b7u, 0x039a7c6du, 0x3219bb09u, 0x45582568u},
{0x75760b58u, 0xe7f4100du, 0x75760b58u, 0xe7f4100du, 0x3896072bu, 0x9ec2d86fu, 0x747d0b2eu, 0xe6d3102bu, 0x01bc012du, 0x01b101a5u, 0x38960785u, 0x9ec2d91eu, 0x747d0bdcu, 0xe6d310c1u, 0x3a3e0785u, 0xa079d927u},
{0x173f4ba5u, 0xfc6ace06u, 0x173f4ba5u, 0xfc6ace06u, 0x06572217u, 0x1b1c4071u, 0x15f54b9du, 0xfb34cdfbu, 0x025a0149u, 0x02010166u, 0x065721edu, 0x1b1c40b1u, 0x15f54caeu, 0xfb34ce26u, 0x07e121edu, 0x1c7d4179u},
{0x6d46f01cu, 0x05822b1au, 0x6d46f01cu, 0x05822b1au, 0xb5c31a2fu, 0x7f8cb841u, 0x6bd6ef72u, 0x05032afdu, 0x01520146u, 0x022f0136u, 0xb5c31984u, 0x7f8cb730u, 0x6bd6ef89u, 0x05032bfau, 0xb6221984u, 0x8108b784u},
{0xbd5c225du, 0x6fb5455cu, 0xbd5c225du, 0x6fb5455cu, 0x833bfc16u, 0xa0aeb64cu, 0xbbf520d3u, 0x6e69461fu, 0x00f20213u, 0x01020208u, 0x833bfb94u, 0xa0aeb62bu, 0xbbf520e2u, 0x6e6945bdu, 0x8481fb94u, 0xa198b57du},
{0x1086e660u, 0x35aff573u, 0x1086e660u, 0x35aff573u, 0x5be730feu, 0xc55178a0u, 0x0ebbe5f2u, 0x34a3f55du, 0x01e50190u, 0x00d7019du, 0x5be73102u, 0xc55177e0u, 0x0ebbe581u, 0x34a3f602u, 0x5cf23102u, 0xc7027786u},
{0x9859cd7cu, 0x60ccb710u, 0x9859cd7cu, 0x60ccb710u, 0xc87966eeu, 0x090a0f8au, 0x96d0cddfu, 0x5e7db77fu, 0x017a017du, 0x00e100ecu, 0xc879687fu, 0x090a1040u, 0x96d0ce28u, 0x5e7db706u, 0xcab8687fu, 0x0ae0102au},
{0xa0134d43u, 0x38a7c012u, 0xa0134d43u, 0x38a7c012u, 0xa86cf91du, 0x2c03a62du, 0x9ef94d92u, 0x374ebfb3u, 0x00eb0169u, 0x015f00c6u, 0xa86cfa3du, 0x2c03a668u, 0x9ef94db0u, 0x374ec00du, 0xa9c1fa3du, 0x2db6a6e9u},
{0x5dfcfa6du, 0x91f58f56u, 0x5dfcfa6du, 0x91f58f56u, 0xf8821c96u, 0xbc36c3b4u, 0x5cdff930u, 0x90c68fc2u, 0x01b20200u, 0x00f10106u, 0xf8821bffu, 0xbc36c364u, 0x5cdff9a6u, 0x90c68f5fu, 0xf94f1bffu, 0xbd02c3d0u},
{0x605c118fu, 0xf936a83bu, 0x605c118fu, 0xf936a83bu, 0xc28161bdu, 0xdc3262f7u, 0x5e6211a1u, 0xf7f3a7c6u, 0x006c01a6u, 0x00c0006bu, 0xc281612au, 0xdc326272u, 0x5e62110du, 0xf7f3a7d0u, 0xc3f6612au, 0xdd7f6221u},
{0xaa91a2c0u, 0xfb800eadu, 0xaa91a2c0u, 0xfb800eadu, 0x9271a953u, 0x48019387u, 0xa918a277u, 0xf9811011u, 0x017a00e4u, 0x0144013bu, 0x9271a9c4u, 0x480193f9u, 0xa918a248u, 0xf9810f73u, 0x945ca9c4u, 0x4962927au},
{0x1776ce69u, 0xd2bc5e51u, 0x1776ce69u, 0xd2bc5e51u, 0x507bf08du, 0x92af3087u, 0x15f2cf01u, 0xd0745f09u, 0x011200f8u, 0x00f10189u, 0x507bf161u, 0x92af3159u, 0x15f2cec2u, 0xd0745dd6u, 0x52d1f161u, 0x93c43054u},
{0xb91037b2u, 0x7ccb6945u, 0xb91037b2u, 0x7ccb6945u, 0x795c6c45u, 0x2d794757u, 0xb7c937c9u, 0x7bab68dcu, 0x019a0172u, 0x00ab00c9u, 0x795c6bedu, 0x2d794786u, 0xb7c937e7u, 0x7bab6969u, 0x7ad26bedu, 0x2f2647b7u},
{0x73373010u, 0xadc14573u, 0x73373010u, 0xadc14573u, 0x973232fdu, 0xca9f21c9u, 0x728c30ebu, 0xacfc44c8u, 0x01670095u, 0x00b000e6u, 0x9732333eu, 0xca9f228eu, 0x728c315cu, 0xacfc4502u, 0x98a2333eu, 0xcb9e22ffu},
{0x2fdb78afu, 0xcdf8a4fcu, 0x2fdb78afu, 0xcdf8a4fcu, 0xa472eb8fu, 0x29e0b337u, 0x2e997898u, 0xcc8ba550u, 0x00ec0130u, 0x00820168u, 0xa472eb5bu, 0x29e0b3f7u, 0x2e9978dbu, 0xcc8ba57bu, 0xa674eb5bu, 0x2b78b351u},
{0x544b284au, 0xae16e4c0u, 0x544b284au, 0xae16e4c0u, 0x2db4ccb9u, 0x8899248bu, 0x52cb27f2u, 0xac61e55bu, 0x00fc0172u, 0x009301c1u, 0x2db4cc7fu, 0x88992433u, 0x52cb282fu, 0xac61e4e1u, 0x2edccc7fu, 0x89d42462u},
{0x33b45d84u, 0x95e87b2du, 0x33b45d84u, 0x95e87b2du, 0xd0dd1826u, 0x85232716u, 0x32135cc1u, 0x95117a77u, 0x01580250u, 0x02520174u, 0xd0dd16b0u, 0x852325cbu, 0x32135c2cu, 0x95117b28u, 0xd13316b0u, 0x86ab266du},
{0x19b1219fu, 0x6e27ad12u, 0x19b1219fu, 0x6e27ad12u, 0x1d42d9b8u, 0x1513649cu, 0x193e210eu, 0x6d17ad0bu, 0x01b001a8u, 0x009b0234u, 0x1d42d952u, 0x15136545u, 0x193e21d5u, 0x6d17ad3cu, 0x1e5ed952u, 0x16546607u}
};
constexpr const char* Names[16] = {"qsad lo", "qsad hi", "mqsad_pk lo", "mqsad_pk hi", "mqsad_u32 0", "mqsad_u32 1", "mqsad_u32 2", "mqsad_u32 3", "qsad const lo", "qsad const hi", "mqsad_u32 b0", "mqsad_u32 b1", "mqsad_u32 b2", "mqsad_u32 b3", "mqsad_pk b lo", "mqsad_pk b hi"};
void Fill(std::uint32_t tid, std::uint32_t* words) {
std::copy(std::begin(Rows[tid]), std::end(Rows[tid]), words);
}
std::array<std::uint32_t, 4> BufferDescriptor(const void* data, std::uint32_t bytes) {
const auto address = reinterpret_cast<std::uintptr_t>(data);
return {static_cast<std::uint32_t>(address), static_cast<std::uint32_t>((address >> 32u) & 0xffffu), bytes, 0x01016facu};
}
std::string Hex(std::uint32_t value) {
char text[16];
std::snprintf(text, sizeof(text), "0x%08x", value);
return text;
}
void Expect(std::uint32_t tid, std::uint32_t actual, std::uint32_t expected, const char* name) {
Require(actual == expected, std::string("vop3 quad sad: lane ") + std::to_string(tid) + " " + name + " is " + Hex(actual) + ", expected " + Hex(expected));
}
void Run(AgcDriver::VulkanDevice& device) {
for (std::uint32_t tid = 0; tid < Threads; ++tid) Fill(tid, &Input[tid * Inputs]);
Output.fill(0xdeadbeefu);
std::vector<std::uint32_t> userData(8, 0u);
const auto input = BufferDescriptor(Input.data(), static_cast<std::uint32_t>(Input.size() * 4u));
const auto output = BufferDescriptor(Output.data(), static_cast<std::uint32_t>(Output.size() * 4u));
std::copy(input.begin(), input.end(), userData.begin());
std::copy(output.begin(), output.end(), userData.begin() + 4);
const std::span<const std::uint32_t> code(Code);
const std::array<ShaderRecompiler::MemoryRegion, 1> memory{{{reinterpret_cast<std::uintptr_t>(code.data()), std::as_bytes(code)}}};
const ShaderRecompiler::ShaderComputeStageInfo compute{{Threads, 1, 1}, 0u, {false, false, false}, false, 1};
ShaderRecompiler::RecompileRequest request{
{ShaderStage::Compute, reinterpret_cast<std::uintptr_t>(code.data()), code, 0, {}},
{32, 0, userData, compute, std::nullopt, std::nullopt, memory},
device.Target(),
{0, 0, 0, 128}
};
request.useCache = false;
const auto result = ShaderRecompiler::Recompile(request);
device.Dispatch(result, 1, 1, 1, {}, reinterpret_cast<std::uintptr_t>(code.data()));
device.WaitIdle();
}
void Check() {
for (std::uint32_t tid = 0; tid < Threads; ++tid) {
const std::uint32_t* in = &Input[tid * Inputs];
const std::uint32_t* out = &Output[tid * Results];
for (std::uint32_t i = 0; i < 16; ++i) Expect(tid, out[i], Expected[tid][i], Names[i]);
}
}
}
int main() {
try {
const auto device = OpenVulkanTestDevice();
if (!device) return VulkanTestSkipped;
Run(*device);
Check();
std::puts("vop3 quad sad tests passed");
return 0;
} catch (const std::exception& error) {
std::cerr << error.what() << '\n';
return 1;
}
}

View File

@ -63,6 +63,9 @@ enum class RdnaOpcode : std::uint16_t {
VSadHiU8,
VSadU16,
VMsadU8,
VQsadPkU16U8,
VMqsadPkU16U8,
VMqsadU32U8,
VAndB32,
VOrB32,
VXorB32,

View File

@ -174,6 +174,9 @@ bool IsVectorAluOpcode(RdnaOpcode opcode) {
case RdnaOpcode::VSadHiU8:
case RdnaOpcode::VSadU16:
case RdnaOpcode::VMsadU8:
case RdnaOpcode::VQsadPkU16U8:
case RdnaOpcode::VMqsadPkU16U8:
case RdnaOpcode::VMqsadU32U8:
case RdnaOpcode::VAndB32:
case RdnaOpcode::VOrB32:
case RdnaOpcode::VXorB32:

View File

@ -465,6 +465,9 @@ constexpr VectorOpcodeInfo vop3Opcodes[] = {
{0x15cu, RdnaOpcode::VSadU16},
{0x15du, RdnaOpcode::VSadU32},
{0x171u, RdnaOpcode::VMsadU8},
{0x172u, RdnaOpcode::VQsadPkU16U8},
{0x173u, RdnaOpcode::VMqsadPkU16U8},
{0x175u, RdnaOpcode::VMqsadU32U8},
{0x15eu, RdnaOpcode::VCvtPkU8F32},
{0x178u, RdnaOpcode::VXor3B32},
{0x12fu, RdnaOpcode::VCvtPkrtzF16F32},

View File

@ -190,7 +190,9 @@ private:
bool integer24(const RdnaInstruction& inst, bool sign, bool addend, bool high = false);
bool vMadU64U32(const RdnaInstruction& inst);
bool vSadU32(const RdnaInstruction& inst);
IrU32 byteSad(const IrU32& lhs, const IrU32& rhs, std::uint32_t fieldBits, bool masked);
bool subwordSad(const RdnaInstruction& inst, std::uint32_t fieldBits, std::uint32_t sumShift, bool masked);
bool vQsadU8(const RdnaInstruction& inst, bool masked, bool wide);
bool vAdd3U32(const RdnaInstruction& inst);
bool sBitsetB32(const RdnaInstruction& inst, bool set);
bool sBitsetB64(const RdnaInstruction& inst, bool set);

View File

@ -158,7 +158,16 @@ std::uint32_t decodedDstSize(const RdnaInstruction& inst) {
}
std::uint32_t embeddedFetchDstSize(const RdnaInstruction& inst) {
return inst.op == RdnaOpcode::VMadU64U32 ? 2u : decodedDstSize(inst);
switch (inst.op) {
case RdnaOpcode::VMadU64U32:
case RdnaOpcode::VQsadPkU16U8:
case RdnaOpcode::VMqsadPkU16U8:
return 2u;
case RdnaOpcode::VMqsadU32U8:
return 4u;
default:
return decodedDstSize(inst);
}
}
// How many consecutive SGPRs a scalar operand of the instruction names, over-estimated where the

View File

@ -344,9 +344,7 @@ bool TranslationContext::vSadU32(const RdnaInstruction& inst) {
return true;
}
bool TranslationContext::subwordSad(const RdnaInstruction& inst, std::uint32_t fieldBits, std::uint32_t sumShift, bool masked) {
const IrU32 lhs = readU32(sourceAt(inst, 0u));
const IrU32 rhs = readU32(sourceAt(inst, 1u));
IrU32 TranslationContext::byteSad(const IrU32& lhs, const IrU32& rhs, std::uint32_t fieldBits, bool masked) {
IrU32 sum(ir.Constant(0u));
for (std::uint32_t offset = 0u; offset < 32u; offset += fieldBits) {
const IrU32 lhsField(ir.Emit(IrOpcode::BitFieldUExtract, IrType::U32, {&lhs.Value(), &ir.Constant(offset), &ir.Constant(fieldBits)}));
@ -360,6 +358,11 @@ bool TranslationContext::subwordSad(const RdnaInstruction& inst, std::uint32_t f
}
sum = IrU32(ir.IAdd(sum.Value(), difference.Value()));
}
return sum;
}
bool TranslationContext::subwordSad(const RdnaInstruction& inst, std::uint32_t fieldBits, std::uint32_t sumShift, bool masked) {
IrU32 sum = byteSad(readU32(sourceAt(inst, 0u)), readU32(sourceAt(inst, 1u)), fieldBits, masked);
if (sumShift != 0u) {
sum = IrU32(ir.ShiftLeftLogical(sum.Value(), ir.Constant(sumShift)));
}
@ -369,6 +372,33 @@ bool TranslationContext::subwordSad(const RdnaInstruction& inst, std::uint32_t f
return true;
}
bool TranslationContext::vQsadU8(const RdnaInstruction& inst, bool masked, bool wide) {
const std::array<IrU32, 2> source = readU32Pair(sourceAt(inst, 0u));
const IrU32 reference = readU32(sourceAt(inst, 1u));
const auto sad = [&](std::uint32_t shift) {
if (shift == 0u) {
return byteSad(source[0], reference, 8u, masked);
}
const IrU32 window(ir.BitwiseOr(ir.ShiftRightLogical(source[0].Value(), ir.Constant(shift)), ir.ShiftLeftLogical(source[1].Value(), ir.Constant(32u - shift))));
return byteSad(window, reference, 8u, masked);
};
const std::array<IrU32, 2> accumulator = readU32Pair(sourceAt(inst, 2u));
if (wide) {
const std::array<IrU32, 2> accumulatorHigh = readU32Pair(offsetOperand(sourceAt(inst, 2u), 2u));
writeU32Pair(inst.destination, {IrU32(ir.IAdd(accumulator[0].Value(), sad(0u).Value())), IrU32(ir.IAdd(accumulator[1].Value(), sad(8u).Value()))});
writeU32Pair(offsetOperand(inst.destination, 2u),
{IrU32(ir.IAdd(accumulatorHigh[0].Value(), sad(16u).Value())), IrU32(ir.IAdd(accumulatorHigh[1].Value(), sad(24u).Value()))});
return true;
}
const auto packed = [&](const IrU32& addend, std::uint32_t shift) {
const IrU32 low(ir.IAdd(addend.Value(), sad(shift).Value()));
const IrU32 high(ir.IAdd(ir.ShiftRightLogical(addend.Value(), ir.Constant(16u)), sad(shift + 8u).Value()));
return IrU32(ir.BitwiseOr(ir.BitwiseAnd(low.Value(), ir.Constant(0xffffu)), ir.ShiftLeftLogical(high.Value(), ir.Constant(16u))));
};
writeU32Pair(inst.destination, {packed(accumulator[0], 0u), packed(accumulator[1], 16u)});
return true;
}
bool TranslationContext::vAdd3U32(const RdnaInstruction& inst) {
const IrU32 lhs = readU32(sourceAt(inst, 0u));
const IrU32 rhs = readU32(sourceAt(inst, 1u));

View File

@ -1027,6 +1027,12 @@ bool TranslationContext::emitVector(const RdnaInstruction& inst) {
return subwordSad(inst, 16u, 0u, false);
case RdnaOpcode::VMsadU8:
return subwordSad(inst, 8u, 0u, true);
case RdnaOpcode::VQsadPkU16U8:
return vQsadU8(inst, false, false);
case RdnaOpcode::VMqsadPkU16U8:
return vQsadU8(inst, true, false);
case RdnaOpcode::VMqsadU32U8:
return vQsadU8(inst, true, true);
case RdnaOpcode::VAdd3U32:
return vAdd3U32(inst);
case RdnaOpcode::VBcntU32B32: