b8649f7b6285ce6fe5f6cb17f564620391230481
[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
111 return inst;
112 }
113
114 uint64_t
115 qpu_m_MOV(struct qpu_reg dst, struct qpu_reg src)
116 {
117 uint64_t inst = 0;
118
119 inst |= QPU_SET_FIELD(QPU_M_V8MIN, QPU_OP_MUL);
120 inst |= qpu_m_dst(dst);
121 inst |= QPU_SET_FIELD(QPU_COND_ALWAYS, QPU_COND_MUL);
122 inst |= QPU_SET_FIELD(src.mux, QPU_MUL_A);
123 inst |= QPU_SET_FIELD(src.mux, QPU_MUL_B);
124 inst |= set_src_raddr(inst, src);
125 inst |= QPU_SET_FIELD(QPU_SIG_NONE, QPU_SIG);
126
127 return inst;
128 }
129
130 uint64_t
131 qpu_load_imm_ui(struct qpu_reg dst, uint32_t val)
132 {
133 uint64_t inst = 0;
134
135 inst |= qpu_a_dst(dst);
136 inst |= qpu_m_dst(qpu_rb(QPU_W_NOP));
137 inst |= QPU_SET_FIELD(QPU_COND_ALWAYS, QPU_COND_ADD);
138 inst |= QPU_SET_FIELD(QPU_COND_ALWAYS, QPU_COND_MUL);
139 inst |= QPU_SET_FIELD(QPU_SIG_LOAD_IMM, QPU_SIG);
140 inst |= val;
141
142 return inst;
143 }
144
145 uint64_t
146 qpu_a_alu2(enum qpu_op_add op,
147 struct qpu_reg dst, struct qpu_reg src0, struct qpu_reg src1)
148 {
149 uint64_t inst = 0;
150
151 inst |= QPU_SET_FIELD(op, QPU_OP_ADD);
152 inst |= qpu_a_dst(dst);
153 inst |= QPU_SET_FIELD(QPU_COND_ALWAYS, QPU_COND_ADD);
154 inst |= QPU_SET_FIELD(src0.mux, QPU_ADD_A);
155 inst |= set_src_raddr(inst, src0);
156 inst |= QPU_SET_FIELD(src1.mux, QPU_ADD_B);
157 inst |= set_src_raddr(inst, src1);
158 inst |= QPU_SET_FIELD(QPU_SIG_NONE, QPU_SIG);
159
160 return inst;
161 }
162
163 uint64_t
164 qpu_m_alu2(enum qpu_op_mul op,
165 struct qpu_reg dst, struct qpu_reg src0, struct qpu_reg src1)
166 {
167 uint64_t inst = 0;
168
169 set_src_raddr(inst, src0);
170 set_src_raddr(inst, src1);
171
172 inst |= QPU_SET_FIELD(op, QPU_OP_MUL);
173 inst |= qpu_m_dst(dst);
174 inst |= QPU_SET_FIELD(QPU_COND_ALWAYS, QPU_COND_MUL);
175 inst |= QPU_SET_FIELD(src0.mux, QPU_MUL_A);
176 inst |= set_src_raddr(inst, src0);
177 inst |= QPU_SET_FIELD(src1.mux, QPU_MUL_B);
178 inst |= set_src_raddr(inst, src1);
179 inst |= QPU_SET_FIELD(QPU_SIG_NONE, QPU_SIG);
180
181 return inst;
182 }
183
184 uint64_t
185 qpu_inst(uint64_t add, uint64_t mul)
186 {
187 uint64_t merge = ((add & ~QPU_WADDR_MUL_MASK) |
188 (mul & ~QPU_WADDR_ADD_MASK));
189
190 /* If either one has no signal field, then use the other's signal field.
191 * (since QPU_SIG_NONE != 0).
192 */
193 if (QPU_GET_FIELD(add, QPU_SIG) == QPU_SIG_NONE)
194 merge = (merge & ~QPU_SIG_MASK) | (mul & QPU_SIG_MASK);
195 else if (QPU_GET_FIELD(mul, QPU_SIG) == QPU_SIG_NONE)
196 merge = (merge & ~QPU_SIG_MASK) | (add & QPU_SIG_MASK);
197 else {
198 assert(QPU_GET_FIELD(add, QPU_SIG) ==
199 QPU_GET_FIELD(mul, QPU_SIG));
200 }
201
202 return merge;
203 }
204
205 uint64_t
206 qpu_set_sig(uint64_t inst, uint32_t sig)
207 {
208 assert(QPU_GET_FIELD(inst, QPU_SIG) == QPU_SIG_NONE);
209 return (inst & ~QPU_SIG_MASK) | QPU_SET_FIELD(sig, QPU_SIG);
210 }
211
212 uint64_t
213 qpu_set_cond_add(uint64_t inst, uint32_t sig)
214 {
215 assert(QPU_GET_FIELD(inst, QPU_COND_ADD) == QPU_COND_ALWAYS);
216 return (inst & ~QPU_COND_ADD_MASK) | QPU_SET_FIELD(sig, QPU_COND_ADD);
217 }
218
219 uint64_t
220 qpu_set_cond_mul(uint64_t inst, uint32_t sig)
221 {
222 assert(QPU_GET_FIELD(inst, QPU_COND_MUL) == QPU_COND_ALWAYS);
223 return (inst & ~QPU_COND_MUL_MASK) | QPU_SET_FIELD(sig, QPU_COND_MUL);
224 }
225