nir: Remove fsin_reduced/fcos_reduced.
[mesa.git] / src / glsl / nir / nir_opcodes.py
1 #! /usr/bin/env python
2 #
3 # Copyright (C) 2014 Connor Abbott
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 (including the next
13 # paragraph) shall be included in all copies or substantial portions of the
14 # Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 # IN THE SOFTWARE.
23 #
24 # Authors:
25 # Connor Abbott (cwabbott0@gmail.com)
26
27
28 # Class that represents all the information we have about the opcode
29 # NOTE: this must be kept in sync with nir_op_info
30
31 class Opcode(object):
32 """Class that represents all the information we have about the opcode
33 NOTE: this must be kept in sync with nir_op_info
34 """
35 def __init__(self, name, output_size, output_type, input_sizes,
36 input_types, algebraic_properties, const_expr):
37 """Parameters:
38
39 - name is the name of the opcode (prepend nir_op_ for the enum name)
40 - all types are strings that get nir_type_ prepended to them
41 - input_types is a list of types
42 - algebraic_properties is a space-seperated string, where nir_op_is_ is
43 prepended before each entry
44 - const_expr is an expression or series of statements that computes the
45 constant value of the opcode given the constant values of its inputs.
46
47 Constant expressions are formed from the variables src0, src1, ...,
48 src(N-1), where N is the number of arguments. The output of the
49 expression should be stored in the dst variable. Per-component input
50 and output variables will be scalars and non-per-component input and
51 output variables will be a struct with fields named x, y, z, and w
52 all of the correct type. Input and output variables can be assumed
53 to already be of the correct type and need no conversion. In
54 particular, the conversion from the C bool type to/from NIR_TRUE and
55 NIR_FALSE happens automatically.
56
57 For per-component instructions, the entire expression will be
58 executed once for each component. For non-per-component
59 instructions, the expression is expected to store the correct values
60 in dst.x, dst.y, etc. If "dst" does not exist anywhere in the
61 constant expression, an assignment to dst will happen automatically
62 and the result will be equivalent to "dst = <expression>" for
63 per-component instructions and "dst.x = dst.y = ... = <expression>"
64 for non-per-component instructions.
65 """
66 assert isinstance(name, str)
67 assert isinstance(output_size, int)
68 assert isinstance(output_type, str)
69 assert isinstance(input_sizes, list)
70 assert isinstance(input_sizes[0], int)
71 assert isinstance(input_types, list)
72 assert isinstance(input_types[0], str)
73 assert isinstance(algebraic_properties, str)
74 assert isinstance(const_expr, str)
75 assert len(input_sizes) == len(input_types)
76 assert 0 <= output_size <= 4
77 for size in input_sizes:
78 assert 0 <= size <= 4
79 if output_size != 0:
80 assert size != 0
81 self.name = name
82 self.num_inputs = len(input_sizes)
83 self.output_size = output_size
84 self.output_type = output_type
85 self.input_sizes = input_sizes
86 self.input_types = input_types
87 self.algebraic_properties = algebraic_properties
88 self.const_expr = const_expr
89
90 # helper variables for strings
91 tfloat = "float"
92 tint = "int"
93 tbool = "bool"
94 tunsigned = "unsigned"
95
96 commutative = "commutative "
97 associative = "associative "
98
99 # global dictionary of opcodes
100 opcodes = {}
101
102 def opcode(name, output_size, output_type, input_sizes, input_types,
103 algebraic_properties, const_expr):
104 assert name not in opcodes
105 opcodes[name] = Opcode(name, output_size, output_type, input_sizes,
106 input_types, algebraic_properties, const_expr)
107
108 def unop_convert(name, in_type, out_type, const_expr):
109 opcode(name, 0, out_type, [0], [in_type], "", const_expr)
110
111 def unop(name, ty, const_expr):
112 opcode(name, 0, ty, [0], [ty], "", const_expr)
113
114 def unop_horiz(name, output_size, output_type, input_size, input_type,
115 const_expr):
116 opcode(name, output_size, output_type, [input_size], [input_type], "",
117 const_expr)
118
119 def unop_reduce(name, output_size, output_type, input_type, prereduce_expr,
120 reduce_expr, final_expr):
121 def prereduce(src):
122 return "(" + prereduce_expr.format(src=src) + ")"
123 def final(src):
124 return final_expr.format(src="(" + src + ")")
125 def reduce_(src0, src1):
126 return reduce_expr.format(src0=src0, src1=src1)
127 src0 = prereduce("src0.x")
128 src1 = prereduce("src0.y")
129 src2 = prereduce("src0.z")
130 src3 = prereduce("src0.w")
131 unop_horiz(name + "2", output_size, output_type, 2, input_type,
132 final(reduce_(src0, src1)))
133 unop_horiz(name + "3", output_size, output_type, 3, input_type,
134 final(reduce_(reduce_(src0, src1), src2)))
135 unop_horiz(name + "4", output_size, output_type, 4, input_type,
136 final(reduce_(reduce_(src0, src1), reduce_(src2, src3))))
137
138
139 # These two move instructions differ in what modifiers they support and what
140 # the negate modifier means. Otherwise, they are identical.
141 unop("fmov", tfloat, "src0")
142 unop("imov", tint, "src0")
143
144 unop("ineg", tint, "-src0")
145 unop("fneg", tfloat, "-src0")
146 unop("inot", tint, "~src0") # invert every bit of the integer
147 unop("fnot", tfloat, "(src0 == 0.0f) ? 1.0f : 0.0f")
148 unop("fsign", tfloat, "(src0 == 0.0f) ? 0.0f : ((src0 > 0.0f) ? 1.0f : -1.0f)")
149 unop("isign", tint, "(src0 == 0) ? 0 : ((src0 > 0) ? 1 : -1)")
150 unop("iabs", tint, "(src0 < 0) ? -src0 : src0")
151 unop("fabs", tfloat, "fabsf(src0)")
152 unop("fsat", tfloat, "(src0 > 1.0f) ? 1.0f : ((src0 <= 0.0f) ? 0.0f : src0)")
153 unop("frcp", tfloat, "1.0f / src0")
154 unop("frsq", tfloat, "1.0f / sqrtf(src0)")
155 unop("fsqrt", tfloat, "sqrtf(src0)")
156 unop("fexp", tfloat, "expf(src0)") # < e^x
157 unop("flog", tfloat, "logf(src0)") # log base e
158 unop("fexp2", tfloat, "exp2f(src0)")
159 unop("flog2", tfloat, "log2f(src0)")
160 unop_convert("f2i", tfloat, tint, "src0") # Float-to-integer conversion.
161 unop_convert("f2u", tfloat, tunsigned, "src0") # Float-to-unsigned conversion
162 unop_convert("i2f", tint, tfloat, "src0") # Integer-to-float conversion.
163 # Float-to-boolean conversion
164 unop_convert("f2b", tfloat, tbool, "src0 != 0.0f")
165 # Boolean-to-float conversion
166 unop_convert("b2f", tbool, tfloat, "src0 ? 1.0f : 0.0f")
167 # Int-to-boolean conversion
168 unop_convert("i2b", tint, tbool, "src0 != 0")
169 unop_convert("b2i", tbool, tint, "src0 ? 1 : 0") # Boolean-to-int conversion
170 unop_convert("u2f", tunsigned, tfloat, "src0") #Unsigned-to-float conversion.
171
172 unop_reduce("bany", 1, tbool, tbool, "{src}", "{src0} || {src1}", "{src}")
173 unop_reduce("ball", 1, tbool, tbool, "{src}", "{src0} && {src1}", "{src}")
174 unop_reduce("fany", 1, tfloat, tfloat, "{src} != 0.0f", "{src0} || {src1}",
175 "{src} ? 1.0f : 0.0f")
176 unop_reduce("fall", 1, tfloat, tfloat, "{src} != 0.0f", "{src0} && {src1}",
177 "{src} ? 1.0f : 0.0f")
178
179 # Unary floating-point rounding operations.
180
181
182 unop("ftrunc", tfloat, "truncf(src0)")
183 unop("fceil", tfloat, "ceilf(src0)")
184 unop("ffloor", tfloat, "floorf(src0)")
185 unop("ffract", tfloat, "src0 - floorf(src0)")
186 unop("fround_even", tfloat, "_mesa_roundevenf(src0)")
187
188
189 # Trigonometric operations.
190
191
192 unop("fsin", tfloat, "sinf(src0)")
193 unop("fcos", tfloat, "cosf(src0)")
194
195
196 # Partial derivatives.
197
198
199 unop("fddx", tfloat, "0.0f") # the derivative of a constant is 0.
200 unop("fddy", tfloat, "0.0f")
201 unop("fddx_fine", tfloat, "0.0f")
202 unop("fddy_fine", tfloat, "0.0f")
203 unop("fddx_coarse", tfloat, "0.0f")
204 unop("fddy_coarse", tfloat, "0.0f")
205
206
207 # Floating point pack and unpack operations.
208
209 def pack_2x16(fmt):
210 unop_horiz("pack_" + fmt + "_2x16", 1, tunsigned, 2, tfloat, """
211 dst.x = (uint32_t) pack_fmt_1x16(src0.x);
212 dst.x |= ((uint32_t) pack_fmt_1x16(src0.y)) << 16;
213 """.replace("fmt", fmt))
214
215 def pack_4x8(fmt):
216 unop_horiz("pack_" + fmt + "_4x8", 1, tunsigned, 4, tfloat, """
217 dst.x = (uint32_t) pack_fmt_1x8(src0.x);
218 dst.x |= ((uint32_t) pack_fmt_1x8(src0.y)) << 8;
219 dst.x |= ((uint32_t) pack_fmt_1x8(src0.z)) << 16;
220 dst.x |= ((uint32_t) pack_fmt_1x8(src0.w)) << 24;
221 """.replace("fmt", fmt))
222
223 def unpack_2x16(fmt):
224 unop_horiz("unpack_" + fmt + "_2x16", 2, tfloat, 1, tunsigned, """
225 dst.x = unpack_fmt_1x16((uint16_t)(src0.x & 0xffff));
226 dst.y = unpack_fmt_1x16((uint16_t)(src0.x << 16));
227 """.replace("fmt", fmt))
228
229 def unpack_4x8(fmt):
230 unop_horiz("unpack_" + fmt + "_4x8", 4, tfloat, 1, tunsigned, """
231 dst.x = unpack_fmt_1x8((uint8_t)(src0.x & 0xff));
232 dst.y = unpack_fmt_1x8((uint8_t)((src0.x >> 8) & 0xff));
233 dst.z = unpack_fmt_1x8((uint8_t)((src0.x >> 16) & 0xff));
234 dst.w = unpack_fmt_1x8((uint8_t)(src0.x >> 24));
235 """.replace("fmt", fmt))
236
237
238 pack_2x16("snorm")
239 pack_4x8("snorm")
240 pack_2x16("unorm")
241 pack_4x8("unorm")
242 pack_2x16("half")
243 unpack_2x16("snorm")
244 unpack_4x8("snorm")
245 unpack_2x16("unorm")
246 unpack_4x8("unorm")
247 unpack_2x16("half")
248
249
250 # Lowered floating point unpacking operations.
251
252
253 unop_horiz("unpack_half_2x16_split_x", 1, tfloat, 1, tunsigned,
254 "unpack_half_1x16((uint16_t)(src0.x & 0xffff))")
255 unop_horiz("unpack_half_2x16_split_y", 1, tfloat, 1, tunsigned,
256 "unpack_half_1x16((uint16_t)(src0.x >> 16))")
257
258
259 # Bit operations, part of ARB_gpu_shader5.
260
261
262 unop("bitfield_reverse", tunsigned, """
263 /* we're not winning any awards for speed here, but that's ok */
264 dst = 0;
265 for (unsigned bit = 0; bit < 32; bit++)
266 dst |= ((src0 >> bit) & 1) << (31 - bit);
267 """)
268 unop("bit_count", tunsigned, """
269 dst = 0;
270 for (unsigned bit = 0; bit < 32; bit++) {
271 if ((src0 >> bit) & 1)
272 dst++;
273 }
274 """)
275
276 unop_convert("ufind_msb", tunsigned, tint, """
277 dst = -1;
278 for (int bit = 31; bit > 0; bit--) {
279 if ((src0 >> bit) & 1) {
280 dst = bit;
281 break;
282 }
283 }
284 """)
285
286 unop("ifind_msb", tint, """
287 dst = -1;
288 for (int bit = 31; bit >= 0; bit--) {
289 /* If src0 < 0, we're looking for the first 0 bit.
290 * if src0 >= 0, we're looking for the first 1 bit.
291 */
292 if ((((src0 >> bit) & 1) && (src0 >= 0)) ||
293 (!((src0 >> bit) & 1) && (src0 < 0))) {
294 dst = bit;
295 break;
296 }
297 }
298 """)
299
300 unop("find_lsb", tint, """
301 dst = -1;
302 for (unsigned bit = 0; bit < 32; bit++) {
303 if ((src0 >> bit) & 1) {
304 dst = bit;
305 break;
306 }
307 }
308 """)
309
310
311 for i in xrange(1, 5):
312 for j in xrange(1, 5):
313 unop_horiz("fnoise{0}_{1}".format(i, j), i, tfloat, j, tfloat, "0.0f")
314
315 def binop_convert(name, out_type, in_type, alg_props, const_expr):
316 opcode(name, 0, out_type, [0, 0], [in_type, in_type], alg_props, const_expr)
317
318 def binop(name, ty, alg_props, const_expr):
319 binop_convert(name, ty, ty, alg_props, const_expr)
320
321 def binop_compare(name, ty, alg_props, const_expr):
322 binop_convert(name, tbool, ty, alg_props, const_expr)
323
324 def binop_horiz(name, out_size, out_type, src1_size, src1_type, src2_size,
325 src2_type, const_expr):
326 opcode(name, out_size, out_type, [src1_size, src2_size], [src1_type, src2_type],
327 "", const_expr)
328
329 def binop_reduce(name, output_size, output_type, src_type, prereduce_expr,
330 reduce_expr, final_expr):
331 def final(src):
332 return final_expr.format(src= "(" + src + ")")
333 def reduce_(src0, src1):
334 return reduce_expr.format(src0=src0, src1=src1)
335 def prereduce(src0, src1):
336 return "(" + prereduce_expr.format(src0=src0, src1=src1) + ")"
337 src0 = prereduce("src0.x", "src1.x")
338 src1 = prereduce("src0.y", "src1.y")
339 src2 = prereduce("src0.z", "src1.z")
340 src3 = prereduce("src0.w", "src1.w")
341 opcode(name + "2", output_size, output_type,
342 [2, 2], [src_type, src_type], commutative,
343 final(reduce_(src0, src1)))
344 opcode(name + "3", output_size, output_type,
345 [3, 3], [src_type, src_type], commutative,
346 final(reduce_(reduce_(src0, src1), src2)))
347 opcode(name + "4", output_size, output_type,
348 [4, 4], [src_type, src_type], commutative,
349 final(reduce_(reduce_(src0, src1), reduce_(src2, src3))))
350
351 binop("fadd", tfloat, commutative + associative, "src0 + src1")
352 binop("iadd", tint, commutative + associative, "src0 + src1")
353 binop("fsub", tfloat, "", "src0 - src1")
354 binop("isub", tint, "", "src0 - src1")
355
356 binop("fmul", tfloat, commutative + associative, "src0 * src1")
357 # low 32-bits of signed/unsigned integer multiply
358 binop("imul", tint, commutative + associative, "src0 * src1")
359 # high 32-bits of signed integer multiply
360 binop("imul_high", tint, commutative,
361 "(int32_t)(((int64_t) src0 * (int64_t) src1) >> 32)")
362 # high 32-bits of unsigned integer multiply
363 binop("umul_high", tunsigned, commutative,
364 "(uint32_t)(((uint64_t) src0 * (uint64_t) src1) >> 32)")
365
366 binop("fdiv", tfloat, "", "src0 / src1")
367 binop("idiv", tint, "", "src0 / src1")
368 binop("udiv", tunsigned, "", "src0 / src1")
369
370 # returns a boolean representing the carry resulting from the addition of
371 # the two unsigned arguments.
372
373 binop_convert("uadd_carry", tbool, tunsigned, commutative, "src0 + src1 < src0")
374
375 # returns a boolean representing the borrow resulting from the subtraction
376 # of the two unsigned arguments.
377
378 binop_convert("usub_borrow", tbool, tunsigned, "", "src1 < src0")
379
380 binop("fmod", tfloat, "", "src0 - src1 * floorf(src0 / src1)")
381 binop("umod", tunsigned, "", "src1 == 0 ? 0 : src0 % src1")
382
383 #
384 # Comparisons
385 #
386
387
388 # these integer-aware comparisons return a boolean (0 or ~0)
389
390 binop_compare("flt", tfloat, "", "src0 < src1")
391 binop_compare("fge", tfloat, "", "src0 >= src1")
392 binop_compare("feq", tfloat, commutative, "src0 == src1")
393 binop_compare("fne", tfloat, commutative, "src0 != src1")
394 binop_compare("ilt", tint, "", "src0 < src1")
395 binop_compare("ige", tint, "", "src0 >= src1")
396 binop_compare("ieq", tint, commutative, "src0 == src1")
397 binop_compare("ine", tint, commutative, "src0 != src1")
398 binop_compare("ult", tunsigned, "", "src0 < src1")
399 binop_compare("uge", tunsigned, "", "src0 >= src1")
400
401 # integer-aware GLSL-style comparisons that compare floats and ints
402
403 binop_reduce("ball_fequal", 1, tbool, tfloat, "{src0} == {src1}",
404 "{src0} && {src1}", "{src}")
405 binop_reduce("bany_fnequal", 1, tbool, tfloat, "{src0} != {src1}",
406 "{src0} || {src1}", "{src}")
407 binop_reduce("ball_iequal", 1, tbool, tint, "{src0} == {src1}",
408 "{src0} && {src1}", "{src}")
409 binop_reduce("bany_inequal", 1, tbool, tint, "{src0} != {src1}",
410 "{src0} || {src1}", "{src}")
411
412 # non-integer-aware GLSL-style comparisons that return 0.0 or 1.0
413
414 binop_reduce("fall_equal", 1, tfloat, tfloat, "{src0} == {src1}",
415 "{src0} && {src1}", "{src} ? 1.0f : 0.0f")
416 binop_reduce("fany_nequal", 1, tfloat, tfloat, "{src0} != {src1}",
417 "{src0} || {src1}", "{src} ? 1.0f : 0.0f")
418
419 # These comparisons for integer-less hardware return 1.0 and 0.0 for true
420 # and false respectively
421
422 binop("slt", tfloat, "", "(src0 < src1) ? 1.0f : 0.0f") # Set on Less Than
423 binop("sge", tfloat, "", "(src0 >= src1) ? 1.0f : 0.0f") # Set on Greater or Equal
424 binop("seq", tfloat, commutative, "(src0 == src1) ? 1.0f : 0.0f") # Set on Equal
425 binop("sne", tfloat, commutative, "(src0 != src1) ? 1.0f : 0.0f") # Set on Not Equal
426
427
428 binop("ishl", tint, "", "src0 << src1")
429 binop("ishr", tint, "", "src0 >> src1")
430 binop("ushr", tunsigned, "", "src0 >> src1")
431
432 # bitwise logic operators
433 #
434 # These are also used as boolean and, or, xor for hardware supporting
435 # integers.
436
437
438 binop("iand", tunsigned, commutative + associative, "src0 & src1")
439 binop("ior", tunsigned, commutative + associative, "src0 | src1")
440 binop("ixor", tunsigned, commutative + associative, "src0 ^ src1")
441
442
443 # floating point logic operators
444 #
445 # These use (src != 0.0) for testing the truth of the input, and output 1.0
446 # for true and 0.0 for false
447
448 binop("fand", tfloat, commutative,
449 "((src0 != 0.0f) && (src1 != 0.0f)) ? 1.0f : 0.0f")
450 binop("for", tfloat, commutative,
451 "((src0 != 0.0f) || (src1 != 0.0f)) ? 1.0f : 0.0f")
452 binop("fxor", tfloat, commutative,
453 "(src0 != 0.0f && src1 == 0.0f) || (src0 == 0.0f && src1 != 0.0f) ? 1.0f : 0.0f")
454
455 binop_reduce("fdot", 1, tfloat, tfloat, "{src0} * {src1}", "{src0} + {src1}",
456 "{src}")
457
458 binop("fmin", tfloat, "", "fminf(src0, src1)")
459 binop("imin", tint, commutative + associative, "src1 > src0 ? src0 : src1")
460 binop("umin", tunsigned, commutative + associative, "src1 > src0 ? src0 : src1")
461 binop("fmax", tfloat, "", "fmaxf(src0, src1)")
462 binop("imax", tint, commutative + associative, "src1 > src0 ? src1 : src0")
463 binop("umax", tunsigned, commutative + associative, "src1 > src0 ? src1 : src0")
464
465 binop("fpow", tfloat, "", "powf(src0, src1)")
466
467 binop_horiz("pack_half_2x16_split", 1, tunsigned, 1, tfloat, 1, tfloat,
468 "pack_half_1x16(src0.x) | (pack_half_1x16(src1.x) << 16)")
469
470 binop_convert("bfm", tunsigned, tint, "", """
471 int offset = src0, bits = src1;
472 if (offset < 0 || bits < 0 || offset + bits > 32)
473 dst = 0; /* undefined per the spec */
474 else
475 dst = ((1 << bits)- 1) << offset;
476 """)
477
478 opcode("ldexp", 0, tfloat, [0, 0], [tfloat, tint], "", """
479 dst = ldexp(src0, src1);
480 /* flush denormals to zero. */
481 if (!isnormal(dst))
482 dst = copysign(0.0f, src0);
483 """)
484
485 # Combines the first component of each input to make a 2-component vector.
486
487 binop_horiz("vec2", 2, tunsigned, 1, tunsigned, 1, tunsigned, """
488 dst.x = src0.x;
489 dst.y = src1.x;
490 """)
491
492 def triop(name, ty, const_expr):
493 opcode(name, 0, ty, [0, 0, 0], [ty, ty, ty], "", const_expr)
494 def triop_horiz(name, output_size, src1_size, src2_size, src3_size, const_expr):
495 opcode(name, output_size, tunsigned,
496 [src1_size, src2_size, src3_size],
497 [tunsigned, tunsigned, tunsigned], "", const_expr)
498
499 triop("ffma", tfloat, "src0 * src1 + src2")
500
501 triop("flrp", tfloat, "src0 * (1 - src2) + src1 * src2")
502
503 # Conditional Select
504 #
505 # A vector conditional select instruction (like ?:, but operating per-
506 # component on vectors). There are two versions, one for floating point
507 # bools (0.0 vs 1.0) and one for integer bools (0 vs ~0).
508
509
510 triop("fcsel", tfloat, "(src0 != 0.0f) ? src1 : src2")
511 opcode("bcsel", 0, tunsigned, [0, 0, 0],
512 [tbool, tunsigned, tunsigned], "", "src0 ? src1 : src2")
513
514 triop("bfi", tunsigned, """
515 unsigned mask = src0, insert = src1 & mask, base = src2;
516 if (mask == 0) {
517 dst = base;
518 } else {
519 unsigned tmp = mask;
520 while (!(tmp & 1)) {
521 tmp >>= 1;
522 insert <<= 1;
523 }
524 dst = (base & ~mask) | insert;
525 }
526 """)
527
528 opcode("ubitfield_extract", 0, tunsigned,
529 [0, 1, 1], [tunsigned, tint, tint], "", """
530 unsigned base = src0;
531 int offset = src1.x, bits = src2.x;
532 if (bits == 0) {
533 dst = 0;
534 } else if (bits < 0 || offset < 0 || offset + bits > 32) {
535 dst = 0; /* undefined per the spec */
536 } else {
537 dst = (base >> offset) & ((1 << bits) - 1);
538 }
539 """)
540 opcode("ibitfield_extract", 0, tint,
541 [0, 1, 1], [tint, tint, tint], "", """
542 int base = src0;
543 int offset = src1.x, bits = src2.x;
544 if (bits == 0) {
545 dst = 0;
546 } else if (offset < 0 || bits < 0 || offset + bits > 32) {
547 dst = 0;
548 } else {
549 dst = (base << (32 - offset - bits)) >> offset; /* use sign-extending shift */
550 }
551 """)
552
553 # Combines the first component of each input to make a 3-component vector.
554
555 triop_horiz("vec3", 3, 1, 1, 1, """
556 dst.x = src0.x;
557 dst.y = src1.x;
558 dst.z = src2.x;
559 """)
560
561 def quadop_horiz(name, output_size, src1_size, src2_size, src3_size,
562 src4_size, const_expr):
563 opcode(name, output_size, tunsigned,
564 [src1_size, src2_size, src3_size, src4_size],
565 [tunsigned, tunsigned, tunsigned, tunsigned],
566 "", const_expr)
567
568 opcode("bitfield_insert", 0, tunsigned, [0, 0, 1, 1],
569 [tunsigned, tunsigned, tint, tint], "", """
570 unsigned base = src0, insert = src1;
571 int offset = src2.x, bits = src3.x;
572 if (bits == 0) {
573 dst = 0;
574 } else if (offset < 0 || bits < 0 || bits + offset > 32) {
575 dst = 0;
576 } else {
577 unsigned mask = ((1 << bits) - 1) << offset;
578 dst = (base & ~mask) | ((insert << bits) & mask);
579 }
580 """)
581
582 quadop_horiz("vec4", 4, 1, 1, 1, 1, """
583 dst.x = src0.x;
584 dst.y = src1.x;
585 dst.z = src2.x;
586 dst.w = src3.x;
587 """)
588
589