nir: Delete all traces of nir_op_fexp
[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("flog", tfloat, "logf(src0)") # log base e
157 unop("fexp2", tfloat, "exp2f(src0)")
158 unop("flog2", tfloat, "log2f(src0)")
159 unop_convert("f2i", tfloat, tint, "src0") # Float-to-integer conversion.
160 unop_convert("f2u", tfloat, tunsigned, "src0") # Float-to-unsigned conversion
161 unop_convert("i2f", tint, tfloat, "src0") # Integer-to-float conversion.
162 # Float-to-boolean conversion
163 unop_convert("f2b", tfloat, tbool, "src0 != 0.0f")
164 # Boolean-to-float conversion
165 unop_convert("b2f", tbool, tfloat, "src0 ? 1.0f : 0.0f")
166 # Int-to-boolean conversion
167 unop_convert("i2b", tint, tbool, "src0 != 0")
168 unop_convert("b2i", tbool, tint, "src0 ? 1 : 0") # Boolean-to-int conversion
169 unop_convert("u2f", tunsigned, tfloat, "src0") #Unsigned-to-float conversion.
170
171 unop_reduce("bany", 1, tbool, tbool, "{src}", "{src0} || {src1}", "{src}")
172 unop_reduce("ball", 1, tbool, tbool, "{src}", "{src0} && {src1}", "{src}")
173 unop_reduce("fany", 1, tfloat, tfloat, "{src} != 0.0f", "{src0} || {src1}",
174 "{src} ? 1.0f : 0.0f")
175 unop_reduce("fall", 1, tfloat, tfloat, "{src} != 0.0f", "{src0} && {src1}",
176 "{src} ? 1.0f : 0.0f")
177
178 # Unary floating-point rounding operations.
179
180
181 unop("ftrunc", tfloat, "truncf(src0)")
182 unop("fceil", tfloat, "ceilf(src0)")
183 unop("ffloor", tfloat, "floorf(src0)")
184 unop("ffract", tfloat, "src0 - floorf(src0)")
185 unop("fround_even", tfloat, "_mesa_roundevenf(src0)")
186
187
188 # Trigonometric operations.
189
190
191 unop("fsin", tfloat, "sinf(src0)")
192 unop("fcos", tfloat, "cosf(src0)")
193
194
195 # Partial derivatives.
196
197
198 unop("fddx", tfloat, "0.0f") # the derivative of a constant is 0.
199 unop("fddy", tfloat, "0.0f")
200 unop("fddx_fine", tfloat, "0.0f")
201 unop("fddy_fine", tfloat, "0.0f")
202 unop("fddx_coarse", tfloat, "0.0f")
203 unop("fddy_coarse", tfloat, "0.0f")
204
205
206 # Floating point pack and unpack operations.
207
208 def pack_2x16(fmt):
209 unop_horiz("pack_" + fmt + "_2x16", 1, tunsigned, 2, tfloat, """
210 dst.x = (uint32_t) pack_fmt_1x16(src0.x);
211 dst.x |= ((uint32_t) pack_fmt_1x16(src0.y)) << 16;
212 """.replace("fmt", fmt))
213
214 def pack_4x8(fmt):
215 unop_horiz("pack_" + fmt + "_4x8", 1, tunsigned, 4, tfloat, """
216 dst.x = (uint32_t) pack_fmt_1x8(src0.x);
217 dst.x |= ((uint32_t) pack_fmt_1x8(src0.y)) << 8;
218 dst.x |= ((uint32_t) pack_fmt_1x8(src0.z)) << 16;
219 dst.x |= ((uint32_t) pack_fmt_1x8(src0.w)) << 24;
220 """.replace("fmt", fmt))
221
222 def unpack_2x16(fmt):
223 unop_horiz("unpack_" + fmt + "_2x16", 2, tfloat, 1, tunsigned, """
224 dst.x = unpack_fmt_1x16((uint16_t)(src0.x & 0xffff));
225 dst.y = unpack_fmt_1x16((uint16_t)(src0.x << 16));
226 """.replace("fmt", fmt))
227
228 def unpack_4x8(fmt):
229 unop_horiz("unpack_" + fmt + "_4x8", 4, tfloat, 1, tunsigned, """
230 dst.x = unpack_fmt_1x8((uint8_t)(src0.x & 0xff));
231 dst.y = unpack_fmt_1x8((uint8_t)((src0.x >> 8) & 0xff));
232 dst.z = unpack_fmt_1x8((uint8_t)((src0.x >> 16) & 0xff));
233 dst.w = unpack_fmt_1x8((uint8_t)(src0.x >> 24));
234 """.replace("fmt", fmt))
235
236
237 pack_2x16("snorm")
238 pack_4x8("snorm")
239 pack_2x16("unorm")
240 pack_4x8("unorm")
241 pack_2x16("half")
242 unpack_2x16("snorm")
243 unpack_4x8("snorm")
244 unpack_2x16("unorm")
245 unpack_4x8("unorm")
246 unpack_2x16("half")
247
248
249 # Lowered floating point unpacking operations.
250
251
252 unop_horiz("unpack_half_2x16_split_x", 1, tfloat, 1, tunsigned,
253 "unpack_half_1x16((uint16_t)(src0.x & 0xffff))")
254 unop_horiz("unpack_half_2x16_split_y", 1, tfloat, 1, tunsigned,
255 "unpack_half_1x16((uint16_t)(src0.x >> 16))")
256
257
258 # Bit operations, part of ARB_gpu_shader5.
259
260
261 unop("bitfield_reverse", tunsigned, """
262 /* we're not winning any awards for speed here, but that's ok */
263 dst = 0;
264 for (unsigned bit = 0; bit < 32; bit++)
265 dst |= ((src0 >> bit) & 1) << (31 - bit);
266 """)
267 unop("bit_count", tunsigned, """
268 dst = 0;
269 for (unsigned bit = 0; bit < 32; bit++) {
270 if ((src0 >> bit) & 1)
271 dst++;
272 }
273 """)
274
275 unop_convert("ufind_msb", tunsigned, tint, """
276 dst = -1;
277 for (int bit = 31; bit > 0; bit--) {
278 if ((src0 >> bit) & 1) {
279 dst = bit;
280 break;
281 }
282 }
283 """)
284
285 unop("ifind_msb", tint, """
286 dst = -1;
287 for (int bit = 31; bit >= 0; bit--) {
288 /* If src0 < 0, we're looking for the first 0 bit.
289 * if src0 >= 0, we're looking for the first 1 bit.
290 */
291 if ((((src0 >> bit) & 1) && (src0 >= 0)) ||
292 (!((src0 >> bit) & 1) && (src0 < 0))) {
293 dst = bit;
294 break;
295 }
296 }
297 """)
298
299 unop("find_lsb", tint, """
300 dst = -1;
301 for (unsigned bit = 0; bit < 32; bit++) {
302 if ((src0 >> bit) & 1) {
303 dst = bit;
304 break;
305 }
306 }
307 """)
308
309
310 for i in xrange(1, 5):
311 for j in xrange(1, 5):
312 unop_horiz("fnoise{0}_{1}".format(i, j), i, tfloat, j, tfloat, "0.0f")
313
314 def binop_convert(name, out_type, in_type, alg_props, const_expr):
315 opcode(name, 0, out_type, [0, 0], [in_type, in_type], alg_props, const_expr)
316
317 def binop(name, ty, alg_props, const_expr):
318 binop_convert(name, ty, ty, alg_props, const_expr)
319
320 def binop_compare(name, ty, alg_props, const_expr):
321 binop_convert(name, tbool, ty, alg_props, const_expr)
322
323 def binop_horiz(name, out_size, out_type, src1_size, src1_type, src2_size,
324 src2_type, const_expr):
325 opcode(name, out_size, out_type, [src1_size, src2_size], [src1_type, src2_type],
326 "", const_expr)
327
328 def binop_reduce(name, output_size, output_type, src_type, prereduce_expr,
329 reduce_expr, final_expr):
330 def final(src):
331 return final_expr.format(src= "(" + src + ")")
332 def reduce_(src0, src1):
333 return reduce_expr.format(src0=src0, src1=src1)
334 def prereduce(src0, src1):
335 return "(" + prereduce_expr.format(src0=src0, src1=src1) + ")"
336 src0 = prereduce("src0.x", "src1.x")
337 src1 = prereduce("src0.y", "src1.y")
338 src2 = prereduce("src0.z", "src1.z")
339 src3 = prereduce("src0.w", "src1.w")
340 opcode(name + "2", output_size, output_type,
341 [2, 2], [src_type, src_type], commutative,
342 final(reduce_(src0, src1)))
343 opcode(name + "3", output_size, output_type,
344 [3, 3], [src_type, src_type], commutative,
345 final(reduce_(reduce_(src0, src1), src2)))
346 opcode(name + "4", output_size, output_type,
347 [4, 4], [src_type, src_type], commutative,
348 final(reduce_(reduce_(src0, src1), reduce_(src2, src3))))
349
350 binop("fadd", tfloat, commutative + associative, "src0 + src1")
351 binop("iadd", tint, commutative + associative, "src0 + src1")
352 binop("fsub", tfloat, "", "src0 - src1")
353 binop("isub", tint, "", "src0 - src1")
354
355 binop("fmul", tfloat, commutative + associative, "src0 * src1")
356 # low 32-bits of signed/unsigned integer multiply
357 binop("imul", tint, commutative + associative, "src0 * src1")
358 # high 32-bits of signed integer multiply
359 binop("imul_high", tint, commutative,
360 "(int32_t)(((int64_t) src0 * (int64_t) src1) >> 32)")
361 # high 32-bits of unsigned integer multiply
362 binop("umul_high", tunsigned, commutative,
363 "(uint32_t)(((uint64_t) src0 * (uint64_t) src1) >> 32)")
364
365 binop("fdiv", tfloat, "", "src0 / src1")
366 binop("idiv", tint, "", "src0 / src1")
367 binop("udiv", tunsigned, "", "src0 / src1")
368
369 # returns a boolean representing the carry resulting from the addition of
370 # the two unsigned arguments.
371
372 binop_convert("uadd_carry", tbool, tunsigned, commutative, "src0 + src1 < src0")
373
374 # returns a boolean representing the borrow resulting from the subtraction
375 # of the two unsigned arguments.
376
377 binop_convert("usub_borrow", tbool, tunsigned, "", "src1 < src0")
378
379 binop("fmod", tfloat, "", "src0 - src1 * floorf(src0 / src1)")
380 binop("umod", tunsigned, "", "src1 == 0 ? 0 : src0 % src1")
381
382 #
383 # Comparisons
384 #
385
386
387 # these integer-aware comparisons return a boolean (0 or ~0)
388
389 binop_compare("flt", tfloat, "", "src0 < src1")
390 binop_compare("fge", tfloat, "", "src0 >= src1")
391 binop_compare("feq", tfloat, commutative, "src0 == src1")
392 binop_compare("fne", tfloat, commutative, "src0 != src1")
393 binop_compare("ilt", tint, "", "src0 < src1")
394 binop_compare("ige", tint, "", "src0 >= src1")
395 binop_compare("ieq", tint, commutative, "src0 == src1")
396 binop_compare("ine", tint, commutative, "src0 != src1")
397 binop_compare("ult", tunsigned, "", "src0 < src1")
398 binop_compare("uge", tunsigned, "", "src0 >= src1")
399
400 # integer-aware GLSL-style comparisons that compare floats and ints
401
402 binop_reduce("ball_fequal", 1, tbool, tfloat, "{src0} == {src1}",
403 "{src0} && {src1}", "{src}")
404 binop_reduce("bany_fnequal", 1, tbool, tfloat, "{src0} != {src1}",
405 "{src0} || {src1}", "{src}")
406 binop_reduce("ball_iequal", 1, tbool, tint, "{src0} == {src1}",
407 "{src0} && {src1}", "{src}")
408 binop_reduce("bany_inequal", 1, tbool, tint, "{src0} != {src1}",
409 "{src0} || {src1}", "{src}")
410
411 # non-integer-aware GLSL-style comparisons that return 0.0 or 1.0
412
413 binop_reduce("fall_equal", 1, tfloat, tfloat, "{src0} == {src1}",
414 "{src0} && {src1}", "{src} ? 1.0f : 0.0f")
415 binop_reduce("fany_nequal", 1, tfloat, tfloat, "{src0} != {src1}",
416 "{src0} || {src1}", "{src} ? 1.0f : 0.0f")
417
418 # These comparisons for integer-less hardware return 1.0 and 0.0 for true
419 # and false respectively
420
421 binop("slt", tfloat, "", "(src0 < src1) ? 1.0f : 0.0f") # Set on Less Than
422 binop("sge", tfloat, "", "(src0 >= src1) ? 1.0f : 0.0f") # Set on Greater or Equal
423 binop("seq", tfloat, commutative, "(src0 == src1) ? 1.0f : 0.0f") # Set on Equal
424 binop("sne", tfloat, commutative, "(src0 != src1) ? 1.0f : 0.0f") # Set on Not Equal
425
426
427 binop("ishl", tint, "", "src0 << src1")
428 binop("ishr", tint, "", "src0 >> src1")
429 binop("ushr", tunsigned, "", "src0 >> src1")
430
431 # bitwise logic operators
432 #
433 # These are also used as boolean and, or, xor for hardware supporting
434 # integers.
435
436
437 binop("iand", tunsigned, commutative + associative, "src0 & src1")
438 binop("ior", tunsigned, commutative + associative, "src0 | src1")
439 binop("ixor", tunsigned, commutative + associative, "src0 ^ src1")
440
441
442 # floating point logic operators
443 #
444 # These use (src != 0.0) for testing the truth of the input, and output 1.0
445 # for true and 0.0 for false
446
447 binop("fand", tfloat, commutative,
448 "((src0 != 0.0f) && (src1 != 0.0f)) ? 1.0f : 0.0f")
449 binop("for", tfloat, commutative,
450 "((src0 != 0.0f) || (src1 != 0.0f)) ? 1.0f : 0.0f")
451 binop("fxor", tfloat, commutative,
452 "(src0 != 0.0f && src1 == 0.0f) || (src0 == 0.0f && src1 != 0.0f) ? 1.0f : 0.0f")
453
454 binop_reduce("fdot", 1, tfloat, tfloat, "{src0} * {src1}", "{src0} + {src1}",
455 "{src}")
456
457 binop("fmin", tfloat, "", "fminf(src0, src1)")
458 binop("imin", tint, commutative + associative, "src1 > src0 ? src0 : src1")
459 binop("umin", tunsigned, commutative + associative, "src1 > src0 ? src0 : src1")
460 binop("fmax", tfloat, "", "fmaxf(src0, src1)")
461 binop("imax", tint, commutative + associative, "src1 > src0 ? src1 : src0")
462 binop("umax", tunsigned, commutative + associative, "src1 > src0 ? src1 : src0")
463
464 binop("fpow", tfloat, "", "powf(src0, src1)")
465
466 binop_horiz("pack_half_2x16_split", 1, tunsigned, 1, tfloat, 1, tfloat,
467 "pack_half_1x16(src0.x) | (pack_half_1x16(src1.x) << 16)")
468
469 binop_convert("bfm", tunsigned, tint, "", """
470 int offset = src0, bits = src1;
471 if (offset < 0 || bits < 0 || offset + bits > 32)
472 dst = 0; /* undefined per the spec */
473 else
474 dst = ((1 << bits)- 1) << offset;
475 """)
476
477 opcode("ldexp", 0, tfloat, [0, 0], [tfloat, tint], "", """
478 dst = ldexp(src0, src1);
479 /* flush denormals to zero. */
480 if (!isnormal(dst))
481 dst = copysign(0.0f, src0);
482 """)
483
484 # Combines the first component of each input to make a 2-component vector.
485
486 binop_horiz("vec2", 2, tunsigned, 1, tunsigned, 1, tunsigned, """
487 dst.x = src0.x;
488 dst.y = src1.x;
489 """)
490
491 def triop(name, ty, const_expr):
492 opcode(name, 0, ty, [0, 0, 0], [ty, ty, ty], "", const_expr)
493 def triop_horiz(name, output_size, src1_size, src2_size, src3_size, const_expr):
494 opcode(name, output_size, tunsigned,
495 [src1_size, src2_size, src3_size],
496 [tunsigned, tunsigned, tunsigned], "", const_expr)
497
498 triop("ffma", tfloat, "src0 * src1 + src2")
499
500 triop("flrp", tfloat, "src0 * (1 - src2) + src1 * src2")
501
502 # Conditional Select
503 #
504 # A vector conditional select instruction (like ?:, but operating per-
505 # component on vectors). There are two versions, one for floating point
506 # bools (0.0 vs 1.0) and one for integer bools (0 vs ~0).
507
508
509 triop("fcsel", tfloat, "(src0 != 0.0f) ? src1 : src2")
510 opcode("bcsel", 0, tunsigned, [0, 0, 0],
511 [tbool, tunsigned, tunsigned], "", "src0 ? src1 : src2")
512
513 triop("bfi", tunsigned, """
514 unsigned mask = src0, insert = src1 & mask, base = src2;
515 if (mask == 0) {
516 dst = base;
517 } else {
518 unsigned tmp = mask;
519 while (!(tmp & 1)) {
520 tmp >>= 1;
521 insert <<= 1;
522 }
523 dst = (base & ~mask) | insert;
524 }
525 """)
526
527 opcode("ubitfield_extract", 0, tunsigned,
528 [0, 1, 1], [tunsigned, tint, tint], "", """
529 unsigned base = src0;
530 int offset = src1.x, bits = src2.x;
531 if (bits == 0) {
532 dst = 0;
533 } else if (bits < 0 || offset < 0 || offset + bits > 32) {
534 dst = 0; /* undefined per the spec */
535 } else {
536 dst = (base >> offset) & ((1 << bits) - 1);
537 }
538 """)
539 opcode("ibitfield_extract", 0, tint,
540 [0, 1, 1], [tint, tint, tint], "", """
541 int base = src0;
542 int offset = src1.x, bits = src2.x;
543 if (bits == 0) {
544 dst = 0;
545 } else if (offset < 0 || bits < 0 || offset + bits > 32) {
546 dst = 0;
547 } else {
548 dst = (base << (32 - offset - bits)) >> offset; /* use sign-extending shift */
549 }
550 """)
551
552 # Combines the first component of each input to make a 3-component vector.
553
554 triop_horiz("vec3", 3, 1, 1, 1, """
555 dst.x = src0.x;
556 dst.y = src1.x;
557 dst.z = src2.x;
558 """)
559
560 def quadop_horiz(name, output_size, src1_size, src2_size, src3_size,
561 src4_size, const_expr):
562 opcode(name, output_size, tunsigned,
563 [src1_size, src2_size, src3_size, src4_size],
564 [tunsigned, tunsigned, tunsigned, tunsigned],
565 "", const_expr)
566
567 opcode("bitfield_insert", 0, tunsigned, [0, 0, 1, 1],
568 [tunsigned, tunsigned, tint, tint], "", """
569 unsigned base = src0, insert = src1;
570 int offset = src2.x, bits = src3.x;
571 if (bits == 0) {
572 dst = 0;
573 } else if (offset < 0 || bits < 0 || bits + offset > 32) {
574 dst = 0;
575 } else {
576 unsigned mask = ((1 << bits) - 1) << offset;
577 dst = (base & ~mask) | ((insert << bits) & mask);
578 }
579 """)
580
581 quadop_horiz("vec4", 4, 1, 1, 1, 1, """
582 dst.x = src0.x;
583 dst.y = src1.x;
584 dst.z = src2.x;
585 dst.w = src3.x;
586 """)
587
588