2 * Copyright (C) 2008 Nicolai Haehnle.
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:
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.
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.
28 #include "radeon_program.h"
32 #include "radeon_compiler.h"
36 * Transform the given clause in the following way:
37 * 1. Replace it with an empty clause
38 * 2. For every instruction in the original clause, try the given
39 * transformations in order.
40 * 3. If one of the transformations returns GL_TRUE, assume that it
41 * has emitted the appropriate instruction(s) into the new clause;
42 * otherwise, copy the instruction verbatim.
44 * \note The transformation is currently not recursive; in other words,
45 * instructions emitted by transformations are not transformed.
47 * \note The transform is called 'local' because it can only look at
48 * one instruction at a time.
50 void radeonLocalTransform(
51 struct radeon_compiler
* c
,
52 int num_transformations
,
53 struct radeon_program_transformation
* transformations
)
55 struct rc_instruction
* inst
= c
->Program
.Instructions
.Next
;
57 while(inst
!= &c
->Program
.Instructions
) {
58 struct rc_instruction
* current
= inst
;
63 for(i
= 0; i
< num_transformations
; ++i
) {
64 struct radeon_program_transformation
* t
= transformations
+ i
;
66 if (t
->function(c
, current
, t
->userData
))
73 * Left multiplication of a register with a swizzle
75 struct rc_src_register
lmul_swizzle(unsigned int swizzle
, struct rc_src_register srcreg
)
77 struct rc_src_register tmp
= srcreg
;
81 for(i
= 0; i
< 4; ++i
) {
82 rc_swizzle swz
= GET_SWZ(swizzle
, i
);
84 tmp
.Swizzle
|= GET_SWZ(srcreg
.Swizzle
, swz
) << (i
*3);
85 tmp
.Negate
|= GET_BIT(srcreg
.Negate
, swz
) << i
;
87 tmp
.Swizzle
|= swz
<< (i
*3);
93 unsigned int rc_find_free_temporary(struct radeon_compiler
* c
)
95 char used
[RC_REGISTER_MAX_INDEX
];
98 memset(used
, 0, sizeof(used
));
100 for (struct rc_instruction
* rcinst
= c
->Program
.Instructions
.Next
; rcinst
!= &c
->Program
.Instructions
; rcinst
= rcinst
->Next
) {
101 const struct rc_sub_instruction
*inst
= &rcinst
->U
.I
;
102 const struct rc_opcode_info
*opcode
= rc_get_opcode_info(inst
->Opcode
);
105 for (k
= 0; k
< opcode
->NumSrcRegs
; k
++) {
106 if (inst
->SrcReg
[k
].File
== RC_FILE_TEMPORARY
)
107 used
[inst
->SrcReg
[k
].Index
] = 1;
110 if (opcode
->HasDstReg
) {
111 if (inst
->DstReg
.File
== RC_FILE_TEMPORARY
)
112 used
[inst
->DstReg
.Index
] = 1;
116 for (i
= 0; i
< RC_REGISTER_MAX_INDEX
; i
++) {
121 rc_error(c
, "Ran out of temporary registers\n");
126 struct rc_instruction
*rc_alloc_instruction(struct radeon_compiler
* c
)
128 struct rc_instruction
* inst
= memory_pool_malloc(&c
->Pool
, sizeof(struct rc_instruction
));
130 memset(inst
, 0, sizeof(struct rc_instruction
));
132 inst
->U
.I
.Opcode
= RC_OPCODE_ILLEGAL_OPCODE
;
133 inst
->U
.I
.DstReg
.WriteMask
= RC_MASK_XYZW
;
134 inst
->U
.I
.SrcReg
[0].Swizzle
= RC_SWIZZLE_XYZW
;
135 inst
->U
.I
.SrcReg
[1].Swizzle
= RC_SWIZZLE_XYZW
;
136 inst
->U
.I
.SrcReg
[2].Swizzle
= RC_SWIZZLE_XYZW
;
141 void rc_insert_instruction(struct rc_instruction
* after
, struct rc_instruction
* inst
)
144 inst
->Next
= after
->Next
;
146 inst
->Prev
->Next
= inst
;
147 inst
->Next
->Prev
= inst
;
150 struct rc_instruction
*rc_insert_new_instruction(struct radeon_compiler
* c
, struct rc_instruction
* after
)
152 struct rc_instruction
* inst
= rc_alloc_instruction(c
);
154 rc_insert_instruction(after
, inst
);
159 void rc_remove_instruction(struct rc_instruction
* inst
)
161 inst
->Prev
->Next
= inst
->Next
;
162 inst
->Next
->Prev
= inst
->Prev
;
166 * Return the number of instructions in the program.
168 unsigned int rc_recompute_ips(struct radeon_compiler
* c
)
172 for(struct rc_instruction
* inst
= c
->Program
.Instructions
.Next
;
173 inst
!= &c
->Program
.Instructions
;
178 c
->Program
.Instructions
.IP
= 0xcafedead;