1/*
2 * Copyright (C) 2008 Nicolai Haehnle.
3 *
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a 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, sublicense, 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
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 */
27
28#ifndef __RADEON_PROGRAM_H_
29#define __RADEON_PROGRAM_H_
30
31#include <stdint.h>
32#include <string.h>
33
34#include "radeon_opcodes.h"
35#include "radeon_code.h"
36#include "radeon_program_constants.h"
37#include "radeon_program_pair.h"
38
39struct radeon_compiler;
40
41struct rc_src_register {
42	unsigned int File:4;
43
44	/** Negative values may be used for relative addressing. */
45	signed int Index:(RC_REGISTER_INDEX_BITS+1);
46	unsigned int RelAddr:1;
47
48	unsigned int Swizzle:12;
49
50	/** Take the component-wise absolute value */
51	unsigned int Abs:1;
52
53	/** Post-Abs negation. */
54	unsigned int Negate:4;
55};
56
57struct rc_dst_register {
58	unsigned int File:3;
59	unsigned int Index:RC_REGISTER_INDEX_BITS;
60	unsigned int WriteMask:4;
61	unsigned int Pred:2;
62};
63
64struct rc_presub_instruction {
65	rc_presubtract_op Opcode;
66	struct rc_src_register SrcReg[2];
67};
68
69/**
70 * Instructions are maintained by the compiler in a doubly linked list
71 * of these structures.
72 *
73 * This instruction format is intended to be expanded for hardware-specific
74 * trickery. At different stages of compilation, a different set of
75 * instruction types may be valid.
76 */
77struct rc_sub_instruction {
78	struct rc_src_register SrcReg[3];
79	struct rc_dst_register DstReg;
80
81	/**
82	 * Opcode of this instruction, according to \ref rc_opcode enums.
83	 */
84	unsigned int Opcode:8;
85
86	/**
87	 * Saturate each value of the result to the range [0,1] or [-1,1],
88	 * according to \ref rc_saturate_mode enums.
89	 */
90	unsigned int SaturateMode:2;
91
92	/**
93	 * Writing to the special register RC_SPECIAL_ALU_RESULT
94	 */
95	/*@{*/
96	unsigned int WriteALUResult:2;
97	unsigned int ALUResultCompare:3;
98	/*@}*/
99
100	/**
101	 * \name Extra fields for TEX, TXB, TXD, TXL, TXP instructions.
102	 */
103	/*@{*/
104	/** Source texture unit. */
105	unsigned int TexSrcUnit:5;
106
107	/** Source texture target, one of the \ref rc_texture_target enums */
108	unsigned int TexSrcTarget:3;
109
110	/** True if tex instruction should do shadow comparison */
111	unsigned int TexShadow:1;
112
113	/**/
114	unsigned int TexSemWait:1;
115	unsigned int TexSemAcquire:1;
116
117	/**R500 Only.  How to swizzle the result of a TEX lookup*/
118	unsigned int TexSwizzle:12;
119	/*@}*/
120
121	/** This holds information about the presubtract operation used by
122	 * this instruction. */
123	struct rc_presub_instruction PreSub;
124
125	rc_omod_op Omod;
126};
127
128typedef enum {
129	RC_INSTRUCTION_NORMAL = 0,
130	RC_INSTRUCTION_PAIR
131} rc_instruction_type;
132
133struct rc_instruction {
134	struct rc_instruction * Prev;
135	struct rc_instruction * Next;
136
137	rc_instruction_type Type;
138	union {
139		struct rc_sub_instruction I;
140		struct rc_pair_instruction P;
141	} U;
142
143	/**
144	 * Warning: IPs are not stable. If you want to use them,
145	 * you need to recompute them at the beginning of each pass
146	 * using \ref rc_recompute_ips
147	 */
148	unsigned int IP;
149};
150
151struct rc_program {
152	/**
153	 * Instructions.Next points to the first instruction,
154	 * Instructions.Prev points to the last instruction.
155	 */
156	struct rc_instruction Instructions;
157
158	/* Long term, we should probably remove InputsRead & OutputsWritten,
159	 * since updating dependent state can be fragile, and they aren't
160	 * actually used very often. */
161	uint32_t InputsRead;
162	uint32_t OutputsWritten;
163	uint32_t ShadowSamplers; /**< Texture units used for shadow sampling. */
164
165	struct rc_constant_list Constants;
166};
167
168/**
169 * A transformation that can be passed to \ref rc_local_transform.
170 *
171 * The function will be called once for each instruction.
172 * It has to either emit the appropriate transformed code for the instruction
173 * and return true, or return false if it doesn't understand the
174 * instruction.
175 *
176 * The function gets passed the userData as last parameter.
177 */
178struct radeon_program_transformation {
179	int (*function)(
180		struct radeon_compiler*,
181		struct rc_instruction*,
182		void*);
183	void *userData;
184};
185
186void rc_local_transform(
187	struct radeon_compiler *c,
188	void *user);
189
190void rc_get_used_temporaries(
191	struct radeon_compiler * c,
192	unsigned char * used,
193	unsigned int used_length);
194
195int rc_find_free_temporary_list(
196	struct radeon_compiler * c,
197	unsigned char * used,
198	unsigned int used_length,
199	unsigned int mask);
200
201unsigned int rc_find_free_temporary(struct radeon_compiler * c);
202
203struct rc_instruction *rc_alloc_instruction(struct radeon_compiler * c);
204struct rc_instruction *rc_insert_new_instruction(struct radeon_compiler * c, struct rc_instruction * after);
205void rc_insert_instruction(struct rc_instruction * after, struct rc_instruction * inst);
206void rc_remove_instruction(struct rc_instruction * inst);
207
208unsigned int rc_recompute_ips(struct radeon_compiler * c);
209
210void rc_print_program(const struct rc_program *prog);
211
212rc_swizzle rc_mask_to_swizzle(unsigned int mask);
213#endif
214