tgsi_ureg.h revision c9c8a5ed02408495b3132cabd7947cc352a117a2
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_compiler.h"
32#include "pipe/p_shader_tokens.h"
33#include "util/u_debug.h"
34
35#ifdef __cplusplus
36extern "C" {
37#endif
38
39struct ureg_program;
40
41/* Almost a tgsi_src_register, but we need to pull in the Absolute
42 * flag from the _ext token.  Indirect flag always implies ADDR[0].
43 */
44struct ureg_src
45{
46   unsigned File        : 4;  /* TGSI_FILE_ */
47   unsigned SwizzleX    : 2;  /* TGSI_SWIZZLE_ */
48   unsigned SwizzleY    : 2;  /* TGSI_SWIZZLE_ */
49   unsigned SwizzleZ    : 2;  /* TGSI_SWIZZLE_ */
50   unsigned SwizzleW    : 2;  /* TGSI_SWIZZLE_ */
51   unsigned Indirect    : 1;  /* BOOL */
52   unsigned DimIndirect : 1;  /* BOOL */
53   unsigned Dimension   : 1;  /* BOOL */
54   unsigned Absolute    : 1;  /* BOOL */
55   unsigned Negate      : 1;  /* BOOL */
56   int      Index       : 16; /* SINT */
57   unsigned IndirectFile     : 4;  /* TGSI_FILE_ */
58   int      IndirectIndex    : 16; /* SINT */
59   unsigned IndirectSwizzle  : 2;  /* TGSI_SWIZZLE_ */
60   int      DimensionIndex   : 16; /* SINT */
61   unsigned DimIndFile       : 4;  /* TGSI_FILE_ */
62   int      DimIndIndex      : 16; /* SINT */
63   unsigned DimIndSwizzle    : 2;  /* TGSI_SWIZZLE_ */
64};
65
66/* Very similar to a tgsi_dst_register, removing unsupported fields
67 * and adding a Saturate flag.  It's easier to push saturate into the
68 * destination register than to try and create a _SAT varient of each
69 * instruction function.
70 */
71struct ureg_dst
72{
73   unsigned File        : 4;  /* TGSI_FILE_ */
74   unsigned WriteMask   : 4;  /* TGSI_WRITEMASK_ */
75   unsigned Indirect    : 1;  /* BOOL */
76   unsigned Saturate    : 1;  /* BOOL */
77   unsigned Predicate   : 1;
78   unsigned PredNegate  : 1;  /* BOOL */
79   unsigned PredSwizzleX: 2;  /* TGSI_SWIZZLE_ */
80   unsigned PredSwizzleY: 2;  /* TGSI_SWIZZLE_ */
81   unsigned PredSwizzleZ: 2;  /* TGSI_SWIZZLE_ */
82   unsigned PredSwizzleW: 2;  /* TGSI_SWIZZLE_ */
83   int      Index       : 16; /* SINT */
84   int      IndirectIndex   : 16; /* SINT */
85   int      IndirectSwizzle : 2;  /* TGSI_SWIZZLE_ */
86};
87
88struct pipe_context;
89
90struct ureg_program *
91ureg_create( unsigned processor );
92
93const struct tgsi_token *
94ureg_finalize( struct ureg_program * );
95
96/* Create and return a shader:
97 */
98void *
99ureg_create_shader( struct ureg_program *,
100                    struct pipe_context *pipe );
101
102
103/* Alternately, return the built token stream and hand ownership of
104 * that memory to the caller:
105 */
106const struct tgsi_token *
107ureg_get_tokens( struct ureg_program *ureg,
108                 unsigned *nr_tokens );
109
110
111/* Free the tokens created by ureg_get_tokens() */
112void ureg_free_tokens( const struct tgsi_token *tokens );
113
114
115void
116ureg_destroy( struct ureg_program * );
117
118
119/***********************************************************************
120 * Convenience routine:
121 */
122static INLINE void *
123ureg_create_shader_and_destroy( struct ureg_program *p,
124                                struct pipe_context *pipe )
125{
126   void *result = ureg_create_shader( p, pipe );
127   ureg_destroy( p );
128   return result;
129}
130
131
132/***********************************************************************
133 * Build shader properties:
134 */
135
136void
137ureg_property_gs_input_prim(struct ureg_program *ureg,
138                            unsigned input_prim);
139
140void
141ureg_property_gs_output_prim(struct ureg_program *ureg,
142                             unsigned output_prim);
143
144void
145ureg_property_gs_max_vertices(struct ureg_program *ureg,
146                              unsigned max_vertices);
147
148void
149ureg_property_fs_coord_origin(struct ureg_program *ureg,
150                            unsigned fs_coord_origin);
151
152void
153ureg_property_fs_coord_pixel_center(struct ureg_program *ureg,
154                            unsigned fs_coord_pixel_center);
155
156void
157ureg_property_fs_color0_writes_all_cbufs(struct ureg_program *ureg,
158                            unsigned fs_color0_writes_all_cbufs);
159
160/***********************************************************************
161 * Build shader declarations:
162 */
163
164struct ureg_src
165ureg_DECL_fs_input_cyl_centroid(struct ureg_program *,
166                       unsigned semantic_name,
167                       unsigned semantic_index,
168                       unsigned interp_mode,
169                       unsigned cylindrical_wrap,
170                       unsigned centroid);
171
172static INLINE struct ureg_src
173ureg_DECL_fs_input_cyl(struct ureg_program *ureg,
174                       unsigned semantic_name,
175                       unsigned semantic_index,
176                       unsigned interp_mode,
177                       unsigned cylindrical_wrap)
178{
179   return ureg_DECL_fs_input_cyl_centroid(ureg,
180                                 semantic_name,
181                                 semantic_index,
182                                 interp_mode,
183                                 cylindrical_wrap,
184                                 0);
185}
186
187static INLINE struct ureg_src
188ureg_DECL_fs_input(struct ureg_program *ureg,
189                   unsigned semantic_name,
190                   unsigned semantic_index,
191                   unsigned interp_mode)
192{
193   return ureg_DECL_fs_input_cyl_centroid(ureg,
194                                 semantic_name,
195                                 semantic_index,
196                                 interp_mode,
197                                 0, 0);
198}
199
200struct ureg_src
201ureg_DECL_vs_input( struct ureg_program *,
202                    unsigned index );
203
204struct ureg_src
205ureg_DECL_gs_input(struct ureg_program *,
206                   unsigned index,
207                   unsigned semantic_name,
208                   unsigned semantic_index);
209
210struct ureg_src
211ureg_DECL_system_value(struct ureg_program *,
212                       unsigned index,
213                       unsigned semantic_name,
214                       unsigned semantic_index);
215
216struct ureg_dst
217ureg_DECL_output( struct ureg_program *,
218                  unsigned semantic_name,
219                  unsigned semantic_index );
220
221struct ureg_src
222ureg_DECL_immediate( struct ureg_program *,
223                     const float *v,
224                     unsigned nr );
225
226struct ureg_src
227ureg_DECL_immediate_uint( struct ureg_program *,
228                          const unsigned *v,
229                          unsigned nr );
230
231struct ureg_src
232ureg_DECL_immediate_block_uint( struct ureg_program *,
233                                const unsigned *v,
234                                unsigned nr );
235
236struct ureg_src
237ureg_DECL_immediate_int( struct ureg_program *,
238                         const int *v,
239                         unsigned nr );
240
241void
242ureg_DECL_constant2D(struct ureg_program *ureg,
243                     unsigned first,
244                     unsigned last,
245                     unsigned index2D);
246
247struct ureg_src
248ureg_DECL_constant( struct ureg_program *,
249                    unsigned index );
250
251struct ureg_dst
252ureg_DECL_temporary( struct ureg_program * );
253
254void
255ureg_release_temporary( struct ureg_program *ureg,
256                        struct ureg_dst tmp );
257
258struct ureg_dst
259ureg_DECL_address( struct ureg_program * );
260
261struct ureg_dst
262ureg_DECL_predicate(struct ureg_program *);
263
264/* Supply an index to the sampler declaration as this is the hook to
265 * the external pipe_sampler state.  Users of this function probably
266 * don't want just any sampler, but a specific one which they've set
267 * up state for in the context.
268 */
269struct ureg_src
270ureg_DECL_sampler( struct ureg_program *,
271                   unsigned index );
272
273
274static INLINE struct ureg_src
275ureg_imm4f( struct ureg_program *ureg,
276                       float a, float b,
277                       float c, float d)
278{
279   float v[4];
280   v[0] = a;
281   v[1] = b;
282   v[2] = c;
283   v[3] = d;
284   return ureg_DECL_immediate( ureg, v, 4 );
285}
286
287static INLINE struct ureg_src
288ureg_imm3f( struct ureg_program *ureg,
289                       float a, float b,
290                       float c)
291{
292   float v[3];
293   v[0] = a;
294   v[1] = b;
295   v[2] = c;
296   return ureg_DECL_immediate( ureg, v, 3 );
297}
298
299static INLINE struct ureg_src
300ureg_imm2f( struct ureg_program *ureg,
301                       float a, float b)
302{
303   float v[2];
304   v[0] = a;
305   v[1] = b;
306   return ureg_DECL_immediate( ureg, v, 2 );
307}
308
309static INLINE struct ureg_src
310ureg_imm1f( struct ureg_program *ureg,
311                       float a)
312{
313   float v[1];
314   v[0] = a;
315   return ureg_DECL_immediate( ureg, v, 1 );
316}
317
318static INLINE struct ureg_src
319ureg_imm4u( struct ureg_program *ureg,
320            unsigned a, unsigned b,
321            unsigned c, unsigned d)
322{
323   unsigned v[4];
324   v[0] = a;
325   v[1] = b;
326   v[2] = c;
327   v[3] = d;
328   return ureg_DECL_immediate_uint( ureg, v, 4 );
329}
330
331static INLINE struct ureg_src
332ureg_imm3u( struct ureg_program *ureg,
333            unsigned a, unsigned b,
334            unsigned c)
335{
336   unsigned v[3];
337   v[0] = a;
338   v[1] = b;
339   v[2] = c;
340   return ureg_DECL_immediate_uint( ureg, v, 3 );
341}
342
343static INLINE struct ureg_src
344ureg_imm2u( struct ureg_program *ureg,
345            unsigned a, unsigned b)
346{
347   unsigned v[2];
348   v[0] = a;
349   v[1] = b;
350   return ureg_DECL_immediate_uint( ureg, v, 2 );
351}
352
353static INLINE struct ureg_src
354ureg_imm1u( struct ureg_program *ureg,
355            unsigned a)
356{
357   return ureg_DECL_immediate_uint( ureg, &a, 1 );
358}
359
360static INLINE struct ureg_src
361ureg_imm4i( struct ureg_program *ureg,
362            int a, int b,
363            int c, int d)
364{
365   int v[4];
366   v[0] = a;
367   v[1] = b;
368   v[2] = c;
369   v[3] = d;
370   return ureg_DECL_immediate_int( ureg, v, 4 );
371}
372
373static INLINE struct ureg_src
374ureg_imm3i( struct ureg_program *ureg,
375            int a, int b,
376            int c)
377{
378   int v[3];
379   v[0] = a;
380   v[1] = b;
381   v[2] = c;
382   return ureg_DECL_immediate_int( ureg, v, 3 );
383}
384
385static INLINE struct ureg_src
386ureg_imm2i( struct ureg_program *ureg,
387            int a, int b)
388{
389   int v[2];
390   v[0] = a;
391   v[1] = b;
392   return ureg_DECL_immediate_int( ureg, v, 2 );
393}
394
395static INLINE struct ureg_src
396ureg_imm1i( struct ureg_program *ureg,
397            int a)
398{
399   return ureg_DECL_immediate_int( ureg, &a, 1 );
400}
401
402/***********************************************************************
403 * Functions for patching up labels
404 */
405
406
407/* Will return a number which can be used in a label to point to the
408 * next instruction to be emitted.
409 */
410unsigned
411ureg_get_instruction_number( struct ureg_program *ureg );
412
413
414/* Patch a given label (expressed as a token number) to point to a
415 * given instruction (expressed as an instruction number).
416 *
417 * Labels are obtained from instruction emitters, eg ureg_CAL().
418 * Instruction numbers are obtained from ureg_get_instruction_number(),
419 * above.
420 */
421void
422ureg_fixup_label(struct ureg_program *ureg,
423                 unsigned label_token,
424                 unsigned instruction_number );
425
426
427/* Generic instruction emitter.  Use if you need to pass the opcode as
428 * a parameter, rather than using the emit_OP() varients below.
429 */
430void
431ureg_insn(struct ureg_program *ureg,
432          unsigned opcode,
433          const struct ureg_dst *dst,
434          unsigned nr_dst,
435          const struct ureg_src *src,
436          unsigned nr_src );
437
438
439void
440ureg_tex_insn(struct ureg_program *ureg,
441              unsigned opcode,
442              const struct ureg_dst *dst,
443              unsigned nr_dst,
444              unsigned target,
445              const struct ureg_src *src,
446              unsigned nr_src );
447
448
449void
450ureg_label_insn(struct ureg_program *ureg,
451                unsigned opcode,
452                const struct ureg_src *src,
453                unsigned nr_src,
454                unsigned *label);
455
456
457/***********************************************************************
458 * Internal instruction helpers, don't call these directly:
459 */
460
461struct ureg_emit_insn_result {
462   unsigned insn_token;       /*< Used to fixup insn size. */
463   unsigned extended_token;   /*< Used to set the Extended bit, usually the same as insn_token. */
464};
465
466struct ureg_emit_insn_result
467ureg_emit_insn(struct ureg_program *ureg,
468               unsigned opcode,
469               boolean saturate,
470               boolean predicate,
471               boolean pred_negate,
472               unsigned pred_swizzle_x,
473               unsigned pred_swizzle_y,
474               unsigned pred_swizzle_z,
475               unsigned pred_swizzle_w,
476               unsigned num_dst,
477               unsigned num_src );
478
479void
480ureg_emit_label(struct ureg_program *ureg,
481                unsigned insn_token,
482                unsigned *label_token );
483
484void
485ureg_emit_texture(struct ureg_program *ureg,
486                  unsigned insn_token,
487                  unsigned target );
488
489void
490ureg_emit_dst( struct ureg_program *ureg,
491               struct ureg_dst dst );
492
493void
494ureg_emit_src( struct ureg_program *ureg,
495               struct ureg_src src );
496
497void
498ureg_fixup_insn_size(struct ureg_program *ureg,
499                     unsigned insn );
500
501
502#define OP00( op )                                              \
503static INLINE void ureg_##op( struct ureg_program *ureg )       \
504{                                                               \
505   unsigned opcode = TGSI_OPCODE_##op;                          \
506   unsigned insn = ureg_emit_insn(ureg,                         \
507                                  opcode,                       \
508                                  FALSE,                        \
509                                  FALSE,                        \
510                                  FALSE,                        \
511                                  TGSI_SWIZZLE_X,               \
512                                  TGSI_SWIZZLE_Y,               \
513                                  TGSI_SWIZZLE_Z,               \
514                                  TGSI_SWIZZLE_W,               \
515                                  0,                            \
516                                  0).insn_token;                \
517   ureg_fixup_insn_size( ureg, insn );                          \
518}
519
520#define OP01( op )                                              \
521static INLINE void ureg_##op( struct ureg_program *ureg,        \
522                              struct ureg_src src )             \
523{                                                               \
524   unsigned opcode = TGSI_OPCODE_##op;                          \
525   unsigned insn = ureg_emit_insn(ureg,                         \
526                                  opcode,                       \
527                                  FALSE,                        \
528                                  FALSE,                        \
529                                  FALSE,                        \
530                                  TGSI_SWIZZLE_X,               \
531                                  TGSI_SWIZZLE_Y,               \
532                                  TGSI_SWIZZLE_Z,               \
533                                  TGSI_SWIZZLE_W,               \
534                                  0,                            \
535                                  1).insn_token;                \
536   ureg_emit_src( ureg, src );                                  \
537   ureg_fixup_insn_size( ureg, insn );                          \
538}
539
540#define OP00_LBL( op )                                          \
541static INLINE void ureg_##op( struct ureg_program *ureg,        \
542                              unsigned *label_token )           \
543{                                                               \
544   unsigned opcode = TGSI_OPCODE_##op;                          \
545   struct ureg_emit_insn_result insn;                           \
546   insn = ureg_emit_insn(ureg,                                  \
547                         opcode,                                \
548                         FALSE,                                 \
549                         FALSE,                                 \
550                         FALSE,                                 \
551                         TGSI_SWIZZLE_X,                        \
552                         TGSI_SWIZZLE_Y,                        \
553                         TGSI_SWIZZLE_Z,                        \
554                         TGSI_SWIZZLE_W,                        \
555                         0,                                     \
556                         0);                                    \
557   ureg_emit_label( ureg, insn.extended_token, label_token );   \
558   ureg_fixup_insn_size( ureg, insn.insn_token );               \
559}
560
561#define OP01_LBL( op )                                          \
562static INLINE void ureg_##op( struct ureg_program *ureg,        \
563                              struct ureg_src src,              \
564                              unsigned *label_token )          \
565{                                                               \
566   unsigned opcode = TGSI_OPCODE_##op;                          \
567   struct ureg_emit_insn_result insn;                           \
568   insn = ureg_emit_insn(ureg,                                  \
569                         opcode,                                \
570                         FALSE,                                 \
571                         FALSE,                                 \
572                         FALSE,                                 \
573                         TGSI_SWIZZLE_X,                        \
574                         TGSI_SWIZZLE_Y,                        \
575                         TGSI_SWIZZLE_Z,                        \
576                         TGSI_SWIZZLE_W,                        \
577                         0,                                     \
578                         1);                                    \
579   ureg_emit_label( ureg, insn.extended_token, label_token );   \
580   ureg_emit_src( ureg, src );                                  \
581   ureg_fixup_insn_size( ureg, insn.insn_token );               \
582}
583
584#define OP10( op )                                                      \
585static INLINE void ureg_##op( struct ureg_program *ureg,                \
586                              struct ureg_dst dst )                     \
587{                                                                       \
588   unsigned opcode = TGSI_OPCODE_##op;                                  \
589   unsigned insn = ureg_emit_insn(ureg,                                 \
590                                  opcode,                               \
591                                  dst.Saturate,                         \
592                                  dst.Predicate,                        \
593                                  dst.PredNegate,                       \
594                                  dst.PredSwizzleX,                     \
595                                  dst.PredSwizzleY,                     \
596                                  dst.PredSwizzleZ,                     \
597                                  dst.PredSwizzleW,                     \
598                                  1,                                    \
599                                  0).insn_token;                        \
600   ureg_emit_dst( ureg, dst );                                          \
601   ureg_fixup_insn_size( ureg, insn );                                  \
602}
603
604
605#define OP11( op )                                                      \
606static INLINE void ureg_##op( struct ureg_program *ureg,                \
607                              struct ureg_dst dst,                      \
608                              struct ureg_src src )                     \
609{                                                                       \
610   unsigned opcode = TGSI_OPCODE_##op;                                  \
611   unsigned insn = ureg_emit_insn(ureg,                                 \
612                                  opcode,                               \
613                                  dst.Saturate,                         \
614                                  dst.Predicate,                        \
615                                  dst.PredNegate,                       \
616                                  dst.PredSwizzleX,                     \
617                                  dst.PredSwizzleY,                     \
618                                  dst.PredSwizzleZ,                     \
619                                  dst.PredSwizzleW,                     \
620                                  1,                                    \
621                                  1).insn_token;                        \
622   ureg_emit_dst( ureg, dst );                                          \
623   ureg_emit_src( ureg, src );                                          \
624   ureg_fixup_insn_size( ureg, insn );                                  \
625}
626
627#define OP12( op )                                                      \
628static INLINE void ureg_##op( struct ureg_program *ureg,                \
629                              struct ureg_dst dst,                      \
630                              struct ureg_src src0,                     \
631                              struct ureg_src src1 )                    \
632{                                                                       \
633   unsigned opcode = TGSI_OPCODE_##op;                                  \
634   unsigned insn = ureg_emit_insn(ureg,                                 \
635                                  opcode,                               \
636                                  dst.Saturate,                         \
637                                  dst.Predicate,                        \
638                                  dst.PredNegate,                       \
639                                  dst.PredSwizzleX,                     \
640                                  dst.PredSwizzleY,                     \
641                                  dst.PredSwizzleZ,                     \
642                                  dst.PredSwizzleW,                     \
643                                  1,                                    \
644                                  2).insn_token;                        \
645   ureg_emit_dst( ureg, dst );                                          \
646   ureg_emit_src( ureg, src0 );                                         \
647   ureg_emit_src( ureg, src1 );                                         \
648   ureg_fixup_insn_size( ureg, insn );                                  \
649}
650
651#define OP12_TEX( op )                                                  \
652static INLINE void ureg_##op( struct ureg_program *ureg,                \
653                              struct ureg_dst dst,                      \
654                              unsigned target,                          \
655                              struct ureg_src src0,                     \
656                              struct ureg_src src1 )                    \
657{                                                                       \
658   unsigned opcode = TGSI_OPCODE_##op;                                  \
659   struct ureg_emit_insn_result insn;                                   \
660   insn = ureg_emit_insn(ureg,                                          \
661                         opcode,                                        \
662                         dst.Saturate,                                  \
663                         dst.Predicate,                                 \
664                         dst.PredNegate,                                \
665                         dst.PredSwizzleX,                              \
666                         dst.PredSwizzleY,                              \
667                         dst.PredSwizzleZ,                              \
668                         dst.PredSwizzleW,                              \
669                         1,                                             \
670                         2);                                            \
671   ureg_emit_texture( ureg, insn.extended_token, target );              \
672   ureg_emit_dst( ureg, dst );                                          \
673   ureg_emit_src( ureg, src0 );                                         \
674   ureg_emit_src( ureg, src1 );                                         \
675   ureg_fixup_insn_size( ureg, insn.insn_token );                       \
676}
677
678#define OP13( op )                                                      \
679static INLINE void ureg_##op( struct ureg_program *ureg,                \
680                              struct ureg_dst dst,                      \
681                              struct ureg_src src0,                     \
682                              struct ureg_src src1,                     \
683                              struct ureg_src src2 )                    \
684{                                                                       \
685   unsigned opcode = TGSI_OPCODE_##op;                                  \
686   unsigned insn = ureg_emit_insn(ureg,                                 \
687                                  opcode,                               \
688                                  dst.Saturate,                         \
689                                  dst.Predicate,                        \
690                                  dst.PredNegate,                       \
691                                  dst.PredSwizzleX,                     \
692                                  dst.PredSwizzleY,                     \
693                                  dst.PredSwizzleZ,                     \
694                                  dst.PredSwizzleW,                     \
695                                  1,                                    \
696                                  3).insn_token;                        \
697   ureg_emit_dst( ureg, dst );                                          \
698   ureg_emit_src( ureg, src0 );                                         \
699   ureg_emit_src( ureg, src1 );                                         \
700   ureg_emit_src( ureg, src2 );                                         \
701   ureg_fixup_insn_size( ureg, insn );                                  \
702}
703
704#define OP14_TEX( op )                                                  \
705static INLINE void ureg_##op( struct ureg_program *ureg,                \
706                              struct ureg_dst dst,                      \
707                              unsigned target,                          \
708                              struct ureg_src src0,                     \
709                              struct ureg_src src1,                     \
710                              struct ureg_src src2,                     \
711                              struct ureg_src src3 )                    \
712{                                                                       \
713   unsigned opcode = TGSI_OPCODE_##op;                                  \
714   struct ureg_emit_insn_result insn;                                   \
715   insn = ureg_emit_insn(ureg,                                          \
716                         opcode,                                        \
717                         dst.Saturate,                                  \
718                         dst.Predicate,                                 \
719                         dst.PredNegate,                                \
720                         dst.PredSwizzleX,                              \
721                         dst.PredSwizzleY,                              \
722                         dst.PredSwizzleZ,                              \
723                         dst.PredSwizzleW,                              \
724                         1,                                             \
725                         4);                                            \
726   ureg_emit_texture( ureg, insn.extended_token, target );              \
727   ureg_emit_dst( ureg, dst );                                          \
728   ureg_emit_src( ureg, src0 );                                         \
729   ureg_emit_src( ureg, src1 );                                         \
730   ureg_emit_src( ureg, src2 );                                         \
731   ureg_emit_src( ureg, src3 );                                         \
732   ureg_fixup_insn_size( ureg, insn.insn_token );                       \
733}
734
735
736/* Use a template include to generate a correctly-typed ureg_OP()
737 * function for each TGSI opcode:
738 */
739#include "tgsi_opcode_tmp.h"
740
741
742/***********************************************************************
743 * Inline helpers for manipulating register structs:
744 */
745static INLINE struct ureg_src
746ureg_negate( struct ureg_src reg )
747{
748   assert(reg.File != TGSI_FILE_NULL);
749   reg.Negate ^= 1;
750   return reg;
751}
752
753static INLINE struct ureg_src
754ureg_abs( struct ureg_src reg )
755{
756   assert(reg.File != TGSI_FILE_NULL);
757   reg.Absolute = 1;
758   reg.Negate = 0;
759   return reg;
760}
761
762static INLINE struct ureg_src
763ureg_swizzle( struct ureg_src reg,
764              int x, int y, int z, int w )
765{
766   unsigned swz = ( (reg.SwizzleX << 0) |
767                    (reg.SwizzleY << 2) |
768                    (reg.SwizzleZ << 4) |
769                    (reg.SwizzleW << 6));
770
771   assert(reg.File != TGSI_FILE_NULL);
772   assert(x < 4);
773   assert(y < 4);
774   assert(z < 4);
775   assert(w < 4);
776
777   reg.SwizzleX = (swz >> (x*2)) & 0x3;
778   reg.SwizzleY = (swz >> (y*2)) & 0x3;
779   reg.SwizzleZ = (swz >> (z*2)) & 0x3;
780   reg.SwizzleW = (swz >> (w*2)) & 0x3;
781   return reg;
782}
783
784static INLINE struct ureg_src
785ureg_scalar( struct ureg_src reg, int x )
786{
787   return ureg_swizzle(reg, x, x, x, x);
788}
789
790static INLINE struct ureg_dst
791ureg_writemask( struct ureg_dst reg,
792                unsigned writemask )
793{
794   assert(reg.File != TGSI_FILE_NULL);
795   reg.WriteMask &= writemask;
796   return reg;
797}
798
799static INLINE struct ureg_dst
800ureg_saturate( struct ureg_dst reg )
801{
802   assert(reg.File != TGSI_FILE_NULL);
803   reg.Saturate = 1;
804   return reg;
805}
806
807static INLINE struct ureg_dst
808ureg_predicate(struct ureg_dst reg,
809               boolean negate,
810               unsigned swizzle_x,
811               unsigned swizzle_y,
812               unsigned swizzle_z,
813               unsigned swizzle_w)
814{
815   assert(reg.File != TGSI_FILE_NULL);
816   reg.Predicate = 1;
817   reg.PredNegate = negate;
818   reg.PredSwizzleX = swizzle_x;
819   reg.PredSwizzleY = swizzle_y;
820   reg.PredSwizzleZ = swizzle_z;
821   reg.PredSwizzleW = swizzle_w;
822   return reg;
823}
824
825static INLINE struct ureg_dst
826ureg_dst_indirect( struct ureg_dst reg, struct ureg_src addr )
827{
828   assert(reg.File != TGSI_FILE_NULL);
829   assert(addr.File == TGSI_FILE_ADDRESS);
830   reg.Indirect = 1;
831   reg.IndirectIndex = addr.Index;
832   reg.IndirectSwizzle = addr.SwizzleX;
833   return reg;
834}
835
836static INLINE struct ureg_src
837ureg_src_indirect( struct ureg_src reg, struct ureg_src addr )
838{
839   assert(reg.File != TGSI_FILE_NULL);
840   assert(addr.File == TGSI_FILE_ADDRESS || addr.File == TGSI_FILE_TEMPORARY);
841   reg.Indirect = 1;
842   reg.IndirectFile = addr.File;
843   reg.IndirectIndex = addr.Index;
844   reg.IndirectSwizzle = addr.SwizzleX;
845   return reg;
846}
847
848static INLINE struct ureg_src
849ureg_src_dimension( struct ureg_src reg, int index )
850{
851   assert(reg.File != TGSI_FILE_NULL);
852   reg.Dimension = 1;
853   reg.DimIndirect = 0;
854   reg.DimensionIndex = index;
855   return reg;
856}
857
858
859static INLINE struct ureg_src
860ureg_src_dimension_indirect( struct ureg_src reg, struct ureg_src addr,
861                             int index )
862{
863   assert(reg.File != TGSI_FILE_NULL);
864   reg.Dimension = 1;
865   reg.DimIndirect = 1;
866   reg.DimensionIndex = index;
867   reg.DimIndFile = addr.File;
868   reg.DimIndIndex = addr.Index;
869   reg.DimIndSwizzle = addr.SwizzleX;
870   return reg;
871}
872
873static INLINE struct ureg_dst
874ureg_dst( struct ureg_src src )
875{
876   struct ureg_dst dst;
877
878   assert(!src.Indirect || src.IndirectFile == TGSI_FILE_ADDRESS);
879
880   dst.File      = src.File;
881   dst.WriteMask = TGSI_WRITEMASK_XYZW;
882   dst.Indirect  = src.Indirect;
883   dst.IndirectIndex = src.IndirectIndex;
884   dst.IndirectSwizzle = src.IndirectSwizzle;
885   dst.Saturate  = 0;
886   dst.Predicate = 0;
887   dst.PredNegate = 0;
888   dst.PredSwizzleX = TGSI_SWIZZLE_X;
889   dst.PredSwizzleY = TGSI_SWIZZLE_Y;
890   dst.PredSwizzleZ = TGSI_SWIZZLE_Z;
891   dst.PredSwizzleW = TGSI_SWIZZLE_W;
892   dst.Index     = src.Index;
893
894   return dst;
895}
896
897static INLINE struct ureg_src
898ureg_src_register(unsigned file,
899                  unsigned index)
900{
901   struct ureg_src src;
902
903   src.File = file;
904   src.SwizzleX = TGSI_SWIZZLE_X;
905   src.SwizzleY = TGSI_SWIZZLE_Y;
906   src.SwizzleZ = TGSI_SWIZZLE_Z;
907   src.SwizzleW = TGSI_SWIZZLE_W;
908   src.Indirect = 0;
909   src.IndirectFile = TGSI_FILE_NULL;
910   src.IndirectIndex = 0;
911   src.IndirectSwizzle = 0;
912   src.Absolute = 0;
913   src.Index = index;
914   src.Negate = 0;
915   src.Dimension = 0;
916   src.DimensionIndex = 0;
917   src.DimIndirect = 0;
918   src.DimIndFile = TGSI_FILE_NULL;
919   src.DimIndIndex = 0;
920   src.DimIndSwizzle = 0;
921
922   return src;
923}
924
925static INLINE struct ureg_src
926ureg_src( struct ureg_dst dst )
927{
928   struct ureg_src src;
929
930   src.File      = dst.File;
931   src.SwizzleX  = TGSI_SWIZZLE_X;
932   src.SwizzleY  = TGSI_SWIZZLE_Y;
933   src.SwizzleZ  = TGSI_SWIZZLE_Z;
934   src.SwizzleW  = TGSI_SWIZZLE_W;
935   src.Indirect  = dst.Indirect;
936   src.IndirectFile = TGSI_FILE_ADDRESS;
937   src.IndirectIndex = dst.IndirectIndex;
938   src.IndirectSwizzle = dst.IndirectSwizzle;
939   src.Absolute  = 0;
940   src.Index     = dst.Index;
941   src.Negate    = 0;
942   src.Dimension = 0;
943   src.DimensionIndex = 0;
944   src.DimIndirect = 0;
945   src.DimIndFile = TGSI_FILE_NULL;
946   src.DimIndIndex = 0;
947   src.DimIndSwizzle = 0;
948
949   return src;
950}
951
952
953
954static INLINE struct ureg_dst
955ureg_dst_undef( void )
956{
957   struct ureg_dst dst;
958
959   dst.File      = TGSI_FILE_NULL;
960   dst.WriteMask = 0;
961   dst.Indirect  = 0;
962   dst.IndirectIndex = 0;
963   dst.IndirectSwizzle = 0;
964   dst.Saturate  = 0;
965   dst.Predicate = 0;
966   dst.PredNegate = 0;
967   dst.PredSwizzleX = TGSI_SWIZZLE_X;
968   dst.PredSwizzleY = TGSI_SWIZZLE_Y;
969   dst.PredSwizzleZ = TGSI_SWIZZLE_Z;
970   dst.PredSwizzleW = TGSI_SWIZZLE_W;
971   dst.Index     = 0;
972
973   return dst;
974}
975
976static INLINE struct ureg_src
977ureg_src_undef( void )
978{
979   struct ureg_src src;
980
981   src.File      = TGSI_FILE_NULL;
982   src.SwizzleX  = 0;
983   src.SwizzleY  = 0;
984   src.SwizzleZ  = 0;
985   src.SwizzleW  = 0;
986   src.Indirect  = 0;
987   src.IndirectFile = TGSI_FILE_NULL;
988   src.IndirectIndex = 0;
989   src.IndirectSwizzle = 0;
990   src.Absolute  = 0;
991   src.Index     = 0;
992   src.Negate    = 0;
993   src.Dimension = 0;
994   src.DimensionIndex = 0;
995   src.DimIndirect = 0;
996   src.DimIndFile = TGSI_FILE_NULL;
997   src.DimIndIndex = 0;
998   src.DimIndSwizzle = 0;
999
1000   return src;
1001}
1002
1003static INLINE boolean
1004ureg_src_is_undef( struct ureg_src src )
1005{
1006   return src.File == TGSI_FILE_NULL;
1007}
1008
1009static INLINE boolean
1010ureg_dst_is_undef( struct ureg_dst dst )
1011{
1012   return dst.File == TGSI_FILE_NULL;
1013}
1014
1015
1016#ifdef __cplusplus
1017}
1018#endif
1019
1020#endif
1021