gallium: add cap for MAX_VERTEX_ATTRIB_STRIDE
[mesa.git] / src / gallium / drivers / vc4 / vc4_qpu.c
1 /*
2 * Copyright © 2014 Broadcom
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
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include <stdbool.h>
25 #include "vc4_qpu.h"
26
27 static uint64_t
28 set_src_raddr(uint64_t inst, struct qpu_reg src)
29 {
30 if (src.mux == QPU_MUX_A) {
31 /* These asserts could be better, checking to be sure we're
32 * not overwriting an actual use of a raddr of 0.
33 */
34 assert(QPU_GET_FIELD(inst, QPU_RADDR_A) == 0 ||
35 QPU_GET_FIELD(inst, QPU_RADDR_A) == src.addr);
36 return inst | QPU_SET_FIELD(src.addr, QPU_RADDR_A);
37 }
38
39 if (src.mux == QPU_MUX_B) {
40 assert(QPU_GET_FIELD(inst, QPU_RADDR_B) == 0 ||
41 QPU_GET_FIELD(inst, QPU_RADDR_B) == src.addr);
42 return inst | QPU_SET_FIELD(src.addr, QPU_RADDR_B);
43 }
44
45 return inst;
46 }
47
48 uint64_t
49 qpu_NOP()
50 {
51 uint64_t inst = 0;
52
53 inst |= QPU_SET_FIELD(QPU_A_NOP, QPU_OP_ADD);
54 inst |= QPU_SET_FIELD(QPU_M_NOP, QPU_OP_MUL);
55
56 /* Note: These field values are actually non-zero */
57 inst |= QPU_SET_FIELD(QPU_W_NOP, QPU_WADDR_ADD);
58 inst |= QPU_SET_FIELD(QPU_W_NOP, QPU_WADDR_MUL);
59 inst |= QPU_SET_FIELD(QPU_SIG_NONE, QPU_SIG);
60
61 return inst;
62 }
63
64 static uint64_t
65 qpu_a_dst(struct qpu_reg dst)
66 {
67 uint64_t inst = 0;
68
69 if (dst.mux <= QPU_MUX_R5) {
70 /* Translate the mux to the ACCn values. */
71 inst |= QPU_SET_FIELD(32 + dst.mux, QPU_WADDR_ADD);
72 } else {
73 inst |= QPU_SET_FIELD(dst.addr, QPU_WADDR_ADD);
74 if (dst.mux == QPU_MUX_B)
75 inst |= QPU_WS;
76 }
77
78 return inst;
79 }
80
81 static uint64_t
82 qpu_m_dst(struct qpu_reg dst)
83 {
84 uint64_t inst = 0;
85
86 if (dst.mux <= QPU_MUX_R5) {
87 /* Translate the mux to the ACCn values. */
88 inst |= QPU_SET_FIELD(32 + dst.mux, QPU_WADDR_MUL);
89 } else {
90 inst |= QPU_SET_FIELD(dst.addr, QPU_WADDR_MUL);
91 if (dst.mux == QPU_MUX_A)
92 inst |= QPU_WS;
93 }
94
95 return inst;
96 }
97
98 uint64_t
99 qpu_a_MOV(struct qpu_reg dst, struct qpu_reg src)
100 {
101 uint64_t inst = 0;
102
103 inst |= QPU_SET_FIELD(QPU_A_OR, QPU_OP_ADD);
104 inst |= qpu_a_dst(dst);
105 inst |= QPU_SET_FIELD(QPU_COND_ALWAYS, QPU_COND_ADD);
106 inst |= QPU_SET_FIELD(src.mux, QPU_ADD_A);
107 inst |= QPU_SET_FIELD(src.mux, QPU_ADD_B);
108 inst |= set_src_raddr(inst, src);
109 inst |= QPU_SET_FIELD(QPU_SIG_NONE, QPU_SIG);
110 inst |= QPU_SET_FIELD(QPU_W_NOP, QPU_WADDR_MUL);
111
112 return inst;
113 }
114
115 uint64_t
116 qpu_m_MOV(struct qpu_reg dst, struct qpu_reg src)
117 {
118 uint64_t inst = 0;
119
120 inst |= QPU_SET_FIELD(QPU_M_V8MIN, QPU_OP_MUL);
121 inst |= qpu_m_dst(dst);
122 inst |= QPU_SET_FIELD(QPU_COND_ALWAYS, QPU_COND_MUL);
123 inst |= QPU_SET_FIELD(src.mux, QPU_MUL_A);
124 inst |= QPU_SET_FIELD(src.mux, QPU_MUL_B);
125 inst |= set_src_raddr(inst, src);
126 inst |= QPU_SET_FIELD(QPU_SIG_NONE, QPU_SIG);
127 inst |= QPU_SET_FIELD(QPU_W_NOP, QPU_WADDR_ADD);
128
129 return inst;
130 }
131
132 uint64_t
133 qpu_load_imm_ui(struct qpu_reg dst, uint32_t val)
134 {
135 uint64_t inst = 0;
136
137 inst |= qpu_a_dst(dst);
138 inst |= QPU_SET_FIELD(QPU_W_NOP, QPU_WADDR_MUL);
139 inst |= QPU_SET_FIELD(QPU_COND_ALWAYS, QPU_COND_ADD);
140 inst |= QPU_SET_FIELD(QPU_COND_ALWAYS, QPU_COND_MUL);
141 inst |= QPU_SET_FIELD(QPU_SIG_LOAD_IMM, QPU_SIG);
142 inst |= val;
143
144 return inst;
145 }
146
147 uint64_t
148 qpu_a_alu2(enum qpu_op_add op,
149 struct qpu_reg dst, struct qpu_reg src0, struct qpu_reg src1)
150 {
151 uint64_t inst = 0;
152
153 inst |= QPU_SET_FIELD(op, QPU_OP_ADD);
154 inst |= qpu_a_dst(dst);
155 inst |= QPU_SET_FIELD(QPU_COND_ALWAYS, QPU_COND_ADD);
156 inst |= QPU_SET_FIELD(src0.mux, QPU_ADD_A);
157 inst |= set_src_raddr(inst, src0);
158 inst |= QPU_SET_FIELD(src1.mux, QPU_ADD_B);
159 inst |= set_src_raddr(inst, src1);
160 inst |= QPU_SET_FIELD(QPU_SIG_NONE, QPU_SIG);
161 inst |= QPU_SET_FIELD(QPU_W_NOP, QPU_WADDR_MUL);
162
163 return inst;
164 }
165
166 uint64_t
167 qpu_m_alu2(enum qpu_op_mul op,
168 struct qpu_reg dst, struct qpu_reg src0, struct qpu_reg src1)
169 {
170 uint64_t inst = 0;
171
172 set_src_raddr(inst, src0);
173 set_src_raddr(inst, src1);
174
175 inst |= QPU_SET_FIELD(op, QPU_OP_MUL);
176 inst |= qpu_m_dst(dst);
177 inst |= QPU_SET_FIELD(QPU_COND_ALWAYS, QPU_COND_MUL);
178 inst |= QPU_SET_FIELD(src0.mux, QPU_MUL_A);
179 inst |= set_src_raddr(inst, src0);
180 inst |= QPU_SET_FIELD(src1.mux, QPU_MUL_B);
181 inst |= set_src_raddr(inst, src1);
182 inst |= QPU_SET_FIELD(QPU_SIG_NONE, QPU_SIG);
183 inst |= QPU_SET_FIELD(QPU_W_NOP, QPU_WADDR_ADD);
184
185 return inst;
186 }
187
188 uint64_t
189 qpu_inst(uint64_t add, uint64_t mul)
190 {
191 uint64_t merge = ((add & ~QPU_WADDR_MUL_MASK) |
192 (mul & ~QPU_WADDR_ADD_MASK));
193
194 /* If either one has no signal field, then use the other's signal field.
195 * (since QPU_SIG_NONE != 0).
196 */
197 if (QPU_GET_FIELD(add, QPU_SIG) == QPU_SIG_NONE)
198 merge = (merge & ~QPU_SIG_MASK) | (mul & QPU_SIG_MASK);
199 else if (QPU_GET_FIELD(mul, QPU_SIG) == QPU_SIG_NONE)
200 merge = (merge & ~QPU_SIG_MASK) | (add & QPU_SIG_MASK);
201 else {
202 assert(QPU_GET_FIELD(add, QPU_SIG) ==
203 QPU_GET_FIELD(mul, QPU_SIG));
204 }
205
206 return merge;
207 }
208
209 uint64_t
210 qpu_set_sig(uint64_t inst, uint32_t sig)
211 {
212 assert(QPU_GET_FIELD(inst, QPU_SIG) == QPU_SIG_NONE);
213 return (inst & ~QPU_SIG_MASK) | QPU_SET_FIELD(sig, QPU_SIG);
214 }
215
216 uint64_t
217 qpu_set_cond_add(uint64_t inst, uint32_t sig)
218 {
219 assert(QPU_GET_FIELD(inst, QPU_COND_ADD) == QPU_COND_ALWAYS);
220 return (inst & ~QPU_COND_ADD_MASK) | QPU_SET_FIELD(sig, QPU_COND_ADD);
221 }
222
223 uint64_t
224 qpu_set_cond_mul(uint64_t inst, uint32_t sig)
225 {
226 assert(QPU_GET_FIELD(inst, QPU_COND_MUL) == QPU_COND_ALWAYS);
227 return (inst & ~QPU_COND_MUL_MASK) | QPU_SET_FIELD(sig, QPU_COND_MUL);
228 }
229