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