From: David Belanger <[email protected]> Add initial trap handler. Implementation provided by Jay Cornwall.
v2: Remove non-GFX13 binary changes v3: squash in updates Signed-off-by: Jay Cornwall <[email protected]> Signed-off-by: David Belanger <[email protected]> Signed-off-by: Alex Deucher <[email protected]> --- .../gpu/drm/amd/amdkfd/cwsr_trap_handler.h | 568 ++++++++ .../amd/amdkfd/cwsr_trap_handler_gfx13.asm | 1181 +++++++++++++++++ 2 files changed, 1749 insertions(+) create mode 100755 drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx13.asm diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h index 5d468460f532c..cad6d808335b2 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h @@ -5994,3 +5994,571 @@ static const uint32_t cwsr_trap_gfx12_1_0_rev_1_hex[] = { 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, }; + +static const uint32_t cwsr_trap_gfx13_hex[] = { + 0xbf820001, 0xbf82028b, + 0xb0804014, 0xb978f803, + 0x8a78ff78, 0x00008c00, + 0xb97bf811, 0x876eff78, + 0x00004000, 0xbf840008, + 0x876eff7b, 0x00000080, + 0xbf85001c, 0x876ea07b, + 0xbf850046, 0xbf8e0010, + 0xb97bf811, 0xbf82fffb, + 0x876eff7b, 0x00000bd0, + 0xbf850014, 0xb96ef812, + 0xbf0d876e, 0xbf840002, + 0xbeee1b87, 0xbeee1d8a, + 0x876f8f7b, 0xbf840002, + 0x886eff6e, 0x00000080, + 0xb96ff813, 0x876e6e6f, + 0xbf850008, 0x876eff6d, + 0xf0000000, 0xbf850005, + 0x876fff6f, 0x00000200, + 0xbf850002, 0x876ea07b, + 0xbf85002c, 0xbefa4d82, + 0xbfc70000, 0x8ffa887a, + 0xbf0d8f7b, 0xbf840002, + 0x887bff7b, 0xffff0000, + 0xf4601bbd, 0xf8000010, + 0xbfc70000, 0x8f6e976e, + 0x8a77ff77, 0x00800000, + 0x88776e77, 0xf4603bbd, + 0xf8000000, 0xbfc70000, + 0xf4603ebd, 0xf8000008, + 0xbfc70000, 0x87ee6e6e, + 0xbf840001, 0xbe80206e, + 0x876eff6d, 0xf0000000, + 0xbf850009, 0xb96ef811, + 0x876eff6e, 0x00000080, + 0xbf850007, 0x8878ff78, + 0x00004000, 0x80ec886c, + 0x82ed806d, 0xbf820002, + 0x806c846c, 0x826d806d, + 0x876dff6d, 0x0000ffff, + 0x87fe7e7e, 0x87ea6a6a, + 0x90788978, 0xb9f83243, + 0xbe80226c, 0xba800151, + 0x00000000, 0xbefa047e, + 0xbefe4d84, 0xbfc70000, + 0xbeee047e, 0xbefe047a, + 0x93faff6f, 0x0002001a, + 0x876fff6f, 0x0000ffff, + 0x876dff6d, 0x0000ffff, + 0x8f7a9e7a, 0x886d7a6d, + 0xb97a025b, 0x8f7a9d7a, + 0x886d7a6d, 0xb97a0742, + 0x8f7a9c7a, 0x886d7a6d, + 0xbf0d9d6d, 0xbf840004, + 0xbf0d9f6d, 0xbf850002, + 0xbefa0380, 0xbf820008, + 0xb97a3b05, 0x807a817a, + 0x8f7a827a, 0xbf0d9c6d, + 0xbf850002, 0x8f7a877a, + 0xbf820001, 0x8f7a887a, + 0x807aff7a, 0x000001c0, + 0x807a6e7a, 0x827b806f, + 0xee22007a, 0x380c0000, + 0x00001000, 0xee22007a, + 0x388c0000, 0x00001400, + 0xee22007a, 0x390c0000, + 0x00001800, 0xee22007a, + 0x398c0000, 0x00001c00, + 0xee22007a, 0x3a0c0000, + 0x00002000, 0xee22007a, + 0x3a8c0000, 0x00002400, + 0xee22007a, 0x3b0c0000, + 0x00002800, 0xee22007a, + 0x3b8c0000, 0x00002c00, + 0xee22007a, 0x3c8c0000, + 0x00003400, 0xbf0d9d6d, + 0xbf840004, 0xbf0d9f6d, + 0xbf850002, 0xbefa0380, + 0xbf820008, 0xb97a3b05, + 0x807a817a, 0x8f7a827a, + 0xbf0d9c6d, 0xbf850002, + 0x8f7a877a, 0xbf820001, + 0x8f7a887a, 0x807aff7a, + 0x00000200, 0x80767a6e, + 0x8277806f, 0xb97af802, + 0xbf0c8b7a, 0xbf850003, + 0xbe804fc2, 0xbfabfffe, + 0xbf840001, 0xbe804ec4, + 0xbfabfffc, 0xb97af803, + 0x877aff7a, 0x0060000c, + 0x8a78ff78, 0x0060000c, + 0x88787a78, 0xbefa037d, + 0xee220076, 0x3d0c0000, + 0x00000000, 0xee220076, + 0x360c0000, 0x00000400, + 0x877aff6d, 0x0000ffff, + 0xee220076, 0x3d0c0000, + 0x00000800, 0xbefa037e, + 0xee220076, 0x3d0c0000, + 0x00000c00, 0xbefa037f, + 0xee220076, 0x3d0c0000, + 0x00001000, 0xee220076, + 0x3c0c0000, 0x00001400, + 0xb97af811, 0xee220076, + 0x3d0c0000, 0x00001800, + 0xbefa0380, 0xee220076, + 0x3d0c0000, 0x00001c00, + 0xb97af801, 0xee220076, + 0x3d0c0000, 0x00002000, + 0xb97af814, 0xee220076, + 0x3d0c0000, 0x00002400, + 0xb97af815, 0xee220076, + 0x3d0c0000, 0x00002800, + 0xb97af812, 0xee220076, + 0x3d0c0000, 0x00002c00, + 0xb97af813, 0xee220076, + 0x3d0c0000, 0x00003000, + 0xb97af802, 0xee220076, + 0x3d0c0000, 0x00003400, + 0xbefa50c1, 0xbfc70000, + 0xee220076, 0x3d0c0000, + 0x00003800, 0xbefa4c88, + 0xbfc70000, 0xee220076, + 0x3d0c0000, 0x00003c00, + 0xb97af82c, 0xee220076, + 0x3d0c0000, 0x00004000, + 0xb97af82d, 0xee220076, + 0x3d0c0000, 0x00004400, + 0xb97a061c, 0xee220076, + 0x3d0c0000, 0x00004800, + 0xbf0d9d6d, 0xbf840022, + 0xbefa5680, 0xbfc70000, + 0xee220076, 0x3d0c0000, + 0x00004c00, 0xb97af82e, + 0xee220076, 0x3d0c0000, + 0x00005000, 0xbefa4c8c, + 0xbfc70000, 0xee220076, + 0x3d0c0000, 0x00005400, + 0xbefa4c8d, 0xbfc70000, + 0xee220076, 0x3d0c0000, + 0x00005800, 0xbefa4c8e, + 0xbfc70000, 0xee220076, + 0x3d0c0000, 0x00005c00, + 0xbefa4c8f, 0xbfc70000, + 0xee220076, 0x3d0c0000, + 0x00006000, 0xbefa4c90, + 0xbfc70000, 0xee220076, + 0x3d0c0000, 0x00006400, + 0xbefa5081, 0xbfc70000, + 0xee220076, 0x3d0c0000, + 0x00008000, 0xbefa5082, + 0xbfc70000, 0xee220076, + 0x3d0c0000, 0x00008400, + 0xbefa5083, 0xbfc70000, + 0xee220076, 0x3d0c0000, + 0x00008800, 0xbefa5084, + 0xbfc70000, 0xee220076, + 0x3d0c0000, 0x00008c00, + 0xbefa5085, 0xbfc70000, + 0xee220076, 0x3d0c0000, + 0x00009000, 0xbefa5086, + 0xbfc70000, 0xee220076, + 0x3d0c0000, 0x00009400, + 0xbefa5087, 0xbfc70000, + 0xee220076, 0x3d0c0000, + 0x00009800, 0xbefa5088, + 0xbfc70000, 0xee220076, + 0x3d0c0000, 0x00009c00, + 0xbefa5089, 0xbfc70000, + 0xee220076, 0x3d0c0000, + 0x0000a000, 0xbefa508a, + 0xbfc70000, 0xee220076, + 0x3d0c0000, 0x0000a400, + 0xbefa508b, 0xbfc70000, + 0xee220076, 0x3d0c0000, + 0x0000a800, 0xbefa508c, + 0xbfc70000, 0xee220076, + 0x3d0c0000, 0x0000ac00, + 0xbefa508d, 0xbfc70000, + 0xee220076, 0x3d0c0000, + 0x0000b000, 0xbefa508e, + 0xbfc70000, 0xee220076, + 0x3d0c0000, 0x0000b400, + 0xbefa508f, 0xbfc70000, + 0xee220076, 0x3d0c0000, + 0x0000b800, 0xbefa5090, + 0xbfc70000, 0xee220076, + 0x3d0c0000, 0x0000bc00, + 0xbefa50a1, 0xbfc70000, + 0xee220076, 0x3d0c0000, + 0x0000c000, 0xbefa50a2, + 0xbfc70000, 0xee220076, + 0x3d0c0000, 0x0000c400, + 0xbefa50a3, 0xbfc70000, + 0xee220076, 0x3d0c0000, + 0x0000c800, 0xbefa50a4, + 0xbfc70000, 0xee220076, + 0x3d0c0000, 0x0000cc00, + 0xbf0d9d6d, 0xbf840004, + 0xbf0d9f6d, 0xbf850002, + 0xbefa0380, 0xbf820008, + 0xb97a3b05, 0x807a817a, + 0x8f7a827a, 0xbf0d9c6d, + 0xbf850002, 0x8f7a877a, + 0xbf820001, 0x8f7a887a, + 0x80767a6e, 0x8277806f, + 0xbefd0380, 0x86800100, + 0x86820102, 0x86840104, + 0x86860106, 0x86880108, + 0x868a010a, 0x868c010c, + 0x868e010e, 0xee220076, + 0x000c0000, 0x00000000, + 0xee220076, 0x008c0000, + 0x00000400, 0xee220076, + 0x010c0000, 0x00000800, + 0xee220076, 0x018c0000, + 0x00000c00, 0xee220076, + 0x020c0000, 0x00001000, + 0xee220076, 0x028c0000, + 0x00001400, 0xee220076, + 0x030c0000, 0x00001800, + 0xee220076, 0x038c0000, + 0x00001c00, 0xee220076, + 0x040c0000, 0x00002000, + 0xee220076, 0x048c0000, + 0x00002400, 0xee220076, + 0x050c0000, 0x00002800, + 0xee220076, 0x058c0000, + 0x00002c00, 0xee220076, + 0x060c0000, 0x00003000, + 0xee220076, 0x068c0000, + 0x00003400, 0xee220076, + 0x070c0000, 0x00003800, + 0xee220076, 0x078c0000, + 0x00003c00, 0x8076c076, + 0x82778077, 0x807d907d, + 0xbf0aff7d, 0x00000060, + 0xbf85ffc2, 0x86800100, + 0x86820102, 0x86840104, + 0x86860106, 0x86880108, + 0x868a010a, 0xee220076, + 0x000c0000, 0x00000000, + 0xee220076, 0x008c0000, + 0x00000400, 0xee220076, + 0x010c0000, 0x00000800, + 0xee220076, 0x018c0000, + 0x00000c00, 0xee220076, + 0x020c0000, 0x00001000, + 0xee220076, 0x028c0000, + 0x00001400, 0xee220076, + 0x030c0000, 0x00001800, + 0xee220076, 0x038c0000, + 0x00001c00, 0xee220076, + 0x040c0000, 0x00002000, + 0xee220076, 0x048c0000, + 0x00002400, 0xee220076, + 0x050c0000, 0x00002800, + 0xee220076, 0x058c0000, + 0x00002c00, 0xb97af802, + 0xbf0d987a, 0xbf85007c, + 0x877aff6d, 0xa0000000, + 0xbf06ff7a, 0x20000000, + 0xbf850030, 0xbef6046e, + 0xb97b3b05, 0x807b817b, + 0x8f7b827b, 0xbefa0380, + 0xbefe04c1, 0xbf9c0000, + 0xbf0d9c6d, 0xbf850014, + 0xbe806f7a, 0xee05c076, + 0x000c0000, 0x00000000, + 0xee05c076, 0x008c0000, + 0x00008000, 0xee05c076, + 0x010c0000, 0x00010000, + 0xee05c076, 0x018c0000, + 0x00018000, 0x8076ff76, + 0x00000200, 0x82778077, + 0x807a847a, 0xbf0a7b7a, + 0xbf85ffed, 0xbf820013, + 0xbe806f7a, 0xee05c076, + 0x000c0000, 0x00000000, + 0xee05c076, 0x008c0000, + 0x00010000, 0xee05c076, + 0x010c0000, 0x00020000, + 0xee05c076, 0x018c0000, + 0x00030000, 0x8076ff76, + 0x00000400, 0x82778077, + 0x807a847a, 0xbf0a7b7a, + 0xbf85ffed, 0xb97b4306, + 0x8f7b8a7b, 0xbf840044, + 0xbf0d9d6d, 0xbf840002, + 0xbe804ec2, 0xbfabfffe, + 0xbf0d9e6d, 0xbf84003e, + 0xbf0d9d6d, 0xbf840004, + 0xbf0d9f6d, 0xbf850002, + 0xbefa0380, 0xbf820008, + 0xb97a3b05, 0x807a817a, + 0x8f7a827a, 0xbf0d9c6d, + 0xbf850002, 0x8f7a877a, + 0xbf820001, 0x8f7a887a, + 0x807aff7a, 0x00000400, + 0x80767a6e, 0x8277806f, + 0xbefe04c1, 0xbefa0380, + 0xbf9c0000, 0xbe806f80, + 0xd7650000, 0x000100c1, + 0xd7660000, 0x000200c1, + 0x34000082, 0xbf0d9c6d, + 0xbf850011, 0xd8d80000, + 0x01000000, 0xbfc60000, + 0xee05c076, 0x008c0000, + 0x00000000, 0x8076ff76, + 0x00000080, 0x82778077, + 0xd5250000, 0x0001ff00, + 0x00000080, 0x807aff7a, + 0x00000080, 0xbf0a7b7a, + 0xbf85fff0, 0xbf820010, + 0xd8d80000, 0x01000000, + 0xbfc60000, 0xee05c076, + 0x008c0000, 0x00000000, + 0x8076ff76, 0x00000100, + 0x82778077, 0xd5250000, + 0x0001ff00, 0x00000100, + 0x807aff7a, 0x00000100, + 0xbf0a7b7a, 0xbf85fff0, + 0xb97af802, 0xbf0c8b7a, + 0xbf850003, 0xbe804fc2, + 0xbfabfffe, 0xbf840001, + 0xbe804ec4, 0xbfabfffc, + 0xbf9b0000, 0xbef4047e, + 0x93eeff75, 0x0002001a, + 0x8775ff75, 0x0000ffff, + 0x8f729e6e, 0xb96e025b, + 0x8f6e9d6e, 0x88726e72, + 0xb96e0742, 0x8f6e9c6e, + 0x88726e72, 0xbf0d9d72, + 0xbf840004, 0xbf0d9f72, + 0xbf850002, 0xbeee0380, + 0xbf820008, 0xb96e3b05, + 0x806e816e, 0x8f6e826e, + 0xbf0d9c72, 0xbf850002, + 0x8f6e876e, 0xbf820001, + 0x8f6e886e, 0x806eff6e, + 0x00000200, 0x80766e74, + 0x82778075, 0xf4601bbb, + 0xf8000034, 0xbfc70000, + 0xbf0d986e, 0xbf840002, + 0xbf900003, 0xbf82007d, + 0xb96f4306, 0x8f6f8a6f, + 0xbf840044, 0xbf0d9e72, + 0xbf84003e, 0xbf0d9d72, + 0xbf840004, 0xbf0d9f72, + 0xbf850002, 0xbeee0380, + 0xbf820008, 0xb96e3b05, + 0x806e816e, 0x8f6e826e, + 0xbf0d9c72, 0xbf850002, + 0x8f6e876e, 0xbf820001, + 0x8f6e886e, 0x806eff6e, + 0x00000400, 0x80766e74, + 0x82778075, 0xbefe04c1, + 0xbeee0380, 0xd7650000, + 0x000100c1, 0xd7660000, + 0x000200c1, 0x34000082, + 0xbf0d9c72, 0xbf850012, + 0xee058076, 0x000c0001, + 0x00000000, 0xbfc00000, + 0xd8340000, 0x00000100, + 0x8076ff76, 0x00000080, + 0x82778077, 0xd5250000, + 0x0001ff00, 0x00000080, + 0x806eff6e, 0x00000080, + 0xbf0a6f6e, 0xbf85fff0, + 0xbfc60000, 0xbf820011, + 0xee058076, 0x000c0001, + 0x00000000, 0xbfc00000, + 0xd8340000, 0x00000100, + 0x8076ff76, 0x00000100, + 0x82778077, 0xd5250000, + 0x0001ff00, 0x00000100, + 0x806eff6e, 0x00000100, + 0xbf0a6f6e, 0xbf85fff0, + 0xbfc60000, 0xbf0d9d72, + 0xbf840002, 0xbe804ec2, + 0xbfabfffe, 0x876eff72, + 0xa0000000, 0xbf06ff6e, + 0x20000000, 0xbf850031, + 0xbef60474, 0xb96f3b05, + 0x806f816f, 0x8f6f826f, + 0xbeee0380, 0xbefe04c1, + 0xbf0d9c72, 0xbf850015, + 0xbe806f6e, 0xee058076, + 0x000c0000, 0x00000000, + 0xee058076, 0x000c0001, + 0x00008000, 0xee058076, + 0x000c0002, 0x00010000, + 0xee058076, 0x000c0003, + 0x00018000, 0x8076ff76, + 0x00000200, 0x82778077, + 0x806e846e, 0xbf0a6f6e, + 0xbf85ffed, 0xbfc00000, + 0xbf820014, 0xbe806f6e, + 0xee058076, 0x000c0000, + 0x00000000, 0xee058076, + 0x000c0001, 0x00010000, + 0xee058076, 0x000c0002, + 0x00020000, 0xee058076, + 0x000c0003, 0x00030000, + 0x8076ff76, 0x00000400, + 0x82778077, 0x806e846e, + 0xbf0a6f6e, 0xbf85ffed, + 0xbfc00000, 0xbf0d9d72, + 0xbf840004, 0xbf0d9f72, + 0xbf850002, 0xbeee0380, + 0xbf820008, 0xb96e3b05, + 0x806e816e, 0x8f6e826e, + 0xbf0d9c72, 0xbf850002, + 0x8f6e876e, 0xbf820001, + 0x8f6e886e, 0x80766e74, + 0x82778075, 0xbeee03ff, + 0x000001a0, 0xf460403b, + 0xdc000000, 0xbfc70000, + 0xbefd03ff, 0x00680000, + 0x86801000, 0x86821002, + 0x80eea06e, 0xf460603b, + 0xdc000000, 0xbfc70000, + 0x80fdff7d, 0x00080000, + 0x86801000, 0x86821002, + 0x86841004, 0x86861006, + 0x80eec06e, 0xf460803b, + 0xdc000000, 0xbfc70000, + 0x80fdff7d, 0x00100000, + 0x86801000, 0x86821002, + 0x86841004, 0x86861006, + 0x86881008, 0x868a100a, + 0x868c100c, 0x868e100e, + 0xbf06807d, 0xbf84fff0, + 0xba80f801, 0x00000000, + 0xbf0d9d72, 0xbf840004, + 0xbf0d9f72, 0xbf850002, + 0xbeee0380, 0xbf820008, + 0xb96e3b05, 0x806e816e, + 0x8f6e826e, 0xbf0d9c72, + 0xbf850002, 0x8f6e876e, + 0xbf820001, 0x8f6e886e, + 0x806eff6e, 0x00000200, + 0x80766e74, 0x82778075, + 0xf4601bfb, 0xf8000000, + 0xf4601b3b, 0xf8000004, + 0xf4601b7b, 0xf8000008, + 0xf4601c3b, 0xf800000c, + 0xf4601c7b, 0xf8000010, + 0xf4601ebb, 0xf8000014, + 0xf4601efb, 0xf8000018, + 0xf4601e7b, 0xf800001c, + 0xf4601cfb, 0xf8000020, + 0xf4601bbb, 0xf8000024, + 0xbfc70000, 0xb9eef814, + 0xf4601bbb, 0xf8000028, + 0xbfc70000, 0xb9eef815, + 0xf4601bbb, 0xf800002c, + 0xbfc70000, 0xb9eef812, + 0xf4601bbb, 0xf8000030, + 0xbfc70000, 0xb9eef813, + 0xf4601bbb, 0xf8000040, + 0xbfc70000, 0xb9eef82c, + 0xf4601bbb, 0xf8000044, + 0xbfc70000, 0xb9eef82d, + 0xf4601bbb, 0xf8000048, + 0xbfc70000, 0xbf06816e, + 0xbf840003, 0xbefd0381, + 0xbefc4c8a, 0xbfc70000, + 0xb96ef802, 0xbf0c8b6e, + 0xbf850003, 0xbe804fc2, + 0xbfabfffe, 0xbf840001, + 0xbe804ec4, 0xbfabfffc, + 0xbf0d9e72, 0xbf84001c, + 0xf4601bbb, 0xf8000038, + 0xbfc70000, 0xbf0d9f6e, + 0xbf840017, 0x93eeff6e, + 0x00080016, 0x876e6e6e, + 0xbf840003, 0xbe804ec1, + 0x816ec16e, 0xbf82fffb, + 0xbef803ff, 0x00000080, + 0xbefd0381, 0xf4601bbb, + 0xf0000000, 0xbfc70000, + 0xbf0c9f6e, 0xbf850008, + 0x887d6e7d, 0xbe80517d, + 0x80788478, 0x877dff7d, + 0x0000007f, 0x807d817d, + 0xbf08907d, 0xbf84fff3, + 0xf4601bbb, 0xf800003c, + 0xbfc70000, 0xbf0d9f6e, + 0xbf84001d, 0xbf0d9e72, + 0xbf840002, 0xbf068180, + 0xbe804fc4, 0xbfabfffc, + 0xbf840017, 0x93eeff6e, + 0x00080016, 0x876e6e6e, + 0xbf840003, 0xbe804ec3, + 0x816ec16e, 0xbf82fffb, + 0xbef803ff, 0x000000c0, + 0xbefd03a1, 0xf4601bbb, + 0xf0000000, 0xbfc70000, + 0xbf0c9f6e, 0xbf850008, + 0x887d6e7d, 0xbe80517d, + 0x80788478, 0x877dff7d, + 0x0000007f, 0x807d817d, + 0xbf08a47d, 0xbf84fff3, + 0xbf0d9d72, 0xbf840040, + 0xf4601bbb, 0xf800004c, + 0xbfc70000, 0xbf06806e, + 0xbf850005, 0xbefd136e, + 0xbe80547d, 0xbfc70000, + 0xbeee1b7d, 0xbf82fff9, + 0xf4601bbb, 0xf8000050, + 0xbfc70000, 0xb9eef82e, + 0xf4601bbb, 0xf8000054, + 0xbfc70000, 0xbf0d9c6e, + 0xbf850003, 0xb9eef824, + 0x807c8080, 0xbf820002, + 0xb9eef824, 0xbf800000, + 0xf4601bbb, 0xf8000058, + 0xbfc70000, 0xbf0d9c6e, + 0xbf850003, 0xb9eef825, + 0x807c8080, 0xbf820002, + 0xb9eef825, 0xbf800000, + 0xf4601bbb, 0xf800005c, + 0xbfc70000, 0xbf0d9c6e, + 0xbf850003, 0xb9eef826, + 0x807c8080, 0xbf820002, + 0xb9eef826, 0xbf800000, + 0xf4601bbb, 0xf8000060, + 0xbfc70000, 0xbf0d9c6e, + 0xbf850003, 0xb9eef827, + 0x807c8080, 0xbf820002, + 0xb9eef827, 0xbf800000, + 0xf4601bbb, 0xf8000064, + 0xbfc70000, 0xbf0d9c6e, + 0xbf850003, 0xb9eef828, + 0x807c8080, 0xbf820002, + 0xb9eef828, 0xbf800000, + 0xbefd036f, 0xbefe0370, + 0xbeff0371, 0xb9fb2011, + 0x907b867b, 0xb9fb0191, + 0x907b827b, 0xb9fbba11, + 0xb9f3f801, 0xbf0d9d72, + 0xbf840004, 0xbf0d9f72, + 0xbf850002, 0xbeee0380, + 0xbf820008, 0xb96e3b05, + 0x806e816e, 0x8f6e826e, + 0xbf0d9c72, 0xbf850002, + 0x8f6e876e, 0xbf820001, + 0x8f6e886e, 0x806eff6e, + 0x000001c0, 0x806e746e, + 0x826f8075, 0xf4605c37, + 0xf8000010, 0xf4605d37, + 0xf8000020, 0xf4601e77, + 0xf8000034, 0xbfc70000, + 0x876dff6d, 0x0000ffff, + 0x87fe7e7e, 0x87ea6a6a, + 0xb9faf803, 0xb96ef802, + 0xbf0c8b6e, 0xbf850003, + 0xbe804fc2, 0xbfabfffe, + 0xbf840001, 0xbe804ec4, + 0xbfabfffc, 0x907a897a, + 0xb9fa0243, 0xbe80226c, + 0xbf9f0000, 0xbf9f0000, + 0xbf9f0000, 0xbf9f0000, + 0xbf9f0000, 0x00000000, +}; diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx13.asm b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx13.asm new file mode 100755 index 0000000000000..58908b4fa40a9 --- /dev/null +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx13.asm @@ -0,0 +1,1181 @@ +/* + * Copyright 2018 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* To compile this assembly code: + * + * gfx13: + * cpp -DASIC_FAMILY=CHIP_GFX13 cwsr_trap_handler_gfx13.asm -P -o gfx13.sp3 + * sp3 gfx13.sp3 -hex gfx13.hex + */ + +#define CHIP_GFX13 39 + +#define HAVE_XNACK 0 +#define HAVE_57BIT_ADDRESS 0 +#define WAVE32_ONLY 0 +#define NUM_NAMED_BARRIERS 0x10 +#define NUM_NAMED_CLUSTER_BARRIERS 0x4 +#define NUM_SEMAPHORES 0x5 +#define SINGLE_STEP_MISSED_WORKAROUND 1 //workaround for lost TRAP_AFTER_INST exception when SAVECTX raised +#define SEMA_DONE_RESTORE_WORKAROUND 1 + +#if HAVE_XNACK && !WAVE32_ONLY +# error +#endif + +#define ADDRESS_HI32_NUM_BITS ((HAVE_57BIT_ADDRESS ? 57 : 48) - 32) +#define ADDRESS_HI32_MASK ((1 << ADDRESS_HI32_NUM_BITS) - 1) + +var SQ_WAVE_STATE_PRIV_ALL_BARRIER_COMPLETE_MASK = 0x60000C +var SQ_WAVE_STATE_PRIV_SCC_SHIFT = 9 +var SQ_WAVE_STATE_PRIV_SYS_PRIO_MASK = 0xC00 +var SQ_WAVE_STATE_PRIV_HALT_MASK = 0x4000 +var SQ_WAVE_STATE_PRIV_POISON_ERR_MASK = 0x8000 +var SQ_WAVE_STATE_PRIV_POISON_ERR_SHIFT = 15 +var SQ_WAVE_STATUS_WAVE64_SHIFT = 29 +var SQ_WAVE_STATUS_WAVE64_SIZE = 1 +var SQ_WAVE_STATUS_NO_VGPRS_SHIFT = 24 +var SQ_WAVE_STATUS_IN_WG_SHIFT = 11 +var SQ_WAVE_STATE_PRIV_ALWAYS_CLEAR_MASK = SQ_WAVE_STATE_PRIV_SYS_PRIO_MASK|SQ_WAVE_STATE_PRIV_POISON_ERR_MASK +var S_RETURN_PC_HI_TRAP_ID_MASK = 0xF0000000 + +var SQ_WAVE_LDS_ALLOC_LDS_SIZE_SHIFT = 12 +var SQ_WAVE_LDS_ALLOC_LDS_SIZE_SIZE = 9 +var SQ_WAVE_GPR_ALLOC_VGPR_SIZE_SIZE = 8 +var SQ_WAVE_GPR_ALLOC_VGPR_SIZE_SHIFT = 12 +var SQ_WAVE_LDS_ALLOC_GRANULARITY = 10 + +var SQ_WAVE_EXCP_FLAG_PRIV_ADDR_WATCH_MASK = 0xF +var SQ_WAVE_EXCP_FLAG_PRIV_MEM_VIOL_MASK = 0x10 +var SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_SHIFT = 5 +var SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_MASK = 0x20 +var SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_MASK = 0x40 +var SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT = 6 +var SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_MASK = 0x80 +var SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_SHIFT = 7 +var SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_MASK = 0x100 +var SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_SHIFT = 8 +var SQ_WAVE_EXCP_FLAG_PRIV_WAVE_END_MASK = 0x200 +var SQ_WAVE_EXCP_FLAG_PRIV_TRAP_AFTER_INST_MASK = 0x800 +var SQ_WAVE_TRAP_CTRL_ADDR_WATCH_MASK = 0x80 +var SQ_WAVE_TRAP_CTRL_TRAP_AFTER_INST_MASK = 0x200 +var SQ_WAVE_TRAP_CTRL_ALU_CONSUME_NAN_SHIFT = 10 +var SQ_WAVE_EXCP_FLAG_USER_ALU_CONSUME_NAN_SHIFT= 7 + +var SQ_WAVE_EXCP_FLAG_PRIV_NON_MASKABLE_EXCP_MASK= SQ_WAVE_EXCP_FLAG_PRIV_MEM_VIOL_MASK |\ + SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_MASK |\ + SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_MASK |\ + SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_MASK |\ + SQ_WAVE_EXCP_FLAG_PRIV_WAVE_END_MASK |\ + SQ_WAVE_EXCP_FLAG_PRIV_TRAP_AFTER_INST_MASK +var SQ_WAVE_EXCP_FLAG_PRIV_RESTORE_PART_1_SIZE = SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_SHIFT +var SQ_WAVE_EXCP_FLAG_PRIV_RESTORE_PART_2_SHIFT = SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT +var SQ_WAVE_EXCP_FLAG_PRIV_RESTORE_PART_2_SIZE = SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_SHIFT - SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT +var SQ_WAVE_EXCP_FLAG_PRIV_RESTORE_PART_3_SHIFT = SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_SHIFT +var SQ_WAVE_EXCP_FLAG_PRIV_RESTORE_PART_3_SIZE = 32 - SQ_WAVE_EXCP_FLAG_PRIV_RESTORE_PART_3_SHIFT + +var BARRIER_STATE_SIGNAL_OFFSET = 22 +var BARRIER_STATE_SIGNAL_SIZE = 8 +var BARRIER_STATE_MEMBER_OFFSET = 12 +var BARRIER_STATE_MEMBER_SIZE = 8 +var BARRIER_STATE_VALID_OFFSET = 31 +var BARRIER_STATE_ID_MASK = 0x7F + +var NAMED_BARRIERS_SR_OFFSET_FROM_HWREG = 0x80 +var NAMED_CLUSTER_BARRIERS_SR_OFFSET_FROM_HWREG = (NAMED_BARRIERS_SR_OFFSET_FROM_HWREG + NUM_NAMED_BARRIERS * 0x4) +var S_BARRIER_INIT_MEMBERCNT_MASK = 0x7F0000 +var S_BARRIER_INIT_MEMBERCNT_SHIFT = 0x10 + +var SQ_WAVE_XNACK_STATE_PRIV_FIRST_REPLAY_SHIFT = 18 +var SQ_WAVE_XNACK_STATE_PRIV_FIRST_REPLAY_SIZE = 1 +var SQ_WAVE_XNACK_STATE_PRIV_REPLAY_W64H_SHIFT = 16 +var SQ_WAVE_XNACK_STATE_PRIV_REPLAY_W64H_SIZE = 1 +var SQ_WAVE_XNACK_STATE_PRIV_FXPTR_SHIFT = 0 +var SQ_WAVE_XNACK_STATE_PRIV_FXPTR_SIZE = 7 + +var SQ_WAVE_GROUP_INFO_IN_WAVEGROUP_SHIFT = 9 + +var SQ_WAVE_IB_STS_SWC_CNT_SHIFT = 12 +var SQ_WAVE_IB_STS_SWC_CNT_SIZE = 2 + +var SQ_WAVE_IB_STS2_NO_IC_HASH_SHIFT = 24 + +var SQ_WAVE_SEMA_STATE_DONE_SHIFT = 28 + +var TTMP11_DEBUG_TRAP_ENABLED_SHIFT = 23 +var TTMP11_DEBUG_TRAP_ENABLED_MASK = 0x800000 +var TTMP11_FIRST_REPLAY_SHIFT = 22 +var TTMP11_FIRST_REPLAY_MASK = 0x400000 +var TTMP11_REPLAY_W64H_SHIFT = 21 +var TTMP11_REPLAY_W64H_MASK = 0x200000 +var TTMP11_FXPTR_SHIFT = 14 +var TTMP11_FXPTR_MASK = 0x1FC000 + +var S_EXEC_LAST_FIRST_WAVE_SHIFT = 26 +var S_EXEC_LAST_FIRST_WAVE_SIZE = 2 + +var S_FLAGS_LAST_WAVE_IN_WAVEGROUP_SHIFT = 31 +var S_FLAGS_LAST_WAVE_IN_WAVEGROUP_MASK = (1 << S_FLAGS_LAST_WAVE_IN_WAVEGROUP_SHIFT) +var S_FLAGS_FIRST_WAVE_IN_WORKGROUP_SHIFT = 30 +var S_FLAGS_IN_WAVEGROUP_SHIFT = 29 +var S_FLAGS_IN_WAVEGROUP_MASK = (1 << S_FLAGS_IN_WAVEGROUP_SHIFT) +#if ! WAVE32_ONLY +var S_FLAGS_WAVE64_SHIFT = 28 +#endif + +var s_return_pc_lo = ttmp0 +var s_return_pc_hi = ttmp1 + +var s_save_flags = s_return_pc_hi +var s_save_base_addr_lo = ttmp2 +var s_save_base_addr_hi = ttmp3 +var s_save_addr_lo = ttmp10 +var s_save_addr_hi = ttmp11 +var s_save_state_priv = ttmp12 +var s_save_tmp = ttmp14 +var s_save_ttmps_lo = ttmp14 +var s_save_exec_lo = ttmp14 +var s_save_excp_flag_priv = ttmp15 +var s_save_alloc_size = ttmp15 +var s_save_ttmps_hi = ttmp15 +var s_save_exec_hi = ttmp15 +var s_save_xnack_mask = exec_hi + +var s_restore_tmp = ttmp2 +var s_restore_ttmps_lo = ttmp2 +var s_restore_alloc_size = ttmp3 +var s_restore_ttmps_hi = ttmp3 +var s_restore_m0 = ttmp3 +var s_restore_exec_lo = ttmp4 +var s_restore_exec_hi = ttmp5 +var s_restore_flags = ttmp6 +var s_restore_mode = ttmp7 +var s_restore_base_addr_lo = ttmp8 +var s_restore_base_addr_hi = ttmp9 +var s_restore_addr_lo = ttmp10 +var s_restore_addr_hi = ttmp11 +var s_restore_mem_offset = ttmp12 +var s_restore_xnack_mask = ttmp13 +var s_restore_state_priv = ttmp14 +var s_restore_excp_flag_priv = ttmp15 + +var TTMP_SR_OFFSET_FROM_HWREG = -0x40 + +shader main + asic(DEFAULT) + type(CS) + wave_size(32) + + s_branch L_SKIP_RESTORE //NOT restore. might be a regular trap or save + +L_JUMP_TO_RESTORE: + s_branch L_RESTORE + +L_SKIP_RESTORE: + s_getreg_b32 s_save_state_priv, hwreg(HW_REG_WAVE_STATE_PRIV) //save STATUS since we will change SCC + + // Clear SPI_PRIO: do not save with elevated priority. + // Clear ECC_ERR: prevents SQC store and triggers FATAL_HALT if setreg'd. + s_andn2_b32 s_save_state_priv, s_save_state_priv, SQ_WAVE_STATE_PRIV_ALWAYS_CLEAR_MASK + + s_getreg_b32 s_save_excp_flag_priv, hwreg(HW_REG_WAVE_EXCP_FLAG_PRIV) + + s_and_b32 ttmp2, s_save_state_priv, SQ_WAVE_STATE_PRIV_HALT_MASK + s_cbranch_scc0 L_NOT_HALTED + +L_HALTED: + // Host trap may occur while wave is halted. + s_and_b32 ttmp2, s_save_excp_flag_priv, SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_MASK + s_cbranch_scc1 L_FETCH_2ND_TRAP + +L_CHECK_SAVE: + s_and_b32 ttmp2, s_save_excp_flag_priv, SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_MASK + s_cbranch_scc1 L_SAVE + + // Wave is halted but neither host trap nor SAVECTX is raised. + // Caused by instruction fetch memory violation. + // Spin wait until context saved to prevent interrupt storm. + s_sleep 0x10 + s_getreg_b32 s_save_excp_flag_priv, hwreg(HW_REG_WAVE_EXCP_FLAG_PRIV) + s_branch L_CHECK_SAVE + +L_NOT_HALTED: + // Let second-level handle non-SAVECTX exception or trap. + // Any concurrent SAVECTX will be handled upon re-entry once halted. + + // Check non-maskable exceptions. memory_violation, illegal_instruction + // and xnack_error exceptions always cause the wave to enter the trap + // handler. + s_and_b32 ttmp2, s_save_excp_flag_priv, SQ_WAVE_EXCP_FLAG_PRIV_NON_MASKABLE_EXCP_MASK + s_cbranch_scc1 L_FETCH_2ND_TRAP + + // Check for maskable exceptions in trapsts.excp and trapsts.excp_hi. + // Maskable exceptions only cause the wave to enter the trap handler if + // their respective bit in mode.excp_en is set. + + // Align bits from EXCP_FLAG_USER/EXCP_FLAG_PRIV with TRAP_CTRL. + s_getreg_b32 ttmp2, hwreg(HW_REG_WAVE_EXCP_FLAG_USER) + s_bitcmp1_b32 ttmp2, SQ_WAVE_EXCP_FLAG_USER_ALU_CONSUME_NAN_SHIFT + s_cbranch_scc0 L_NOT_ALU_CONSUME_NAN + s_bitset0_b32 ttmp2, SQ_WAVE_EXCP_FLAG_USER_ALU_CONSUME_NAN_SHIFT + s_bitset1_b32 ttmp2, SQ_WAVE_TRAP_CTRL_ALU_CONSUME_NAN_SHIFT + +L_NOT_ALU_CONSUME_NAN: + s_and_b32 ttmp3, s_save_excp_flag_priv, SQ_WAVE_EXCP_FLAG_PRIV_ADDR_WATCH_MASK + s_cbranch_scc0 L_NOT_ADDR_WATCH + s_or_b32 ttmp2, ttmp2, SQ_WAVE_TRAP_CTRL_ADDR_WATCH_MASK + +L_NOT_ADDR_WATCH: + s_getreg_b32 ttmp3, hwreg(HW_REG_WAVE_TRAP_CTRL) + s_and_b32 ttmp2, ttmp3, ttmp2 + s_cbranch_scc1 L_FETCH_2ND_TRAP + +L_CHECK_TRAP_ID: + // Check trap_id != 0 + s_and_b32 ttmp2, s_return_pc_hi, S_RETURN_PC_HI_TRAP_ID_MASK + s_cbranch_scc1 L_FETCH_2ND_TRAP + +#if SINGLE_STEP_MISSED_WORKAROUND + // Prioritize single step exception over context save. + // Second-level trap will halt wave and RFE, re-entering for SAVECTX. + // WAVE_TRAP_CTRL is already in ttmp3. + s_and_b32 ttmp3, ttmp3, SQ_WAVE_TRAP_CTRL_TRAP_AFTER_INST_MASK + s_cbranch_scc1 L_FETCH_2ND_TRAP +#endif + + s_and_b32 ttmp2, s_save_excp_flag_priv, SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_MASK + s_cbranch_scc1 L_SAVE + +L_FETCH_2ND_TRAP: +#if HAVE_XNACK + save_and_clear_xnack_state_priv(ttmp14) +#endif + + // Read second-level TBA/TMA from first-level TMA and jump if available. + // ttmp[2:5] and ttmp12 can be used (others hold SPI-initialized debug data) + // ttmp12 holds SQ_WAVE_STATUS + s_sendmsg_rtn_b64 [ttmp14, ttmp15], sendmsg(MSG_RTN_GET_TMA) + s_wait_kmcnt 0 + s_lshl_b64 [ttmp14, ttmp15], [ttmp14, ttmp15], 0x8 + + s_bitcmp1_b32 ttmp15, (ADDRESS_HI32_NUM_BITS - 1) + s_cbranch_scc0 L_NO_SIGN_EXTEND_TMA + s_or_b32 ttmp15, ttmp15, ~ADDRESS_HI32_MASK +L_NO_SIGN_EXTEND_TMA: + + s_load_dword ttmp2, [ttmp14, ttmp15], 0x10 scope:SCOPE_SYS // debug trap enabled flag + s_wait_kmcnt 0 + s_lshl_b32 ttmp2, ttmp2, TTMP11_DEBUG_TRAP_ENABLED_SHIFT + s_andn2_b32 ttmp11, ttmp11, TTMP11_DEBUG_TRAP_ENABLED_MASK + s_or_b32 ttmp11, ttmp11, ttmp2 + + s_load_dwordx2 [ttmp2, ttmp3], [ttmp14, ttmp15], 0x0 scope:SCOPE_SYS // second-level TBA + s_wait_kmcnt 0 + s_load_dwordx2 [ttmp14, ttmp15], [ttmp14, ttmp15], 0x8 scope:SCOPE_SYS // second-level TMA + s_wait_kmcnt 0 + + s_and_b64 [ttmp2, ttmp3], [ttmp2, ttmp3], [ttmp2, ttmp3] + s_cbranch_scc0 L_NO_NEXT_TRAP // second-level trap handler not been set + s_setpc_b64 [ttmp2, ttmp3] // jump to second-level trap handler + +L_NO_NEXT_TRAP: + // If not caused by trap then halt wave to prevent re-entry. + s_and_b32 ttmp2, s_return_pc_hi, S_RETURN_PC_HI_TRAP_ID_MASK + s_cbranch_scc1 L_TRAP_CASE + + // Host trap will not cause trap re-entry. + s_getreg_b32 ttmp2, hwreg(HW_REG_WAVE_EXCP_FLAG_PRIV) + s_and_b32 ttmp2, ttmp2, SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_MASK + s_cbranch_scc1 L_EXIT_TRAP + s_or_b32 s_save_state_priv, s_save_state_priv, SQ_WAVE_STATE_PRIV_HALT_MASK + + // If the PC points to S_ENDPGM then context save will fail if STATE_PRIV.HALT is set. + // Rewind the PC to prevent this from occurring. + s_sub_u32 ttmp0, ttmp0, 0x8 + s_subb_u32 ttmp1, ttmp1, 0x0 + + s_branch L_EXIT_TRAP + +L_TRAP_CASE: + // Advance past trap instruction to prevent re-entry. + s_add_u32 ttmp0, ttmp0, 0x4 + s_addc_u32 ttmp1, ttmp1, 0x0 + +L_EXIT_TRAP: + s_and_b32 ttmp1, ttmp1, ADDRESS_HI32_MASK + + // Restore SQ_WAVE_STATUS. + s_and_b64 exec, exec, exec // Restore STATUS.EXECZ, not writable by s_setreg_b32 + s_and_b64 vcc, vcc, vcc // Restore STATUS.VCCZ, not writable by s_setreg_b32 + + // STATE_PRIV.*BARRIER_COMPLETE may have changed since we read it. + // Only restore fields which the trap handler changes. + s_lshr_b32 s_save_state_priv, s_save_state_priv, SQ_WAVE_STATE_PRIV_SCC_SHIFT + s_setreg_b32 hwreg(HW_REG_WAVE_STATE_PRIV, SQ_WAVE_STATE_PRIV_SCC_SHIFT, \ + SQ_WAVE_STATE_PRIV_POISON_ERR_SHIFT - SQ_WAVE_STATE_PRIV_SCC_SHIFT + 1), s_save_state_priv + + s_rfe_b64 [ttmp0, ttmp1] + +L_SAVE: + s_setreg_imm32_b32 hwreg(HW_REG_WAVE_EXCP_FLAG_PRIV, SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_SHIFT, 1), 0 + + // Get save address { 4’b0, lastWaveOfWavegroup, firstWaveOfWorkgroup, 1’b0, memAddr[56:0] } + s_mov_b64 [s_save_exec_lo, s_save_exec_hi], exec + s_sendmsg_rtn_b64 exec, sendmsg(MSG_RTN_SAVE_WAVE) + s_wait_kmcnt 0 + s_mov_b64 [s_save_base_addr_lo, s_save_base_addr_hi], exec + s_mov_b64 exec, [s_save_exec_lo, s_save_exec_hi] + + // Save last_wave_in_wavegroup / first_wave_in_workgroup flags so we can clear high bits of save address. + s_bfe_u32 s_save_tmp, s_save_base_addr_hi, (S_EXEC_LAST_FIRST_WAVE_SHIFT | (S_EXEC_LAST_FIRST_WAVE_SIZE << 0x10)) + s_and_b32 s_save_base_addr_hi, s_save_base_addr_hi, ADDRESS_HI32_MASK + s_and_b32 s_save_flags, s_save_flags, ADDRESS_HI32_MASK + s_lshl_b32 s_save_tmp, s_save_tmp, S_FLAGS_FIRST_WAVE_IN_WORKGROUP_SHIFT + s_or_b32 s_save_flags, s_save_flags, s_save_tmp + + // Save in_wavegroup and wave64 flags for later use. + s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_GROUP_INFO, SQ_WAVE_GROUP_INFO_IN_WAVEGROUP_SHIFT, 1) + s_lshl_b32 s_save_tmp, s_save_tmp, S_FLAGS_IN_WAVEGROUP_SHIFT + s_or_b32 s_save_flags, s_save_flags, s_save_tmp + +#if ! WAVE32_ONLY + s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_STATUS, SQ_WAVE_STATUS_WAVE64_SHIFT, 1) + s_lshl_b32 s_save_tmp, s_save_tmp, S_FLAGS_WAVE64_SHIFT + s_or_b32 s_save_flags, s_save_flags, s_save_tmp +#endif + +#if HAVE_XNACK + save_and_clear_xnack_state_priv(s_save_tmp) + s_getreg_b32 s_save_xnack_mask, hwreg(HW_REG_WAVE_XNACK_MASK) + s_setreg_imm32_b32 hwreg(HW_REG_WAVE_XNACK_MASK), 0 +#endif + + // Save trap temporaries 4-11, 13 initialized by SPI debug dispatch logic + // ttmp SR memory offset: size(VGPR)+size(SGPR)-0x40 + get_vgpr_size_bytes(s_save_ttmps_lo, s_save_flags) + s_add_u32 s_save_ttmps_lo, s_save_ttmps_lo, (get_sgpr_size_bytes() + TTMP_SR_OFFSET_FROM_HWREG) + s_add_u32 s_save_ttmps_lo, s_save_ttmps_lo, s_save_base_addr_lo + s_addc_u32 s_save_ttmps_hi, s_save_base_addr_hi, 0 + + global_store_sgpr_b32 ttmp4, [s_save_ttmps_lo, s_save_ttmps_hi] scope:SCOPE_SYS offset:0x10 + global_store_sgpr_b32 ttmp5, [s_save_ttmps_lo, s_save_ttmps_hi] scope:SCOPE_SYS offset:0x14 + global_store_sgpr_b32 ttmp6, [s_save_ttmps_lo, s_save_ttmps_hi] scope:SCOPE_SYS offset:0x18 + global_store_sgpr_b32 ttmp7, [s_save_ttmps_lo, s_save_ttmps_hi] scope:SCOPE_SYS offset:0x1C + global_store_sgpr_b32 ttmp8, [s_save_ttmps_lo, s_save_ttmps_hi] scope:SCOPE_SYS offset:0x20 + global_store_sgpr_b32 ttmp9, [s_save_ttmps_lo, s_save_ttmps_hi] scope:SCOPE_SYS offset:0x24 + global_store_sgpr_b32 ttmp10, [s_save_ttmps_lo, s_save_ttmps_hi] scope:SCOPE_SYS offset:0x28 + global_store_sgpr_b32 ttmp11, [s_save_ttmps_lo, s_save_ttmps_hi] scope:SCOPE_SYS offset:0x2C + global_store_sgpr_b32 ttmp13, [s_save_ttmps_lo, s_save_ttmps_hi] scope:SCOPE_SYS offset:0x34 + +L_SAVE_HWREG: + // HWREG SR memory offset : size(VGPR)+size(SGPR) + get_vgpr_size_bytes(s_save_tmp, s_save_flags) + s_add_u32 s_save_tmp, s_save_tmp, get_sgpr_size_bytes() + s_add_u32 s_save_addr_lo, s_save_base_addr_lo, s_save_tmp + s_addc_u32 s_save_addr_hi, s_save_base_addr_hi, 0 + + // Ensure no further changes to barrier or LDS state. + // STATE_PRIV.*BARRIER_COMPLETE may change up to this point. + wait_trap_barriers(s_save_tmp) + + // Re-read final state of *BARRIER_COMPLETE fields for save. + s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_STATE_PRIV) + s_and_b32 s_save_tmp, s_save_tmp, SQ_WAVE_STATE_PRIV_ALL_BARRIER_COMPLETE_MASK + s_andn2_b32 s_save_state_priv, s_save_state_priv, SQ_WAVE_STATE_PRIV_ALL_BARRIER_COMPLETE_MASK + s_or_b32 s_save_state_priv, s_save_state_priv, s_save_tmp + + s_mov_b32 s_save_tmp, m0 + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0x0 + + global_store_sgpr_b32 s_return_pc_lo, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0x4 + + s_and_b32 s_save_tmp, s_return_pc_hi, ADDRESS_HI32_MASK + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0x8 + + s_mov_b32 s_save_tmp, exec_lo + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0xC + +#if WAVE32_ONLY + s_mov_b32 s_save_tmp, 0 +#else + s_mov_b32 s_save_tmp, exec_hi +#endif + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0x10 + + global_store_sgpr_b32 s_save_state_priv, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0x14 + + s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_EXCP_FLAG_PRIV) + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0x18 + +#if HAVE_XNACK + s_mov_b32 s_save_tmp, s_save_xnack_mask +#else + s_mov_b32 s_save_tmp, 0 +#endif + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0x1C + + s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_MODE) + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0x20 + + s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_SCRATCH_BASE_LO) + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0x24 + + s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_SCRATCH_BASE_HI) + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0x28 + + s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_EXCP_FLAG_USER) + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0x2C + + s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_TRAP_CTRL) + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0x30 + + s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_STATUS) + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0x34 + + s_get_barrier_state s_save_tmp, -1 + s_wait_kmcnt 0 + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0x38 + + s_sendmsg_rtn_b32 s_save_tmp, sendmsg(MSG_RTN_GET_CLUSTER_BARRIER_STATE) + s_wait_kmcnt 0 + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0x3C + + s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_GPR_MSB_IDX0) + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0x40 + + s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_GPR_IDX123) + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0x44 + + s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_IB_STS2, SQ_WAVE_IB_STS2_NO_IC_HASH_SHIFT, 1) + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0x48 + + // Locks and semaphores are only supported in wavegroups. + s_bitcmp1_b32 s_save_flags, S_FLAGS_IN_WAVEGROUP_SHIFT + s_cbranch_scc0 L_SAVE_SKIP_LOCKS_SEMAPHORES + + s_get_lock_state s_save_tmp, 0 + s_wait_kmcnt 0 + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0x4C + + s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_SEMA_MODE) + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:0x50 + +for var sema_idx = 0; sema_idx < NUM_SEMAPHORES; sema_idx ++ + s_sendmsg_rtn_b32 s_save_tmp, sendmsg(MSG_RTN_GET_SEMA1 + sema_idx) + s_wait_kmcnt 0 + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:(0x54 + sema_idx * 4) +end + +L_SAVE_SKIP_LOCKS_SEMAPHORES: + for var bar_idx = 0; bar_idx < NUM_NAMED_BARRIERS; bar_idx ++ + s_get_barrier_state s_save_tmp, (bar_idx + 1) + s_wait_kmcnt 0 + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:(NAMED_BARRIERS_SR_OFFSET_FROM_HWREG + bar_idx * 4) + end + + for var bar_idx = 0; bar_idx < NUM_NAMED_CLUSTER_BARRIERS; bar_idx ++ + s_get_barrier_state s_save_tmp, (bar_idx + 0x21) + s_wait_kmcnt 0 + global_store_sgpr_b32 s_save_tmp, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:(NAMED_CLUSTER_BARRIERS_SR_OFFSET_FROM_HWREG + bar_idx * 4) + end + +L_SAVE_SGPRS: + // SGPR SR memory offset : size(VGPR) + get_vgpr_size_bytes(s_save_tmp, s_save_flags) + s_add_u32 s_save_addr_lo, s_save_base_addr_lo, s_save_tmp + s_addc_u32 s_save_addr_hi, s_save_base_addr_hi, 0 + + s_mov_b32 m0, 0 //SGPR initial index value =0 + + // s[0:15], s[16:31], ... s[80:95] +L_SAVE_SGPR_LOOP: +for var sgpr_idx = 0; sgpr_idx < 0x10; sgpr_idx += 2 + s_mov_indexed_b64 s[sgpr_idx], s[sgpr_idx], { src_idx_en: 1, src_idx: MOV_INDEXED_M0 } //s[N] = s[N+m0], s[N+1] = s[N+1+m0] +end + +for var sgpr_idx = 0; sgpr_idx < 0x10; sgpr_idx ++ + global_store_sgpr_b32 s[sgpr_idx], [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:(sgpr_idx * 4) +end + + s_add_u32 s_save_addr_lo, s_save_addr_lo, 0x40 + s_addc_u32 s_save_addr_hi, s_save_addr_hi, 0 + s_add_u32 m0, m0, 0x10 //next sgpr index + s_cmp_lt_u32 m0, 0x60 //scc = (m0 < first 96 SGPR) ? 1 : 0 + s_cbranch_scc1 L_SAVE_SGPR_LOOP //first 96 SGPR save is complete? + + // s[96:107] +for var sgpr_idx = 0; sgpr_idx < 0xC; sgpr_idx += 2 + s_mov_indexed_b64 s[sgpr_idx], s[sgpr_idx], { src_idx_en: 1, src_idx: MOV_INDEXED_M0 } //s[N] = s[N+m0], s[N+1] = s[N+1+m0] +end + +for var sgpr_idx = 0; sgpr_idx < 0xC; sgpr_idx ++ + global_store_sgpr_b32 s[sgpr_idx], [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:(sgpr_idx * 4) +end + + // If VGPRs have been deallocated then there is no more state to save. + s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_STATUS) + s_bitcmp1_b32 s_save_tmp, SQ_WAVE_STATUS_NO_VGPRS_SHIFT + s_cbranch_scc1 L_SAVE_DONE + + // In a wavegroup only the last wave saves VGPRs. + s_and_b32 s_save_tmp, s_save_flags, (S_FLAGS_IN_WAVEGROUP_MASK | S_FLAGS_LAST_WAVE_IN_WAVEGROUP_MASK) + s_cmp_eq_u32 s_save_tmp, S_FLAGS_IN_WAVEGROUP_MASK + s_cbranch_scc1 L_SAVE_LDS + +L_SAVE_VGPRS: + // VGPR SR memory offset: 0 + s_mov_b64 [s_save_addr_lo, s_save_addr_hi], [s_save_base_addr_lo, s_save_base_addr_hi] + + get_vgpr_num(s_save_alloc_size) + s_mov_b32 s_save_tmp, 0 + s_mov_b64 exec, 0xFFFFFFFFFFFFFFFF + s_set_vgpr_frames 0 + +#if ! WAVE32_ONLY + s_bitcmp1_b32 s_save_flags, S_FLAGS_WAVE64_SHIFT + s_cbranch_scc1 L_SAVE_VGPRS_WAVE64 +#endif + + save_vgprs(0x80) + +#if ! WAVE32_ONLY + s_branch L_SAVE_LDS + +L_SAVE_VGPRS_WAVE64: + save_vgprs(0x100) +#endif + +L_SAVE_LDS: + // If no LDS is allocated then skip save. + s_getreg_b32 s_save_alloc_size, hwreg(HW_REG_WAVE_LDS_ALLOC, SQ_WAVE_LDS_ALLOC_LDS_SIZE_SHIFT, SQ_WAVE_LDS_ALLOC_LDS_SIZE_SIZE) + s_lshl_b32 s_save_alloc_size, s_save_alloc_size, SQ_WAVE_LDS_ALLOC_GRANULARITY + s_cbranch_scc0 L_SAVE_DONE + + // Wavegroups wait for a barrier to ensure shared VGPRs have been saved. + s_bitcmp1_b32 s_save_flags, S_FLAGS_IN_WAVEGROUP_SHIFT + s_cbranch_scc0 L_SAVE_SKIP_WAVEGROUP_VGPR_BARRIER + s_barrier_signal -2 + s_barrier_wait -2 + +L_SAVE_SKIP_WAVEGROUP_VGPR_BARRIER: + // Only the first wave in a group saves LDS. + s_bitcmp1_b32 s_save_flags, S_FLAGS_FIRST_WAVE_IN_WORKGROUP_SHIFT + s_cbranch_scc0 L_SAVE_DONE + + // LDS at offset: size(VGPR)+SIZE(SGPR)+SIZE(HWREG) + get_vgpr_size_bytes(s_save_tmp, s_save_flags) + s_add_u32 s_save_tmp, s_save_tmp, (get_sgpr_size_bytes() + get_hwreg_size_bytes()) + s_add_u32 s_save_addr_lo, s_save_base_addr_lo, s_save_tmp + s_addc_u32 s_save_addr_hi, s_save_base_addr_hi, 0 + + s_mov_b64 exec, 0xFFFFFFFFFFFFFFFF + s_mov_b32 s_save_tmp, 0 + s_set_vgpr_frames 0 + s_set_gpr_idx_u32 dst_idx0, 0 + + // v0 = [0x0, 0x4, 0x8, 0xC, ... 0x7C (wave32) or 0xFC (wave64)] + v_mbcnt_lo_u32_b32 v0, -1, 0 +#if ! WAVE32_ONLY + v_mbcnt_hi_u32_b32 v0, -1, v0 +#endif + v_lshlrev_b32 v0, 2, v0 + +#if ! WAVE32_ONLY + s_bitcmp1_b32 s_save_flags, S_FLAGS_WAVE64_SHIFT + s_cbranch_scc1 L_SAVE_LDS_WAVE64 +#endif + + save_lds(0x80) + +#if ! WAVE32_ONLY + s_branch L_SAVE_DONE + +L_SAVE_LDS_WAVE64: + save_lds(0x100) +#endif + +L_SAVE_DONE: + // Make sure that no wave of the group/cluster can exit the trap handler + // before the group/cluster barrier state is saved. + wait_trap_barriers(s_save_tmp) + + s_endpgm_saved + +L_RESTORE: + // Get restore address { 4’b0, lastWaveOfWavegroup, firstWaveOfWorkgroup, 1’b0, memAddr[56:0] } + s_mov_b64 [s_restore_base_addr_lo, s_restore_base_addr_hi], exec + + // Save last_wave_in_wavegroup / first_wave_in_workgroup flags so we can clear high bits of restore address. + s_bfe_u32 s_restore_tmp, s_restore_base_addr_hi, (S_EXEC_LAST_FIRST_WAVE_SHIFT | (S_EXEC_LAST_FIRST_WAVE_SIZE << 0x10)) + s_and_b32 s_restore_base_addr_hi, s_restore_base_addr_hi, ADDRESS_HI32_MASK + s_lshl_b32 s_restore_flags, s_restore_tmp, S_FLAGS_FIRST_WAVE_IN_WORKGROUP_SHIFT + + // Save in_wavegroup and wave64 flags for later use. + s_getreg_b32 s_restore_tmp, hwreg(HW_REG_WAVE_GROUP_INFO, SQ_WAVE_GROUP_INFO_IN_WAVEGROUP_SHIFT, 1) + s_lshl_b32 s_restore_tmp, s_restore_tmp, S_FLAGS_IN_WAVEGROUP_SHIFT + s_or_b32 s_restore_flags, s_restore_flags, s_restore_tmp + +#if ! WAVE32_ONLY + s_getreg_b32 s_restore_tmp, hwreg(HW_REG_WAVE_STATUS, SQ_WAVE_STATUS_WAVE64_SHIFT, 1) + s_lshl_b32 s_restore_tmp, s_restore_tmp, S_FLAGS_WAVE64_SHIFT + s_or_b32 s_restore_flags, s_restore_flags, s_restore_tmp +#endif + + // HWREG SR memory offset : size(VGPR)+size(SGPR) + get_vgpr_size_bytes(s_restore_tmp, s_restore_flags) + s_add_u32 s_restore_tmp, s_restore_tmp, get_sgpr_size_bytes() + s_add_u32 s_restore_addr_lo, s_restore_base_addr_lo, s_restore_tmp + s_addc_u32 s_restore_addr_hi, s_restore_base_addr_hi, 0 + + // Deallocate VGPRs if needed and skip LDS/VGPR restore. + s_load_b32 s_restore_tmp, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x34 + s_wait_kmcnt 0 + s_bitcmp1_b32 s_restore_tmp, SQ_WAVE_STATUS_NO_VGPRS_SHIFT + s_cbranch_scc0 L_RESTORE_LDS + s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) + s_branch L_RESTORE_SGPRS + +L_RESTORE_LDS: + // If no LDS is allocated then skip restore. + s_getreg_b32 s_restore_alloc_size, hwreg(HW_REG_WAVE_LDS_ALLOC, SQ_WAVE_LDS_ALLOC_LDS_SIZE_SHIFT, SQ_WAVE_LDS_ALLOC_LDS_SIZE_SIZE) + s_lshl_b32 s_restore_alloc_size, s_restore_alloc_size, SQ_WAVE_LDS_ALLOC_GRANULARITY + s_cbranch_scc0 L_RESTORE_SKIP_WAVEGROUP_VGPR_BARRIER + + // Only the first wave in a group restores LDS. + s_bitcmp1_b32 s_restore_flags, S_FLAGS_FIRST_WAVE_IN_WORKGROUP_SHIFT + s_cbranch_scc0 L_RESTORE_VGPRS + + // LDS at offset: size(VGPR)+SIZE(SGPR)+SIZE(HWREG) + get_vgpr_size_bytes(s_restore_tmp, s_restore_flags) + s_add_u32 s_restore_tmp, s_restore_tmp, (get_sgpr_size_bytes() + get_hwreg_size_bytes()) + s_add_u32 s_restore_addr_lo, s_restore_base_addr_lo, s_restore_tmp + s_addc_u32 s_restore_addr_hi, s_restore_base_addr_hi, 0 + + s_mov_b64 exec, 0xFFFFFFFFFFFFFFFF + s_mov_b32 s_restore_tmp, 0 + + // v0 = [0x0, 0x4, 0x8, 0xC, ... 0x7C (wave32) or 0xFC (wave64)] + v_mbcnt_lo_u32_b32 v0, -1, 0 +#if ! WAVE32_ONLY + v_mbcnt_hi_u32_b32 v0, -1, v0 +#endif + v_lshlrev_b32 v0, 2, v0 + +#if ! WAVE32_ONLY + s_bitcmp1_b32 s_restore_flags, S_FLAGS_WAVE64_SHIFT + s_cbranch_scc1 L_RESTORE_LDS_WAVE64 +#endif + + restore_lds(0x80) + +#if ! WAVE32_ONLY + s_branch L_RESTORE_VGPRS + +L_RESTORE_LDS_WAVE64: + restore_lds(0x100) +#endif + +L_RESTORE_VGPRS: + // Wavegroups wait for a barrier to ensure shared VGPRs are no longer in use. + s_bitcmp1_b32 s_restore_flags, S_FLAGS_IN_WAVEGROUP_SHIFT + s_cbranch_scc0 L_RESTORE_SKIP_WAVEGROUP_VGPR_BARRIER + s_barrier_signal -2 + s_barrier_wait -2 + +L_RESTORE_SKIP_WAVEGROUP_VGPR_BARRIER: + // In a wavegroup only the last wave restores VGPRs. + s_and_b32 s_restore_tmp, s_restore_flags, (S_FLAGS_IN_WAVEGROUP_MASK | S_FLAGS_LAST_WAVE_IN_WAVEGROUP_MASK) + s_cmp_eq_u32 s_restore_tmp, S_FLAGS_IN_WAVEGROUP_MASK + s_cbranch_scc1 L_RESTORE_SGPRS + + // VGPR SR memory offset : 0 + s_mov_b64 [s_restore_addr_lo, s_restore_addr_hi], [s_restore_base_addr_lo, s_restore_base_addr_hi] + + get_vgpr_num(s_restore_alloc_size) + s_mov_b32 s_restore_tmp, 0 + s_mov_b64 exec, 0xFFFFFFFFFFFFFFFF + +#if ! WAVE32_ONLY + s_bitcmp1_b32 s_restore_flags, S_FLAGS_WAVE64_SHIFT + s_cbranch_scc1 L_RESTORE_VGPRS_WAVE64 +#endif + + restore_vgprs(0x80) + +#if ! WAVE32_ONLY + s_branch L_RESTORE_SGPRS + +L_RESTORE_VGPRS_WAVE64: + restore_vgprs(0x100) +#endif + +L_RESTORE_SGPRS: + // SGPR SR memory offset : size(VGPR) + get_vgpr_size_bytes(s_restore_tmp, s_restore_flags) + s_add_u32 s_restore_addr_lo, s_restore_base_addr_lo, s_restore_tmp + s_addc_u32 s_restore_addr_hi, s_restore_base_addr_hi, 0 + + // s[104:107] + s_mov_b32 s_restore_tmp, (0x68 * 4) + s_load_b128 s0, [s_restore_addr_lo, s_restore_addr_hi], s_restore_tmp scope:SCOPE_SYS + s_wait_kmcnt 0 + + s_mov_b32 m0, (0x68 << 0x10) +for var sgpr_idx = 0; sgpr_idx < 4; sgpr_idx += 2 + s_mov_indexed_b64 s[sgpr_idx], s[sgpr_idx], { dst_idx_en: 1, dst_idx: MOV_INDEXED_M0 } //s[N+m0] = s[N], s[N+1+m0] = s[N+1] +end + + // s[96:103] + s_sub_u32 s_restore_tmp, s_restore_tmp, 0x20 + s_load_b256 s0, [s_restore_addr_lo, s_restore_addr_hi], s_restore_tmp scope:SCOPE_SYS + s_wait_kmcnt 0 + + s_sub_u32 m0, m0, (0x8 << 0x10) +for var sgpr_idx = 0; sgpr_idx < 8; sgpr_idx += 2 + s_mov_indexed_b64 s[sgpr_idx], s[sgpr_idx], { dst_idx_en: 1, dst_idx: MOV_INDEXED_M0 } //s[N+m0] = s[N], s[N+1+m0] = s[N+1] +end + + // s[80:95], s[64:79], ... s[0:15] + L_RESTORE_SGPR_LOOP: + s_sub_u32 s_restore_tmp, s_restore_tmp, 0x40 + s_load_b512 s0, [s_restore_addr_lo, s_restore_addr_hi], s_restore_tmp scope:SCOPE_SYS + s_wait_kmcnt 0 + + s_sub_u32 m0, m0, (0x10 << 0x10) +for var sgpr_idx = 0; sgpr_idx < 0x10; sgpr_idx += 2 + s_mov_indexed_b64 s[sgpr_idx], s[sgpr_idx], { dst_idx_en: 1, dst_idx: MOV_INDEXED_M0 } //s[N+m0] = s[N], s[N+1+m0] = s[N+1] +end + + s_cmp_eq_u32 m0, 0 + s_cbranch_scc0 L_RESTORE_SGPR_LOOP + + // s_barrier with STATE_PRIV.TRAP_AFTER_INST=1, STATUS.PRIV=1 incorrectly asserts debug exception. + // Clear DEBUG_EN before and restore MODE after the barrier. + s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE), 0 + +L_RESTORE_HWREG: + // HWREG SR memory offset : size(VGPR)+size(SGPR) + get_vgpr_size_bytes(s_restore_tmp, s_restore_flags) + s_add_u32 s_restore_tmp, s_restore_tmp, get_sgpr_size_bytes() + s_add_u32 s_restore_addr_lo, s_restore_base_addr_lo, s_restore_tmp + s_addc_u32 s_restore_addr_hi, s_restore_base_addr_hi, 0x0 + + s_load_b32 s_restore_m0, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS + s_load_b32 s_return_pc_lo, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x4 + s_load_b32 s_return_pc_hi, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x8 + s_load_b32 s_restore_exec_lo, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0xC + s_load_b32 s_restore_exec_hi, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x10 + s_load_b32 s_restore_state_priv, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x14 + s_load_b32 s_restore_excp_flag_priv, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x18 + s_load_b32 s_restore_xnack_mask, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x1C + s_load_b32 s_restore_mode, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x20 + + s_load_b32 s_restore_tmp, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x24 + s_wait_kmcnt 0 + s_setreg_b32 hwreg(HW_REG_WAVE_SCRATCH_BASE_LO), s_restore_tmp + + s_load_b32 s_restore_tmp, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x28 + s_wait_kmcnt 0 + s_setreg_b32 hwreg(HW_REG_WAVE_SCRATCH_BASE_HI), s_restore_tmp + + s_load_b32 s_restore_tmp, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x2C + s_wait_kmcnt 0 + s_setreg_b32 hwreg(HW_REG_WAVE_EXCP_FLAG_USER), s_restore_tmp + + s_load_b32 s_restore_tmp, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x30 + s_wait_kmcnt 0 + s_setreg_b32 hwreg(HW_REG_WAVE_TRAP_CTRL), s_restore_tmp + + s_load_b32 s_restore_tmp, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x40 + s_wait_kmcnt 0 + s_setreg_b32 hwreg(HW_REG_WAVE_GPR_MSB_IDX0), s_restore_tmp + + s_load_b32 s_restore_tmp, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x44 + s_wait_kmcnt 0 + s_setreg_b32 hwreg(HW_REG_WAVE_GPR_IDX123), s_restore_tmp + + s_load_b32 s_restore_tmp, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x48 + s_wait_kmcnt 0 + s_cmp_eq_u32 s_restore_tmp, 1 + s_cbranch_scc0 L_RESTORE_NO_IC_HASH_DISABLE + s_mov_b32 m0, 1 + s_sendmsg_rtn_b32 null, sendmsg(MSG_RTN_SET_CACHE_MODE) + s_wait_kmcnt 0 + +L_RESTORE_NO_IC_HASH_DISABLE: + // Ensure all waves of the group/cluster are created before restoring barrier state. + wait_trap_barriers(s_restore_tmp) + + // Only the first wave needs to restore group barriers. + s_bitcmp1_b32 s_restore_flags, S_FLAGS_FIRST_WAVE_IN_WORKGROUP_SHIFT + s_cbranch_scc0 L_RESTORE_SKIP_GROUP_BARRIER + + // Skip group barriers if wave is not part of a group. + s_load_b32 s_restore_tmp, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x38 + s_wait_kmcnt 0 + s_bitcmp1_b32 s_restore_tmp, BARRIER_STATE_VALID_OFFSET + s_cbranch_scc0 L_RESTORE_SKIP_GROUP_BARRIER + + // Restore workgroup barrier signal count. + restore_barrier_signal_count(-1) + + s_mov_b32 s_restore_mem_offset, NAMED_BARRIERS_SR_OFFSET_FROM_HWREG + s_mov_b32 m0, 1 + +L_RESTORE_NAMED_BARRIER_LOOP: + s_load_b32 s_restore_tmp, [s_restore_addr_lo, s_restore_addr_hi], s_restore_mem_offset scope:SCOPE_SYS + s_wait_kmcnt 0 + + s_bitcmp0_b32 s_restore_tmp, BARRIER_STATE_VALID_OFFSET + s_cbranch_scc1 L_RESTORE_SKIP_GROUP_BARRIER + + s_or_b32 m0, m0, s_restore_tmp + s_barrier_init m0 + + s_add_u32 s_restore_mem_offset, s_restore_mem_offset, 4 + s_and_b32 m0, m0, BARRIER_STATE_ID_MASK + s_add_u32 m0, m0, 1 + s_cmp_gt_u32 m0, NUM_NAMED_BARRIERS + s_cbranch_scc0 L_RESTORE_NAMED_BARRIER_LOOP + +L_RESTORE_SKIP_GROUP_BARRIER: + s_load_b32 s_restore_tmp, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x3C + s_wait_kmcnt 0 + + // Skip cluster barrier restore if wave is not part of a cluster. + s_bitcmp1_b32 s_restore_tmp, BARRIER_STATE_VALID_OFFSET + s_cbranch_scc0 L_RESTORE_SKIP_CLUSTER_BARRIER + + // Only the first wave in the group signals the trap cluster barrier. + s_bitcmp1_b32 s_restore_flags, S_FLAGS_FIRST_WAVE_IN_WORKGROUP_SHIFT + s_cbranch_scc0 L_RESTORE_SKIP_TRAP_CLUSTER_BARRIER_SIGNAL + + // Clear SCC: s_barrier_signal_isfirst -4 writes SCC=>1 but not SCC=>0. + s_cmp_eq_u32 0, 1 + s_barrier_signal_isfirst -4 + +L_RESTORE_SKIP_TRAP_CLUSTER_BARRIER_SIGNAL: + s_barrier_wait -4 + + // Only the first wave in the cluster restores the barrier. + s_cbranch_scc0 L_RESTORE_SKIP_CLUSTER_BARRIER + + // Restore cluster barrier signal count. + restore_barrier_signal_count(-3) + + s_mov_b32 s_restore_mem_offset, NAMED_CLUSTER_BARRIERS_SR_OFFSET_FROM_HWREG + s_mov_b32 m0, 0x21 + +L_RESTORE_NAMED_CLUSTER_BARRIER_LOOP: + s_load_b32 s_restore_tmp, [s_restore_addr_lo, s_restore_addr_hi], s_restore_mem_offset scope:SCOPE_SYS + s_wait_kmcnt 0 + + s_bitcmp0_b32 s_restore_tmp, BARRIER_STATE_VALID_OFFSET + s_cbranch_scc1 L_RESTORE_SKIP_CLUSTER_BARRIER + + s_or_b32 m0, m0, s_restore_tmp + s_barrier_init m0 + + s_add_u32 s_restore_mem_offset, s_restore_mem_offset, 0x4 + s_and_b32 m0, m0, BARRIER_STATE_ID_MASK + s_add_u32 m0, m0, 1 + s_cmp_gt_u32 m0, (0x20 + NUM_NAMED_CLUSTER_BARRIERS) + s_cbranch_scc0 L_RESTORE_NAMED_CLUSTER_BARRIER_LOOP + +L_RESTORE_SKIP_CLUSTER_BARRIER: + // Locks and semaphores are only supported in wavegroups. + s_bitcmp1_b32 s_restore_flags, S_FLAGS_IN_WAVEGROUP_SHIFT + s_cbranch_scc0 L_RESTORE_SKIP_LOCKS_SEMAPHORES + + s_load_b32 s_restore_tmp, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x4C + s_wait_kmcnt 0 + +L_RESTORE_LOCK_LOOP: + s_cmp_eq_u32 s_restore_tmp, 0 + s_cbranch_scc1 L_RESTORE_LOCKS_DONE + + s_ctz_i32_b32 m0, s_restore_tmp + s_try_lock m0 + s_wait_kmcnt 0 + + s_bitset0_b32 s_restore_tmp, m0 + s_branch L_RESTORE_LOCK_LOOP + +L_RESTORE_LOCKS_DONE: + s_load_b32 s_restore_tmp, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x50 + s_wait_kmcnt 0 + s_setreg_b32 hwreg(HW_REG_WAVE_SEMA_MODE), s_restore_tmp + +#if SEMA_DONE_RESTORE_WORKAROUND + label L_RESTORE_SEMA_IS_DONE[NUM_SEMAPHORES] + label L_RESTORE_SEMA_NEXT[NUM_SEMAPHORES] +#endif + +for var sema_idx = 0; sema_idx < NUM_SEMAPHORES; sema_idx ++ + s_load_b32 s_restore_tmp, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:(0x54 + sema_idx * 4) + s_wait_kmcnt 0 + +#if SEMA_DONE_RESTORE_WORKAROUND + s_bitcmp1_b32 s_restore_tmp, SQ_WAVE_SEMA_STATE_DONE_SHIFT + s_cbranch_scc1 L_RESTORE_SEMA_IS_DONE[sema_idx] + + s_setreg_b32 hwreg(HW_REG_WAVE_SEMA1_STATE + sema_idx), s_restore_tmp + s_add_u32 null, 0, 0 + s_branch L_RESTORE_SEMA_NEXT[sema_idx] + +L_RESTORE_SEMA_IS_DONE[sema_idx]: + s_setreg_b32 hwreg(HW_REG_WAVE_SEMA1_STATE + sema_idx), s_restore_tmp + s_nop 0 + +L_RESTORE_SEMA_NEXT[sema_idx]: +#else + s_setreg_b32 hwreg(HW_REG_WAVE_SEMA1_STATE + sema_idx), s_restore_tmp +#endif + +end + +L_RESTORE_SKIP_LOCKS_SEMAPHORES: + s_mov_b32 m0, s_restore_m0 + s_mov_b32 exec_lo, s_restore_exec_lo + s_mov_b32 exec_hi, s_restore_exec_hi + +#if HAVE_XNACK + s_setreg_b32 hwreg(HW_REG_WAVE_XNACK_MASK), s_restore_xnack_mask +#endif + + // EXCP_FLAG_PRIV.SAVE_CONTEXT and HOST_TRAP may have changed. + // Only restore the other fields to avoid clobbering them. + s_setreg_b32 hwreg(HW_REG_WAVE_EXCP_FLAG_PRIV, 0, SQ_WAVE_EXCP_FLAG_PRIV_RESTORE_PART_1_SIZE), s_restore_excp_flag_priv + s_lshr_b32 s_restore_excp_flag_priv, s_restore_excp_flag_priv, SQ_WAVE_EXCP_FLAG_PRIV_RESTORE_PART_2_SHIFT + s_setreg_b32 hwreg(HW_REG_WAVE_EXCP_FLAG_PRIV, SQ_WAVE_EXCP_FLAG_PRIV_RESTORE_PART_2_SHIFT, SQ_WAVE_EXCP_FLAG_PRIV_RESTORE_PART_2_SIZE), s_restore_excp_flag_priv + s_lshr_b32 s_restore_excp_flag_priv, s_restore_excp_flag_priv, SQ_WAVE_EXCP_FLAG_PRIV_RESTORE_PART_3_SHIFT - SQ_WAVE_EXCP_FLAG_PRIV_RESTORE_PART_2_SHIFT + s_setreg_b32 hwreg(HW_REG_WAVE_EXCP_FLAG_PRIV, SQ_WAVE_EXCP_FLAG_PRIV_RESTORE_PART_3_SHIFT, SQ_WAVE_EXCP_FLAG_PRIV_RESTORE_PART_3_SIZE), s_restore_excp_flag_priv + + s_setreg_b32 hwreg(HW_REG_WAVE_MODE), s_restore_mode + + // Restore trap temporaries 4-11, 13 initialized by SPI debug dispatch logic + // ttmp SR memory offset : + // - gfx12: size(VGPR)+size(SGPR)+0x40 + // - gfx12.5: size(VGPR)+size(SGPR)-0x40 + get_vgpr_size_bytes(s_restore_ttmps_lo, s_restore_flags) + s_add_u32 s_restore_ttmps_lo, s_restore_ttmps_lo, (get_sgpr_size_bytes() + TTMP_SR_OFFSET_FROM_HWREG) + s_add_u32 s_restore_ttmps_lo, s_restore_ttmps_lo, s_restore_base_addr_lo + s_addc_u32 s_restore_ttmps_hi, s_restore_base_addr_hi, 0x0 + s_load_dwordx4 [ttmp4, ttmp5, ttmp6, ttmp7], [s_restore_ttmps_lo, s_restore_ttmps_hi], 0x10 scope:SCOPE_SYS + s_load_dwordx4 [ttmp8, ttmp9, ttmp10, ttmp11], [s_restore_ttmps_lo, s_restore_ttmps_hi], 0x20 scope:SCOPE_SYS + s_load_dword ttmp13, [s_restore_ttmps_lo, s_restore_ttmps_hi], 0x34 scope:SCOPE_SYS + s_wait_kmcnt 0 + +#if HAVE_XNACK + restore_xnack_state_priv(s_restore_tmp) +#endif + + s_and_b32 s_return_pc_hi, s_return_pc_hi, ADDRESS_HI32_MASK //Do it here in order not to affect STATUS + s_and_b64 exec, exec, exec // Restore STATUS.EXECZ, not writable by s_setreg_b32 + s_and_b64 vcc, vcc, vcc // Restore STATUS.VCCZ, not writable by s_setreg_b32 + + s_setreg_b32 hwreg(HW_REG_WAVE_STATE_PRIV), s_restore_state_priv // SCC is included, which is changed by previous salu + + // Make barrier and LDS state visible to all waves in the group/cluster. + // STATE_PRIV.*BARRIER_COMPLETE may change after this point. + wait_trap_barriers(s_restore_tmp) + + // SCC is changed by wait_trap_barriers, restore it separately. + s_lshr_b32 s_restore_state_priv, s_restore_state_priv, SQ_WAVE_STATE_PRIV_SCC_SHIFT + s_setreg_b32 hwreg(HW_REG_WAVE_STATE_PRIV, SQ_WAVE_STATE_PRIV_SCC_SHIFT, 1), s_restore_state_priv + + s_rfe_b64 s_return_pc_lo //Return to the main shader program and resume execution +end + +function get_vgpr_num(s_vgpr_num) + s_getreg_b32 s_vgpr_num, hwreg(HW_REG_WAVE_GPR_ALLOC, SQ_WAVE_GPR_ALLOC_VGPR_SIZE_SHIFT, SQ_WAVE_GPR_ALLOC_VGPR_SIZE_SIZE) + s_add_u32 s_vgpr_num, s_vgpr_num, 1 + s_lshl_b32 s_vgpr_num, s_vgpr_num, 2 //Number of VGPRs = (vgpr_size + 1) * 4 +end + +function get_vgpr_size_bytes(s_vgpr_size_byte, s_flags) + s_bitcmp1_b32 s_flags, S_FLAGS_IN_WAVEGROUP_SHIFT + s_cbranch_scc0 L_HAVE_VGPR_SAVE_AREA + s_bitcmp1_b32 s_flags, S_FLAGS_LAST_WAVE_IN_WAVEGROUP_SHIFT + s_cbranch_scc1 L_HAVE_VGPR_SAVE_AREA + + s_mov_b32 s_vgpr_size_byte, 0 + s_branch L_VGPR_SIZE_DONE + +L_HAVE_VGPR_SAVE_AREA: + get_vgpr_num(s_vgpr_size_byte) + s_bitcmp1_b32 s_flags, S_FLAGS_WAVE64_SHIFT + s_cbranch_scc1 L_HAVE_VGPR64 + s_lshl_b32 s_vgpr_size_byte, s_vgpr_size_byte, 7 //Size of VGPRs = (vgpr_size + 1) * 4 * 32 * 4 + s_branch L_VGPR_SIZE_DONE + +L_HAVE_VGPR64: + s_lshl_b32 s_vgpr_size_byte, s_vgpr_size_byte, 8 //Size of VGPRs = (vgpr_size + 1) * 4 * 64 * 4 + +L_VGPR_SIZE_DONE: +end + +function get_sgpr_size_bytes + return 512 +end + +function get_hwreg_size_bytes + return 512 +end + +#if HAVE_XNACK +function save_and_clear_xnack_state_priv(s_tmp) + // Preserve and clear XNACK state before issuing further translations. + // Save XNACK_STATE_PRIV.{FIRST_REPLAY, REPLAY_W64H, FXPTR} into ttmp11[22:14]. + s_andn2_b32 ttmp11, ttmp11, (TTMP11_FIRST_REPLAY_MASK | TTMP11_REPLAY_W64H_MASK | TTMP11_FXPTR_MASK) + + s_getreg_b32 s_tmp, hwreg(HW_REG_WAVE_XNACK_STATE_PRIV, SQ_WAVE_XNACK_STATE_PRIV_FIRST_REPLAY_SHIFT, SQ_WAVE_XNACK_STATE_PRIV_FIRST_REPLAY_SIZE) + s_lshl_b32 s_tmp, s_tmp, TTMP11_FIRST_REPLAY_SHIFT + s_or_b32 ttmp11, ttmp11, s_tmp + + s_getreg_b32 s_tmp, hwreg(HW_REG_WAVE_XNACK_STATE_PRIV, SQ_WAVE_XNACK_STATE_PRIV_REPLAY_W64H_SHIFT, SQ_WAVE_XNACK_STATE_PRIV_REPLAY_W64H_SIZE) + s_lshl_b32 s_tmp, s_tmp, TTMP11_REPLAY_W64H_SHIFT + s_or_b32 ttmp11, ttmp11, s_tmp + + s_getreg_b32 s_tmp, hwreg(HW_REG_WAVE_XNACK_STATE_PRIV, SQ_WAVE_XNACK_STATE_PRIV_FXPTR_SHIFT, SQ_WAVE_XNACK_STATE_PRIV_FXPTR_SIZE) + s_lshl_b32 s_tmp, s_tmp, TTMP11_FXPTR_SHIFT + s_or_b32 ttmp11, ttmp11, s_tmp + + s_setreg_imm32_b32 hwreg(HW_REG_WAVE_XNACK_STATE_PRIV), 0 +end + +function restore_xnack_state_priv(s_tmp) + s_lshr_b32 s_tmp, ttmp11, TTMP11_FIRST_REPLAY_SHIFT + s_setreg_b32 hwreg(HW_REG_WAVE_XNACK_STATE_PRIV, SQ_WAVE_XNACK_STATE_PRIV_FIRST_REPLAY_SHIFT, SQ_WAVE_XNACK_STATE_PRIV_FIRST_REPLAY_SIZE), s_tmp + + s_lshr_b32 s_tmp, ttmp11, TTMP11_REPLAY_W64H_SHIFT + s_setreg_b32 hwreg(HW_REG_WAVE_XNACK_STATE_PRIV, SQ_WAVE_XNACK_STATE_PRIV_REPLAY_W64H_SHIFT, SQ_WAVE_XNACK_STATE_PRIV_REPLAY_W64H_SIZE), s_tmp + + s_lshr_b32 s_tmp, ttmp11, TTMP11_FXPTR_SHIFT + s_setreg_b32 hwreg(HW_REG_WAVE_XNACK_STATE_PRIV, SQ_WAVE_XNACK_STATE_PRIV_FXPTR_SHIFT, SQ_WAVE_XNACK_STATE_PRIV_FXPTR_SIZE), s_tmp +end +#endif + +function wait_trap_barriers(s_tmp) + // If not in a WG then wave cannot use s_barrier_signal_isfirst. + s_getreg_b32 s_tmp, hwreg(HW_REG_WAVE_STATUS) + s_bitcmp0_b32 s_tmp, SQ_WAVE_STATUS_IN_WG_SHIFT + s_cbranch_scc1 L_TRAP_CLUSTER_BARRIER_SIGNAL + + s_barrier_signal_isfirst -2 + s_barrier_wait -2 + + // Only the first wave in the group signals the trap cluster barrier. + s_cbranch_scc0 L_SKIP_TRAP_CLUSTER_BARRIER_SIGNAL + +L_TRAP_CLUSTER_BARRIER_SIGNAL: + s_barrier_signal -4 + +L_SKIP_TRAP_CLUSTER_BARRIER_SIGNAL: + s_barrier_wait -4 +end + +function restore_barrier_signal_count(barrier_id) + // extract the saved signal count from s_restore_tmp + s_bfe_u32 s_restore_tmp, s_restore_tmp, (BARRIER_STATE_SIGNAL_OFFSET | (BARRIER_STATE_SIGNAL_SIZE << 0x10)) + + // We need to call s_barrier_signal repeatedly to restore the signal count + // of the group/cluster barrier. The member count is already initialized. +L_BARRIER_RESTORE_LOOP: + s_and_b32 s_restore_tmp, s_restore_tmp, s_restore_tmp + s_cbranch_scc0 L_BARRIER_RESTORE_DONE + s_barrier_signal barrier_id + s_add_i32 s_restore_tmp, s_restore_tmp, -1 + s_branch L_BARRIER_RESTORE_LOOP + +L_BARRIER_RESTORE_DONE: +end + +function save_vgprs(vgpr_size) +L_SAVE_VGPR_LOOP: + // Index groups of VGPRs v[0,1,2,3], v[4,5,6,7], ... + s_set_gpr_idx_u32 dst_idx0, s_save_tmp + +for var vgpr_idx = 0; vgpr_idx < 4; vgpr_idx ++ + global_store_addtid_b32 v[vgpr_idx], [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS offset:(vgpr_idx * vgpr_size) +end + + s_add_u32 s_save_addr_lo, s_save_addr_lo, vgpr_size * 4 + s_addc_u32 s_save_addr_hi, s_save_addr_hi, 0 + + s_add_u32 s_save_tmp, s_save_tmp, 4 + s_cmp_lt_u32 s_save_tmp, s_save_alloc_size + s_cbranch_scc1 L_SAVE_VGPR_LOOP +end + +function save_lds(vgpr_size) +L_SAVE_LDS_LOOP: + // Copy LDS to save area in VGPR-sized blocks. + ds_read_b32 v1, v0 + s_wait_dscnt 0 + global_store_addtid_b32 v1, [s_save_addr_lo, s_save_addr_hi] scope:SCOPE_SYS + + s_add_u32 s_save_addr_lo, s_save_addr_lo, vgpr_size + s_addc_u32 s_save_addr_hi, s_save_addr_hi, 0 + v_add_nc_u32 v0, v0, vgpr_size + + s_add_u32 s_save_tmp, s_save_tmp, vgpr_size + s_cmp_lt_u32 s_save_tmp, s_save_alloc_size + s_cbranch_scc1 L_SAVE_LDS_LOOP +end + +function restore_vgprs(vgpr_size) +L_RESTORE_VGPR_LOOP: + // Index groups of VGPRs v[0,1,2,3], v[4,5,6,7], ... + s_set_gpr_idx_u32 dst_idx0, s_restore_tmp + +for var vgpr_idx = 0; vgpr_idx < 4; vgpr_idx ++ + global_load_addtid_b32 v[vgpr_idx], [s_restore_addr_lo, s_restore_addr_hi] scope:SCOPE_SYS offset:(vgpr_idx * vgpr_size) +end + + s_add_u32 s_restore_addr_lo, s_restore_addr_lo, vgpr_size * 4 + s_addc_u32 s_restore_addr_hi, s_restore_addr_hi, 0 + + s_add_u32 s_restore_tmp, s_restore_tmp, 4 + s_cmp_lt_u32 s_restore_tmp, s_restore_alloc_size + s_cbranch_scc1 L_RESTORE_VGPR_LOOP + + s_wait_loadcnt 0 +end + +function restore_lds(vgpr_size) +L_RESTORE_LDS_LOOP: + // Copy LDS from restore area in VGPR-sized blocks. + global_load_addtid_b32 v1, [s_restore_addr_lo, s_restore_addr_hi] scope:SCOPE_SYS + s_wait_loadcnt 0 + ds_store_b32 v0, v1 + + s_add_u32 s_restore_addr_lo, s_restore_addr_lo, vgpr_size + s_addc_u32 s_restore_addr_hi, s_restore_addr_hi, 0 + v_add_nc_u32 v0, v0, vgpr_size + + s_add_u32 s_restore_tmp, s_restore_tmp, vgpr_size + s_cmp_lt_u32 s_restore_tmp, s_restore_alloc_size + s_cbranch_scc1 L_RESTORE_LDS_LOOP + + s_wait_dscnt 0 +end -- 2.56.0
