Merge commit 'origin/master' into HEAD
[mesa.git] / src / gallium / auxiliary / rtasm / rtasm_ppc.c
1 /**************************************************************************
2 *
3 * Copyright (C) 2008 Tungsten Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 **************************************************************************/
23
24 /**
25 * PPC code generation.
26 * \author Brian Paul
27 */
28
29
30 #include "util/u_memory.h"
31 #include "pipe/p_debug.h"
32 #include "rtasm_ppc.h"
33
34
35 void
36 ppc_init_func(struct ppc_function *p, unsigned max_inst)
37 {
38 p->store = align_malloc(max_inst * PPC_INST_SIZE, 16);
39 p->num_inst = 0;
40 p->max_inst = max_inst;
41 p->vec_used = ~0;
42 }
43
44
45 void
46 ppc_release_func(struct ppc_function *p)
47 {
48 assert(p->num_inst <= p->max_inst);
49 if (p->store != NULL) {
50 align_free(p->store);
51 }
52 p->store = NULL;
53 }
54
55
56 /**
57 * Alloate a vector register.
58 * \return register index or -1 if none left.
59 */
60 int
61 ppc_allocate_vec_register(struct ppc_function *p, int reg)
62 {
63 unsigned i;
64 for (i = 0; i < PPC_NUM_VEC_REGS; i++) {
65 const uint64_t mask = 1 << i;
66 if ((p->vec_used & mask) != 0) {
67 p->vec_used &= ~mask;
68 return i;
69 }
70 }
71
72 return -1;
73 }
74
75
76 /**
77 * Mark the given vector register as "unallocated".
78 */
79 void
80 ppc_release_vec_register(struct ppc_function *p, int reg)
81 {
82 assert(reg < PPC_NUM_VEC_REGS);
83 assert((p->vec_used & (1 << reg)) == 0);
84
85 p->vec_used |= (1 << reg);
86 }
87
88
89
90 union vx_inst {
91 uint32_t bits;
92 struct {
93 unsigned op:6;
94 unsigned vD:5;
95 unsigned vA:5;
96 unsigned vB:5;
97 unsigned op2:11;
98 } inst;
99 };
100
101 union vxr_inst {
102 uint32_t bits;
103 struct {
104 unsigned op:6;
105 unsigned vD:5;
106 unsigned vA:5;
107 unsigned vB:5;
108 unsigned rC:1;
109 unsigned op2:10;
110 } inst;
111 };
112
113 union va_inst {
114 uint32_t bits;
115 struct {
116 unsigned op:6;
117 unsigned vD:5;
118 unsigned vA:5;
119 unsigned vB:5;
120 unsigned vC:5;
121 unsigned op2:6;
122 } inst;
123 };
124
125
126 static inline void
127 emit_vx(struct ppc_function *p, uint op2, uint vD, uint vA, uint vB)
128 {
129 union vx_inst inst;
130 inst.inst.op = 4;
131 inst.inst.vD = vD;
132 inst.inst.vA = vA;
133 inst.inst.vB = vB;
134 inst.inst.op2 = op2;
135 p->store[p->num_inst++] = inst.bits;
136 assert(p->num_inst <= p->max_inst);
137 };
138
139 static inline void
140 emit_vxr(struct ppc_function *p, uint op2, uint vD, uint vA, uint vB)
141 {
142 union vxr_inst inst;
143 inst.inst.op = 4;
144 inst.inst.vD = vD;
145 inst.inst.vA = vA;
146 inst.inst.vB = vB;
147 inst.inst.rC = 0;
148 inst.inst.op2 = op2;
149 p->store[p->num_inst++] = inst.bits;
150 assert(p->num_inst <= p->max_inst);
151 };
152
153 static inline void
154 emit_va(struct ppc_function *p, uint op2, uint vD, uint vA, uint vB, uint vC)
155 {
156 union va_inst inst;
157 inst.inst.op = 4;
158 inst.inst.vD = vD;
159 inst.inst.vA = vA;
160 inst.inst.vB = vB;
161 inst.inst.vC = vC;
162 inst.inst.op2 = op2;
163 p->store[p->num_inst++] = inst.bits;
164 assert(p->num_inst <= p->max_inst);
165 };
166
167
168
169 /**
170 ** float vector arithmetic
171 **/
172
173 /** vector float add */
174 void
175 ppc_vaddfp(struct ppc_function *p,uint vD, uint vA, uint vB)
176 {
177 emit_vx(p, 10, vD, vA, vB);
178 }
179
180 /** vector float substract */
181 void
182 ppc_vsubfp(struct ppc_function *p, uint vD, uint vA, uint vB)
183 {
184 emit_vx(p, 74, vD, vA, vB);
185 }
186
187 /** vector float min */
188 void
189 ppc_vminfp(struct ppc_function *p, uint vD, uint vA, uint vB)
190 {
191 emit_vx(p, 1098, vD, vA, vB);
192 }
193
194 /** vector float max */
195 void
196 ppc_vmaxfp(struct ppc_function *p, uint vD, uint vA, uint vB)
197 {
198 emit_vx(p, 1034, vD, vA, vB);
199 }
200
201 /** vector float mult add */
202 void
203 ppc_vmaddfp(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC)
204 {
205 emit_va(p, 46, vD, vA, vB, vC);
206 }
207
208 /** vector float compare greater than */
209 void
210 ppc_vcmpgtfpx(struct ppc_function *p, uint vD, uint vA, uint vB)
211 {
212 emit_vxr(p, 710, vD, vA, vB);
213 }
214
215 /** vector float compare greater than or equal to */
216 void
217 ppc_vcmpgefpx(struct ppc_function *p, uint vD, uint vA, uint vB)
218 {
219 emit_vxr(p, 454, vD, vA, vB);
220 }
221
222 /** vector float compare equal */
223 void
224 ppc_vcmpeqfpx(struct ppc_function *p, uint vD, uint vA, uint vB)
225 {
226 emit_vxr(p, 198, vD, vA, vB);
227 }
228
229 /** vector float 2^x */
230 void
231 ppc_vexptefp(struct ppc_function *p, uint vD, uint vB)
232 {
233 emit_vx(p, 394, vD, 0, vB);
234 }
235
236 /** vector float log2(x) */
237 void
238 ppc_vlogefp(struct ppc_function *p, uint vD, uint vB)
239 {
240 emit_vx(p, 458, vD, 0, vB);
241 }
242
243 /** vector float reciprocol */
244 void
245 ppc_vrefp(struct ppc_function *p, uint vD, uint vB)
246 {
247 emit_vx(p, 266, vD, 0, vB);
248 }
249
250 /** vector float reciprocol sqrt estimate */
251 void
252 ppc_vrsqrtefp(struct ppc_function *p, uint vD, uint vB)
253 {
254 emit_vx(p, 330, vD, 0, vB);
255 }
256
257 /** vector float round to negative infinity */
258 void
259 ppc_vrfim(struct ppc_function *p, uint vD, uint vB)
260 {
261 emit_vx(p, 714, vD, 0, vB);
262 }
263
264 /** vector float round to positive infinity */
265 void
266 ppc_vrfip(struct ppc_function *p, uint vD, uint vB)
267 {
268 emit_vx(p, 650, vD, 0, vB);
269 }
270
271 /** vector float round to nearest int */
272 void
273 ppc_vrfin(struct ppc_function *p, uint vD, uint vB)
274 {
275 emit_vx(p, 522, vD, 0, vB);
276 }
277
278 /** vector float round to int toward zero */
279 void
280 ppc_vrfiz(struct ppc_function *p, uint vD, uint vB)
281 {
282 emit_vx(p, 586, vD, 0, vB);
283 }
284
285
286
287 /**
288 ** bitwise operations
289 **/
290
291
292 /** vector and */
293 void
294 ppc_vand(struct ppc_function *p, uint vD, uint vA, uint vB)
295 {
296 emit_vx(p, 1028, vD, vA, vB);
297 }
298
299 /** vector and complement */
300 void
301 ppc_vandc(struct ppc_function *p, uint vD, uint vA, uint vB)
302 {
303 emit_vx(p, 1092, vD, vA, vB);
304 }
305
306 /** vector or */
307 void
308 ppc_vor(struct ppc_function *p, uint vD, uint vA, uint vB)
309 {
310 emit_vx(p, 1156, vD, vA, vB);
311 }
312
313 /** vector nor */
314 void
315 ppc_vnor(struct ppc_function *p, uint vD, uint vA, uint vB)
316 {
317 emit_vx(p, 1284, vD, vA, vB);
318 }
319
320 /** vector xor */
321 void
322 ppc_vxor(struct ppc_function *p, uint vD, uint vA, uint vB)
323 {
324 emit_vx(p, 1220, vD, vA, vB);
325 }
326
327
328 /**
329 ** Vector shuffle / select / splat / etc
330 **/
331
332 /** vector permute */
333 void
334 ppc_vperm(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC)
335 {
336 emit_va(p, 43, vD, vA, vB, vC);
337 }
338
339 /** vector select */
340 void
341 ppc_vsel(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC)
342 {
343 emit_va(p, 42, vD, vA, vB, vC);
344 }
345
346 /** vector splat byte */
347 void
348 ppc_vspltb(struct ppc_function *p, uint vD, uint vB, uint imm)
349 {
350 emit_vx(p, 42, vD, imm, vB);
351 }
352
353 /** vector splat half word */
354 void
355 ppc_vsplthw(struct ppc_function *p, uint vD, uint vB, uint imm)
356 {
357 emit_vx(p, 588, vD, imm, vB);
358 }
359
360 /** vector splat word */
361 void
362 ppc_vspltw(struct ppc_function *p, uint vD, uint vB, uint imm)
363 {
364 emit_vx(p, 652, vD, imm, vB);
365 }