1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2022 Imagination Technologies Ltd.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
5bf215546Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal
6bf215546Sopenharmony_ci * in the Software without restriction, including without limitation the rights
7bf215546Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8bf215546Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is
9bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18bf215546Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21bf215546Sopenharmony_ci * SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include <assert.h>
25bf215546Sopenharmony_ci#include <stdbool.h>
26bf215546Sopenharmony_ci#include <stdint.h>
27bf215546Sopenharmony_ci#include <stdio.h>
28bf215546Sopenharmony_ci#include <string.h>
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci#include "pvr_device_info.h"
31bf215546Sopenharmony_ci#include "pvr_pds.h"
32bf215546Sopenharmony_ci#include "pvr_rogue_pds_defs.h"
33bf215546Sopenharmony_ci#include "pvr_rogue_pds_disasm.h"
34bf215546Sopenharmony_ci#include "pvr_rogue_pds_encode.h"
35bf215546Sopenharmony_ci#include "util/log.h"
36bf215546Sopenharmony_ci#include "util/macros.h"
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci#define R32_C(x) ((x) + PVR_ROGUE_PDSINST_REGS32_CONST32_LOWER)
39bf215546Sopenharmony_ci#define R32_T(x) ((x) + PVR_ROGUE_PDSINST_REGS32_TEMP32_LOWER)
40bf215546Sopenharmony_ci#define R32_P(x) ((x) + PVR_ROGUE_PDSINST_REGS32_PTEMP32_LOWER)
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_ci#define R32TP_T(x) ((x) + PVR_ROGUE_PDSINST_REGS32TP_TEMP32_LOWER)
43bf215546Sopenharmony_ci#define R32TP_P(x) ((x) + PVR_ROGUE_PDSINST_REGS32TP_PTEMP32_LOWER)
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci#define R64_C(x) ((x) + PVR_ROGUE_PDSINST_REGS64_CONST64_LOWER)
46bf215546Sopenharmony_ci#define R64_T(x) ((x) + PVR_ROGUE_PDSINST_REGS64_TEMP64_LOWER)
47bf215546Sopenharmony_ci#define R64_P(x) ((x) + PVR_ROGUE_PDSINST_REGS64_PTEMP64_LOWER)
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci#define R64TP_T(x) ((x) + PVR_ROGUE_PDSINST_REGS64TP_TEMP64_LOWER)
50bf215546Sopenharmony_ci#define R64TP_P(x) ((x) + PVR_ROGUE_PDSINST_REGS64TP_PTEMP64_LOWER)
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci/* 32-bit PTemp index for draw indirect base instance. */
53bf215546Sopenharmony_ci#define PVR_INDIRECT_BASE_INSTANCE_PTEMP 1U
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_ci/* Number of constants to reserve per DDMAD instruction in the PDS Vertex. */
56bf215546Sopenharmony_ci#define PVR_PDS_DDMAD_NUM_CONSTS 8
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_ci#if defined(TRACE_PDS)
59bf215546Sopenharmony_ci/* Some macros for a pretty printing. */
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci#   define pvr_debug_pds_const(reg, size, annotation) \
62bf215546Sopenharmony_ci      mesa_logd("const[%d]   @  (%dbits)  %s", reg, size, annotation)
63bf215546Sopenharmony_ci#   define pvr_debug_pds_temp(reg, size, annotation) \
64bf215546Sopenharmony_ci      mesa_logd("temp[%d]    @  (%dbits)  %s", reg, size, annotation)
65bf215546Sopenharmony_ci#   define pvr_debug_pds_note(...) mesa_logd("              // " __VA_ARGS__)
66bf215546Sopenharmony_ci#   define pvr_debug_pds_flag(flags, flag) \
67bf215546Sopenharmony_ci      {                                    \
68bf215546Sopenharmony_ci         if ((flags & flag) == flag)       \
69bf215546Sopenharmony_ci            mesa_logd(" > " #flag);        \
70bf215546Sopenharmony_ci      }
71bf215546Sopenharmony_ci#   define pvr_debug(annotation) mesa_logd(annotation)
72bf215546Sopenharmony_ci
73bf215546Sopenharmony_ci#else
74bf215546Sopenharmony_ci#   define pvr_debug_pds_const(reg, size, annotation)
75bf215546Sopenharmony_ci#   define pvr_debug_pds_temp(reg, size, annotation)
76bf215546Sopenharmony_ci#   define pvr_debug_pds_note(...)
77bf215546Sopenharmony_ci#   define pvr_debug_pds_flag(flags, flag)
78bf215546Sopenharmony_ci#   define pvr_debug(annotation)
79bf215546Sopenharmony_ci#endif
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_cistruct pvr_pds_const_map_entry_write_state {
82bf215546Sopenharmony_ci   const struct pvr_pds_info *PDS_info;
83bf215546Sopenharmony_ci   struct pvr_const_map_entry *entry;
84bf215546Sopenharmony_ci   size_t size_of_last_entry_in_bytes;
85bf215546Sopenharmony_ci   uint32_t entry_count;
86bf215546Sopenharmony_ci   size_t entries_size_in_bytes;
87bf215546Sopenharmony_ci};
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_cistatic void pvr_init_pds_const_map_entry_write_state(
90bf215546Sopenharmony_ci   struct pvr_pds_info *PDS_info,
91bf215546Sopenharmony_ci   struct pvr_pds_const_map_entry_write_state *entry_write_state)
92bf215546Sopenharmony_ci{
93bf215546Sopenharmony_ci   entry_write_state->PDS_info = PDS_info;
94bf215546Sopenharmony_ci   entry_write_state->entry = PDS_info->entries;
95bf215546Sopenharmony_ci   entry_write_state->size_of_last_entry_in_bytes = 0;
96bf215546Sopenharmony_ci   entry_write_state->entry_count = 0;
97bf215546Sopenharmony_ci   entry_write_state->entries_size_in_bytes = 0;
98bf215546Sopenharmony_ci}
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci/* Returns a pointer to the next struct pvr_const_map_entry. */
101bf215546Sopenharmony_cistatic void *pvr_prepare_next_pds_const_map_entry(
102bf215546Sopenharmony_ci   struct pvr_pds_const_map_entry_write_state *entry_write_state,
103bf215546Sopenharmony_ci   size_t size_of_next_entry_in_bytes)
104bf215546Sopenharmony_ci{
105bf215546Sopenharmony_ci   /* Move on to the next entry. */
106bf215546Sopenharmony_ci   uint8_t *next_entry = ((uint8_t *)entry_write_state->entry +
107bf215546Sopenharmony_ci                          entry_write_state->size_of_last_entry_in_bytes);
108bf215546Sopenharmony_ci   entry_write_state->entry = (struct pvr_const_map_entry *)next_entry;
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci   entry_write_state->size_of_last_entry_in_bytes = size_of_next_entry_in_bytes;
111bf215546Sopenharmony_ci   entry_write_state->entry_count++;
112bf215546Sopenharmony_ci   entry_write_state->entries_size_in_bytes += size_of_next_entry_in_bytes;
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci   /* Check if we can write into the next entry. */
115bf215546Sopenharmony_ci   assert(entry_write_state->entries_size_in_bytes <=
116bf215546Sopenharmony_ci          entry_write_state->PDS_info->entries_size_in_bytes);
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ci   return entry_write_state->entry;
119bf215546Sopenharmony_ci}
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_cistatic void pvr_write_pds_const_map_entry_vertex_attribute_address(
122bf215546Sopenharmony_ci   struct pvr_pds_const_map_entry_write_state *entry_write_state,
123bf215546Sopenharmony_ci   const struct pvr_pds_vertex_dma *DMA,
124bf215546Sopenharmony_ci   uint32_t const_val,
125bf215546Sopenharmony_ci   bool use_robust_vertex_fetch)
126bf215546Sopenharmony_ci{
127bf215546Sopenharmony_ci   pvr_debug_pds_note("DMA %d dwords, stride %d, offset %d, bindingIdx %d",
128bf215546Sopenharmony_ci                      DMA->size_in_dwords,
129bf215546Sopenharmony_ci                      DMA->stride,
130bf215546Sopenharmony_ci                      DMA->offset,
131bf215546Sopenharmony_ci                      DMA->binding_index);
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_ci   if (use_robust_vertex_fetch) {
134bf215546Sopenharmony_ci      struct pvr_const_map_entry_robust_vertex_attribute_address
135bf215546Sopenharmony_ci         *robust_attribute_entry;
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci      robust_attribute_entry =
138bf215546Sopenharmony_ci         pvr_prepare_next_pds_const_map_entry(entry_write_state,
139bf215546Sopenharmony_ci                                              sizeof(*robust_attribute_entry));
140bf215546Sopenharmony_ci      robust_attribute_entry->type =
141bf215546Sopenharmony_ci         PVR_PDS_CONST_MAP_ENTRY_TYPE_ROBUST_VERTEX_ATTRIBUTE_ADDRESS;
142bf215546Sopenharmony_ci      robust_attribute_entry->const_offset = const_val;
143bf215546Sopenharmony_ci      robust_attribute_entry->binding_index = DMA->binding_index;
144bf215546Sopenharmony_ci      robust_attribute_entry->component_size_in_bytes =
145bf215546Sopenharmony_ci         DMA->component_size_in_bytes;
146bf215546Sopenharmony_ci      robust_attribute_entry->offset = DMA->offset;
147bf215546Sopenharmony_ci      robust_attribute_entry->stride = DMA->stride;
148bf215546Sopenharmony_ci      robust_attribute_entry->size_in_dwords = DMA->size_in_dwords;
149bf215546Sopenharmony_ci      robust_attribute_entry->robustness_buffer_offset =
150bf215546Sopenharmony_ci         DMA->robustness_buffer_offset;
151bf215546Sopenharmony_ci   } else {
152bf215546Sopenharmony_ci      struct pvr_const_map_entry_vertex_attribute_address *attribute_entry;
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci      attribute_entry =
155bf215546Sopenharmony_ci         pvr_prepare_next_pds_const_map_entry(entry_write_state,
156bf215546Sopenharmony_ci                                              sizeof(*attribute_entry));
157bf215546Sopenharmony_ci      attribute_entry->type =
158bf215546Sopenharmony_ci         PVR_PDS_CONST_MAP_ENTRY_TYPE_VERTEX_ATTRIBUTE_ADDRESS;
159bf215546Sopenharmony_ci      attribute_entry->const_offset = const_val;
160bf215546Sopenharmony_ci      attribute_entry->binding_index = DMA->binding_index;
161bf215546Sopenharmony_ci      attribute_entry->offset = DMA->offset;
162bf215546Sopenharmony_ci      attribute_entry->stride = DMA->stride;
163bf215546Sopenharmony_ci      attribute_entry->size_in_dwords = DMA->size_in_dwords;
164bf215546Sopenharmony_ci   }
165bf215546Sopenharmony_ci}
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_cistatic ALWAYS_INLINE uint32_t pvr_pds_encode_doutu(uint32_t cc,
168bf215546Sopenharmony_ci                                                   uint32_t end,
169bf215546Sopenharmony_ci                                                   uint32_t src0)
170bf215546Sopenharmony_ci{
171bf215546Sopenharmony_ci   return pvr_pds_inst_encode_dout(cc,
172bf215546Sopenharmony_ci                                   end,
173bf215546Sopenharmony_ci                                   0,
174bf215546Sopenharmony_ci                                   src0,
175bf215546Sopenharmony_ci                                   PVR_ROGUE_PDSINST_DSTDOUT_DOUTU);
176bf215546Sopenharmony_ci}
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_cistatic uint32_t
179bf215546Sopenharmony_cipvr_encode_burst(struct pvr_pds_const_map_entry_write_state *entry_write_state,
180bf215546Sopenharmony_ci                 bool last_DMA,
181bf215546Sopenharmony_ci                 bool halt,
182bf215546Sopenharmony_ci                 unsigned int const32,
183bf215546Sopenharmony_ci                 unsigned int const64,
184bf215546Sopenharmony_ci                 unsigned int dma_size_in_dwords,
185bf215546Sopenharmony_ci                 unsigned int destination,
186bf215546Sopenharmony_ci                 unsigned int store)
187bf215546Sopenharmony_ci{
188bf215546Sopenharmony_ci   uint32_t literal_value;
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_ci   /* Encode literal value. */
191bf215546Sopenharmony_ci   literal_value = dma_size_in_dwords
192bf215546Sopenharmony_ci                   << PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTD_SRC1_BSIZE_SHIFT;
193bf215546Sopenharmony_ci   literal_value |= destination
194bf215546Sopenharmony_ci                    << PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTD_SRC1_AO_SHIFT;
195bf215546Sopenharmony_ci   literal_value |= PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTD_SRC1_CMODE_CACHED |
196bf215546Sopenharmony_ci                    store;
197bf215546Sopenharmony_ci
198bf215546Sopenharmony_ci   if (last_DMA)
199bf215546Sopenharmony_ci      literal_value |= PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTD_SRC1_LAST_EN;
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci   /* Create const map entry. */
202bf215546Sopenharmony_ci   struct pvr_const_map_entry_literal32 *literal_entry;
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci   literal_entry = pvr_prepare_next_pds_const_map_entry(entry_write_state,
205bf215546Sopenharmony_ci                                                        sizeof(*literal_entry));
206bf215546Sopenharmony_ci   literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32;
207bf215546Sopenharmony_ci   literal_entry->const_offset = const32;
208bf215546Sopenharmony_ci   literal_entry->literal_value = literal_value;
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci   /* Encode DOUTD */
211bf215546Sopenharmony_ci   return pvr_pds_inst_encode_dout(0,
212bf215546Sopenharmony_ci                                   halt,
213bf215546Sopenharmony_ci                                   R32_C(const32),
214bf215546Sopenharmony_ci                                   R64_C(const64),
215bf215546Sopenharmony_ci                                   PVR_ROGUE_PDSINST_DSTDOUT_DOUTD);
216bf215546Sopenharmony_ci}
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci#define pvr_encode_burst_cs(psDataEntry,        \
219bf215546Sopenharmony_ci                            last_DMA,           \
220bf215546Sopenharmony_ci                            halt,               \
221bf215546Sopenharmony_ci                            const32,            \
222bf215546Sopenharmony_ci                            const64,            \
223bf215546Sopenharmony_ci                            dma_size_in_dwords, \
224bf215546Sopenharmony_ci                            destination)        \
225bf215546Sopenharmony_ci   pvr_encode_burst(                            \
226bf215546Sopenharmony_ci      psDataEntry,                              \
227bf215546Sopenharmony_ci      last_DMA,                                 \
228bf215546Sopenharmony_ci      halt,                                     \
229bf215546Sopenharmony_ci      const32,                                  \
230bf215546Sopenharmony_ci      const64,                                  \
231bf215546Sopenharmony_ci      dma_size_in_dwords,                       \
232bf215546Sopenharmony_ci      destination,                              \
233bf215546Sopenharmony_ci      PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_DEST_COMMON_STORE)
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_cistatic uint32_t pvr_encode_direct_write(
236bf215546Sopenharmony_ci   struct pvr_pds_const_map_entry_write_state *entry_write_state,
237bf215546Sopenharmony_ci   bool last_DMA,
238bf215546Sopenharmony_ci   bool halt,
239bf215546Sopenharmony_ci   unsigned int const32,
240bf215546Sopenharmony_ci   unsigned int const64,
241bf215546Sopenharmony_ci   uint32_t data_mask,
242bf215546Sopenharmony_ci   unsigned int destination,
243bf215546Sopenharmony_ci   uint32_t destination_store,
244bf215546Sopenharmony_ci   const struct pvr_device_info *dev_info)
245bf215546Sopenharmony_ci{
246bf215546Sopenharmony_ci   struct pvr_const_map_entry_literal32 *literal_entry;
247bf215546Sopenharmony_ci
248bf215546Sopenharmony_ci   uint32_t instruction =
249bf215546Sopenharmony_ci      pvr_pds_inst_encode_dout(0,
250bf215546Sopenharmony_ci                               halt,
251bf215546Sopenharmony_ci                               const32,
252bf215546Sopenharmony_ci                               const64,
253bf215546Sopenharmony_ci                               PVR_ROGUE_PDSINST_DSTDOUT_DOUTW);
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci   literal_entry = pvr_prepare_next_pds_const_map_entry(entry_write_state,
256bf215546Sopenharmony_ci                                                        sizeof(*literal_entry));
257bf215546Sopenharmony_ci   literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32;
258bf215546Sopenharmony_ci   literal_entry->const_offset = const32;
259bf215546Sopenharmony_ci   literal_entry->literal_value = destination_store;
260bf215546Sopenharmony_ci
261bf215546Sopenharmony_ci   if (PVR_HAS_FEATURE(dev_info, slc_mcu_cache_controls)) {
262bf215546Sopenharmony_ci      literal_entry->literal_value |=
263bf215546Sopenharmony_ci         PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_CMODE_CACHED;
264bf215546Sopenharmony_ci   }
265bf215546Sopenharmony_ci
266bf215546Sopenharmony_ci   literal_entry->literal_value |=
267bf215546Sopenharmony_ci      destination << PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_AO_SHIFT;
268bf215546Sopenharmony_ci
269bf215546Sopenharmony_ci   if (data_mask == 0x1) {
270bf215546Sopenharmony_ci      literal_entry->literal_value |=
271bf215546Sopenharmony_ci         PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_BSIZE_LOWER;
272bf215546Sopenharmony_ci   } else if (data_mask == 0x2) {
273bf215546Sopenharmony_ci      literal_entry->literal_value |=
274bf215546Sopenharmony_ci         PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_BSIZE_UPPER;
275bf215546Sopenharmony_ci   } else {
276bf215546Sopenharmony_ci      literal_entry->literal_value |=
277bf215546Sopenharmony_ci         PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_BSIZE_ALL64;
278bf215546Sopenharmony_ci   }
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci   if (last_DMA) {
281bf215546Sopenharmony_ci      literal_entry->literal_value |=
282bf215546Sopenharmony_ci         PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_LAST_EN;
283bf215546Sopenharmony_ci   }
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_ci   return instruction;
286bf215546Sopenharmony_ci}
287bf215546Sopenharmony_ci
288bf215546Sopenharmony_ci/* Constant and Temporary register allocation
289bf215546Sopenharmony_ci * - reserve space for a 32-bit register or a 64-bit register
290bf215546Sopenharmony_ci * - returned indices are offsets to 32-bit register locations
291bf215546Sopenharmony_ci * - 64-bit registers need to be aligned to even indices.
292bf215546Sopenharmony_ci */
293bf215546Sopenharmony_ci#define RESERVE_32BIT 1U
294bf215546Sopenharmony_ci#define RESERVE_64BIT 2U
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_ci#if defined(DEBUG)
297bf215546Sopenharmony_ci#   define pvr_find_constant(usage, words, name) \
298bf215546Sopenharmony_ci      pvr_find_constant2(usage, words, name)
299bf215546Sopenharmony_ci#   define pvr_get_temps(usage, words, name) pvr_get_temps2(usage, words, name)
300bf215546Sopenharmony_ci#else
301bf215546Sopenharmony_ci#   define pvr_find_constant(usage, words, name) \
302bf215546Sopenharmony_ci      pvr_find_constant2(usage, words, NULL);
303bf215546Sopenharmony_ci#   define pvr_get_temps(usage, words, name) pvr_get_temps2(usage, words, NULL)
304bf215546Sopenharmony_ci#endif
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_cistatic uint32_t
307bf215546Sopenharmony_cipvr_find_constant2(uint8_t *const_usage, uint8_t words, const char *const_name)
308bf215546Sopenharmony_ci{
309bf215546Sopenharmony_ci   uint32_t const_index = ~0U;
310bf215546Sopenharmony_ci   uint32_t step = words;
311bf215546Sopenharmony_ci   uint8_t mask = (1 << words) - 1;
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci   assert(words == 1 || words == 2);
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_ci   /* Find a register at 'step' alignment that satisfies the mask. */
316bf215546Sopenharmony_ci   for (uint32_t i = 0; i < PVR_MAX_VERTEX_ATTRIB_DMAS; i++) {
317bf215546Sopenharmony_ci      for (uint32_t b = 0; b < PVR_PDS_DDMAD_NUM_CONSTS; b += step) {
318bf215546Sopenharmony_ci         if ((const_usage[i] & (mask << b)) != 0)
319bf215546Sopenharmony_ci            continue;
320bf215546Sopenharmony_ci         const_usage[i] |= (mask << b);
321bf215546Sopenharmony_ci         const_index = i * 8 + b;
322bf215546Sopenharmony_ci         pvr_debug_pds_const(const_index, words * 32, const_name);
323bf215546Sopenharmony_ci         return const_index;
324bf215546Sopenharmony_ci      }
325bf215546Sopenharmony_ci   }
326bf215546Sopenharmony_ci
327bf215546Sopenharmony_ci   unreachable("Unexpected: Space cannot be found for constant");
328bf215546Sopenharmony_ci   return ~0U;
329bf215546Sopenharmony_ci}
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_ci#define PVR_MAX_PDS_TEMPS 32
332bf215546Sopenharmony_cistruct pvr_temp_usage {
333bf215546Sopenharmony_ci   uint32_t temp_usage;
334bf215546Sopenharmony_ci   uint8_t temp_used;
335bf215546Sopenharmony_ci   uint8_t temps_needed;
336bf215546Sopenharmony_ci};
337bf215546Sopenharmony_ci
338bf215546Sopenharmony_ci#define PVR_INVALID_TEMP UINT8_C(~0)
339bf215546Sopenharmony_ci
340bf215546Sopenharmony_cistatic uint8_t pvr_get_temps2(struct pvr_temp_usage *temps,
341bf215546Sopenharmony_ci                              uint8_t temps_needed,
342bf215546Sopenharmony_ci                              const char *temp_name)
343bf215546Sopenharmony_ci{
344bf215546Sopenharmony_ci   uint8_t step = temps_needed;
345bf215546Sopenharmony_ci   uint8_t mask = (1 << temps_needed) - 1;
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_ci   assert(temps_needed == 1 || temps_needed == 2);
348bf215546Sopenharmony_ci   assert(temps->temp_used + temps_needed <= PVR_MAX_PDS_TEMPS);
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_ci   for (uint8_t i = 0; i < PVR_MAX_PDS_TEMPS; i += step) {
351bf215546Sopenharmony_ci      if ((temps->temp_usage & (mask << i)) != 0)
352bf215546Sopenharmony_ci         continue;
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_ci      const size_t clzBits = 8 * sizeof(unsigned int);
355bf215546Sopenharmony_ci
356bf215546Sopenharmony_ci      temps->temp_usage |= (mask << i);
357bf215546Sopenharmony_ci      temps->temp_used += temps_needed;
358bf215546Sopenharmony_ci      temps->temps_needed =
359bf215546Sopenharmony_ci         clzBits - __builtin_clz((unsigned int)temps->temp_usage);
360bf215546Sopenharmony_ci
361bf215546Sopenharmony_ci      pvr_debug_pds_temp(i, temps_needed * 32, temp_name);
362bf215546Sopenharmony_ci
363bf215546Sopenharmony_ci      return i;
364bf215546Sopenharmony_ci   }
365bf215546Sopenharmony_ci
366bf215546Sopenharmony_ci   unreachable("Unexpected: Space cannot be found for temps");
367bf215546Sopenharmony_ci   return PVR_INVALID_TEMP;
368bf215546Sopenharmony_ci}
369bf215546Sopenharmony_ci
370bf215546Sopenharmony_ci/**
371bf215546Sopenharmony_ci * Wrapper macro to add a toggle for "data mode", allowing us to calculate the
372bf215546Sopenharmony_ci * size of a PDS program without actually attempting to store it.
373bf215546Sopenharmony_ci *
374bf215546Sopenharmony_ci * \param dest The array/memory pointer where the PDS program should be stored.
375bf215546Sopenharmony_ci *             If the given code is NULL, automatically switch to count mode
376bf215546Sopenharmony_ci *             instead of attempting to fill in unallocated memory.
377bf215546Sopenharmony_ci * \param counter The local counter that holds the total instruction count.
378bf215546Sopenharmony_ci * \param statement What function call/value should be stored at dest[counter]
379bf215546Sopenharmony_ci *                  when condition is false.
380bf215546Sopenharmony_ci */
381bf215546Sopenharmony_ci
382bf215546Sopenharmony_ci#define PVR_PDS_MODE_TOGGLE(dest, counter, statement) \
383bf215546Sopenharmony_ci   if (!dest) {                                       \
384bf215546Sopenharmony_ci      counter++;                                      \
385bf215546Sopenharmony_ci   } else {                                           \
386bf215546Sopenharmony_ci      dest[counter++] = statement;                    \
387bf215546Sopenharmony_ci      PVR_PDS_PRINT_INST(statement);                  \
388bf215546Sopenharmony_ci   }
389bf215546Sopenharmony_ci
390bf215546Sopenharmony_ci/**
391bf215546Sopenharmony_ci * Generates the PDS vertex primary program for the dma's listed in the input
392bf215546Sopenharmony_ci * structure. Produces the constant map for the Vulkan driver based upon the
393bf215546Sopenharmony_ci * requirements of the instructions added to the program.
394bf215546Sopenharmony_ci *
395bf215546Sopenharmony_ci * PDS Data Layout
396bf215546Sopenharmony_ci * ---------------
397bf215546Sopenharmony_ci *
398bf215546Sopenharmony_ci * The PDS data is optimized for the DDMAD layout, with the data for those
399bf215546Sopenharmony_ci * instructions laid out first. The data required for other instructions is laid
400bf215546Sopenharmony_ci * out in the entries unused by the DDMADs.
401bf215546Sopenharmony_ci *
402bf215546Sopenharmony_ci * DDMAD layout
403bf215546Sopenharmony_ci * \verbatim
404bf215546Sopenharmony_ci * 	bank | index | usage
405bf215546Sopenharmony_ci * 	0    |  0:1  | temps (current index)[-]
406bf215546Sopenharmony_ci * 	2    |  2:3  | stride[32]
407bf215546Sopenharmony_ci * 	1    |  4:5  | base address[64]
408bf215546Sopenharmony_ci * 	3    |  6:7  | ctrl[64]
409bf215546Sopenharmony_ci * \endverbatim
410bf215546Sopenharmony_ci *
411bf215546Sopenharmony_ci *  Each DMA whose stride > 0 requires one entry, laid out as above. We stride
412bf215546Sopenharmony_ci * 	over the banks to ensure that each ddmad reads each of its operands from a
413bf215546Sopenharmony_ci * 	different bank (i.e. remove bank clashes)
414bf215546Sopenharmony_ci *
415bf215546Sopenharmony_ci * 	Note: This is "wasting" const[0:1] and const[2], however these free
416bf215546Sopenharmony_ci * 	registers will be used by other, non-ddmad instructions.
417bf215546Sopenharmony_ci *
418bf215546Sopenharmony_ci * 	The const register usage is maintained in the au8ConstUsage array, the
419bf215546Sopenharmony_ci * DDMAD instructions, for example, will utilize the top 5 registers in each
420bf215546Sopenharmony_ci * block of 8 hence a 'usage mask' of 0xF8 (0b11111000).
421bf215546Sopenharmony_ci *
422bf215546Sopenharmony_ci * 	Constant Map
423bf215546Sopenharmony_ci * 	------------
424bf215546Sopenharmony_ci *
425bf215546Sopenharmony_ci * 	The constant map is built up as we add PDS instructions and passed back
426bf215546Sopenharmony_ci * for the driver to fill in the PDS data section with the correct parameters
427bf215546Sopenharmony_ci * for each draw call.
428bf215546Sopenharmony_ci *
429bf215546Sopenharmony_ci * \param input_program PDS Program description.
430bf215546Sopenharmony_ci * \param code Buffer to be filled in with the PDS program. If NULL is provided,
431bf215546Sopenharmony_ci *             automatically switch to count-mode, preventing writes to
432bf215546Sopenharmony_ci *             unallocated memory.
433bf215546Sopenharmony_ci * \param info PDS info structure filled in for the driver, contains the
434bf215546Sopenharmony_ci *             constant map.
435bf215546Sopenharmony_ci * \param use_robust_vertex_fetch Do vertex fetches apply range checking.
436bf215546Sopenharmony_ci * \param dev_info pvr device information struct.
437bf215546Sopenharmony_ci */
438bf215546Sopenharmony_civoid pvr_pds_generate_vertex_primary_program(
439bf215546Sopenharmony_ci   struct pvr_pds_vertex_primary_program_input *input_program,
440bf215546Sopenharmony_ci   uint32_t *code,
441bf215546Sopenharmony_ci   struct pvr_pds_info *info,
442bf215546Sopenharmony_ci   bool use_robust_vertex_fetch,
443bf215546Sopenharmony_ci   const struct pvr_device_info *dev_info)
444bf215546Sopenharmony_ci{
445bf215546Sopenharmony_ci   struct pvr_pds_const_map_entry_write_state entry_write_state;
446bf215546Sopenharmony_ci   struct pvr_const_map_entry_doutu_address *doutu_address_entry;
447bf215546Sopenharmony_ci
448bf215546Sopenharmony_ci   uint32_t instruction = 0; /* index into code */
449bf215546Sopenharmony_ci   uint32_t index; /* index used for current attribute, either vertex or
450bf215546Sopenharmony_ci                    * instance.
451bf215546Sopenharmony_ci                    */
452bf215546Sopenharmony_ci
453bf215546Sopenharmony_ci   uint32_t total_dma_count = 0;
454bf215546Sopenharmony_ci   uint32_t running_dma_count = 0;
455bf215546Sopenharmony_ci
456bf215546Sopenharmony_ci   uint32_t write_instance_control = ~0;
457bf215546Sopenharmony_ci   uint32_t write_vertex_control = ~0;
458bf215546Sopenharmony_ci   uint32_t write_base_instance_control = ~0;
459bf215546Sopenharmony_ci   uint32_t write_base_vertex_control = ~0;
460bf215546Sopenharmony_ci   uint32_t pvr_write_draw_index_control = ~0;
461bf215546Sopenharmony_ci
462bf215546Sopenharmony_ci   uint32_t ddmad_count = 0;
463bf215546Sopenharmony_ci   uint32_t doutw_count = 0;
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_ci   uint32_t base_instance = 0;
466bf215546Sopenharmony_ci   uint32_t base_vertex = 0;
467bf215546Sopenharmony_ci   uint32_t draw_index = 0;
468bf215546Sopenharmony_ci
469bf215546Sopenharmony_ci   uint8_t const_usage[PVR_MAX_VERTEX_ATTRIB_DMAS] = { 0 };
470bf215546Sopenharmony_ci
471bf215546Sopenharmony_ci   struct pvr_temp_usage temp_usage = { 0 };
472bf215546Sopenharmony_ci
473bf215546Sopenharmony_ci   uint32_t zero_temp = PVR_INVALID_TEMP;
474bf215546Sopenharmony_ci
475bf215546Sopenharmony_ci   uint32_t max_index_temp = PVR_INVALID_TEMP;
476bf215546Sopenharmony_ci   uint32_t current_index_temp = PVR_INVALID_TEMP;
477bf215546Sopenharmony_ci
478bf215546Sopenharmony_ci   uint32_t index_id_temp = PVR_INVALID_TEMP;
479bf215546Sopenharmony_ci   uint32_t base_instance_ID_temp = PVR_INVALID_TEMP;
480bf215546Sopenharmony_ci   uint32_t instance_ID_temp = PVR_INVALID_TEMP;
481bf215546Sopenharmony_ci
482bf215546Sopenharmony_ci   /* Debug tracing of program flags. */
483bf215546Sopenharmony_ci   pvr_debug("pvr_pds_generate_vertex_primary_program");
484bf215546Sopenharmony_ci   pvr_debug("=================================================");
485bf215546Sopenharmony_ci   pvr_debug_pds_flag(input_program->flags,
486bf215546Sopenharmony_ci                      PVR_PDS_VERTEX_FLAGS_VERTEX_ID_REQUIRED);
487bf215546Sopenharmony_ci   pvr_debug_pds_flag(input_program->flags,
488bf215546Sopenharmony_ci                      PVR_PDS_VERTEX_FLAGS_INSTANCE_ID_REQUIRED);
489bf215546Sopenharmony_ci   pvr_debug_pds_flag(input_program->flags,
490bf215546Sopenharmony_ci                      PVR_PDS_VERTEX_FLAGS_DRAW_INDIRECT_VARIANT);
491bf215546Sopenharmony_ci   pvr_debug_pds_flag(input_program->flags,
492bf215546Sopenharmony_ci                      PVR_PDS_VERTEX_FLAGS_BASE_INSTANCE_VARIANT);
493bf215546Sopenharmony_ci   pvr_debug_pds_flag(input_program->flags,
494bf215546Sopenharmony_ci                      PVR_PDS_VERTEX_FLAGS_BASE_INSTANCE_REQUIRED);
495bf215546Sopenharmony_ci   pvr_debug_pds_flag(input_program->flags,
496bf215546Sopenharmony_ci                      PVR_PDS_VERTEX_FLAGS_BASE_VERTEX_REQUIRED);
497bf215546Sopenharmony_ci   pvr_debug_pds_flag(input_program->flags,
498bf215546Sopenharmony_ci                      PVR_PDS_VERTEX_FLAGS_DRAW_INDEX_REQUIRED);
499bf215546Sopenharmony_ci   pvr_debug(" ");
500bf215546Sopenharmony_ci
501bf215546Sopenharmony_ci   pvr_init_pds_const_map_entry_write_state(info, &entry_write_state);
502bf215546Sopenharmony_ci
503bf215546Sopenharmony_ci   /* At a minimum we need 2 dwords for the DOUTU, but since we allocate in
504bf215546Sopenharmony_ci    * blocks of 4 we can reserve dwords for the instance/vertex DOUTW.
505bf215546Sopenharmony_ci    */
506bf215546Sopenharmony_ci   info->data_size_in_dwords = 4;
507bf215546Sopenharmony_ci
508bf215546Sopenharmony_ci   /* Reserve 2 temps - these are automatically filled in by the VDM
509bf215546Sopenharmony_ci    *
510bf215546Sopenharmony_ci    * For instanced draw calls we manually increment the instance id by the
511bf215546Sopenharmony_ci    * base-instance offset which is either provided as a constant, or in a
512bf215546Sopenharmony_ci    * ptemp (for draw indirect)
513bf215546Sopenharmony_ci    *
514bf215546Sopenharmony_ci    * temp - contents
515bf215546Sopenharmony_ci    * ---------------
516bf215546Sopenharmony_ci    * 0    - index id (pre-filled)
517bf215546Sopenharmony_ci    * 1    - base instance + instance id
518bf215546Sopenharmony_ci    */
519bf215546Sopenharmony_ci   index_id_temp = pvr_get_temps(&temp_usage, RESERVE_32BIT, "VDM Index id");
520bf215546Sopenharmony_ci   instance_ID_temp =
521bf215546Sopenharmony_ci      pvr_get_temps(&temp_usage, RESERVE_32BIT, "VDM Instance id");
522bf215546Sopenharmony_ci
523bf215546Sopenharmony_ci   /* Reserve the lowest 2 dwords for DOUTU.
524bf215546Sopenharmony_ci    * [------XX]
525bf215546Sopenharmony_ci    */
526bf215546Sopenharmony_ci   const_usage[0] = 0x03;
527bf215546Sopenharmony_ci
528bf215546Sopenharmony_ci   /* Reserve consts for all the DDMAD's. */
529bf215546Sopenharmony_ci   for (uint32_t dma = 0; dma < input_program->dma_count; dma++) {
530bf215546Sopenharmony_ci      /* Mark the consts required by this ddmad "in-use".
531bf215546Sopenharmony_ci       * [XXXXX---]
532bf215546Sopenharmony_ci       */
533bf215546Sopenharmony_ci      const_usage[ddmad_count++] |= 0xf8;
534bf215546Sopenharmony_ci   }
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_ci   /* Start off by assuming we can fit everything in the 8 dwords/ddmad
537bf215546Sopenharmony_ci    * footprint, if any DOUTD/DOUTW falls outside we will increase this
538bf215546Sopenharmony_ci    * counter.
539bf215546Sopenharmony_ci    */
540bf215546Sopenharmony_ci   if (ddmad_count)
541bf215546Sopenharmony_ci      info->data_size_in_dwords = PVR_PDS_DDMAD_NUM_CONSTS * ddmad_count;
542bf215546Sopenharmony_ci
543bf215546Sopenharmony_ci   if (input_program->flags & PVR_PDS_VERTEX_FLAGS_VERTEX_ID_REQUIRED) {
544bf215546Sopenharmony_ci      doutw_count++;
545bf215546Sopenharmony_ci      write_vertex_control =
546bf215546Sopenharmony_ci         pvr_find_constant(const_usage, RESERVE_32BIT, "Vertex id DOUTW Ctrl");
547bf215546Sopenharmony_ci   }
548bf215546Sopenharmony_ci
549bf215546Sopenharmony_ci   if (input_program->flags & PVR_PDS_VERTEX_FLAGS_INSTANCE_ID_REQUIRED) {
550bf215546Sopenharmony_ci      doutw_count++;
551bf215546Sopenharmony_ci      write_instance_control = pvr_find_constant(const_usage,
552bf215546Sopenharmony_ci                                                 RESERVE_32BIT,
553bf215546Sopenharmony_ci                                                 "Instance id DOUTW Ctrl");
554bf215546Sopenharmony_ci   }
555bf215546Sopenharmony_ci
556bf215546Sopenharmony_ci   if (input_program->flags & PVR_PDS_VERTEX_FLAGS_BASE_INSTANCE_REQUIRED) {
557bf215546Sopenharmony_ci      doutw_count++;
558bf215546Sopenharmony_ci      write_base_instance_control =
559bf215546Sopenharmony_ci         pvr_find_constant(const_usage,
560bf215546Sopenharmony_ci                           RESERVE_32BIT,
561bf215546Sopenharmony_ci                           "Base Instance DOUTW Ctrl");
562bf215546Sopenharmony_ci   }
563bf215546Sopenharmony_ci
564bf215546Sopenharmony_ci   if (input_program->flags & PVR_PDS_VERTEX_FLAGS_BASE_VERTEX_REQUIRED) {
565bf215546Sopenharmony_ci      doutw_count++;
566bf215546Sopenharmony_ci      write_base_vertex_control = pvr_find_constant(const_usage,
567bf215546Sopenharmony_ci                                                    RESERVE_32BIT,
568bf215546Sopenharmony_ci                                                    "Base Vertex DOUTW Ctrl");
569bf215546Sopenharmony_ci
570bf215546Sopenharmony_ci      /* Load base vertex from constant for non-indirect variants. */
571bf215546Sopenharmony_ci      if ((input_program->flags & PVR_PDS_VERTEX_FLAGS_DRAW_INDIRECT_VARIANT) ==
572bf215546Sopenharmony_ci          0) {
573bf215546Sopenharmony_ci         struct pvr_const_map_entry_base_vertex *psBaseVertexEntry =
574bf215546Sopenharmony_ci            (struct pvr_const_map_entry_base_vertex *)entry_write_state.entry;
575bf215546Sopenharmony_ci
576bf215546Sopenharmony_ci         base_vertex =
577bf215546Sopenharmony_ci            pvr_find_constant(const_usage, RESERVE_32BIT, "base_vertex");
578bf215546Sopenharmony_ci
579bf215546Sopenharmony_ci         psBaseVertexEntry =
580bf215546Sopenharmony_ci            pvr_prepare_next_pds_const_map_entry(&entry_write_state,
581bf215546Sopenharmony_ci                                                 sizeof(*psBaseVertexEntry));
582bf215546Sopenharmony_ci         psBaseVertexEntry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_BASE_VERTEX;
583bf215546Sopenharmony_ci         psBaseVertexEntry->const_offset = base_vertex;
584bf215546Sopenharmony_ci      }
585bf215546Sopenharmony_ci   }
586bf215546Sopenharmony_ci
587bf215546Sopenharmony_ci   if (input_program->flags & PVR_PDS_VERTEX_FLAGS_DRAW_INDEX_REQUIRED) {
588bf215546Sopenharmony_ci      doutw_count++;
589bf215546Sopenharmony_ci      pvr_write_draw_index_control =
590bf215546Sopenharmony_ci         pvr_find_constant(const_usage, RESERVE_32BIT, "Draw Index DOUTW Ctrl");
591bf215546Sopenharmony_ci
592bf215546Sopenharmony_ci      /* Set draw index to 0 for non-indirect variants. */
593bf215546Sopenharmony_ci      if ((input_program->flags & PVR_PDS_VERTEX_FLAGS_DRAW_INDIRECT_VARIANT) ==
594bf215546Sopenharmony_ci          0) {
595bf215546Sopenharmony_ci         struct pvr_const_map_entry_literal32 *literal_entry;
596bf215546Sopenharmony_ci
597bf215546Sopenharmony_ci         draw_index =
598bf215546Sopenharmony_ci            pvr_find_constant(const_usage, RESERVE_32BIT, "draw_index");
599bf215546Sopenharmony_ci
600bf215546Sopenharmony_ci         literal_entry =
601bf215546Sopenharmony_ci            pvr_prepare_next_pds_const_map_entry(&entry_write_state,
602bf215546Sopenharmony_ci                                                 sizeof(*literal_entry));
603bf215546Sopenharmony_ci         literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32;
604bf215546Sopenharmony_ci         literal_entry->const_offset = draw_index;
605bf215546Sopenharmony_ci         literal_entry->literal_value = 0;
606bf215546Sopenharmony_ci      }
607bf215546Sopenharmony_ci   }
608bf215546Sopenharmony_ci
609bf215546Sopenharmony_ci   if (input_program->flags & PVR_PDS_VERTEX_FLAGS_DRAW_INDIRECT_VARIANT) {
610bf215546Sopenharmony_ci      /* Load absolute instance id into uiInstanceIdTemp. */
611bf215546Sopenharmony_ci      PVR_PDS_MODE_TOGGLE(
612bf215546Sopenharmony_ci         code,
613bf215546Sopenharmony_ci         instruction,
614bf215546Sopenharmony_ci         pvr_pds_inst_encode_add32(
615bf215546Sopenharmony_ci            /* cc    */ 0,
616bf215546Sopenharmony_ci            /* alum  */ 0,
617bf215546Sopenharmony_ci            /* sna   */ 0,
618bf215546Sopenharmony_ci            /* src0  */ R32_P(PVR_INDIRECT_BASE_INSTANCE_PTEMP),
619bf215546Sopenharmony_ci            /* src1  */ R32_T(instance_ID_temp),
620bf215546Sopenharmony_ci            /* dst   */ R32TP_T(instance_ID_temp)));
621bf215546Sopenharmony_ci   } else if (input_program->flags &
622bf215546Sopenharmony_ci              PVR_PDS_VERTEX_FLAGS_BASE_INSTANCE_VARIANT) {
623bf215546Sopenharmony_ci      struct pvr_const_map_entry_base_instance *base_instance_entry =
624bf215546Sopenharmony_ci         (struct pvr_const_map_entry_base_instance *)entry_write_state.entry;
625bf215546Sopenharmony_ci
626bf215546Sopenharmony_ci      base_instance =
627bf215546Sopenharmony_ci         pvr_find_constant(const_usage, RESERVE_32BIT, "base_instance");
628bf215546Sopenharmony_ci
629bf215546Sopenharmony_ci      PVR_PDS_MODE_TOGGLE(code,
630bf215546Sopenharmony_ci                          instruction,
631bf215546Sopenharmony_ci                          pvr_pds_inst_encode_add32(
632bf215546Sopenharmony_ci                             /* cc    */ 0,
633bf215546Sopenharmony_ci                             /* alum  */ 0,
634bf215546Sopenharmony_ci                             /* sna   */ 0,
635bf215546Sopenharmony_ci                             /* src0  */ R32_C(base_instance),
636bf215546Sopenharmony_ci                             /* src1  */ R32_T(instance_ID_temp),
637bf215546Sopenharmony_ci                             /* dst   */ R32TP_T(instance_ID_temp)));
638bf215546Sopenharmony_ci
639bf215546Sopenharmony_ci      base_instance_entry =
640bf215546Sopenharmony_ci         pvr_prepare_next_pds_const_map_entry(&entry_write_state,
641bf215546Sopenharmony_ci                                              sizeof(*base_instance_entry));
642bf215546Sopenharmony_ci      base_instance_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_BASE_INSTANCE;
643bf215546Sopenharmony_ci      base_instance_entry->const_offset = base_instance;
644bf215546Sopenharmony_ci   } else if (input_program->flags &
645bf215546Sopenharmony_ci              PVR_PDS_VERTEX_FLAGS_BASE_INSTANCE_REQUIRED) {
646bf215546Sopenharmony_ci      struct pvr_const_map_entry_base_instance *base_instance_entry =
647bf215546Sopenharmony_ci         (struct pvr_const_map_entry_base_instance *)entry_write_state.entry;
648bf215546Sopenharmony_ci
649bf215546Sopenharmony_ci      base_instance = pvr_find_constant(const_usage,
650bf215546Sopenharmony_ci                                        RESERVE_32BIT,
651bf215546Sopenharmony_ci                                        "base_instance (Driver Const)");
652bf215546Sopenharmony_ci
653bf215546Sopenharmony_ci      /* Base instance provided by the driver. */
654bf215546Sopenharmony_ci      base_instance_entry =
655bf215546Sopenharmony_ci         pvr_prepare_next_pds_const_map_entry(&entry_write_state,
656bf215546Sopenharmony_ci                                              sizeof(*base_instance_entry));
657bf215546Sopenharmony_ci      base_instance_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_BASE_INSTANCE;
658bf215546Sopenharmony_ci      base_instance_entry->const_offset = base_instance;
659bf215546Sopenharmony_ci   }
660bf215546Sopenharmony_ci
661bf215546Sopenharmony_ci   total_dma_count = ddmad_count;
662bf215546Sopenharmony_ci
663bf215546Sopenharmony_ci   total_dma_count += doutw_count;
664bf215546Sopenharmony_ci
665bf215546Sopenharmony_ci   if (use_robust_vertex_fetch) {
666bf215546Sopenharmony_ci      pvr_debug_pds_note("RobustBufferVertexFetch Initialization");
667bf215546Sopenharmony_ci
668bf215546Sopenharmony_ci      if (PVR_HAS_FEATURE(dev_info, pds_ddmadt)) {
669bf215546Sopenharmony_ci         zero_temp = pvr_get_temps(&temp_usage, RESERVE_32BIT, "zero_temp");
670bf215546Sopenharmony_ci
671bf215546Sopenharmony_ci         /* Load 0 into instance_ID_temp. */
672bf215546Sopenharmony_ci         PVR_PDS_MODE_TOGGLE(code,
673bf215546Sopenharmony_ci                             instruction,
674bf215546Sopenharmony_ci                             pvr_pds_inst_encode_limm(0, /* cc */
675bf215546Sopenharmony_ci                                                      zero_temp, /* SRC1 */
676bf215546Sopenharmony_ci                                                      0, /* SRC0 */
677bf215546Sopenharmony_ci                                                      0 /* GR */
678bf215546Sopenharmony_ci                                                      ));
679bf215546Sopenharmony_ci      } else {
680bf215546Sopenharmony_ci         zero_temp = pvr_get_temps(&temp_usage, RESERVE_64BIT, "zero_temp");
681bf215546Sopenharmony_ci
682bf215546Sopenharmony_ci         max_index_temp =
683bf215546Sopenharmony_ci            pvr_get_temps(&temp_usage, RESERVE_64BIT, "uMaxIndex");
684bf215546Sopenharmony_ci         current_index_temp =
685bf215546Sopenharmony_ci            pvr_get_temps(&temp_usage, RESERVE_64BIT, "uCurrentIndex");
686bf215546Sopenharmony_ci
687bf215546Sopenharmony_ci         PVR_PDS_MODE_TOGGLE(code,
688bf215546Sopenharmony_ci                             instruction,
689bf215546Sopenharmony_ci                             pvr_pds_inst_encode_stflp64(
690bf215546Sopenharmony_ci                                0, /* cc */
691bf215546Sopenharmony_ci                                PVR_ROGUE_PDSINST_LOP_XOR, /* LOP */
692bf215546Sopenharmony_ci                                1, /* IM */
693bf215546Sopenharmony_ci                                R64TP_T(zero_temp >> 1), /* SRC0 (REGS64TP)
694bf215546Sopenharmony_ci                                                          */
695bf215546Sopenharmony_ci                                R64TP_T(zero_temp >> 1), /* SRC1 (REGS64TP)
696bf215546Sopenharmony_ci                                                          */
697bf215546Sopenharmony_ci                                0, /* SRC2 (REGS32) */
698bf215546Sopenharmony_ci                                R64TP_T(zero_temp >> 1) /* DST (REG64TP) */
699bf215546Sopenharmony_ci                                ));
700bf215546Sopenharmony_ci         PVR_PDS_MODE_TOGGLE(code,
701bf215546Sopenharmony_ci                             instruction,
702bf215546Sopenharmony_ci                             pvr_pds_inst_encode_stflp64(
703bf215546Sopenharmony_ci                                0, /* cc */
704bf215546Sopenharmony_ci                                PVR_ROGUE_PDSINST_LOP_NONE, /* LOP */
705bf215546Sopenharmony_ci                                1, /* IM */
706bf215546Sopenharmony_ci                                R64TP_T(zero_temp >> 1), /* SRC0 (REGS64TP)
707bf215546Sopenharmony_ci                                                          */
708bf215546Sopenharmony_ci                                0, /* SRC1 (REGS64TP) */
709bf215546Sopenharmony_ci                                0, /* SRC2 (REGS32) */
710bf215546Sopenharmony_ci                                R64TP_T(current_index_temp >> 1) /* DST */
711bf215546Sopenharmony_ci                                /* (REG64TP) */
712bf215546Sopenharmony_ci                                ));
713bf215546Sopenharmony_ci         PVR_PDS_MODE_TOGGLE(code,
714bf215546Sopenharmony_ci                             instruction,
715bf215546Sopenharmony_ci                             pvr_pds_inst_encode_stflp64(
716bf215546Sopenharmony_ci                                0, /* cc */
717bf215546Sopenharmony_ci                                PVR_ROGUE_PDSINST_LOP_NONE, /* LOP */
718bf215546Sopenharmony_ci                                1, /* IM */
719bf215546Sopenharmony_ci                                R64TP_T(zero_temp >> 1), /* SRC0 (REGS64TP)
720bf215546Sopenharmony_ci                                                          */
721bf215546Sopenharmony_ci                                0, /* SRC1 (REGS64TP) */
722bf215546Sopenharmony_ci                                0, /* SRC2 (REGS32) */
723bf215546Sopenharmony_ci                                R64TP_T(max_index_temp >> 1) /* DST */
724bf215546Sopenharmony_ci                                /* (REG64TP) */
725bf215546Sopenharmony_ci                                ));
726bf215546Sopenharmony_ci      }
727bf215546Sopenharmony_ci   }
728bf215546Sopenharmony_ci
729bf215546Sopenharmony_ci   if (input_program->dma_count && use_robust_vertex_fetch) {
730bf215546Sopenharmony_ci      PVR_PDS_MODE_TOGGLE(
731bf215546Sopenharmony_ci         code,
732bf215546Sopenharmony_ci         instruction,
733bf215546Sopenharmony_ci         pvr_pds_inst_encode_bra(PVR_ROGUE_PDSINST_PREDICATE_KEEP, /* SRCC */
734bf215546Sopenharmony_ci                                 0, /* Neg */
735bf215546Sopenharmony_ci                                 PVR_HAS_FEATURE(dev_info, pds_ddmadt)
736bf215546Sopenharmony_ci                                    ? PVR_ROGUE_PDSINST_PREDICATE_OOB
737bf215546Sopenharmony_ci                                    : PVR_ROGUE_PDSINST_PREDICATE_P0, /* SETC */
738bf215546Sopenharmony_ci                                 1 /* Addr */
739bf215546Sopenharmony_ci                                 ));
740bf215546Sopenharmony_ci   }
741bf215546Sopenharmony_ci
742bf215546Sopenharmony_ci   for (uint32_t dma = 0; dma < input_program->dma_count; dma++) {
743bf215546Sopenharmony_ci      uint32_t const_base = dma * PVR_PDS_DDMAD_NUM_CONSTS;
744bf215546Sopenharmony_ci      uint32_t control_word;
745bf215546Sopenharmony_ci      struct pvr_const_map_entry_literal32 *literal_entry;
746bf215546Sopenharmony_ci
747bf215546Sopenharmony_ci      struct pvr_pds_vertex_dma *vertex_dma = &input_program->dma_list[dma];
748bf215546Sopenharmony_ci      bool last_DMA = (++running_dma_count == total_dma_count);
749bf215546Sopenharmony_ci
750bf215546Sopenharmony_ci      pvr_debug_pds_note("Vertex Attribute DMA %d (last=%d)", dma, last_DMA);
751bf215546Sopenharmony_ci
752bf215546Sopenharmony_ci      /* The id we use to index into this dma. */
753bf215546Sopenharmony_ci      if (vertex_dma->flags & PVR_PDS_VERTEX_DMA_FLAGS_INSTANCE_RATE) {
754bf215546Sopenharmony_ci         pvr_debug_pds_note("Instance Rate (divisor = %d)",
755bf215546Sopenharmony_ci                            vertex_dma->divisor);
756bf215546Sopenharmony_ci
757bf215546Sopenharmony_ci         /* 4    - madd 0 - needs to be 64-bit aligned
758bf215546Sopenharmony_ci          * 5    - madd 1
759bf215546Sopenharmony_ci          */
760bf215546Sopenharmony_ci         if (vertex_dma->divisor > 1) {
761bf215546Sopenharmony_ci            const uint32_t adjusted_instance_ID_temp =
762bf215546Sopenharmony_ci               pvr_get_temps(&temp_usage,
763bf215546Sopenharmony_ci                             RESERVE_64BIT,
764bf215546Sopenharmony_ci                             "adjusted_instance_ID_temp");
765bf215546Sopenharmony_ci            const uint32_t MADD_temp =
766bf215546Sopenharmony_ci               pvr_get_temps(&temp_usage, RESERVE_64BIT, "MADD_temp");
767bf215546Sopenharmony_ci
768bf215546Sopenharmony_ci            /* 1. Remove base instance value from temp 1 to get instance id
769bf215546Sopenharmony_ci             * 2. Divide the instance id by the divisor - Iout = (Iin *
770bf215546Sopenharmony_ci             *    Multiplier) >> (shift+31)
771bf215546Sopenharmony_ci             * 3. Add the base instance back on.
772bf215546Sopenharmony_ci             *
773bf215546Sopenharmony_ci             * Need two zero temps for the add part of the later MAD.
774bf215546Sopenharmony_ci             */
775bf215546Sopenharmony_ci
776bf215546Sopenharmony_ci            PVR_PDS_MODE_TOGGLE(code,
777bf215546Sopenharmony_ci                                instruction,
778bf215546Sopenharmony_ci                                pvr_pds_inst_encode_add64(
779bf215546Sopenharmony_ci                                   /* cc    */ 0,
780bf215546Sopenharmony_ci                                   /* alum  */ 0,
781bf215546Sopenharmony_ci                                   /* sna   */ 1,
782bf215546Sopenharmony_ci                                   /* src0  */ R64_T(MADD_temp >> 1),
783bf215546Sopenharmony_ci                                   /* src1  */ R64_T(MADD_temp >> 1),
784bf215546Sopenharmony_ci                                   /* dst   */ R64TP_T(MADD_temp >> 1)));
785bf215546Sopenharmony_ci
786bf215546Sopenharmony_ci            if (input_program->flags &
787bf215546Sopenharmony_ci                PVR_PDS_VERTEX_FLAGS_DRAW_INDIRECT_VARIANT) {
788bf215546Sopenharmony_ci               /* Subtract base instance from temp 1, put into
789bf215546Sopenharmony_ci                * adjusted_instance_ID_temp.
790bf215546Sopenharmony_ci                */
791bf215546Sopenharmony_ci               PVR_PDS_MODE_TOGGLE(
792bf215546Sopenharmony_ci                  code,
793bf215546Sopenharmony_ci                  instruction,
794bf215546Sopenharmony_ci                  pvr_pds_inst_encode_add32(
795bf215546Sopenharmony_ci                     /* cc    */ 0,
796bf215546Sopenharmony_ci                     /* alum  */ 0,
797bf215546Sopenharmony_ci                     /* sna   */ 1,
798bf215546Sopenharmony_ci                     /* src0  */ R32_T(instance_ID_temp),
799bf215546Sopenharmony_ci                     /* src1  */ R32_P(PVR_INDIRECT_BASE_INSTANCE_PTEMP),
800bf215546Sopenharmony_ci                     /* dst   */ R32TP_T(adjusted_instance_ID_temp)));
801bf215546Sopenharmony_ci            } else if (input_program->flags &
802bf215546Sopenharmony_ci                       PVR_PDS_VERTEX_FLAGS_BASE_INSTANCE_VARIANT) {
803bf215546Sopenharmony_ci               /* Subtract base instance from temp 1, put into
804bf215546Sopenharmony_ci                * adjusted_instance_ID_temp.
805bf215546Sopenharmony_ci                */
806bf215546Sopenharmony_ci               PVR_PDS_MODE_TOGGLE(
807bf215546Sopenharmony_ci                  code,
808bf215546Sopenharmony_ci                  instruction,
809bf215546Sopenharmony_ci                  pvr_pds_inst_encode_add32(
810bf215546Sopenharmony_ci                     /* cc    */ 0,
811bf215546Sopenharmony_ci                     /* alum  */ 0,
812bf215546Sopenharmony_ci                     /* sna   */ 1,
813bf215546Sopenharmony_ci                     /* src0  */ R32_T(instance_ID_temp),
814bf215546Sopenharmony_ci                     /* src1  */ R32_C(base_instance),
815bf215546Sopenharmony_ci                     /* dst   */ R32TP_T(adjusted_instance_ID_temp)));
816bf215546Sopenharmony_ci            } else {
817bf215546Sopenharmony_ci               /* Copy instance from temp 1 to adjusted_instance_ID_temp.
818bf215546Sopenharmony_ci                */
819bf215546Sopenharmony_ci               PVR_PDS_MODE_TOGGLE(
820bf215546Sopenharmony_ci                  code,
821bf215546Sopenharmony_ci                  instruction,
822bf215546Sopenharmony_ci                  pvr_pds_inst_encode_add32(
823bf215546Sopenharmony_ci                     /* cc    */ 0,
824bf215546Sopenharmony_ci                     /* alum  */ 0,
825bf215546Sopenharmony_ci                     /* sna   */ 0,
826bf215546Sopenharmony_ci                     /* src0  */ R32_T(instance_ID_temp),
827bf215546Sopenharmony_ci                     /* src1  */ R32_T(MADD_temp), /* MADD_temp is set
828bf215546Sopenharmony_ci                                                    * to 0 at this point.
829bf215546Sopenharmony_ci                                                    */
830bf215546Sopenharmony_ci                     /* dst   */ R32TP_T(adjusted_instance_ID_temp)));
831bf215546Sopenharmony_ci            }
832bf215546Sopenharmony_ci
833bf215546Sopenharmony_ci            /* shift = the bit of the next highest power of two. */
834bf215546Sopenharmony_ci            uint32_t shift_unsigned =
835bf215546Sopenharmony_ci               (31 - __builtin_clz(vertex_dma->divisor - 1)) + 1;
836bf215546Sopenharmony_ci            int32_t shift = (int32_t)shift_unsigned;
837bf215546Sopenharmony_ci            uint32_t shift_2s_comp;
838bf215546Sopenharmony_ci
839bf215546Sopenharmony_ci            pvr_debug_pds_note(
840bf215546Sopenharmony_ci               "Perform instance rate divide (as integer multiply and rshift)");
841bf215546Sopenharmony_ci
842bf215546Sopenharmony_ci            const uint32_t multipier_constant =
843bf215546Sopenharmony_ci               pvr_find_constant(const_usage,
844bf215546Sopenharmony_ci                                 RESERVE_32BIT,
845bf215546Sopenharmony_ci                                 "MultiplierConstant (for InstanceDivisor)");
846bf215546Sopenharmony_ci
847bf215546Sopenharmony_ci            /* multiplier = ( 2^(shift + 31) + (divisor - 1) ) / divisor,
848bf215546Sopenharmony_ci               note: the division above is integer division. */
849bf215546Sopenharmony_ci            uint64_t multipier64 =
850bf215546Sopenharmony_ci               (uint64_t)((((uint64_t)1 << ((uint64_t)shift_unsigned + 31)) +
851bf215546Sopenharmony_ci                           ((uint64_t)vertex_dma->divisor - (uint64_t)1)) /
852bf215546Sopenharmony_ci                          (uint64_t)vertex_dma->divisor);
853bf215546Sopenharmony_ci            uint32_t multiplier = (uint32_t)multipier64;
854bf215546Sopenharmony_ci
855bf215546Sopenharmony_ci            pvr_debug_pds_note(" - Value of MultiplierConstant = %u",
856bf215546Sopenharmony_ci                               multiplier);
857bf215546Sopenharmony_ci            pvr_debug_pds_note(" - Value of Shift = %d", shift);
858bf215546Sopenharmony_ci
859bf215546Sopenharmony_ci            literal_entry =
860bf215546Sopenharmony_ci               pvr_prepare_next_pds_const_map_entry(&entry_write_state,
861bf215546Sopenharmony_ci                                                    sizeof(*literal_entry));
862bf215546Sopenharmony_ci            literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32;
863bf215546Sopenharmony_ci            literal_entry->const_offset = multipier_constant;
864bf215546Sopenharmony_ci            literal_entry->literal_value = multiplier;
865bf215546Sopenharmony_ci
866bf215546Sopenharmony_ci            /* (Iin * Multiplier) */
867bf215546Sopenharmony_ci            PVR_PDS_MODE_TOGGLE(
868bf215546Sopenharmony_ci               code,
869bf215546Sopenharmony_ci               instruction,
870bf215546Sopenharmony_ci               pvr_rogue_inst_encode_mad(0, /* Sign of add is positive */
871bf215546Sopenharmony_ci                                         0, /* Unsigned ALU mode */
872bf215546Sopenharmony_ci                                         0, /* Unconditional */
873bf215546Sopenharmony_ci                                         R32_C(multipier_constant),
874bf215546Sopenharmony_ci                                         R32_T(adjusted_instance_ID_temp),
875bf215546Sopenharmony_ci                                         R64_T(MADD_temp / 2),
876bf215546Sopenharmony_ci                                         R64TP_T(MADD_temp / 2)));
877bf215546Sopenharmony_ci
878bf215546Sopenharmony_ci            /*  >> (shift + 31) */
879bf215546Sopenharmony_ci            shift += 31;
880bf215546Sopenharmony_ci            shift *= -1;
881bf215546Sopenharmony_ci
882bf215546Sopenharmony_ci            if (shift < -31) {
883bf215546Sopenharmony_ci               /* >> (31) */
884bf215546Sopenharmony_ci               shift_2s_comp = 0xFFFE1;
885bf215546Sopenharmony_ci               PVR_PDS_MODE_TOGGLE(code,
886bf215546Sopenharmony_ci                                   instruction,
887bf215546Sopenharmony_ci                                   pvr_pds_inst_encode_stflp64(
888bf215546Sopenharmony_ci                                      /* cc */ 0,
889bf215546Sopenharmony_ci                                      /* LOP */ PVR_ROGUE_PDSINST_LOP_NONE,
890bf215546Sopenharmony_ci                                      /* IM */ 1, /*  enable immediate */
891bf215546Sopenharmony_ci                                      /* SRC0 */ R64_T(MADD_temp / 2),
892bf215546Sopenharmony_ci                                      /* SRC1 */ 0, /* This won't be used
893bf215546Sopenharmony_ci                                                       in a shift
894bf215546Sopenharmony_ci                                                       operation. */
895bf215546Sopenharmony_ci                                      /* SRC2 (Shift) */ shift_2s_comp,
896bf215546Sopenharmony_ci                                      /* DST */ R64TP_T(MADD_temp / 2)));
897bf215546Sopenharmony_ci               shift += 31;
898bf215546Sopenharmony_ci            }
899bf215546Sopenharmony_ci
900bf215546Sopenharmony_ci            /* >> (shift + 31) */
901bf215546Sopenharmony_ci            shift_2s_comp = *((uint32_t *)&shift);
902bf215546Sopenharmony_ci            PVR_PDS_MODE_TOGGLE(code,
903bf215546Sopenharmony_ci                                instruction,
904bf215546Sopenharmony_ci                                pvr_pds_inst_encode_stflp64(
905bf215546Sopenharmony_ci                                   /* cc */ 0,
906bf215546Sopenharmony_ci                                   /* LOP */ PVR_ROGUE_PDSINST_LOP_NONE,
907bf215546Sopenharmony_ci                                   /* IM */ 1, /*  enable immediate */
908bf215546Sopenharmony_ci                                   /* SRC0 */ R64_T(MADD_temp / 2),
909bf215546Sopenharmony_ci                                   /* SRC1 */ 0, /* This won't be used
910bf215546Sopenharmony_ci                                                  * in a shift
911bf215546Sopenharmony_ci                                                  * operation. */
912bf215546Sopenharmony_ci                                   /* SRC2 (Shift) */ shift_2s_comp,
913bf215546Sopenharmony_ci                                   /* DST */ R64TP_T(MADD_temp / 2)));
914bf215546Sopenharmony_ci
915bf215546Sopenharmony_ci            if (input_program->flags &
916bf215546Sopenharmony_ci                PVR_PDS_VERTEX_FLAGS_DRAW_INDIRECT_VARIANT) {
917bf215546Sopenharmony_ci               /* Add base instance. */
918bf215546Sopenharmony_ci               PVR_PDS_MODE_TOGGLE(
919bf215546Sopenharmony_ci                  code,
920bf215546Sopenharmony_ci                  instruction,
921bf215546Sopenharmony_ci                  pvr_pds_inst_encode_add32(
922bf215546Sopenharmony_ci                     /* cc    */ 0,
923bf215546Sopenharmony_ci                     /* alum  */ 0,
924bf215546Sopenharmony_ci                     /* sna   */ 0,
925bf215546Sopenharmony_ci                     /* src0  */ R32_T(MADD_temp),
926bf215546Sopenharmony_ci                     /* src1  */ R32_P(PVR_INDIRECT_BASE_INSTANCE_PTEMP),
927bf215546Sopenharmony_ci                     /* dst   */ R32TP_T(MADD_temp)));
928bf215546Sopenharmony_ci            } else if (input_program->flags &
929bf215546Sopenharmony_ci                       PVR_PDS_VERTEX_FLAGS_BASE_INSTANCE_VARIANT) {
930bf215546Sopenharmony_ci               /* Add base instance. */
931bf215546Sopenharmony_ci               PVR_PDS_MODE_TOGGLE(code,
932bf215546Sopenharmony_ci                                   instruction,
933bf215546Sopenharmony_ci                                   pvr_pds_inst_encode_add32(
934bf215546Sopenharmony_ci                                      /* cc    */ 0,
935bf215546Sopenharmony_ci                                      /* alum  */ 0,
936bf215546Sopenharmony_ci                                      /* sna   */ 0,
937bf215546Sopenharmony_ci                                      /* src0  */ R32_T(MADD_temp),
938bf215546Sopenharmony_ci                                      /* src1  */ R32_C(base_instance),
939bf215546Sopenharmony_ci                                      /* dst   */ R32TP_T(MADD_temp)));
940bf215546Sopenharmony_ci            }
941bf215546Sopenharmony_ci
942bf215546Sopenharmony_ci            pvr_debug_pds_note(
943bf215546Sopenharmony_ci               "DMA Vertex Index will be sourced from 'MADD_temp'");
944bf215546Sopenharmony_ci            index = MADD_temp;
945bf215546Sopenharmony_ci         } else if (vertex_dma->divisor == 0) {
946bf215546Sopenharmony_ci            if (base_instance_ID_temp == PVR_INVALID_TEMP) {
947bf215546Sopenharmony_ci               base_instance_ID_temp = pvr_get_temps(&temp_usage,
948bf215546Sopenharmony_ci                                                     RESERVE_32BIT,
949bf215546Sopenharmony_ci                                                     "uBaseInstanceIDTemp");
950bf215546Sopenharmony_ci            }
951bf215546Sopenharmony_ci
952bf215546Sopenharmony_ci            /* Load 0 into instance_ID_temp. */
953bf215546Sopenharmony_ci            PVR_PDS_MODE_TOGGLE(code,
954bf215546Sopenharmony_ci                                instruction,
955bf215546Sopenharmony_ci                                pvr_pds_inst_encode_limm(
956bf215546Sopenharmony_ci                                   /* cc       */ 0,
957bf215546Sopenharmony_ci                                   /* src1     */ base_instance_ID_temp,
958bf215546Sopenharmony_ci                                   /* src0     */ 0,
959bf215546Sopenharmony_ci                                   /* gr       */ 0));
960bf215546Sopenharmony_ci
961bf215546Sopenharmony_ci            if (input_program->flags &
962bf215546Sopenharmony_ci                PVR_PDS_VERTEX_FLAGS_DRAW_INDIRECT_VARIANT) {
963bf215546Sopenharmony_ci               /* Add base instance. */
964bf215546Sopenharmony_ci               PVR_PDS_MODE_TOGGLE(
965bf215546Sopenharmony_ci                  code,
966bf215546Sopenharmony_ci                  instruction,
967bf215546Sopenharmony_ci                  pvr_pds_inst_encode_add32(
968bf215546Sopenharmony_ci                     /* cc    */ 0,
969bf215546Sopenharmony_ci                     /* alum  */ 0,
970bf215546Sopenharmony_ci                     /* sna   */ 0,
971bf215546Sopenharmony_ci                     /* src0  */ R32_P(PVR_INDIRECT_BASE_INSTANCE_PTEMP),
972bf215546Sopenharmony_ci                     /* src1  */ R32_T(base_instance_ID_temp),
973bf215546Sopenharmony_ci                     /* dst   */ R32TP_T(base_instance_ID_temp)));
974bf215546Sopenharmony_ci
975bf215546Sopenharmony_ci            } else if (input_program->flags &
976bf215546Sopenharmony_ci                       PVR_PDS_VERTEX_FLAGS_BASE_INSTANCE_VARIANT) {
977bf215546Sopenharmony_ci               /* Add base instance. */
978bf215546Sopenharmony_ci               PVR_PDS_MODE_TOGGLE(
979bf215546Sopenharmony_ci                  code,
980bf215546Sopenharmony_ci                  instruction,
981bf215546Sopenharmony_ci                  pvr_pds_inst_encode_add32(
982bf215546Sopenharmony_ci                     /* cc    */ 0,
983bf215546Sopenharmony_ci                     /* alum  */ 0,
984bf215546Sopenharmony_ci                     /* sna   */ 0,
985bf215546Sopenharmony_ci                     /* src0  */ R32_C(base_instance),
986bf215546Sopenharmony_ci                     /* src1  */ R32_T(base_instance_ID_temp),
987bf215546Sopenharmony_ci                     /* dst   */ R32TP_T(base_instance_ID_temp)));
988bf215546Sopenharmony_ci            }
989bf215546Sopenharmony_ci
990bf215546Sopenharmony_ci            pvr_debug_pds_note(
991bf215546Sopenharmony_ci               "DMA Vertex Index will be sourced from 'uBaseInstanceIdTemp'");
992bf215546Sopenharmony_ci            index = base_instance_ID_temp;
993bf215546Sopenharmony_ci         } else {
994bf215546Sopenharmony_ci            pvr_debug_pds_note(
995bf215546Sopenharmony_ci               "DMA Vertex Index will be sourced from 'uInstanceIdTemp'");
996bf215546Sopenharmony_ci            index = instance_ID_temp;
997bf215546Sopenharmony_ci         }
998bf215546Sopenharmony_ci      } else {
999bf215546Sopenharmony_ci         pvr_debug_pds_note(
1000bf215546Sopenharmony_ci            "DMA Vertex Index will be sourced from 'uIndexIdTemp'");
1001bf215546Sopenharmony_ci         index = index_id_temp;
1002bf215546Sopenharmony_ci      }
1003bf215546Sopenharmony_ci
1004bf215546Sopenharmony_ci      /* DDMAD Const Usage [__XX_---] */
1005bf215546Sopenharmony_ci      pvr_write_pds_const_map_entry_vertex_attribute_address(
1006bf215546Sopenharmony_ci         &entry_write_state,
1007bf215546Sopenharmony_ci         vertex_dma,
1008bf215546Sopenharmony_ci         const_base + 4,
1009bf215546Sopenharmony_ci         use_robust_vertex_fetch);
1010bf215546Sopenharmony_ci
1011bf215546Sopenharmony_ci      /* DDMAD Const Usage [__XXX---] */
1012bf215546Sopenharmony_ci      literal_entry =
1013bf215546Sopenharmony_ci         pvr_prepare_next_pds_const_map_entry(&entry_write_state,
1014bf215546Sopenharmony_ci                                              sizeof(*literal_entry));
1015bf215546Sopenharmony_ci      literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32;
1016bf215546Sopenharmony_ci      literal_entry->const_offset = const_base + 3;
1017bf215546Sopenharmony_ci      literal_entry->literal_value = vertex_dma->stride;
1018bf215546Sopenharmony_ci
1019bf215546Sopenharmony_ci      control_word = vertex_dma->size_in_dwords
1020bf215546Sopenharmony_ci                     << PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_BSIZE_SHIFT;
1021bf215546Sopenharmony_ci      control_word |= vertex_dma->destination
1022bf215546Sopenharmony_ci                      << PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_AO_SHIFT;
1023bf215546Sopenharmony_ci      control_word |= (PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_DEST_UNIFIED_STORE |
1024bf215546Sopenharmony_ci                       PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_CMODE_CACHED);
1025bf215546Sopenharmony_ci
1026bf215546Sopenharmony_ci      /* DDMADT instructions will do a dummy doutd when OOB if
1027bf215546Sopenharmony_ci       * PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_LAST_EN is set but as the driver
1028bf215546Sopenharmony_ci       * would need to do another doutd after an OOB DDMADT to provide the 'in
1029bf215546Sopenharmony_ci       * bounds' data the DDMADT can't be set as LAST.
1030bf215546Sopenharmony_ci       *
1031bf215546Sopenharmony_ci       * This requires us to include a final dummy DDMAD.LAST instruction.
1032bf215546Sopenharmony_ci       *
1033bf215546Sopenharmony_ci       * Pseudocode taken from SeriesXE2017.PDS Instruction Controller
1034bf215546Sopenharmony_ci       * Specification.doc
1035bf215546Sopenharmony_ci       *
1036bf215546Sopenharmony_ci       *	DDMAD src0,src1,src2,src3
1037bf215546Sopenharmony_ci       *
1038bf215546Sopenharmony_ci       *	calculated_source_address := src0*src1+src2
1039bf215546Sopenharmony_ci       *	base_address              := src2
1040bf215546Sopenharmony_ci       *	dma_parameters            := src3[31:0]
1041bf215546Sopenharmony_ci       *	buffer_size               := src3[63:33]
1042bf215546Sopenharmony_ci       *	test                      := src3[32]
1043bf215546Sopenharmony_ci       *
1044bf215546Sopenharmony_ci       *	if (test == 1) {
1045bf215546Sopenharmony_ci       *	   // DDMAD(T)
1046bf215546Sopenharmony_ci       *	   if (calculated_source_address[39:0] + (burst_size<<2) <=
1047bf215546Sopenharmony_ci       *         base_address[39:0] + buffer_size) {
1048bf215546Sopenharmony_ci       *        OOB := 0
1049bf215546Sopenharmony_ci       *        DOUTD calculated_source_address,dma_paramters
1050bf215546Sopenharmony_ci       *     } else {
1051bf215546Sopenharmony_ci       *        OOB := 1
1052bf215546Sopenharmony_ci       *        if (last_instance == 1) {
1053bf215546Sopenharmony_ci       *           dma_parameters[BURST_SIZE] := 0
1054bf215546Sopenharmony_ci       *           DOUTD calculated_source_address,dma_paramters
1055bf215546Sopenharmony_ci       *	      }
1056bf215546Sopenharmony_ci       *	   }
1057bf215546Sopenharmony_ci       *	} else {
1058bf215546Sopenharmony_ci       *	   // DDMAD
1059bf215546Sopenharmony_ci       *	   DOUTD calculated_source_address,dma_paramters
1060bf215546Sopenharmony_ci       *	}
1061bf215546Sopenharmony_ci       */
1062bf215546Sopenharmony_ci
1063bf215546Sopenharmony_ci      if (last_DMA && (!PVR_HAS_FEATURE(dev_info, pds_ddmadt) ||
1064bf215546Sopenharmony_ci                       !use_robust_vertex_fetch)) {
1065bf215546Sopenharmony_ci         pvr_debug_pds_note("LAST DDMAD");
1066bf215546Sopenharmony_ci         control_word |= PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_LAST_EN;
1067bf215546Sopenharmony_ci      }
1068bf215546Sopenharmony_ci
1069bf215546Sopenharmony_ci      /* DDMAD Const Usage [_XXXX---] */
1070bf215546Sopenharmony_ci      literal_entry =
1071bf215546Sopenharmony_ci         pvr_prepare_next_pds_const_map_entry(&entry_write_state,
1072bf215546Sopenharmony_ci                                              sizeof(*literal_entry));
1073bf215546Sopenharmony_ci      literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32;
1074bf215546Sopenharmony_ci      literal_entry->const_offset = (const_base + 6);
1075bf215546Sopenharmony_ci      literal_entry->literal_value = control_word;
1076bf215546Sopenharmony_ci
1077bf215546Sopenharmony_ci      if (PVR_HAS_FEATURE(dev_info, pds_ddmadt)) {
1078bf215546Sopenharmony_ci         /* DDMAD Const Usage [XXXXX---]
1079bf215546Sopenharmony_ci          * With DDMADT an extra 32bits of SRC3 contains the information for
1080bf215546Sopenharmony_ci          * performing out-of-bounds tests on the DMA.
1081bf215546Sopenharmony_ci          */
1082bf215546Sopenharmony_ci
1083bf215546Sopenharmony_ci         if (use_robust_vertex_fetch) {
1084bf215546Sopenharmony_ci            struct pvr_pds_const_map_entry_vertex_attr_ddmadt_oob_buffer_size
1085bf215546Sopenharmony_ci               *obb_buffer_size;
1086bf215546Sopenharmony_ci            obb_buffer_size =
1087bf215546Sopenharmony_ci               pvr_prepare_next_pds_const_map_entry(&entry_write_state,
1088bf215546Sopenharmony_ci                                                    sizeof(*obb_buffer_size));
1089bf215546Sopenharmony_ci
1090bf215546Sopenharmony_ci            obb_buffer_size->type =
1091bf215546Sopenharmony_ci               PVR_PDS_CONST_MAP_ENTRY_TYPE_VERTEX_ATTR_DDMADT_OOB_BUFFER_SIZE;
1092bf215546Sopenharmony_ci            obb_buffer_size->const_offset = const_base + 7;
1093bf215546Sopenharmony_ci            obb_buffer_size->binding_index = vertex_dma->binding_index;
1094bf215546Sopenharmony_ci         } else {
1095bf215546Sopenharmony_ci            literal_entry =
1096bf215546Sopenharmony_ci               pvr_prepare_next_pds_const_map_entry(&entry_write_state,
1097bf215546Sopenharmony_ci                                                    sizeof(*literal_entry));
1098bf215546Sopenharmony_ci            literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32;
1099bf215546Sopenharmony_ci            literal_entry->const_offset = const_base + 7;
1100bf215546Sopenharmony_ci            literal_entry->literal_value = 0;
1101bf215546Sopenharmony_ci         }
1102bf215546Sopenharmony_ci
1103bf215546Sopenharmony_ci         PVR_PDS_MODE_TOGGLE(
1104bf215546Sopenharmony_ci            code,
1105bf215546Sopenharmony_ci            instruction,
1106bf215546Sopenharmony_ci            pvr_pds_inst_encode_ddmad(0, /* cc */
1107bf215546Sopenharmony_ci                                      0, /* END */
1108bf215546Sopenharmony_ci                                      R32_C(const_base + 3), /* SRC0 (REGS32) */
1109bf215546Sopenharmony_ci                                      index, /* SRC1 (REGS32T) */
1110bf215546Sopenharmony_ci                                      R64_C((const_base + 4) >> 1), /* SRC2
1111bf215546Sopenharmony_ci                                                                     * (REGS64)
1112bf215546Sopenharmony_ci                                                                     */
1113bf215546Sopenharmony_ci                                      R64_C((const_base + 6) >> 1) /* SRC3
1114bf215546Sopenharmony_ci                                                                    * (REGS64C)
1115bf215546Sopenharmony_ci                                                                    */
1116bf215546Sopenharmony_ci                                      ));
1117bf215546Sopenharmony_ci
1118bf215546Sopenharmony_ci         if (use_robust_vertex_fetch) {
1119bf215546Sopenharmony_ci            /* If not out of bounds, skip next DDMAD instructions. */
1120bf215546Sopenharmony_ci            PVR_PDS_MODE_TOGGLE(code,
1121bf215546Sopenharmony_ci                                instruction,
1122bf215546Sopenharmony_ci                                pvr_pds_inst_encode_ddmad(
1123bf215546Sopenharmony_ci                                   1, /* cc */
1124bf215546Sopenharmony_ci                                   0, /* END */
1125bf215546Sopenharmony_ci                                   R32_C(const_base + 3), /* SRC0 (REGS32) */
1126bf215546Sopenharmony_ci                                   R32_T(zero_temp), /* SRC1 (REGS32T) */
1127bf215546Sopenharmony_ci                                   R64_C((const_base + 4) >> 1), /* SRC2
1128bf215546Sopenharmony_ci                                                                  * (REGS64)
1129bf215546Sopenharmony_ci                                                                  */
1130bf215546Sopenharmony_ci                                   R64_C((const_base + 6) >> 1) /* SRC3
1131bf215546Sopenharmony_ci                                                                 * (REGS64C)
1132bf215546Sopenharmony_ci                                                                 */
1133bf215546Sopenharmony_ci                                   ));
1134bf215546Sopenharmony_ci
1135bf215546Sopenharmony_ci            /* Now the driver must have a dummy DDMAD marked as last. */
1136bf215546Sopenharmony_ci            if (last_DMA) {
1137bf215546Sopenharmony_ci               uint32_t dummy_dma_const = pvr_find_constant(const_usage,
1138bf215546Sopenharmony_ci                                                            RESERVE_64BIT,
1139bf215546Sopenharmony_ci                                                            "uDummyDMAConst");
1140bf215546Sopenharmony_ci               uint32_t zero_const =
1141bf215546Sopenharmony_ci                  pvr_find_constant(const_usage, RESERVE_64BIT, "uZeroConst");
1142bf215546Sopenharmony_ci
1143bf215546Sopenharmony_ci               literal_entry =
1144bf215546Sopenharmony_ci                  pvr_prepare_next_pds_const_map_entry(&entry_write_state,
1145bf215546Sopenharmony_ci                                                       sizeof(*literal_entry));
1146bf215546Sopenharmony_ci               literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32;
1147bf215546Sopenharmony_ci               literal_entry->const_offset = zero_const;
1148bf215546Sopenharmony_ci               literal_entry->literal_value = 0;
1149bf215546Sopenharmony_ci
1150bf215546Sopenharmony_ci               literal_entry =
1151bf215546Sopenharmony_ci                  pvr_prepare_next_pds_const_map_entry(&entry_write_state,
1152bf215546Sopenharmony_ci                                                       sizeof(*literal_entry));
1153bf215546Sopenharmony_ci               literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32;
1154bf215546Sopenharmony_ci               literal_entry->const_offset = zero_const + 1;
1155bf215546Sopenharmony_ci               literal_entry->literal_value = 0;
1156bf215546Sopenharmony_ci
1157bf215546Sopenharmony_ci               literal_entry =
1158bf215546Sopenharmony_ci                  pvr_prepare_next_pds_const_map_entry(&entry_write_state,
1159bf215546Sopenharmony_ci                                                       sizeof(*literal_entry));
1160bf215546Sopenharmony_ci               literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32;
1161bf215546Sopenharmony_ci               literal_entry->const_offset = dummy_dma_const;
1162bf215546Sopenharmony_ci               literal_entry->literal_value = 0;
1163bf215546Sopenharmony_ci
1164bf215546Sopenharmony_ci               literal_entry->literal_value |=
1165bf215546Sopenharmony_ci                  0 << PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_BSIZE_SHIFT;
1166bf215546Sopenharmony_ci               literal_entry->literal_value |=
1167bf215546Sopenharmony_ci                  (PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_DEST_UNIFIED_STORE |
1168bf215546Sopenharmony_ci                   PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_CMODE_CACHED);
1169bf215546Sopenharmony_ci               literal_entry->literal_value |=
1170bf215546Sopenharmony_ci                  PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_LAST_EN;
1171bf215546Sopenharmony_ci
1172bf215546Sopenharmony_ci               literal_entry =
1173bf215546Sopenharmony_ci                  pvr_prepare_next_pds_const_map_entry(&entry_write_state,
1174bf215546Sopenharmony_ci                                                       sizeof(*literal_entry));
1175bf215546Sopenharmony_ci               literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32;
1176bf215546Sopenharmony_ci               literal_entry->const_offset = dummy_dma_const + 1;
1177bf215546Sopenharmony_ci               literal_entry->literal_value = 0;
1178bf215546Sopenharmony_ci
1179bf215546Sopenharmony_ci               PVR_PDS_MODE_TOGGLE(code,
1180bf215546Sopenharmony_ci                                   instruction,
1181bf215546Sopenharmony_ci                                   pvr_pds_inst_encode_ddmad(
1182bf215546Sopenharmony_ci                                      0, /* cc */
1183bf215546Sopenharmony_ci                                      0, /* END */
1184bf215546Sopenharmony_ci                                      R32_C(zero_const), /* SRC0 (REGS32)
1185bf215546Sopenharmony_ci                                                          */
1186bf215546Sopenharmony_ci                                      R32_T(zero_temp), /* SRC1 (REGS32T)
1187bf215546Sopenharmony_ci                                                         */
1188bf215546Sopenharmony_ci                                      R64_C((dummy_dma_const) >> 1), /* SRC2
1189bf215546Sopenharmony_ci                                                                        (REGS64)
1190bf215546Sopenharmony_ci                                                                     */
1191bf215546Sopenharmony_ci                                      R64_C((dummy_dma_const) >> 1) /* SRC3
1192bf215546Sopenharmony_ci                                                                       (REGS64C)
1193bf215546Sopenharmony_ci                                                                    */
1194bf215546Sopenharmony_ci                                      ));
1195bf215546Sopenharmony_ci            }
1196bf215546Sopenharmony_ci         }
1197bf215546Sopenharmony_ci      } else {
1198bf215546Sopenharmony_ci         if (use_robust_vertex_fetch) {
1199bf215546Sopenharmony_ci            struct pvr_const_map_entry_vertex_attribute_max_index
1200bf215546Sopenharmony_ci               *max_index_entry;
1201bf215546Sopenharmony_ci
1202bf215546Sopenharmony_ci            pvr_debug("RobustVertexFetch DDMAD");
1203bf215546Sopenharmony_ci
1204bf215546Sopenharmony_ci            const uint32_t max_index_const =
1205bf215546Sopenharmony_ci               pvr_find_constant(const_usage, RESERVE_32BIT, "max_index_const");
1206bf215546Sopenharmony_ci
1207bf215546Sopenharmony_ci            max_index_entry =
1208bf215546Sopenharmony_ci               pvr_prepare_next_pds_const_map_entry(&entry_write_state,
1209bf215546Sopenharmony_ci                                                    sizeof(*max_index_entry));
1210bf215546Sopenharmony_ci            max_index_entry->const_offset = max_index_const;
1211bf215546Sopenharmony_ci            max_index_entry->type =
1212bf215546Sopenharmony_ci               PVR_PDS_CONST_MAP_ENTRY_TYPE_VERTEX_ATTRIBUTE_MAX_INDEX;
1213bf215546Sopenharmony_ci            max_index_entry->binding_index = vertex_dma->binding_index;
1214bf215546Sopenharmony_ci            max_index_entry->offset = vertex_dma->offset;
1215bf215546Sopenharmony_ci            max_index_entry->stride = vertex_dma->stride;
1216bf215546Sopenharmony_ci            max_index_entry->size_in_dwords = vertex_dma->size_in_dwords;
1217bf215546Sopenharmony_ci            max_index_entry->component_size_in_bytes =
1218bf215546Sopenharmony_ci               vertex_dma->component_size_in_bytes;
1219bf215546Sopenharmony_ci
1220bf215546Sopenharmony_ci            PVR_PDS_MODE_TOGGLE(
1221bf215546Sopenharmony_ci               code,
1222bf215546Sopenharmony_ci               instruction,
1223bf215546Sopenharmony_ci               pvr_pds_inst_encode_add32(0, /* cc */
1224bf215546Sopenharmony_ci                                         0, /* ALUM */
1225bf215546Sopenharmony_ci                                         PVR_ROGUE_PDSINST_LOP_NONE, /* SNA */
1226bf215546Sopenharmony_ci                                         R32_C(max_index_const), /* SRC0
1227bf215546Sopenharmony_ci                                                                  * (REGS32)
1228bf215546Sopenharmony_ci                                                                  */
1229bf215546Sopenharmony_ci                                         R32_T(zero_temp), /* SRC1 (REGS32) */
1230bf215546Sopenharmony_ci                                         R32TP_T(max_index_temp) /* DST
1231bf215546Sopenharmony_ci                                                                  * (REG32TP)
1232bf215546Sopenharmony_ci                                                                  */
1233bf215546Sopenharmony_ci                                         ));
1234bf215546Sopenharmony_ci
1235bf215546Sopenharmony_ci            PVR_PDS_MODE_TOGGLE(code,
1236bf215546Sopenharmony_ci                                instruction,
1237bf215546Sopenharmony_ci                                pvr_pds_inst_encode_stflp32(
1238bf215546Sopenharmony_ci                                   1, /* IM */
1239bf215546Sopenharmony_ci                                   0, /* cc */
1240bf215546Sopenharmony_ci                                   PVR_ROGUE_PDSINST_LOP_NONE, /* LOP */
1241bf215546Sopenharmony_ci                                   index, /* SRC0 (REGS32T) */
1242bf215546Sopenharmony_ci                                   0, /* SRC1 (REGS32) */
1243bf215546Sopenharmony_ci                                   0, /* SRC2 (REG32TP) */
1244bf215546Sopenharmony_ci                                   R32TP_T(current_index_temp) /* DST
1245bf215546Sopenharmony_ci                                                                * (REG32TP)
1246bf215546Sopenharmony_ci                                                                */
1247bf215546Sopenharmony_ci                                   ));
1248bf215546Sopenharmony_ci
1249bf215546Sopenharmony_ci            PVR_PDS_MODE_TOGGLE(
1250bf215546Sopenharmony_ci               code,
1251bf215546Sopenharmony_ci               instruction,
1252bf215546Sopenharmony_ci               pvr_pds_inst_encode_cmp(
1253bf215546Sopenharmony_ci                  0, /* cc enable */
1254bf215546Sopenharmony_ci                  PVR_ROGUE_PDSINST_COP_GT, /* Operation */
1255bf215546Sopenharmony_ci                  R64TP_T(current_index_temp >> 1), /* SRC
1256bf215546Sopenharmony_ci                                                     * (REGS64TP)
1257bf215546Sopenharmony_ci                                                     */
1258bf215546Sopenharmony_ci                  R64_T(max_index_temp >> 1) /* SRC1 (REGS64) */
1259bf215546Sopenharmony_ci                  ));
1260bf215546Sopenharmony_ci
1261bf215546Sopenharmony_ci            PVR_PDS_MODE_TOGGLE(code,
1262bf215546Sopenharmony_ci                                instruction,
1263bf215546Sopenharmony_ci                                pvr_pds_inst_encode_stflp32(
1264bf215546Sopenharmony_ci                                   1, /* IM */
1265bf215546Sopenharmony_ci                                   1, /* cc */
1266bf215546Sopenharmony_ci                                   PVR_ROGUE_PDSINST_LOP_NONE, /* LOP */
1267bf215546Sopenharmony_ci                                   zero_temp, /* SRC0 (REGS32T) */
1268bf215546Sopenharmony_ci                                   0, /* SRC1 (REGS32) */
1269bf215546Sopenharmony_ci                                   0, /* SRC2 (REG32TP) */
1270bf215546Sopenharmony_ci                                   R32TP_T(current_index_temp) /* DST
1271bf215546Sopenharmony_ci                                                                * (REG32TP)
1272bf215546Sopenharmony_ci                                                                */
1273bf215546Sopenharmony_ci                                   ));
1274bf215546Sopenharmony_ci
1275bf215546Sopenharmony_ci            PVR_PDS_MODE_TOGGLE(code,
1276bf215546Sopenharmony_ci                                instruction,
1277bf215546Sopenharmony_ci                                pvr_pds_inst_encode_ddmad(
1278bf215546Sopenharmony_ci                                   0, /* cc  */
1279bf215546Sopenharmony_ci                                   0, /* END */
1280bf215546Sopenharmony_ci                                   R32_C(const_base + 3), /* SRC0 (REGS32) */
1281bf215546Sopenharmony_ci                                   current_index_temp, /* SRC1 (REGS32T) */
1282bf215546Sopenharmony_ci                                   R64_C((const_base + 4) >> 1), /* SRC2
1283bf215546Sopenharmony_ci                                                                  * (REGS64)
1284bf215546Sopenharmony_ci                                                                  */
1285bf215546Sopenharmony_ci                                   (const_base + 6) >> 1 /* SRC3 (REGS64C) */
1286bf215546Sopenharmony_ci                                   ));
1287bf215546Sopenharmony_ci         } else {
1288bf215546Sopenharmony_ci            PVR_PDS_MODE_TOGGLE(code,
1289bf215546Sopenharmony_ci                                instruction,
1290bf215546Sopenharmony_ci                                pvr_pds_inst_encode_ddmad(
1291bf215546Sopenharmony_ci                                   /* cc    */ 0,
1292bf215546Sopenharmony_ci                                   /* end   */ 0,
1293bf215546Sopenharmony_ci                                   /* src0  */ R32_C(const_base + 3),
1294bf215546Sopenharmony_ci                                   /* src2  */ (index),
1295bf215546Sopenharmony_ci                                   /* src1  */ R64_C((const_base + 4) >> 1),
1296bf215546Sopenharmony_ci                                   /* src3  */ (const_base + 6) >> 1));
1297bf215546Sopenharmony_ci         }
1298bf215546Sopenharmony_ci      }
1299bf215546Sopenharmony_ci   }
1300bf215546Sopenharmony_ci
1301bf215546Sopenharmony_ci   if (input_program->flags & PVR_PDS_VERTEX_FLAGS_VERTEX_ID_REQUIRED) {
1302bf215546Sopenharmony_ci      bool last_DMA = (++running_dma_count == total_dma_count);
1303bf215546Sopenharmony_ci
1304bf215546Sopenharmony_ci      PVR_PDS_MODE_TOGGLE(
1305bf215546Sopenharmony_ci         code,
1306bf215546Sopenharmony_ci         instruction,
1307bf215546Sopenharmony_ci         pvr_encode_direct_write(
1308bf215546Sopenharmony_ci            &entry_write_state,
1309bf215546Sopenharmony_ci            last_DMA,
1310bf215546Sopenharmony_ci            false,
1311bf215546Sopenharmony_ci            R64_C(write_vertex_control),
1312bf215546Sopenharmony_ci            R64_T(0),
1313bf215546Sopenharmony_ci            0x1,
1314bf215546Sopenharmony_ci            input_program->vertex_id_register,
1315bf215546Sopenharmony_ci            PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_DEST_UNIFIED_STORE,
1316bf215546Sopenharmony_ci            dev_info));
1317bf215546Sopenharmony_ci   }
1318bf215546Sopenharmony_ci
1319bf215546Sopenharmony_ci   if (input_program->flags & PVR_PDS_VERTEX_FLAGS_INSTANCE_ID_REQUIRED) {
1320bf215546Sopenharmony_ci      bool last_DMA = (++running_dma_count == total_dma_count);
1321bf215546Sopenharmony_ci
1322bf215546Sopenharmony_ci      PVR_PDS_MODE_TOGGLE(
1323bf215546Sopenharmony_ci         code,
1324bf215546Sopenharmony_ci         instruction,
1325bf215546Sopenharmony_ci         pvr_encode_direct_write(
1326bf215546Sopenharmony_ci            &entry_write_state,
1327bf215546Sopenharmony_ci            last_DMA,
1328bf215546Sopenharmony_ci            false,
1329bf215546Sopenharmony_ci            R64_C(write_instance_control),
1330bf215546Sopenharmony_ci            R64_T(0),
1331bf215546Sopenharmony_ci            0x2,
1332bf215546Sopenharmony_ci            input_program->instance_id_register,
1333bf215546Sopenharmony_ci            PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_DEST_UNIFIED_STORE,
1334bf215546Sopenharmony_ci            dev_info));
1335bf215546Sopenharmony_ci   }
1336bf215546Sopenharmony_ci
1337bf215546Sopenharmony_ci   if (input_program->flags & PVR_PDS_VERTEX_FLAGS_BASE_INSTANCE_REQUIRED) {
1338bf215546Sopenharmony_ci      bool last_DMA = (++running_dma_count == total_dma_count);
1339bf215546Sopenharmony_ci
1340bf215546Sopenharmony_ci      if (input_program->flags & PVR_PDS_VERTEX_FLAGS_DRAW_INDIRECT_VARIANT) {
1341bf215546Sopenharmony_ci         /* Base instance comes from ptemp 1. */
1342bf215546Sopenharmony_ci         PVR_PDS_MODE_TOGGLE(
1343bf215546Sopenharmony_ci            code,
1344bf215546Sopenharmony_ci            instruction,
1345bf215546Sopenharmony_ci            pvr_encode_direct_write(
1346bf215546Sopenharmony_ci               &entry_write_state,
1347bf215546Sopenharmony_ci               last_DMA,
1348bf215546Sopenharmony_ci               false,
1349bf215546Sopenharmony_ci               R64_C(write_base_instance_control),
1350bf215546Sopenharmony_ci               R64_P(PVR_INDIRECT_BASE_INSTANCE_PTEMP >> 1),
1351bf215546Sopenharmony_ci               0x2,
1352bf215546Sopenharmony_ci               input_program->base_instance_register,
1353bf215546Sopenharmony_ci               PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_DEST_UNIFIED_STORE,
1354bf215546Sopenharmony_ci               dev_info));
1355bf215546Sopenharmony_ci      } else {
1356bf215546Sopenharmony_ci         uint32_t data_mask = (base_instance & 1) ? 0x2 : 0x1;
1357bf215546Sopenharmony_ci
1358bf215546Sopenharmony_ci         /* Base instance comes from driver constant. */
1359bf215546Sopenharmony_ci         PVR_PDS_MODE_TOGGLE(
1360bf215546Sopenharmony_ci            code,
1361bf215546Sopenharmony_ci            instruction,
1362bf215546Sopenharmony_ci            pvr_encode_direct_write(
1363bf215546Sopenharmony_ci               &entry_write_state,
1364bf215546Sopenharmony_ci               last_DMA,
1365bf215546Sopenharmony_ci               false,
1366bf215546Sopenharmony_ci               R64_C(write_base_instance_control),
1367bf215546Sopenharmony_ci               R64_C(base_instance >> 1),
1368bf215546Sopenharmony_ci               data_mask,
1369bf215546Sopenharmony_ci               input_program->base_instance_register,
1370bf215546Sopenharmony_ci               PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_DEST_UNIFIED_STORE,
1371bf215546Sopenharmony_ci               dev_info));
1372bf215546Sopenharmony_ci      }
1373bf215546Sopenharmony_ci   }
1374bf215546Sopenharmony_ci
1375bf215546Sopenharmony_ci   if (input_program->flags & PVR_PDS_VERTEX_FLAGS_BASE_VERTEX_REQUIRED) {
1376bf215546Sopenharmony_ci      bool last_DMA = (++running_dma_count == total_dma_count);
1377bf215546Sopenharmony_ci
1378bf215546Sopenharmony_ci      if (input_program->flags & PVR_PDS_VERTEX_FLAGS_DRAW_INDIRECT_VARIANT) {
1379bf215546Sopenharmony_ci         /* Base vertex comes from ptemp 0 (initialized by PDS hardware). */
1380bf215546Sopenharmony_ci         PVR_PDS_MODE_TOGGLE(
1381bf215546Sopenharmony_ci            code,
1382bf215546Sopenharmony_ci            instruction,
1383bf215546Sopenharmony_ci            pvr_encode_direct_write(
1384bf215546Sopenharmony_ci               &entry_write_state,
1385bf215546Sopenharmony_ci               last_DMA,
1386bf215546Sopenharmony_ci               false,
1387bf215546Sopenharmony_ci               R64_C(write_base_vertex_control),
1388bf215546Sopenharmony_ci               R64_P(0),
1389bf215546Sopenharmony_ci               0x1,
1390bf215546Sopenharmony_ci               input_program->base_vertex_register,
1391bf215546Sopenharmony_ci               PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_DEST_UNIFIED_STORE,
1392bf215546Sopenharmony_ci               dev_info));
1393bf215546Sopenharmony_ci      } else {
1394bf215546Sopenharmony_ci         uint32_t data_mask = (base_vertex & 1) ? 0x2 : 0x1;
1395bf215546Sopenharmony_ci
1396bf215546Sopenharmony_ci         /* Base vertex comes from driver constant (literal 0). */
1397bf215546Sopenharmony_ci         PVR_PDS_MODE_TOGGLE(
1398bf215546Sopenharmony_ci            code,
1399bf215546Sopenharmony_ci            instruction,
1400bf215546Sopenharmony_ci            pvr_encode_direct_write(
1401bf215546Sopenharmony_ci               &entry_write_state,
1402bf215546Sopenharmony_ci               last_DMA,
1403bf215546Sopenharmony_ci               false,
1404bf215546Sopenharmony_ci               R64_C(write_base_vertex_control),
1405bf215546Sopenharmony_ci               R64_C(base_vertex >> 1),
1406bf215546Sopenharmony_ci               data_mask,
1407bf215546Sopenharmony_ci               input_program->base_vertex_register,
1408bf215546Sopenharmony_ci               PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_DEST_UNIFIED_STORE,
1409bf215546Sopenharmony_ci               dev_info));
1410bf215546Sopenharmony_ci      }
1411bf215546Sopenharmony_ci   }
1412bf215546Sopenharmony_ci
1413bf215546Sopenharmony_ci   if (input_program->flags & PVR_PDS_VERTEX_FLAGS_DRAW_INDEX_REQUIRED) {
1414bf215546Sopenharmony_ci      bool last_DMA = (++running_dma_count == total_dma_count);
1415bf215546Sopenharmony_ci
1416bf215546Sopenharmony_ci      if (input_program->flags & PVR_PDS_VERTEX_FLAGS_DRAW_INDIRECT_VARIANT) {
1417bf215546Sopenharmony_ci         /* Draw index comes from ptemp 3. */
1418bf215546Sopenharmony_ci         PVR_PDS_MODE_TOGGLE(
1419bf215546Sopenharmony_ci            code,
1420bf215546Sopenharmony_ci            instruction,
1421bf215546Sopenharmony_ci            pvr_encode_direct_write(
1422bf215546Sopenharmony_ci               &entry_write_state,
1423bf215546Sopenharmony_ci               last_DMA,
1424bf215546Sopenharmony_ci               false,
1425bf215546Sopenharmony_ci               R64_C(pvr_write_draw_index_control),
1426bf215546Sopenharmony_ci               R64_P(1),
1427bf215546Sopenharmony_ci               0x2,
1428bf215546Sopenharmony_ci               input_program->draw_index_register,
1429bf215546Sopenharmony_ci               PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_DEST_UNIFIED_STORE,
1430bf215546Sopenharmony_ci               dev_info));
1431bf215546Sopenharmony_ci      } else {
1432bf215546Sopenharmony_ci         uint32_t data_mask = (draw_index & 1) ? 0x2 : 0x1;
1433bf215546Sopenharmony_ci
1434bf215546Sopenharmony_ci         /* Draw index comes from constant (literal 0). */
1435bf215546Sopenharmony_ci         PVR_PDS_MODE_TOGGLE(
1436bf215546Sopenharmony_ci            code,
1437bf215546Sopenharmony_ci            instruction,
1438bf215546Sopenharmony_ci            pvr_encode_direct_write(
1439bf215546Sopenharmony_ci               &entry_write_state,
1440bf215546Sopenharmony_ci               last_DMA,
1441bf215546Sopenharmony_ci               false,
1442bf215546Sopenharmony_ci               R64_C(pvr_write_draw_index_control),
1443bf215546Sopenharmony_ci               R64_C(draw_index >> 1),
1444bf215546Sopenharmony_ci               data_mask,
1445bf215546Sopenharmony_ci               input_program->draw_index_register,
1446bf215546Sopenharmony_ci               PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_DEST_UNIFIED_STORE,
1447bf215546Sopenharmony_ci               dev_info));
1448bf215546Sopenharmony_ci      }
1449bf215546Sopenharmony_ci   }
1450bf215546Sopenharmony_ci
1451bf215546Sopenharmony_ci   doutu_address_entry =
1452bf215546Sopenharmony_ci      pvr_prepare_next_pds_const_map_entry(&entry_write_state,
1453bf215546Sopenharmony_ci                                           sizeof(*doutu_address_entry));
1454bf215546Sopenharmony_ci   doutu_address_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_DOUTU_ADDRESS;
1455bf215546Sopenharmony_ci   doutu_address_entry->const_offset = 0;
1456bf215546Sopenharmony_ci   doutu_address_entry->doutu_control = input_program->usc_task_control.src0;
1457bf215546Sopenharmony_ci
1458bf215546Sopenharmony_ci   if (use_robust_vertex_fetch) {
1459bf215546Sopenharmony_ci      /* Restore IF0 */
1460bf215546Sopenharmony_ci      PVR_PDS_MODE_TOGGLE(
1461bf215546Sopenharmony_ci         code,
1462bf215546Sopenharmony_ci         instruction,
1463bf215546Sopenharmony_ci         pvr_pds_inst_encode_bra(PVR_ROGUE_PDSINST_PREDICATE_KEEP, /* SRCCC */
1464bf215546Sopenharmony_ci                                 0, /* Neg */
1465bf215546Sopenharmony_ci                                 PVR_ROGUE_PDSINST_PREDICATE_IF0, /* SETCC */
1466bf215546Sopenharmony_ci                                 1 /* Addr */
1467bf215546Sopenharmony_ci                                 ));
1468bf215546Sopenharmony_ci   }
1469bf215546Sopenharmony_ci
1470bf215546Sopenharmony_ci   PVR_PDS_MODE_TOGGLE(code, instruction, pvr_pds_encode_doutu(1, 1, 0));
1471bf215546Sopenharmony_ci   PVR_PDS_MODE_TOGGLE(code, instruction, pvr_pds_inst_encode_halt(0));
1472bf215546Sopenharmony_ci
1473bf215546Sopenharmony_ci   assert(running_dma_count == total_dma_count);
1474bf215546Sopenharmony_ci
1475bf215546Sopenharmony_ci   for (uint32_t i = 0; i < ARRAY_SIZE(const_usage); i++) {
1476bf215546Sopenharmony_ci      if (const_usage[i] == 0)
1477bf215546Sopenharmony_ci         break;
1478bf215546Sopenharmony_ci
1479bf215546Sopenharmony_ci      info->data_size_in_dwords =
1480bf215546Sopenharmony_ci         8 * i + (32 - __builtin_clz((uint32_t)const_usage[i]));
1481bf215546Sopenharmony_ci   }
1482bf215546Sopenharmony_ci
1483bf215546Sopenharmony_ci   info->temps_required = temp_usage.temps_needed;
1484bf215546Sopenharmony_ci   info->entry_count = entry_write_state.entry_count;
1485bf215546Sopenharmony_ci   info->entries_written_size_in_bytes =
1486bf215546Sopenharmony_ci      entry_write_state.entries_size_in_bytes;
1487bf215546Sopenharmony_ci   info->code_size_in_dwords = instruction;
1488bf215546Sopenharmony_ci
1489bf215546Sopenharmony_ci   pvr_debug("=================================================\n");
1490bf215546Sopenharmony_ci}
1491bf215546Sopenharmony_ci
1492bf215546Sopenharmony_civoid pvr_pds_generate_descriptor_upload_program(
1493bf215546Sopenharmony_ci   struct pvr_descriptor_program_input *input_program,
1494bf215546Sopenharmony_ci   uint32_t *code_section,
1495bf215546Sopenharmony_ci   struct pvr_pds_info *info)
1496bf215546Sopenharmony_ci{
1497bf215546Sopenharmony_ci   unsigned int num_consts64;
1498bf215546Sopenharmony_ci   unsigned int num_consts32;
1499bf215546Sopenharmony_ci   unsigned int next_const64;
1500bf215546Sopenharmony_ci   unsigned int next_const32;
1501bf215546Sopenharmony_ci   unsigned int instruction = 0;
1502bf215546Sopenharmony_ci   uint32_t compile_time_buffer_index = 0;
1503bf215546Sopenharmony_ci
1504bf215546Sopenharmony_ci   unsigned int total_dma_count = 0;
1505bf215546Sopenharmony_ci   unsigned int running_dma_count = 0;
1506bf215546Sopenharmony_ci
1507bf215546Sopenharmony_ci   struct pvr_pds_const_map_entry_write_state entry_write_state;
1508bf215546Sopenharmony_ci
1509bf215546Sopenharmony_ci   /* Calculate the total register usage so we can stick 32-bit consts
1510bf215546Sopenharmony_ci    * after 64. Each DOUTD/DDMAD requires 1 32-bit constant and 1 64-bit
1511bf215546Sopenharmony_ci    * constant.
1512bf215546Sopenharmony_ci    */
1513bf215546Sopenharmony_ci   num_consts32 = input_program->descriptor_set_count;
1514bf215546Sopenharmony_ci   num_consts64 = input_program->descriptor_set_count;
1515bf215546Sopenharmony_ci   total_dma_count = input_program->descriptor_set_count;
1516bf215546Sopenharmony_ci
1517bf215546Sopenharmony_ci   pvr_init_pds_const_map_entry_write_state(info, &entry_write_state);
1518bf215546Sopenharmony_ci
1519bf215546Sopenharmony_ci   for (unsigned int index = 0; index < input_program->buffer_count; index++) {
1520bf215546Sopenharmony_ci      struct pvr_pds_buffer *buffer = &input_program->buffers[index];
1521bf215546Sopenharmony_ci
1522bf215546Sopenharmony_ci      /* This switch statement looks pointless but we want to optimize DMAs
1523bf215546Sopenharmony_ci       * that can be done as a DOUTW.
1524bf215546Sopenharmony_ci       */
1525bf215546Sopenharmony_ci      switch (buffer->type) {
1526bf215546Sopenharmony_ci      default: {
1527bf215546Sopenharmony_ci         /* 1 DOUTD per compile time buffer: */
1528bf215546Sopenharmony_ci         num_consts32++;
1529bf215546Sopenharmony_ci         num_consts64++;
1530bf215546Sopenharmony_ci         total_dma_count++;
1531bf215546Sopenharmony_ci         break;
1532bf215546Sopenharmony_ci      }
1533bf215546Sopenharmony_ci      }
1534bf215546Sopenharmony_ci   }
1535bf215546Sopenharmony_ci
1536bf215546Sopenharmony_ci   /* DOUTU for the secondary update program requires a 64-bit constant. */
1537bf215546Sopenharmony_ci   if (input_program->secondary_program_present)
1538bf215546Sopenharmony_ci      num_consts64++;
1539bf215546Sopenharmony_ci
1540bf215546Sopenharmony_ci   info->data_size_in_dwords = (num_consts64 * 2) + (num_consts32);
1541bf215546Sopenharmony_ci
1542bf215546Sopenharmony_ci   /* Start counting constants. */
1543bf215546Sopenharmony_ci   next_const64 = 0;
1544bf215546Sopenharmony_ci   next_const32 = num_consts64 * 2;
1545bf215546Sopenharmony_ci
1546bf215546Sopenharmony_ci   /* For each descriptor set perform a DOUTD. */
1547bf215546Sopenharmony_ci   for (unsigned int descriptor_index = 0;
1548bf215546Sopenharmony_ci        descriptor_index < input_program->descriptor_set_count;
1549bf215546Sopenharmony_ci        descriptor_index++) {
1550bf215546Sopenharmony_ci      struct pvr_const_map_entry_descriptor_set *descriptor_set_entry;
1551bf215546Sopenharmony_ci      struct pvr_pds_descriptor_set *descriptor_set =
1552bf215546Sopenharmony_ci         &input_program->descriptor_sets[descriptor_index];
1553bf215546Sopenharmony_ci
1554bf215546Sopenharmony_ci      bool last_DMA = (++running_dma_count == total_dma_count);
1555bf215546Sopenharmony_ci      bool halt = last_DMA && !input_program->secondary_program_present;
1556bf215546Sopenharmony_ci
1557bf215546Sopenharmony_ci      descriptor_set_entry =
1558bf215546Sopenharmony_ci         pvr_prepare_next_pds_const_map_entry(&entry_write_state,
1559bf215546Sopenharmony_ci                                              sizeof(*descriptor_set_entry));
1560bf215546Sopenharmony_ci      descriptor_set_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_DESCRIPTOR_SET;
1561bf215546Sopenharmony_ci      descriptor_set_entry->const_offset = next_const64 * 2;
1562bf215546Sopenharmony_ci      descriptor_set_entry->descriptor_set = descriptor_set->descriptor_set;
1563bf215546Sopenharmony_ci      descriptor_set_entry->primary = descriptor_set->primary;
1564bf215546Sopenharmony_ci      descriptor_set_entry->offset_in_dwords = descriptor_set->offset_in_dwords;
1565bf215546Sopenharmony_ci
1566bf215546Sopenharmony_ci      PVR_PDS_MODE_TOGGLE(code_section,
1567bf215546Sopenharmony_ci                          instruction,
1568bf215546Sopenharmony_ci                          pvr_encode_burst_cs(&entry_write_state,
1569bf215546Sopenharmony_ci                                              last_DMA,
1570bf215546Sopenharmony_ci                                              halt,
1571bf215546Sopenharmony_ci                                              next_const32,
1572bf215546Sopenharmony_ci                                              next_const64,
1573bf215546Sopenharmony_ci                                              descriptor_set->size_in_dwords,
1574bf215546Sopenharmony_ci                                              descriptor_set->destination));
1575bf215546Sopenharmony_ci
1576bf215546Sopenharmony_ci      next_const64++;
1577bf215546Sopenharmony_ci      next_const32++;
1578bf215546Sopenharmony_ci   }
1579bf215546Sopenharmony_ci
1580bf215546Sopenharmony_ci   for (unsigned int index = 0; index < input_program->buffer_count; index++) {
1581bf215546Sopenharmony_ci      struct pvr_pds_buffer *buffer = &input_program->buffers[index];
1582bf215546Sopenharmony_ci
1583bf215546Sopenharmony_ci      bool last_DMA = (++running_dma_count == total_dma_count);
1584bf215546Sopenharmony_ci      bool halt = last_DMA && !input_program->secondary_program_present;
1585bf215546Sopenharmony_ci
1586bf215546Sopenharmony_ci      switch (buffer->type) {
1587bf215546Sopenharmony_ci      case PVR_BUFFER_TYPE_PUSH_CONSTS: {
1588bf215546Sopenharmony_ci         struct pvr_const_map_entry_special_buffer *special_buffer_entry;
1589bf215546Sopenharmony_ci
1590bf215546Sopenharmony_ci         special_buffer_entry =
1591bf215546Sopenharmony_ci            pvr_prepare_next_pds_const_map_entry(&entry_write_state,
1592bf215546Sopenharmony_ci                                                 sizeof(*special_buffer_entry));
1593bf215546Sopenharmony_ci         special_buffer_entry->type =
1594bf215546Sopenharmony_ci            PVR_PDS_CONST_MAP_ENTRY_TYPE_SPECIAL_BUFFER;
1595bf215546Sopenharmony_ci         special_buffer_entry->buffer_type = PVR_BUFFER_TYPE_PUSH_CONSTS;
1596bf215546Sopenharmony_ci         special_buffer_entry->buffer_index = buffer->source_offset;
1597bf215546Sopenharmony_ci         break;
1598bf215546Sopenharmony_ci      }
1599bf215546Sopenharmony_ci      case PVR_BUFFER_TYPE_DYNAMIC: {
1600bf215546Sopenharmony_ci         struct pvr_const_map_entry_special_buffer *special_buffer_entry;
1601bf215546Sopenharmony_ci
1602bf215546Sopenharmony_ci         special_buffer_entry =
1603bf215546Sopenharmony_ci            pvr_prepare_next_pds_const_map_entry(&entry_write_state,
1604bf215546Sopenharmony_ci                                                 sizeof(*special_buffer_entry));
1605bf215546Sopenharmony_ci         special_buffer_entry->type =
1606bf215546Sopenharmony_ci            PVR_PDS_CONST_MAP_ENTRY_TYPE_SPECIAL_BUFFER;
1607bf215546Sopenharmony_ci         special_buffer_entry->buffer_type = PVR_BUFFER_TYPE_DYNAMIC;
1608bf215546Sopenharmony_ci         special_buffer_entry->buffer_index = buffer->source_offset;
1609bf215546Sopenharmony_ci         break;
1610bf215546Sopenharmony_ci      }
1611bf215546Sopenharmony_ci      case PVR_BUFFER_TYPES_COMPILE_TIME: {
1612bf215546Sopenharmony_ci         struct pvr_const_map_entry_special_buffer *special_buffer_entry;
1613bf215546Sopenharmony_ci
1614bf215546Sopenharmony_ci         special_buffer_entry =
1615bf215546Sopenharmony_ci            pvr_prepare_next_pds_const_map_entry(&entry_write_state,
1616bf215546Sopenharmony_ci                                                 sizeof(*special_buffer_entry));
1617bf215546Sopenharmony_ci         special_buffer_entry->type =
1618bf215546Sopenharmony_ci            PVR_PDS_CONST_MAP_ENTRY_TYPE_SPECIAL_BUFFER;
1619bf215546Sopenharmony_ci         special_buffer_entry->buffer_type = PVR_BUFFER_TYPES_COMPILE_TIME;
1620bf215546Sopenharmony_ci         special_buffer_entry->buffer_index = compile_time_buffer_index++;
1621bf215546Sopenharmony_ci         break;
1622bf215546Sopenharmony_ci      }
1623bf215546Sopenharmony_ci      case PVR_BUFFER_TYPES_BUFFER_LENGTHS: {
1624bf215546Sopenharmony_ci         struct pvr_const_map_entry_special_buffer *special_buffer_entry;
1625bf215546Sopenharmony_ci
1626bf215546Sopenharmony_ci         special_buffer_entry =
1627bf215546Sopenharmony_ci            pvr_prepare_next_pds_const_map_entry(&entry_write_state,
1628bf215546Sopenharmony_ci                                                 sizeof(*special_buffer_entry));
1629bf215546Sopenharmony_ci         special_buffer_entry->type =
1630bf215546Sopenharmony_ci            PVR_PDS_CONST_MAP_ENTRY_TYPE_SPECIAL_BUFFER;
1631bf215546Sopenharmony_ci         special_buffer_entry->buffer_type = PVR_BUFFER_TYPES_BUFFER_LENGTHS;
1632bf215546Sopenharmony_ci         break;
1633bf215546Sopenharmony_ci      }
1634bf215546Sopenharmony_ci      case PVR_BUFFER_TYPE_BLEND_CONSTS: {
1635bf215546Sopenharmony_ci         struct pvr_const_map_entry_special_buffer *special_buffer_entry;
1636bf215546Sopenharmony_ci
1637bf215546Sopenharmony_ci         special_buffer_entry =
1638bf215546Sopenharmony_ci            pvr_prepare_next_pds_const_map_entry(&entry_write_state,
1639bf215546Sopenharmony_ci                                                 sizeof(*special_buffer_entry));
1640bf215546Sopenharmony_ci         special_buffer_entry->type =
1641bf215546Sopenharmony_ci            PVR_PDS_CONST_MAP_ENTRY_TYPE_SPECIAL_BUFFER;
1642bf215546Sopenharmony_ci         special_buffer_entry->buffer_type = PVR_BUFFER_TYPE_BLEND_CONSTS;
1643bf215546Sopenharmony_ci         special_buffer_entry->buffer_index =
1644bf215546Sopenharmony_ci            input_program->blend_constants_used_mask;
1645bf215546Sopenharmony_ci         break;
1646bf215546Sopenharmony_ci      }
1647bf215546Sopenharmony_ci      case PVR_BUFFER_TYPE_UBO: {
1648bf215546Sopenharmony_ci         struct pvr_const_map_entry_constant_buffer *constant_buffer_entry;
1649bf215546Sopenharmony_ci
1650bf215546Sopenharmony_ci         constant_buffer_entry = pvr_prepare_next_pds_const_map_entry(
1651bf215546Sopenharmony_ci            &entry_write_state,
1652bf215546Sopenharmony_ci            sizeof(*constant_buffer_entry));
1653bf215546Sopenharmony_ci         constant_buffer_entry->type =
1654bf215546Sopenharmony_ci            PVR_PDS_CONST_MAP_ENTRY_TYPE_CONSTANT_BUFFER;
1655bf215546Sopenharmony_ci         constant_buffer_entry->buffer_id = buffer->buffer_id;
1656bf215546Sopenharmony_ci         constant_buffer_entry->desc_set = buffer->desc_set;
1657bf215546Sopenharmony_ci         constant_buffer_entry->binding = buffer->binding;
1658bf215546Sopenharmony_ci         constant_buffer_entry->offset = buffer->source_offset;
1659bf215546Sopenharmony_ci         constant_buffer_entry->size_in_dwords = buffer->size_in_dwords;
1660bf215546Sopenharmony_ci         break;
1661bf215546Sopenharmony_ci      }
1662bf215546Sopenharmony_ci      case PVR_BUFFER_TYPES_UBO_ZEROING: {
1663bf215546Sopenharmony_ci         struct pvr_const_map_entry_constant_buffer_zeroing
1664bf215546Sopenharmony_ci            *constant_buffer_entry;
1665bf215546Sopenharmony_ci
1666bf215546Sopenharmony_ci         constant_buffer_entry = pvr_prepare_next_pds_const_map_entry(
1667bf215546Sopenharmony_ci            &entry_write_state,
1668bf215546Sopenharmony_ci            sizeof(*constant_buffer_entry));
1669bf215546Sopenharmony_ci         constant_buffer_entry->type =
1670bf215546Sopenharmony_ci            PVR_PDS_CONST_MAP_ENTRY_TYPE_CONSTANT_BUFFER_ZEROING;
1671bf215546Sopenharmony_ci         constant_buffer_entry->buffer_id = buffer->buffer_id;
1672bf215546Sopenharmony_ci         constant_buffer_entry->offset = buffer->source_offset;
1673bf215546Sopenharmony_ci         constant_buffer_entry->size_in_dwords = buffer->size_in_dwords;
1674bf215546Sopenharmony_ci         break;
1675bf215546Sopenharmony_ci      }
1676bf215546Sopenharmony_ci      }
1677bf215546Sopenharmony_ci
1678bf215546Sopenharmony_ci      entry_write_state.entry->const_offset = next_const64 * 2;
1679bf215546Sopenharmony_ci
1680bf215546Sopenharmony_ci      PVR_PDS_MODE_TOGGLE(code_section,
1681bf215546Sopenharmony_ci                          instruction,
1682bf215546Sopenharmony_ci                          pvr_encode_burst_cs(&entry_write_state,
1683bf215546Sopenharmony_ci                                              last_DMA,
1684bf215546Sopenharmony_ci                                              halt,
1685bf215546Sopenharmony_ci                                              next_const32,
1686bf215546Sopenharmony_ci                                              next_const64,
1687bf215546Sopenharmony_ci                                              buffer->size_in_dwords,
1688bf215546Sopenharmony_ci                                              buffer->destination));
1689bf215546Sopenharmony_ci
1690bf215546Sopenharmony_ci      next_const64++;
1691bf215546Sopenharmony_ci      next_const32++;
1692bf215546Sopenharmony_ci   }
1693bf215546Sopenharmony_ci
1694bf215546Sopenharmony_ci   if (total_dma_count != running_dma_count)
1695bf215546Sopenharmony_ci      fprintf(stderr, "Mismatch in DMA count\n");
1696bf215546Sopenharmony_ci
1697bf215546Sopenharmony_ci   if (input_program->secondary_program_present) {
1698bf215546Sopenharmony_ci      struct pvr_const_map_entry_doutu_address *doutu_address;
1699bf215546Sopenharmony_ci
1700bf215546Sopenharmony_ci      PVR_PDS_MODE_TOGGLE(code_section,
1701bf215546Sopenharmony_ci                          instruction,
1702bf215546Sopenharmony_ci                          pvr_pds_encode_doutu(false, true, next_const64));
1703bf215546Sopenharmony_ci
1704bf215546Sopenharmony_ci      doutu_address =
1705bf215546Sopenharmony_ci         pvr_prepare_next_pds_const_map_entry(&entry_write_state,
1706bf215546Sopenharmony_ci                                              sizeof(*doutu_address));
1707bf215546Sopenharmony_ci      doutu_address->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_DOUTU_ADDRESS;
1708bf215546Sopenharmony_ci      doutu_address->const_offset = next_const64 * 2;
1709bf215546Sopenharmony_ci      doutu_address->doutu_control = input_program->secondary_task_control.src0;
1710bf215546Sopenharmony_ci
1711bf215546Sopenharmony_ci      next_const64++;
1712bf215546Sopenharmony_ci   }
1713bf215546Sopenharmony_ci
1714bf215546Sopenharmony_ci   if (instruction == 0 && input_program->must_not_be_empty) {
1715bf215546Sopenharmony_ci      PVR_PDS_MODE_TOGGLE(code_section,
1716bf215546Sopenharmony_ci                          instruction,
1717bf215546Sopenharmony_ci                          pvr_pds_inst_encode_halt(
1718bf215546Sopenharmony_ci                             /* cc */ false));
1719bf215546Sopenharmony_ci   }
1720bf215546Sopenharmony_ci
1721bf215546Sopenharmony_ci   info->entry_count = entry_write_state.entry_count;
1722bf215546Sopenharmony_ci   info->entries_written_size_in_bytes =
1723bf215546Sopenharmony_ci      entry_write_state.entries_size_in_bytes;
1724bf215546Sopenharmony_ci   info->code_size_in_dwords = instruction;
1725bf215546Sopenharmony_ci}
1726