1 2 #include "radeon_compiler.h" 3 #include "radeon_compiler_util.h" 4 #include "radeon_dataflow.h" 5 #include "radeon_program.h" 6 #include "radeon_program_constants.h" 7 8 struct vert_fc_state { 9 struct radeon_compiler *C; 10 unsigned BranchDepth; 11 unsigned LoopDepth; 12 unsigned LoopsReserved; 13 int PredStack[R500_PVS_MAX_LOOP_DEPTH]; 14 int PredicateReg; 15 unsigned InCFBreak; 16 }; 17 18 static void build_pred_src( 19 struct rc_src_register * src, 20 struct vert_fc_state * fc_state) 21 { 22 src->Swizzle = RC_MAKE_SWIZZLE(RC_SWIZZLE_UNUSED, RC_SWIZZLE_UNUSED, 23 RC_SWIZZLE_UNUSED, RC_SWIZZLE_W); 24 src->File = RC_FILE_TEMPORARY; 25 src->Index = fc_state->PredicateReg; 26 } 27 28 static void build_pred_dst( 29 struct rc_dst_register * dst, 30 struct vert_fc_state * fc_state) 31 { 32 dst->WriteMask = RC_MASK_W; 33 dst->File = RC_FILE_TEMPORARY; 34 dst->Index = fc_state->PredicateReg; 35 } 36 37 static void mark_write(void * userdata, struct rc_instruction * inst, 38 rc_register_file file, unsigned int index, unsigned int mask) 39 { 40 unsigned int * writemasks = userdata; 41 42 if (file != RC_FILE_TEMPORARY) 43 return; 44 45 if (index >= R300_VS_MAX_TEMPS) 46 return; 47 48 writemasks[index] |= mask; 49 } 50 51 static int reserve_predicate_reg(struct vert_fc_state * fc_state) 52 { 53 int i; 54 unsigned int writemasks[RC_REGISTER_MAX_INDEX]; 55 struct rc_instruction * inst; 56 memset(writemasks, 0, sizeof(writemasks)); 57 for(inst = fc_state->C->Program.Instructions.Next; 58 inst != &fc_state->C->Program.Instructions; 59 inst = inst->Next) { 60 rc_for_all_writes_mask(inst, mark_write, writemasks); 61 } 62 63 for(i = 0; i < fc_state->C->max_temp_regs; i++) { 64 /* Most of the control flow instructions only write the 65 * W component of the Predicate Register, but 66 * the docs say that ME_PRED_SET_CLR and 67 * ME_PRED_SET_RESTORE write all components of the 68 * register, so we must reserve a register that has 69 * all its components free. */ 70 if (!writemasks[i]) { 71 fc_state->PredicateReg = i; 72 break; 73 } 74 } 75 if (i == fc_state->C->max_temp_regs) { 76 rc_error(fc_state->C, "No free temporary to use for" 77 " predicate stack counter.\n"); 78 return -1; 79 } 80 return 1; 81 } 82 83 static void lower_bgnloop( 84 struct rc_instruction * inst, 85 struct vert_fc_state * fc_state) 86 { 87 struct rc_instruction * new_inst = 88 rc_insert_new_instruction(fc_state->C, inst->Prev); 89 90 if ((!fc_state->C->is_r500 91 && fc_state->LoopsReserved >= R300_VS_MAX_LOOP_DEPTH) 92 || fc_state->LoopsReserved >= R500_PVS_MAX_LOOP_DEPTH) { 93 rc_error(fc_state->C, "Loops are nested too deep."); 94 return; 95 } 96 97 if (fc_state->LoopDepth == 0 && fc_state->BranchDepth == 0) { 98 if (fc_state->PredicateReg == -1) { 99 if (reserve_predicate_reg(fc_state) == -1) { 100 return; 101 } 102 } 103 104 /* Initialize the predicate bit to true. */ 105 new_inst->U.I.Opcode = RC_ME_PRED_SEQ; 106 build_pred_dst(&new_inst->U.I.DstReg, fc_state); 107 new_inst->U.I.SrcReg[0].Index = 0; 108 new_inst->U.I.SrcReg[0].File = RC_FILE_NONE; 109 new_inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_0000; 110 } else { 111 fc_state->PredStack[fc_state->LoopDepth] = 112 fc_state->PredicateReg; 113 /* Copy the the current predicate value to this loop's 114 * predicate register */ 115 116 /* Use the old predicate value for src0 */ 117 build_pred_src(&new_inst->U.I.SrcReg[0], fc_state); 118 119 /* Reserve this loop's predicate register */ 120 if (reserve_predicate_reg(fc_state) == -1) { 121 return; 122 } 123 124 /* Copy the old predicate value to the new register */ 125 new_inst->U.I.Opcode = RC_OPCODE_ADD; 126 build_pred_dst(&new_inst->U.I.DstReg, fc_state); 127 new_inst->U.I.SrcReg[1].Index = 0; 128 new_inst->U.I.SrcReg[1].File = RC_FILE_NONE; 129 new_inst->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_0000; 130 } 131 132 } 133 134 static void lower_brk( 135 struct rc_instruction * inst, 136 struct vert_fc_state * fc_state) 137 { 138 if (fc_state->LoopDepth == 1) { 139 inst->U.I.Opcode = RC_OPCODE_RCP; 140 inst->U.I.DstReg.Pred = RC_PRED_INV; 141 inst->U.I.SrcReg[0].Index = 0; 142 inst->U.I.SrcReg[0].File = RC_FILE_NONE; 143 inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_0000; 144 } else { 145 inst->U.I.Opcode = RC_ME_PRED_SET_CLR; 146 inst->U.I.DstReg.Pred = RC_PRED_SET; 147 } 148 149 build_pred_dst(&inst->U.I.DstReg, fc_state); 150 } 151 152 static void lower_endloop( 153 struct rc_instruction * inst, 154 struct vert_fc_state * fc_state) 155 { 156 struct rc_instruction * new_inst = 157 rc_insert_new_instruction(fc_state->C, inst); 158 159 new_inst->U.I.Opcode = RC_ME_PRED_SET_RESTORE; 160 build_pred_dst(&new_inst->U.I.DstReg, fc_state); 161 /* Restore the previous predicate register. */ 162 fc_state->PredicateReg = fc_state->PredStack[fc_state->LoopDepth - 1]; 163 build_pred_src(&new_inst->U.I.SrcReg[0], fc_state); 164 } 165 166 static void lower_if( 167 struct rc_instruction * inst, 168 struct vert_fc_state * fc_state) 169 { 170 /* Reserve a temporary to use as our predicate stack counter, if we 171 * don't already have one. */ 172 if (fc_state->PredicateReg == -1) { 173 /* If we are inside a loop, the Predicate Register should 174 * have already been defined. */ 175 assert(fc_state->LoopDepth == 0); 176 177 if (reserve_predicate_reg(fc_state) == -1) { 178 return; 179 } 180 } 181 182 if (inst->Next->U.I.Opcode == RC_OPCODE_BRK) { 183 fc_state->InCFBreak = 1; 184 } 185 if ((fc_state->BranchDepth == 0 && fc_state->LoopDepth == 0) 186 || (fc_state->LoopDepth == 1 && fc_state->InCFBreak)) { 187 if (fc_state->InCFBreak) { 188 inst->U.I.Opcode = RC_ME_PRED_SEQ; 189 inst->U.I.DstReg.Pred = RC_PRED_SET; 190 } else { 191 inst->U.I.Opcode = RC_ME_PRED_SNEQ; 192 } 193 } else { 194 unsigned swz; 195 inst->U.I.Opcode = RC_VE_PRED_SNEQ_PUSH; 196 memcpy(&inst->U.I.SrcReg[1], &inst->U.I.SrcReg[0], 197 sizeof(inst->U.I.SrcReg[1])); 198 swz = rc_get_scalar_src_swz(inst->U.I.SrcReg[1].Swizzle); 199 /* VE_PRED_SNEQ_PUSH needs to the branch condition to be in the 200 * w component */ 201 inst->U.I.SrcReg[1].Swizzle = RC_MAKE_SWIZZLE(RC_SWIZZLE_UNUSED, 202 RC_SWIZZLE_UNUSED, RC_SWIZZLE_UNUSED, swz); 203 build_pred_src(&inst->U.I.SrcReg[0], fc_state); 204 } 205 build_pred_dst(&inst->U.I.DstReg, fc_state); 206 } 207 208 void rc_vert_fc(struct radeon_compiler *c, void *user) 209 { 210 struct rc_instruction * inst; 211 struct vert_fc_state fc_state; 212 213 memset(&fc_state, 0, sizeof(fc_state)); 214 fc_state.PredicateReg = -1; 215 fc_state.C = c; 216 217 for(inst = c->Program.Instructions.Next; 218 inst != &c->Program.Instructions; 219 inst = inst->Next) { 220 221 switch (inst->U.I.Opcode) { 222 223 case RC_OPCODE_BGNLOOP: 224 lower_bgnloop(inst, &fc_state); 225 fc_state.LoopDepth++; 226 break; 227 228 case RC_OPCODE_BRK: 229 lower_brk(inst, &fc_state); 230 break; 231 232 case RC_OPCODE_ENDLOOP: 233 if (fc_state.BranchDepth != 0 234 || fc_state.LoopDepth != 1) { 235 lower_endloop(inst, &fc_state); 236 } 237 fc_state.LoopDepth--; 238 /* Skip PRED_RESTORE */ 239 inst = inst->Next; 240 break; 241 case RC_OPCODE_IF: 242 lower_if(inst, &fc_state); 243 fc_state.BranchDepth++; 244 break; 245 246 case RC_OPCODE_ELSE: 247 inst->U.I.Opcode = RC_ME_PRED_SET_INV; 248 build_pred_dst(&inst->U.I.DstReg, &fc_state); 249 build_pred_src(&inst->U.I.SrcReg[0], &fc_state); 250 break; 251 252 case RC_OPCODE_ENDIF: 253 if (fc_state.LoopDepth == 1 && fc_state.InCFBreak) { 254 struct rc_instruction * to_delete = inst; 255 inst = inst->Prev; 256 rc_remove_instruction(to_delete); 257 /* XXX: Delete the endif instruction */ 258 } else { 259 inst->U.I.Opcode = RC_ME_PRED_SET_POP; 260 build_pred_dst(&inst->U.I.DstReg, &fc_state); 261 build_pred_src(&inst->U.I.SrcReg[0], &fc_state); 262 } 263 fc_state.InCFBreak = 0; 264 fc_state.BranchDepth--; 265 break; 266 267 default: 268 if (fc_state.BranchDepth || fc_state.LoopDepth) { 269 inst->U.I.DstReg.Pred = RC_PRED_SET; 270 } 271 break; 272 } 273 274 if (c->Error) { 275 return; 276 } 277 } 278 } 279