From fa0ff0849c5d96534195d276658aa8211d115076 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Mon, 26 Jul 2021 06:37:25 +0200 Subject: [PATCH] etnaviv: Add isaspec support This commit adds etnaviv.xml which describes the used ISA. Quite some time was spend to to get it into that shape by creating a big collection of shader asm generated by the binary blob. These shaders are used as basis for test driven development for this ISA specification. The xml has some black spots but the internal disasm is used by developers so that should be no problem. Some refinement will happen during normal development. This commit adds only disasm support. Signed-off-by: Christian Gmeiner Reviewed-by: Rob Clark Part-of: --- .clang-format-include | 1 + .gitlab-ci/test-source-dep.yml | 1 + src/etnaviv/ci/gitlab-ci.yml | 1 + src/etnaviv/isa/.clang-format | 7 + src/etnaviv/isa/disasm.c | 33 + src/etnaviv/isa/etnaviv.xml | 1246 +++++++++++++++++++++++++++++ src/etnaviv/isa/isa.h | 11 + src/etnaviv/isa/meson.build | 48 ++ src/etnaviv/isa/tests/disasm.cpp | 311 +++++++ src/etnaviv/isa/tests/meson.build | 14 + src/etnaviv/meson.build | 1 + 11 files changed, 1674 insertions(+) create mode 100644 src/etnaviv/isa/.clang-format create mode 100644 src/etnaviv/isa/disasm.c create mode 100644 src/etnaviv/isa/etnaviv.xml create mode 100644 src/etnaviv/isa/isa.h create mode 100644 src/etnaviv/isa/meson.build create mode 100644 src/etnaviv/isa/tests/disasm.cpp create mode 100644 src/etnaviv/isa/tests/meson.build diff --git a/.clang-format-include b/.clang-format-include index be36b4ffb33..63e032dc5d8 100644 --- a/.clang-format-include +++ b/.clang-format-include @@ -5,3 +5,4 @@ src/gallium/drivers/i915 src/amd/vulkan/**/* src/amd/compiler/**/* src/egl/**/* +src/etnaviv/isa/**/* diff --git a/.gitlab-ci/test-source-dep.yml b/.gitlab-ci/test-source-dep.yml index 4a2bed11b27..bee4d9c5772 100644 --- a/.gitlab-ci/test-source-dep.yml +++ b/.gitlab-ci/test-source-dep.yml @@ -253,6 +253,7 @@ - src/egl/**/* - src/amd/vulkan/**/* - src/amd/compiler/**/* + - src/etnaviv/isa/**/* when: on_success allow_failure: false # in other pipelines, formatting checks are allowed to fail diff --git a/src/etnaviv/ci/gitlab-ci.yml b/src/etnaviv/ci/gitlab-ci.yml index 947869d2c53..94c84cce6e9 100644 --- a/src/etnaviv/ci/gitlab-ci.yml +++ b/src/etnaviv/ci/gitlab-ci.yml @@ -13,6 +13,7 @@ - src/etnaviv/ci/$GPU_VERSION-skips.txt - src/etnaviv/drm/**/* - src/etnaviv/drm-shim/**/* + - src/etnaviv/isa/**/* - src/gallium/drivers/etnaviv/**/* - src/gallium/winsys/etnaviv/**/* - src/gallium/auxiliary/renderonly/**/* diff --git a/src/etnaviv/isa/.clang-format b/src/etnaviv/isa/.clang-format new file mode 100644 index 00000000000..b1a43d91fe2 --- /dev/null +++ b/src/etnaviv/isa/.clang-format @@ -0,0 +1,7 @@ + +BasedOnStyle: InheritParentConfig +DisableFormat: false + +AlignConsecutiveBitFields: true +ColumnLimit: 100 +BreakStringLiterals: false diff --git a/src/etnaviv/isa/disasm.c b/src/etnaviv/isa/disasm.c new file mode 100644 index 00000000000..88710f663c3 --- /dev/null +++ b/src/etnaviv/isa/disasm.c @@ -0,0 +1,33 @@ +/* + * Copyright © 2023 Igalia S.L. + * SPDX-License-Identifier: MIT + */ + +#include + +#include "util/os_file.h" + +#include "isa.h" + +static void +pre_instr_cb(void *d, unsigned n, void *instr) +{ + uint32_t *dwords = (uint32_t *)instr; + printf("%03d [%08x %08x %08x %08x] ", n, dwords[0], dwords[1], dwords[2], dwords[3]); +} + +int +main(int argc, char *argv[]) +{ + size_t sz; + void *raw = os_read_file(argv[1], &sz); + + isa_disasm(raw, sz, stdout, + &(struct isa_decode_options){ + .show_errors = true, + .branch_labels = true, + .pre_instr_cb = pre_instr_cb, + }); + + return 0; +} diff --git a/src/etnaviv/isa/etnaviv.xml b/src/etnaviv/isa/etnaviv.xml new file mode 100644 index 00000000000..b09c0a4609f --- /dev/null +++ b/src/etnaviv/isa/etnaviv.xml @@ -0,0 +1,1246 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {DST_USE} == 0 + + + void + + + + + t{REG}{AMODE}{COMPS} + + + + + + + + + + + + + 00 + + + + {TYPE_BIT2} << 2 | {TYPE_BIT01} + + + + + + .{SWIZ_X}{SWIZ_Y}{SWIZ_Z}{SWIZ_W} + + + + + + + + + + + + + + + + + + + + + 00000 + + + + + + + + {HIGH_HALF} << 1 | {LOW_HALF} + + + + + + + 00000000 + + + + + {SRC_NEG}{SRC_ABS}{SRC_RGROUP}{SRC_REG}{SRC_AMODE}{SRC_SWIZ}{SRC_ABS} + + + + + + + + ({SRC_AMODE} >> 1) + + + + + (({SRC_RGROUP} == 7) & ({IMMED_TYPE} == 0)) + + + + {IMMED} + + + + + (((({SRC_AMODE} & 0x1) << 19) | + ({SRC_ABS} << 18) | + ({SRC_NEG} << 17) | + ({SRC_SWIZ} << 9) | + {SRC_REG}) << 12) + + + + + + + (({SRC_RGROUP} == 7) & ({IMMED_TYPE} == 1)) + + + + {IMMED} + + + + + ((({SRC_AMODE} & 0x1) << 19) | + ({SRC_ABS} << 18) | + ({SRC_NEG} << 17) | + ({SRC_SWIZ} << 9) | + {SRC_REG}) + + + + + + + (({SRC_RGROUP} == 7) & ({IMMED_TYPE} == 2)) + + + + {IMMED} + + + + + ((({SRC_AMODE} & 0x1) << 19) | + ({SRC_ABS} << 18) | + ({SRC_NEG} << 17) | + ({SRC_SWIZ} << 9) | + {SRC_REG}) + + + + + + + (({SRC_RGROUP} == 7) & ({IMMED_TYPE} == 3)) + + + + {IMMED} + + + + + ((({SRC_AMODE} & 0x1) << 19) | + ({SRC_ABS} << 18) | + ({SRC_NEG} << 17) | + ({SRC_SWIZ} << 9) | + {SRC_REG}) + + + + + + + + {INSTR_ALU} {DST:align=18}, {SRC0}, {SRC1}, {SRC2} + + + xxxxxxxx + + + 1 + + + + + + + + + + + 1 + + + + + + + + + + + 1 + + + + + + + + + + + + + {INSTR_ALU} {DST:align=18}, {SRC0}, {SRC1}, {SRC2} + + + xxxxxxxx + + + 1 + + + + + + + + + + + 1 + + + + + + + + + + + 1 + + + + + + + + + + + + + {NAME} {DST:align=18}{DST_FULL}, void, void, void + + + + 0 + 000000000 + 00000000 + 0 + 0 + 0 + 000 + + + 0 + 000000000 + 00000000 + 0 + 0 + 000 + 000 + + + 0 + 000000000 + 00000000 + 0 + 0 + 000 + 000 + + + + ({SRC0_USE} != 0) && ({SRC1_USE} != 0) + + + + Needed for texkill + + {NAME}{COND}{TYPE}{PMODE}{THREAD}{RMODE} {DST:align=18}{DST_FULL}, void, void, void + + + + + {NAME}{COND}{TYPE}{PMODE}{THREAD}{RMODE} {DST:align=18}, {SRC0}, {SRC1}, void + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 000000000 + 00000000 + 0 + 0 + 000 + 000 + + + + + {INSTR_ALU} {DST:align=18}, {SRC0}, void, void + + + + 1 + + + + + + + + + + + 0 + 000000000 + 00000000 + 0 + 0 + 000 + 000 + + + 0 + 000000000 + 00000000 + 0 + 0 + 000 + 000 + + + + + {INSTR_ALU} {DST:align=18}, void, void, {SRC2} + + + + 0 + 000000000 + 00000000 + 0 + 0 + 0 + 000 + + + 0 + 000000000 + 00000000 + 0 + 0 + 000 + 000 + + + 1 + + + + + + + + + + + + + {INSTR_ALU} {DST:align=18}, {SRC0}, {SRC1}, void + + + + 1 + + + + + + + + + + + 1 + + + + + + + + + + + 0 + 000000000 + 00000000 + 0 + 0 + 000 + 000 + + + + + {INSTR_ALU} {DST:align=18}, {SRC0}, void, {SRC2} + + + + 1 + + + + + + + + + + + 0 + 000000000 + 00000000 + 0 + 0 + 000 + 000 + + + 1 + + + + + + + + + + + + + {INSTR_ALU} {DST:align=18}, {SRC0}, {SRC1}, {SRC2} + + + + 1 + + + + + + + + + + + 1 + + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 0 + + + + + {INSTR_TEX} {DST:align=18}, tex{TEX_ID}, {SRC0}, void, void + + + + 1 + + + + + + + + + + + 0 + 000000000 + 00000000 + 0 + 0 + 000 + 000 + + + 0 + 000000000 + 00000000 + 0 + 0 + 000 + 000 + + + + + {INSTR_TEX} {DST:align=18}, tex{TEX_ID}, {SRC0}, {SRC1}, {SRC2} + + + + 1 + + + + + + + + + + + 1 + + + + + + + + + + + 1 + + + + + + + + + + + + 00000000000000000000 + + 00 + x + 00000000 + + 0000 + + 0000000000 + + + + + {INSTR_CF} {:align=18}void, void, void, {TARGET} + + + 0000000000 + 0000000000 + + 0 + 0000000000000 + 0000000000000 + 000 + + + + + {INSTR_CF} {:align=18}void, {SRC0}, {SRC1}, {TARGET} + + + + 1 + + + + + + + + + + + 1 + + + + + + + + + + + + ({LEFT_SHIFT} != 0) + + + + + + + + + + 00000 + 00 + + + 00 + + + 0 + + + + + + + {HIGH_HALF} << 1 | {LOW_HALF} + + + + + + {INSTR_LOAD_STORE} {DST:align=18}, {SRC0}, {SRC1}, void + + + + + {INSTR_LOAD_STORE_WITH_LEFT_SHIFT} {DST:align=18}, {SRC0}, {SRC1}, void + + + + + 1 + + + + + + + + + + + 1 + + + + + + + + + + + 0 + 000000000 + 00000000 + 0 + 0 + 000 + 000 + + + + xxxxx + x + xxxxx + + xxxxx + xx + + + 00 + + + x + + + + + + + {HIGH_HALF} << 1 | {LOW_HALF} + + + + + + {INSTR_LOAD_STORE} {:align=18}mem{COMPS}, {SRC0}, {SRC1}, {SRC2} + + + + + {INSTR_LOAD_STORE_WITH_LEFT_SHIFT} {:align=18}mem{COMPS}, {SRC0}, {SRC1}, {SRC2} + + + + + 1 + + + + + + + + + + + 1 + + + + + + + + + + + 1 + + + + + + + + + + + + + + 000000 + 0 + + + + 000001 + 0 + + + + 000010 + 0 + + + + 000011 + 0 + + + + + + 000100 + 0 + + + + 000101 + 0 + + + + 000110 + 0 + + + + + + + 001001 + 0 + + + + + + + 001100 + 0 + + + + 001101 + 0 + + + + + + 001111 + 0 + + + + 010000 + 0 + + + + 010001 + 0 + + + + 010010 + 0 + + + + + + 010100 + 0 + + + + 010101 + 0 + + + + 010110 + 0 + + + + 010110 + 0 + + + + 010111 + 0 + + + + 011000 + 0 + + + + + + + + + + + + + + + 100001 + 0 + + + + 100010 + 0 + + + + 100011 + 0 + + + + + + 100101 + 0 + + + + 100110 + 0 + + + + 100111 + 0 + + + + + + + 101010 + 0 + + + + + + 101100 + 0 + + + + 101101 + 0 + + + + 101110 + 0 + + + + 101111 + 0 + + + + + + 110001 + 0 + + + + 110010 + 0 + + + + 110011 + 0 + + + + 111011 + 0 + + + + 111100 + 0 + + + + + + + + 000000 + 1 + + + + + + 000100 + 1 + + + + 001000 + 1 + + + + 001100 + 1 + + + + 001110 + 1 + + + + 011100 + 1 + + + + 011101 + 1 + + + + 011110 + 1 + + + + 011111 + 1 + + + + 100001 + 1 + + + + 010111 + 1 + + + + 011000 + 1 + + + + 011001 + 1 + + + + 011010 + 1 + + + + 011011 + 1 + + + + 100101 + 1 + + + + 100110 + 1 + + + + 100111 + 1 + + + + 101000 + 1 + + + + 101001 + 1 + + + + 101010 + 1 + + + + 101011 + 1 + + + + 101100 + 1 + + + + 101111 + 1 + + + diff --git a/src/etnaviv/isa/isa.h b/src/etnaviv/isa/isa.h new file mode 100644 index 00000000000..6214bc154ec --- /dev/null +++ b/src/etnaviv/isa/isa.h @@ -0,0 +1,11 @@ +/* + * Copyright © 2023 Igalia S.L. + * SPDX-License-Identifier: MIT + */ + +#ifndef _ISA_H_ +#define _ISA_H_ + +#include "compiler/isaspec/isaspec.h" + +#endif /* _ISA_H_ */ diff --git a/src/etnaviv/isa/meson.build b/src/etnaviv/isa/meson.build new file mode 100644 index 00000000000..a191f76ac5d --- /dev/null +++ b/src/etnaviv/isa/meson.build @@ -0,0 +1,48 @@ +# +# Copyright © 2023 Igalia S.L. +# SPDX-License-Identifier: MIT +# + +isa_depend_files = [ + 'etnaviv.xml', +] + +etnaviv_isa = custom_target( + 'etnaviv-isa', + input: ['etnaviv.xml'], + output: ['etnaviv-isa.c', 'etnaviv-isa.h'], + command: [ + prog_isaspec_decode, '--xml', '@INPUT@', + '--out-c', '@OUTPUT0@', '--out-h', '@OUTPUT1@', + ], + depend_files: isa_depend_files, +) + +decode_files = [ + etnaviv_isa, + 'isa.h', +] + +libetnaviv_decode = static_library( + 'etnaviv_decode', + decode_files, + dependencies: [idep_mesautil, idep_isaspec_decode], + include_directories: [ + inc_include, + inc_src, + ], + gnu_symbol_visibility: 'hidden', +) + +disasm = executable( + 'etnaviv-disasm', + ['disasm.c'], + link_with: libetnaviv_decode, + build_by_default: with_tools.contains('etnaviv'), + include_directories: [ + inc_src, + ], + install: false, +) + +subdir('tests') diff --git a/src/etnaviv/isa/tests/disasm.cpp b/src/etnaviv/isa/tests/disasm.cpp new file mode 100644 index 00000000000..09f3b478d04 --- /dev/null +++ b/src/etnaviv/isa/tests/disasm.cpp @@ -0,0 +1,311 @@ +/* + * Copyright © 2023 Igalia S.L. + * SPDX-License-Identifier: MIT + */ + +/* Unit test for disassembly of instructions. + * + * The goal is to take instructions we've seen the blob produce, and test that + * we can disassemble them correctly. + */ + +#include "compiler/isaspec/isaspec.h" +#include + +struct disasm_state { + uint32_t bin[4]; + const char *disasm; + + friend std::ostream &operator<<(std::ostream &os, const disasm_state &obj) + { + // clang-format off + return os + << "binary: " + << std::showbase << std::internal << std::setfill('0') << std::setw(8) << std::hex << obj.bin[0] << " " + << std::showbase << std::internal << std::setfill('0') << std::setw(8) << std::hex << obj.bin[1] << " " + << std::showbase << std::internal << std::setfill('0') << std::setw(8) << std::hex << obj.bin[2] << " " + << std::showbase << std::internal << std::setfill('0') << std::setw(8) << std::hex << obj.bin[3] << " " + << "disasm: " << obj.disasm; + // clang-format on + } +}; + +struct DisasmTest : testing::Test, testing::WithParamInterface { + char *disasm_output; + + DisasmTest() + { + static const struct isa_decode_options options = {.show_errors = true, + .branch_labels = false}; + + constexpr int output_size = 4096; + disasm_output = (char *)malloc(output_size); + FILE *fdisasm = fmemopen(disasm_output, output_size, "w+"); + + if (!fdisasm) { + return; + } + + isa_disasm((void *)GetParam().bin, 16, fdisasm, &options); + fflush(fdisasm); + } +}; + +TEST_P(DisasmTest, basicOpCodes) +{ + auto as = GetParam(); + EXPECT_STREQ(as.disasm, disasm_output); +} + +// clang-format off +INSTANTIATE_TEST_SUITE_P(Default, DisasmTest, + testing::Values( + disasm_state{ {0x00000000, 0x00000000, 0x00000000, 0x00000000}, "nop void, void, void, void\n" }, + disasm_state{ {0x07811018, 0x15001f20, 0x00000000, 0x00000000}, "texld.xyzw t1, tex0, t1.xyyy, void, void\n" }, + disasm_state{ {0x07831018, 0x39003f20, 0x00000000, 0x00000000}, "texld.xyzw t3, tex0, t3.xyzw, void, void\n" }, + disasm_state{ {0x07811009, 0x00000000, 0x00000000, 0x20390008}, "mov.pack t1, void, void, u0.xyzw\n" }, + disasm_state{ {0x01821009, 0x00000000, 0x00000000, 0x00150028}, "mov.pack t2.xy__, void, void, t2.xyyy\n"}, + disasm_state{ {0x01821009, 0x00000000, 0x00000000, 0x00550028}, "mov.pack t2.xy__, void, void, -t2.xyyy\n"}, + disasm_state{ {0x01821009, 0x00000000, 0x00000000, 0x00950028}, "mov.pack t2.xy__, void, void, |t2.xyyy|\n"} + ) +); +// clang-format on + +// clang-format off +INSTANTIATE_TEST_SUITE_P(OperandTypes, DisasmTest, + testing::Values( + disasm_state{ {0x01821009, 0x00000000, 0x00000000, 0x00150028}, "mov.pack t2.xy__, void, void, t2.xyyy\n"}, + disasm_state{ {0x01821009, 0x00000000, 0x40000000, 0x00150028}, "mov.s32.pack t2.xy__, void, void, t2.xyyy\n"}, + disasm_state{ {0x01821009, 0x00000000, 0x80000000, 0x00150028}, "mov.s8.pack t2.xy__, void, void, t2.xyyy\n"}, + disasm_state{ {0x01821009, 0x00000000, 0xc0000000, 0x00150028}, "mov.u16.pack t2.xy__, void, void, t2.xyyy\n"}, + disasm_state{ {0x01821009, 0x00200000, 0x00000000, 0x00150028}, "mov.f16.pack t2.xy__, void, void, t2.xyyy\n"}, + disasm_state{ {0x01821009, 0x00200000, 0x40000000, 0x00150028}, "mov.s16.pack t2.xy__, void, void, t2.xyyy\n"}, + disasm_state{ {0x01821009, 0x00200000, 0x80000000, 0x00150028}, "mov.u32.pack t2.xy__, void, void, t2.xyyy\n"}, + disasm_state{ {0x01821009, 0x00200000, 0xc0000000, 0x00150028}, "mov.u8.pack t2.xy__, void, void, t2.xyyy\n"} + ) +); +// clang-format on + +// clang-format off +INSTANTIATE_TEST_SUITE_P(Opcodes, DisasmTest, + testing::Values( + // GC3000 + disasm_state{ {0x00000000, 0x00000000, 0x00000000, 0x00000000}, "nop void, void, void, void\n" }, + disasm_state{ {0x00801001, 0x00001804, 0x00000000, 0x00000008}, "add t0.x___, t1.xxxx, void, t0.xxxx\n" }, + disasm_state{ {0x07801002, 0x39002805, 0x01c800c0, 0x00390038}, "mad.rtz t0, t2.xyzw, t1.xyzw, t3.xyzw\n" }, + disasm_state{ {0x00801003, 0x00001804, 0x00000040, 0x00000000}, "mul t0.x___, t1.xxxx, t0.xxxx, void\n" }, + disasm_state{ {0x00801005, 0x09000802, 0x00000040, 0x00000002}, "dp3.pack.rtne t0.x___, t0.xyzx, u0.xxxx, void\n" }, + disasm_state{ {0x00801006, 0x39001804, 0x01c800c0, 0x00000000}, "dp4 t0.x___, t1.xyzw, t1.xyzw, void\n" }, + disasm_state{ {0x01821009, 0x00000000, 0x00000000, 0x00150028}, "mov.pack t2.xy__, void, void, t2.xyyy\n"}, + disasm_state{ {0x0081100c, 0x00000000, 0x00000000, 0x00000018}, "rcp.pack t1.x___, void, void, t1.xxxx\n" }, + disasm_state{ {0x0080100d, 0x00000004, 0x00000000, 0x00000008}, "rsq t0.x___, void, void, t0.xxxx\n" }, + disasm_state{ {0x0783108f, 0x39002800, 0x05c800c0, 0x00390028}, "select.lt.pack t3, t2.xyzw, |t1.xyzw|, t2.xyzw\n"}, + disasm_state{ {0x008010d0, 0x00000800, 0x00000040, 0x00000002}, "set.ge.pack t0.x___, t0.xxxx, u0.xxxx, void\n" }, + disasm_state{ {0x01001011, 0x00000004, 0x00000000, 0x00154008}, "exp t0._y__, void, void, t0.yyyy\n" }, + disasm_state{ {0x01801012, 0x00000005, 0x00000000, 0x00000008}, "log.rtz t0.xy__, void, void, t0.xxxx\n" }, + disasm_state{ {0x00000014, 0x00000000, 0x00000000, 0x00000380}, "call void, void, void, 7\n" }, + disasm_state{ {0x00000015, 0x00000000, 0x00000000, 0x00000000}, "ret void, void, void, void\n" }, + disasm_state{ {0x00000016, 0x00000000, 0x00000000, 0x00001080}, "branch void, void, void, 33\n"}, + disasm_state{ {0x00000017, 0x00000000, 0x00000000, 0x00000000}, "texkill.pack void, void, void, void\n" }, + disasm_state{ {0x00000057, 0x00002800, 0x00000040, 0x00000002}, "texkill.gt.pack void, t2.xxxx, u0.xxxx, void\n" }, + disasm_state{ {0x07811018, 0x15001f20, 0x00000000, 0x00000000}, "texld.xyzw t1, tex0, t1.xyyy, void, void\n" }, + disasm_state{ {0x00801021, 0x00000004, 0x00000000, 0x00000008}, "sqrt t0.x___, void, void, t0.xxxx\n" }, + disasm_state{ {0x03001022, 0x00000005, 0x00000000, 0x00154008}, "sin.rtz t0.zy, void, void, t0.yyyy\n" }, + disasm_state{ {0x01801023, 0x00000005, 0x00000000, 0x00000008}, "cos.rtz t0.xy__, void, void, t0.xxxx\n" }, + disasm_state{ {0x00801025, 0x00000004, 0x00000000, 0x00000008}, "floor t0.x___, void, void, t0.xxxx\n"}, + disasm_state{ {0x00801026, 0x00000004, 0x00000000, 0x00000008}, "ceil t0.x___, void, void, t0.xxxx\n"}, + disasm_state{ {0x00801027, 0x00000004, 0x00000000, 0x00000008}, "sign t0.x___, void, void, t0.xxxx\n" }, + disasm_state{ {0x0000002a, 0x00000000, 0x00000000, 0x00000000}, "barrier void, void, void, void\n" }, + disasm_state{ {0x0080102c, 0x00200804, 0x50001040, 0x00000007}, "i2i.s16 t0.x___, t0.xxxx, 32, void\n" }, + disasm_state{ {0x0381102d, 0x00201804, 0x40000000, 0x00000000}, "i2f.s16 t1.xyz_, t1.xxxx, void, void\n"}, + disasm_state{ {0x0101102e, 0x00201804, 0x80000020, 0x00002000}, "f2i.u32.t0 t1._y__, th1.xxxx, void, void\n"}, + disasm_state{ {0x0081102f, 0x00000806, 0x40000000, 0x00000000}, "f2irnd.s32.rtne t1.x___, t0.xxxx, void, void\n"}, + disasm_state{ {0x00811131, 0x80001800, 0x00aa0040, 0x202a800a}, "cmp.le.pack t1.x___, |t1.xxxx|, u0.yyyy, u0.zzzz\n"}, + disasm_state{ {0x00801032, 0x00000c04, 0x10000050, 0x00000007}, "load.denorm t0.x___, u0.xxxx, 0, void\n"}, + disasm_state{ {0x00800033, 0x00000c84, 0x10000050, 0x0000000f}, "store.skpHp.denorm mem.x___, u0.xxxx, 0, t0.xxxx\n"}, + disasm_state{ {0x0080103b, 0x00001804, 0x40000000, 0x00400028}, "iaddsat.s32 t0.x___, t1.xxxx, void, -t2.xxxx\n"}, + disasm_state{ {0x01001008, 0x15400804, 0xd00100c0, 0x00000007}, "imod.u16 t0._y__, t0.yyyy, 1, void\n"}, + disasm_state{ {0x0080103c, 0x00001804, 0x40000140, 0x00000000}, "imullo0.s32 t0.x___, t1.xxxx, t2.xxxx, void\n"}, + disasm_state{ {0x00801000, 0x00001804, 0x40010140, 0x00000000}, "imulhi0.s32 t0.x___, t1.xxxx, t2.xxxx, void\n"}, + disasm_state{ {0x00801004, 0x00201804, 0x40010040, 0x00000000}, "idiv0.s16 t0.x___, t1.xxxx, t0.xxxx, void\n"}, + disasm_state{ {0x0080100e, 0x00001804, 0x40010140, 0x00000038}, "imadlosat0.s32 t0.x___, t1.xxxx, t2.xxxx, t3.xxxx\n"}, + disasm_state{ {0x0082101c, 0x00001804, 0x40010000, 0x00000008}, "or.s32 t2.x___, t1.xxxx, void, t0.xxxx\n"}, + disasm_state{ {0x0082101d, 0x00001804, 0x40010000, 0x00000008}, "and.s32 t2.x___, t1.xxxx, void, t0.xxxx\n"}, + disasm_state{ {0x0080101e, 0x00001804, 0x40010000, 0x00000008}, "xor.s32 t0.x___, t1.xxxx, void, t0.xxxx\n"}, + disasm_state{ {0x0080101f, 0x00000004, 0x40010000, 0x00000018}, "not.s32 t0.x___, void, void, t1.xxxx\n"}, + disasm_state{ {0x00801021, 0x00000004, 0x00010000, 0x00000008}, "popcount t0.x___, void, void, t0.xxxx\n"}, + disasm_state{ {0x00801017, 0x00000004, 0x40010000, 0x00000018}, "iabs.s32 t0.x___, void, void, t1.xxxx\n"}, + disasm_state{ {0x00801018, 0x00000004, 0x40010000, 0x00000008}, "leadzero.s32 t0.x___, void, void, t0.xxxx\n"}, + disasm_state{ {0x00801019, 0x15400804, 0x40010000, 0x74000028}, "lshift.s32 t0.x___, t0.yyyy, void, 2\n"}, + disasm_state{ {0x0080101a, 0x00001804, 0x40010000, 0x78000018}, "rshift.s32 t0.x___, t1.xxxx, void, 1\n"}, + disasm_state{ {0x0080101b, 0x00001804, 0x40010000, 0x00000008}, "rotate.s32 t0.x___, t1.xxxx, void, t0.xxxx\n"}, + disasm_state{ {0x01061025, 0x2aa00804, 0xa0010050, 0x7800001f}, "atomic_add.u32 t6._y__, u0.zzzz, 0, 1\n"}, + disasm_state{ {0x00801025, 0x2a800884, 0x50010050, 0x0000000f}, "atomic_add.s32 t0.x___, u0.zzzz, 0, t0.xxxx\t; dontcare bits in atomic_add: 00000000000000000000008000000000\n"}, + disasm_state{ {0x00821026, 0x2a800884, 0x50010050, 0x0000001f}, "atomic_xchg.s32 t2.x___, u0.zzzz, 0, t1.xxxx\t; dontcare bits in atomic_xchg: 00000000000000000000008000000000\n"}, + disasm_state{ {0x00801027, 0x2a800884, 0x50010050, 0x0015000f}, "atomic_cmp_xchg.s32 t0.x___, u0.zzzz, 0, t0.xyyy\t; dontcare bits in atomic_cmp_xchg: 00000000000000000000008000000000\n"}, + disasm_state{ {0x00821028, 0x2a800884, 0x50010050, 0x0000001f}, "atomic_min.s32 t2.x___, u0.zzzz, 0, t1.xxxx\t; dontcare bits in atomic_min: 00000000000000000000008000000000\n"}, + disasm_state{ {0x00821029, 0x2a800884, 0x50010050, 0x0000000f}, "atomic_max.s32 t2.x___, u0.zzzz, 0, t0.xxxx\t; dontcare bits in atomic_max: 00000000000000000000008000000000\n"}, + disasm_state{ {0x0080102a, 0x2a800884, 0x50010050, 0x0000000f}, "atomic_or.s32 t0.x___, u0.zzzz, 0, t0.xxxx\t; dontcare bits in atomic_or: 00000000000000000000008000000000\n"}, + disasm_state{ {0x0082102b, 0x2a800884, 0x50010050, 0x0000001f}, "atomic_and.s32 t2.x___, u0.zzzz, 0, t1.xxxx\t; dontcare bits in atomic_and: 00000000000000000000008000000000\n"}, + disasm_state{ {0x0080102c, 0x2a800884, 0x50010050, 0x0000001f}, "atomic_xor.s32 t0.x___, u0.zzzz, 0, t1.xxxx\t; dontcare bits in atomic_xor: 00000000000000000000008000000000\n"} + ) +); +// clang-format on + +// clang-format off +INSTANTIATE_TEST_SUITE_P(Branch, DisasmTest, + testing::Values( + // taken from deqp2 run on GC2000 + disasm_state{ {0x00000016, 0x00000000, 0x00000000, 0x00001080}, "branch void, void, void, 33\n"}, + disasm_state{ {0x00000056, 0x00000800, 0x000000d0, 0x00000280}, "branch.gt void, u0.xxxx, t1.xxxx, 5\n"}, + disasm_state{ {0x00000056, 0x00000800, 0x000000d0, 0x00000280}, "branch.gt void, u0.xxxx, t1.xxxx, 5\n"}, + disasm_state{ {0x00000096, 0x15402800, 0x00000040, 0x00000082}, "branch.lt void, t2.yyyy, u0.xxxx, 1\n"}, + disasm_state{ {0x000000d6, 0x00001800, 0x01540250, 0x00000980}, "branch.ge void, u1.xxxx, t4.zzzz, 19\n"}, + disasm_state{ {0x00000116, 0x3fc01800, 0x000000c0, 0x00000482}, "branch.le void, t1.wwww, u1.xxxx, 9\n"}, + disasm_state{ {0x00000156, 0x39001800, 0x000002c0, 0x00001282}, "branch.eq void, t1.xyzw, u5.xxxx, 37\n"}, + disasm_state{ {0x00000196, 0x15401800, 0x00aa0040, 0x00000382}, "branch.ne void, t1.yyyy, u0.yyyy, 7\n"} + ) +); +// clang-format on + +// clang-format off +INSTANTIATE_TEST_SUITE_P(Abs, DisasmTest, + testing::Values( + // taken from deqp2 run on GC2000 + disasm_state{ {0x00811131, 0x80001800, 0x00aa0040, 0x202a800a}, "cmp.le.pack t1.x___, |t1.xxxx|, u0.yyyy, u0.zzzz\n"}, + disasm_state{ {0x0783108f, 0x39002800, 0x05c800c0, 0x00390028}, "select.lt.pack t3, t2.xyzw, |t1.xyzw|, t2.xyzw\n"}, + disasm_state{ {0x0383108f, 0xa9001800, 0x05480140, 0x00a90018}, "select.lt.pack t3.xyz_, |t1.xyzz|, |t2.xyzz|, |t1.xyzz|\n"} + ) +); +// clang-format on + +// clang-format off +INSTANTIATE_TEST_SUITE_P(Minus, DisasmTest, + testing::Values( + // taken from deqp2 run on GC2000 + disasm_state{ {0x01021001, 0x3fc00800, 0x00000010, 0x00554018}, "add.pack t2._y__, u0.wwww, void, -t1.yyyy\n"}, + disasm_state{ {0x00821001, 0x40001800, 0x00000000, 0x00554018}, "add.pack t2.x___, -t1.xxxx, void, -t1.yyyy\n"} + ) +); +// clang-format on + +// clang-format off +INSTANTIATE_TEST_SUITE_P(AddressRegister, DisasmTest, + testing::Values( + // taken from deqp2 run on GC2000 + disasm_state{ {0x00823009, 0x00000000, 0x00000000, 0x00000018}, "mov.pack t2[a.x].x___, void, void, t1.xxxx\n"}, + disasm_state{ {0x00825009, 0x00000000, 0x00000000, 0x00154028}, "mov.pack t2[a.y].x___, void, void, t2.yyyy\n"}, + disasm_state{ {0x00827009, 0x00000000, 0x00000000, 0x00000018}, "mov.pack t2[a.z].x___, void, void, t1.xxxx\n"}, + disasm_state{ {0x00829009, 0x00000000, 0x00000000, 0x00000018}, "mov.pack t2[a.w].x___, void, void, t1.xxxx\n"}, + disasm_state{ {0x00801009, 0x00000000, 0x00000000, 0x02000028}, "mov.pack t0.x___, void, void, t2[a.x].xxxx\n"}, + disasm_state{ {0x01031009, 0x00000000, 0x00000000, 0x043fc018}, "mov.pack t3._y__, void, void, t1[a.y].wwww\n"}, + disasm_state{ {0x02031009, 0x00000000, 0x00000000, 0x063fc018}, "mov.pack t3.__z_, void, void, t1[a.z].wwww\n"}, + disasm_state{ {0x01811001, 0x15001800, 0x00000000, 0x28150018}, "add.pack t1.xy__, t1.xyyy, void, u1[a.w].xyyy\n"}, + disasm_state{ {0x01011001, 0x00001800, 0x00000001, 0x04000018}, "add.pack t1._y__, t1[a.x].xxxx, void, t1[a.y].xxxx\n"} + ) +); +// clang-format on + +// clang-format off +INSTANTIATE_TEST_SUITE_P(Threads, DisasmTest, + testing::Values( + // taken from deqp3 run on GC3000 + disasm_state{ {0x01011001, 0x00001804, 0x00000020, 0xa0402008}, "add.t0 t1._y__, th1.xxxx, void, -u0.xxxx\n"}, + disasm_state{ {0x01021001, 0x00002804, 0x00000020, 0xa1400008}, "add.t1 t2._y__, th2.xxxx, void, -u0.xxxx\n"}, + + // full dual-16 shader from a deqp3 run on GC3000 + disasm_state{ {0x0101102e, 0x00201804, 0x80000020, 0x00002000}, "f2i.u32.t0 t1._y__, th1.xxxx, void, void\n"}, + disasm_state{ {0x0101102e, 0x00202804, 0x80000020, 0x01000000}, "f2i.u32.t1 t1._y__, th2.xxxx, void, void\n"}, + disasm_state{ {0x00811171, 0x15601804, 0x80000040, 0x76fffffa}, "cmp.eq.u32.t0 t1.x___, t1.yyyy, u0.xxxx, -1\n"}, + disasm_state{ {0x00811171, 0x15601804, 0x80000040, 0x77ffdffa}, "cmp.eq.u32.t1 t1.x___, t1.yyyy, u0.xxxx, -1\n"}, + disasm_state{ {0x0081158f, 0x00201804, 0x700000c0, 0x7c00000f}, "select.0x16.s16 t1.x___, t1.xxxx, 0.000000, 0.000000\n"}, + disasm_state{ {0x0381102d, 0x00201804, 0x40000000, 0x00000000}, "i2f.s16 t1.xyz_, t1.xxxx, void, void\n"}, + disasm_state{ {0x04011009, 0x00000004, 0x00000000, 0x20154008}, "mov t1.___w, void, void, u0.yyyy\n"} + ) +); +// clang-format on + +// clang-format off +INSTANTIATE_TEST_SUITE_P(ImmediateValues, DisasmTest, + testing::Values( + // taken from deqp3 run on GC3000 + disasm_state{ {0x00801001, 0x7e000805, 0x00000038, 0x00800008}, "add.rtz t0.x___, 0.500000, void, |t0.xxxx|\n"}, /* type: 0 */ + disasm_state{ {0x00811131, 0x95401804, 0x00aa0060, 0x76fffffa}, "cmp.le.t0 t1.x___, |th1.yyyy|, u0.yyyy, -1\n"}, /* type: 1 */ + disasm_state{ {0x0080101a, 0x00001804, 0x40010000, 0x78000018}, "rshift.s32 t0.x___, t1.xxxx, void, 1\n"}, /* type: 2*/ + disasm_state{ {0x020211b1, 0x00001804, 0x01fe0040, 0x7c1fdffa}, "cmp.ne t2.__z_, t1.xxxx, u0.wwww, -nan\n"} /* type: 3 */ + ) +); +// clang-format on + +// clang-format off +INSTANTIATE_TEST_SUITE_P(LoadStore, DisasmTest, + testing::Values( + // full opencl shader on GC3000 + disasm_state{ {0x00801032, 0x00000c04, 0x10000050, 0x00000007}, "load.denorm t0.x___, u0.xxxx, 0, void\n"}, + disasm_state{ {0x00811032, 0x15400c04, 0x10000050, 0x00000007}, "load.denorm t1.x___, u0.yyyy, 0, void\n"}, + disasm_state{ {0x00801001, 0x00001804, 0x00000000, 0x00000008}, "add t0.x___, t1.xxxx, void, t0.xxxx\n"}, + disasm_state{ {0x00800033, 0x00000c84, 0x10000050, 0x0000000f}, "store.skpHp.denorm mem.x___, u0.xxxx, 0, t0.xxxx\n"} + ) +); +// clang-format on + +// clang-format off +INSTANTIATE_TEST_SUITE_P(Rounding, DisasmTest, + testing::Values( + // taken from opencl shader on GC3000 + disasm_state{ {0x0081102f, 0x00000806, 0x40000000, 0x00000000}, "f2irnd.s32.rtne t1.x___, t0.xxxx, void, void\n"} + ) +); +// clang-format on + +// clang-format off +INSTANTIATE_TEST_SUITE_P(CLRoundShader, DisasmTest, + testing::Values( + // taken from opencl shader on GC3000 + disasm_state{ {0x00801032, 0x15400c04, 0x10000050, 0x00000007}, "load.denorm t0.x___, u0.yyyy, 0, void\n"}, + disasm_state{ {0x00811027, 0x00000004, 0x00000000, 0x00000008}, "sign t1.x___, void, void, t0.xxxx\n"}, + disasm_state{ {0x00801001, 0x7e000805, 0x00000038, 0x00800008}, "add.rtz t0.x___, 0.500000, void, |t0.xxxx|\n"}, + disasm_state{ {0x00801025, 0x00000004, 0x00000000, 0x00000008}, "floor t0.x___, void, void, t0.xxxx\n"}, + disasm_state{ {0x00801003, 0x00001805, 0x00000040, 0x00000000}, "mul.rtz t0.x___, t1.xxxx, t0.xxxx, void\n"} + ) +); +// clang-format on + +// clang-format off +INSTANTIATE_TEST_SUITE_P(TFShader, DisasmTest, + testing::Values( + // taken from transform shader on GC2000 + disasm_state{ {0x0081102e, 0x00000800, 0x40000020, 0x00000000}, "f2i.s32.pack t1.x___, th0.xxxx, void, void\n"}, + disasm_state{ {0x07821009, 0x00000000, 0x00000000, 0x00390008}, "mov.pack t2, void, void, t0.xyzw\n"}, + disasm_state{ {0x01831009, 0x00000000, 0x00000000, 0x00150008}, "mov.pack t3.xy__, void, void, t0.xyyy\n"}, + disasm_state{ {0x03841009, 0x00000000, 0x00000000, 0x00290008}, "mov.pack t4.xyz_, void, void, t0.xyzz\n"}, + disasm_state{ {0x0201102d, 0x00000800, 0x40000010, 0x00000000}, "i2f.s32.pack t1.__z_, u0.xxxx, void, void\n"}, + disasm_state{ {0x00000156, 0x2a801800, 0x01540040, 0x00000402}, "branch.eq void, t1.zzzz, u0.zzzz, 8\n"}, + disasm_state{ {0x0081100c, 0x3fc00800, 0x400100d0, 0x20154008}, "imadlo0.s32.pack t1.x___, u0.wwww, t1.xxxx, u0.yyyy\n"}, + disasm_state{ {0x07820033, 0x00001800, 0x01540040, 0x0039002a}, "store.pack mem, t1.xxxx, u0.zzzz, t2.xyzw\t; dontcare bits in store: 00000000000000000000000000020000\n"} + ) +); +// clang-format on + +// clang-format off +INSTANTIATE_TEST_SUITE_P(texldlpcf, DisasmTest, + testing::Values( + // taken from dEQP-GLES3.functional.shaders.texture_functions.texturelod.sampler2dshadow_vertex (GC7000) + disasm_state{ {0x04011809, 0x00000004, 0x00000000, 0x002a8018}, "mov.sat t1.___w, void, void, t1.zzzz\n"}, + disasm_state{ {0x0081102f, 0x29001800, 0x00010140, 0x003fc018}, "texldlpcf.xxxx t1.x___, tex0, t1.xyzz, t1.xxxx, t1.wwww\n"}, + disasm_state{ {0x07011009, 0x00000004, 0x00000000, 0x20390018}, "mov t1._yzw, void, void, u1.xyzw\n"} + ) +); +// clang-format on + +// clang-format off +INSTANTIATE_TEST_SUITE_P(LoadStoreVariants, DisasmTest, + testing::Values( + // seen on GC7000 + disasm_state{ {0x01001032, 0x15400c14, 0x00000050, 0x00000000}, "load.denorm.ls2 t0._y__, u0.yyyy, t0.xxxx, void\n"}, + disasm_state{ {0x01001032, 0x15400d14, 0x00000040, 0x00000000}, "load.denorm.local.ls2 t0._y__, t0.yyyy, t0.xxxx, void\n"}, + disasm_state{ {0x00800033, 0x00000c14, 0x00000050, 0x00154008}, "store.denorm.ls2 mem.x___, u0.xxxx, t0.xxxx, t0.yyyy\n"}, + disasm_state{ {0x00861033, 0x15400d04, 0x100efe40, 0x7085860f}, "store.denorm.local mem.x___, t0.yyyy, 4092, 99.000000\t; dontcare bits in store: 00000000000000000000000000061000\n"} + ) +); +// clang-format on diff --git a/src/etnaviv/isa/tests/meson.build b/src/etnaviv/isa/tests/meson.build new file mode 100644 index 00000000000..afb13bf5cec --- /dev/null +++ b/src/etnaviv/isa/tests/meson.build @@ -0,0 +1,14 @@ +# +# Copyright © 2023 Igalia S.L. +# SPDX-License-Identifier: MIT +# + +test( + 'etnaviv_isa_disasm', + executable( + 'etnaviv_disasm', 'disasm.cpp', + link_with: [libetnaviv_decode], + include_directories: [inc_etnaviv, inc_src], + dependencies : [idep_gtest], + ) +) diff --git a/src/etnaviv/meson.build b/src/etnaviv/meson.build index f2292c6dd12..2150aae1b3b 100644 --- a/src/etnaviv/meson.build +++ b/src/etnaviv/meson.build @@ -21,6 +21,7 @@ inc_etnaviv = include_directories(['.']) subdir('drm') +subdir('isa') if with_tools.contains('drm-shim') subdir('drm-shim')