static void instruction_ready(struct schedule_state * s, struct schedule_instruction * sinst) { DBG("%i is now ready\n", sinst->Instruction->IP); /* Adding Ready TEX instructions to the end of the "Ready List" helps * us emit TEX instructions in blocks without losing our place. */ if (sinst->Instruction->Type == RC_INSTRUCTION_NORMAL) add_inst_to_list_end(&s->ReadyTEX, sinst); else if (sinst->Instruction->U.P.Alpha.Opcode == RC_OPCODE_NOP) add_inst_to_list(&s->ReadyRGB, sinst); else if (sinst->Instruction->U.P.RGB.Opcode == RC_OPCODE_NOP) add_inst_to_list(&s->ReadyAlpha, sinst); else add_inst_to_list(&s->ReadyFullALU, sinst); }
static void try_convert_and_pair( struct schedule_state *s, struct schedule_instruction ** inst_list) { struct schedule_instruction * list_ptr = *inst_list; while (list_ptr && *inst_list && (*inst_list)->NextReady) { int paired = 0; if (list_ptr->Instruction->U.P.Alpha.Opcode != RC_OPCODE_NOP && list_ptr->Instruction->U.P.RGB.Opcode != RC_OPCODE_REPL_ALPHA) { goto next; } if (list_ptr->NumWriteValues == 1 && convert_rgb_to_alpha(s, list_ptr)) { struct schedule_instruction * pair_ptr; remove_inst_from_list(inst_list, list_ptr); add_inst_to_list_score(&s->ReadyAlpha, list_ptr); for (pair_ptr = s->ReadyRGB; pair_ptr; pair_ptr = pair_ptr->NextReady) { if (merge_instructions(&pair_ptr->Instruction->U.P, &list_ptr->Instruction->U.P)) { remove_inst_from_list(&s->ReadyAlpha, list_ptr); remove_inst_from_list(&s->ReadyRGB, pair_ptr); pair_ptr->PairedInst = list_ptr; add_inst_to_list(&s->ReadyFullALU, pair_ptr); list_ptr = *inst_list; paired = 1; break; } } } if (!paired) { next: list_ptr = list_ptr->NextReady; } } }
/** * This function attempts to merge RGB and Alpha instructions together. */ static void pair_instructions(struct schedule_state * s) { struct schedule_instruction *rgb_ptr; struct schedule_instruction *alpha_ptr; /* Some pairings might fail because they require too * many source slots; try all possible pairings if necessary */ rgb_ptr = s->ReadyRGB; while(rgb_ptr) { struct schedule_instruction * rgb_next = rgb_ptr->NextReady; alpha_ptr = s->ReadyAlpha; while(alpha_ptr) { struct schedule_instruction * alpha_next = alpha_ptr->NextReady; if (merge_instructions(&rgb_ptr->Instruction->U.P, &alpha_ptr->Instruction->U.P)) { /* Remove RGB and Alpha from their ready lists. */ remove_inst_from_list(&s->ReadyRGB, rgb_ptr); remove_inst_from_list(&s->ReadyAlpha, alpha_ptr); rgb_ptr->PairedInst = alpha_ptr; add_inst_to_list(&s->ReadyFullALU, rgb_ptr); break; } alpha_ptr = alpha_next; } rgb_ptr = rgb_next; } if (!s->Opt) { return; } /* Full instructions that have RC_OPCODE_REPL_ALPHA in the RGB * slot can be converted into Alpha instructions. */ try_convert_and_pair(s, &s->ReadyFullALU); /* Try to convert some of the RGB instructions to Alpha and * try to pair it with another RGB. */ try_convert_and_pair(s, &s->ReadyRGB); }