1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2013 Advanced Micro Devices, Inc.
3bf215546Sopenharmony_ci * All Rights Reserved.
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
8bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub
9bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom
10bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
14bf215546Sopenharmony_ci * Software.
15bf215546Sopenharmony_ci *
16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE.
23bf215546Sopenharmony_ci */
24bf215546Sopenharmony_ci
25bf215546Sopenharmony_ci/**
26bf215546Sopenharmony_ci * This file contains helpers for writing commands to commands streams.
27bf215546Sopenharmony_ci */
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci#ifndef SI_BUILD_PM4_H
30bf215546Sopenharmony_ci#define SI_BUILD_PM4_H
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "si_pipe.h"
33bf215546Sopenharmony_ci#include "sid.h"
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci#if 0
36bf215546Sopenharmony_ci#include "ac_shadowed_regs.h"
37bf215546Sopenharmony_ci#define SI_CHECK_SHADOWED_REGS(reg_offset, count) ac_check_shadowed_regs(GFX10, CHIP_NAVI14, reg_offset, count)
38bf215546Sopenharmony_ci#else
39bf215546Sopenharmony_ci#define SI_CHECK_SHADOWED_REGS(reg_offset, count)
40bf215546Sopenharmony_ci#endif
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_ci#define radeon_begin(cs) struct radeon_cmdbuf *__cs = (cs); \
43bf215546Sopenharmony_ci                         unsigned __cs_num = __cs->current.cdw; \
44bf215546Sopenharmony_ci                         UNUSED unsigned __cs_num_initial = __cs_num; \
45bf215546Sopenharmony_ci                         uint32_t *__cs_buf = __cs->current.buf
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_ci#define radeon_begin_again(cs) do { \
48bf215546Sopenharmony_ci   assert(__cs == NULL); \
49bf215546Sopenharmony_ci   __cs = (cs); \
50bf215546Sopenharmony_ci   __cs_num = __cs->current.cdw; \
51bf215546Sopenharmony_ci   __cs_num_initial = __cs_num; \
52bf215546Sopenharmony_ci   __cs_buf = __cs->current.buf; \
53bf215546Sopenharmony_ci} while (0)
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_ci#define radeon_end() do { \
56bf215546Sopenharmony_ci   __cs->current.cdw = __cs_num; \
57bf215546Sopenharmony_ci   assert(__cs->current.cdw <= __cs->current.max_dw); \
58bf215546Sopenharmony_ci   __cs = NULL; \
59bf215546Sopenharmony_ci} while (0)
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci#define radeon_emit(value)  __cs_buf[__cs_num++] = (value)
62bf215546Sopenharmony_ci#define radeon_packets_added()  (__cs_num != __cs_num_initial)
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_ci#define radeon_end_update_context_roll(sctx) do { \
65bf215546Sopenharmony_ci   radeon_end(); \
66bf215546Sopenharmony_ci   if (radeon_packets_added()) \
67bf215546Sopenharmony_ci      (sctx)->context_roll = true; \
68bf215546Sopenharmony_ci} while (0)
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci#define radeon_emit_array(values, num) do { \
71bf215546Sopenharmony_ci   unsigned __n = (num); \
72bf215546Sopenharmony_ci   memcpy(__cs_buf + __cs_num, (values), __n * 4); \
73bf215546Sopenharmony_ci   __cs_num += __n; \
74bf215546Sopenharmony_ci} while (0)
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci#define radeon_set_config_reg_seq(reg, num) do { \
77bf215546Sopenharmony_ci   SI_CHECK_SHADOWED_REGS(reg, num); \
78bf215546Sopenharmony_ci   assert((reg) < SI_CONTEXT_REG_OFFSET); \
79bf215546Sopenharmony_ci   radeon_emit(PKT3(PKT3_SET_CONFIG_REG, num, 0)); \
80bf215546Sopenharmony_ci   radeon_emit(((reg) - SI_CONFIG_REG_OFFSET) >> 2); \
81bf215546Sopenharmony_ci} while (0)
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci#define radeon_set_config_reg(reg, value) do { \
84bf215546Sopenharmony_ci   radeon_set_config_reg_seq(reg, 1); \
85bf215546Sopenharmony_ci   radeon_emit(value); \
86bf215546Sopenharmony_ci} while (0)
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_ci#define radeon_set_context_reg_seq(reg, num) do { \
89bf215546Sopenharmony_ci   SI_CHECK_SHADOWED_REGS(reg, num); \
90bf215546Sopenharmony_ci   assert((reg) >= SI_CONTEXT_REG_OFFSET); \
91bf215546Sopenharmony_ci   radeon_emit(PKT3(PKT3_SET_CONTEXT_REG, num, 0)); \
92bf215546Sopenharmony_ci   radeon_emit(((reg) - SI_CONTEXT_REG_OFFSET) >> 2); \
93bf215546Sopenharmony_ci} while (0)
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_ci#define radeon_set_context_reg(reg, value) do { \
96bf215546Sopenharmony_ci   radeon_set_context_reg_seq(reg, 1); \
97bf215546Sopenharmony_ci   radeon_emit(value); \
98bf215546Sopenharmony_ci} while (0)
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci#define radeon_set_context_reg_seq_array(reg, num, values) do { \
101bf215546Sopenharmony_ci   radeon_set_context_reg_seq(reg, num); \
102bf215546Sopenharmony_ci   radeon_emit_array(values, num); \
103bf215546Sopenharmony_ci} while (0)
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci#define radeon_set_context_reg_idx(reg, idx, value) do { \
106bf215546Sopenharmony_ci   SI_CHECK_SHADOWED_REGS(reg, 1); \
107bf215546Sopenharmony_ci   assert((reg) >= SI_CONTEXT_REG_OFFSET); \
108bf215546Sopenharmony_ci   radeon_emit(PKT3(PKT3_SET_CONTEXT_REG, 1, 0)); \
109bf215546Sopenharmony_ci   radeon_emit(((reg) - SI_CONTEXT_REG_OFFSET) >> 2 | ((idx) << 28)); \
110bf215546Sopenharmony_ci   radeon_emit(value); \
111bf215546Sopenharmony_ci} while (0)
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci#define radeon_set_sh_reg_seq(reg, num) do { \
114bf215546Sopenharmony_ci   SI_CHECK_SHADOWED_REGS(reg, num); \
115bf215546Sopenharmony_ci   assert((reg) >= SI_SH_REG_OFFSET && (reg) < SI_SH_REG_END); \
116bf215546Sopenharmony_ci   radeon_emit(PKT3(PKT3_SET_SH_REG, num, 0)); \
117bf215546Sopenharmony_ci   radeon_emit(((reg) - SI_SH_REG_OFFSET) >> 2); \
118bf215546Sopenharmony_ci} while (0)
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci#define radeon_set_sh_reg_idx3_seq(reg, num) do { \
121bf215546Sopenharmony_ci   SI_CHECK_SHADOWED_REGS(reg, num); \
122bf215546Sopenharmony_ci   assert((reg) >= SI_SH_REG_OFFSET && (reg) < SI_SH_REG_END); \
123bf215546Sopenharmony_ci   radeon_emit(PKT3(PKT3_SET_SH_REG_INDEX, num, 0)); \
124bf215546Sopenharmony_ci   radeon_emit((((reg) - SI_SH_REG_OFFSET) >> 2) | (3 << 28)); \
125bf215546Sopenharmony_ci} while (0)
126bf215546Sopenharmony_ci
127bf215546Sopenharmony_ci#define radeon_set_sh_reg(reg, value) do { \
128bf215546Sopenharmony_ci   radeon_set_sh_reg_seq(reg, 1); \
129bf215546Sopenharmony_ci   radeon_emit(value); \
130bf215546Sopenharmony_ci} while (0)
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci#define radeon_set_sh_reg_idx3(reg, value) do { \
133bf215546Sopenharmony_ci   radeon_set_sh_reg_idx3_seq(reg, 1); \
134bf215546Sopenharmony_ci   radeon_emit(value); \
135bf215546Sopenharmony_ci} while (0)
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci#define radeon_set_uconfig_reg_seq(reg, num, perfctr) do { \
138bf215546Sopenharmony_ci   SI_CHECK_SHADOWED_REGS(reg, num); \
139bf215546Sopenharmony_ci   assert((reg) >= CIK_UCONFIG_REG_OFFSET && (reg) < CIK_UCONFIG_REG_END); \
140bf215546Sopenharmony_ci   radeon_emit(PKT3(PKT3_SET_UCONFIG_REG, num, perfctr)); \
141bf215546Sopenharmony_ci   radeon_emit(((reg) - CIK_UCONFIG_REG_OFFSET) >> 2); \
142bf215546Sopenharmony_ci} while (0)
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci#define radeon_set_uconfig_reg(reg, value) do { \
145bf215546Sopenharmony_ci   radeon_set_uconfig_reg_seq(reg, 1, false); \
146bf215546Sopenharmony_ci   radeon_emit(value); \
147bf215546Sopenharmony_ci} while (0)
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci#define radeon_set_uconfig_reg_perfctr(reg, value) do { \
150bf215546Sopenharmony_ci   radeon_set_uconfig_reg_seq(reg, 1, true); \
151bf215546Sopenharmony_ci   radeon_emit(value); \
152bf215546Sopenharmony_ci} while (0)
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci#define radeon_set_uconfig_reg_idx(screen, gfx_level, reg, idx, value) do { \
155bf215546Sopenharmony_ci   SI_CHECK_SHADOWED_REGS(reg, 1); \
156bf215546Sopenharmony_ci   assert((reg) >= CIK_UCONFIG_REG_OFFSET && (reg) < CIK_UCONFIG_REG_END); \
157bf215546Sopenharmony_ci   assert((idx) != 0); \
158bf215546Sopenharmony_ci   unsigned __opcode = PKT3_SET_UCONFIG_REG_INDEX; \
159bf215546Sopenharmony_ci   if ((gfx_level) < GFX9 || \
160bf215546Sopenharmony_ci       ((gfx_level) == GFX9 && (screen)->info.me_fw_version < 26)) \
161bf215546Sopenharmony_ci      __opcode = PKT3_SET_UCONFIG_REG; \
162bf215546Sopenharmony_ci   radeon_emit(PKT3(__opcode, 1, 0)); \
163bf215546Sopenharmony_ci   radeon_emit(((reg) - CIK_UCONFIG_REG_OFFSET) >> 2 | ((idx) << 28)); \
164bf215546Sopenharmony_ci   radeon_emit(value); \
165bf215546Sopenharmony_ci} while (0)
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci/* Emit PKT3_SET_CONTEXT_REG if the register value is different. */
168bf215546Sopenharmony_ci#define radeon_opt_set_context_reg(sctx, offset, reg, val) do { \
169bf215546Sopenharmony_ci   unsigned __value = val; \
170bf215546Sopenharmony_ci   if (((sctx->tracked_regs.reg_saved >> (reg)) & 0x1) != 0x1 || \
171bf215546Sopenharmony_ci       sctx->tracked_regs.reg_value[reg] != __value) { \
172bf215546Sopenharmony_ci      radeon_set_context_reg(offset, __value); \
173bf215546Sopenharmony_ci      sctx->tracked_regs.reg_saved |= 0x1ull << (reg); \
174bf215546Sopenharmony_ci      sctx->tracked_regs.reg_value[reg] = __value; \
175bf215546Sopenharmony_ci   } \
176bf215546Sopenharmony_ci} while (0)
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci/**
179bf215546Sopenharmony_ci * Set 2 consecutive registers if any registers value is different.
180bf215546Sopenharmony_ci * @param offset        starting register offset
181bf215546Sopenharmony_ci * @param val1          is written to first register
182bf215546Sopenharmony_ci * @param val2          is written to second register
183bf215546Sopenharmony_ci */
184bf215546Sopenharmony_ci#define radeon_opt_set_context_reg2(sctx, offset, reg, val1, val2) do { \
185bf215546Sopenharmony_ci   unsigned __value1 = (val1), __value2 = (val2); \
186bf215546Sopenharmony_ci   if (((sctx->tracked_regs.reg_saved >> (reg)) & 0x3) != 0x3 || \
187bf215546Sopenharmony_ci       sctx->tracked_regs.reg_value[reg] != __value1 || \
188bf215546Sopenharmony_ci       sctx->tracked_regs.reg_value[(reg) + 1] != __value2) { \
189bf215546Sopenharmony_ci      radeon_set_context_reg_seq(offset, 2); \
190bf215546Sopenharmony_ci      radeon_emit(__value1); \
191bf215546Sopenharmony_ci      radeon_emit(__value2); \
192bf215546Sopenharmony_ci      sctx->tracked_regs.reg_value[reg] = __value1; \
193bf215546Sopenharmony_ci      sctx->tracked_regs.reg_value[(reg) + 1] = __value2; \
194bf215546Sopenharmony_ci      sctx->tracked_regs.reg_saved |= 0x3ull << (reg); \
195bf215546Sopenharmony_ci   } \
196bf215546Sopenharmony_ci} while (0)
197bf215546Sopenharmony_ci
198bf215546Sopenharmony_ci/**
199bf215546Sopenharmony_ci * Set 3 consecutive registers if any registers value is different.
200bf215546Sopenharmony_ci */
201bf215546Sopenharmony_ci#define radeon_opt_set_context_reg3(sctx, offset, reg, val1, val2, val3) do { \
202bf215546Sopenharmony_ci   unsigned __value1 = (val1), __value2 = (val2), __value3 = (val3); \
203bf215546Sopenharmony_ci   if (((sctx->tracked_regs.reg_saved >> (reg)) & 0x7) != 0x7 || \
204bf215546Sopenharmony_ci       sctx->tracked_regs.reg_value[reg] != __value1 || \
205bf215546Sopenharmony_ci       sctx->tracked_regs.reg_value[(reg) + 1] != __value2 || \
206bf215546Sopenharmony_ci       sctx->tracked_regs.reg_value[(reg) + 2] != __value3) { \
207bf215546Sopenharmony_ci      radeon_set_context_reg_seq(offset, 3); \
208bf215546Sopenharmony_ci      radeon_emit(__value1); \
209bf215546Sopenharmony_ci      radeon_emit(__value2); \
210bf215546Sopenharmony_ci      radeon_emit(__value3); \
211bf215546Sopenharmony_ci      sctx->tracked_regs.reg_value[reg] = __value1; \
212bf215546Sopenharmony_ci      sctx->tracked_regs.reg_value[(reg) + 1] = __value2; \
213bf215546Sopenharmony_ci      sctx->tracked_regs.reg_value[(reg) + 2] = __value3; \
214bf215546Sopenharmony_ci      sctx->tracked_regs.reg_saved |= 0x7ull << (reg); \
215bf215546Sopenharmony_ci   } \
216bf215546Sopenharmony_ci} while (0)
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci/**
219bf215546Sopenharmony_ci * Set 4 consecutive registers if any registers value is different.
220bf215546Sopenharmony_ci */
221bf215546Sopenharmony_ci#define radeon_opt_set_context_reg4(sctx, offset, reg, val1, val2, val3, val4) do { \
222bf215546Sopenharmony_ci   unsigned __value1 = (val1), __value2 = (val2), __value3 = (val3), __value4 = (val4); \
223bf215546Sopenharmony_ci   if (((sctx->tracked_regs.reg_saved >> (reg)) & 0xf) != 0xf || \
224bf215546Sopenharmony_ci       sctx->tracked_regs.reg_value[reg] != __value1 || \
225bf215546Sopenharmony_ci       sctx->tracked_regs.reg_value[(reg) + 1] != __value2 || \
226bf215546Sopenharmony_ci       sctx->tracked_regs.reg_value[(reg) + 2] != __value3 || \
227bf215546Sopenharmony_ci       sctx->tracked_regs.reg_value[(reg) + 3] != __value4) { \
228bf215546Sopenharmony_ci      radeon_set_context_reg_seq(offset, 4); \
229bf215546Sopenharmony_ci      radeon_emit(__value1); \
230bf215546Sopenharmony_ci      radeon_emit(__value2); \
231bf215546Sopenharmony_ci      radeon_emit(__value3); \
232bf215546Sopenharmony_ci      radeon_emit(__value4); \
233bf215546Sopenharmony_ci      sctx->tracked_regs.reg_value[reg] = __value1; \
234bf215546Sopenharmony_ci      sctx->tracked_regs.reg_value[(reg) + 1] = __value2; \
235bf215546Sopenharmony_ci      sctx->tracked_regs.reg_value[(reg) + 2] = __value3; \
236bf215546Sopenharmony_ci      sctx->tracked_regs.reg_value[(reg) + 3] = __value4; \
237bf215546Sopenharmony_ci      sctx->tracked_regs.reg_saved |= 0xfull << (reg); \
238bf215546Sopenharmony_ci   } \
239bf215546Sopenharmony_ci} while (0)
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_ci/**
242bf215546Sopenharmony_ci * Set consecutive registers if any registers value is different.
243bf215546Sopenharmony_ci */
244bf215546Sopenharmony_ci#define radeon_opt_set_context_regn(sctx, offset, value, saved_val, num) do { \
245bf215546Sopenharmony_ci   if (memcmp(value, saved_val, sizeof(uint32_t) * (num))) { \
246bf215546Sopenharmony_ci      radeon_set_context_reg_seq(offset, num); \
247bf215546Sopenharmony_ci      radeon_emit_array(value, num); \
248bf215546Sopenharmony_ci      memcpy(saved_val, value, sizeof(uint32_t) * (num)); \
249bf215546Sopenharmony_ci   } \
250bf215546Sopenharmony_ci} while (0)
251bf215546Sopenharmony_ci
252bf215546Sopenharmony_ci#define radeon_opt_set_sh_reg(sctx, offset, reg, val) do { \
253bf215546Sopenharmony_ci   unsigned __value = val; \
254bf215546Sopenharmony_ci   if (((sctx->tracked_regs.reg_saved >> (reg)) & 0x1) != 0x1 || \
255bf215546Sopenharmony_ci       sctx->tracked_regs.reg_value[reg] != __value) { \
256bf215546Sopenharmony_ci      radeon_set_sh_reg(offset, __value); \
257bf215546Sopenharmony_ci      sctx->tracked_regs.reg_saved |= BITFIELD64_BIT(reg); \
258bf215546Sopenharmony_ci      sctx->tracked_regs.reg_value[reg] = __value; \
259bf215546Sopenharmony_ci   } \
260bf215546Sopenharmony_ci} while (0)
261bf215546Sopenharmony_ci
262bf215546Sopenharmony_ci#define radeon_opt_set_sh_reg_idx3(sctx, offset, reg, val) do { \
263bf215546Sopenharmony_ci   unsigned __value = val; \
264bf215546Sopenharmony_ci   if (((sctx->tracked_regs.reg_saved >> (reg)) & 0x1) != 0x1 || \
265bf215546Sopenharmony_ci       sctx->tracked_regs.reg_value[reg] != __value) { \
266bf215546Sopenharmony_ci      if (sctx->gfx_level >= GFX10) \
267bf215546Sopenharmony_ci         radeon_set_sh_reg_idx3(offset, __value); \
268bf215546Sopenharmony_ci      else \
269bf215546Sopenharmony_ci         radeon_set_sh_reg(offset, __value); \
270bf215546Sopenharmony_ci      sctx->tracked_regs.reg_saved |= BITFIELD64_BIT(reg); \
271bf215546Sopenharmony_ci      sctx->tracked_regs.reg_value[reg] = __value; \
272bf215546Sopenharmony_ci   } \
273bf215546Sopenharmony_ci} while (0)
274bf215546Sopenharmony_ci
275bf215546Sopenharmony_ci#define radeon_opt_set_uconfig_reg(sctx, offset, reg, val) do { \
276bf215546Sopenharmony_ci   unsigned __value = val; \
277bf215546Sopenharmony_ci   if (((sctx->tracked_regs.reg_saved >> (reg)) & 0x1) != 0x1 || \
278bf215546Sopenharmony_ci       sctx->tracked_regs.reg_value[reg] != __value) { \
279bf215546Sopenharmony_ci      radeon_set_uconfig_reg(offset, __value); \
280bf215546Sopenharmony_ci      sctx->tracked_regs.reg_saved |= 0x1ull << (reg); \
281bf215546Sopenharmony_ci      sctx->tracked_regs.reg_value[reg] = __value; \
282bf215546Sopenharmony_ci   } \
283bf215546Sopenharmony_ci} while (0)
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_ci#define radeon_set_privileged_config_reg(reg, value) do { \
286bf215546Sopenharmony_ci   assert((reg) < CIK_UCONFIG_REG_OFFSET); \
287bf215546Sopenharmony_ci   radeon_emit(PKT3(PKT3_COPY_DATA, 4, 0)); \
288bf215546Sopenharmony_ci   radeon_emit(COPY_DATA_SRC_SEL(COPY_DATA_IMM) | \
289bf215546Sopenharmony_ci               COPY_DATA_DST_SEL(COPY_DATA_PERF)); \
290bf215546Sopenharmony_ci   radeon_emit(value); \
291bf215546Sopenharmony_ci   radeon_emit(0); /* unused */ \
292bf215546Sopenharmony_ci   radeon_emit((reg) >> 2); \
293bf215546Sopenharmony_ci   radeon_emit(0); /* unused */ \
294bf215546Sopenharmony_ci} while (0)
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_ci#define radeon_emit_32bit_pointer(sscreen, va) do { \
297bf215546Sopenharmony_ci   radeon_emit(va); \
298bf215546Sopenharmony_ci   assert((va) == 0 || ((va) >> 32) == sscreen->info.address32_hi); \
299bf215546Sopenharmony_ci} while (0)
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_ci#define radeon_emit_one_32bit_pointer(sctx, desc, sh_base) do { \
302bf215546Sopenharmony_ci   unsigned sh_offset = (sh_base) + (desc)->shader_userdata_offset; \
303bf215546Sopenharmony_ci   radeon_set_sh_reg_seq(sh_offset, 1); \
304bf215546Sopenharmony_ci   radeon_emit_32bit_pointer(sctx->screen, (desc)->gpu_address); \
305bf215546Sopenharmony_ci} while (0)
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_ci/* Wrappers that are only used when they are passed as function pointers. */
308bf215546Sopenharmony_cistatic inline void radeon_set_sh_reg_func(struct radeon_cmdbuf *cs, unsigned reg_offset,
309bf215546Sopenharmony_ci                                          uint32_t value)
310bf215546Sopenharmony_ci{
311bf215546Sopenharmony_ci   radeon_begin(cs);
312bf215546Sopenharmony_ci   radeon_set_sh_reg(reg_offset, value);
313bf215546Sopenharmony_ci   radeon_end();
314bf215546Sopenharmony_ci}
315bf215546Sopenharmony_ci
316bf215546Sopenharmony_cistatic inline void radeon_set_sh_reg_idx3_func(struct radeon_cmdbuf *cs, unsigned reg_offset,
317bf215546Sopenharmony_ci                                               uint32_t value)
318bf215546Sopenharmony_ci{
319bf215546Sopenharmony_ci   radeon_begin(cs);
320bf215546Sopenharmony_ci   radeon_set_sh_reg_idx3(reg_offset, value);
321bf215546Sopenharmony_ci   radeon_end();
322bf215546Sopenharmony_ci}
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_ci/* This should be evaluated at compile time if all parameters are constants. */
325bf215546Sopenharmony_cistatic ALWAYS_INLINE unsigned
326bf215546Sopenharmony_cisi_get_user_data_base(enum amd_gfx_level gfx_level, enum si_has_tess has_tess,
327bf215546Sopenharmony_ci                      enum si_has_gs has_gs, enum si_has_ngg ngg,
328bf215546Sopenharmony_ci                      enum pipe_shader_type shader)
329bf215546Sopenharmony_ci{
330bf215546Sopenharmony_ci   switch (shader) {
331bf215546Sopenharmony_ci   case PIPE_SHADER_VERTEX:
332bf215546Sopenharmony_ci      /* VS can be bound as VS, ES, or LS. */
333bf215546Sopenharmony_ci      if (has_tess) {
334bf215546Sopenharmony_ci         if (gfx_level >= GFX10) {
335bf215546Sopenharmony_ci            return R_00B430_SPI_SHADER_USER_DATA_HS_0;
336bf215546Sopenharmony_ci         } else if (gfx_level == GFX9) {
337bf215546Sopenharmony_ci            return R_00B430_SPI_SHADER_USER_DATA_LS_0;
338bf215546Sopenharmony_ci         } else {
339bf215546Sopenharmony_ci            return R_00B530_SPI_SHADER_USER_DATA_LS_0;
340bf215546Sopenharmony_ci         }
341bf215546Sopenharmony_ci      } else if (gfx_level >= GFX10) {
342bf215546Sopenharmony_ci         if (ngg || has_gs) {
343bf215546Sopenharmony_ci            return R_00B230_SPI_SHADER_USER_DATA_GS_0;
344bf215546Sopenharmony_ci         } else {
345bf215546Sopenharmony_ci            return R_00B130_SPI_SHADER_USER_DATA_VS_0;
346bf215546Sopenharmony_ci         }
347bf215546Sopenharmony_ci      } else if (has_gs) {
348bf215546Sopenharmony_ci         return R_00B330_SPI_SHADER_USER_DATA_ES_0;
349bf215546Sopenharmony_ci      } else {
350bf215546Sopenharmony_ci         return R_00B130_SPI_SHADER_USER_DATA_VS_0;
351bf215546Sopenharmony_ci      }
352bf215546Sopenharmony_ci
353bf215546Sopenharmony_ci   case PIPE_SHADER_TESS_CTRL:
354bf215546Sopenharmony_ci      if (gfx_level == GFX9) {
355bf215546Sopenharmony_ci         return R_00B430_SPI_SHADER_USER_DATA_LS_0;
356bf215546Sopenharmony_ci      } else {
357bf215546Sopenharmony_ci         return R_00B430_SPI_SHADER_USER_DATA_HS_0;
358bf215546Sopenharmony_ci      }
359bf215546Sopenharmony_ci
360bf215546Sopenharmony_ci   case PIPE_SHADER_TESS_EVAL:
361bf215546Sopenharmony_ci      /* TES can be bound as ES, VS, or not bound. */
362bf215546Sopenharmony_ci      if (has_tess) {
363bf215546Sopenharmony_ci         if (gfx_level >= GFX10) {
364bf215546Sopenharmony_ci            if (ngg || has_gs) {
365bf215546Sopenharmony_ci               return R_00B230_SPI_SHADER_USER_DATA_GS_0;
366bf215546Sopenharmony_ci            } else {
367bf215546Sopenharmony_ci               return R_00B130_SPI_SHADER_USER_DATA_VS_0;
368bf215546Sopenharmony_ci            }
369bf215546Sopenharmony_ci         } else if (has_gs) {
370bf215546Sopenharmony_ci            return R_00B330_SPI_SHADER_USER_DATA_ES_0;
371bf215546Sopenharmony_ci         } else {
372bf215546Sopenharmony_ci            return R_00B130_SPI_SHADER_USER_DATA_VS_0;
373bf215546Sopenharmony_ci         }
374bf215546Sopenharmony_ci      } else {
375bf215546Sopenharmony_ci         return 0;
376bf215546Sopenharmony_ci      }
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_ci   case PIPE_SHADER_GEOMETRY:
379bf215546Sopenharmony_ci      if (gfx_level == GFX9) {
380bf215546Sopenharmony_ci         return R_00B330_SPI_SHADER_USER_DATA_ES_0;
381bf215546Sopenharmony_ci      } else {
382bf215546Sopenharmony_ci         return R_00B230_SPI_SHADER_USER_DATA_GS_0;
383bf215546Sopenharmony_ci      }
384bf215546Sopenharmony_ci
385bf215546Sopenharmony_ci   default:
386bf215546Sopenharmony_ci      assert(0);
387bf215546Sopenharmony_ci      return 0;
388bf215546Sopenharmony_ci   }
389bf215546Sopenharmony_ci}
390bf215546Sopenharmony_ci
391bf215546Sopenharmony_ci#endif
392