📄 ppc-instructions
字号:
int_busy &= model_ptr->int_busy; for(i = 0; i < 32; i++) { if (((1 << i) & int_busy) != 0) { TRACE(trace_model, ("Waiting for register r%d.\n", i)); } } } if (fp_busy) { fp_busy &= model_ptr->fp_busy; for(i = 0; i < 32; i++) { if (((1 << i) & fp_busy) != 0) { TRACE(trace_model, ("Waiting for register f%d.\n", i)); } } } if (cr_or_fpscr_busy) { cr_or_fpscr_busy &= model_ptr->cr_fpscr_busy; for(i = 0; i < 8; i++) { if (((1 << i) & cr_or_fpscr_busy) != 0) { TRACE(trace_model, ("Waiting for register cr%d.\n", i)); } } if (cr_or_fpscr_busy & 0x100) TRACE(trace_model, ("Waiting for register fpscr.\n")); } if (spr_busy != PPC_NO_SPR && model_ptr->spr_busy[spr_busy]) TRACE(trace_model, ("Waiting for register %s.\n", spr_name(spr_busy)));# Advance state to next cycle, releasing any registers allocatedvoid::model-internal::model_new_cycle:model_data *model_ptr model_busy *cur_busy = model_ptr->busy_head.next; model_busy *free_list = model_ptr->free_list; model_busy *busy_tail = &model_ptr->busy_head; int nr_writebacks = model_ptr->max_nr_writebacks; model_busy *next; model_ptr->nr_cycles++; TRACE(trace_model,("New cycle %lu\n", (unsigned long)model_ptr->nr_cycles)); for ( ; cur_busy; cur_busy = next) { next = cur_busy->next; if (--cur_busy->done <= 0) { /* function unit done, release registers if we have writeback slots */ nr_writebacks -= cur_busy->nr_writebacks; if (nr_writebacks >= 0) { model_ptr->int_busy &= ~cur_busy->int_busy; model_ptr->fp_busy &= ~cur_busy->fp_busy; model_ptr->cr_fpscr_busy &= ~cur_busy->cr_fpscr_busy; if (cur_busy->spr_busy != PPC_NO_SPR) model_ptr->spr_busy[cur_busy->spr_busy] = 0; model_ptr->vr_busy &= ~cur_busy->vr_busy; model_ptr->vscr_busy = ~cur_busy->vscr_busy; if (WITH_TRACE && ppc_trace[trace_model]) model_trace_release(model_ptr, cur_busy); model_ptr->busy[cur_busy->unit] = 0; cur_busy->next = free_list; free_list = cur_busy; } else { /* writeback slots not available */ TRACE(trace_model,("%d writeback slot%s not available for %s\n", cur_busy->nr_writebacks, cur_busy->nr_writebacks == 1 ? " is" : "s are", ppc_function_unit_name[cur_busy->unit])); cur_busy->done++; /* undo -- above */ model_ptr->nr_stalls_writeback++; busy_tail->next = cur_busy; busy_tail = cur_busy; } } else if (--cur_busy->issue <= 0) { /* function unit pipelined, allow new use */ TRACE(trace_model,("pipeline, %s ready for next client\n", ppc_function_unit_name[cur_busy->unit])); model_ptr->busy[cur_busy->unit] = 0; busy_tail->next = cur_busy; busy_tail = cur_busy; } else { TRACE(trace_model,("%s still working, issue = %d, done = %d\n", ppc_function_unit_name[cur_busy->unit], cur_busy->issue, cur_busy->done)); busy_tail->next = cur_busy; busy_tail = cur_busy; } } busy_tail->next = (model_busy *)0; model_ptr->busy_tail = busy_tail; model_ptr->free_list = free_list;# Mark a function unit as busy, return the busy structuremodel_busy *::model-internal::model_make_busy:model_data *model_ptr, ppc_function_unit unit, int issue, int done model_busy *busy; TRACE(trace_model,("unit = %s, issue = %d, done = %d\n", ppc_function_unit_name[unit], issue, done)); if (!model_ptr->free_list) { busy = ZALLOC(model_busy); } else { busy = model_ptr->free_list; model_ptr->free_list = busy->next; busy->next = (model_busy *)0; busy->int_busy = 0; busy->fp_busy = 0; busy->cr_fpscr_busy = 0; busy->nr_writebacks = 0; busy->vr_busy = 0; busy->vscr_busy = 0; } busy->unit = unit; busy->issue = issue; busy->done = done; busy->spr_busy = PPC_NO_SPR; model_ptr->busy_tail->next = busy; model_ptr->busy_tail = busy; model_ptr->busy[unit] = 1; model_ptr->nr_units[unit]++; return busy;# Wait until a function unit is non-busy, and then allocate a busy pointer & return the pointermodel_busy *::model-internal::model_wait_for_unit:itable_index index, model_data *const model_ptr, const model_time *const time_ptr ppc_function_unit first_unit = time_ptr->first_unit; ppc_function_unit second_unit = time_ptr->second_unit; int stall_increment = 0; for (;;) { if (!model_ptr->busy[first_unit]) return model_make_busy(model_ptr, first_unit, model_ptr->timing[index].issue, model_ptr->timing[index].done); if (!model_ptr->busy[second_unit]) return model_make_busy(model_ptr, second_unit, model_ptr->timing[index].issue, model_ptr->timing[index].done); TRACE(trace_model,("all function units are busy for %s\n", itable[index].name)); model_ptr->nr_stalls_unit += stall_increment; /* don't count first stall */ stall_increment = 1; model_new_cycle(model_ptr); }# Serialize the processor, waiting for all instructions to drain out before adding an instruction.void::model-function::model_serialize:itable_index index, model_data *model_ptr while (model_ptr->busy_head.next) { TRACE(trace_model,("waiting for pipeline to empty\n")); model_ptr->nr_stalls_serialize++; model_new_cycle(model_ptr); } (void) model_make_busy(model_ptr, model_ptr->timing[index].first_unit, model_ptr->timing[index].issue, model_ptr->timing[index].done);# Wait for a CR to become unbusyvoid::model-function::model_wait_for_cr:model_data *model_ptr, unsigned CRBIT unsigned u; unsigned32 cr_mask; int cr_var = 0; for (u = 0xc0000000; (u != 0) && (CRBIT & u) == 0; u >>= 4 ) cr_var++; cr_mask = (1 << cr_var); while ((model_ptr->cr_fpscr_busy & cr_mask) != 0) { TRACE(trace_model,("waiting for CR %d\n", cr_var)); model_ptr->nr_stalls_data++; model_new_cycle(model_ptr); }# Schedule an instruction that takes integer input registers and produces output registersvoid::model-function::ppc_insn_int:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask const unsigned32 int_mask = out_mask | in_mask; model_busy *busy_ptr; if ((model_ptr->int_busy & int_mask) != 0) { model_new_cycle(model_ptr); /* don't count first dependency as a stall */ while ((model_ptr->int_busy & int_mask) != 0) { if (WITH_TRACE && ppc_trace[trace_model]) model_trace_busy_p(model_ptr, int_mask, 0, 0, PPC_NO_SPR); model_ptr->nr_stalls_data++; model_new_cycle(model_ptr); } } busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]); model_ptr->int_busy |= out_mask; busy_ptr->int_busy |= out_mask; if (out_mask) busy_ptr->nr_writebacks = (PPC_ONE_BIT_SET_P(out_mask)) ? 1 : 2; if (WITH_TRACE && ppc_trace[trace_model]) model_trace_make_busy(model_ptr, out_mask, 0, 0);# Schedule an instruction that takes integer input registers and produces output registers & sets a CR registervoid::model-function::ppc_insn_int_cr:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask, const unsigned32 cr_mask const unsigned32 int_mask = out_mask | in_mask; model_busy *busy_ptr; if ((model_ptr->int_busy & int_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) { model_new_cycle(model_ptr); /* don't count first dependency as a stall */ while ((model_ptr->int_busy & int_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) { if (WITH_TRACE && ppc_trace[trace_model]) model_trace_busy_p(model_ptr, int_mask, 0, cr_mask, PPC_NO_SPR); model_ptr->nr_stalls_data++; model_new_cycle(model_ptr); } } busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]); model_ptr->int_busy |= out_mask; busy_ptr->int_busy |= out_mask; model_ptr->cr_fpscr_busy |= cr_mask; busy_ptr->cr_fpscr_busy |= cr_mask; if (out_mask) busy_ptr->nr_writebacks = (PPC_ONE_BIT_SET_P(out_mask)) ? 1 : 2; if (cr_mask) busy_ptr->nr_writebacks++; if (WITH_TRACE && ppc_trace[trace_model]) model_trace_make_busy(model_ptr, out_mask, 0, cr_mask);# Schedule an instruction that takes CR input registers and produces output CR registersvoid::model-function::ppc_insn_cr:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask const unsigned32 cr_mask = out_mask | in_mask; model_busy *busy_ptr; if ((model_ptr->cr_fpscr_busy & cr_mask) != 0) { model_new_cycle(model_ptr); /* don't count first dependency as a stall */ while ((model_ptr->cr_fpscr_busy & cr_mask) != 0) { if (WITH_TRACE && ppc_trace[trace_model]) model_trace_busy_p(model_ptr, 0, 0, cr_mask, PPC_NO_SPR); model_ptr->nr_stalls_data++; model_new_cycle(model_ptr); } } busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]); model_ptr->cr_fpscr_busy |= out_mask; busy_ptr->cr_fpscr_busy |= out_mask; if (out_mask) busy_ptr->nr_writebacks = 1; if (WITH_TRACE && ppc_trace[trace_model]) model_trace_make_busy(model_ptr, 0, 0, out_mask);# Schedule an instruction that takes floating point input registers and produces an output fp registervoid::model-function::ppc_insn_float:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask const unsigned32 fp_mask = out_mask | in_mask; model_busy *busy_ptr; if ((model_ptr->fp_busy & fp_mask) != 0) { model_new_cycle(model_ptr); /* don't count first dependency as a stall */ while ((model_ptr->fp_busy & fp_mask) != 0) { if (WITH_TRACE && ppc_trace[trace_model]) model_trace_busy_p(model_ptr, 0, fp_mask, 0, PPC_NO_SPR); model_ptr->nr_stalls_data++; model_new_cycle(model_ptr); } } busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]); model_ptr->fp_busy |= out_mask; busy_ptr->fp_busy |= out_mask; busy_ptr->nr_writebacks = 1; if (WITH_TRACE && ppc_trace[trace_model]) model_trace_make_busy(model_ptr, 0, out_mask, 0);# Schedule an instruction that takes floating point input registers and produces an output fp register & sets a CR regvoid::model-function::ppc_insn_float_cr:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask, const unsigned32 cr_mask const unsigned32 fp_mask = out_mask | in_mask; model_busy *busy_ptr; if ((model_ptr->fp_busy & fp_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) { model_new_cycle(model_ptr); /* don't count first dependency as a stall */ while ((model_ptr->fp_busy & fp_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) { if (WITH_TRACE && ppc_trace[trace_model]) model_trace_busy_p(model_ptr, 0, fp_mask, cr_mask, PPC_NO_SPR); model_ptr->nr_stalls_data++; model_new_cycle(model_ptr); } } busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]); model_ptr->fp_busy |= out_mask; busy_ptr->fp_busy |= out_mask; model_ptr->cr_fpscr_busy |= cr_mask; busy_ptr->cr_fpscr_busy |= cr_mask; busy_ptr->nr_writebacks = (cr_mask) ? 2 : 1; if (WITH_TRACE && ppc_trace[trace_model]) model_trace_make_busy(model_ptr, 0, out_mask, cr_mask);# Schedule an instruction that takes both int/float input registers and produces output int/float registersvoid::model-function::ppc_insn_int_float:itable_index index, model_data *model_ptr, const unsigned32 out_int_mask, const unsigned32 out_fp_mask, const unsigned32 in_int_mask, const unsigned32 in_fp_mask const unsigned32 int_mask = out_int_mask | in_int_mask; const unsigned32 fp_mask = out_fp_mask | in_fp_mask; model_busy *busy_ptr; if ((model_ptr->int_busy & int_mask) || (model_ptr->fp_busy & fp_mask)) { model_new_cycle(model_ptr); /* don't count first dependency as a stall */ while ((model_ptr->int_busy & int_mask) || (model_ptr->fp_busy & fp_mask)) { if (WITH_TRACE && ppc_trace[trace_model]) model_trace_busy_p(model_ptr, int_mask, fp_mask, 0, PPC_NO_SPR); model_ptr->nr_stalls_data++; model_new_cycle(model_ptr); } busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]); model_ptr->int_busy |= out_int_mask; busy_ptr->int_busy |= out_int_mask; model_ptr->fp_busy |= out_fp_mask; busy_ptr->fp_busy |= out_fp_mask; busy_ptr->nr_writebacks = ((out_int_mask) ? 1 : 0) + ((out_fp_mask) ? 1 : 0); if (WITH_TRACE && ppc_trace[trace_model]) model_trace_make_busy(model_ptr, out_int_mask, out_fp_mask, 0); return; }# Schedule an MFSPR instruction that takes 1 special purpose register and produces an integer output registervoid::model-function::ppc_insn_from_spr:itable_index index, model_data *model_ptr, const unsigned32 int_mask, const unsigned nSPR model_busy *busy_ptr; while ((model_ptr->int_busy & int_mask) != 0 || model_ptr->spr_busy[nSPR] != 0) { if (WITH_TRACE && ppc_trace[trace_model]) model_trace_busy_p(model_ptr, int_mask, 0, 0, nSPR); model_ptr->nr_stalls_data++; model_new_cycle(model_ptr); } busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]); model_ptr->int_busy |= int_mask; busy_ptr->int_busy |= int_mask; busy_ptr->nr_writebacks = 1; if (WITH_TRACE && ppc_trace[trace_model]) model_trace_make_busy(model_ptr, int_mask, 0, 0);# Schedule an MTSPR instruction that takes 1 integer register and produces a special purpose output registervoid::model-function::ppc_insn_to_spr:itable_index index, model_data *model_ptr, const unsigned32 int_mask, const unsigned nSPR model_busy *busy_ptr; while ((model_ptr->int_busy & int_mask) != 0 || model_ptr->spr_busy[nSPR] != 0) { if (WITH_TRACE && ppc_trace[trace_model]) model_trace_busy_p(model_ptr, int_mask, 0, 0, nSPR); model_ptr->nr_stalls_data++; model_new_cycle(model_ptr); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -