Merge tag 'devicetree-fixes-for-5.15-1' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / amdkfd / cwsr_trap_handler_gfx9.asm
1 /*
2  * Copyright 2016 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  */
22
23 /* To compile this assembly code:
24  *
25  * gfx9:
26  *   cpp -DASIC_FAMILY=CHIP_VEGAM cwsr_trap_handler_gfx9.asm -P -o gfx9.sp3
27  *   sp3 gfx9.sp3 -hex gfx9.hex
28  *
29  * arcturus:
30  *   cpp -DASIC_FAMILY=CHIP_ARCTURUS cwsr_trap_handler_gfx9.asm -P -o arcturus.sp3
31  *   sp3 arcturus.sp3 -hex arcturus.hex
32  *
33  * aldebaran:
34  *   cpp -DASIC_FAMILY=CHIP_ALDEBARAN cwsr_trap_handler_gfx9.asm -P -o aldebaran.sp3
35  *   sp3 aldebaran.sp3 -hex aldebaran.hex
36  */
37
38 #define CHIP_VEGAM 18
39 #define CHIP_ARCTURUS 23
40 #define CHIP_ALDEBARAN 25
41
42 var ACK_SQC_STORE                   =   1                   //workaround for suspected SQC store bug causing incorrect stores under concurrency
43 var SAVE_AFTER_XNACK_ERROR          =   1                   //workaround for TCP store failure after XNACK error when ALLOW_REPLAY=0, for debugger
44 var SINGLE_STEP_MISSED_WORKAROUND   =   1                   //workaround for lost MODE.DEBUG_EN exception when SAVECTX raised
45
46 /**************************************************************************/
47 /*                      variables                                         */
48 /**************************************************************************/
49 var SQ_WAVE_STATUS_INST_ATC_SHIFT  = 23
50 var SQ_WAVE_STATUS_INST_ATC_MASK   = 0x00800000
51 var SQ_WAVE_STATUS_SPI_PRIO_SHIFT  = 1
52 var SQ_WAVE_STATUS_SPI_PRIO_MASK   = 0x00000006
53 var SQ_WAVE_STATUS_HALT_MASK       = 0x2000
54 var SQ_WAVE_STATUS_PRE_SPI_PRIO_SHIFT   = 0
55 var SQ_WAVE_STATUS_PRE_SPI_PRIO_SIZE    = 1
56 var SQ_WAVE_STATUS_POST_SPI_PRIO_SHIFT  = 3
57 var SQ_WAVE_STATUS_POST_SPI_PRIO_SIZE   = 29
58 var SQ_WAVE_STATUS_ALLOW_REPLAY_MASK    = 0x400000
59
60 var SQ_WAVE_LDS_ALLOC_LDS_SIZE_SHIFT    = 12
61 var SQ_WAVE_LDS_ALLOC_LDS_SIZE_SIZE     = 9
62 var SQ_WAVE_GPR_ALLOC_VGPR_SIZE_SIZE    = 6
63 var SQ_WAVE_GPR_ALLOC_SGPR_SIZE_SIZE    = 3                     //FIXME  sq.blk still has 4 bits at this time while SQ programming guide has 3 bits
64 var SQ_WAVE_GPR_ALLOC_SGPR_SIZE_SHIFT   = 24
65
66 #if ASIC_FAMILY >= CHIP_ALDEBARAN
67 var SQ_WAVE_GPR_ALLOC_VGPR_SIZE_SHIFT   = 6
68 var SQ_WAVE_GPR_ALLOC_ACCV_OFFSET_SHIFT = 12
69 var SQ_WAVE_GPR_ALLOC_ACCV_OFFSET_SIZE  = 6
70 #else
71 var SQ_WAVE_GPR_ALLOC_VGPR_SIZE_SHIFT   = 8
72 #endif
73
74 var SQ_WAVE_TRAPSTS_SAVECTX_MASK    =   0x400
75 var SQ_WAVE_TRAPSTS_EXCE_MASK       =   0x1FF                   // Exception mask
76 var SQ_WAVE_TRAPSTS_SAVECTX_SHIFT   =   10
77 var SQ_WAVE_TRAPSTS_MEM_VIOL_MASK   =   0x100
78 var SQ_WAVE_TRAPSTS_MEM_VIOL_SHIFT  =   8
79 var SQ_WAVE_TRAPSTS_PRE_SAVECTX_MASK    =   0x3FF
80 var SQ_WAVE_TRAPSTS_PRE_SAVECTX_SHIFT   =   0x0
81 var SQ_WAVE_TRAPSTS_PRE_SAVECTX_SIZE    =   10
82 var SQ_WAVE_TRAPSTS_POST_SAVECTX_MASK   =   0xFFFFF800
83 var SQ_WAVE_TRAPSTS_POST_SAVECTX_SHIFT  =   11
84 var SQ_WAVE_TRAPSTS_POST_SAVECTX_SIZE   =   21
85 var SQ_WAVE_TRAPSTS_ILLEGAL_INST_MASK   =   0x800
86 var SQ_WAVE_TRAPSTS_XNACK_ERROR_MASK    =   0x10000000
87
88 var SQ_WAVE_IB_STS_RCNT_SHIFT           =   16                  //FIXME
89 var SQ_WAVE_IB_STS_FIRST_REPLAY_SHIFT   =   15                  //FIXME
90 var SQ_WAVE_IB_STS_RCNT_FIRST_REPLAY_MASK       = 0x1F8000
91 var SQ_WAVE_IB_STS_RCNT_FIRST_REPLAY_MASK_NEG   = 0x00007FFF    //FIXME
92
93 var SQ_WAVE_MODE_DEBUG_EN_MASK          =   0x800
94
95 var SQ_BUF_RSRC_WORD1_ATC_SHIFT     =   24
96 var SQ_BUF_RSRC_WORD3_MTYPE_SHIFT   =   27
97
98 var TTMP11_SAVE_RCNT_FIRST_REPLAY_SHIFT =   26                  // bits [31:26] unused by SPI debug data
99 var TTMP11_SAVE_RCNT_FIRST_REPLAY_MASK  =   0xFC000000
100
101 /*      Save        */
102 var S_SAVE_BUF_RSRC_WORD1_STRIDE        =   0x00040000          //stride is 4 bytes
103 var S_SAVE_BUF_RSRC_WORD3_MISC          =   0x00807FAC          //SQ_SEL_X/Y/Z/W, BUF_NUM_FORMAT_FLOAT, (0 for MUBUF stride[17:14] when ADD_TID_ENABLE and BUF_DATA_FORMAT_32 for MTBUF), ADD_TID_ENABLE
104
105 var S_SAVE_SPI_INIT_ATC_MASK            =   0x08000000          //bit[27]: ATC bit
106 var S_SAVE_SPI_INIT_ATC_SHIFT           =   27
107 var S_SAVE_SPI_INIT_MTYPE_MASK          =   0x70000000          //bit[30:28]: Mtype
108 var S_SAVE_SPI_INIT_MTYPE_SHIFT         =   28
109 var S_SAVE_SPI_INIT_FIRST_WAVE_MASK     =   0x04000000          //bit[26]: FirstWaveInTG
110 var S_SAVE_SPI_INIT_FIRST_WAVE_SHIFT    =   26
111
112 var S_SAVE_PC_HI_RCNT_SHIFT             =   27                  //FIXME  check with Brian to ensure all fields other than PC[47:0] can be used
113 var S_SAVE_PC_HI_RCNT_MASK              =   0xF8000000          //FIXME
114 var S_SAVE_PC_HI_FIRST_REPLAY_SHIFT     =   26                  //FIXME
115 var S_SAVE_PC_HI_FIRST_REPLAY_MASK      =   0x04000000          //FIXME
116
117 var s_save_spi_init_lo              =   exec_lo
118 var s_save_spi_init_hi              =   exec_hi
119
120 var s_save_pc_lo            =   ttmp0           //{TTMP1, TTMP0} = {3'h0,pc_rewind[3:0], HT[0],trapID[7:0], PC[47:0]}
121 var s_save_pc_hi            =   ttmp1
122 var s_save_exec_lo          =   ttmp2
123 var s_save_exec_hi          =   ttmp3
124 var s_save_tmp              =   ttmp14
125 var s_save_trapsts          =   ttmp15          //not really used until the end of the SAVE routine
126 var s_save_xnack_mask_lo    =   ttmp6
127 var s_save_xnack_mask_hi    =   ttmp7
128 var s_save_buf_rsrc0        =   ttmp8
129 var s_save_buf_rsrc1        =   ttmp9
130 var s_save_buf_rsrc2        =   ttmp10
131 var s_save_buf_rsrc3        =   ttmp11
132 var s_save_status           =   ttmp12
133 var s_save_mem_offset       =   ttmp4
134 var s_save_alloc_size       =   s_save_trapsts          //conflict
135 var s_save_m0               =   ttmp5
136 var s_save_ttmps_lo         =   s_save_tmp              //no conflict
137 var s_save_ttmps_hi         =   s_save_trapsts          //no conflict
138
139 /*      Restore     */
140 var S_RESTORE_BUF_RSRC_WORD1_STRIDE         =   S_SAVE_BUF_RSRC_WORD1_STRIDE
141 var S_RESTORE_BUF_RSRC_WORD3_MISC           =   S_SAVE_BUF_RSRC_WORD3_MISC
142
143 var S_RESTORE_SPI_INIT_ATC_MASK             =   0x08000000          //bit[27]: ATC bit
144 var S_RESTORE_SPI_INIT_ATC_SHIFT            =   27
145 var S_RESTORE_SPI_INIT_MTYPE_MASK           =   0x70000000          //bit[30:28]: Mtype
146 var S_RESTORE_SPI_INIT_MTYPE_SHIFT          =   28
147 var S_RESTORE_SPI_INIT_FIRST_WAVE_MASK      =   0x04000000          //bit[26]: FirstWaveInTG
148 var S_RESTORE_SPI_INIT_FIRST_WAVE_SHIFT     =   26
149
150 var S_RESTORE_PC_HI_RCNT_SHIFT              =   S_SAVE_PC_HI_RCNT_SHIFT
151 var S_RESTORE_PC_HI_RCNT_MASK               =   S_SAVE_PC_HI_RCNT_MASK
152 var S_RESTORE_PC_HI_FIRST_REPLAY_SHIFT      =   S_SAVE_PC_HI_FIRST_REPLAY_SHIFT
153 var S_RESTORE_PC_HI_FIRST_REPLAY_MASK       =   S_SAVE_PC_HI_FIRST_REPLAY_MASK
154
155 var s_restore_spi_init_lo                   =   exec_lo
156 var s_restore_spi_init_hi                   =   exec_hi
157
158 var s_restore_mem_offset        =   ttmp12
159 var s_restore_tmp2              =   ttmp13
160 var s_restore_alloc_size        =   ttmp3
161 var s_restore_tmp               =   ttmp2
162 var s_restore_mem_offset_save   =   s_restore_tmp       //no conflict
163 var s_restore_accvgpr_offset_save = ttmp7
164
165 var s_restore_m0            =   s_restore_alloc_size    //no conflict
166
167 var s_restore_mode          =   s_restore_accvgpr_offset_save
168
169 var s_restore_pc_lo         =   ttmp0
170 var s_restore_pc_hi         =   ttmp1
171 var s_restore_exec_lo       =   ttmp4
172 var s_restore_exec_hi       =   ttmp5
173 var s_restore_status        =   ttmp14
174 var s_restore_trapsts       =   ttmp15
175 var s_restore_xnack_mask_lo =   xnack_mask_lo
176 var s_restore_xnack_mask_hi =   xnack_mask_hi
177 var s_restore_buf_rsrc0     =   ttmp8
178 var s_restore_buf_rsrc1     =   ttmp9
179 var s_restore_buf_rsrc2     =   ttmp10
180 var s_restore_buf_rsrc3     =   ttmp11
181 var s_restore_ttmps_lo      =   s_restore_tmp           //no conflict
182 var s_restore_ttmps_hi      =   s_restore_alloc_size    //no conflict
183
184 /**************************************************************************/
185 /*                      trap handler entry points                         */
186 /**************************************************************************/
187 /* Shader Main*/
188
189 shader main
190   asic(DEFAULT)
191   type(CS)
192
193
194         s_branch L_SKIP_RESTORE                                     //NOT restore. might be a regular trap or save
195
196 L_JUMP_TO_RESTORE:
197     s_branch L_RESTORE                                              //restore
198
199 L_SKIP_RESTORE:
200
201     s_getreg_b32    s_save_status, hwreg(HW_REG_STATUS)                             //save STATUS since we will change SCC
202     s_andn2_b32     s_save_status, s_save_status, SQ_WAVE_STATUS_SPI_PRIO_MASK      //check whether this is for save
203
204 if SINGLE_STEP_MISSED_WORKAROUND
205     // No single step exceptions if MODE.DEBUG_EN=0.
206     s_getreg_b32    ttmp2, hwreg(HW_REG_MODE)
207     s_and_b32       ttmp2, ttmp2, SQ_WAVE_MODE_DEBUG_EN_MASK
208     s_cbranch_scc0  L_NO_SINGLE_STEP_WORKAROUND
209
210     // Second-level trap already handled exception if STATUS.HALT=1.
211     s_and_b32       ttmp2, s_save_status, SQ_WAVE_STATUS_HALT_MASK
212
213     // Prioritize single step exception over context save.
214     // Second-level trap will halt wave and RFE, re-entering for SAVECTX.
215     s_cbranch_scc0  L_FETCH_2ND_TRAP
216
217 L_NO_SINGLE_STEP_WORKAROUND:
218 end
219
220     s_getreg_b32    s_save_trapsts, hwreg(HW_REG_TRAPSTS)
221     s_and_b32       ttmp2, s_save_trapsts, SQ_WAVE_TRAPSTS_SAVECTX_MASK    //check whether this is for save
222     s_cbranch_scc1  L_SAVE                                      //this is the operation for save
223
224     // *********    Handle non-CWSR traps       *******************
225
226     // Illegal instruction is a non-maskable exception which blocks context save.
227     // Halt the wavefront and return from the trap.
228     s_and_b32       ttmp2, s_save_trapsts, SQ_WAVE_TRAPSTS_ILLEGAL_INST_MASK
229     s_cbranch_scc1  L_HALT_WAVE
230
231     // If STATUS.MEM_VIOL is asserted then we cannot fetch from the TMA.
232     // Instead, halt the wavefront and return from the trap.
233     s_and_b32       ttmp2, s_save_trapsts, SQ_WAVE_TRAPSTS_MEM_VIOL_MASK
234     s_cbranch_scc0  L_FETCH_2ND_TRAP
235
236 L_HALT_WAVE:
237     // If STATUS.HALT is set then this fault must come from SQC instruction fetch.
238     // We cannot prevent further faults. Spin wait until context saved.
239     s_and_b32       ttmp2, s_save_status, SQ_WAVE_STATUS_HALT_MASK
240     s_cbranch_scc0  L_NOT_ALREADY_HALTED
241
242 L_WAIT_CTX_SAVE:
243     s_sleep         0x10
244     s_getreg_b32    ttmp2, hwreg(HW_REG_TRAPSTS)
245     s_and_b32       ttmp2, ttmp2, SQ_WAVE_TRAPSTS_SAVECTX_MASK
246     s_cbranch_scc0  L_WAIT_CTX_SAVE
247
248 L_NOT_ALREADY_HALTED:
249     s_or_b32        s_save_status, s_save_status, SQ_WAVE_STATUS_HALT_MASK
250
251     // If the PC points to S_ENDPGM then context save will fail if STATUS.HALT is set.
252     // Rewind the PC to prevent this from occurring. The debugger compensates for this.
253     s_sub_u32       ttmp0, ttmp0, 0x8
254     s_subb_u32      ttmp1, ttmp1, 0x0
255
256 L_FETCH_2ND_TRAP:
257     // Preserve and clear scalar XNACK state before issuing scalar reads.
258     // Save IB_STS.FIRST_REPLAY[15] and IB_STS.RCNT[20:16] into unused space ttmp11[31:26].
259     s_getreg_b32    ttmp2, hwreg(HW_REG_IB_STS)
260     s_and_b32       ttmp3, ttmp2, SQ_WAVE_IB_STS_RCNT_FIRST_REPLAY_MASK
261     s_lshl_b32      ttmp3, ttmp3, (TTMP11_SAVE_RCNT_FIRST_REPLAY_SHIFT - SQ_WAVE_IB_STS_FIRST_REPLAY_SHIFT)
262     s_andn2_b32     ttmp11, ttmp11, TTMP11_SAVE_RCNT_FIRST_REPLAY_MASK
263     s_or_b32        ttmp11, ttmp11, ttmp3
264
265     s_andn2_b32     ttmp2, ttmp2, SQ_WAVE_IB_STS_RCNT_FIRST_REPLAY_MASK
266     s_setreg_b32    hwreg(HW_REG_IB_STS), ttmp2
267
268     // Read second-level TBA/TMA from first-level TMA and jump if available.
269     // ttmp[2:5] and ttmp12 can be used (others hold SPI-initialized debug data)
270     // ttmp12 holds SQ_WAVE_STATUS
271     s_getreg_b32    ttmp14, hwreg(HW_REG_SQ_SHADER_TMA_LO)
272     s_getreg_b32    ttmp15, hwreg(HW_REG_SQ_SHADER_TMA_HI)
273     s_lshl_b64      [ttmp14, ttmp15], [ttmp14, ttmp15], 0x8
274     s_load_dwordx2  [ttmp2, ttmp3], [ttmp14, ttmp15], 0x0 glc:1 // second-level TBA
275     s_waitcnt       lgkmcnt(0)
276     s_load_dwordx2  [ttmp14, ttmp15], [ttmp14, ttmp15], 0x8 glc:1 // second-level TMA
277     s_waitcnt       lgkmcnt(0)
278     s_and_b64       [ttmp2, ttmp3], [ttmp2, ttmp3], [ttmp2, ttmp3]
279     s_cbranch_scc0  L_NO_NEXT_TRAP // second-level trap handler not been set
280     s_setpc_b64     [ttmp2, ttmp3] // jump to second-level trap handler
281
282 L_NO_NEXT_TRAP:
283     s_getreg_b32    s_save_trapsts, hwreg(HW_REG_TRAPSTS)
284     s_and_b32       s_save_trapsts, s_save_trapsts, SQ_WAVE_TRAPSTS_EXCE_MASK // Check whether it is an exception
285     s_cbranch_scc1  L_EXCP_CASE   // Exception, jump back to the shader program directly.
286     s_add_u32       ttmp0, ttmp0, 4   // S_TRAP case, add 4 to ttmp0
287     s_addc_u32  ttmp1, ttmp1, 0
288 L_EXCP_CASE:
289     s_and_b32   ttmp1, ttmp1, 0xFFFF
290
291     // Restore SQ_WAVE_IB_STS.
292     s_lshr_b32      ttmp2, ttmp11, (TTMP11_SAVE_RCNT_FIRST_REPLAY_SHIFT - SQ_WAVE_IB_STS_FIRST_REPLAY_SHIFT)
293     s_and_b32       ttmp2, ttmp2, SQ_WAVE_IB_STS_RCNT_FIRST_REPLAY_MASK
294     s_setreg_b32    hwreg(HW_REG_IB_STS), ttmp2
295
296     // Restore SQ_WAVE_STATUS.
297     s_and_b64       exec, exec, exec // Restore STATUS.EXECZ, not writable by s_setreg_b32
298     s_and_b64       vcc, vcc, vcc    // Restore STATUS.VCCZ, not writable by s_setreg_b32
299     set_status_without_spi_prio(s_save_status, ttmp2)
300
301     s_rfe_b64       [ttmp0, ttmp1]
302
303     // *********        End handling of non-CWSR traps   *******************
304
305 /**************************************************************************/
306 /*                      save routine                                      */
307 /**************************************************************************/
308
309 L_SAVE:
310     s_and_b32       s_save_pc_hi, s_save_pc_hi, 0x0000ffff    //pc[47:32]
311
312     s_mov_b32       s_save_tmp, 0                                                           //clear saveCtx bit
313     s_setreg_b32    hwreg(HW_REG_TRAPSTS, SQ_WAVE_TRAPSTS_SAVECTX_SHIFT, 1), s_save_tmp     //clear saveCtx bit
314
315     s_getreg_b32    s_save_tmp, hwreg(HW_REG_IB_STS, SQ_WAVE_IB_STS_RCNT_SHIFT, SQ_WAVE_IB_STS_RCNT_SIZE)                   //save RCNT
316     s_lshl_b32      s_save_tmp, s_save_tmp, S_SAVE_PC_HI_RCNT_SHIFT
317     s_or_b32        s_save_pc_hi, s_save_pc_hi, s_save_tmp
318     s_getreg_b32    s_save_tmp, hwreg(HW_REG_IB_STS, SQ_WAVE_IB_STS_FIRST_REPLAY_SHIFT, SQ_WAVE_IB_STS_FIRST_REPLAY_SIZE)   //save FIRST_REPLAY
319     s_lshl_b32      s_save_tmp, s_save_tmp, S_SAVE_PC_HI_FIRST_REPLAY_SHIFT
320     s_or_b32        s_save_pc_hi, s_save_pc_hi, s_save_tmp
321     s_getreg_b32    s_save_tmp, hwreg(HW_REG_IB_STS)                                        //clear RCNT and FIRST_REPLAY in IB_STS
322     s_and_b32       s_save_tmp, s_save_tmp, SQ_WAVE_IB_STS_RCNT_FIRST_REPLAY_MASK_NEG
323
324     s_setreg_b32    hwreg(HW_REG_IB_STS), s_save_tmp
325
326     /*      inform SPI the readiness and wait for SPI's go signal */
327     s_mov_b32       s_save_exec_lo, exec_lo                                                 //save EXEC and use EXEC for the go signal from SPI
328     s_mov_b32       s_save_exec_hi, exec_hi
329     s_mov_b64       exec,   0x0                                                             //clear EXEC to get ready to receive
330
331         s_sendmsg   sendmsg(MSG_SAVEWAVE)  //send SPI a message and wait for SPI's write to EXEC
332
333     // Set SPI_PRIO=2 to avoid starving instruction fetch in the waves we're waiting for.
334     s_or_b32 s_save_tmp, s_save_status, (2 << SQ_WAVE_STATUS_SPI_PRIO_SHIFT)
335     s_setreg_b32 hwreg(HW_REG_STATUS), s_save_tmp
336
337   L_SLEEP:
338     s_sleep 0x2                // sleep 1 (64clk) is not enough for 8 waves per SIMD, which will cause SQ hang, since the 7,8th wave could not get arbit to exec inst, while other waves are stuck into the sleep-loop and waiting for wrexec!=0
339
340         s_cbranch_execz L_SLEEP
341
342     // Save trap temporaries 4-11, 13 initialized by SPI debug dispatch logic
343     // ttmp SR memory offset : size(VGPR)+size(SGPR)+0x40
344     get_vgpr_size_bytes(s_save_ttmps_lo)
345     get_sgpr_size_bytes(s_save_ttmps_hi)
346     s_add_u32       s_save_ttmps_lo, s_save_ttmps_lo, s_save_ttmps_hi
347     s_add_u32       s_save_ttmps_lo, s_save_ttmps_lo, s_save_spi_init_lo
348     s_addc_u32      s_save_ttmps_hi, s_save_spi_init_hi, 0x0
349     s_and_b32       s_save_ttmps_hi, s_save_ttmps_hi, 0xFFFF
350     s_store_dwordx4 [ttmp4, ttmp5, ttmp6, ttmp7], [s_save_ttmps_lo, s_save_ttmps_hi], 0x50 glc:1
351     ack_sqc_store_workaround()
352     s_store_dwordx4 [ttmp8, ttmp9, ttmp10, ttmp11], [s_save_ttmps_lo, s_save_ttmps_hi], 0x60 glc:1
353     ack_sqc_store_workaround()
354     s_store_dword   ttmp13, [s_save_ttmps_lo, s_save_ttmps_hi], 0x74 glc:1
355     ack_sqc_store_workaround()
356
357     /*      setup Resource Contants    */
358     s_mov_b32       s_save_buf_rsrc0,   s_save_spi_init_lo                                                      //base_addr_lo
359     s_and_b32       s_save_buf_rsrc1,   s_save_spi_init_hi, 0x0000FFFF                                          //base_addr_hi
360     s_or_b32        s_save_buf_rsrc1,   s_save_buf_rsrc1,  S_SAVE_BUF_RSRC_WORD1_STRIDE
361     s_mov_b32       s_save_buf_rsrc2,   0                                                                       //NUM_RECORDS initial value = 0 (in bytes) although not neccessarily inited
362     s_mov_b32       s_save_buf_rsrc3,   S_SAVE_BUF_RSRC_WORD3_MISC
363     s_and_b32       s_save_tmp,         s_save_spi_init_hi, S_SAVE_SPI_INIT_ATC_MASK
364     s_lshr_b32      s_save_tmp,         s_save_tmp, (S_SAVE_SPI_INIT_ATC_SHIFT-SQ_BUF_RSRC_WORD1_ATC_SHIFT)         //get ATC bit into position
365     s_or_b32        s_save_buf_rsrc3,   s_save_buf_rsrc3,  s_save_tmp                                           //or ATC
366     s_and_b32       s_save_tmp,         s_save_spi_init_hi, S_SAVE_SPI_INIT_MTYPE_MASK
367     s_lshr_b32      s_save_tmp,         s_save_tmp, (S_SAVE_SPI_INIT_MTYPE_SHIFT-SQ_BUF_RSRC_WORD3_MTYPE_SHIFT)     //get MTYPE bits into position
368     s_or_b32        s_save_buf_rsrc3,   s_save_buf_rsrc3,  s_save_tmp                                           //or MTYPE
369
370     //FIXME  right now s_save_m0/s_save_mem_offset use tma_lo/tma_hi  (might need to save them before using them?)
371     s_mov_b32       s_save_m0,          m0                                                                  //save M0
372
373     /*      global mem offset           */
374     s_mov_b32       s_save_mem_offset,  0x0                                                                     //mem offset initial value = 0
375
376
377
378
379     /*      save HW registers   */
380     //////////////////////////////
381
382   L_SAVE_HWREG:
383         // HWREG SR memory offset : size(VGPR)+size(SGPR)
384        get_vgpr_size_bytes(s_save_mem_offset)
385        get_sgpr_size_bytes(s_save_tmp)
386        s_add_u32 s_save_mem_offset, s_save_mem_offset, s_save_tmp
387
388
389     s_mov_b32       s_save_buf_rsrc2, 0x4                               //NUM_RECORDS   in bytes
390         s_mov_b32       s_save_buf_rsrc2,  0x1000000                                //NUM_RECORDS in bytes
391
392
393     write_hwreg_to_mem(s_save_m0, s_save_buf_rsrc0, s_save_mem_offset)                  //M0
394     write_hwreg_to_mem(s_save_pc_lo, s_save_buf_rsrc0, s_save_mem_offset)                   //PC
395     write_hwreg_to_mem(s_save_pc_hi, s_save_buf_rsrc0, s_save_mem_offset)
396     write_hwreg_to_mem(s_save_exec_lo, s_save_buf_rsrc0, s_save_mem_offset)             //EXEC
397     write_hwreg_to_mem(s_save_exec_hi, s_save_buf_rsrc0, s_save_mem_offset)
398     write_hwreg_to_mem(s_save_status, s_save_buf_rsrc0, s_save_mem_offset)              //STATUS
399
400     //s_save_trapsts conflicts with s_save_alloc_size
401     s_getreg_b32    s_save_trapsts, hwreg(HW_REG_TRAPSTS)
402     write_hwreg_to_mem(s_save_trapsts, s_save_buf_rsrc0, s_save_mem_offset)             //TRAPSTS
403
404     write_hwreg_to_mem(xnack_mask_lo, s_save_buf_rsrc0, s_save_mem_offset)          //XNACK_MASK_LO
405     write_hwreg_to_mem(xnack_mask_hi, s_save_buf_rsrc0, s_save_mem_offset)          //XNACK_MASK_HI
406
407     //use s_save_tmp would introduce conflict here between s_save_tmp and s_save_buf_rsrc2
408     s_getreg_b32    s_save_m0, hwreg(HW_REG_MODE)                                                   //MODE
409     write_hwreg_to_mem(s_save_m0, s_save_buf_rsrc0, s_save_mem_offset)
410
411
412
413     /*      the first wave in the threadgroup    */
414     s_and_b32       s_save_tmp, s_save_spi_init_hi, S_SAVE_SPI_INIT_FIRST_WAVE_MASK     // extract fisrt wave bit
415     s_mov_b32        s_save_exec_hi, 0x0
416     s_or_b32         s_save_exec_hi, s_save_tmp, s_save_exec_hi                          // save first wave bit to s_save_exec_hi.bits[26]
417
418
419     /*          save SGPRs      */
420         // Save SGPR before LDS save, then the s0 to s4 can be used during LDS save...
421     //////////////////////////////
422
423     // SGPR SR memory offset : size(VGPR)
424     get_vgpr_size_bytes(s_save_mem_offset)
425     // TODO, change RSRC word to rearrange memory layout for SGPRS
426
427     s_getreg_b32    s_save_alloc_size, hwreg(HW_REG_GPR_ALLOC,SQ_WAVE_GPR_ALLOC_SGPR_SIZE_SHIFT,SQ_WAVE_GPR_ALLOC_SGPR_SIZE_SIZE)               //spgr_size
428     s_add_u32       s_save_alloc_size, s_save_alloc_size, 1
429     s_lshl_b32      s_save_alloc_size, s_save_alloc_size, 4                         //Number of SGPRs = (sgpr_size + 1) * 16   (non-zero value)
430
431         s_lshl_b32      s_save_buf_rsrc2,   s_save_alloc_size, 2                    //NUM_RECORDS in bytes
432
433         s_mov_b32       s_save_buf_rsrc2,  0x1000000                                //NUM_RECORDS in bytes
434
435
436     // backup s_save_buf_rsrc0,1 to s_save_pc_lo/hi, since write_16sgpr_to_mem function will change the rsrc0
437     //s_mov_b64 s_save_pc_lo, s_save_buf_rsrc0
438     s_mov_b64 s_save_xnack_mask_lo, s_save_buf_rsrc0
439     s_add_u32 s_save_buf_rsrc0, s_save_buf_rsrc0, s_save_mem_offset
440     s_addc_u32 s_save_buf_rsrc1, s_save_buf_rsrc1, 0
441
442     s_mov_b32       m0, 0x0                         //SGPR initial index value =0
443     s_nop           0x0                             //Manually inserted wait states
444   L_SAVE_SGPR_LOOP:
445     // SGPR is allocated in 16 SGPR granularity
446     s_movrels_b64   s0, s0     //s0 = s[0+m0], s1 = s[1+m0]
447     s_movrels_b64   s2, s2     //s2 = s[2+m0], s3 = s[3+m0]
448     s_movrels_b64   s4, s4     //s4 = s[4+m0], s5 = s[5+m0]
449     s_movrels_b64   s6, s6     //s6 = s[6+m0], s7 = s[7+m0]
450     s_movrels_b64   s8, s8     //s8 = s[8+m0], s9 = s[9+m0]
451     s_movrels_b64   s10, s10   //s10 = s[10+m0], s11 = s[11+m0]
452     s_movrels_b64   s12, s12   //s12 = s[12+m0], s13 = s[13+m0]
453     s_movrels_b64   s14, s14   //s14 = s[14+m0], s15 = s[15+m0]
454
455     write_16sgpr_to_mem(s0, s_save_buf_rsrc0, s_save_mem_offset) //PV: the best performance should be using s_buffer_store_dwordx4
456     s_add_u32       m0, m0, 16                                                      //next sgpr index
457     s_cmp_lt_u32    m0, s_save_alloc_size                                           //scc = (m0 < s_save_alloc_size) ? 1 : 0
458     s_cbranch_scc1  L_SAVE_SGPR_LOOP                                    //SGPR save is complete?
459     // restore s_save_buf_rsrc0,1
460     //s_mov_b64 s_save_buf_rsrc0, s_save_pc_lo
461     s_mov_b64 s_save_buf_rsrc0, s_save_xnack_mask_lo
462
463
464
465
466     /*          save first 4 VGPR, then LDS save could use   */
467         // each wave will alloc 4 vgprs at least...
468     /////////////////////////////////////////////////////////////////////////////////////
469
470     s_mov_b32       s_save_mem_offset, 0
471     s_mov_b32       exec_lo, 0xFFFFFFFF                                             //need every thread from now on
472     s_mov_b32       exec_hi, 0xFFFFFFFF
473     s_mov_b32       xnack_mask_lo, 0x0
474     s_mov_b32       xnack_mask_hi, 0x0
475
476         s_mov_b32       s_save_buf_rsrc2,  0x1000000                                //NUM_RECORDS in bytes
477
478
479     // VGPR Allocated in 4-GPR granularity
480
481 if SAVE_AFTER_XNACK_ERROR
482         check_if_tcp_store_ok()
483         s_cbranch_scc1 L_SAVE_FIRST_VGPRS_WITH_TCP
484
485         write_vgprs_to_mem_with_sqc(v0, 4, s_save_buf_rsrc0, s_save_mem_offset)
486         s_branch L_SAVE_LDS
487
488 L_SAVE_FIRST_VGPRS_WITH_TCP:
489 end
490
491     write_4vgprs_to_mem(s_save_buf_rsrc0, s_save_mem_offset)
492
493     /*          save LDS        */
494     //////////////////////////////
495
496   L_SAVE_LDS:
497
498         // Change EXEC to all threads...
499     s_mov_b32       exec_lo, 0xFFFFFFFF   //need every thread from now on
500     s_mov_b32       exec_hi, 0xFFFFFFFF
501
502     s_getreg_b32    s_save_alloc_size, hwreg(HW_REG_LDS_ALLOC,SQ_WAVE_LDS_ALLOC_LDS_SIZE_SHIFT,SQ_WAVE_LDS_ALLOC_LDS_SIZE_SIZE)             //lds_size
503     s_and_b32       s_save_alloc_size, s_save_alloc_size, 0xFFFFFFFF                //lds_size is zero?
504     s_cbranch_scc0  L_SAVE_LDS_DONE                                                                            //no lds used? jump to L_SAVE_DONE
505
506     s_barrier               //LDS is used? wait for other waves in the same TG
507     s_and_b32       s_save_tmp, s_save_exec_hi, S_SAVE_SPI_INIT_FIRST_WAVE_MASK                //exec is still used here
508     s_cbranch_scc0  L_SAVE_LDS_DONE
509
510         // first wave do LDS save;
511
512     s_lshl_b32      s_save_alloc_size, s_save_alloc_size, 6                         //LDS size in dwords = lds_size * 64dw
513     s_lshl_b32      s_save_alloc_size, s_save_alloc_size, 2                         //LDS size in bytes
514     s_mov_b32       s_save_buf_rsrc2,  s_save_alloc_size                            //NUM_RECORDS in bytes
515
516     // LDS at offset: size(VGPR)+SIZE(SGPR)+SIZE(HWREG)
517     //
518     get_vgpr_size_bytes(s_save_mem_offset)
519     get_sgpr_size_bytes(s_save_tmp)
520     s_add_u32  s_save_mem_offset, s_save_mem_offset, s_save_tmp
521     s_add_u32 s_save_mem_offset, s_save_mem_offset, get_hwreg_size_bytes()
522
523
524         s_mov_b32       s_save_buf_rsrc2,  0x1000000                  //NUM_RECORDS in bytes
525
526     s_mov_b32       m0, 0x0                                               //lds_offset initial value = 0
527
528
529       v_mbcnt_lo_u32_b32 v2, 0xffffffff, 0x0
530       v_mbcnt_hi_u32_b32 v3, 0xffffffff, v2     // tid
531
532 if SAVE_AFTER_XNACK_ERROR
533         check_if_tcp_store_ok()
534         s_cbranch_scc1 L_SAVE_LDS_WITH_TCP
535
536         v_lshlrev_b32 v2, 2, v3
537 L_SAVE_LDS_LOOP_SQC:
538         ds_read2_b32 v[0:1], v2 offset0:0 offset1:0x40
539         s_waitcnt lgkmcnt(0)
540
541         write_vgprs_to_mem_with_sqc(v0, 2, s_save_buf_rsrc0, s_save_mem_offset)
542
543         v_add_u32 v2, 0x200, v2
544         v_cmp_lt_u32 vcc[0:1], v2, s_save_alloc_size
545         s_cbranch_vccnz L_SAVE_LDS_LOOP_SQC
546
547         s_branch L_SAVE_LDS_DONE
548
549 L_SAVE_LDS_WITH_TCP:
550 end
551
552       v_mul_i32_i24 v2, v3, 8   // tid*8
553       v_mov_b32 v3, 256*2
554       s_mov_b32 m0, 0x10000
555       s_mov_b32 s0, s_save_buf_rsrc3
556       s_and_b32 s_save_buf_rsrc3, s_save_buf_rsrc3, 0xFF7FFFFF    // disable add_tid
557       s_or_b32 s_save_buf_rsrc3, s_save_buf_rsrc3, 0x58000   //DFMT
558
559 L_SAVE_LDS_LOOP_VECTOR:
560       ds_read_b64 v[0:1], v2    //x =LDS[a], byte address
561       s_waitcnt lgkmcnt(0)
562       buffer_store_dwordx2  v[0:1], v2, s_save_buf_rsrc0, s_save_mem_offset offen:1  glc:1  slc:1
563 //      s_waitcnt vmcnt(0)
564 //      v_add_u32 v2, vcc[0:1], v2, v3
565       v_add_u32 v2, v2, v3
566       v_cmp_lt_u32 vcc[0:1], v2, s_save_alloc_size
567       s_cbranch_vccnz L_SAVE_LDS_LOOP_VECTOR
568
569       // restore rsrc3
570       s_mov_b32 s_save_buf_rsrc3, s0
571
572 L_SAVE_LDS_DONE:
573
574
575     /*          save VGPRs  - set the Rest VGPRs        */
576     //////////////////////////////////////////////////////////////////////////////////////
577   L_SAVE_VGPR:
578     // VGPR SR memory offset: 0
579     // TODO rearrange the RSRC words to use swizzle for VGPR save...
580
581     s_mov_b32       s_save_mem_offset, (0+256*4)                                    // for the rest VGPRs
582     s_mov_b32       exec_lo, 0xFFFFFFFF                                             //need every thread from now on
583     s_mov_b32       exec_hi, 0xFFFFFFFF
584
585     get_num_arch_vgprs(s_save_alloc_size)
586     s_mov_b32       s_save_buf_rsrc2,  0x1000000                                    //NUM_RECORDS in bytes
587
588
589     // VGPR store using dw burst
590     s_mov_b32         m0, 0x4   //VGPR initial index value =0
591     s_cmp_lt_u32      m0, s_save_alloc_size
592     s_cbranch_scc0    L_SAVE_VGPR_END
593
594
595     s_set_gpr_idx_on    m0, 0x1 //M0[7:0] = M0[7:0] and M0[15:12] = 0x1
596     s_add_u32       s_save_alloc_size, s_save_alloc_size, 0x1000                    //add 0x1000 since we compare m0 against it later
597
598 if SAVE_AFTER_XNACK_ERROR
599         check_if_tcp_store_ok()
600         s_cbranch_scc1 L_SAVE_VGPR_LOOP
601
602 L_SAVE_VGPR_LOOP_SQC:
603         write_vgprs_to_mem_with_sqc(v0, 4, s_save_buf_rsrc0, s_save_mem_offset)
604
605         s_add_u32 m0, m0, 4
606         s_cmp_lt_u32 m0, s_save_alloc_size
607         s_cbranch_scc1 L_SAVE_VGPR_LOOP_SQC
608
609         s_set_gpr_idx_off
610         s_branch L_SAVE_VGPR_END
611 end
612
613   L_SAVE_VGPR_LOOP:
614     v_mov_b32       v0, v0              //v0 = v[0+m0]
615     v_mov_b32       v1, v1              //v0 = v[0+m0]
616     v_mov_b32       v2, v2              //v0 = v[0+m0]
617     v_mov_b32       v3, v3              //v0 = v[0+m0]
618
619     write_4vgprs_to_mem(s_save_buf_rsrc0, s_save_mem_offset)
620
621     s_add_u32       m0, m0, 4                                                       //next vgpr index
622     s_add_u32       s_save_mem_offset, s_save_mem_offset, 256*4                     //every buffer_store_dword does 256 bytes
623     s_cmp_lt_u32    m0, s_save_alloc_size                                           //scc = (m0 < s_save_alloc_size) ? 1 : 0
624     s_cbranch_scc1  L_SAVE_VGPR_LOOP                                                //VGPR save is complete?
625     s_set_gpr_idx_off
626
627 L_SAVE_VGPR_END:
628
629 #if ASIC_FAMILY >= CHIP_ARCTURUS
630     // Save ACC VGPRs
631
632 #if ASIC_FAMILY >= CHIP_ALDEBARAN
633     // ACC VGPR count may differ from ARCH VGPR count.
634     get_num_acc_vgprs(s_save_alloc_size, s_save_tmp)
635     s_and_b32       s_save_alloc_size, s_save_alloc_size, s_save_alloc_size
636     s_cbranch_scc0  L_SAVE_ACCVGPR_END
637     s_add_u32       s_save_alloc_size, s_save_alloc_size, 0x1000                    //add 0x1000 since we compare m0 against it later
638 #endif
639
640     s_mov_b32 m0, 0x0 //VGPR initial index value =0
641     s_set_gpr_idx_on m0, 0x1 //M0[7:0] = M0[7:0] and M0[15:12] = 0x1
642
643 if SAVE_AFTER_XNACK_ERROR
644     check_if_tcp_store_ok()
645     s_cbranch_scc1 L_SAVE_ACCVGPR_LOOP
646
647 L_SAVE_ACCVGPR_LOOP_SQC:
648     for var vgpr = 0; vgpr < 4; ++ vgpr
649         v_accvgpr_read v[vgpr], acc[vgpr]  // v[N] = acc[N+m0]
650     end
651
652     write_vgprs_to_mem_with_sqc(v0, 4, s_save_buf_rsrc0, s_save_mem_offset)
653
654     s_add_u32 m0, m0, 4
655     s_cmp_lt_u32 m0, s_save_alloc_size
656     s_cbranch_scc1 L_SAVE_ACCVGPR_LOOP_SQC
657
658     s_set_gpr_idx_off
659     s_branch L_SAVE_ACCVGPR_END
660 end
661
662 L_SAVE_ACCVGPR_LOOP:
663     for var vgpr = 0; vgpr < 4; ++ vgpr
664         v_accvgpr_read v[vgpr], acc[vgpr]  // v[N] = acc[N+m0]
665     end
666
667     write_4vgprs_to_mem(s_save_buf_rsrc0, s_save_mem_offset)
668
669     s_add_u32 m0, m0, 4
670     s_add_u32 s_save_mem_offset, s_save_mem_offset, 256*4
671     s_cmp_lt_u32 m0, s_save_alloc_size
672     s_cbranch_scc1 L_SAVE_ACCVGPR_LOOP
673     s_set_gpr_idx_off
674
675 L_SAVE_ACCVGPR_END:
676 #endif
677
678     s_branch    L_END_PGM
679
680
681
682 /**************************************************************************/
683 /*                      restore routine                                   */
684 /**************************************************************************/
685
686 L_RESTORE:
687     /*      Setup Resource Contants    */
688     s_mov_b32       s_restore_buf_rsrc0,    s_restore_spi_init_lo                                                           //base_addr_lo
689     s_and_b32       s_restore_buf_rsrc1,    s_restore_spi_init_hi, 0x0000FFFF                                               //base_addr_hi
690     s_or_b32        s_restore_buf_rsrc1,    s_restore_buf_rsrc1,  S_RESTORE_BUF_RSRC_WORD1_STRIDE
691     s_mov_b32       s_restore_buf_rsrc2,    0                                                                               //NUM_RECORDS initial value = 0 (in bytes)
692     s_mov_b32       s_restore_buf_rsrc3,    S_RESTORE_BUF_RSRC_WORD3_MISC
693     s_and_b32       s_restore_tmp,          s_restore_spi_init_hi, S_RESTORE_SPI_INIT_ATC_MASK
694     s_lshr_b32      s_restore_tmp,          s_restore_tmp, (S_RESTORE_SPI_INIT_ATC_SHIFT-SQ_BUF_RSRC_WORD1_ATC_SHIFT)       //get ATC bit into position
695     s_or_b32        s_restore_buf_rsrc3,    s_restore_buf_rsrc3,  s_restore_tmp                                             //or ATC
696     s_and_b32       s_restore_tmp,          s_restore_spi_init_hi, S_RESTORE_SPI_INIT_MTYPE_MASK
697     s_lshr_b32      s_restore_tmp,          s_restore_tmp, (S_RESTORE_SPI_INIT_MTYPE_SHIFT-SQ_BUF_RSRC_WORD3_MTYPE_SHIFT)   //get MTYPE bits into position
698     s_or_b32        s_restore_buf_rsrc3,    s_restore_buf_rsrc3,  s_restore_tmp                                             //or MTYPE
699
700     /*      global mem offset           */
701 //  s_mov_b32       s_restore_mem_offset, 0x0                               //mem offset initial value = 0
702
703     /*      the first wave in the threadgroup    */
704     s_and_b32       s_restore_tmp, s_restore_spi_init_hi, S_RESTORE_SPI_INIT_FIRST_WAVE_MASK
705     s_cbranch_scc0  L_RESTORE_VGPR
706
707     /*          restore LDS     */
708     //////////////////////////////
709   L_RESTORE_LDS:
710
711     s_mov_b32       exec_lo, 0xFFFFFFFF                                                     //need every thread from now on   //be consistent with SAVE although can be moved ahead
712     s_mov_b32       exec_hi, 0xFFFFFFFF
713
714     s_getreg_b32    s_restore_alloc_size, hwreg(HW_REG_LDS_ALLOC,SQ_WAVE_LDS_ALLOC_LDS_SIZE_SHIFT,SQ_WAVE_LDS_ALLOC_LDS_SIZE_SIZE)              //lds_size
715     s_and_b32       s_restore_alloc_size, s_restore_alloc_size, 0xFFFFFFFF                  //lds_size is zero?
716     s_cbranch_scc0  L_RESTORE_VGPR                                                          //no lds used? jump to L_RESTORE_VGPR
717     s_lshl_b32      s_restore_alloc_size, s_restore_alloc_size, 6                           //LDS size in dwords = lds_size * 64dw
718     s_lshl_b32      s_restore_alloc_size, s_restore_alloc_size, 2                           //LDS size in bytes
719     s_mov_b32       s_restore_buf_rsrc2,    s_restore_alloc_size                            //NUM_RECORDS in bytes
720
721     // LDS at offset: size(VGPR)+SIZE(SGPR)+SIZE(HWREG)
722     //
723     get_vgpr_size_bytes(s_restore_mem_offset)
724     get_sgpr_size_bytes(s_restore_tmp)
725     s_add_u32  s_restore_mem_offset, s_restore_mem_offset, s_restore_tmp
726     s_add_u32  s_restore_mem_offset, s_restore_mem_offset, get_hwreg_size_bytes()            //FIXME, Check if offset overflow???
727
728
729         s_mov_b32       s_restore_buf_rsrc2,  0x1000000                                     //NUM_RECORDS in bytes
730     s_mov_b32       m0, 0x0                                                                 //lds_offset initial value = 0
731
732   L_RESTORE_LDS_LOOP:
733         buffer_load_dword   v0, v0, s_restore_buf_rsrc0, s_restore_mem_offset lds:1                    // first 64DW
734         buffer_load_dword   v0, v0, s_restore_buf_rsrc0, s_restore_mem_offset lds:1 offset:256         // second 64DW
735     s_add_u32       m0, m0, 256*2                                               // 128 DW
736     s_add_u32       s_restore_mem_offset, s_restore_mem_offset, 256*2           //mem offset increased by 128DW
737     s_cmp_lt_u32    m0, s_restore_alloc_size                                    //scc=(m0 < s_restore_alloc_size) ? 1 : 0
738     s_cbranch_scc1  L_RESTORE_LDS_LOOP                                                      //LDS restore is complete?
739
740
741     /*          restore VGPRs       */
742     //////////////////////////////
743   L_RESTORE_VGPR:
744     s_mov_b32       exec_lo, 0xFFFFFFFF                                                     //need every thread from now on   //be consistent with SAVE although can be moved ahead
745     s_mov_b32       exec_hi, 0xFFFFFFFF
746     s_mov_b32       s_restore_buf_rsrc2,  0x1000000                                         //NUM_RECORDS in bytes
747
748     // Save ARCH VGPRs 4-N, then all ACC VGPRs, then ARCH VGPRs 0-3.
749     get_num_arch_vgprs(s_restore_alloc_size)
750     s_add_u32       s_restore_alloc_size, s_restore_alloc_size, 0x8000                      //add 0x8000 since we compare m0 against it later
751
752     // ARCH VGPRs at offset: 0
753     s_mov_b32       s_restore_mem_offset, 0x0
754     s_mov_b32       s_restore_mem_offset_save, s_restore_mem_offset     // restore start with v1, v0 will be the last
755     s_add_u32       s_restore_mem_offset, s_restore_mem_offset, 256*4
756     s_mov_b32       m0, 4                               //VGPR initial index value = 1
757     s_set_gpr_idx_on    m0, 0x8                                                             //M0[7:0] = M0[7:0] and M0[15:12] = 0x8
758
759   L_RESTORE_VGPR_LOOP:
760     read_4vgprs_from_mem(s_restore_buf_rsrc0, s_restore_mem_offset)
761     v_mov_b32       v0, v0                                                                  //v[0+m0] = v0
762     v_mov_b32       v1, v1
763     v_mov_b32       v2, v2
764     v_mov_b32       v3, v3
765     s_add_u32       m0, m0, 4                                                               //next vgpr index
766     s_add_u32       s_restore_mem_offset, s_restore_mem_offset, 256*4                           //every buffer_load_dword does 256 bytes
767     s_cmp_lt_u32    m0, s_restore_alloc_size                                                //scc = (m0 < s_restore_alloc_size) ? 1 : 0
768     s_cbranch_scc1  L_RESTORE_VGPR_LOOP                                                     //VGPR restore (except v0) is complete?
769
770 #if ASIC_FAMILY >= CHIP_ALDEBARAN
771     // ACC VGPR count may differ from ARCH VGPR count.
772     get_num_acc_vgprs(s_restore_alloc_size, s_restore_tmp2)
773     s_and_b32       s_restore_alloc_size, s_restore_alloc_size, s_restore_alloc_size
774     s_cbranch_scc0  L_RESTORE_ACCVGPR_END
775     s_add_u32       s_restore_alloc_size, s_restore_alloc_size, 0x8000                      //add 0x8000 since we compare m0 against it later
776 #endif
777
778 #if ASIC_FAMILY >= CHIP_ARCTURUS
779     // ACC VGPRs at offset: size(ARCH VGPRs)
780     s_mov_b32       m0, 0
781     s_set_gpr_idx_on    m0, 0x8                                                             //M0[7:0] = M0[7:0] and M0[15:12] = 0x8
782
783   L_RESTORE_ACCVGPR_LOOP:
784     read_4vgprs_from_mem(s_restore_buf_rsrc0, s_restore_mem_offset)
785
786     for var vgpr = 0; vgpr < 4; ++ vgpr
787         v_accvgpr_write acc[vgpr], v[vgpr]
788     end
789
790     s_add_u32       m0, m0, 4                                                               //next vgpr index
791     s_add_u32       s_restore_mem_offset, s_restore_mem_offset, 256*4                       //every buffer_load_dword does 256 bytes
792     s_cmp_lt_u32    m0, s_restore_alloc_size                                                //scc = (m0 < s_restore_alloc_size) ? 1 : 0
793     s_cbranch_scc1  L_RESTORE_ACCVGPR_LOOP                                                  //VGPR restore (except v0) is complete?
794   L_RESTORE_ACCVGPR_END:
795 #endif
796
797     s_set_gpr_idx_off
798
799     // Restore VGPRs 0-3 last, no longer needed.
800     read_4vgprs_from_mem(s_restore_buf_rsrc0, s_restore_mem_offset_save)
801
802     /*          restore SGPRs       */
803     //////////////////////////////
804
805     // SGPR SR memory offset : size(VGPR)
806     get_vgpr_size_bytes(s_restore_mem_offset)
807     get_sgpr_size_bytes(s_restore_tmp)
808     s_add_u32 s_restore_mem_offset, s_restore_mem_offset, s_restore_tmp
809     s_sub_u32 s_restore_mem_offset, s_restore_mem_offset, 16*4     // restore SGPR from S[n] to S[0], by 16 sgprs group
810     // TODO, change RSRC word to rearrange memory layout for SGPRS
811
812     s_getreg_b32    s_restore_alloc_size, hwreg(HW_REG_GPR_ALLOC,SQ_WAVE_GPR_ALLOC_SGPR_SIZE_SHIFT,SQ_WAVE_GPR_ALLOC_SGPR_SIZE_SIZE)                //spgr_size
813     s_add_u32       s_restore_alloc_size, s_restore_alloc_size, 1
814     s_lshl_b32      s_restore_alloc_size, s_restore_alloc_size, 4                           //Number of SGPRs = (sgpr_size + 1) * 16   (non-zero value)
815
816         s_lshl_b32      s_restore_buf_rsrc2,    s_restore_alloc_size, 2                     //NUM_RECORDS in bytes
817         s_mov_b32       s_restore_buf_rsrc2,  0x1000000                                     //NUM_RECORDS in bytes
818
819     s_mov_b32 m0, s_restore_alloc_size
820
821  L_RESTORE_SGPR_LOOP:
822     read_16sgpr_from_mem(s0, s_restore_buf_rsrc0, s_restore_mem_offset)  //PV: further performance improvement can be made
823     s_waitcnt       lgkmcnt(0)                                                              //ensure data ready
824
825     s_sub_u32 m0, m0, 16    // Restore from S[n] to S[0]
826     s_nop 0 // hazard SALU M0=> S_MOVREL
827
828     s_movreld_b64   s0, s0      //s[0+m0] = s0
829     s_movreld_b64   s2, s2
830     s_movreld_b64   s4, s4
831     s_movreld_b64   s6, s6
832     s_movreld_b64   s8, s8
833     s_movreld_b64   s10, s10
834     s_movreld_b64   s12, s12
835     s_movreld_b64   s14, s14
836
837     s_cmp_eq_u32    m0, 0               //scc = (m0 < s_restore_alloc_size) ? 1 : 0
838     s_cbranch_scc0  L_RESTORE_SGPR_LOOP             //SGPR restore (except s0) is complete?
839
840     /*      restore HW registers    */
841     //////////////////////////////
842   L_RESTORE_HWREG:
843
844
845     // HWREG SR memory offset : size(VGPR)+size(SGPR)
846     get_vgpr_size_bytes(s_restore_mem_offset)
847     get_sgpr_size_bytes(s_restore_tmp)
848     s_add_u32 s_restore_mem_offset, s_restore_mem_offset, s_restore_tmp
849
850
851     s_mov_b32       s_restore_buf_rsrc2, 0x4                                                //NUM_RECORDS   in bytes
852         s_mov_b32       s_restore_buf_rsrc2,  0x1000000                                     //NUM_RECORDS in bytes
853
854     read_hwreg_from_mem(s_restore_m0, s_restore_buf_rsrc0, s_restore_mem_offset)                    //M0
855     read_hwreg_from_mem(s_restore_pc_lo, s_restore_buf_rsrc0, s_restore_mem_offset)             //PC
856     read_hwreg_from_mem(s_restore_pc_hi, s_restore_buf_rsrc0, s_restore_mem_offset)
857     read_hwreg_from_mem(s_restore_exec_lo, s_restore_buf_rsrc0, s_restore_mem_offset)               //EXEC
858     read_hwreg_from_mem(s_restore_exec_hi, s_restore_buf_rsrc0, s_restore_mem_offset)
859     read_hwreg_from_mem(s_restore_status, s_restore_buf_rsrc0, s_restore_mem_offset)                //STATUS
860     read_hwreg_from_mem(s_restore_trapsts, s_restore_buf_rsrc0, s_restore_mem_offset)               //TRAPSTS
861     read_hwreg_from_mem(xnack_mask_lo, s_restore_buf_rsrc0, s_restore_mem_offset)                   //XNACK_MASK_LO
862     read_hwreg_from_mem(xnack_mask_hi, s_restore_buf_rsrc0, s_restore_mem_offset)                   //XNACK_MASK_HI
863     read_hwreg_from_mem(s_restore_mode, s_restore_buf_rsrc0, s_restore_mem_offset)              //MODE
864
865     s_waitcnt       lgkmcnt(0)                                                                                      //from now on, it is safe to restore STATUS and IB_STS
866
867     s_mov_b32       m0,         s_restore_m0
868     s_mov_b32       exec_lo,    s_restore_exec_lo
869     s_mov_b32       exec_hi,    s_restore_exec_hi
870
871     s_and_b32       s_restore_m0, SQ_WAVE_TRAPSTS_PRE_SAVECTX_MASK, s_restore_trapsts
872     s_setreg_b32    hwreg(HW_REG_TRAPSTS, SQ_WAVE_TRAPSTS_PRE_SAVECTX_SHIFT, SQ_WAVE_TRAPSTS_PRE_SAVECTX_SIZE), s_restore_m0
873     s_and_b32       s_restore_m0, SQ_WAVE_TRAPSTS_POST_SAVECTX_MASK, s_restore_trapsts
874     s_lshr_b32      s_restore_m0, s_restore_m0, SQ_WAVE_TRAPSTS_POST_SAVECTX_SHIFT
875     s_setreg_b32    hwreg(HW_REG_TRAPSTS, SQ_WAVE_TRAPSTS_POST_SAVECTX_SHIFT, SQ_WAVE_TRAPSTS_POST_SAVECTX_SIZE), s_restore_m0
876     //s_setreg_b32  hwreg(HW_REG_TRAPSTS),  s_restore_trapsts      //don't overwrite SAVECTX bit as it may be set through external SAVECTX during restore
877     s_setreg_b32    hwreg(HW_REG_MODE),     s_restore_mode
878
879     // Restore trap temporaries 4-11, 13 initialized by SPI debug dispatch logic
880     // ttmp SR memory offset : size(VGPR)+size(SGPR)+0x40
881     get_vgpr_size_bytes(s_restore_ttmps_lo)
882     get_sgpr_size_bytes(s_restore_ttmps_hi)
883     s_add_u32       s_restore_ttmps_lo, s_restore_ttmps_lo, s_restore_ttmps_hi
884     s_add_u32       s_restore_ttmps_lo, s_restore_ttmps_lo, s_restore_buf_rsrc0
885     s_addc_u32      s_restore_ttmps_hi, s_restore_buf_rsrc1, 0x0
886     s_and_b32       s_restore_ttmps_hi, s_restore_ttmps_hi, 0xFFFF
887     s_load_dwordx4  [ttmp4, ttmp5, ttmp6, ttmp7], [s_restore_ttmps_lo, s_restore_ttmps_hi], 0x50 glc:1
888     s_load_dwordx4  [ttmp8, ttmp9, ttmp10, ttmp11], [s_restore_ttmps_lo, s_restore_ttmps_hi], 0x60 glc:1
889     s_load_dword    ttmp13, [s_restore_ttmps_lo, s_restore_ttmps_hi], 0x74 glc:1
890     s_waitcnt       lgkmcnt(0)
891
892     //reuse s_restore_m0 as a temp register
893     s_and_b32       s_restore_m0, s_restore_pc_hi, S_SAVE_PC_HI_RCNT_MASK
894     s_lshr_b32      s_restore_m0, s_restore_m0, S_SAVE_PC_HI_RCNT_SHIFT
895     s_lshl_b32      s_restore_m0, s_restore_m0, SQ_WAVE_IB_STS_RCNT_SHIFT
896     s_mov_b32       s_restore_tmp, 0x0                                                                              //IB_STS is zero
897     s_or_b32        s_restore_tmp, s_restore_tmp, s_restore_m0
898     s_and_b32       s_restore_m0, s_restore_pc_hi, S_SAVE_PC_HI_FIRST_REPLAY_MASK
899     s_lshr_b32      s_restore_m0, s_restore_m0, S_SAVE_PC_HI_FIRST_REPLAY_SHIFT
900     s_lshl_b32      s_restore_m0, s_restore_m0, SQ_WAVE_IB_STS_FIRST_REPLAY_SHIFT
901     s_or_b32        s_restore_tmp, s_restore_tmp, s_restore_m0
902     s_and_b32       s_restore_m0, s_restore_status, SQ_WAVE_STATUS_INST_ATC_MASK
903     s_lshr_b32      s_restore_m0, s_restore_m0, SQ_WAVE_STATUS_INST_ATC_SHIFT
904     s_setreg_b32    hwreg(HW_REG_IB_STS),   s_restore_tmp
905
906     s_and_b32 s_restore_pc_hi, s_restore_pc_hi, 0x0000ffff      //pc[47:32]        //Do it here in order not to affect STATUS
907     s_and_b64    exec, exec, exec  // Restore STATUS.EXECZ, not writable by s_setreg_b32
908     s_and_b64    vcc, vcc, vcc  // Restore STATUS.VCCZ, not writable by s_setreg_b32
909     set_status_without_spi_prio(s_restore_status, s_restore_tmp) // SCC is included, which is changed by previous salu
910
911     s_barrier                                                   //barrier to ensure the readiness of LDS before access attempts from any other wave in the same TG //FIXME not performance-optimal at this time
912
913 //  s_rfe_b64 s_restore_pc_lo                                   //Return to the main shader program and resume execution
914     s_rfe_restore_b64  s_restore_pc_lo, s_restore_m0            // s_restore_m0[0] is used to set STATUS.inst_atc
915
916
917 /**************************************************************************/
918 /*                      the END                                           */
919 /**************************************************************************/
920 L_END_PGM:
921     s_endpgm
922
923 end
924
925
926 /**************************************************************************/
927 /*                      the helper functions                              */
928 /**************************************************************************/
929
930 //Only for save hwreg to mem
931 function write_hwreg_to_mem(s, s_rsrc, s_mem_offset)
932         s_mov_b32 exec_lo, m0                   //assuming exec_lo is not needed anymore from this point on
933         s_mov_b32 m0, s_mem_offset
934         s_buffer_store_dword s, s_rsrc, m0      glc:1
935         ack_sqc_store_workaround()
936         s_add_u32       s_mem_offset, s_mem_offset, 4
937         s_mov_b32   m0, exec_lo
938 end
939
940
941 // HWREG are saved before SGPRs, so all HWREG could be use.
942 function write_16sgpr_to_mem(s, s_rsrc, s_mem_offset)
943
944         s_buffer_store_dwordx4 s[0], s_rsrc, 0  glc:1
945         ack_sqc_store_workaround()
946         s_buffer_store_dwordx4 s[4], s_rsrc, 16  glc:1
947         ack_sqc_store_workaround()
948         s_buffer_store_dwordx4 s[8], s_rsrc, 32  glc:1
949         ack_sqc_store_workaround()
950         s_buffer_store_dwordx4 s[12], s_rsrc, 48 glc:1
951         ack_sqc_store_workaround()
952         s_add_u32       s_rsrc[0], s_rsrc[0], 4*16
953         s_addc_u32      s_rsrc[1], s_rsrc[1], 0x0             // +scc
954 end
955
956
957 function read_hwreg_from_mem(s, s_rsrc, s_mem_offset)
958     s_buffer_load_dword s, s_rsrc, s_mem_offset     glc:1
959     s_add_u32       s_mem_offset, s_mem_offset, 4
960 end
961
962 function read_16sgpr_from_mem(s, s_rsrc, s_mem_offset)
963     s_buffer_load_dwordx16 s, s_rsrc, s_mem_offset      glc:1
964     s_sub_u32       s_mem_offset, s_mem_offset, 4*16
965 end
966
967 function check_if_tcp_store_ok
968         // If STATUS.ALLOW_REPLAY=0 and TRAPSTS.XNACK_ERROR=1 then TCP stores will fail.
969         s_and_b32 s_save_tmp, s_save_status, SQ_WAVE_STATUS_ALLOW_REPLAY_MASK
970         s_cbranch_scc1 L_TCP_STORE_CHECK_DONE
971
972         s_getreg_b32 s_save_tmp, hwreg(HW_REG_TRAPSTS)
973         s_andn2_b32 s_save_tmp, SQ_WAVE_TRAPSTS_XNACK_ERROR_MASK, s_save_tmp
974
975 L_TCP_STORE_CHECK_DONE:
976 end
977
978 function write_4vgprs_to_mem(s_rsrc, s_mem_offset)
979         buffer_store_dword v0, v0, s_rsrc, s_mem_offset slc:1 glc:1
980         buffer_store_dword v1, v0, s_rsrc, s_mem_offset slc:1 glc:1  offset:256
981         buffer_store_dword v2, v0, s_rsrc, s_mem_offset slc:1 glc:1  offset:256*2
982         buffer_store_dword v3, v0, s_rsrc, s_mem_offset slc:1 glc:1  offset:256*3
983 end
984
985 function read_4vgprs_from_mem(s_rsrc, s_mem_offset)
986         buffer_load_dword v0, v0, s_rsrc, s_mem_offset slc:1 glc:1
987         buffer_load_dword v1, v0, s_rsrc, s_mem_offset slc:1 glc:1 offset:256
988         buffer_load_dword v2, v0, s_rsrc, s_mem_offset slc:1 glc:1 offset:256*2
989         buffer_load_dword v3, v0, s_rsrc, s_mem_offset slc:1 glc:1 offset:256*3
990         s_waitcnt vmcnt(0)
991 end
992
993 function write_vgpr_to_mem_with_sqc(v, s_rsrc, s_mem_offset)
994         s_mov_b32 s4, 0
995
996 L_WRITE_VGPR_LANE_LOOP:
997         for var lane = 0; lane < 4; ++ lane
998                 v_readlane_b32 s[lane], v, s4
999                 s_add_u32 s4, s4, 1
1000         end
1001
1002         s_buffer_store_dwordx4 s[0:3], s_rsrc, s_mem_offset glc:1
1003         ack_sqc_store_workaround()
1004
1005         s_add_u32 s_mem_offset, s_mem_offset, 0x10
1006         s_cmp_eq_u32 s4, 0x40
1007         s_cbranch_scc0 L_WRITE_VGPR_LANE_LOOP
1008 end
1009
1010 function write_vgprs_to_mem_with_sqc(v, n_vgprs, s_rsrc, s_mem_offset)
1011         for var vgpr = 0; vgpr < n_vgprs; ++ vgpr
1012                 write_vgpr_to_mem_with_sqc(v[vgpr], s_rsrc, s_mem_offset)
1013         end
1014 end
1015
1016 function get_lds_size_bytes(s_lds_size_byte)
1017     // SQ LDS granularity is 64DW, while PGM_RSRC2.lds_size is in granularity 128DW
1018     s_getreg_b32   s_lds_size_byte, hwreg(HW_REG_LDS_ALLOC, SQ_WAVE_LDS_ALLOC_LDS_SIZE_SHIFT, SQ_WAVE_LDS_ALLOC_LDS_SIZE_SIZE)          // lds_size
1019     s_lshl_b32     s_lds_size_byte, s_lds_size_byte, 8                      //LDS size in dwords = lds_size * 64 *4Bytes    // granularity 64DW
1020 end
1021
1022 function get_vgpr_size_bytes(s_vgpr_size_byte)
1023     s_getreg_b32   s_vgpr_size_byte, hwreg(HW_REG_GPR_ALLOC,SQ_WAVE_GPR_ALLOC_VGPR_SIZE_SHIFT,SQ_WAVE_GPR_ALLOC_VGPR_SIZE_SIZE)  //vpgr_size
1024     s_add_u32      s_vgpr_size_byte, s_vgpr_size_byte, 1
1025     s_lshl_b32     s_vgpr_size_byte, s_vgpr_size_byte, (2+8) //Number of VGPRs = (vgpr_size + 1) * 4 * 64 * 4   (non-zero value)   //FIXME for GFX, zero is possible
1026
1027 #if ASIC_FAMILY >= CHIP_ARCTURUS
1028     s_lshl_b32     s_vgpr_size_byte, s_vgpr_size_byte, 1  // Double size for ACC VGPRs
1029 #endif
1030 end
1031
1032 function get_sgpr_size_bytes(s_sgpr_size_byte)
1033     s_getreg_b32   s_sgpr_size_byte, hwreg(HW_REG_GPR_ALLOC,SQ_WAVE_GPR_ALLOC_SGPR_SIZE_SHIFT,SQ_WAVE_GPR_ALLOC_SGPR_SIZE_SIZE)  //spgr_size
1034     s_add_u32      s_sgpr_size_byte, s_sgpr_size_byte, 1
1035     s_lshl_b32     s_sgpr_size_byte, s_sgpr_size_byte, 6 //Number of SGPRs = (sgpr_size + 1) * 16 *4   (non-zero value)
1036 end
1037
1038 function get_hwreg_size_bytes
1039     return 128 //HWREG size 128 bytes
1040 end
1041
1042 function get_num_arch_vgprs(s_num_arch_vgprs)
1043 #if ASIC_FAMILY >= CHIP_ALDEBARAN
1044     // VGPR count includes ACC VGPRs, use ACC VGPR offset for ARCH VGPR count.
1045     s_getreg_b32    s_num_arch_vgprs, hwreg(HW_REG_GPR_ALLOC,SQ_WAVE_GPR_ALLOC_ACCV_OFFSET_SHIFT,SQ_WAVE_GPR_ALLOC_ACCV_OFFSET_SIZE)
1046 #else
1047     s_getreg_b32    s_num_arch_vgprs, hwreg(HW_REG_GPR_ALLOC,SQ_WAVE_GPR_ALLOC_VGPR_SIZE_SHIFT,SQ_WAVE_GPR_ALLOC_VGPR_SIZE_SIZE)
1048 #endif
1049
1050     // Number of VGPRs = (vgpr_size + 1) * 4
1051     s_add_u32       s_num_arch_vgprs, s_num_arch_vgprs, 1
1052     s_lshl_b32      s_num_arch_vgprs, s_num_arch_vgprs, 2
1053 end
1054
1055 #if ASIC_FAMILY >= CHIP_ALDEBARAN
1056 function get_num_acc_vgprs(s_num_acc_vgprs, s_tmp)
1057     // VGPR count = (GPR_ALLOC.VGPR_SIZE + 1) * 8
1058     s_getreg_b32    s_num_acc_vgprs, hwreg(HW_REG_GPR_ALLOC,SQ_WAVE_GPR_ALLOC_VGPR_SIZE_SHIFT,SQ_WAVE_GPR_ALLOC_VGPR_SIZE_SIZE)
1059     s_add_u32       s_num_acc_vgprs, s_num_acc_vgprs, 1
1060     s_lshl_b32      s_num_acc_vgprs, s_num_acc_vgprs, 3
1061
1062     // ACC VGPR count = VGPR count - ARCH VGPR count.
1063     get_num_arch_vgprs(s_tmp)
1064     s_sub_u32       s_num_acc_vgprs, s_num_acc_vgprs, s_tmp
1065 end
1066 #endif
1067
1068 function ack_sqc_store_workaround
1069     if ACK_SQC_STORE
1070         s_waitcnt lgkmcnt(0)
1071     end
1072 end
1073
1074 function set_status_without_spi_prio(status, tmp)
1075     // Do not restore STATUS.SPI_PRIO since scheduler may have raised it.
1076     s_lshr_b32      tmp, status, SQ_WAVE_STATUS_POST_SPI_PRIO_SHIFT
1077     s_setreg_b32    hwreg(HW_REG_STATUS, SQ_WAVE_STATUS_POST_SPI_PRIO_SHIFT, SQ_WAVE_STATUS_POST_SPI_PRIO_SIZE), tmp
1078     s_nop           0x2 // avoid S_SETREG => S_SETREG hazard
1079     s_setreg_b32    hwreg(HW_REG_STATUS, SQ_WAVE_STATUS_PRE_SPI_PRIO_SHIFT, SQ_WAVE_STATUS_PRE_SPI_PRIO_SIZE), status
1080 end