📄 profile-fr500.c
字号:
/* frv simulator fr500 dependent profiling code. Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. Contributed by Red HatThis file is part of the GNU simulators.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public License alongwith this program; if not, write to the Free Software Foundation, Inc.,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/#define WANT_CPU#define WANT_CPU_FRVBF#include "sim-main.h"#include "bfd.h"#if WITH_PROFILE_MODEL_P#include "profile.h"#include "profile-fr500.h"/* Initialize cycle counting for an insn. FIRST_P is non-zero if this is the first insn in a set of parallel insns. */voidfr500_model_insn_before (SIM_CPU *cpu, int first_p){ if (first_p) { MODEL_FR500_DATA *d = CPU_MODEL_DATA (cpu); FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu); ps->cur_gr_complex = ps->prev_gr_complex; d->cur_fpop = d->prev_fpop; d->cur_media = d->prev_media; d->cur_cc_complex = d->prev_cc_complex; }}/* Record the cycles computed for an insn. LAST_P is non-zero if this is the last insn in a set of parallel insns, and we update the total cycle count. CYCLES is the cycle count of the insn. */voidfr500_model_insn_after (SIM_CPU *cpu, int last_p, int cycles){ if (last_p) { MODEL_FR500_DATA *d = CPU_MODEL_DATA (cpu); FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu); ps->prev_gr_complex = ps->cur_gr_complex; d->prev_fpop = d->cur_fpop; d->prev_media = d->cur_media; d->prev_cc_complex = d->cur_cc_complex; }}static voidset_use_is_fpop (SIM_CPU *cpu, INT fr){ MODEL_FR500_DATA *d = CPU_MODEL_DATA (cpu); fr500_reset_fr_flags (cpu, (fr)); d->cur_fpop |= (((DI)1) << (fr));}static voidset_use_not_fpop (SIM_CPU *cpu, INT fr){ MODEL_FR500_DATA *d = CPU_MODEL_DATA (cpu); d->cur_fpop &= ~(((DI)1) << (fr));}static intuse_is_fpop (SIM_CPU *cpu, INT fr){ MODEL_FR500_DATA *d = CPU_MODEL_DATA (cpu); return d->prev_fpop & (((DI)1) << (fr));}static voidset_use_is_media ( SIM_CPU *cpu, INT fr){ MODEL_FR500_DATA *d = CPU_MODEL_DATA (cpu); fr500_reset_fr_flags (cpu, (fr)); d->cur_media |= (((DI)1) << (fr));}static voidset_use_not_media (SIM_CPU *cpu, INT fr){ MODEL_FR500_DATA *d = CPU_MODEL_DATA (cpu); d->cur_media &= ~(((DI)1) << (fr));}static intuse_is_media (SIM_CPU *cpu, INT fr){ MODEL_FR500_DATA *d = CPU_MODEL_DATA (cpu); return d->prev_media & (((DI)1) << (fr));}static voidset_use_is_cc_complex (SIM_CPU *cpu, INT cc){ MODEL_FR500_DATA *d = CPU_MODEL_DATA (cpu); fr500_reset_cc_flags (cpu, cc); d->cur_cc_complex |= (((DI)1) << (cc));}static voidset_use_not_cc_complex (SIM_CPU *cpu, INT cc){ MODEL_FR500_DATA *d = CPU_MODEL_DATA (cpu); d->cur_cc_complex &= ~(((DI)1) << (cc));}static intuse_is_cc_complex (SIM_CPU *cpu, INT cc){ MODEL_FR500_DATA *d = CPU_MODEL_DATA (cpu); return d->prev_cc_complex & (((DI)1) << (cc));}voidfr500_reset_fr_flags (SIM_CPU *cpu, INT fr){ set_use_not_fpop (cpu, fr); set_use_not_media (cpu, fr);}voidfr500_reset_cc_flags (SIM_CPU *cpu, INT cc){ set_use_not_cc_complex (cpu, cc);}/* Latency of floating point registers may be less than recorded when followed by another floating point insn. */static voidadjust_float_register_busy (SIM_CPU *cpu, INT in_FRi, INT in_FRj, INT out_FRk, int cycles){ /* If the registers were previously used in a floating point op, then their latency will be less than previously recorded. See Table 13-13 in the LSI. */ if (in_FRi >= 0) if (use_is_fpop (cpu, in_FRi)) decrease_FR_busy (cpu, in_FRi, cycles); else enforce_full_fr_latency (cpu, in_FRi); if (in_FRj >= 0 && in_FRj != in_FRi) if (use_is_fpop (cpu, in_FRj)) decrease_FR_busy (cpu, in_FRj, cycles); else enforce_full_fr_latency (cpu, in_FRj); if (out_FRk >= 0 && out_FRk != in_FRi && out_FRk != in_FRj) if (use_is_fpop (cpu, out_FRk)) decrease_FR_busy (cpu, out_FRk, cycles); else enforce_full_fr_latency (cpu, out_FRk);}/* Latency of floating point registers may be less than recorded when followed by another floating point insn. */static voidadjust_double_register_busy (SIM_CPU *cpu, INT in_FRi, INT in_FRj, INT out_FRk, int cycles){ /* If the registers were previously used in a floating point op, then their latency will be less than previously recorded. See Table 13-13 in the LSI. */ adjust_float_register_busy (cpu, in_FRi, in_FRj, out_FRk, cycles); if (in_FRi >= 0) ++in_FRi; if (in_FRj >= 0) ++in_FRj; if (out_FRk >= 0) ++out_FRk; adjust_float_register_busy (cpu, in_FRi, in_FRj, out_FRk, cycles);}/* Latency of floating point registers is less than recorded when followed by another floating point insn. */static voidrestore_float_register_busy (SIM_CPU *cpu, INT in_FRi, INT in_FRj, INT out_FRk, int cycles){ /* If the registers were previously used in a floating point op, then their latency will be less than previously recorded. See Table 13-13 in the LSI. */ if (in_FRi >= 0 && use_is_fpop (cpu, in_FRi)) increase_FR_busy (cpu, in_FRi, cycles); if (in_FRj != in_FRi && use_is_fpop (cpu, in_FRj)) increase_FR_busy (cpu, in_FRj, cycles); if (out_FRk != in_FRi && out_FRk != in_FRj && use_is_fpop (cpu, out_FRk)) increase_FR_busy (cpu, out_FRk, cycles);}/* Latency of floating point registers is less than recorded when followed by another floating point insn. */static voidrestore_double_register_busy (SIM_CPU *cpu, INT in_FRi, INT in_FRj, INT out_FRk, int cycles){ /* If the registers were previously used in a floating point op, then their latency will be less than previously recorded. See Table 13-13 in the LSI. */ restore_float_register_busy (cpu, in_FRi, in_FRj, out_FRk, cycles); if (in_FRi >= 0) ++in_FRi; if (in_FRj >= 0) ++in_FRj; if (out_FRk >= 0) ++out_FRk; restore_float_register_busy (cpu, in_FRi, in_FRj, out_FRk, cycles);}intfrvbf_model_fr500_u_exec (SIM_CPU *cpu, const IDESC *idesc, int unit_num, int referenced){ return idesc->timing->units[unit_num].done;}intfrvbf_model_fr500_u_integer (SIM_CPU *cpu, const IDESC *idesc, int unit_num, int referenced, INT in_GRi, INT in_GRj, INT out_GRk, INT out_ICCi_1){ int cycles; if (model_insn == FRV_INSN_MODEL_PASS_1) { /* icc0-icc4 are the upper 4 fields of the CCR. */ if (out_ICCi_1 >= 0) out_ICCi_1 += 4; /* The entire VLIW insn must wait if there is a dependency on a register which is not ready yet. The latency of the registers may be less than previously recorded, depending on how they were used previously. See Table 13-8 in the LSI. */ if (in_GRi != out_GRk && in_GRi >= 0) { if (use_is_gr_complex (cpu, in_GRi)) decrease_GR_busy (cpu, in_GRi, 1); } if (in_GRj != out_GRk && in_GRj != in_GRi && in_GRj >= 0) { if (use_is_gr_complex (cpu, in_GRj)) decrease_GR_busy (cpu, in_GRj, 1); } vliw_wait_for_GR (cpu, in_GRi); vliw_wait_for_GR (cpu, in_GRj); vliw_wait_for_GR (cpu, out_GRk); vliw_wait_for_CCR (cpu, out_ICCi_1); handle_resource_wait (cpu); load_wait_for_GR (cpu, in_GRi); load_wait_for_GR (cpu, in_GRj); load_wait_for_GR (cpu, out_GRk); trace_vliw_wait_cycles (cpu); return 0; } /* GRk is available immediately to the next VLIW insn as is ICCi_1. */ cycles = idesc->timing->units[unit_num].done; return cycles;}intfrvbf_model_fr500_u_imul (SIM_CPU *cpu, const IDESC *idesc, int unit_num, int referenced, INT in_GRi, INT in_GRj, INT out_GRk, INT out_ICCi_1){ int cycles; /* icc0-icc4 are the upper 4 fields of the CCR. */ if (out_ICCi_1 >= 0) out_ICCi_1 += 4; if (model_insn == FRV_INSN_MODEL_PASS_1) { /* The entire VLIW insn must wait if there is a dependency on a register which is not ready yet. The latency of the registers may be less than previously recorded, depending on how they were used previously. See Table 13-8 in the LSI. */ if (in_GRi != out_GRk && in_GRi >= 0) { if (use_is_gr_complex (cpu, in_GRi)) decrease_GR_busy (cpu, in_GRi, 1); } if (in_GRj != out_GRk && in_GRj != in_GRi && in_GRj >= 0) { if (use_is_gr_complex (cpu, in_GRj)) decrease_GR_busy (cpu, in_GRj, 1); } vliw_wait_for_GR (cpu, in_GRi); vliw_wait_for_GR (cpu, in_GRj); vliw_wait_for_GRdouble (cpu, out_GRk); vliw_wait_for_CCR (cpu, out_ICCi_1); handle_resource_wait (cpu); load_wait_for_GR (cpu, in_GRi); load_wait_for_GR (cpu, in_GRj); load_wait_for_GRdouble (cpu, out_GRk); trace_vliw_wait_cycles (cpu); return 0; } /* GRk has a latency of 2 cycles. */ cycles = idesc->timing->units[unit_num].done; update_GRdouble_latency (cpu, out_GRk, cycles + 2); set_use_is_gr_complex (cpu, out_GRk); set_use_is_gr_complex (cpu, out_GRk + 1); /* ICCi_1 has a latency of 1 cycle. */ update_CCR_latency (cpu, out_ICCi_1, cycles + 1); return cycles;}intfrvbf_model_fr500_u_idiv (SIM_CPU *cpu, const IDESC *idesc, int unit_num, int referenced, INT in_GRi, INT in_GRj, INT out_GRk, INT out_ICCi_1){ int cycles; FRV_VLIW *vliw; int slot; /* icc0-icc4 are the upper 4 fields of the CCR. */ if (out_ICCi_1 >= 0) out_ICCi_1 += 4; vliw = CPU_VLIW (cpu); slot = vliw->next_slot - 1; slot = (*vliw->current_vliw)[slot] - UNIT_I0; if (model_insn == FRV_INSN_MODEL_PASS_1) { /* The entire VLIW insn must wait if there is a dependency on a register which is not ready yet. The latency of the registers may be less than previously recorded, depending on how they were used previously. See Table 13-8 in the LSI. */ if (in_GRi != out_GRk && in_GRi >= 0) { if (use_is_gr_complex (cpu, in_GRi)) decrease_GR_busy (cpu, in_GRi, 1); } if (in_GRj != out_GRk && in_GRj != in_GRi && in_GRj >= 0) { if (use_is_gr_complex (cpu, in_GRj)) decrease_GR_busy (cpu, in_GRj, 1); } vliw_wait_for_GR (cpu, in_GRi); vliw_wait_for_GR (cpu, in_GRj); vliw_wait_for_GR (cpu, out_GRk); vliw_wait_for_CCR (cpu, out_ICCi_1); vliw_wait_for_idiv_resource (cpu, slot); handle_resource_wait (cpu); load_wait_for_GR (cpu, in_GRi); load_wait_for_GR (cpu, in_GRj); load_wait_for_GR (cpu, out_GRk); trace_vliw_wait_cycles (cpu); return 0; } /* GRk has a latency of 19 cycles! */ cycles = idesc->timing->units[unit_num].done; update_GR_latency (cpu, out_GRk, cycles + 19); set_use_is_gr_complex (cpu, out_GRk); /* ICCi_1 has a latency of 19 cycles. */ update_CCR_latency (cpu, out_ICCi_1, cycles + 19); set_use_is_cc_complex (cpu, out_ICCi_1); if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING)) { /* GNER has a latency of 18 cycles. */ update_SPR_latency (cpu, GNER_FOR_GR (out_GRk), cycles + 18); } /* the idiv resource has a latency of 18 cycles! */ update_idiv_resource_latency (cpu, slot, cycles + 18); return cycles;}intfrvbf_model_fr500_u_branch (SIM_CPU *cpu, const IDESC *idesc, int unit_num, int referenced, INT in_GRi, INT in_GRj, INT in_ICCi_2, INT in_FCCi_2){ int cycles; FRV_PROFILE_STATE *ps; if (model_insn == FRV_INSN_MODEL_PASS_1) { /* icc0-icc4 are the upper 4 fields of the CCR. */ if (in_ICCi_2 >= 0) in_ICCi_2 += 4; /* The entire VLIW insn must wait if there is a dependency on a register which is not ready yet. The latency of the registers may be less than previously recorded, depending on how they were used previously. See Table 13-8 in the LSI. */ if (in_GRi >= 0) { if (use_is_gr_complex (cpu, in_GRi)) decrease_GR_busy (cpu, in_GRi, 1); } if (in_GRj != in_GRi && in_GRj >= 0) { if (use_is_gr_complex (cpu, in_GRj)) decrease_GR_busy (cpu, in_GRj, 1); } vliw_wait_for_GR (cpu, in_GRi); vliw_wait_for_GR (cpu, in_GRj); vliw_wait_for_CCR (cpu, in_ICCi_2); vliw_wait_for_CCR (cpu, in_FCCi_2); handle_resource_wait (cpu); load_wait_for_GR (cpu, in_GRi); load_wait_for_GR (cpu, in_GRj); trace_vliw_wait_cycles (cpu); return 0; } /* When counting branches taken or not taken, don't consider branches after
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -