1 /*
2 * Copyright (C) 2021 Collabora Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors (Collabora):
24 * Alyssa Rosenzweig <[email protected]>
25 */
26
27 #ifndef __VALHALL_H
28 #define __VALHALL_H
29
30 #include <stdint.h>
31 #include "bi_opcodes.h"
32 #include "valhall_enums.h"
33
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37
38 #define VA_NUM_GENERAL_SLOTS 3
39
40 extern const uint32_t valhall_immediates[32];
41
42 enum va_size {
43 VA_SIZE_8 = 0,
44 VA_SIZE_16 = 1,
45 VA_SIZE_32 = 2,
46 VA_SIZE_64 = 3,
47 };
48
49 enum va_unit {
50 /** Fused floating-point multiply-add */
51 VA_UNIT_FMA = 0,
52
53 /** Type conversion and basic arithmetic */
54 VA_UNIT_CVT = 1,
55
56 /** Special function unit */
57 VA_UNIT_SFU = 2,
58
59 /** Varying */
60 VA_UNIT_V = 3,
61
62 /** General load/store */
63 VA_UNIT_LS = 4,
64
65 /** Texture */
66 VA_UNIT_T = 5,
67
68 /** Fused varying and texture */
69 VA_UNIT_VT = 6,
70
71 /** Produces a message for a unit not otherwise specified */
72 VA_UNIT_NONE = 7
73 };
74
75 struct va_src_info {
76 bool absneg : 1;
77 bool swizzle : 1;
78 bool notted : 1;
79 bool lane : 1;
80 bool lanes : 1;
81 bool halfswizzle : 1;
82 bool widen : 1;
83 bool combine : 1;
84 enum va_size size : 2;
85 } __attribute__((packed));
86
87 struct va_opcode_info {
88 uint64_t exact;
89 struct va_src_info srcs[4];
90 uint8_t type_size : 8;
91 enum va_unit unit : 3;
92 unsigned nr_srcs : 3;
93 unsigned nr_staging_srcs : 2;
94 unsigned nr_staging_dests : 2;
95 bool has_dest : 1;
96 bool is_signed : 1;
97 bool clamp : 1;
98 bool saturate : 1;
99 bool rhadd : 1;
100 bool round_mode : 1;
101 bool condition : 1;
102 bool result_type : 1;
103 bool vecsize : 1;
104 bool register_format : 1;
105 bool slot : 1;
106 bool sr_count : 1;
107 bool sr_write_count : 1;
108 unsigned sr_control : 2;
109 };
110
111 extern const struct va_opcode_info valhall_opcodes[BI_NUM_OPCODES];
112
113 /* Bifrost specifies the source of bitwise operations as (A, B, shift), but
114 * Valhall specifies (A, shift, B). We follow Bifrost conventions in the
115 * compiler, so normalize.
116 *
117 * Bifrost specifies BLEND as staging + (coverage, blend descriptor), but
118 * Valhall specifies staging + (blend descriptor, coverage). Given we put
119 * staging sources first, this works out to the same swap as bitwise ops.
120 */
121
122 static inline bool
va_swap_12(enum bi_opcode op)123 va_swap_12(enum bi_opcode op)
124 {
125 switch (op) {
126 case BI_OPCODE_BLEND:
127 case BI_OPCODE_LSHIFT_AND_I32:
128 case BI_OPCODE_LSHIFT_AND_V2I16:
129 case BI_OPCODE_LSHIFT_AND_V4I8:
130 case BI_OPCODE_LSHIFT_OR_I32:
131 case BI_OPCODE_LSHIFT_OR_V2I16:
132 case BI_OPCODE_LSHIFT_OR_V4I8:
133 case BI_OPCODE_LSHIFT_XOR_I32:
134 case BI_OPCODE_LSHIFT_XOR_V2I16:
135 case BI_OPCODE_LSHIFT_XOR_V4I8:
136 case BI_OPCODE_RSHIFT_AND_I32:
137 case BI_OPCODE_RSHIFT_AND_V2I16:
138 case BI_OPCODE_RSHIFT_AND_V4I8:
139 case BI_OPCODE_RSHIFT_OR_I32:
140 case BI_OPCODE_RSHIFT_OR_V2I16:
141 case BI_OPCODE_RSHIFT_OR_V4I8:
142 case BI_OPCODE_RSHIFT_XOR_I32:
143 case BI_OPCODE_RSHIFT_XOR_V2I16:
144 case BI_OPCODE_RSHIFT_XOR_V4I8:
145 return true;
146 default:
147 return false;
148 }
149 }
150
151 static inline struct va_src_info
va_src_info(enum bi_opcode op,unsigned src)152 va_src_info(enum bi_opcode op, unsigned src)
153 {
154 unsigned idx = (va_swap_12(op) && (src == 1 || src == 2)) ? (3 - src) : src;
155 return valhall_opcodes[op].srcs[idx];
156 }
157
158 static inline bool
va_flow_is_wait_or_none(enum va_flow flow)159 va_flow_is_wait_or_none(enum va_flow flow)
160 {
161 return (flow <= VA_FLOW_WAIT);
162 }
163
164 static inline bool
va_is_valid_const_table(unsigned table)165 va_is_valid_const_table(unsigned table)
166 {
167 return (table >= 0 && table <= 11) || (table >= 60 && table <= 63);
168 }
169
170 static inline uint32_t
va_res_fold_table_idx(uint32_t table)171 va_res_fold_table_idx(uint32_t table)
172 {
173 switch (table) {
174 case 0 ... 11:
175 return table;
176 case 60 ... 63:
177 return table + 12 - 60;
178 default:
179 assert(!"Can't pack table");
180 return 0;
181 }
182 }
183
184 #ifdef __cplusplus
185 } /* extern C */
186 #endif
187
188 #endif
189