1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright 2021 Alyssa Rosenzweig
3*61046927SAndroid Build Coastguard Worker * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker */
5*61046927SAndroid Build Coastguard Worker
6*61046927SAndroid Build Coastguard Worker #include "agx_compiler.h"
7*61046927SAndroid Build Coastguard Worker #include "agx_opcodes.h"
8*61046927SAndroid Build Coastguard Worker
9*61046927SAndroid Build Coastguard Worker /* Binary patches needed for branch offsets */
10*61046927SAndroid Build Coastguard Worker struct agx_branch_fixup {
11*61046927SAndroid Build Coastguard Worker /* Offset into the binary to patch */
12*61046927SAndroid Build Coastguard Worker off_t offset;
13*61046927SAndroid Build Coastguard Worker
14*61046927SAndroid Build Coastguard Worker /* Value to patch with will be block->offset */
15*61046927SAndroid Build Coastguard Worker agx_block *block;
16*61046927SAndroid Build Coastguard Worker
17*61046927SAndroid Build Coastguard Worker /* If true, skips to the last instruction of the target block */
18*61046927SAndroid Build Coastguard Worker bool skip_to_end;
19*61046927SAndroid Build Coastguard Worker };
20*61046927SAndroid Build Coastguard Worker
21*61046927SAndroid Build Coastguard Worker static void
pack_assert_internal(const agx_instr * I,bool condition,const char * msg)22*61046927SAndroid Build Coastguard Worker pack_assert_internal(const agx_instr *I, bool condition, const char *msg)
23*61046927SAndroid Build Coastguard Worker {
24*61046927SAndroid Build Coastguard Worker if (!condition) {
25*61046927SAndroid Build Coastguard Worker printf("Packing assertion failed for instruction:\n\n");
26*61046927SAndroid Build Coastguard Worker agx_print_instr(I, stdout);
27*61046927SAndroid Build Coastguard Worker printf("\n%s\n", msg);
28*61046927SAndroid Build Coastguard Worker abort();
29*61046927SAndroid Build Coastguard Worker }
30*61046927SAndroid Build Coastguard Worker }
31*61046927SAndroid Build Coastguard Worker
32*61046927SAndroid Build Coastguard Worker #define pack_assert_msg(I, cond, msg) \
33*61046927SAndroid Build Coastguard Worker pack_assert_internal(I, cond, msg ": " #cond)
34*61046927SAndroid Build Coastguard Worker
35*61046927SAndroid Build Coastguard Worker #define pack_assert(I, cond) pack_assert_internal(I, cond, #cond)
36*61046927SAndroid Build Coastguard Worker
37*61046927SAndroid Build Coastguard Worker static void
assert_register_is_aligned(const agx_instr * I,agx_index reg)38*61046927SAndroid Build Coastguard Worker assert_register_is_aligned(const agx_instr *I, agx_index reg)
39*61046927SAndroid Build Coastguard Worker {
40*61046927SAndroid Build Coastguard Worker pack_assert_msg(I, reg.type == AGX_INDEX_REGISTER, "expecting a register");
41*61046927SAndroid Build Coastguard Worker
42*61046927SAndroid Build Coastguard Worker switch (reg.size) {
43*61046927SAndroid Build Coastguard Worker case AGX_SIZE_16:
44*61046927SAndroid Build Coastguard Worker return;
45*61046927SAndroid Build Coastguard Worker case AGX_SIZE_32:
46*61046927SAndroid Build Coastguard Worker pack_assert_msg(I, (reg.value & 1) == 0, "unaligned reg");
47*61046927SAndroid Build Coastguard Worker return;
48*61046927SAndroid Build Coastguard Worker case AGX_SIZE_64:
49*61046927SAndroid Build Coastguard Worker pack_assert_msg(I, (reg.value & 3) == 0, "unaligned reg");
50*61046927SAndroid Build Coastguard Worker return;
51*61046927SAndroid Build Coastguard Worker }
52*61046927SAndroid Build Coastguard Worker
53*61046927SAndroid Build Coastguard Worker unreachable("Invalid register size");
54*61046927SAndroid Build Coastguard Worker }
55*61046927SAndroid Build Coastguard Worker
56*61046927SAndroid Build Coastguard Worker /* Texturing has its own operands */
57*61046927SAndroid Build Coastguard Worker static unsigned
agx_pack_sample_coords(const agx_instr * I,agx_index index,bool * flag,bool * is_16)58*61046927SAndroid Build Coastguard Worker agx_pack_sample_coords(const agx_instr *I, agx_index index, bool *flag,
59*61046927SAndroid Build Coastguard Worker bool *is_16)
60*61046927SAndroid Build Coastguard Worker {
61*61046927SAndroid Build Coastguard Worker /* TODO: Do we have a use case for 16-bit coords? */
62*61046927SAndroid Build Coastguard Worker pack_assert_msg(I, index.size == AGX_SIZE_32, "32-bit coordinates");
63*61046927SAndroid Build Coastguard Worker pack_assert_msg(I, index.value < 0x100, "coordinate register bound");
64*61046927SAndroid Build Coastguard Worker
65*61046927SAndroid Build Coastguard Worker *is_16 = false;
66*61046927SAndroid Build Coastguard Worker *flag = index.discard;
67*61046927SAndroid Build Coastguard Worker return index.value;
68*61046927SAndroid Build Coastguard Worker }
69*61046927SAndroid Build Coastguard Worker
70*61046927SAndroid Build Coastguard Worker static unsigned
agx_pack_texture(const agx_instr * I,agx_index base,agx_index index,unsigned * packed_base,unsigned * flag)71*61046927SAndroid Build Coastguard Worker agx_pack_texture(const agx_instr *I, agx_index base, agx_index index,
72*61046927SAndroid Build Coastguard Worker unsigned *packed_base, unsigned *flag)
73*61046927SAndroid Build Coastguard Worker {
74*61046927SAndroid Build Coastguard Worker if (base.type == AGX_INDEX_IMMEDIATE) {
75*61046927SAndroid Build Coastguard Worker pack_assert(I, base.value == 0);
76*61046927SAndroid Build Coastguard Worker
77*61046927SAndroid Build Coastguard Worker /* Texture state registers */
78*61046927SAndroid Build Coastguard Worker *packed_base = 0;
79*61046927SAndroid Build Coastguard Worker
80*61046927SAndroid Build Coastguard Worker if (index.type == AGX_INDEX_REGISTER) {
81*61046927SAndroid Build Coastguard Worker pack_assert(I, index.size == AGX_SIZE_16);
82*61046927SAndroid Build Coastguard Worker *flag = 1;
83*61046927SAndroid Build Coastguard Worker } else {
84*61046927SAndroid Build Coastguard Worker pack_assert(I, index.type == AGX_INDEX_IMMEDIATE);
85*61046927SAndroid Build Coastguard Worker *flag = 0;
86*61046927SAndroid Build Coastguard Worker }
87*61046927SAndroid Build Coastguard Worker } else {
88*61046927SAndroid Build Coastguard Worker pack_assert(I, base.type == AGX_INDEX_UNIFORM);
89*61046927SAndroid Build Coastguard Worker pack_assert(I, base.size == AGX_SIZE_64);
90*61046927SAndroid Build Coastguard Worker pack_assert(I, (base.value & 3) == 0);
91*61046927SAndroid Build Coastguard Worker pack_assert(I, index.size == AGX_SIZE_32);
92*61046927SAndroid Build Coastguard Worker
93*61046927SAndroid Build Coastguard Worker /* Bindless */
94*61046927SAndroid Build Coastguard Worker *packed_base = base.value >> 2;
95*61046927SAndroid Build Coastguard Worker *flag = 3;
96*61046927SAndroid Build Coastguard Worker }
97*61046927SAndroid Build Coastguard Worker
98*61046927SAndroid Build Coastguard Worker return index.value;
99*61046927SAndroid Build Coastguard Worker }
100*61046927SAndroid Build Coastguard Worker
101*61046927SAndroid Build Coastguard Worker static unsigned
agx_pack_sampler(const agx_instr * I,agx_index index,bool * flag)102*61046927SAndroid Build Coastguard Worker agx_pack_sampler(const agx_instr *I, agx_index index, bool *flag)
103*61046927SAndroid Build Coastguard Worker {
104*61046927SAndroid Build Coastguard Worker if (index.type == AGX_INDEX_REGISTER) {
105*61046927SAndroid Build Coastguard Worker pack_assert(I, index.size == AGX_SIZE_16);
106*61046927SAndroid Build Coastguard Worker *flag = 1;
107*61046927SAndroid Build Coastguard Worker } else {
108*61046927SAndroid Build Coastguard Worker pack_assert(I, index.type == AGX_INDEX_IMMEDIATE);
109*61046927SAndroid Build Coastguard Worker *flag = 0;
110*61046927SAndroid Build Coastguard Worker }
111*61046927SAndroid Build Coastguard Worker
112*61046927SAndroid Build Coastguard Worker return index.value;
113*61046927SAndroid Build Coastguard Worker }
114*61046927SAndroid Build Coastguard Worker
115*61046927SAndroid Build Coastguard Worker static unsigned
agx_pack_sample_compare_offset(const agx_instr * I,agx_index index)116*61046927SAndroid Build Coastguard Worker agx_pack_sample_compare_offset(const agx_instr *I, agx_index index)
117*61046927SAndroid Build Coastguard Worker {
118*61046927SAndroid Build Coastguard Worker if (index.type == AGX_INDEX_NULL)
119*61046927SAndroid Build Coastguard Worker return 0;
120*61046927SAndroid Build Coastguard Worker
121*61046927SAndroid Build Coastguard Worker pack_assert(I, index.size == AGX_SIZE_32);
122*61046927SAndroid Build Coastguard Worker pack_assert(I, index.value < 0x100);
123*61046927SAndroid Build Coastguard Worker assert_register_is_aligned(I, index);
124*61046927SAndroid Build Coastguard Worker return index.value;
125*61046927SAndroid Build Coastguard Worker }
126*61046927SAndroid Build Coastguard Worker
127*61046927SAndroid Build Coastguard Worker static unsigned
agx_pack_lod(const agx_instr * I,agx_index index,unsigned * lod_mode)128*61046927SAndroid Build Coastguard Worker agx_pack_lod(const agx_instr *I, agx_index index, unsigned *lod_mode)
129*61046927SAndroid Build Coastguard Worker {
130*61046927SAndroid Build Coastguard Worker /* For automatic LOD, the LOD field is unused. Assert as much. */
131*61046927SAndroid Build Coastguard Worker if ((*lod_mode) == AGX_LOD_MODE_AUTO_LOD) {
132*61046927SAndroid Build Coastguard Worker pack_assert(I, index.type == AGX_INDEX_IMMEDIATE);
133*61046927SAndroid Build Coastguard Worker pack_assert(I, index.value == 0);
134*61046927SAndroid Build Coastguard Worker return 0;
135*61046927SAndroid Build Coastguard Worker }
136*61046927SAndroid Build Coastguard Worker
137*61046927SAndroid Build Coastguard Worker if (index.type == AGX_INDEX_UNIFORM) {
138*61046927SAndroid Build Coastguard Worker /* Translate LOD mode from register mode to uniform mode */
139*61046927SAndroid Build Coastguard Worker pack_assert(I,
140*61046927SAndroid Build Coastguard Worker ((*lod_mode) & BITFIELD_BIT(2)) && "must start as reg mode");
141*61046927SAndroid Build Coastguard Worker *lod_mode = (*lod_mode) & ~BITFIELD_BIT(2);
142*61046927SAndroid Build Coastguard Worker pack_assert(I, index.value < 0x200);
143*61046927SAndroid Build Coastguard Worker } else {
144*61046927SAndroid Build Coastguard Worker /* Otherwise must be registers */
145*61046927SAndroid Build Coastguard Worker pack_assert(I, index.type == AGX_INDEX_REGISTER);
146*61046927SAndroid Build Coastguard Worker pack_assert(I, index.value < 0x100);
147*61046927SAndroid Build Coastguard Worker }
148*61046927SAndroid Build Coastguard Worker
149*61046927SAndroid Build Coastguard Worker return index.value;
150*61046927SAndroid Build Coastguard Worker }
151*61046927SAndroid Build Coastguard Worker
152*61046927SAndroid Build Coastguard Worker static unsigned
agx_pack_pbe_source(const agx_instr * I,agx_index index,bool * flag)153*61046927SAndroid Build Coastguard Worker agx_pack_pbe_source(const agx_instr *I, agx_index index, bool *flag)
154*61046927SAndroid Build Coastguard Worker {
155*61046927SAndroid Build Coastguard Worker pack_assert(I, index.size == AGX_SIZE_16 || index.size == AGX_SIZE_32);
156*61046927SAndroid Build Coastguard Worker assert_register_is_aligned(I, index);
157*61046927SAndroid Build Coastguard Worker
158*61046927SAndroid Build Coastguard Worker *flag = (index.size == AGX_SIZE_32);
159*61046927SAndroid Build Coastguard Worker return index.value;
160*61046927SAndroid Build Coastguard Worker }
161*61046927SAndroid Build Coastguard Worker
162*61046927SAndroid Build Coastguard Worker static unsigned
agx_pack_pbe_lod(const agx_instr * I,agx_index index,bool * flag)163*61046927SAndroid Build Coastguard Worker agx_pack_pbe_lod(const agx_instr *I, agx_index index, bool *flag)
164*61046927SAndroid Build Coastguard Worker {
165*61046927SAndroid Build Coastguard Worker pack_assert(I, index.size == AGX_SIZE_16);
166*61046927SAndroid Build Coastguard Worker
167*61046927SAndroid Build Coastguard Worker if (index.type == AGX_INDEX_IMMEDIATE)
168*61046927SAndroid Build Coastguard Worker *flag = true;
169*61046927SAndroid Build Coastguard Worker else if (index.type == AGX_INDEX_REGISTER)
170*61046927SAndroid Build Coastguard Worker *flag = false;
171*61046927SAndroid Build Coastguard Worker else
172*61046927SAndroid Build Coastguard Worker unreachable("Invalid PBE LOD type");
173*61046927SAndroid Build Coastguard Worker
174*61046927SAndroid Build Coastguard Worker return index.value;
175*61046927SAndroid Build Coastguard Worker }
176*61046927SAndroid Build Coastguard Worker
177*61046927SAndroid Build Coastguard Worker /* Load/stores have their own operands */
178*61046927SAndroid Build Coastguard Worker
179*61046927SAndroid Build Coastguard Worker static unsigned
agx_pack_memory_reg(const agx_instr * I,agx_index index,bool * flag)180*61046927SAndroid Build Coastguard Worker agx_pack_memory_reg(const agx_instr *I, agx_index index, bool *flag)
181*61046927SAndroid Build Coastguard Worker {
182*61046927SAndroid Build Coastguard Worker assert_register_is_aligned(I, index);
183*61046927SAndroid Build Coastguard Worker
184*61046927SAndroid Build Coastguard Worker *flag = (index.size >= AGX_SIZE_32);
185*61046927SAndroid Build Coastguard Worker return index.value;
186*61046927SAndroid Build Coastguard Worker }
187*61046927SAndroid Build Coastguard Worker
188*61046927SAndroid Build Coastguard Worker static unsigned
agx_pack_memory_base(const agx_instr * I,agx_index index,bool * flag)189*61046927SAndroid Build Coastguard Worker agx_pack_memory_base(const agx_instr *I, agx_index index, bool *flag)
190*61046927SAndroid Build Coastguard Worker {
191*61046927SAndroid Build Coastguard Worker pack_assert(I, index.size == AGX_SIZE_64);
192*61046927SAndroid Build Coastguard Worker pack_assert(I, (index.value & 1) == 0);
193*61046927SAndroid Build Coastguard Worker
194*61046927SAndroid Build Coastguard Worker /* Can't seem to access high uniforms from memory instructions */
195*61046927SAndroid Build Coastguard Worker pack_assert(I, index.value < 0x100);
196*61046927SAndroid Build Coastguard Worker
197*61046927SAndroid Build Coastguard Worker if (index.type == AGX_INDEX_UNIFORM) {
198*61046927SAndroid Build Coastguard Worker *flag = 1;
199*61046927SAndroid Build Coastguard Worker } else {
200*61046927SAndroid Build Coastguard Worker pack_assert(I, index.type == AGX_INDEX_REGISTER);
201*61046927SAndroid Build Coastguard Worker *flag = 0;
202*61046927SAndroid Build Coastguard Worker }
203*61046927SAndroid Build Coastguard Worker
204*61046927SAndroid Build Coastguard Worker return index.value;
205*61046927SAndroid Build Coastguard Worker }
206*61046927SAndroid Build Coastguard Worker
207*61046927SAndroid Build Coastguard Worker static unsigned
agx_pack_memory_index(const agx_instr * I,agx_index index,bool * flag)208*61046927SAndroid Build Coastguard Worker agx_pack_memory_index(const agx_instr *I, agx_index index, bool *flag)
209*61046927SAndroid Build Coastguard Worker {
210*61046927SAndroid Build Coastguard Worker if (index.type == AGX_INDEX_IMMEDIATE) {
211*61046927SAndroid Build Coastguard Worker pack_assert(I, index.value < 0x10000);
212*61046927SAndroid Build Coastguard Worker *flag = 1;
213*61046927SAndroid Build Coastguard Worker
214*61046927SAndroid Build Coastguard Worker return index.value;
215*61046927SAndroid Build Coastguard Worker } else {
216*61046927SAndroid Build Coastguard Worker pack_assert(I, index.type == AGX_INDEX_REGISTER);
217*61046927SAndroid Build Coastguard Worker pack_assert(I, index.size == AGX_SIZE_32);
218*61046927SAndroid Build Coastguard Worker pack_assert(I, (index.value & 1) == 0);
219*61046927SAndroid Build Coastguard Worker pack_assert(I, index.value < 0x100);
220*61046927SAndroid Build Coastguard Worker
221*61046927SAndroid Build Coastguard Worker *flag = 0;
222*61046927SAndroid Build Coastguard Worker return index.value;
223*61046927SAndroid Build Coastguard Worker }
224*61046927SAndroid Build Coastguard Worker }
225*61046927SAndroid Build Coastguard Worker
226*61046927SAndroid Build Coastguard Worker static uint16_t
agx_pack_local_base(const agx_instr * I,agx_index index,unsigned * flags)227*61046927SAndroid Build Coastguard Worker agx_pack_local_base(const agx_instr *I, agx_index index, unsigned *flags)
228*61046927SAndroid Build Coastguard Worker {
229*61046927SAndroid Build Coastguard Worker pack_assert(I, index.size == AGX_SIZE_16);
230*61046927SAndroid Build Coastguard Worker
231*61046927SAndroid Build Coastguard Worker if (index.type == AGX_INDEX_IMMEDIATE) {
232*61046927SAndroid Build Coastguard Worker pack_assert(I, index.value == 0);
233*61046927SAndroid Build Coastguard Worker *flags = 2;
234*61046927SAndroid Build Coastguard Worker return 0;
235*61046927SAndroid Build Coastguard Worker } else if (index.type == AGX_INDEX_UNIFORM) {
236*61046927SAndroid Build Coastguard Worker *flags = 1 | ((index.value >> 8) << 1);
237*61046927SAndroid Build Coastguard Worker return index.value & BITFIELD_MASK(7);
238*61046927SAndroid Build Coastguard Worker } else {
239*61046927SAndroid Build Coastguard Worker assert_register_is_aligned(I, index);
240*61046927SAndroid Build Coastguard Worker *flags = 0;
241*61046927SAndroid Build Coastguard Worker return index.value;
242*61046927SAndroid Build Coastguard Worker }
243*61046927SAndroid Build Coastguard Worker }
244*61046927SAndroid Build Coastguard Worker
245*61046927SAndroid Build Coastguard Worker static uint16_t
agx_pack_local_index(const agx_instr * I,agx_index index,bool * flag)246*61046927SAndroid Build Coastguard Worker agx_pack_local_index(const agx_instr *I, agx_index index, bool *flag)
247*61046927SAndroid Build Coastguard Worker {
248*61046927SAndroid Build Coastguard Worker pack_assert(I, index.size == AGX_SIZE_16);
249*61046927SAndroid Build Coastguard Worker
250*61046927SAndroid Build Coastguard Worker if (index.type == AGX_INDEX_IMMEDIATE) {
251*61046927SAndroid Build Coastguard Worker pack_assert(I, index.value < 0x10000);
252*61046927SAndroid Build Coastguard Worker *flag = 1;
253*61046927SAndroid Build Coastguard Worker return index.value;
254*61046927SAndroid Build Coastguard Worker } else {
255*61046927SAndroid Build Coastguard Worker assert_register_is_aligned(I, index);
256*61046927SAndroid Build Coastguard Worker *flag = 0;
257*61046927SAndroid Build Coastguard Worker return index.value;
258*61046927SAndroid Build Coastguard Worker }
259*61046927SAndroid Build Coastguard Worker }
260*61046927SAndroid Build Coastguard Worker
261*61046927SAndroid Build Coastguard Worker static unsigned
agx_pack_atomic_source(const agx_instr * I,agx_index index)262*61046927SAndroid Build Coastguard Worker agx_pack_atomic_source(const agx_instr *I, agx_index index)
263*61046927SAndroid Build Coastguard Worker {
264*61046927SAndroid Build Coastguard Worker pack_assert_msg(I, index.size == AGX_SIZE_32, "no 64-bit atomics yet");
265*61046927SAndroid Build Coastguard Worker assert_register_is_aligned(I, index);
266*61046927SAndroid Build Coastguard Worker return index.value;
267*61046927SAndroid Build Coastguard Worker }
268*61046927SAndroid Build Coastguard Worker
269*61046927SAndroid Build Coastguard Worker static unsigned
agx_pack_atomic_dest(const agx_instr * I,agx_index index,bool * flag)270*61046927SAndroid Build Coastguard Worker agx_pack_atomic_dest(const agx_instr *I, agx_index index, bool *flag)
271*61046927SAndroid Build Coastguard Worker {
272*61046927SAndroid Build Coastguard Worker /* Atomic destinstions are optional (e.g. for update with no return) */
273*61046927SAndroid Build Coastguard Worker if (index.type == AGX_INDEX_NULL) {
274*61046927SAndroid Build Coastguard Worker *flag = 0;
275*61046927SAndroid Build Coastguard Worker return 0;
276*61046927SAndroid Build Coastguard Worker }
277*61046927SAndroid Build Coastguard Worker
278*61046927SAndroid Build Coastguard Worker /* But are otherwise registers */
279*61046927SAndroid Build Coastguard Worker pack_assert_msg(I, index.size == AGX_SIZE_32, "no 64-bit atomics yet");
280*61046927SAndroid Build Coastguard Worker assert_register_is_aligned(I, index);
281*61046927SAndroid Build Coastguard Worker *flag = 1;
282*61046927SAndroid Build Coastguard Worker return index.value;
283*61046927SAndroid Build Coastguard Worker }
284*61046927SAndroid Build Coastguard Worker
285*61046927SAndroid Build Coastguard Worker /* ALU goes through a common path */
286*61046927SAndroid Build Coastguard Worker
287*61046927SAndroid Build Coastguard Worker static unsigned
agx_pack_alu_dst(const agx_instr * I,agx_index dest)288*61046927SAndroid Build Coastguard Worker agx_pack_alu_dst(const agx_instr *I, agx_index dest)
289*61046927SAndroid Build Coastguard Worker {
290*61046927SAndroid Build Coastguard Worker assert_register_is_aligned(I, dest);
291*61046927SAndroid Build Coastguard Worker unsigned reg = dest.value;
292*61046927SAndroid Build Coastguard Worker enum agx_size size = dest.size;
293*61046927SAndroid Build Coastguard Worker pack_assert(I, reg < 0x100);
294*61046927SAndroid Build Coastguard Worker
295*61046927SAndroid Build Coastguard Worker return (dest.cache ? (1 << 0) : 0) | ((size >= AGX_SIZE_32) ? (1 << 1) : 0) |
296*61046927SAndroid Build Coastguard Worker ((size == AGX_SIZE_64) ? (1 << 2) : 0) | ((reg << 2));
297*61046927SAndroid Build Coastguard Worker }
298*61046927SAndroid Build Coastguard Worker
299*61046927SAndroid Build Coastguard Worker static unsigned
agx_pack_alu_src(const agx_instr * I,agx_index src)300*61046927SAndroid Build Coastguard Worker agx_pack_alu_src(const agx_instr *I, agx_index src)
301*61046927SAndroid Build Coastguard Worker {
302*61046927SAndroid Build Coastguard Worker unsigned value = src.value;
303*61046927SAndroid Build Coastguard Worker enum agx_size size = src.size;
304*61046927SAndroid Build Coastguard Worker
305*61046927SAndroid Build Coastguard Worker if (src.type == AGX_INDEX_IMMEDIATE) {
306*61046927SAndroid Build Coastguard Worker /* Flags 0 for an 8-bit immediate */
307*61046927SAndroid Build Coastguard Worker pack_assert(I, value < 0x100);
308*61046927SAndroid Build Coastguard Worker
309*61046927SAndroid Build Coastguard Worker return (value & BITFIELD_MASK(6)) | ((value >> 6) << 10);
310*61046927SAndroid Build Coastguard Worker } else if (src.type == AGX_INDEX_UNIFORM) {
311*61046927SAndroid Build Coastguard Worker pack_assert(I, size == AGX_SIZE_16 || size == AGX_SIZE_32);
312*61046927SAndroid Build Coastguard Worker pack_assert(I, value < AGX_NUM_UNIFORMS);
313*61046927SAndroid Build Coastguard Worker
314*61046927SAndroid Build Coastguard Worker return (value & BITFIELD_MASK(6)) |
315*61046927SAndroid Build Coastguard Worker ((value & BITFIELD_BIT(8)) ? (1 << 6) : 0) |
316*61046927SAndroid Build Coastguard Worker ((size == AGX_SIZE_32) ? (1 << 7) : 0) | (0x1 << 8) |
317*61046927SAndroid Build Coastguard Worker (((value >> 6) & BITFIELD_MASK(2)) << 10);
318*61046927SAndroid Build Coastguard Worker } else {
319*61046927SAndroid Build Coastguard Worker assert_register_is_aligned(I, src);
320*61046927SAndroid Build Coastguard Worker pack_assert(I, !(src.cache && src.discard));
321*61046927SAndroid Build Coastguard Worker
322*61046927SAndroid Build Coastguard Worker unsigned hint = src.discard ? 0x3 : src.cache ? 0x2 : 0x1;
323*61046927SAndroid Build Coastguard Worker unsigned size_flag = (size == AGX_SIZE_64) ? 0x3
324*61046927SAndroid Build Coastguard Worker : (size == AGX_SIZE_32) ? 0x2
325*61046927SAndroid Build Coastguard Worker : (size == AGX_SIZE_16) ? 0x0
326*61046927SAndroid Build Coastguard Worker : 0x0;
327*61046927SAndroid Build Coastguard Worker
328*61046927SAndroid Build Coastguard Worker return (value & BITFIELD_MASK(6)) | (hint << 6) | (size_flag << 8) |
329*61046927SAndroid Build Coastguard Worker (((value >> 6) & BITFIELD_MASK(2)) << 10);
330*61046927SAndroid Build Coastguard Worker }
331*61046927SAndroid Build Coastguard Worker }
332*61046927SAndroid Build Coastguard Worker
333*61046927SAndroid Build Coastguard Worker static unsigned
agx_pack_cmpsel_src(const agx_instr * I,agx_index src,enum agx_size dest_size)334*61046927SAndroid Build Coastguard Worker agx_pack_cmpsel_src(const agx_instr *I, agx_index src, enum agx_size dest_size)
335*61046927SAndroid Build Coastguard Worker {
336*61046927SAndroid Build Coastguard Worker unsigned value = src.value;
337*61046927SAndroid Build Coastguard Worker ASSERTED enum agx_size size = src.size;
338*61046927SAndroid Build Coastguard Worker
339*61046927SAndroid Build Coastguard Worker if (src.type == AGX_INDEX_IMMEDIATE) {
340*61046927SAndroid Build Coastguard Worker /* Flags 0x4 for an 8-bit immediate */
341*61046927SAndroid Build Coastguard Worker pack_assert(I, value < 0x100);
342*61046927SAndroid Build Coastguard Worker
343*61046927SAndroid Build Coastguard Worker return (value & BITFIELD_MASK(6)) | (0x4 << 6) | ((value >> 6) << 10);
344*61046927SAndroid Build Coastguard Worker } else if (src.type == AGX_INDEX_UNIFORM) {
345*61046927SAndroid Build Coastguard Worker pack_assert(I, size == AGX_SIZE_16 || size == AGX_SIZE_32);
346*61046927SAndroid Build Coastguard Worker pack_assert(I, size == dest_size);
347*61046927SAndroid Build Coastguard Worker pack_assert(I, value < 0x200);
348*61046927SAndroid Build Coastguard Worker
349*61046927SAndroid Build Coastguard Worker return (value & BITFIELD_MASK(6)) | ((value >> 8) << 6) | (0x3 << 7) |
350*61046927SAndroid Build Coastguard Worker (((value >> 6) & BITFIELD_MASK(2)) << 10);
351*61046927SAndroid Build Coastguard Worker } else {
352*61046927SAndroid Build Coastguard Worker pack_assert(I, src.type == AGX_INDEX_REGISTER);
353*61046927SAndroid Build Coastguard Worker pack_assert(I, !(src.cache && src.discard));
354*61046927SAndroid Build Coastguard Worker pack_assert(I, size == AGX_SIZE_16 || size == AGX_SIZE_32);
355*61046927SAndroid Build Coastguard Worker pack_assert(I, size == dest_size);
356*61046927SAndroid Build Coastguard Worker assert_register_is_aligned(I, src);
357*61046927SAndroid Build Coastguard Worker
358*61046927SAndroid Build Coastguard Worker unsigned hint = src.discard ? 0x3 : src.cache ? 0x2 : 0x1;
359*61046927SAndroid Build Coastguard Worker
360*61046927SAndroid Build Coastguard Worker return (value & BITFIELD_MASK(6)) | (hint << 6) |
361*61046927SAndroid Build Coastguard Worker (((value >> 6) & BITFIELD_MASK(2)) << 10);
362*61046927SAndroid Build Coastguard Worker }
363*61046927SAndroid Build Coastguard Worker }
364*61046927SAndroid Build Coastguard Worker
365*61046927SAndroid Build Coastguard Worker static unsigned
agx_pack_sample_mask_src(const agx_instr * I,agx_index src)366*61046927SAndroid Build Coastguard Worker agx_pack_sample_mask_src(const agx_instr *I, agx_index src)
367*61046927SAndroid Build Coastguard Worker {
368*61046927SAndroid Build Coastguard Worker unsigned value = src.value;
369*61046927SAndroid Build Coastguard Worker unsigned packed_value =
370*61046927SAndroid Build Coastguard Worker (value & BITFIELD_MASK(6)) | (((value >> 6) & BITFIELD_MASK(2)) << 10);
371*61046927SAndroid Build Coastguard Worker
372*61046927SAndroid Build Coastguard Worker if (src.type == AGX_INDEX_IMMEDIATE) {
373*61046927SAndroid Build Coastguard Worker pack_assert(I, value < 0x100);
374*61046927SAndroid Build Coastguard Worker return packed_value | (1 << 7);
375*61046927SAndroid Build Coastguard Worker } else {
376*61046927SAndroid Build Coastguard Worker pack_assert(I, src.type == AGX_INDEX_REGISTER);
377*61046927SAndroid Build Coastguard Worker assert_register_is_aligned(I, src);
378*61046927SAndroid Build Coastguard Worker pack_assert(I, !(src.cache && src.discard));
379*61046927SAndroid Build Coastguard Worker
380*61046927SAndroid Build Coastguard Worker return packed_value;
381*61046927SAndroid Build Coastguard Worker }
382*61046927SAndroid Build Coastguard Worker }
383*61046927SAndroid Build Coastguard Worker
384*61046927SAndroid Build Coastguard Worker static unsigned
agx_pack_float_mod(agx_index src)385*61046927SAndroid Build Coastguard Worker agx_pack_float_mod(agx_index src)
386*61046927SAndroid Build Coastguard Worker {
387*61046927SAndroid Build Coastguard Worker return (src.abs ? (1 << 0) : 0) | (src.neg ? (1 << 1) : 0);
388*61046927SAndroid Build Coastguard Worker }
389*61046927SAndroid Build Coastguard Worker
390*61046927SAndroid Build Coastguard Worker static bool
agx_all_16(agx_instr * I)391*61046927SAndroid Build Coastguard Worker agx_all_16(agx_instr *I)
392*61046927SAndroid Build Coastguard Worker {
393*61046927SAndroid Build Coastguard Worker agx_foreach_dest(I, d) {
394*61046927SAndroid Build Coastguard Worker if (!agx_is_null(I->dest[d]) && I->dest[d].size != AGX_SIZE_16)
395*61046927SAndroid Build Coastguard Worker return false;
396*61046927SAndroid Build Coastguard Worker }
397*61046927SAndroid Build Coastguard Worker
398*61046927SAndroid Build Coastguard Worker agx_foreach_src(I, s) {
399*61046927SAndroid Build Coastguard Worker if (!agx_is_null(I->src[s]) && I->src[s].size != AGX_SIZE_16)
400*61046927SAndroid Build Coastguard Worker return false;
401*61046927SAndroid Build Coastguard Worker }
402*61046927SAndroid Build Coastguard Worker
403*61046927SAndroid Build Coastguard Worker return true;
404*61046927SAndroid Build Coastguard Worker }
405*61046927SAndroid Build Coastguard Worker
406*61046927SAndroid Build Coastguard Worker /* Generic pack for ALU instructions, which are quite regular */
407*61046927SAndroid Build Coastguard Worker
408*61046927SAndroid Build Coastguard Worker static void
agx_pack_alu(struct util_dynarray * emission,agx_instr * I)409*61046927SAndroid Build Coastguard Worker agx_pack_alu(struct util_dynarray *emission, agx_instr *I)
410*61046927SAndroid Build Coastguard Worker {
411*61046927SAndroid Build Coastguard Worker struct agx_opcode_info info = agx_opcodes_info[I->op];
412*61046927SAndroid Build Coastguard Worker bool is_16 = agx_all_16(I) && info.encoding_16.exact;
413*61046927SAndroid Build Coastguard Worker struct agx_encoding encoding = is_16 ? info.encoding_16 : info.encoding;
414*61046927SAndroid Build Coastguard Worker
415*61046927SAndroid Build Coastguard Worker pack_assert_msg(I, encoding.exact, "invalid encoding");
416*61046927SAndroid Build Coastguard Worker
417*61046927SAndroid Build Coastguard Worker uint64_t raw = encoding.exact;
418*61046927SAndroid Build Coastguard Worker uint16_t extend = 0;
419*61046927SAndroid Build Coastguard Worker
420*61046927SAndroid Build Coastguard Worker // TODO: assert saturable
421*61046927SAndroid Build Coastguard Worker if (I->saturate)
422*61046927SAndroid Build Coastguard Worker raw |= (1 << 6);
423*61046927SAndroid Build Coastguard Worker
424*61046927SAndroid Build Coastguard Worker if (info.nr_dests) {
425*61046927SAndroid Build Coastguard Worker pack_assert(I, info.nr_dests == 1);
426*61046927SAndroid Build Coastguard Worker unsigned D = agx_pack_alu_dst(I, I->dest[0]);
427*61046927SAndroid Build Coastguard Worker unsigned extend_offset = (sizeof(extend) * 8) - 4;
428*61046927SAndroid Build Coastguard Worker
429*61046927SAndroid Build Coastguard Worker raw |= (D & BITFIELD_MASK(8)) << 7;
430*61046927SAndroid Build Coastguard Worker extend |= ((D >> 8) << extend_offset);
431*61046927SAndroid Build Coastguard Worker
432*61046927SAndroid Build Coastguard Worker if (info.immediates & AGX_IMMEDIATE_INVERT_COND) {
433*61046927SAndroid Build Coastguard Worker raw |= (uint64_t)(I->invert_cond) << 47;
434*61046927SAndroid Build Coastguard Worker }
435*61046927SAndroid Build Coastguard Worker } else if (info.immediates & AGX_IMMEDIATE_NEST) {
436*61046927SAndroid Build Coastguard Worker raw |= (I->invert_cond << 8);
437*61046927SAndroid Build Coastguard Worker raw |= (I->nest << 11);
438*61046927SAndroid Build Coastguard Worker raw |= (I->icond << 13);
439*61046927SAndroid Build Coastguard Worker }
440*61046927SAndroid Build Coastguard Worker
441*61046927SAndroid Build Coastguard Worker for (unsigned s = 0; s < info.nr_srcs; ++s) {
442*61046927SAndroid Build Coastguard Worker bool is_cmpsel = (s >= 2) && (I->op == AGX_OPCODE_ICMPSEL ||
443*61046927SAndroid Build Coastguard Worker I->op == AGX_OPCODE_FCMPSEL);
444*61046927SAndroid Build Coastguard Worker
445*61046927SAndroid Build Coastguard Worker unsigned src = is_cmpsel
446*61046927SAndroid Build Coastguard Worker ? agx_pack_cmpsel_src(I, I->src[s], I->dest[0].size)
447*61046927SAndroid Build Coastguard Worker : agx_pack_alu_src(I, I->src[s]);
448*61046927SAndroid Build Coastguard Worker
449*61046927SAndroid Build Coastguard Worker unsigned src_short = (src & BITFIELD_MASK(10));
450*61046927SAndroid Build Coastguard Worker unsigned src_extend = (src >> 10);
451*61046927SAndroid Build Coastguard Worker
452*61046927SAndroid Build Coastguard Worker /* Size bit always zero and so omitted for 16-bit */
453*61046927SAndroid Build Coastguard Worker if (is_16 && !is_cmpsel)
454*61046927SAndroid Build Coastguard Worker pack_assert(I, (src_short & (1 << 9)) == 0);
455*61046927SAndroid Build Coastguard Worker
456*61046927SAndroid Build Coastguard Worker if (info.is_float || (I->op == AGX_OPCODE_FCMPSEL && !is_cmpsel)) {
457*61046927SAndroid Build Coastguard Worker unsigned fmod = agx_pack_float_mod(I->src[s]);
458*61046927SAndroid Build Coastguard Worker unsigned fmod_offset = is_16 ? 9 : 10;
459*61046927SAndroid Build Coastguard Worker src_short |= (fmod << fmod_offset);
460*61046927SAndroid Build Coastguard Worker } else if (I->op == AGX_OPCODE_IMAD || I->op == AGX_OPCODE_IADD) {
461*61046927SAndroid Build Coastguard Worker /* Force unsigned for immediates so uadd_sat works properly */
462*61046927SAndroid Build Coastguard Worker bool zext = I->src[s].abs || I->src[s].type == AGX_INDEX_IMMEDIATE;
463*61046927SAndroid Build Coastguard Worker bool extends = I->src[s].size < AGX_SIZE_64;
464*61046927SAndroid Build Coastguard Worker
465*61046927SAndroid Build Coastguard Worker unsigned sxt = (extends && !zext) ? (1 << 10) : 0;
466*61046927SAndroid Build Coastguard Worker
467*61046927SAndroid Build Coastguard Worker unsigned negate_src = (I->op == AGX_OPCODE_IMAD) ? 2 : 1;
468*61046927SAndroid Build Coastguard Worker pack_assert(I, !I->src[s].neg || s == negate_src);
469*61046927SAndroid Build Coastguard Worker src_short |= sxt;
470*61046927SAndroid Build Coastguard Worker }
471*61046927SAndroid Build Coastguard Worker
472*61046927SAndroid Build Coastguard Worker /* Sources come at predictable offsets */
473*61046927SAndroid Build Coastguard Worker unsigned offset = 16 + (12 * s);
474*61046927SAndroid Build Coastguard Worker raw |= (((uint64_t)src_short) << offset);
475*61046927SAndroid Build Coastguard Worker
476*61046927SAndroid Build Coastguard Worker /* Destination and each source get extended in reverse order */
477*61046927SAndroid Build Coastguard Worker unsigned extend_offset = (sizeof(extend) * 8) - ((s + 3) * 2);
478*61046927SAndroid Build Coastguard Worker extend |= (src_extend << extend_offset);
479*61046927SAndroid Build Coastguard Worker }
480*61046927SAndroid Build Coastguard Worker
481*61046927SAndroid Build Coastguard Worker if ((I->op == AGX_OPCODE_IMAD && I->src[2].neg) ||
482*61046927SAndroid Build Coastguard Worker (I->op == AGX_OPCODE_IADD && I->src[1].neg))
483*61046927SAndroid Build Coastguard Worker raw |= (1 << 27);
484*61046927SAndroid Build Coastguard Worker
485*61046927SAndroid Build Coastguard Worker if (info.immediates & AGX_IMMEDIATE_TRUTH_TABLE) {
486*61046927SAndroid Build Coastguard Worker raw |= (I->truth_table & 0x3) << 26;
487*61046927SAndroid Build Coastguard Worker raw |= (uint64_t)(I->truth_table >> 2) << 38;
488*61046927SAndroid Build Coastguard Worker } else if (info.immediates & AGX_IMMEDIATE_SHIFT) {
489*61046927SAndroid Build Coastguard Worker pack_assert(I, I->shift <= 4);
490*61046927SAndroid Build Coastguard Worker raw |= (uint64_t)(I->shift & 1) << 39;
491*61046927SAndroid Build Coastguard Worker raw |= (uint64_t)(I->shift >> 1) << 52;
492*61046927SAndroid Build Coastguard Worker } else if (info.immediates & AGX_IMMEDIATE_BFI_MASK) {
493*61046927SAndroid Build Coastguard Worker raw |= (uint64_t)(I->bfi_mask & 0x3) << 38;
494*61046927SAndroid Build Coastguard Worker raw |= (uint64_t)((I->bfi_mask >> 2) & 0x3) << 50;
495*61046927SAndroid Build Coastguard Worker raw |= (uint64_t)((I->bfi_mask >> 4) & 0x1) << 63;
496*61046927SAndroid Build Coastguard Worker } else if (info.immediates & AGX_IMMEDIATE_SIMD_OP) {
497*61046927SAndroid Build Coastguard Worker raw |= (uint64_t)(I->simd_op & 0x1) << 28;
498*61046927SAndroid Build Coastguard Worker raw |= (uint64_t)((I->simd_op >> 1) & 0x7) << 38;
499*61046927SAndroid Build Coastguard Worker raw |= (uint64_t)((I->simd_op >> 4) & 0x1) << 47;
500*61046927SAndroid Build Coastguard Worker } else if (info.immediates & AGX_IMMEDIATE_SR) {
501*61046927SAndroid Build Coastguard Worker raw |= (uint64_t)(I->sr & 0x3F) << 16;
502*61046927SAndroid Build Coastguard Worker raw |= (uint64_t)(I->sr >> 6) << 26;
503*61046927SAndroid Build Coastguard Worker } else if (info.immediates & AGX_IMMEDIATE_WRITEOUT)
504*61046927SAndroid Build Coastguard Worker raw |= (uint64_t)(I->imm) << 8;
505*61046927SAndroid Build Coastguard Worker else if (info.immediates & AGX_IMMEDIATE_IMM)
506*61046927SAndroid Build Coastguard Worker raw |= (uint64_t)(I->imm) << 16;
507*61046927SAndroid Build Coastguard Worker else if (info.immediates & AGX_IMMEDIATE_ROUND)
508*61046927SAndroid Build Coastguard Worker raw |= (uint64_t)(I->imm) << 26;
509*61046927SAndroid Build Coastguard Worker else if (info.immediates & (AGX_IMMEDIATE_FCOND | AGX_IMMEDIATE_ICOND))
510*61046927SAndroid Build Coastguard Worker raw |= (uint64_t)(I->fcond) << 61;
511*61046927SAndroid Build Coastguard Worker
512*61046927SAndroid Build Coastguard Worker /* Determine length bit */
513*61046927SAndroid Build Coastguard Worker unsigned length = encoding.length_short;
514*61046927SAndroid Build Coastguard Worker uint64_t short_mask = BITFIELD64_MASK(8 * length);
515*61046927SAndroid Build Coastguard Worker bool length_bit = (extend || (raw & ~short_mask));
516*61046927SAndroid Build Coastguard Worker
517*61046927SAndroid Build Coastguard Worker if (encoding.extensible && length_bit) {
518*61046927SAndroid Build Coastguard Worker raw |= (1 << 15);
519*61046927SAndroid Build Coastguard Worker length += (length > 8) ? 4 : 2;
520*61046927SAndroid Build Coastguard Worker }
521*61046927SAndroid Build Coastguard Worker
522*61046927SAndroid Build Coastguard Worker /* Pack! */
523*61046927SAndroid Build Coastguard Worker if (length <= sizeof(uint64_t)) {
524*61046927SAndroid Build Coastguard Worker unsigned extend_offset = ((length - sizeof(extend)) * 8);
525*61046927SAndroid Build Coastguard Worker
526*61046927SAndroid Build Coastguard Worker /* XXX: Encode these special cases better */
527*61046927SAndroid Build Coastguard Worker switch (I->op) {
528*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_IADD:
529*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_ICMP_BALLOT:
530*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_ICMP_QUAD_BALLOT:
531*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_FCMP_BALLOT:
532*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_FCMP_QUAD_BALLOT:
533*61046927SAndroid Build Coastguard Worker extend_offset -= 16;
534*61046927SAndroid Build Coastguard Worker break;
535*61046927SAndroid Build Coastguard Worker default:
536*61046927SAndroid Build Coastguard Worker break;
537*61046927SAndroid Build Coastguard Worker }
538*61046927SAndroid Build Coastguard Worker
539*61046927SAndroid Build Coastguard Worker raw |= (uint64_t)extend << extend_offset;
540*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, length), &raw, length);
541*61046927SAndroid Build Coastguard Worker } else {
542*61046927SAndroid Build Coastguard Worker /* So far, >8 byte ALU is only to store the extend bits */
543*61046927SAndroid Build Coastguard Worker unsigned extend_offset = (((length - sizeof(extend)) * 8) - 64);
544*61046927SAndroid Build Coastguard Worker unsigned hi = ((uint64_t)extend) << extend_offset;
545*61046927SAndroid Build Coastguard Worker
546*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, 8), &raw, 8);
547*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, length - 8), &hi,
548*61046927SAndroid Build Coastguard Worker length - 8);
549*61046927SAndroid Build Coastguard Worker }
550*61046927SAndroid Build Coastguard Worker }
551*61046927SAndroid Build Coastguard Worker
552*61046927SAndroid Build Coastguard Worker static void
agx_pack_instr(struct util_dynarray * emission,struct util_dynarray * fixups,agx_instr * I,bool needs_g13x_coherency)553*61046927SAndroid Build Coastguard Worker agx_pack_instr(struct util_dynarray *emission, struct util_dynarray *fixups,
554*61046927SAndroid Build Coastguard Worker agx_instr *I, bool needs_g13x_coherency)
555*61046927SAndroid Build Coastguard Worker {
556*61046927SAndroid Build Coastguard Worker switch (I->op) {
557*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_LD_TILE:
558*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_ST_TILE: {
559*61046927SAndroid Build Coastguard Worker bool load = (I->op == AGX_OPCODE_LD_TILE);
560*61046927SAndroid Build Coastguard Worker unsigned D = agx_pack_alu_dst(I, load ? I->dest[0] : I->src[0]);
561*61046927SAndroid Build Coastguard Worker pack_assert(I, I->mask < 0x10);
562*61046927SAndroid Build Coastguard Worker pack_assert(I, I->pixel_offset < 0x200);
563*61046927SAndroid Build Coastguard Worker
564*61046927SAndroid Build Coastguard Worker agx_index sample_index = load ? I->src[0] : I->src[1];
565*61046927SAndroid Build Coastguard Worker agx_index coords = load ? I->src[1] : I->src[2];
566*61046927SAndroid Build Coastguard Worker pack_assert(I, sample_index.type == AGX_INDEX_REGISTER ||
567*61046927SAndroid Build Coastguard Worker sample_index.type == AGX_INDEX_IMMEDIATE);
568*61046927SAndroid Build Coastguard Worker pack_assert(I, sample_index.size == AGX_SIZE_16);
569*61046927SAndroid Build Coastguard Worker unsigned St = (sample_index.type == AGX_INDEX_REGISTER) ? 1 : 0;
570*61046927SAndroid Build Coastguard Worker unsigned S = sample_index.value;
571*61046927SAndroid Build Coastguard Worker pack_assert(I, S < 0x100);
572*61046927SAndroid Build Coastguard Worker
573*61046927SAndroid Build Coastguard Worker pack_assert(I, I->explicit_coords == (coords.type == AGX_INDEX_REGISTER));
574*61046927SAndroid Build Coastguard Worker unsigned C = I->explicit_coords ? coords.value : 0;
575*61046927SAndroid Build Coastguard Worker
576*61046927SAndroid Build Coastguard Worker uint64_t raw = agx_opcodes_info[I->op].encoding.exact |
577*61046927SAndroid Build Coastguard Worker ((uint64_t)(D & BITFIELD_MASK(8)) << 7) | (St << 22) |
578*61046927SAndroid Build Coastguard Worker ((uint64_t)(I->format) << 24) |
579*61046927SAndroid Build Coastguard Worker ((uint64_t)(C & BITFIELD_MASK(6)) << 16) |
580*61046927SAndroid Build Coastguard Worker ((uint64_t)(I->pixel_offset & BITFIELD_MASK(7)) << 28) |
581*61046927SAndroid Build Coastguard Worker (load || I->explicit_coords ? (1ull << 35) : 0) |
582*61046927SAndroid Build Coastguard Worker ((uint64_t)(I->mask) << 36) |
583*61046927SAndroid Build Coastguard Worker ((uint64_t)(I->pixel_offset >> 7) << 40) |
584*61046927SAndroid Build Coastguard Worker ((uint64_t)(S & BITFIELD_MASK(6)) << 42) |
585*61046927SAndroid Build Coastguard Worker (I->explicit_coords ? (1ull << 55) : 0) |
586*61046927SAndroid Build Coastguard Worker ((uint64_t)(S >> 6) << 56) | ((uint64_t)(C >> 6) << 58) |
587*61046927SAndroid Build Coastguard Worker (((uint64_t)(D >> 8)) << 60);
588*61046927SAndroid Build Coastguard Worker
589*61046927SAndroid Build Coastguard Worker unsigned size = 8;
590*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, size), &raw, size);
591*61046927SAndroid Build Coastguard Worker break;
592*61046927SAndroid Build Coastguard Worker }
593*61046927SAndroid Build Coastguard Worker
594*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_SAMPLE_MASK: {
595*61046927SAndroid Build Coastguard Worker unsigned S = agx_pack_sample_mask_src(I, I->src[1]);
596*61046927SAndroid Build Coastguard Worker unsigned T = I->src[0].value;
597*61046927SAndroid Build Coastguard Worker bool Tt = I->src[0].type == AGX_INDEX_IMMEDIATE;
598*61046927SAndroid Build Coastguard Worker pack_assert(I, Tt || I->src[0].type == AGX_INDEX_REGISTER);
599*61046927SAndroid Build Coastguard Worker uint32_t raw = 0xc1 | (Tt ? BITFIELD_BIT(8) : 0) |
600*61046927SAndroid Build Coastguard Worker ((T & BITFIELD_MASK(6)) << 9) | ((S & 0xff) << 16) |
601*61046927SAndroid Build Coastguard Worker ((T >> 6) << 24) | ((S >> 8) << 26);
602*61046927SAndroid Build Coastguard Worker
603*61046927SAndroid Build Coastguard Worker unsigned size = 4;
604*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, size), &raw, size);
605*61046927SAndroid Build Coastguard Worker break;
606*61046927SAndroid Build Coastguard Worker }
607*61046927SAndroid Build Coastguard Worker
608*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_WAIT: {
609*61046927SAndroid Build Coastguard Worker uint64_t raw =
610*61046927SAndroid Build Coastguard Worker agx_opcodes_info[I->op].encoding.exact | (I->scoreboard << 8);
611*61046927SAndroid Build Coastguard Worker
612*61046927SAndroid Build Coastguard Worker unsigned size = 2;
613*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, size), &raw, size);
614*61046927SAndroid Build Coastguard Worker break;
615*61046927SAndroid Build Coastguard Worker }
616*61046927SAndroid Build Coastguard Worker
617*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_ITER:
618*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_ITERPROJ:
619*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_LDCF: {
620*61046927SAndroid Build Coastguard Worker bool flat = (I->op == AGX_OPCODE_LDCF);
621*61046927SAndroid Build Coastguard Worker bool perspective = (I->op == AGX_OPCODE_ITERPROJ);
622*61046927SAndroid Build Coastguard Worker unsigned D = agx_pack_alu_dst(I, I->dest[0]);
623*61046927SAndroid Build Coastguard Worker unsigned channels = (I->channels & 0x3);
624*61046927SAndroid Build Coastguard Worker
625*61046927SAndroid Build Coastguard Worker agx_index src_I = I->src[0];
626*61046927SAndroid Build Coastguard Worker pack_assert(I, src_I.type == AGX_INDEX_IMMEDIATE ||
627*61046927SAndroid Build Coastguard Worker src_I.type == AGX_INDEX_REGISTER);
628*61046927SAndroid Build Coastguard Worker
629*61046927SAndroid Build Coastguard Worker unsigned cf_I = src_I.value;
630*61046927SAndroid Build Coastguard Worker unsigned cf_J = 0;
631*61046927SAndroid Build Coastguard Worker
632*61046927SAndroid Build Coastguard Worker if (perspective) {
633*61046927SAndroid Build Coastguard Worker agx_index src_J = I->src[1];
634*61046927SAndroid Build Coastguard Worker pack_assert(I, src_J.type == AGX_INDEX_IMMEDIATE);
635*61046927SAndroid Build Coastguard Worker cf_J = src_J.value;
636*61046927SAndroid Build Coastguard Worker }
637*61046927SAndroid Build Coastguard Worker
638*61046927SAndroid Build Coastguard Worker pack_assert(I, cf_I < 0x100);
639*61046927SAndroid Build Coastguard Worker pack_assert(I, cf_J < 0x100);
640*61046927SAndroid Build Coastguard Worker
641*61046927SAndroid Build Coastguard Worker enum agx_interpolation interp = I->interpolation;
642*61046927SAndroid Build Coastguard Worker agx_index sample_index = flat ? agx_null() : I->src[perspective ? 2 : 1];
643*61046927SAndroid Build Coastguard Worker
644*61046927SAndroid Build Coastguard Worker /* Fix up the interpolation enum to distinguish the sample index source */
645*61046927SAndroid Build Coastguard Worker if (interp == AGX_INTERPOLATION_SAMPLE) {
646*61046927SAndroid Build Coastguard Worker if (sample_index.type == AGX_INDEX_REGISTER)
647*61046927SAndroid Build Coastguard Worker interp = AGX_INTERPOLATION_SAMPLE_REGISTER;
648*61046927SAndroid Build Coastguard Worker else
649*61046927SAndroid Build Coastguard Worker pack_assert(I, sample_index.type == AGX_INDEX_IMMEDIATE);
650*61046927SAndroid Build Coastguard Worker } else {
651*61046927SAndroid Build Coastguard Worker sample_index = agx_zero();
652*61046927SAndroid Build Coastguard Worker }
653*61046927SAndroid Build Coastguard Worker
654*61046927SAndroid Build Coastguard Worker bool kill = false; // TODO: optimize
655*61046927SAndroid Build Coastguard Worker bool forward = false; // TODO: optimize
656*61046927SAndroid Build Coastguard Worker
657*61046927SAndroid Build Coastguard Worker uint64_t raw =
658*61046927SAndroid Build Coastguard Worker 0x21 | (flat ? (1 << 7) : 0) | (perspective ? (1 << 6) : 0) |
659*61046927SAndroid Build Coastguard Worker ((D & 0xFF) << 7) | (1ull << 15) | /* XXX */
660*61046927SAndroid Build Coastguard Worker ((cf_I & BITFIELD_MASK(6)) << 16) |
661*61046927SAndroid Build Coastguard Worker ((src_I.type == AGX_INDEX_REGISTER) ? (1 << 23) : 0) |
662*61046927SAndroid Build Coastguard Worker ((cf_J & BITFIELD_MASK(6)) << 24) | (((uint64_t)channels) << 30) |
663*61046927SAndroid Build Coastguard Worker (((uint64_t)sample_index.value) << 32) | (forward ? (1ull << 46) : 0) |
664*61046927SAndroid Build Coastguard Worker (((uint64_t)interp) << 48) | (kill ? (1ull << 52) : 0) |
665*61046927SAndroid Build Coastguard Worker (((uint64_t)(D >> 8)) << 56) | ((uint64_t)(cf_I >> 6) << 58) |
666*61046927SAndroid Build Coastguard Worker ((uint64_t)(cf_J >> 6) << 60);
667*61046927SAndroid Build Coastguard Worker
668*61046927SAndroid Build Coastguard Worker unsigned size = 8;
669*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, size), &raw, size);
670*61046927SAndroid Build Coastguard Worker break;
671*61046927SAndroid Build Coastguard Worker }
672*61046927SAndroid Build Coastguard Worker
673*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_ST_VARY: {
674*61046927SAndroid Build Coastguard Worker agx_index index_src = I->src[0];
675*61046927SAndroid Build Coastguard Worker agx_index value = I->src[1];
676*61046927SAndroid Build Coastguard Worker
677*61046927SAndroid Build Coastguard Worker pack_assert(I, index_src.type == AGX_INDEX_IMMEDIATE ||
678*61046927SAndroid Build Coastguard Worker index_src.type == AGX_INDEX_REGISTER);
679*61046927SAndroid Build Coastguard Worker pack_assert(I, index_src.value < BITFIELD_MASK(8));
680*61046927SAndroid Build Coastguard Worker pack_assert(I, value.type == AGX_INDEX_REGISTER);
681*61046927SAndroid Build Coastguard Worker pack_assert(I, value.size == AGX_SIZE_32);
682*61046927SAndroid Build Coastguard Worker
683*61046927SAndroid Build Coastguard Worker uint64_t raw = 0x11 | (I->last ? (1 << 7) : 0) |
684*61046927SAndroid Build Coastguard Worker ((value.value & 0x3F) << 9) |
685*61046927SAndroid Build Coastguard Worker (((uint64_t)(index_src.value & 0x3F)) << 16) |
686*61046927SAndroid Build Coastguard Worker (index_src.type == AGX_INDEX_IMMEDIATE ? (1 << 23) : 0) |
687*61046927SAndroid Build Coastguard Worker ((value.value >> 6) << 24) |
688*61046927SAndroid Build Coastguard Worker ((index_src.value >> 6) << 26) | (0x8u << 28); /* XXX */
689*61046927SAndroid Build Coastguard Worker
690*61046927SAndroid Build Coastguard Worker unsigned size = 4;
691*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, size), &raw, size);
692*61046927SAndroid Build Coastguard Worker break;
693*61046927SAndroid Build Coastguard Worker }
694*61046927SAndroid Build Coastguard Worker
695*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_DEVICE_LOAD:
696*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_DEVICE_STORE:
697*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_UNIFORM_STORE: {
698*61046927SAndroid Build Coastguard Worker bool is_device_store = I->op == AGX_OPCODE_DEVICE_STORE;
699*61046927SAndroid Build Coastguard Worker bool is_uniform_store = I->op == AGX_OPCODE_UNIFORM_STORE;
700*61046927SAndroid Build Coastguard Worker bool is_store = is_device_store || is_uniform_store;
701*61046927SAndroid Build Coastguard Worker bool has_base = !is_uniform_store;
702*61046927SAndroid Build Coastguard Worker
703*61046927SAndroid Build Coastguard Worker /* Uniform stores are required to be 16-bit. The encoding that should be
704*61046927SAndroid Build Coastguard Worker * 32-bit annoyingly doesn't work. Fix up the format and size so we can
705*61046927SAndroid Build Coastguard Worker * use scalar 32-bit values in the IR and avoid special casing earlier in
706*61046927SAndroid Build Coastguard Worker * the compiler.
707*61046927SAndroid Build Coastguard Worker */
708*61046927SAndroid Build Coastguard Worker enum agx_format format = is_uniform_store ? AGX_FORMAT_I16 : I->format;
709*61046927SAndroid Build Coastguard Worker agx_index reg = is_store ? I->src[0] : I->dest[0];
710*61046927SAndroid Build Coastguard Worker unsigned mask = I->mask;
711*61046927SAndroid Build Coastguard Worker
712*61046927SAndroid Build Coastguard Worker if (is_uniform_store && reg.size != AGX_SIZE_16) {
713*61046927SAndroid Build Coastguard Worker if (reg.size == AGX_SIZE_64) {
714*61046927SAndroid Build Coastguard Worker assert(mask == 1);
715*61046927SAndroid Build Coastguard Worker mask = BITFIELD_MASK(4);
716*61046927SAndroid Build Coastguard Worker } else {
717*61046927SAndroid Build Coastguard Worker assert(reg.size == AGX_SIZE_32);
718*61046927SAndroid Build Coastguard Worker assert(mask == 1 || mask == 3);
719*61046927SAndroid Build Coastguard Worker mask = BITFIELD_MASK(mask == 3 ? 4 : 2);
720*61046927SAndroid Build Coastguard Worker }
721*61046927SAndroid Build Coastguard Worker
722*61046927SAndroid Build Coastguard Worker reg.size = AGX_SIZE_16;
723*61046927SAndroid Build Coastguard Worker }
724*61046927SAndroid Build Coastguard Worker
725*61046927SAndroid Build Coastguard Worker unsigned offset_src = (has_base ? 1 : 0) + (is_store ? 1 : 0);
726*61046927SAndroid Build Coastguard Worker
727*61046927SAndroid Build Coastguard Worker bool Rt, At = false, Ot;
728*61046927SAndroid Build Coastguard Worker unsigned R = agx_pack_memory_reg(I, reg, &Rt);
729*61046927SAndroid Build Coastguard Worker unsigned A =
730*61046927SAndroid Build Coastguard Worker has_base ? agx_pack_memory_base(I, I->src[is_store ? 1 : 0], &At) : 0;
731*61046927SAndroid Build Coastguard Worker unsigned O = agx_pack_memory_index(I, I->src[offset_src], &Ot);
732*61046927SAndroid Build Coastguard Worker unsigned u1 = is_uniform_store ? 0 : 1; // XXX
733*61046927SAndroid Build Coastguard Worker unsigned u3 = 0;
734*61046927SAndroid Build Coastguard Worker unsigned u4 = is_uniform_store ? 0 : 4; // XXX
735*61046927SAndroid Build Coastguard Worker unsigned u5 = 0;
736*61046927SAndroid Build Coastguard Worker bool L = true; /* TODO: when would you want short? */
737*61046927SAndroid Build Coastguard Worker
738*61046927SAndroid Build Coastguard Worker pack_assert(I, mask != 0);
739*61046927SAndroid Build Coastguard Worker pack_assert(I, format <= 0x10);
740*61046927SAndroid Build Coastguard Worker
741*61046927SAndroid Build Coastguard Worker uint64_t raw =
742*61046927SAndroid Build Coastguard Worker agx_opcodes_info[I->op].encoding.exact |
743*61046927SAndroid Build Coastguard Worker ((format & BITFIELD_MASK(3)) << 7) | ((R & BITFIELD_MASK(6)) << 10) |
744*61046927SAndroid Build Coastguard Worker ((A & BITFIELD_MASK(4)) << 16) | ((O & BITFIELD_MASK(4)) << 20) |
745*61046927SAndroid Build Coastguard Worker (Ot ? (1 << 24) : 0) | (I->src[offset_src].abs ? (1 << 25) : 0) |
746*61046927SAndroid Build Coastguard Worker (is_uniform_store ? (2 << 25) : 0) | (u1 << 26) | (At << 27) |
747*61046927SAndroid Build Coastguard Worker (u3 << 28) | (I->scoreboard << 30) |
748*61046927SAndroid Build Coastguard Worker (((uint64_t)((O >> 4) & BITFIELD_MASK(4))) << 32) |
749*61046927SAndroid Build Coastguard Worker (((uint64_t)((A >> 4) & BITFIELD_MASK(4))) << 36) |
750*61046927SAndroid Build Coastguard Worker (((uint64_t)((R >> 6) & BITFIELD_MASK(2))) << 40) |
751*61046927SAndroid Build Coastguard Worker (((uint64_t)I->shift) << 42) | (((uint64_t)u4) << 44) |
752*61046927SAndroid Build Coastguard Worker (L ? (1ull << 47) : 0) | (((uint64_t)(format >> 3)) << 48) |
753*61046927SAndroid Build Coastguard Worker (((uint64_t)Rt) << 49) | (((uint64_t)u5) << 50) |
754*61046927SAndroid Build Coastguard Worker (((uint64_t)mask) << 52) | (((uint64_t)(O >> 8)) << 56);
755*61046927SAndroid Build Coastguard Worker
756*61046927SAndroid Build Coastguard Worker unsigned size = L ? 8 : 6;
757*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, size), &raw, size);
758*61046927SAndroid Build Coastguard Worker break;
759*61046927SAndroid Build Coastguard Worker }
760*61046927SAndroid Build Coastguard Worker
761*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_LOCAL_LOAD:
762*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_LOCAL_STORE: {
763*61046927SAndroid Build Coastguard Worker bool is_load = I->op == AGX_OPCODE_LOCAL_LOAD;
764*61046927SAndroid Build Coastguard Worker bool L = true; /* TODO: when would you want short? */
765*61046927SAndroid Build Coastguard Worker unsigned At;
766*61046927SAndroid Build Coastguard Worker bool Rt, Ot;
767*61046927SAndroid Build Coastguard Worker
768*61046927SAndroid Build Coastguard Worker unsigned R =
769*61046927SAndroid Build Coastguard Worker agx_pack_memory_reg(I, is_load ? I->dest[0] : I->src[0], &Rt);
770*61046927SAndroid Build Coastguard Worker unsigned A = agx_pack_local_base(I, is_load ? I->src[0] : I->src[1], &At);
771*61046927SAndroid Build Coastguard Worker unsigned O =
772*61046927SAndroid Build Coastguard Worker agx_pack_local_index(I, is_load ? I->src[1] : I->src[2], &Ot);
773*61046927SAndroid Build Coastguard Worker
774*61046927SAndroid Build Coastguard Worker uint64_t raw =
775*61046927SAndroid Build Coastguard Worker agx_opcodes_info[I->op].encoding.exact | (Rt ? BITFIELD64_BIT(8) : 0) |
776*61046927SAndroid Build Coastguard Worker ((R & BITFIELD_MASK(6)) << 9) | (L ? BITFIELD64_BIT(15) : 0) |
777*61046927SAndroid Build Coastguard Worker ((A & BITFIELD_MASK(6)) << 16) | (At << 22) | (I->format << 24) |
778*61046927SAndroid Build Coastguard Worker ((O & BITFIELD64_MASK(6)) << 28) | (Ot ? BITFIELD64_BIT(34) : 0) |
779*61046927SAndroid Build Coastguard Worker (((uint64_t)I->mask) << 36) | (((uint64_t)(O >> 6)) << 48) |
780*61046927SAndroid Build Coastguard Worker (((uint64_t)(A >> 6)) << 58) | (((uint64_t)(R >> 6)) << 60);
781*61046927SAndroid Build Coastguard Worker
782*61046927SAndroid Build Coastguard Worker unsigned size = L ? 8 : 6;
783*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, size), &raw, size);
784*61046927SAndroid Build Coastguard Worker break;
785*61046927SAndroid Build Coastguard Worker }
786*61046927SAndroid Build Coastguard Worker
787*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_ATOMIC: {
788*61046927SAndroid Build Coastguard Worker bool At, Ot, Rt;
789*61046927SAndroid Build Coastguard Worker unsigned A = agx_pack_memory_base(I, I->src[1], &At);
790*61046927SAndroid Build Coastguard Worker unsigned O = agx_pack_memory_index(I, I->src[2], &Ot);
791*61046927SAndroid Build Coastguard Worker unsigned R = agx_pack_atomic_dest(I, I->dest[0], &Rt);
792*61046927SAndroid Build Coastguard Worker unsigned S = agx_pack_atomic_source(I, I->src[0]);
793*61046927SAndroid Build Coastguard Worker
794*61046927SAndroid Build Coastguard Worker uint64_t raw =
795*61046927SAndroid Build Coastguard Worker agx_opcodes_info[I->op].encoding.exact |
796*61046927SAndroid Build Coastguard Worker (((uint64_t)I->atomic_opc) << 6) | ((R & BITFIELD_MASK(6)) << 10) |
797*61046927SAndroid Build Coastguard Worker ((A & BITFIELD_MASK(4)) << 16) | ((O & BITFIELD_MASK(4)) << 20) |
798*61046927SAndroid Build Coastguard Worker (Ot ? (1 << 24) : 0) | (I->src[2].abs ? (1 << 25) : 0) | (At << 27) |
799*61046927SAndroid Build Coastguard Worker (I->scoreboard << 30) |
800*61046927SAndroid Build Coastguard Worker (((uint64_t)((O >> 4) & BITFIELD_MASK(4))) << 32) |
801*61046927SAndroid Build Coastguard Worker (((uint64_t)((A >> 4) & BITFIELD_MASK(4))) << 36) |
802*61046927SAndroid Build Coastguard Worker (((uint64_t)(R >> 6)) << 40) |
803*61046927SAndroid Build Coastguard Worker (needs_g13x_coherency ? BITFIELD64_BIT(45) : 0) |
804*61046927SAndroid Build Coastguard Worker (Rt ? BITFIELD64_BIT(47) : 0) | (((uint64_t)S) << 48) |
805*61046927SAndroid Build Coastguard Worker (((uint64_t)(O >> 8)) << 56);
806*61046927SAndroid Build Coastguard Worker
807*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, 8), &raw, 8);
808*61046927SAndroid Build Coastguard Worker break;
809*61046927SAndroid Build Coastguard Worker }
810*61046927SAndroid Build Coastguard Worker
811*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_LOCAL_ATOMIC: {
812*61046927SAndroid Build Coastguard Worker bool L = true; /* TODO: Don't force */
813*61046927SAndroid Build Coastguard Worker
814*61046927SAndroid Build Coastguard Worker unsigned At;
815*61046927SAndroid Build Coastguard Worker bool Rt = false, Ot;
816*61046927SAndroid Build Coastguard Worker
817*61046927SAndroid Build Coastguard Worker bool Ra = I->dest[0].type != AGX_INDEX_NULL;
818*61046927SAndroid Build Coastguard Worker unsigned R = Ra ? agx_pack_memory_reg(I, I->dest[0], &Rt) : 0;
819*61046927SAndroid Build Coastguard Worker unsigned S = agx_pack_atomic_source(I, I->src[0]);
820*61046927SAndroid Build Coastguard Worker unsigned A = agx_pack_local_base(I, I->src[1], &At);
821*61046927SAndroid Build Coastguard Worker unsigned O = agx_pack_local_index(I, I->src[2], &Ot);
822*61046927SAndroid Build Coastguard Worker
823*61046927SAndroid Build Coastguard Worker uint64_t raw =
824*61046927SAndroid Build Coastguard Worker agx_opcodes_info[I->op].encoding.exact | (Rt ? BITFIELD64_BIT(8) : 0) |
825*61046927SAndroid Build Coastguard Worker ((R & BITFIELD_MASK(6)) << 9) | (L ? BITFIELD64_BIT(15) : 0) |
826*61046927SAndroid Build Coastguard Worker ((A & BITFIELD_MASK(6)) << 16) | (At << 22) |
827*61046927SAndroid Build Coastguard Worker (((uint64_t)I->atomic_opc) << 24) | ((O & BITFIELD64_MASK(6)) << 28) |
828*61046927SAndroid Build Coastguard Worker (Ot ? BITFIELD64_BIT(34) : 0) | (Ra ? BITFIELD64_BIT(38) : 0) |
829*61046927SAndroid Build Coastguard Worker (((uint64_t)(O >> 6)) << 48) | (((uint64_t)(A >> 6)) << 58) |
830*61046927SAndroid Build Coastguard Worker (((uint64_t)(R >> 6)) << 60);
831*61046927SAndroid Build Coastguard Worker
832*61046927SAndroid Build Coastguard Worker uint64_t raw2 = S;
833*61046927SAndroid Build Coastguard Worker
834*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, 8), &raw, 8);
835*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, 2), &raw2, 2);
836*61046927SAndroid Build Coastguard Worker break;
837*61046927SAndroid Build Coastguard Worker }
838*61046927SAndroid Build Coastguard Worker
839*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_TEXTURE_LOAD:
840*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_IMAGE_LOAD:
841*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_TEXTURE_SAMPLE: {
842*61046927SAndroid Build Coastguard Worker pack_assert(I, I->mask != 0);
843*61046927SAndroid Build Coastguard Worker pack_assert(I, I->format <= 0x10);
844*61046927SAndroid Build Coastguard Worker
845*61046927SAndroid Build Coastguard Worker bool Rt, Ct, St, Cs;
846*61046927SAndroid Build Coastguard Worker unsigned Tt;
847*61046927SAndroid Build Coastguard Worker unsigned U;
848*61046927SAndroid Build Coastguard Worker enum agx_lod_mode lod_mode = I->lod_mode;
849*61046927SAndroid Build Coastguard Worker
850*61046927SAndroid Build Coastguard Worker unsigned R = agx_pack_memory_reg(I, I->dest[0], &Rt);
851*61046927SAndroid Build Coastguard Worker unsigned C = agx_pack_sample_coords(I, I->src[0], &Ct, &Cs);
852*61046927SAndroid Build Coastguard Worker unsigned T = agx_pack_texture(I, I->src[2], I->src[3], &U, &Tt);
853*61046927SAndroid Build Coastguard Worker unsigned S = agx_pack_sampler(I, I->src[4], &St);
854*61046927SAndroid Build Coastguard Worker unsigned O = agx_pack_sample_compare_offset(I, I->src[5]);
855*61046927SAndroid Build Coastguard Worker unsigned D = agx_pack_lod(I, I->src[1], &lod_mode);
856*61046927SAndroid Build Coastguard Worker
857*61046927SAndroid Build Coastguard Worker unsigned q1 = I->shadow;
858*61046927SAndroid Build Coastguard Worker unsigned q2 = I->query_lod ? 2 : 0;
859*61046927SAndroid Build Coastguard Worker unsigned q3 = 12; // XXX
860*61046927SAndroid Build Coastguard Worker unsigned kill = 0; // helper invocation kill bit
861*61046927SAndroid Build Coastguard Worker
862*61046927SAndroid Build Coastguard Worker /* Set bit 43 for image loads. This seems to makes sure that image loads
863*61046927SAndroid Build Coastguard Worker * get the value written by the latest image store, not some other image
864*61046927SAndroid Build Coastguard Worker * store that was already in flight, fixing
865*61046927SAndroid Build Coastguard Worker *
866*61046927SAndroid Build Coastguard Worker * KHR-GLES31.core.shader_image_load_store.basic-glsl-misc-fs
867*61046927SAndroid Build Coastguard Worker *
868*61046927SAndroid Build Coastguard Worker * Apple seems to set this bit unconditionally for read/write image loads
869*61046927SAndroid Build Coastguard Worker * and never for readonly image loads. Some sort of cache control.
870*61046927SAndroid Build Coastguard Worker */
871*61046927SAndroid Build Coastguard Worker if (I->op == AGX_OPCODE_IMAGE_LOAD)
872*61046927SAndroid Build Coastguard Worker q3 |= 1;
873*61046927SAndroid Build Coastguard Worker
874*61046927SAndroid Build Coastguard Worker uint32_t extend = ((U & BITFIELD_MASK(5)) << 0) | (kill << 5) |
875*61046927SAndroid Build Coastguard Worker ((I->dim >> 3) << 7) | ((R >> 6) << 8) |
876*61046927SAndroid Build Coastguard Worker ((C >> 6) << 10) | ((D >> 6) << 12) | ((T >> 6) << 14) |
877*61046927SAndroid Build Coastguard Worker ((O & BITFIELD_MASK(6)) << 16) | (I->gather << 23) |
878*61046927SAndroid Build Coastguard Worker (I->offset << 27) | ((S >> 6) << 28) | ((O >> 6) << 30);
879*61046927SAndroid Build Coastguard Worker
880*61046927SAndroid Build Coastguard Worker bool L = (extend != 0);
881*61046927SAndroid Build Coastguard Worker
882*61046927SAndroid Build Coastguard Worker uint64_t raw =
883*61046927SAndroid Build Coastguard Worker 0x31 | ((I->op != AGX_OPCODE_TEXTURE_SAMPLE) ? (1 << 6) : 0) |
884*61046927SAndroid Build Coastguard Worker (Rt ? (1 << 8) : 0) | ((R & BITFIELD_MASK(6)) << 9) |
885*61046927SAndroid Build Coastguard Worker (L ? (1 << 15) : 0) | ((C & BITFIELD_MASK(6)) << 16) |
886*61046927SAndroid Build Coastguard Worker (Ct ? (1 << 22) : 0) | (q1 << 23) | ((D & BITFIELD_MASK(6)) << 24) |
887*61046927SAndroid Build Coastguard Worker (q2 << 30) | (((uint64_t)(T & BITFIELD_MASK(6))) << 32) |
888*61046927SAndroid Build Coastguard Worker (((uint64_t)Tt) << 38) |
889*61046927SAndroid Build Coastguard Worker (((uint64_t)(I->dim & BITFIELD_MASK(3))) << 40) |
890*61046927SAndroid Build Coastguard Worker (((uint64_t)q3) << 43) | (((uint64_t)I->mask) << 48) |
891*61046927SAndroid Build Coastguard Worker (((uint64_t)lod_mode) << 52) |
892*61046927SAndroid Build Coastguard Worker (((uint64_t)(S & BITFIELD_MASK(6))) << 56) | (((uint64_t)St) << 62) |
893*61046927SAndroid Build Coastguard Worker (((uint64_t)I->scoreboard) << 63);
894*61046927SAndroid Build Coastguard Worker
895*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, 8), &raw, 8);
896*61046927SAndroid Build Coastguard Worker if (L)
897*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, 4), &extend, 4);
898*61046927SAndroid Build Coastguard Worker
899*61046927SAndroid Build Coastguard Worker break;
900*61046927SAndroid Build Coastguard Worker }
901*61046927SAndroid Build Coastguard Worker
902*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_IMAGE_WRITE: {
903*61046927SAndroid Build Coastguard Worker bool Ct, Dt, Rt, Cs;
904*61046927SAndroid Build Coastguard Worker unsigned Tt;
905*61046927SAndroid Build Coastguard Worker unsigned U;
906*61046927SAndroid Build Coastguard Worker
907*61046927SAndroid Build Coastguard Worker unsigned R = agx_pack_pbe_source(I, I->src[0], &Rt);
908*61046927SAndroid Build Coastguard Worker unsigned C = agx_pack_sample_coords(I, I->src[1], &Ct, &Cs);
909*61046927SAndroid Build Coastguard Worker unsigned D = agx_pack_pbe_lod(I, I->src[2], &Dt);
910*61046927SAndroid Build Coastguard Worker unsigned T = agx_pack_texture(I, I->src[3], I->src[4], &U, &Tt);
911*61046927SAndroid Build Coastguard Worker bool rtz = false;
912*61046927SAndroid Build Coastguard Worker
913*61046927SAndroid Build Coastguard Worker pack_assert(I, U < (1 << 5));
914*61046927SAndroid Build Coastguard Worker pack_assert(I, D < (1 << 8));
915*61046927SAndroid Build Coastguard Worker pack_assert(I, R < (1 << 8));
916*61046927SAndroid Build Coastguard Worker pack_assert(I, C < (1 << 8));
917*61046927SAndroid Build Coastguard Worker pack_assert(I, T < (1 << 8));
918*61046927SAndroid Build Coastguard Worker pack_assert(I, Tt < (1 << 2));
919*61046927SAndroid Build Coastguard Worker
920*61046927SAndroid Build Coastguard Worker uint64_t raw = agx_opcodes_info[I->op].encoding.exact |
921*61046927SAndroid Build Coastguard Worker (Rt ? (1 << 8) : 0) | ((R & BITFIELD_MASK(6)) << 9) |
922*61046927SAndroid Build Coastguard Worker ((C & BITFIELD_MASK(6)) << 16) | (Ct ? (1 << 22) : 0) |
923*61046927SAndroid Build Coastguard Worker ((D & BITFIELD_MASK(6)) << 24) | (Dt ? (1u << 31) : 0) |
924*61046927SAndroid Build Coastguard Worker (((uint64_t)(T & BITFIELD_MASK(6))) << 32) |
925*61046927SAndroid Build Coastguard Worker (((uint64_t)Tt) << 38) |
926*61046927SAndroid Build Coastguard Worker (((uint64_t)I->dim & BITFIELD_MASK(3)) << 40) |
927*61046927SAndroid Build Coastguard Worker (Cs ? (1ull << 47) : 0) | (((uint64_t)U) << 48) |
928*61046927SAndroid Build Coastguard Worker (rtz ? (1ull << 53) : 0) |
929*61046927SAndroid Build Coastguard Worker ((I->dim & BITFIELD_BIT(4)) ? (1ull << 55) : 0) |
930*61046927SAndroid Build Coastguard Worker (((uint64_t)R >> 6) << 56) | (((uint64_t)C >> 6) << 58) |
931*61046927SAndroid Build Coastguard Worker (((uint64_t)D >> 6) << 60) | (((uint64_t)T >> 6) << 62);
932*61046927SAndroid Build Coastguard Worker
933*61046927SAndroid Build Coastguard Worker if (raw >> 48) {
934*61046927SAndroid Build Coastguard Worker raw |= BITFIELD_BIT(15);
935*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, 8), &raw, 8);
936*61046927SAndroid Build Coastguard Worker } else {
937*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, 6), &raw, 6);
938*61046927SAndroid Build Coastguard Worker }
939*61046927SAndroid Build Coastguard Worker
940*61046927SAndroid Build Coastguard Worker break;
941*61046927SAndroid Build Coastguard Worker }
942*61046927SAndroid Build Coastguard Worker
943*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_BLOCK_IMAGE_STORE: {
944*61046927SAndroid Build Coastguard Worker enum agx_format F = I->format;
945*61046927SAndroid Build Coastguard Worker pack_assert(I, F < 0x10);
946*61046927SAndroid Build Coastguard Worker
947*61046927SAndroid Build Coastguard Worker unsigned Tt = 0;
948*61046927SAndroid Build Coastguard Worker pack_assert(I, Tt < 0x4);
949*61046927SAndroid Build Coastguard Worker
950*61046927SAndroid Build Coastguard Worker unsigned U;
951*61046927SAndroid Build Coastguard Worker unsigned T = agx_pack_texture(I, I->src[0], I->src[1], &U, &Tt);
952*61046927SAndroid Build Coastguard Worker pack_assert(I, T < 0x100);
953*61046927SAndroid Build Coastguard Worker pack_assert(I, U < (1 << 5));
954*61046927SAndroid Build Coastguard Worker
955*61046927SAndroid Build Coastguard Worker bool Cs = false;
956*61046927SAndroid Build Coastguard Worker bool Ct = I->src[3].discard;
957*61046927SAndroid Build Coastguard Worker unsigned C = I->src[3].value;
958*61046927SAndroid Build Coastguard Worker
959*61046927SAndroid Build Coastguard Worker agx_index offset = I->src[2];
960*61046927SAndroid Build Coastguard Worker pack_assert(I, offset.size == AGX_SIZE_32);
961*61046927SAndroid Build Coastguard Worker assert_register_is_aligned(I, offset);
962*61046927SAndroid Build Coastguard Worker unsigned R = offset.value;
963*61046927SAndroid Build Coastguard Worker
964*61046927SAndroid Build Coastguard Worker bool unk1 = true;
965*61046927SAndroid Build Coastguard Worker
966*61046927SAndroid Build Coastguard Worker /* This bit has weird behaviour with the interaction of the texture state
967*61046927SAndroid Build Coastguard Worker * index and the tilebuffer offset. Probably best not to use it for now.
968*61046927SAndroid Build Coastguard Worker */
969*61046927SAndroid Build Coastguard Worker unsigned unk3 = 1;
970*61046927SAndroid Build Coastguard Worker
971*61046927SAndroid Build Coastguard Worker uint32_t word0 = agx_opcodes_info[I->op].encoding.exact |
972*61046927SAndroid Build Coastguard Worker (1 << 15) /* we always set length bit for now */ |
973*61046927SAndroid Build Coastguard Worker ((F & 1) << 8) | ((R & BITFIELD_MASK(6)) << 9) |
974*61046927SAndroid Build Coastguard Worker ((C & BITFIELD_MASK(6)) << 16) | (Ct ? (1 << 22) : 0) |
975*61046927SAndroid Build Coastguard Worker (I->explicit_coords ? (1 << 23) : 0) |
976*61046927SAndroid Build Coastguard Worker (unk1 ? (1u << 31) : 0);
977*61046927SAndroid Build Coastguard Worker
978*61046927SAndroid Build Coastguard Worker uint32_t word1 = (T & BITFIELD_MASK(6)) | (Tt << 6) |
979*61046927SAndroid Build Coastguard Worker ((I->dim & BITFIELD_MASK(3)) << 8) | (9 << 11) |
980*61046927SAndroid Build Coastguard Worker (Cs ? (1 << 15) : 0) | (((uint64_t)U) << 16) |
981*61046927SAndroid Build Coastguard Worker ((I->dim & BITFIELD_BIT(3)) ? (1u << 23) : 0) |
982*61046927SAndroid Build Coastguard Worker ((R >> 6) << 24) | ((C >> 6) << 26);
983*61046927SAndroid Build Coastguard Worker
984*61046927SAndroid Build Coastguard Worker uint32_t word2 = (F >> 1) | (unk3 ? (1 << 3) : 0) | ((T >> 6) << 14);
985*61046927SAndroid Build Coastguard Worker
986*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, 4), &word0, 4);
987*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, 4), &word1, 4);
988*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, 2), &word2, 2);
989*61046927SAndroid Build Coastguard Worker break;
990*61046927SAndroid Build Coastguard Worker }
991*61046927SAndroid Build Coastguard Worker
992*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_ZS_EMIT: {
993*61046927SAndroid Build Coastguard Worker agx_index S = I->src[0];
994*61046927SAndroid Build Coastguard Worker if (S.type == AGX_INDEX_IMMEDIATE)
995*61046927SAndroid Build Coastguard Worker pack_assert(I, S.value < BITFIELD_BIT(8));
996*61046927SAndroid Build Coastguard Worker else
997*61046927SAndroid Build Coastguard Worker assert_register_is_aligned(I, S);
998*61046927SAndroid Build Coastguard Worker
999*61046927SAndroid Build Coastguard Worker agx_index T = I->src[1];
1000*61046927SAndroid Build Coastguard Worker assert_register_is_aligned(I, T);
1001*61046927SAndroid Build Coastguard Worker
1002*61046927SAndroid Build Coastguard Worker pack_assert(I, I->zs >= 1 && I->zs <= 3);
1003*61046927SAndroid Build Coastguard Worker
1004*61046927SAndroid Build Coastguard Worker uint32_t word0 = agx_opcodes_info[I->op].encoding.exact |
1005*61046927SAndroid Build Coastguard Worker ((S.type == AGX_INDEX_IMMEDIATE) ? (1 << 8) : 0) |
1006*61046927SAndroid Build Coastguard Worker ((S.value & BITFIELD_MASK(6)) << 9) |
1007*61046927SAndroid Build Coastguard Worker ((T.value & BITFIELD_MASK(6)) << 16) |
1008*61046927SAndroid Build Coastguard Worker ((T.value >> 6) << 26) | ((S.value >> 6) << 24) |
1009*61046927SAndroid Build Coastguard Worker (I->zs << 29);
1010*61046927SAndroid Build Coastguard Worker
1011*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, 4), &word0, 4);
1012*61046927SAndroid Build Coastguard Worker break;
1013*61046927SAndroid Build Coastguard Worker }
1014*61046927SAndroid Build Coastguard Worker
1015*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_JMP_EXEC_ANY:
1016*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_JMP_EXEC_NONE:
1017*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_JMP_EXEC_NONE_AFTER: {
1018*61046927SAndroid Build Coastguard Worker /* We don't implement indirect branches */
1019*61046927SAndroid Build Coastguard Worker pack_assert(I, I->target != NULL);
1020*61046927SAndroid Build Coastguard Worker
1021*61046927SAndroid Build Coastguard Worker /* We'll fix the offset later. */
1022*61046927SAndroid Build Coastguard Worker struct agx_branch_fixup fixup = {
1023*61046927SAndroid Build Coastguard Worker .block = I->target,
1024*61046927SAndroid Build Coastguard Worker .offset = emission->size,
1025*61046927SAndroid Build Coastguard Worker .skip_to_end = I->op == AGX_OPCODE_JMP_EXEC_NONE_AFTER,
1026*61046927SAndroid Build Coastguard Worker };
1027*61046927SAndroid Build Coastguard Worker
1028*61046927SAndroid Build Coastguard Worker util_dynarray_append(fixups, struct agx_branch_fixup, fixup);
1029*61046927SAndroid Build Coastguard Worker
1030*61046927SAndroid Build Coastguard Worker /* The rest of the instruction is fixed */
1031*61046927SAndroid Build Coastguard Worker struct agx_opcode_info info = agx_opcodes_info[I->op];
1032*61046927SAndroid Build Coastguard Worker uint64_t raw = info.encoding.exact;
1033*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, 6), &raw, 6);
1034*61046927SAndroid Build Coastguard Worker break;
1035*61046927SAndroid Build Coastguard Worker }
1036*61046927SAndroid Build Coastguard Worker
1037*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_DOORBELL: {
1038*61046927SAndroid Build Coastguard Worker pack_assert(I, I->imm < BITFIELD_MASK(8));
1039*61046927SAndroid Build Coastguard Worker struct agx_opcode_info info = agx_opcodes_info[I->op];
1040*61046927SAndroid Build Coastguard Worker uint64_t raw = info.encoding.exact | (I->imm << 40);
1041*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, 6), &raw, 6);
1042*61046927SAndroid Build Coastguard Worker break;
1043*61046927SAndroid Build Coastguard Worker }
1044*61046927SAndroid Build Coastguard Worker
1045*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_STACK_UNMAP:
1046*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_STACK_MAP: {
1047*61046927SAndroid Build Coastguard Worker agx_index value = I->op == AGX_OPCODE_STACK_MAP ? I->src[0] : I->dest[0];
1048*61046927SAndroid Build Coastguard Worker
1049*61046927SAndroid Build Coastguard Worker pack_assert(I, value.type == AGX_INDEX_REGISTER);
1050*61046927SAndroid Build Coastguard Worker pack_assert(I, value.size == AGX_SIZE_32);
1051*61046927SAndroid Build Coastguard Worker pack_assert(I, I->imm < BITFIELD_MASK(16));
1052*61046927SAndroid Build Coastguard Worker
1053*61046927SAndroid Build Coastguard Worker unsigned q1 = 0; // XXX
1054*61046927SAndroid Build Coastguard Worker unsigned q2 = 0; // XXX
1055*61046927SAndroid Build Coastguard Worker unsigned q3 = 0; // XXX
1056*61046927SAndroid Build Coastguard Worker unsigned q4 = 16; // XXX
1057*61046927SAndroid Build Coastguard Worker unsigned q5 = 16; // XXX
1058*61046927SAndroid Build Coastguard Worker
1059*61046927SAndroid Build Coastguard Worker struct agx_opcode_info info = agx_opcodes_info[I->op];
1060*61046927SAndroid Build Coastguard Worker uint64_t raw =
1061*61046927SAndroid Build Coastguard Worker info.encoding.exact | (q1 << 8) | ((value.value & 0x3F) << 10) |
1062*61046927SAndroid Build Coastguard Worker ((I->imm & 0xF) << 20) | (1UL << 24) | // XXX
1063*61046927SAndroid Build Coastguard Worker (1UL << 26) | // XXX
1064*61046927SAndroid Build Coastguard Worker (q2 << 30) | ((uint64_t)((I->imm >> 4) & 0xF) << 32) |
1065*61046927SAndroid Build Coastguard Worker ((uint64_t)q3 << 37) | ((uint64_t)(value.value >> 6) << 40) |
1066*61046927SAndroid Build Coastguard Worker ((uint64_t)q4 << 42) | (1UL << 47) | // XXX
1067*61046927SAndroid Build Coastguard Worker ((uint64_t)q5 << 48) | ((uint64_t)(I->imm >> 8) << 56);
1068*61046927SAndroid Build Coastguard Worker
1069*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, 8), &raw, 8);
1070*61046927SAndroid Build Coastguard Worker break;
1071*61046927SAndroid Build Coastguard Worker }
1072*61046927SAndroid Build Coastguard Worker
1073*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_STACK_LOAD:
1074*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_STACK_STORE: {
1075*61046927SAndroid Build Coastguard Worker enum agx_format format = I->format;
1076*61046927SAndroid Build Coastguard Worker unsigned mask = I->mask;
1077*61046927SAndroid Build Coastguard Worker
1078*61046927SAndroid Build Coastguard Worker bool is_load = I->op == AGX_OPCODE_STACK_LOAD;
1079*61046927SAndroid Build Coastguard Worker bool L = true; /* TODO: when would you want short? */
1080*61046927SAndroid Build Coastguard Worker
1081*61046927SAndroid Build Coastguard Worker pack_assert(I, mask != 0);
1082*61046927SAndroid Build Coastguard Worker pack_assert(I, format <= 0x10);
1083*61046927SAndroid Build Coastguard Worker
1084*61046927SAndroid Build Coastguard Worker bool Rt, Ot;
1085*61046927SAndroid Build Coastguard Worker unsigned R =
1086*61046927SAndroid Build Coastguard Worker agx_pack_memory_reg(I, is_load ? I->dest[0] : I->src[0], &Rt);
1087*61046927SAndroid Build Coastguard Worker unsigned O =
1088*61046927SAndroid Build Coastguard Worker agx_pack_memory_index(I, is_load ? I->src[0] : I->src[1], &Ot);
1089*61046927SAndroid Build Coastguard Worker
1090*61046927SAndroid Build Coastguard Worker unsigned i1 = 1; // XXX
1091*61046927SAndroid Build Coastguard Worker unsigned i2 = 0; // XXX
1092*61046927SAndroid Build Coastguard Worker unsigned i5 = 4; // XXX
1093*61046927SAndroid Build Coastguard Worker
1094*61046927SAndroid Build Coastguard Worker uint64_t raw =
1095*61046927SAndroid Build Coastguard Worker agx_opcodes_info[I->op].encoding.exact |
1096*61046927SAndroid Build Coastguard Worker ((format & BITFIELD_MASK(2)) << 8) | ((R & BITFIELD_MASK(6)) << 10) |
1097*61046927SAndroid Build Coastguard Worker ((O & BITFIELD_MASK(4)) << 20) | (Ot ? (1 << 24) : 0) |
1098*61046927SAndroid Build Coastguard Worker ((uint64_t)i1 << 26) | ((uint64_t)I->scoreboard << 30) |
1099*61046927SAndroid Build Coastguard Worker (((uint64_t)((O >> 4) & BITFIELD_MASK(4))) << 32) |
1100*61046927SAndroid Build Coastguard Worker ((uint64_t)i2 << 36) |
1101*61046927SAndroid Build Coastguard Worker (((uint64_t)((R >> 6) & BITFIELD_MASK(2))) << 40) |
1102*61046927SAndroid Build Coastguard Worker ((uint64_t)i5 << 44) | (L ? (1UL << 47) : 0) |
1103*61046927SAndroid Build Coastguard Worker (((uint64_t)(format >> 2)) << 50) | (((uint64_t)Rt) << 49) |
1104*61046927SAndroid Build Coastguard Worker (((uint64_t)mask) << 52) | (((uint64_t)(O >> 8)) << 56);
1105*61046927SAndroid Build Coastguard Worker
1106*61046927SAndroid Build Coastguard Worker unsigned size = L ? 8 : 6;
1107*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, size), &raw, size);
1108*61046927SAndroid Build Coastguard Worker break;
1109*61046927SAndroid Build Coastguard Worker }
1110*61046927SAndroid Build Coastguard Worker case AGX_OPCODE_STACK_ADJUST: {
1111*61046927SAndroid Build Coastguard Worker struct agx_opcode_info info = agx_opcodes_info[I->op];
1112*61046927SAndroid Build Coastguard Worker
1113*61046927SAndroid Build Coastguard Worker unsigned i0 = 0; // XXX
1114*61046927SAndroid Build Coastguard Worker unsigned i1 = 1; // XXX
1115*61046927SAndroid Build Coastguard Worker unsigned i2 = 2; // XXX
1116*61046927SAndroid Build Coastguard Worker unsigned i3 = 0; // XXX
1117*61046927SAndroid Build Coastguard Worker unsigned i4 = 0; // XXX
1118*61046927SAndroid Build Coastguard Worker
1119*61046927SAndroid Build Coastguard Worker uint64_t raw =
1120*61046927SAndroid Build Coastguard Worker info.encoding.exact | ((uint64_t)i0 << 8) | ((uint64_t)i1 << 26) |
1121*61046927SAndroid Build Coastguard Worker ((uint64_t)i2 << 36) | ((uint64_t)i3 << 44) | ((uint64_t)i4 << 50) |
1122*61046927SAndroid Build Coastguard Worker ((I->stack_size & 0xF) << 20) |
1123*61046927SAndroid Build Coastguard Worker ((uint64_t)((I->stack_size >> 4) & 0xF) << 32) | (1UL << 47) | // XXX
1124*61046927SAndroid Build Coastguard Worker ((uint64_t)(I->stack_size >> 8) << 56);
1125*61046927SAndroid Build Coastguard Worker
1126*61046927SAndroid Build Coastguard Worker memcpy(util_dynarray_grow_bytes(emission, 1, 8), &raw, 8);
1127*61046927SAndroid Build Coastguard Worker break;
1128*61046927SAndroid Build Coastguard Worker }
1129*61046927SAndroid Build Coastguard Worker
1130*61046927SAndroid Build Coastguard Worker default:
1131*61046927SAndroid Build Coastguard Worker agx_pack_alu(emission, I);
1132*61046927SAndroid Build Coastguard Worker return;
1133*61046927SAndroid Build Coastguard Worker }
1134*61046927SAndroid Build Coastguard Worker }
1135*61046927SAndroid Build Coastguard Worker
1136*61046927SAndroid Build Coastguard Worker /* Relative branches may be emitted before their targets, so we patch the
1137*61046927SAndroid Build Coastguard Worker * binary to fix up the branch offsets after the main emit */
1138*61046927SAndroid Build Coastguard Worker
1139*61046927SAndroid Build Coastguard Worker static void
agx_fixup_branch(struct util_dynarray * emission,struct agx_branch_fixup fix)1140*61046927SAndroid Build Coastguard Worker agx_fixup_branch(struct util_dynarray *emission, struct agx_branch_fixup fix)
1141*61046927SAndroid Build Coastguard Worker {
1142*61046927SAndroid Build Coastguard Worker /* Branch offset is 2 bytes into the jump instruction */
1143*61046927SAndroid Build Coastguard Worker uint8_t *location = ((uint8_t *)emission->data) + fix.offset + 2;
1144*61046927SAndroid Build Coastguard Worker
1145*61046927SAndroid Build Coastguard Worker off_t target = fix.skip_to_end ? fix.block->last_offset : fix.block->offset;
1146*61046927SAndroid Build Coastguard Worker
1147*61046927SAndroid Build Coastguard Worker /* Offsets are relative to the jump instruction */
1148*61046927SAndroid Build Coastguard Worker int32_t patch = (int32_t)target - (int32_t)fix.offset;
1149*61046927SAndroid Build Coastguard Worker
1150*61046927SAndroid Build Coastguard Worker /* Patch the binary */
1151*61046927SAndroid Build Coastguard Worker memcpy(location, &patch, sizeof(patch));
1152*61046927SAndroid Build Coastguard Worker }
1153*61046927SAndroid Build Coastguard Worker
1154*61046927SAndroid Build Coastguard Worker void
agx_pack_binary(agx_context * ctx,struct util_dynarray * emission)1155*61046927SAndroid Build Coastguard Worker agx_pack_binary(agx_context *ctx, struct util_dynarray *emission)
1156*61046927SAndroid Build Coastguard Worker {
1157*61046927SAndroid Build Coastguard Worker struct util_dynarray fixups;
1158*61046927SAndroid Build Coastguard Worker util_dynarray_init(&fixups, ctx);
1159*61046927SAndroid Build Coastguard Worker
1160*61046927SAndroid Build Coastguard Worker agx_foreach_block(ctx, block) {
1161*61046927SAndroid Build Coastguard Worker /* Relative to the start of the binary, the block begins at the current
1162*61046927SAndroid Build Coastguard Worker * number of bytes emitted */
1163*61046927SAndroid Build Coastguard Worker block->offset = emission->size;
1164*61046927SAndroid Build Coastguard Worker
1165*61046927SAndroid Build Coastguard Worker agx_foreach_instr_in_block(block, ins) {
1166*61046927SAndroid Build Coastguard Worker block->last_offset = emission->size;
1167*61046927SAndroid Build Coastguard Worker agx_pack_instr(emission, &fixups, ins,
1168*61046927SAndroid Build Coastguard Worker ctx->key->dev.needs_g13x_coherency);
1169*61046927SAndroid Build Coastguard Worker }
1170*61046927SAndroid Build Coastguard Worker }
1171*61046927SAndroid Build Coastguard Worker
1172*61046927SAndroid Build Coastguard Worker util_dynarray_foreach(&fixups, struct agx_branch_fixup, fixup)
1173*61046927SAndroid Build Coastguard Worker agx_fixup_branch(emission, *fixup);
1174*61046927SAndroid Build Coastguard Worker
1175*61046927SAndroid Build Coastguard Worker util_dynarray_fini(&fixups);
1176*61046927SAndroid Build Coastguard Worker
1177*61046927SAndroid Build Coastguard Worker /* Dougall calls the instruction in this footer "trap". Match the blob. */
1178*61046927SAndroid Build Coastguard Worker if (!ctx->key->no_stop || ctx->is_preamble) {
1179*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < 8; ++i) {
1180*61046927SAndroid Build Coastguard Worker uint16_t trap = agx_opcodes_info[AGX_OPCODE_TRAP].encoding.exact;
1181*61046927SAndroid Build Coastguard Worker util_dynarray_append(emission, uint16_t, trap);
1182*61046927SAndroid Build Coastguard Worker }
1183*61046927SAndroid Build Coastguard Worker }
1184*61046927SAndroid Build Coastguard Worker }
1185