1/**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE, INC AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28#ifndef TGSI_UREG_H
29#define TGSI_UREG_H
30
31#include "pipe/p_defines.h"
32#include "pipe/p_format.h"
33#include "pipe/p_compiler.h"
34#include "pipe/p_shader_tokens.h"
35#include "util/u_debug.h"
36
37#ifdef __cplusplus
38extern "C" {
39#endif
40
41struct pipe_screen;
42struct ureg_program;
43struct pipe_stream_output_info;
44struct shader_info;
45
46/* Almost a tgsi_src_register, but we need to pull in the Absolute
47 * flag from the _ext token.  Indirect flag always implies ADDR[0].
48 */
49struct ureg_src
50{
51   unsigned File             : 4;  /* TGSI_FILE_ */
52   unsigned SwizzleX         : 2;  /* TGSI_SWIZZLE_ */
53   unsigned SwizzleY         : 2;  /* TGSI_SWIZZLE_ */
54   unsigned SwizzleZ         : 2;  /* TGSI_SWIZZLE_ */
55   unsigned SwizzleW         : 2;  /* TGSI_SWIZZLE_ */
56   unsigned Indirect         : 1;  /* BOOL */
57   unsigned DimIndirect      : 1;  /* BOOL */
58   unsigned Dimension        : 1;  /* BOOL */
59   unsigned Absolute         : 1;  /* BOOL */
60   unsigned Negate           : 1;  /* BOOL */
61   unsigned IndirectFile     : 4;  /* TGSI_FILE_ */
62   unsigned IndirectSwizzle  : 2;  /* TGSI_SWIZZLE_ */
63   unsigned DimIndFile       : 4;  /* TGSI_FILE_ */
64   unsigned DimIndSwizzle    : 2;  /* TGSI_SWIZZLE_ */
65   int      Index            : 16; /* SINT */
66   int      IndirectIndex    : 16; /* SINT */
67   int      DimensionIndex   : 16; /* SINT */
68   int      DimIndIndex      : 16; /* SINT */
69   unsigned ArrayID          : 10; /* UINT */
70};
71
72/* Very similar to a tgsi_dst_register, removing unsupported fields
73 * and adding a Saturate flag.  It's easier to push saturate into the
74 * destination register than to try and create a _SAT variant of each
75 * instruction function.
76 */
77struct ureg_dst
78{
79   unsigned File            : 4;  /* TGSI_FILE_ */
80   unsigned WriteMask       : 4;  /* TGSI_WRITEMASK_ */
81   unsigned Indirect        : 1;  /* BOOL */
82   unsigned DimIndirect     : 1;  /* BOOL */
83   unsigned Dimension       : 1;  /* BOOL */
84   unsigned Saturate        : 1;  /* BOOL */
85   unsigned Invariant       : 1;  /* BOOL */
86   int      Index           : 16; /* SINT */
87   int      IndirectIndex   : 16; /* SINT */
88   unsigned IndirectFile    : 4;  /* TGSI_FILE_ */
89   int      IndirectSwizzle : 2;  /* TGSI_SWIZZLE_ */
90   unsigned DimIndFile      : 4;  /* TGSI_FILE_ */
91   unsigned DimIndSwizzle   : 2;  /* TGSI_SWIZZLE_ */
92   int      DimensionIndex  : 16; /* SINT */
93   int      DimIndIndex     : 16; /* SINT */
94   unsigned ArrayID         : 10; /* UINT */
95};
96
97struct pipe_context;
98
99struct ureg_program *
100ureg_create(enum pipe_shader_type processor);
101
102struct ureg_program *
103ureg_create_with_screen(enum pipe_shader_type processor,
104                        struct pipe_screen *screen);
105
106const struct tgsi_token *
107ureg_finalize( struct ureg_program * );
108
109/* Create and return a shader:
110 */
111void *
112ureg_create_shader( struct ureg_program *,
113                    struct pipe_context *pipe,
114		    const struct pipe_stream_output_info *so );
115
116void
117ureg_set_next_shader_processor(struct ureg_program *ureg, unsigned processor);
118
119/* Alternately, return the built token stream and hand ownership of
120 * that memory to the caller:
121 */
122const struct tgsi_token *
123ureg_get_tokens( struct ureg_program *ureg,
124                 unsigned *nr_tokens );
125
126/*
127 * Returns the number of currently declared outputs.
128 */
129unsigned
130ureg_get_nr_outputs( const struct ureg_program *ureg );
131
132
133/* Free the tokens created by ureg_get_tokens() */
134void ureg_free_tokens( const struct tgsi_token *tokens );
135
136
137void
138ureg_destroy( struct ureg_program * );
139
140void ureg_set_precise( struct ureg_program *ureg, bool precise );
141
142/***********************************************************************
143 * Convenience routine:
144 */
145static inline void *
146ureg_create_shader_with_so_and_destroy( struct ureg_program *p,
147			struct pipe_context *pipe,
148			const struct pipe_stream_output_info *so )
149{
150   void *result = ureg_create_shader( p, pipe, so );
151   ureg_destroy( p );
152   return result;
153}
154
155static inline void *
156ureg_create_shader_and_destroy( struct ureg_program *p,
157                                struct pipe_context *pipe )
158{
159   return ureg_create_shader_with_so_and_destroy(p, pipe, NULL);
160}
161
162
163/***********************************************************************
164 * Build shader properties:
165 */
166
167void
168ureg_property(struct ureg_program *ureg, unsigned name, unsigned value);
169
170
171/***********************************************************************
172 * Build shader declarations:
173 */
174
175struct ureg_src
176ureg_DECL_fs_input_centroid_layout(struct ureg_program *,
177                       enum tgsi_semantic semantic_name,
178                       unsigned semantic_index,
179                       enum tgsi_interpolate_mode interp_mode,
180                       enum tgsi_interpolate_loc interp_location,
181                       unsigned index,
182                       unsigned usage_mask,
183                       unsigned array_id,
184                       unsigned array_size);
185
186struct ureg_src
187ureg_DECL_fs_input_centroid(struct ureg_program *,
188                       enum tgsi_semantic semantic_name,
189                       unsigned semantic_index,
190                       enum tgsi_interpolate_mode interp_mode,
191                       enum tgsi_interpolate_loc interp_location,
192                       unsigned array_id,
193                       unsigned array_size);
194
195static inline struct ureg_src
196ureg_DECL_fs_input(struct ureg_program *ureg,
197                   enum tgsi_semantic semantic_name,
198                   unsigned semantic_index,
199                   enum tgsi_interpolate_mode interp_mode)
200{
201   return ureg_DECL_fs_input_centroid(ureg,
202                                 semantic_name,
203                                 semantic_index,
204                                 interp_mode,
205                                 TGSI_INTERPOLATE_LOC_CENTER, 0, 1);
206}
207
208struct ureg_src
209ureg_DECL_vs_input( struct ureg_program *,
210                    unsigned index );
211
212struct ureg_src
213ureg_DECL_input_layout(struct ureg_program *,
214                enum tgsi_semantic semantic_name,
215                unsigned semantic_index,
216                unsigned index,
217                unsigned usage_mask,
218                unsigned array_id,
219                unsigned array_size);
220
221struct ureg_src
222ureg_DECL_input(struct ureg_program *,
223                enum tgsi_semantic semantic_name,
224                unsigned semantic_index,
225                unsigned array_id,
226                unsigned array_size);
227
228struct ureg_src
229ureg_DECL_system_value(struct ureg_program *,
230                       enum tgsi_semantic semantic_name,
231                       unsigned semantic_index);
232
233struct ureg_dst
234ureg_DECL_output_layout(struct ureg_program *,
235                        enum tgsi_semantic semantic_name,
236                        unsigned semantic_index,
237                        unsigned streams,
238                        unsigned index,
239                        unsigned usage_mask,
240                        unsigned array_id,
241                        unsigned array_size,
242                        boolean invariant);
243
244struct ureg_dst
245ureg_DECL_output_masked(struct ureg_program *,
246                        enum tgsi_semantic semantic_name,
247                        unsigned semantic_index,
248                        unsigned usage_mask,
249                        unsigned array_id,
250                        unsigned array_size);
251
252struct ureg_dst
253ureg_DECL_output(struct ureg_program *,
254                 enum tgsi_semantic semantic_name,
255                 unsigned semantic_index);
256
257struct ureg_dst
258ureg_DECL_output_array(struct ureg_program *ureg,
259                       enum tgsi_semantic semantic_name,
260                       unsigned semantic_index,
261                       unsigned array_id,
262                       unsigned array_size);
263
264struct ureg_src
265ureg_DECL_immediate( struct ureg_program *,
266                     const float *v,
267                     unsigned nr );
268
269struct ureg_src
270ureg_DECL_immediate_f64( struct ureg_program *,
271                         const double *v,
272                         unsigned nr );
273
274struct ureg_src
275ureg_DECL_immediate_uint( struct ureg_program *,
276                          const unsigned *v,
277                          unsigned nr );
278
279struct ureg_src
280ureg_DECL_immediate_block_uint( struct ureg_program *,
281                                const unsigned *v,
282                                unsigned nr );
283
284struct ureg_src
285ureg_DECL_immediate_int( struct ureg_program *,
286                         const int *v,
287                         unsigned nr );
288
289struct ureg_src
290ureg_DECL_immediate_uint64( struct ureg_program *,
291                            const uint64_t *v,
292                            unsigned nr );
293
294struct ureg_src
295ureg_DECL_immediate_int64( struct ureg_program *,
296                           const int64_t *v,
297                           unsigned nr );
298
299void
300ureg_DECL_constant2D(struct ureg_program *ureg,
301                     unsigned first,
302                     unsigned last,
303                     unsigned index2D);
304
305struct ureg_src
306ureg_DECL_constant( struct ureg_program *,
307                    unsigned index );
308
309void
310ureg_DECL_hw_atomic(struct ureg_program *ureg,
311                    unsigned first,
312                    unsigned last,
313                    unsigned buffer_id,
314                    unsigned array_id);
315
316struct ureg_dst
317ureg_DECL_temporary( struct ureg_program * );
318
319/**
320 * Emit a temporary with the LOCAL declaration flag set.  For use when
321 * the register value is not required to be preserved across
322 * subroutine boundaries.
323 */
324struct ureg_dst
325ureg_DECL_local_temporary( struct ureg_program * );
326
327/**
328 * Declare "size" continuous temporary registers.
329 */
330struct ureg_dst
331ureg_DECL_array_temporary( struct ureg_program *,
332                           unsigned size,
333                           boolean local );
334
335void
336ureg_release_temporary( struct ureg_program *ureg,
337                        struct ureg_dst tmp );
338
339struct ureg_dst
340ureg_DECL_address( struct ureg_program * );
341
342/* Supply an index to the sampler declaration as this is the hook to
343 * the external pipe_sampler state.  Users of this function probably
344 * don't want just any sampler, but a specific one which they've set
345 * up state for in the context.
346 */
347struct ureg_src
348ureg_DECL_sampler( struct ureg_program *,
349                   unsigned index );
350
351struct ureg_src
352ureg_DECL_sampler_view(struct ureg_program *,
353                       unsigned index,
354                       enum tgsi_texture_type target,
355                       enum tgsi_return_type return_type_x,
356                       enum tgsi_return_type return_type_y,
357                       enum tgsi_return_type return_type_z,
358                       enum tgsi_return_type return_type_w );
359
360struct ureg_src
361ureg_DECL_image(struct ureg_program *ureg,
362                unsigned index,
363                enum tgsi_texture_type target,
364                enum pipe_format format,
365                boolean wr,
366                boolean raw);
367
368struct ureg_src
369ureg_DECL_buffer(struct ureg_program *ureg, unsigned nr, bool atomic);
370
371struct ureg_src
372ureg_DECL_memory(struct ureg_program *ureg, unsigned memory_type);
373
374static inline struct ureg_src
375ureg_imm4f( struct ureg_program *ureg,
376                       float a, float b,
377                       float c, float d)
378{
379   float v[4];
380   v[0] = a;
381   v[1] = b;
382   v[2] = c;
383   v[3] = d;
384   return ureg_DECL_immediate( ureg, v, 4 );
385}
386
387static inline struct ureg_src
388ureg_imm3f( struct ureg_program *ureg,
389                       float a, float b,
390                       float c)
391{
392   float v[3];
393   v[0] = a;
394   v[1] = b;
395   v[2] = c;
396   return ureg_DECL_immediate( ureg, v, 3 );
397}
398
399static inline struct ureg_src
400ureg_imm2f( struct ureg_program *ureg,
401                       float a, float b)
402{
403   float v[2];
404   v[0] = a;
405   v[1] = b;
406   return ureg_DECL_immediate( ureg, v, 2 );
407}
408
409static inline struct ureg_src
410ureg_imm1f( struct ureg_program *ureg,
411                       float a)
412{
413   float v[1];
414   v[0] = a;
415   return ureg_DECL_immediate( ureg, v, 1 );
416}
417
418static inline struct ureg_src
419ureg_imm4u( struct ureg_program *ureg,
420            unsigned a, unsigned b,
421            unsigned c, unsigned d)
422{
423   unsigned v[4];
424   v[0] = a;
425   v[1] = b;
426   v[2] = c;
427   v[3] = d;
428   return ureg_DECL_immediate_uint( ureg, v, 4 );
429}
430
431static inline struct ureg_src
432ureg_imm3u( struct ureg_program *ureg,
433            unsigned a, unsigned b,
434            unsigned c)
435{
436   unsigned v[3];
437   v[0] = a;
438   v[1] = b;
439   v[2] = c;
440   return ureg_DECL_immediate_uint( ureg, v, 3 );
441}
442
443static inline struct ureg_src
444ureg_imm2u( struct ureg_program *ureg,
445            unsigned a, unsigned b)
446{
447   unsigned v[2];
448   v[0] = a;
449   v[1] = b;
450   return ureg_DECL_immediate_uint( ureg, v, 2 );
451}
452
453static inline struct ureg_src
454ureg_imm1u( struct ureg_program *ureg,
455            unsigned a)
456{
457   return ureg_DECL_immediate_uint( ureg, &a, 1 );
458}
459
460static inline struct ureg_src
461ureg_imm4i( struct ureg_program *ureg,
462            int a, int b,
463            int c, int d)
464{
465   int v[4];
466   v[0] = a;
467   v[1] = b;
468   v[2] = c;
469   v[3] = d;
470   return ureg_DECL_immediate_int( ureg, v, 4 );
471}
472
473static inline struct ureg_src
474ureg_imm3i( struct ureg_program *ureg,
475            int a, int b,
476            int c)
477{
478   int v[3];
479   v[0] = a;
480   v[1] = b;
481   v[2] = c;
482   return ureg_DECL_immediate_int( ureg, v, 3 );
483}
484
485static inline struct ureg_src
486ureg_imm2i( struct ureg_program *ureg,
487            int a, int b)
488{
489   int v[2];
490   v[0] = a;
491   v[1] = b;
492   return ureg_DECL_immediate_int( ureg, v, 2 );
493}
494
495static inline struct ureg_src
496ureg_imm1i( struct ureg_program *ureg,
497            int a)
498{
499   return ureg_DECL_immediate_int( ureg, &a, 1 );
500}
501
502/* Where the destination register has a valid file, but an empty
503 * writemask.
504 */
505static inline boolean
506ureg_dst_is_empty( struct ureg_dst dst )
507{
508   return dst.File != TGSI_FILE_NULL &&
509          dst.WriteMask == 0;
510}
511
512/***********************************************************************
513 * Functions for patching up labels
514 */
515
516
517/* Will return a number which can be used in a label to point to the
518 * next instruction to be emitted.
519 */
520unsigned
521ureg_get_instruction_number( struct ureg_program *ureg );
522
523
524/* Patch a given label (expressed as a token number) to point to a
525 * given instruction (expressed as an instruction number).
526 *
527 * Labels are obtained from instruction emitters, eg ureg_CAL().
528 * Instruction numbers are obtained from ureg_get_instruction_number(),
529 * above.
530 */
531void
532ureg_fixup_label(struct ureg_program *ureg,
533                 unsigned label_token,
534                 unsigned instruction_number );
535
536
537/* Generic instruction emitter.  Use if you need to pass the opcode as
538 * a parameter, rather than using the emit_OP() variants below.
539 */
540void
541ureg_insn(struct ureg_program *ureg,
542          enum tgsi_opcode opcode,
543          const struct ureg_dst *dst,
544          unsigned nr_dst,
545          const struct ureg_src *src,
546          unsigned nr_src,
547          unsigned precise );
548
549
550void
551ureg_tex_insn(struct ureg_program *ureg,
552              enum tgsi_opcode opcode,
553              const struct ureg_dst *dst,
554              unsigned nr_dst,
555              enum tgsi_texture_type target,
556              enum tgsi_return_type return_type,
557              const struct tgsi_texture_offset *texoffsets,
558              unsigned nr_offset,
559              const struct ureg_src *src,
560              unsigned nr_src );
561
562
563void
564ureg_memory_insn(struct ureg_program *ureg,
565                 enum tgsi_opcode opcode,
566                 const struct ureg_dst *dst,
567                 unsigned nr_dst,
568                 const struct ureg_src *src,
569                 unsigned nr_src,
570                 unsigned qualifier,
571                 enum tgsi_texture_type texture,
572                 enum pipe_format format);
573
574/***********************************************************************
575 * Internal instruction helpers, don't call these directly:
576 */
577
578struct ureg_emit_insn_result {
579   unsigned insn_token;       /*< Used to fixup insn size. */
580   unsigned extended_token;   /*< Used to set the Extended bit, usually the same as insn_token. */
581};
582
583struct ureg_emit_insn_result
584ureg_emit_insn(struct ureg_program *ureg,
585               enum tgsi_opcode opcode,
586               boolean saturate,
587               unsigned precise,
588               unsigned num_dst,
589               unsigned num_src);
590
591void
592ureg_emit_label(struct ureg_program *ureg,
593                unsigned insn_token,
594                unsigned *label_token );
595
596void
597ureg_emit_texture(struct ureg_program *ureg,
598                  unsigned insn_token,
599                  enum tgsi_texture_type target,
600                  enum tgsi_return_type return_type,
601                  unsigned num_offsets);
602
603void
604ureg_emit_texture_offset(struct ureg_program *ureg,
605                         const struct tgsi_texture_offset *offset);
606
607void
608ureg_emit_memory(struct ureg_program *ureg,
609                 unsigned insn_token,
610                 unsigned qualifier,
611                 enum tgsi_texture_type texture,
612                 enum pipe_format format);
613
614void
615ureg_emit_dst( struct ureg_program *ureg,
616               struct ureg_dst dst );
617
618void
619ureg_emit_src( struct ureg_program *ureg,
620               struct ureg_src src );
621
622void
623ureg_fixup_insn_size(struct ureg_program *ureg,
624                     unsigned insn );
625
626
627#define OP00( op )                                              \
628static inline void ureg_##op( struct ureg_program *ureg )       \
629{                                                               \
630   enum tgsi_opcode opcode = TGSI_OPCODE_##op;                  \
631   struct ureg_emit_insn_result insn;                           \
632   insn = ureg_emit_insn(ureg,                                  \
633                         opcode,                                \
634                         FALSE,                                 \
635                         0,                                     \
636                         0,                                     \
637                         0);                                    \
638   ureg_fixup_insn_size( ureg, insn.insn_token );               \
639}
640
641#define OP01( op )                                              \
642static inline void ureg_##op( struct ureg_program *ureg,        \
643                              struct ureg_src src )             \
644{                                                               \
645   enum tgsi_opcode opcode = TGSI_OPCODE_##op;                  \
646   struct ureg_emit_insn_result insn;                           \
647   insn = ureg_emit_insn(ureg,                                  \
648                         opcode,                                \
649                         FALSE,                                 \
650                         0,                                     \
651                         0,                                     \
652                         1);                                    \
653   ureg_emit_src( ureg, src );                                  \
654   ureg_fixup_insn_size( ureg, insn.insn_token );               \
655}
656
657#define OP00_LBL( op )                                          \
658static inline void ureg_##op( struct ureg_program *ureg,        \
659                              unsigned *label_token )           \
660{                                                               \
661   enum tgsi_opcode opcode = TGSI_OPCODE_##op;                  \
662   struct ureg_emit_insn_result insn;                           \
663   insn = ureg_emit_insn(ureg,                                  \
664                         opcode,                                \
665                         FALSE,                                 \
666                         0,                                     \
667                         0,                                     \
668                         0);                                    \
669   ureg_emit_label( ureg, insn.extended_token, label_token );   \
670   ureg_fixup_insn_size( ureg, insn.insn_token );               \
671}
672
673#define OP01_LBL( op )                                          \
674static inline void ureg_##op( struct ureg_program *ureg,        \
675                              struct ureg_src src,              \
676                              unsigned *label_token )          \
677{                                                               \
678   enum tgsi_opcode opcode = TGSI_OPCODE_##op;                  \
679   struct ureg_emit_insn_result insn;                           \
680   insn = ureg_emit_insn(ureg,                                  \
681                         opcode,                                \
682                         FALSE,                                 \
683                         0,                                     \
684                         0,                                     \
685                         1);                                    \
686   ureg_emit_label( ureg, insn.extended_token, label_token );   \
687   ureg_emit_src( ureg, src );                                  \
688   ureg_fixup_insn_size( ureg, insn.insn_token );               \
689}
690
691#define OP10( op )                                                      \
692static inline void ureg_##op( struct ureg_program *ureg,                \
693                              struct ureg_dst dst )                     \
694{                                                                       \
695   enum tgsi_opcode opcode = TGSI_OPCODE_##op;                          \
696   struct ureg_emit_insn_result insn;                                   \
697   if (ureg_dst_is_empty(dst))                                          \
698      return;                                                           \
699   insn = ureg_emit_insn(ureg,                                          \
700                         opcode,                                        \
701                         dst.Saturate,                                  \
702                         0,                                             \
703                         1,                                             \
704                         0);                                            \
705   ureg_emit_dst( ureg, dst );                                          \
706   ureg_fixup_insn_size( ureg, insn.insn_token );                       \
707}
708
709
710#define OP11( op )                                                      \
711static inline void ureg_##op( struct ureg_program *ureg,                \
712                              struct ureg_dst dst,                      \
713                              struct ureg_src src )                     \
714{                                                                       \
715   enum tgsi_opcode opcode = TGSI_OPCODE_##op;                          \
716   struct ureg_emit_insn_result insn;                                   \
717   if (ureg_dst_is_empty(dst))                                          \
718      return;                                                           \
719   insn = ureg_emit_insn(ureg,                                          \
720                         opcode,                                        \
721                         dst.Saturate,                                  \
722                         0,                                             \
723                         1,                                             \
724                         1);                                            \
725   ureg_emit_dst( ureg, dst );                                          \
726   ureg_emit_src( ureg, src );                                          \
727   ureg_fixup_insn_size( ureg, insn.insn_token );                       \
728}
729
730#define OP12( op )                                                      \
731static inline void ureg_##op( struct ureg_program *ureg,                \
732                              struct ureg_dst dst,                      \
733                              struct ureg_src src0,                     \
734                              struct ureg_src src1 )                    \
735{                                                                       \
736   enum tgsi_opcode opcode = TGSI_OPCODE_##op;                          \
737   struct ureg_emit_insn_result insn;                                   \
738   if (ureg_dst_is_empty(dst))                                          \
739      return;                                                           \
740   insn = ureg_emit_insn(ureg,                                          \
741                         opcode,                                        \
742                         dst.Saturate,                                  \
743                         0,                                             \
744                         1,                                             \
745                         2);                                            \
746   ureg_emit_dst( ureg, dst );                                          \
747   ureg_emit_src( ureg, src0 );                                         \
748   ureg_emit_src( ureg, src1 );                                         \
749   ureg_fixup_insn_size( ureg, insn.insn_token );                       \
750}
751
752#define OP12_TEX( op )                                                  \
753static inline void ureg_##op( struct ureg_program *ureg,                \
754                              struct ureg_dst dst,                      \
755                              enum tgsi_texture_type target,            \
756                              struct ureg_src src0,                     \
757                              struct ureg_src src1 )                    \
758{                                                                       \
759   enum tgsi_opcode opcode = TGSI_OPCODE_##op;                          \
760   enum tgsi_return_type return_type = TGSI_RETURN_TYPE_UNKNOWN;        \
761   struct ureg_emit_insn_result insn;                                   \
762   if (ureg_dst_is_empty(dst))                                          \
763      return;                                                           \
764   insn = ureg_emit_insn(ureg,                                          \
765                         opcode,                                        \
766                         dst.Saturate,                                  \
767                         0,                                             \
768                         1,                                             \
769                         2);                                            \
770   ureg_emit_texture( ureg, insn.extended_token, target,                \
771                      return_type, 0 );                                 \
772   ureg_emit_dst( ureg, dst );                                          \
773   ureg_emit_src( ureg, src0 );                                         \
774   ureg_emit_src( ureg, src1 );                                         \
775   ureg_fixup_insn_size( ureg, insn.insn_token );                       \
776}
777
778#define OP13( op )                                                      \
779static inline void ureg_##op( struct ureg_program *ureg,                \
780                              struct ureg_dst dst,                      \
781                              struct ureg_src src0,                     \
782                              struct ureg_src src1,                     \
783                              struct ureg_src src2 )                    \
784{                                                                       \
785   enum tgsi_opcode opcode = TGSI_OPCODE_##op;                          \
786   struct ureg_emit_insn_result insn;                                   \
787   if (ureg_dst_is_empty(dst))                                          \
788      return;                                                           \
789   insn = ureg_emit_insn(ureg,                                          \
790                         opcode,                                        \
791                         dst.Saturate,                                  \
792                         0,                                             \
793                         1,                                             \
794                         3);                                            \
795   ureg_emit_dst( ureg, dst );                                          \
796   ureg_emit_src( ureg, src0 );                                         \
797   ureg_emit_src( ureg, src1 );                                         \
798   ureg_emit_src( ureg, src2 );                                         \
799   ureg_fixup_insn_size( ureg, insn.insn_token );                       \
800}
801
802#define OP14( op )                                                      \
803static inline void ureg_##op( struct ureg_program *ureg,                \
804                              struct ureg_dst dst,                      \
805                              struct ureg_src src0,                     \
806                              struct ureg_src src1,                     \
807                              struct ureg_src src2,                     \
808                              struct ureg_src src3 )                    \
809{                                                                       \
810   enum tgsi_opcode opcode = TGSI_OPCODE_##op;                          \
811   struct ureg_emit_insn_result insn;                                   \
812   if (ureg_dst_is_empty(dst))                                          \
813      return;                                                           \
814   insn = ureg_emit_insn(ureg,                                          \
815                         opcode,                                        \
816                         dst.Saturate,                                  \
817                         0,                                             \
818                         1,                                             \
819                         4);                                            \
820   ureg_emit_dst( ureg, dst );                                          \
821   ureg_emit_src( ureg, src0 );                                         \
822   ureg_emit_src( ureg, src1 );                                         \
823   ureg_emit_src( ureg, src2 );                                         \
824   ureg_emit_src( ureg, src3 );                                         \
825   ureg_fixup_insn_size( ureg, insn.insn_token );                       \
826}
827
828#define OP14_TEX( op )                                                  \
829static inline void ureg_##op( struct ureg_program *ureg,                \
830                              struct ureg_dst dst,                      \
831                              enum tgsi_texture_type target,            \
832                              struct ureg_src src0,                     \
833                              struct ureg_src src1,                     \
834                              struct ureg_src src2,                     \
835                              struct ureg_src src3 )                    \
836{                                                                       \
837   enum tgsi_opcode opcode = TGSI_OPCODE_##op;                          \
838   enum tgsi_return_type return_type = TGSI_RETURN_TYPE_UNKNOWN;        \
839   struct ureg_emit_insn_result insn;                                   \
840   if (ureg_dst_is_empty(dst))                                          \
841      return;                                                           \
842   insn = ureg_emit_insn(ureg,                                          \
843                         opcode,                                        \
844                         dst.Saturate,                                  \
845                         0,                                             \
846                         1,                                             \
847                         4);                                            \
848   ureg_emit_texture( ureg, insn.extended_token, target,                \
849                      return_type, 0 );                                 \
850   ureg_emit_dst( ureg, dst );                                          \
851   ureg_emit_src( ureg, src0 );                                         \
852   ureg_emit_src( ureg, src1 );                                         \
853   ureg_emit_src( ureg, src2 );                                         \
854   ureg_emit_src( ureg, src3 );                                         \
855   ureg_fixup_insn_size( ureg, insn.insn_token );                       \
856}
857
858/* Use a template include to generate a correctly-typed ureg_OP()
859 * function for each TGSI opcode:
860 */
861#include "tgsi_opcode_tmp.h"
862
863
864/***********************************************************************
865 * Inline helpers for manipulating register structs:
866 */
867static inline struct ureg_src
868ureg_negate( struct ureg_src reg )
869{
870   assert(reg.File != TGSI_FILE_NULL);
871   reg.Negate ^= 1;
872   return reg;
873}
874
875static inline struct ureg_src
876ureg_abs( struct ureg_src reg )
877{
878   assert(reg.File != TGSI_FILE_NULL);
879   reg.Absolute = 1;
880   reg.Negate = 0;
881   return reg;
882}
883
884static inline struct ureg_src
885ureg_swizzle( struct ureg_src reg,
886              int x, int y, int z, int w )
887{
888   unsigned swz = ( (reg.SwizzleX << 0) |
889                    (reg.SwizzleY << 2) |
890                    (reg.SwizzleZ << 4) |
891                    (reg.SwizzleW << 6));
892
893   assert(reg.File != TGSI_FILE_NULL);
894   assert(x < 4);
895   assert(y < 4);
896   assert(z < 4);
897   assert(w < 4);
898
899   reg.SwizzleX = (swz >> (x*2)) & 0x3;
900   reg.SwizzleY = (swz >> (y*2)) & 0x3;
901   reg.SwizzleZ = (swz >> (z*2)) & 0x3;
902   reg.SwizzleW = (swz >> (w*2)) & 0x3;
903   return reg;
904}
905
906static inline struct ureg_src
907ureg_scalar( struct ureg_src reg, int x )
908{
909   return ureg_swizzle(reg, x, x, x, x);
910}
911
912static inline struct ureg_dst
913ureg_writemask( struct ureg_dst reg,
914                unsigned writemask )
915{
916   assert(reg.File != TGSI_FILE_NULL);
917   reg.WriteMask &= writemask;
918   return reg;
919}
920
921static inline struct ureg_dst
922ureg_saturate( struct ureg_dst reg )
923{
924   assert(reg.File != TGSI_FILE_NULL);
925   reg.Saturate = 1;
926   return reg;
927}
928
929static inline struct ureg_dst
930ureg_dst_indirect( struct ureg_dst reg, struct ureg_src addr )
931{
932   assert(reg.File != TGSI_FILE_NULL);
933   reg.Indirect = 1;
934   reg.IndirectFile = addr.File;
935   reg.IndirectIndex = addr.Index;
936   reg.IndirectSwizzle = addr.SwizzleX;
937   return reg;
938}
939
940static inline struct ureg_src
941ureg_src_indirect( struct ureg_src reg, struct ureg_src addr )
942{
943   assert(reg.File != TGSI_FILE_NULL);
944   reg.Indirect = 1;
945   reg.IndirectFile = addr.File;
946   reg.IndirectIndex = addr.Index;
947   reg.IndirectSwizzle = addr.SwizzleX;
948   return reg;
949}
950
951static inline struct ureg_dst
952ureg_dst_dimension( struct ureg_dst reg, int index )
953{
954   assert(reg.File != TGSI_FILE_NULL);
955   reg.Dimension = 1;
956   reg.DimIndirect = 0;
957   reg.DimensionIndex = index;
958   return reg;
959}
960
961static inline struct ureg_src
962ureg_src_dimension( struct ureg_src reg, int index )
963{
964   assert(reg.File != TGSI_FILE_NULL);
965   reg.Dimension = 1;
966   reg.DimIndirect = 0;
967   reg.DimensionIndex = index;
968   return reg;
969}
970
971static inline struct ureg_dst
972ureg_dst_dimension_indirect( struct ureg_dst reg, struct ureg_src addr,
973                             int index )
974{
975   assert(reg.File != TGSI_FILE_NULL);
976   reg.Dimension = 1;
977   reg.DimIndirect = 1;
978   reg.DimensionIndex = index;
979   reg.DimIndFile = addr.File;
980   reg.DimIndIndex = addr.Index;
981   reg.DimIndSwizzle = addr.SwizzleX;
982   return reg;
983}
984
985static inline struct ureg_src
986ureg_src_dimension_indirect( struct ureg_src reg, struct ureg_src addr,
987                             int index )
988{
989   assert(reg.File != TGSI_FILE_NULL);
990   reg.Dimension = 1;
991   reg.DimIndirect = 1;
992   reg.DimensionIndex = index;
993   reg.DimIndFile = addr.File;
994   reg.DimIndIndex = addr.Index;
995   reg.DimIndSwizzle = addr.SwizzleX;
996   return reg;
997}
998
999static inline struct ureg_src
1000ureg_src_array_offset(struct ureg_src reg, int offset)
1001{
1002   reg.Index += offset;
1003   return reg;
1004}
1005
1006static inline struct ureg_dst
1007ureg_dst_array_offset( struct ureg_dst reg, int offset )
1008{
1009   reg.Index += offset;
1010   return reg;
1011}
1012
1013static inline struct ureg_dst
1014ureg_dst_array_register(unsigned file,
1015                        unsigned index,
1016                        unsigned array_id)
1017{
1018   struct ureg_dst dst;
1019
1020   dst.File      = file;
1021   dst.WriteMask = TGSI_WRITEMASK_XYZW;
1022   dst.Indirect  = 0;
1023   dst.IndirectFile = TGSI_FILE_NULL;
1024   dst.IndirectIndex = 0;
1025   dst.IndirectSwizzle = 0;
1026   dst.Saturate  = 0;
1027   dst.Index     = index;
1028   dst.Dimension = 0;
1029   dst.DimensionIndex = 0;
1030   dst.DimIndirect = 0;
1031   dst.DimIndFile = TGSI_FILE_NULL;
1032   dst.DimIndIndex = 0;
1033   dst.DimIndSwizzle = 0;
1034   dst.ArrayID = array_id;
1035   dst.Invariant = 0;
1036
1037   return dst;
1038}
1039
1040static inline struct ureg_dst
1041ureg_dst_register(unsigned file,
1042                  unsigned index)
1043{
1044   return ureg_dst_array_register(file, index, 0);
1045}
1046
1047static inline struct ureg_dst
1048ureg_dst( struct ureg_src src )
1049{
1050   struct ureg_dst dst;
1051
1052   dst.File      = src.File;
1053   dst.WriteMask = TGSI_WRITEMASK_XYZW;
1054   dst.IndirectFile = src.IndirectFile;
1055   dst.Indirect  = src.Indirect;
1056   dst.IndirectIndex = src.IndirectIndex;
1057   dst.IndirectSwizzle = src.IndirectSwizzle;
1058   dst.Saturate  = 0;
1059   dst.Index     = src.Index;
1060   dst.Dimension = src.Dimension;
1061   dst.DimensionIndex = src.DimensionIndex;
1062   dst.DimIndirect = src.DimIndirect;
1063   dst.DimIndFile = src.DimIndFile;
1064   dst.DimIndIndex = src.DimIndIndex;
1065   dst.DimIndSwizzle = src.DimIndSwizzle;
1066   dst.ArrayID = src.ArrayID;
1067   dst.Invariant = 0;
1068
1069   return dst;
1070}
1071
1072static inline struct ureg_src
1073ureg_src_array_register(unsigned file,
1074                        unsigned index,
1075                        unsigned array_id)
1076{
1077   struct ureg_src src;
1078
1079   src.File = file;
1080   src.SwizzleX = TGSI_SWIZZLE_X;
1081   src.SwizzleY = TGSI_SWIZZLE_Y;
1082   src.SwizzleZ = TGSI_SWIZZLE_Z;
1083   src.SwizzleW = TGSI_SWIZZLE_W;
1084   src.Indirect = 0;
1085   src.IndirectFile = TGSI_FILE_NULL;
1086   src.IndirectIndex = 0;
1087   src.IndirectSwizzle = 0;
1088   src.Absolute = 0;
1089   src.Index = index;
1090   src.Negate = 0;
1091   src.Dimension = 0;
1092   src.DimensionIndex = 0;
1093   src.DimIndirect = 0;
1094   src.DimIndFile = TGSI_FILE_NULL;
1095   src.DimIndIndex = 0;
1096   src.DimIndSwizzle = 0;
1097   src.ArrayID = array_id;
1098
1099   return src;
1100}
1101
1102static inline struct ureg_src
1103ureg_src_register(unsigned file,
1104                  unsigned index)
1105{
1106   return ureg_src_array_register(file, index, 0);
1107}
1108
1109static inline struct ureg_src
1110ureg_src( struct ureg_dst dst )
1111{
1112   struct ureg_src src;
1113
1114   src.File      = dst.File;
1115   src.SwizzleX  = TGSI_SWIZZLE_X;
1116   src.SwizzleY  = TGSI_SWIZZLE_Y;
1117   src.SwizzleZ  = TGSI_SWIZZLE_Z;
1118   src.SwizzleW  = TGSI_SWIZZLE_W;
1119   src.Indirect  = dst.Indirect;
1120   src.IndirectFile = dst.IndirectFile;
1121   src.IndirectIndex = dst.IndirectIndex;
1122   src.IndirectSwizzle = dst.IndirectSwizzle;
1123   src.Absolute  = 0;
1124   src.Index     = dst.Index;
1125   src.Negate    = 0;
1126   src.Dimension = dst.Dimension;
1127   src.DimensionIndex = dst.DimensionIndex;
1128   src.DimIndirect = dst.DimIndirect;
1129   src.DimIndFile = dst.DimIndFile;
1130   src.DimIndIndex = dst.DimIndIndex;
1131   src.DimIndSwizzle = dst.DimIndSwizzle;
1132   src.ArrayID = dst.ArrayID;
1133
1134   return src;
1135}
1136
1137
1138
1139static inline struct ureg_dst
1140ureg_dst_undef( void )
1141{
1142   struct ureg_dst dst;
1143
1144   dst.File      = TGSI_FILE_NULL;
1145   dst.WriteMask = 0;
1146   dst.Indirect  = 0;
1147   dst.IndirectFile = TGSI_FILE_NULL;
1148   dst.IndirectIndex = 0;
1149   dst.IndirectSwizzle = 0;
1150   dst.Saturate  = 0;
1151   dst.Index     = 0;
1152   dst.Dimension = 0;
1153   dst.DimensionIndex = 0;
1154   dst.DimIndirect = 0;
1155   dst.DimIndFile = TGSI_FILE_NULL;
1156   dst.DimIndIndex = 0;
1157   dst.DimIndSwizzle = 0;
1158   dst.ArrayID = 0;
1159   dst.Invariant = 0;
1160
1161   return dst;
1162}
1163
1164static inline struct ureg_src
1165ureg_src_undef( void )
1166{
1167   struct ureg_src src;
1168
1169   src.File      = TGSI_FILE_NULL;
1170   src.SwizzleX  = 0;
1171   src.SwizzleY  = 0;
1172   src.SwizzleZ  = 0;
1173   src.SwizzleW  = 0;
1174   src.Indirect  = 0;
1175   src.IndirectFile = TGSI_FILE_NULL;
1176   src.IndirectIndex = 0;
1177   src.IndirectSwizzle = 0;
1178   src.Absolute  = 0;
1179   src.Index     = 0;
1180   src.Negate    = 0;
1181   src.Dimension = 0;
1182   src.DimensionIndex = 0;
1183   src.DimIndirect = 0;
1184   src.DimIndFile = TGSI_FILE_NULL;
1185   src.DimIndIndex = 0;
1186   src.DimIndSwizzle = 0;
1187   src.ArrayID = 0;
1188
1189   return src;
1190}
1191
1192static inline boolean
1193ureg_src_is_undef( struct ureg_src src )
1194{
1195   return src.File == TGSI_FILE_NULL;
1196}
1197
1198static inline boolean
1199ureg_dst_is_undef( struct ureg_dst dst )
1200{
1201   return dst.File == TGSI_FILE_NULL;
1202}
1203
1204void
1205ureg_setup_shader_info(struct ureg_program *ureg,
1206                       const struct shader_info *info);
1207
1208#ifdef __cplusplus
1209}
1210#endif
1211
1212#endif
1213