1 /*
2  * Copyright (c) 2017 Lima Project
3  * Copyright (c) 2013 Ben Brewer (ben.brewer@codethink.co.uk)
4  * Copyright (c) 2013 Connor Abbott (connor@abbott.cx)
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sub license,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial portions
15  * of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  *
25  */
26 
27 #ifndef LIMA_IR_PP_CODEGEN_H
28 #define LIMA_IR_PP_CODEGEN_H
29 
30 #include <stdint.h>
31 #include <stdbool.h>
32 
33 /* Control */
34 
35 typedef union __attribute__((__packed__)) {
36    struct __attribute__((__packed__)) {
37       unsigned count      :  5;
38       bool     stop       :  1;
39       bool     sync       :  1;
40       unsigned fields     : 12;
41       unsigned next_count :  6;
42       bool     prefetch   :  1;
43       unsigned unknown    :  6;
44    };
45    uint32_t mask;
46 } ppir_codegen_ctrl;
47 
48 typedef enum {
49    ppir_codegen_field_shift_varying      =  0,
50    ppir_codegen_field_shift_sampler      =  1,
51    ppir_codegen_field_shift_uniform      =  2,
52    ppir_codegen_field_shift_vec4_mul     =  3,
53    ppir_codegen_field_shift_float_mul    =  4,
54    ppir_codegen_field_shift_vec4_acc     =  5,
55    ppir_codegen_field_shift_float_acc    =  6,
56    ppir_codegen_field_shift_combine      =  7,
57    ppir_codegen_field_shift_temp_write   =  8,
58    ppir_codegen_field_shift_branch       =  9,
59    ppir_codegen_field_shift_vec4_const_0 = 10,
60    ppir_codegen_field_shift_vec4_const_1 = 11,
61    ppir_codegen_field_shift_count        = 12,
62 } ppir_codegen_field_shift;
63 
64 /* Data Inputs */
65 
66 typedef enum {
67    ppir_codegen_vec4_reg_frag_color =  0,
68    ppir_codegen_vec4_reg_constant0  = 12,
69    ppir_codegen_vec4_reg_constant1  = 13,
70    ppir_codegen_vec4_reg_texture    = 14,
71    ppir_codegen_vec4_reg_uniform    = 15,
72    ppir_codegen_vec4_reg_discard    = 15,
73 } ppir_codegen_vec4_reg;
74 
75 typedef union __attribute__((__packed__)) {
76    struct __attribute__((__packed__)) {
77       unsigned              perspective   :  2;
78       unsigned              source_type   :  2;
79       unsigned              unknown_0     :  1; /* = 0 */
80       unsigned              alignment     :  2;
81       unsigned              unknown_1     :  3; /* = 00 0 */
82       unsigned              offset_vector :  4;
83       unsigned              unknown_2     :  2; /* = 00 */
84       unsigned              offset_scalar :  2;
85       unsigned              index         :  6;
86       ppir_codegen_vec4_reg dest          :  4;
87       unsigned              mask          :  4;
88       unsigned              unknown_3     :  2; /* = 00 */
89    } imm;
90    struct __attribute__((__packed__)) {
91       unsigned              perspective :  2;
92       unsigned              source_type :  2; /* = 01 */
93       unsigned              unknown_0   :  2; /* = 00 */
94       bool                  normalize   :  1;
95       unsigned              unknown_1   :  3;
96       ppir_codegen_vec4_reg source      :  4;
97       bool                  negate      :  1;
98       bool                  absolute    :  1;
99       unsigned              swizzle     :  8;
100       ppir_codegen_vec4_reg dest        :  4;
101       unsigned              mask        :  4;
102       unsigned              unknown_2   :  2; /* = 00 */
103    } reg;
104 } ppir_codegen_field_varying;
105 
106 typedef enum {
107    ppir_codegen_sampler_type_2d   = 0x00,
108    ppir_codegen_sampler_type_cube = 0x1F,
109 } ppir_codegen_sampler_type;
110 
111 typedef struct __attribute__((__packed__)) {
112    unsigned                  lod_bias     :  6;
113    unsigned                  index_offset :  6;
114    unsigned                  unknown_0    :  5; /* = 00000 */
115    bool                      explicit_lod :  1;
116    bool                      lod_bias_en  :  1;
117    unsigned                  unknown_1    :  5; /* = 00000 */
118    ppir_codegen_sampler_type type         :  5;
119    bool                      offset_en    :  1;
120    unsigned                  index        : 12;
121    unsigned                  unknown_2    : 20; /* = 0011 1001 0000 0000 0001 */
122 } ppir_codegen_field_sampler;
123 
124 typedef enum {
125    ppir_codegen_uniform_src_uniform   = 0,
126    ppir_codegen_uniform_src_temporary = 3,
127 } ppir_codegen_uniform_src;
128 
129 typedef struct __attribute__((__packed__)) {
130    ppir_codegen_uniform_src source     :  2;
131    unsigned                 unknown_0  :  8; /* = 00 0000 00 */
132    unsigned                 alignment  :  2; /* 00: float, 01: vec2, 10: vec4 */
133    unsigned                 unknown_1  :  6; /* = 00 0000 */
134    unsigned                 offset_reg :  6;
135    bool                     offset_en  :  1;
136    unsigned                 index      : 16;
137 } ppir_codegen_field_uniform;
138 
139 /* Vector Pipe */
140 
141 typedef enum {
142    ppir_codegen_vec4_mul_op_not = 0x08, /* Logical Not */
143    ppir_codegen_vec4_mul_op_and = 0x09, /* Logical AND */
144    ppir_codegen_vec4_mul_op_or  = 0x0A, /* Logical OR */
145    ppir_codegen_vec4_mul_op_xor = 0x0B, /* Logical XOR */
146    ppir_codegen_vec4_mul_op_ne  = 0x0C, /* Not Equal */
147    ppir_codegen_vec4_mul_op_gt  = 0x0D, /* Great Than */
148    ppir_codegen_vec4_mul_op_ge  = 0x0E, /* Great than or Equal */
149    ppir_codegen_vec4_mul_op_eq  = 0x0F, /* Equal */
150    ppir_codegen_vec4_mul_op_min = 0x10, /* Minimum */
151    ppir_codegen_vec4_mul_op_max = 0x11, /* Maximum */
152    ppir_codegen_vec4_mul_op_mov = 0x1F, /* Passthrough, result = arg1 */
153 } ppir_codegen_vec4_mul_op;
154 
155 typedef enum {
156    ppir_codegen_outmod_none           = 0,
157    ppir_codegen_outmod_clamp_fraction = 1,
158    ppir_codegen_outmod_clamp_positive = 2,
159    ppir_codegen_outmod_round          = 3,
160 } ppir_codegen_outmod;
161 
162 typedef struct __attribute__((__packed__)) {
163    ppir_codegen_vec4_reg    arg0_source   : 4;
164    unsigned                 arg0_swizzle  : 8;
165    bool                     arg0_absolute : 1;
166    bool                     arg0_negate   : 1;
167    ppir_codegen_vec4_reg    arg1_source   : 4;
168    unsigned                 arg1_swizzle  : 8;
169    bool                     arg1_absolute : 1;
170    bool                     arg1_negate   : 1;
171    unsigned                 dest          : 4;
172    unsigned                 mask          : 4;
173    ppir_codegen_outmod      dest_modifier : 2;
174    ppir_codegen_vec4_mul_op op            : 5;
175 } ppir_codegen_field_vec4_mul;
176 
177 typedef enum {
178    ppir_codegen_vec4_acc_op_add   = 0x00,
179    ppir_codegen_vec4_acc_op_fract = 0x04, /* Fract? */
180    ppir_codegen_vec4_acc_op_ne    = 0x08, /* Not Equal */
181    ppir_codegen_vec4_acc_op_gt    = 0x09, /* Great-Than */
182    ppir_codegen_vec4_acc_op_ge    = 0x0A, /* Great-than or Equal */
183    ppir_codegen_vec4_acc_op_eq    = 0x0B, /* Equal */
184    ppir_codegen_vec4_acc_op_floor = 0x0C,
185    ppir_codegen_vec4_acc_op_ceil  = 0x0D,
186    ppir_codegen_vec4_acc_op_min   = 0x0E,
187    ppir_codegen_vec4_acc_op_max   = 0x0F,
188    ppir_codegen_vec4_acc_op_sum3  = 0x10, /* dest.xyzw = (arg0.x + arg0.y + arg0.z) */
189    ppir_codegen_vec4_acc_op_sum4  = 0x11, /* dest.xyzw = (arg0.x + arg0.y + arg0.z + arg0.w) */
190    ppir_codegen_vec4_acc_op_dFdx  = 0x14,
191    ppir_codegen_vec4_acc_op_dFdy  = 0x15,
192    ppir_codegen_vec4_acc_op_sel   = 0x17, /* result = (^fmul ? arg0 : arg1) */
193    ppir_codegen_vec4_acc_op_mov   = 0x1F, /* Passthrough, result = arg0 */
194 } ppir_codegen_vec4_acc_op;
195 
196 typedef struct __attribute__((__packed__)) {
197    ppir_codegen_vec4_reg    arg0_source   : 4;
198    unsigned                 arg0_swizzle  : 8;
199    bool                     arg0_absolute : 1;
200    bool                     arg0_negate   : 1;
201    ppir_codegen_vec4_reg    arg1_source   : 4;
202    unsigned                 arg1_swizzle  : 8;
203    bool                     arg1_absolute : 1;
204    bool                     arg1_negate   : 1;
205    unsigned                 dest          : 4;
206    unsigned                 mask          : 4;
207    ppir_codegen_outmod      dest_modifier : 2;
208    ppir_codegen_vec4_acc_op op            : 5;
209    bool                     mul_in        : 1; /* whether to get arg0 from multiply unit below */
210 } ppir_codegen_field_vec4_acc;
211 
212 /* Float (Scalar) Pipe */
213 
214 typedef enum {
215    ppir_codegen_float_mul_op_not = 0x08, /* Logical Not */
216    ppir_codegen_float_mul_op_and = 0x09, /* Logical AND */
217    ppir_codegen_float_mul_op_or  = 0x0A, /* Logical OR */
218    ppir_codegen_float_mul_op_xor = 0x0B, /* Logical XOR */
219    ppir_codegen_float_mul_op_ne  = 0x0C, /* Not Equal */
220    ppir_codegen_float_mul_op_gt  = 0x0D, /* Great Than */
221    ppir_codegen_float_mul_op_ge  = 0x0E, /* great than or Equal */
222    ppir_codegen_float_mul_op_eq  = 0x0F, /* Equal */
223    ppir_codegen_float_mul_op_min = 0x10, /* Minimum */
224    ppir_codegen_float_mul_op_max = 0x11, /* Maximum */
225    ppir_codegen_float_mul_op_mov = 0x1F, /* Passthrough, result = arg1 */
226 } ppir_codegen_float_mul_op;
227 
228 typedef struct __attribute__((__packed__)) {
229    unsigned                  arg0_source   : 6;
230    bool                      arg0_absolute : 1;
231    bool                      arg0_negate   : 1;
232    unsigned                  arg1_source   : 6;
233    bool                      arg1_absolute : 1;
234    bool                      arg1_negate   : 1;
235    unsigned                  dest          : 6;
236    bool                      output_en     : 1; /* Set to 0 when outputting directly to float_acc below. */
237    ppir_codegen_outmod       dest_modifier : 2;
238    ppir_codegen_float_mul_op op            : 5;
239 } ppir_codegen_field_float_mul;
240 
241 typedef enum {
242    ppir_codegen_float_acc_op_add   = 0x00,
243    ppir_codegen_float_acc_op_fract = 0x04,
244    ppir_codegen_float_acc_op_ne    = 0x08, /* Not Equal */
245    ppir_codegen_float_acc_op_gt    = 0x09, /* Great-Than */
246    ppir_codegen_float_acc_op_ge    = 0x0A, /* Great-than or Equal */
247    ppir_codegen_float_acc_op_eq    = 0x0B, /* Equal */
248    ppir_codegen_float_acc_op_floor = 0x0C,
249    ppir_codegen_float_acc_op_ceil  = 0x0D,
250    ppir_codegen_float_acc_op_min   = 0x0E,
251    ppir_codegen_float_acc_op_max   = 0x0F,
252    ppir_codegen_float_acc_op_dFdx  = 0x14,
253    ppir_codegen_float_acc_op_dFdy  = 0x15,
254    ppir_codegen_float_acc_op_sel   = 0x17, /* result = (^fmul ? arg0 : arg1) */
255    ppir_codegen_float_acc_op_mov   = 0x1F, /* Passthrough, result = arg1 */
256 } ppir_codegen_float_acc_op;
257 
258 typedef struct __attribute__((__packed__)) {
259    unsigned                  arg0_source   : 6;
260    bool                      arg0_absolute : 1;
261    bool                      arg0_negate   : 1;
262    unsigned                  arg1_source   : 6;
263    bool                      arg1_absolute : 1;
264    bool                      arg1_negate   : 1;
265    unsigned                  dest          : 6;
266    bool                      output_en     : 1; /* Always true */
267    ppir_codegen_outmod       dest_modifier : 2;
268    ppir_codegen_float_acc_op op            : 5;
269    bool                      mul_in        : 1; /* Get arg1 from float_mul above. */
270 } ppir_codegen_field_float_acc;
271 
272 /* Temporary Write / Framebuffer Read */
273 
274 typedef union __attribute__((__packed__)) {
275    struct __attribute__((__packed__)) {
276       unsigned dest       :  2; /* = 11 */
277       unsigned unknown_0  :  2; /* = 00 */
278       unsigned source     :  6;
279       unsigned alignment  :  2; /* 0: float, 1:vec2, 2: vec4 */
280       unsigned unknown_1  :  6; /* = 00 0000 */
281       unsigned offset_reg :  6;
282       bool     offset_en  :  1;
283       unsigned index      : 16;
284    } temp_write;
285    struct __attribute__((__packed__)) {
286       bool     source    :  1; /* 0 = fb_depth, 1 = fb_color */
287       unsigned unknown_0 :  5; /* = 00 111 */
288       unsigned dest      :  4;
289       unsigned unknown_1 : 31; /* = 0 0000 ... 10 */
290    } fb_read;
291 } ppir_codegen_field_temp_write;
292 
293 /* Result combiner */
294 
295 typedef enum {
296    ppir_codegen_combine_scalar_op_rcp   = 0, /* Reciprocal */
297    ppir_codegen_combine_scalar_op_mov   = 1, /* No Operation */
298    ppir_codegen_combine_scalar_op_sqrt  = 2, /* Square-Root */
299    ppir_codegen_combine_scalar_op_rsqrt = 3, /* Inverse Square-Root */
300    ppir_codegen_combine_scalar_op_exp2  = 4, /* Binary Exponent */
301    ppir_codegen_combine_scalar_op_log2  = 5, /* Binary Logarithm */
302    ppir_codegen_combine_scalar_op_sin   = 6, /* Sine   (Scaled LUT) */
303    ppir_codegen_combine_scalar_op_cos   = 7, /* Cosine (Scaled LUT) */
304    ppir_codegen_combine_scalar_op_atan  = 8, /* Arc Tangent Part 1 */
305    ppir_codegen_combine_scalar_op_atan2 = 9, /* Arc Tangent 2 Part 1 */
306 } ppir_codegen_combine_scalar_op;
307 
308 typedef union __attribute__((__packed__)) {
309    struct __attribute__((__packed__)) {
310       bool                           dest_vec      : 1;
311       bool                           arg1_en       : 1;
312       ppir_codegen_combine_scalar_op op            : 4;
313       bool                           arg1_absolute : 1;
314       bool                           arg1_negate   : 1;
315       unsigned                       arg1_src      : 6;
316       bool                           arg0_absolute : 1;
317       bool                           arg0_negate   : 1;
318       unsigned                       arg0_src      : 6;
319       ppir_codegen_outmod            dest_modifier : 2;
320       unsigned                       dest          : 6;
321    } scalar;
322    struct __attribute__((__packed__)) {
323       bool     dest_vec     : 1;
324       bool     arg1_en      : 1;
325       unsigned arg1_swizzle : 8;
326       unsigned arg1_source  : 4;
327       unsigned padding_0    : 8;
328       unsigned mask         : 4;
329       unsigned dest         : 4;
330    } vector;
331 } ppir_codegen_field_combine;
332 
333 /* Branch/Control Flow */
334 
335 #define PPIR_CODEGEN_DISCARD_WORD0 0x007F0003
336 #define PPIR_CODEGEN_DISCARD_WORD1 0x00000000
337 #define PPIR_CODEGEN_DISCARD_WORD2 0x000
338 
339 typedef union __attribute__((__packed__)) {
340    struct __attribute__((__packed__)) {
341       unsigned unknown_0   :  4; /* = 0000 */
342       unsigned arg1_source :  6;
343       unsigned arg0_source :  6;
344       bool     cond_gt     :  1;
345       bool     cond_eq     :  1;
346       bool     cond_lt     :  1;
347       unsigned unknown_1   : 22; /* = 0 0000 0000 0000 0000 0000 0 */
348       signed   target      : 27;
349       unsigned next_count  :  5;
350    } branch;
351    struct __attribute__((__packed__)) {
352       unsigned word0 : 32;
353       unsigned word1 : 32;
354       unsigned word2 : 9;
355    } discard;
356 } ppir_codegen_field_branch;
357 
358 void ppir_disassemble_instr(uint32_t *instr, unsigned offset, FILE *fp);
359 
360 #endif
361