diff options
author | Dave Brolley <brolley@redhat.com> | 2003-10-08 18:19:33 +0000 |
---|---|---|
committer | Dave Brolley <brolley@redhat.com> | 2003-10-08 18:19:33 +0000 |
commit | e930b1f54ff2768c5818eb0a450b1d98d46d273d (patch) | |
tree | beff79b0fd16e78faffe78489d34d064d5618b43 /sim/frv/profile-fr550.c | |
parent | 7c3f9ad027b9ec2906f3367ca7be18e5fb8f6893 (diff) | |
download | fsf-binutils-gdb-e930b1f54ff2768c5818eb0a450b1d98d46d273d.zip fsf-binutils-gdb-e930b1f54ff2768c5818eb0a450b1d98d46d273d.tar.gz fsf-binutils-gdb-e930b1f54ff2768c5818eb0a450b1d98d46d273d.tar.bz2 |
2003-10-06 Dave Brolley <brolley@redhat.com>
* profile-fr550.[ch]: New files.
* configure.in: Move frv handling to alphabetically correct placement.
* Makefile.in: Add fr550 support.
* frv-sim.h,frv.c,interrups.c,memory.c,mloop.in,pipeline.c,
profile.[ch],registers.c,traps.c: Add fr550 support.
* arch.c,arch.h,cpu.c,cpu.h,cpuall.h,model.h,decode.c,decode.h,sem.c:
Regenerate.
Diffstat (limited to 'sim/frv/profile-fr550.c')
-rw-r--r-- | sim/frv/profile-fr550.c | 2664 |
1 files changed, 2664 insertions, 0 deletions
diff --git a/sim/frv/profile-fr550.c b/sim/frv/profile-fr550.c new file mode 100644 index 0000000..c92cf97 --- /dev/null +++ b/sim/frv/profile-fr550.c @@ -0,0 +1,2664 @@ +/* frv simulator fr550 dependent profiling code. + + Copyright (C) 2003 Free Software Foundation, Inc. + Contributed by Red Hat + +This file is part of the GNU simulators. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the 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 of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with 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-fr550.h" + +/* Initialize cycle counting for an insn. + FIRST_P is non-zero if this is the first insn in a set of parallel + insns. */ +void +fr550_model_insn_before (SIM_CPU *cpu, int first_p) +{ + if (first_p) + { + MODEL_FR550_DATA *d = CPU_MODEL_DATA (cpu); + d->cur_fr_load = d->prev_fr_load; + d->cur_fr_complex_1 = d->prev_fr_complex_1; + d->cur_fr_complex_2 = d->prev_fr_complex_2; + d->cur_ccr_complex = d->prev_ccr_complex; + d->cur_acc_mmac = d->prev_acc_mmac; + } +} + +/* 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. */ +void +fr550_model_insn_after (SIM_CPU *cpu, int last_p, int cycles) +{ + if (last_p) + { + MODEL_FR550_DATA *d = CPU_MODEL_DATA (cpu); + d->prev_fr_load = d->cur_fr_load; + d->prev_fr_complex_1 = d->cur_fr_complex_1; + d->prev_fr_complex_2 = d->cur_fr_complex_2; + d->prev_ccr_complex = d->cur_ccr_complex; + d->prev_acc_mmac = d->cur_acc_mmac; + } +} + +static void fr550_reset_fr_flags (SIM_CPU *cpu, INT fr); +static void fr550_reset_ccr_flags (SIM_CPU *cpu, INT ccr); +static void fr550_reset_acc_flags (SIM_CPU *cpu, INT acc); + +static void +set_use_is_fr_load (SIM_CPU *cpu, INT fr) +{ + MODEL_FR550_DATA *d = CPU_MODEL_DATA (cpu); + fr550_reset_fr_flags (cpu, (fr)); + d->cur_fr_load |= (((DI)1) << (fr)); +} + +static void +set_use_not_fr_load (SIM_CPU *cpu, INT fr) +{ + MODEL_FR550_DATA *d = CPU_MODEL_DATA (cpu); + d->cur_fr_load &= ~(((DI)1) << (fr)); +} + +static int +use_is_fr_load (SIM_CPU *cpu, INT fr) +{ + MODEL_FR550_DATA *d = CPU_MODEL_DATA (cpu); + return d->prev_fr_load & (((DI)1) << (fr)); +} + +static void +set_use_is_fr_complex_1 (SIM_CPU *cpu, INT fr) +{ + MODEL_FR550_DATA *d = CPU_MODEL_DATA (cpu); + fr550_reset_fr_flags (cpu, (fr)); + d->cur_fr_complex_1 |= (((DI)1) << (fr)); +} + +static void +set_use_not_fr_complex_1 (SIM_CPU *cpu, INT fr) +{ + MODEL_FR550_DATA *d = CPU_MODEL_DATA (cpu); + d->cur_fr_complex_1 &= ~(((DI)1) << (fr)); +} + +static int +use_is_fr_complex_1 (SIM_CPU *cpu, INT fr) +{ + MODEL_FR550_DATA *d = CPU_MODEL_DATA (cpu); + return d->prev_fr_complex_1 & (((DI)1) << (fr)); +} + +static void +set_use_is_fr_complex_2 (SIM_CPU *cpu, INT fr) +{ + MODEL_FR550_DATA *d = CPU_MODEL_DATA (cpu); + fr550_reset_fr_flags (cpu, (fr)); + d->cur_fr_complex_2 |= (((DI)1) << (fr)); +} + +static void +set_use_not_fr_complex_2 (SIM_CPU *cpu, INT fr) +{ + MODEL_FR550_DATA *d = CPU_MODEL_DATA (cpu); + d->cur_fr_complex_2 &= ~(((DI)1) << (fr)); +} + +static int +use_is_fr_complex_2 (SIM_CPU *cpu, INT fr) +{ + MODEL_FR550_DATA *d = CPU_MODEL_DATA (cpu); + return d->prev_fr_complex_2 & (((DI)1) << (fr)); +} + +static void +set_use_is_ccr_complex (SIM_CPU *cpu, INT ccr) +{ + MODEL_FR550_DATA *d = CPU_MODEL_DATA (cpu); + fr550_reset_ccr_flags (cpu, (ccr)); + d->cur_ccr_complex |= (((SI)1) << (ccr)); +} + +static void +set_use_not_ccr_complex (SIM_CPU *cpu, INT ccr) +{ + MODEL_FR550_DATA *d = CPU_MODEL_DATA (cpu); + d->cur_ccr_complex &= ~(((SI)1) << (ccr)); +} + +static int +use_is_ccr_complex (SIM_CPU *cpu, INT ccr) +{ + MODEL_FR550_DATA *d = CPU_MODEL_DATA (cpu); + return d->prev_ccr_complex & (((SI)1) << (ccr)); +} + +static void +set_use_is_acc_mmac (SIM_CPU *cpu, INT acc) +{ + MODEL_FR550_DATA *d = CPU_MODEL_DATA (cpu); + fr550_reset_acc_flags (cpu, (acc)); + d->cur_acc_mmac |= (((DI)1) << (acc)); +} + +static void +set_use_not_acc_mmac (SIM_CPU *cpu, INT acc) +{ + MODEL_FR550_DATA *d = CPU_MODEL_DATA (cpu); + d->cur_acc_mmac &= ~(((DI)1) << (acc)); +} + +static int +use_is_acc_mmac (SIM_CPU *cpu, INT acc) +{ + MODEL_FR550_DATA *d = CPU_MODEL_DATA (cpu); + return d->prev_acc_mmac & (((DI)1) << (acc)); +} + +static void +fr550_reset_fr_flags (SIM_CPU *cpu, INT fr) +{ + set_use_not_fr_load (cpu, fr); + set_use_not_fr_complex_1 (cpu, fr); + set_use_not_fr_complex_2 (cpu, fr); +} + +static void +fr550_reset_ccr_flags (SIM_CPU *cpu, INT ccr) +{ + set_use_not_ccr_complex (cpu, ccr); +} + +static void +fr550_reset_acc_flags (SIM_CPU *cpu, INT acc) +{ + set_use_not_acc_mmac (cpu, acc); +} + +/* Detect overlap between two register ranges. Works if one of the registers + is -1 with width 1 (i.e. undefined), but not both. */ +#define REG_OVERLAP(r1, w1, r2, w2) ( \ + (r1) + (w1) - 1 >= (r2) && (r2) + (w2) - 1 >= (r1) \ +) + +/* Latency of floating point registers may be less than recorded when followed + by another floating point insn. */ +static void +adjust_float_register_busy (SIM_CPU *cpu, + INT in_FRi, int iwidth, + INT in_FRj, int jwidth, + INT out_FRk, int kwidth) +{ + int i; + /* The latency of FRk may be less than previously recorded. + See Table 14-15 in the LSI. */ + if (in_FRi >= 0) + { + for (i = 0; i < iwidth; ++i) + { + if (! REG_OVERLAP (in_FRi + i, 1, out_FRk, kwidth)) + if (use_is_fr_load (cpu, in_FRi + i)) + decrease_FR_busy (cpu, in_FRi + i, 1); + else + enforce_full_fr_latency (cpu, in_FRi + i); + } + } + + if (in_FRj >= 0) + { + for (i = 0; i < jwidth; ++i) + { + if (! REG_OVERLAP (in_FRj + i, 1, in_FRi, iwidth) + && ! REG_OVERLAP (in_FRj + i, 1, out_FRk, kwidth)) + if (use_is_fr_load (cpu, in_FRj + i)) + decrease_FR_busy (cpu, in_FRj + i, 1); + else + enforce_full_fr_latency (cpu, in_FRj + i); + } + } + + if (out_FRk >= 0) + { + for (i = 0; i < kwidth; ++i) + { + if (! REG_OVERLAP (out_FRk + i, 1, in_FRi, iwidth) + && ! REG_OVERLAP (out_FRk + i, 1, in_FRj, jwidth)) + { + if (use_is_fr_complex_1 (cpu, out_FRk + i)) + decrease_FR_busy (cpu, out_FRk + i, 1); + else if (use_is_fr_complex_2 (cpu, out_FRk + i)) + decrease_FR_busy (cpu, out_FRk + i, 2); + else + enforce_full_fr_latency (cpu, out_FRk + i); + } + } + } +} + +static void +restore_float_register_busy (SIM_CPU *cpu, + INT in_FRi, int iwidth, + INT in_FRj, int jwidth, + INT out_FRk, int kwidth) +{ + int i; + /* The latency of FRk may be less than previously recorded. + See Table 14-15 in the LSI. */ + if (in_FRi >= 0) + { + for (i = 0; i < iwidth; ++i) + { + if (! REG_OVERLAP (in_FRi + i, 1, out_FRk, kwidth)) + if (use_is_fr_load (cpu, in_FRi + i)) + increase_FR_busy (cpu, in_FRi + i, 1); + } + } + + if (in_FRj >= 0) + { + for (i = 0; i < jwidth; ++i) + { + if (! REG_OVERLAP (in_FRj + i, 1, in_FRi, iwidth) + && ! REG_OVERLAP (in_FRj + i, 1, out_FRk, kwidth)) + if (use_is_fr_load (cpu, in_FRj + i)) + increase_FR_busy (cpu, in_FRj + i, 1); + } + } + + if (out_FRk >= 0) + { + for (i = 0; i < kwidth; ++i) + { + if (! REG_OVERLAP (out_FRk + i, 1, in_FRi, iwidth) + && ! REG_OVERLAP (out_FRk + i, 1, in_FRj, jwidth)) + { + if (use_is_fr_complex_1 (cpu, out_FRk + i)) + increase_FR_busy (cpu, out_FRk + i, 1); + else if (use_is_fr_complex_2 (cpu, out_FRk + i)) + increase_FR_busy (cpu, out_FRk + i, 2); + } + } + } +} + +/* Latency of floating point registers may be less than recorded when used in a + media insns and followed by another media insn. */ +static void +adjust_float_register_busy_for_media (SIM_CPU *cpu, + INT in_FRi, int iwidth, + INT in_FRj, int jwidth, + INT out_FRk, int kwidth) +{ + int i; + /* The latency of FRk may be less than previously recorded. + See Table 14-15 in the LSI. */ + if (out_FRk >= 0) + { + for (i = 0; i < kwidth; ++i) + { + if (! REG_OVERLAP (out_FRk + i, 1, in_FRi, iwidth) + && ! REG_OVERLAP (out_FRk + i, 1, in_FRj, jwidth)) + { + if (use_is_fr_complex_1 (cpu, out_FRk + i)) + decrease_FR_busy (cpu, out_FRk + i, 1); + else + enforce_full_fr_latency (cpu, out_FRk + i); + } + } + } +} + +static void +restore_float_register_busy_for_media (SIM_CPU *cpu, + INT in_FRi, int iwidth, + INT in_FRj, int jwidth, + INT out_FRk, int kwidth) +{ + int i; + if (out_FRk >= 0) + { + for (i = 0; i < kwidth; ++i) + { + if (! REG_OVERLAP (out_FRk + i, 1, in_FRi, iwidth) + && ! REG_OVERLAP (out_FRk + i, 1, in_FRj, jwidth)) + { + if (use_is_fr_complex_1 (cpu, out_FRk + i)) + increase_FR_busy (cpu, out_FRk + i, 1); + } + } + } +} + +/* Latency of accumulator registers may be less than recorded when used in a + media insns and followed by another media insn. */ +static void +adjust_acc_busy_for_mmac (SIM_CPU *cpu, + INT in_ACC, int inwidth, + INT out_ACC, int outwidth) +{ + int i; + /* The latency of an accumulator may be less than previously recorded. + See Table 14-15 in the LSI. */ + if (in_ACC >= 0) + { + for (i = 0; i < inwidth; ++i) + { + if (use_is_acc_mmac (cpu, in_ACC + i)) + decrease_ACC_busy (cpu, in_ACC + i, 1); + else + enforce_full_acc_latency (cpu, in_ACC + i); + } + } + if (out_ACC >= 0) + { + for (i = 0; i < outwidth; ++i) + { + if (! REG_OVERLAP (out_ACC + i, 1, in_ACC, inwidth)) + { + if (use_is_acc_mmac (cpu, out_ACC + i)) + decrease_ACC_busy (cpu, out_ACC + i, 1); + else + enforce_full_acc_latency (cpu, out_ACC + i); + } + } + } +} + +static void +restore_acc_busy_for_mmac (SIM_CPU *cpu, + INT in_ACC, int inwidth, + INT out_ACC, int outwidth) +{ + int i; + if (in_ACC >= 0) + { + for (i = 0; i < inwidth; ++i) + { + if (use_is_acc_mmac (cpu, in_ACC + i)) + increase_ACC_busy (cpu, in_ACC + i, 1); + } + } + if (out_ACC >= 0) + { + for (i = 0; i < outwidth; ++i) + { + if (! REG_OVERLAP (out_ACC + i, 1, in_ACC, inwidth)) + { + if (use_is_acc_mmac (cpu, out_ACC + i)) + increase_ACC_busy (cpu, out_ACC + i, 1); + } + } + } +} + +int +frvbf_model_fr550_u_exec (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced) +{ + return idesc->timing->units[unit_num].done; +} + +int +frvbf_model_fr550_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; + + /* 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. */ + 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; + } + + fr550_reset_ccr_flags (cpu, out_ICCi_1); + + /* GRk is available immediately to the next VLIW insn as is ICCi_1. */ + cycles = idesc->timing->units[unit_num].done; + return cycles; +} + +int +frvbf_model_fr550_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. */ + 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 1 cycles. */ + cycles = idesc->timing->units[unit_num].done; + update_GRdouble_latency (cpu, out_GRk, cycles + 1); + + /* ICCi_1 has a latency of 1 cycle. */ + update_CCR_latency (cpu, out_ICCi_1, cycles + 1); + + fr550_reset_ccr_flags (cpu, out_ICCi_1); + + return cycles; +} + +int +frvbf_model_fr550_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. */ + 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 18 cycles! */ + cycles = idesc->timing->units[unit_num].done; + update_GR_latency (cpu, out_GRk, cycles + 18); + + /* ICCi_1 has a latency of 18 cycles. */ + update_CCR_latency (cpu, out_ICCi_1, cycles + 18); + + 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); + + fr550_reset_ccr_flags (cpu, out_ICCi_1); + + return cycles; +} + +int +frvbf_model_fr550_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. */ + 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 + the first taken branch in a vliw insn. */ + ps = CPU_PROFILE_STATE (cpu); + if (! ps->vliw_branch_taken) + { + /* (1 << 4): The pc is the 5th element in inputs, outputs. + ??? can be cleaned up */ + PROFILE_DATA *p = CPU_PROFILE_DATA (cpu); + int taken = (referenced & (1 << 4)) != 0; + if (taken) + { + ++PROFILE_MODEL_TAKEN_COUNT (p); + ps->vliw_branch_taken = 1; + } + else + ++PROFILE_MODEL_UNTAKEN_COUNT (p); + } + + cycles = idesc->timing->units[unit_num].done; + return cycles; +} + +int +frvbf_model_fr550_u_trap (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; + + 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. */ + 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; + } + + cycles = idesc->timing->units[unit_num].done; + return cycles; +} + +int +frvbf_model_fr550_u_check (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_ICCi_3, INT in_FCCi_3) +{ + /* Modelling for this unit is the same as for fr500. */ + return frvbf_model_fr500_u_check (cpu, idesc, unit_num, referenced, + in_ICCi_3, in_FCCi_3); +} + +int +frvbf_model_fr550_u_set_hilo (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT out_GRkhi, INT out_GRklo) +{ + int cycles; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + { + /* The entire VLIW insn must wait if there is a dependency on a GR + which is not ready yet. */ + vliw_wait_for_GR (cpu, out_GRkhi); + vliw_wait_for_GR (cpu, out_GRklo); + handle_resource_wait (cpu); + load_wait_for_GR (cpu, out_GRkhi); + load_wait_for_GR (cpu, out_GRklo); + trace_vliw_wait_cycles (cpu); + return 0; + } + + /* GRk is available immediately to the next VLIW insn. */ + cycles = idesc->timing->units[unit_num].done; + + return cycles; +} + +int +frvbf_model_fr550_u_gr_load (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_GRi, INT in_GRj, + INT out_GRk, INT out_GRdoublek) +{ + int cycles; + + 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. */ + vliw_wait_for_GR (cpu, in_GRi); + vliw_wait_for_GR (cpu, in_GRj); + vliw_wait_for_GR (cpu, out_GRk); + vliw_wait_for_GRdouble (cpu, out_GRdoublek); + 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); + load_wait_for_GRdouble (cpu, out_GRdoublek); + trace_vliw_wait_cycles (cpu); + return 0; + } + + cycles = idesc->timing->units[unit_num].done; + + /* The latency of GRk for a load will depend on how long it takes to retrieve + the the data from the cache or memory. */ + update_GR_latency_for_load (cpu, out_GRk, cycles); + update_GRdouble_latency_for_load (cpu, out_GRdoublek, cycles); + + if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING)) + { + /* GNER has a latency of 2 cycles. */ + update_SPR_latency (cpu, GNER_FOR_GR (out_GRk), cycles + 2); + update_SPR_latency (cpu, GNER_FOR_GR (out_GRdoublek), cycles + 2); + } + + return cycles; +} + +int +frvbf_model_fr550_u_gr_store (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_GRi, INT in_GRj, + INT in_GRk, INT in_GRdoublek) +{ + int cycles; + + 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. */ + vliw_wait_for_GR (cpu, in_GRi); + vliw_wait_for_GR (cpu, in_GRj); + vliw_wait_for_GR (cpu, in_GRk); + vliw_wait_for_GRdouble (cpu, in_GRdoublek); + handle_resource_wait (cpu); + load_wait_for_GR (cpu, in_GRi); + load_wait_for_GR (cpu, in_GRj); + load_wait_for_GR (cpu, in_GRk); + load_wait_for_GRdouble (cpu, in_GRdoublek); + trace_vliw_wait_cycles (cpu); + return 0; + } + + /* The target register is available immediately. */ + cycles = idesc->timing->units[unit_num].done; + + return cycles; +} + +int +frvbf_model_fr550_u_fr_load (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_GRi, INT in_GRj, + INT out_FRk, INT out_FRdoublek) +{ + int cycles; + 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. */ + adjust_float_register_busy (cpu, -1, 1, -1, 1, out_FRk, 1); + adjust_float_register_busy (cpu, -1, 1, -1, 1, out_FRdoublek, 2); + vliw_wait_for_GR (cpu, in_GRi); + vliw_wait_for_GR (cpu, in_GRj); + vliw_wait_for_FR (cpu, out_FRk); + vliw_wait_for_FRdouble (cpu, out_FRdoublek); + if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING)) + { + vliw_wait_for_SPR (cpu, FNER_FOR_FR (out_FRk)); + vliw_wait_for_SPR (cpu, FNER_FOR_FR (out_FRdoublek)); + } + handle_resource_wait (cpu); + load_wait_for_GR (cpu, in_GRi); + load_wait_for_GR (cpu, in_GRj); + load_wait_for_FR (cpu, out_FRk); + load_wait_for_FRdouble (cpu, out_FRdoublek); + trace_vliw_wait_cycles (cpu); + return 0; + } + + cycles = idesc->timing->units[unit_num].done; + + /* The latency of FRk for a load will depend on how long it takes to retrieve + the the data from the cache or memory. */ + update_FR_latency_for_load (cpu, out_FRk, cycles); + update_FRdouble_latency_for_load (cpu, out_FRdoublek, cycles); + + if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING)) + { + /* FNER has a latency of 3 cycles. */ + update_SPR_latency (cpu, FNER_FOR_FR (out_FRk), cycles + 3); + update_SPR_latency (cpu, FNER_FOR_FR (out_FRdoublek), cycles + 3); + } + + if (out_FRk >= 0) + set_use_is_fr_load (cpu, out_FRk); + if (out_FRdoublek >= 0) + { + set_use_is_fr_load (cpu, out_FRdoublek); + set_use_is_fr_load (cpu, out_FRdoublek + 1); + } + + return cycles; +} + +int +frvbf_model_fr550_u_fr_store (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_GRi, INT in_GRj, + INT in_FRk, INT in_FRdoublek) +{ + int cycles; + + 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. */ + adjust_float_register_busy (cpu, in_FRk, 1, -1, 1, -1, 1); + adjust_float_register_busy (cpu, in_FRdoublek, 2, -1, 1, -1, 1); + vliw_wait_for_GR (cpu, in_GRi); + vliw_wait_for_GR (cpu, in_GRj); + vliw_wait_for_FR (cpu, in_FRk); + vliw_wait_for_FRdouble (cpu, in_FRdoublek); + handle_resource_wait (cpu); + load_wait_for_GR (cpu, in_GRi); + load_wait_for_GR (cpu, in_GRj); + load_wait_for_FR (cpu, in_FRk); + load_wait_for_FRdouble (cpu, in_FRdoublek); + trace_vliw_wait_cycles (cpu); + return 0; + } + + /* The target register is available immediately. */ + cycles = idesc->timing->units[unit_num].done; + + return cycles; +} + +int +frvbf_model_fr550_u_ici (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_GRi, INT in_GRj) +{ + int cycles; + + 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. */ + vliw_wait_for_GR (cpu, in_GRi); + vliw_wait_for_GR (cpu, in_GRj); + 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; + } + + cycles = idesc->timing->units[unit_num].done; + request_cache_invalidate (cpu, CPU_INSN_CACHE (cpu), cycles); + return cycles; +} + +int +frvbf_model_fr550_u_dci (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_GRi, INT in_GRj) +{ + int cycles; + + 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. */ + vliw_wait_for_GR (cpu, in_GRi); + vliw_wait_for_GR (cpu, in_GRj); + 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; + } + + cycles = idesc->timing->units[unit_num].done; + request_cache_invalidate (cpu, CPU_DATA_CACHE (cpu), cycles); + return cycles; +} + +int +frvbf_model_fr550_u_dcf (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_GRi, INT in_GRj) +{ + int cycles; + + 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. */ + vliw_wait_for_GR (cpu, in_GRi); + vliw_wait_for_GR (cpu, in_GRj); + 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; + } + + cycles = idesc->timing->units[unit_num].done; + request_cache_flush (cpu, CPU_DATA_CACHE (cpu), cycles); + return cycles; +} + +int +frvbf_model_fr550_u_icpl (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_GRi, INT in_GRj) +{ + int cycles; + + 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. */ + vliw_wait_for_GR (cpu, in_GRi); + vliw_wait_for_GR (cpu, in_GRj); + 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; + } + + cycles = idesc->timing->units[unit_num].done; + request_cache_preload (cpu, CPU_INSN_CACHE (cpu), cycles); + return cycles; +} + +int +frvbf_model_fr550_u_dcpl (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_GRi, INT in_GRj) +{ + int cycles; + + 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. */ + vliw_wait_for_GR (cpu, in_GRi); + vliw_wait_for_GR (cpu, in_GRj); + 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; + } + + cycles = idesc->timing->units[unit_num].done; + request_cache_preload (cpu, CPU_DATA_CACHE (cpu), cycles); + return cycles; +} + +int +frvbf_model_fr550_u_icul (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_GRi, INT in_GRj) +{ + int cycles; + + 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. */ + vliw_wait_for_GR (cpu, in_GRi); + vliw_wait_for_GR (cpu, in_GRj); + 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; + } + + cycles = idesc->timing->units[unit_num].done; + request_cache_unlock (cpu, CPU_INSN_CACHE (cpu), cycles); + return cycles; +} + +int +frvbf_model_fr550_u_dcul (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_GRi, INT in_GRj) +{ + int cycles; + + 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. */ + vliw_wait_for_GR (cpu, in_GRi); + vliw_wait_for_GR (cpu, in_GRj); + 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; + } + + cycles = idesc->timing->units[unit_num].done; + request_cache_unlock (cpu, CPU_DATA_CACHE (cpu), cycles); + return cycles; +} + +int +frvbf_model_fr550_u_float_arith (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_FRi, INT in_FRj, + INT in_FRdoublei, INT in_FRdoublej, + INT out_FRk, INT out_FRdoublek) +{ + int cycles; + FRV_PROFILE_STATE *ps; + FRV_VLIW *vliw; + int slot; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + /* The preprocessing can execute right away. */ + cycles = idesc->timing->units[unit_num].done; + + /* The post processing must wait if there is a dependency on a FR + which is not ready yet. */ + adjust_float_register_busy (cpu, in_FRi, 1, in_FRj, 1, out_FRk, 1); + adjust_float_register_busy (cpu, in_FRdoublei, 2, in_FRdoublej, 2, out_FRdoublek, 2); + ps = CPU_PROFILE_STATE (cpu); + ps->post_wait = cycles; + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_float (cpu, slot); + post_wait_for_FR (cpu, in_FRi); + post_wait_for_FR (cpu, in_FRj); + post_wait_for_FR (cpu, out_FRk); + post_wait_for_FRdouble (cpu, in_FRdoublei); + post_wait_for_FRdouble (cpu, in_FRdoublej); + post_wait_for_FRdouble (cpu, out_FRdoublek); + if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING)) + { + post_wait_for_SPR (cpu, FNER_FOR_FR (out_FRk)); + post_wait_for_SPR (cpu, FNER_FOR_FR (out_FRdoublek)); + } + restore_float_register_busy (cpu, in_FRi, 1, in_FRj, 1, out_FRk, 1); + restore_float_register_busy (cpu, in_FRdoublei, 2, in_FRdoublej, 2, out_FRdoublek, 2); + + /* The latency of FRk will be at least the latency of the other inputs. */ + update_FR_latency (cpu, out_FRk, ps->post_wait); + update_FRdouble_latency (cpu, out_FRdoublek, ps->post_wait); + + if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING)) + { + update_SPR_latency (cpu, FNER_FOR_FR (out_FRk), ps->post_wait); + update_SPR_latency (cpu, FNER_FOR_FR (out_FRdoublek), ps->post_wait); + } + + /* Once initiated, post-processing will take 2 cycles. */ + update_FR_ptime (cpu, out_FRk, 2); + update_FRdouble_ptime (cpu, out_FRdoublek, 2); + if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING)) + { + update_SPR_ptime (cpu, FNER_FOR_FR (out_FRk), 2); + update_SPR_ptime (cpu, FNER_FOR_FR (out_FRdoublek), 2); + } + + /* Mark this use of the register as a floating point op. */ + if (out_FRk >= 0) + set_use_is_fr_complex_2 (cpu, out_FRk); + if (out_FRdoublek >= 0) + { + set_use_is_fr_complex_2 (cpu, out_FRdoublek); + if (out_FRdoublek < 63) + set_use_is_fr_complex_2 (cpu, out_FRdoublek + 1); + } + + /* the media point unit resource has a latency of 4 cycles */ + update_media_resource_latency (cpu, slot, cycles + 4); + + return cycles; +} + +int +frvbf_model_fr550_u_float_dual_arith (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_FRi, INT in_FRj, + INT in_FRdoublei, INT in_FRdoublej, + INT out_FRk, INT out_FRdoublek) +{ + int cycles; + INT dual_FRi; + INT dual_FRj; + INT dual_FRk; + INT dual_FRdoublei; + INT dual_FRdoublej; + INT dual_FRdoublek; + FRV_PROFILE_STATE *ps; + FRV_VLIW *vliw; + int slot; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + /* The preprocessing can execute right away. */ + cycles = idesc->timing->units[unit_num].done; + + /* The post processing must wait if there is a dependency on a FR + which is not ready yet. */ + dual_FRi = DUAL_REG (in_FRi); + dual_FRj = DUAL_REG (in_FRj); + dual_FRk = DUAL_REG (out_FRk); + dual_FRdoublei = DUAL_DOUBLE (in_FRdoublei); + dual_FRdoublej = DUAL_DOUBLE (in_FRdoublej); + dual_FRdoublek = DUAL_DOUBLE (out_FRdoublek); + + adjust_float_register_busy (cpu, in_FRi, 2, in_FRj, 2, out_FRk, 2); + adjust_float_register_busy (cpu, in_FRdoublei, 4, in_FRdoublej, 4, out_FRdoublek, 4); + ps = CPU_PROFILE_STATE (cpu); + ps->post_wait = cycles; + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_float (cpu, slot); + post_wait_for_FR (cpu, in_FRi); + post_wait_for_FR (cpu, in_FRj); + post_wait_for_FR (cpu, out_FRk); + post_wait_for_FR (cpu, dual_FRi); + post_wait_for_FR (cpu, dual_FRj); + post_wait_for_FR (cpu, dual_FRk); + post_wait_for_FRdouble (cpu, in_FRdoublei); + post_wait_for_FRdouble (cpu, in_FRdoublej); + post_wait_for_FRdouble (cpu, out_FRdoublek); + post_wait_for_FRdouble (cpu, dual_FRdoublei); + post_wait_for_FRdouble (cpu, dual_FRdoublej); + post_wait_for_FRdouble (cpu, dual_FRdoublek); + if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING)) + { + post_wait_for_SPR (cpu, FNER_FOR_FR (out_FRk)); + post_wait_for_SPR (cpu, FNER_FOR_FR (dual_FRk)); + post_wait_for_SPR (cpu, FNER_FOR_FR (out_FRdoublek)); + post_wait_for_SPR (cpu, FNER_FOR_FR (dual_FRdoublek)); + } + restore_float_register_busy (cpu, in_FRi, 2, in_FRj, 2, out_FRk, 2); + restore_float_register_busy (cpu, in_FRdoublei, 4, in_FRdoublej, 4, out_FRdoublek, 4); + + /* The latency of FRk will be at least the latency of the other inputs. */ + update_FR_latency (cpu, out_FRk, ps->post_wait); + update_FR_latency (cpu, dual_FRk, ps->post_wait); + update_FRdouble_latency (cpu, out_FRdoublek, ps->post_wait); + update_FRdouble_latency (cpu, dual_FRdoublek, ps->post_wait); + + if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING)) + { + update_SPR_latency (cpu, FNER_FOR_FR (out_FRk), ps->post_wait); + update_SPR_latency (cpu, FNER_FOR_FR (dual_FRk), ps->post_wait); + update_SPR_latency (cpu, FNER_FOR_FR (out_FRdoublek), ps->post_wait); + update_SPR_latency (cpu, FNER_FOR_FR (dual_FRdoublek), ps->post_wait); + } + + /* Once initiated, post-processing will take 3 cycles. */ + update_FR_ptime (cpu, out_FRk, 3); + update_FR_ptime (cpu, dual_FRk, 3); + update_FRdouble_ptime (cpu, out_FRdoublek, 3); + update_FRdouble_ptime (cpu, dual_FRdoublek, 3); + + if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING)) + { + update_SPR_ptime (cpu, FNER_FOR_FR (out_FRk), 3); + update_SPR_ptime (cpu, FNER_FOR_FR (dual_FRk), 3); + update_SPR_ptime (cpu, FNER_FOR_FR (out_FRdoublek), 3); + update_SPR_ptime (cpu, FNER_FOR_FR (dual_FRdoublek), 3); + } + + /* Mark this use of the register as a floating point op. */ + if (out_FRk >= 0) + fr550_reset_fr_flags (cpu, out_FRk); + if (dual_FRk >= 0) + fr550_reset_fr_flags (cpu, dual_FRk); + if (out_FRdoublek >= 0) + { + fr550_reset_fr_flags (cpu, out_FRdoublek); + if (out_FRdoublek < 63) + fr550_reset_fr_flags (cpu, out_FRdoublek + 1); + } + if (dual_FRdoublek >= 0) + { + fr550_reset_fr_flags (cpu, dual_FRdoublek); + if (dual_FRdoublek < 63) + fr550_reset_fr_flags (cpu, dual_FRdoublek + 1); + } + + /* the media point unit resource has a latency of 5 cycles */ + update_media_resource_latency (cpu, slot, cycles + 5); + + return cycles; +} + +int +frvbf_model_fr550_u_float_div (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_FRi, INT in_FRj, INT out_FRk) +{ + int cycles; + FRV_VLIW *vliw; + int slot; + FRV_PROFILE_STATE *ps; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + cycles = idesc->timing->units[unit_num].done; + + /* The post processing must wait if there is a dependency on a FR + which is not ready yet. */ + adjust_float_register_busy (cpu, in_FRi, 1, in_FRj, 1, out_FRk, 1); + ps = CPU_PROFILE_STATE (cpu); + ps->post_wait = cycles; + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_float (cpu, slot); + post_wait_for_fdiv (cpu, slot); + post_wait_for_FR (cpu, in_FRi); + post_wait_for_FR (cpu, in_FRj); + post_wait_for_FR (cpu, out_FRk); + if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING)) + post_wait_for_SPR (cpu, FNER_FOR_FR (out_FRk)); + restore_float_register_busy (cpu, in_FRi, 1, in_FRj, 1, out_FRk, 1); + + /* The latency of FRk will be at least the latency of the other inputs. */ + /* Once initiated, post-processing will take 9 cycles. */ + update_FR_latency (cpu, out_FRk, ps->post_wait); + update_FR_ptime (cpu, out_FRk, 9); + + if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING)) + { + /* FNER has a latency of 9 cycles. */ + update_SPR_latency (cpu, FNER_FOR_FR (out_FRk), ps->post_wait); + update_SPR_ptime (cpu, FNER_FOR_FR (out_FRk), 9); + } + + /* The latency of the fdiv unit will be at least the latency of the other + inputs. Once initiated, post-processing will take 9 cycles. */ + update_fdiv_resource_latency (cpu, slot, ps->post_wait + 9); + + /* the media point unit resource has a latency of 11 cycles */ + update_media_resource_latency (cpu, slot, cycles + 11); + + fr550_reset_fr_flags (cpu, out_FRk); + + return cycles; +} + +int +frvbf_model_fr550_u_float_sqrt (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_FRj, INT in_FRdoublej, + INT out_FRk, INT out_FRdoublek) +{ + int cycles; + FRV_VLIW *vliw; + int slot; + FRV_PROFILE_STATE *ps; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + cycles = idesc->timing->units[unit_num].done; + + /* The post processing must wait if there is a dependency on a FR + which is not ready yet. */ + adjust_float_register_busy (cpu, -1, 1, in_FRj, 1, out_FRk, 1); + adjust_float_register_busy (cpu, -1, 1, in_FRdoublej, 2, out_FRdoublek, 2); + ps = CPU_PROFILE_STATE (cpu); + ps->post_wait = cycles; + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_float (cpu, slot); + post_wait_for_fsqrt (cpu, slot); + post_wait_for_FR (cpu, in_FRj); + post_wait_for_FR (cpu, out_FRk); + post_wait_for_FRdouble (cpu, in_FRdoublej); + post_wait_for_FRdouble (cpu, out_FRdoublek); + if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING)) + { + post_wait_for_SPR (cpu, FNER_FOR_FR (out_FRk)); + post_wait_for_SPR (cpu, FNER_FOR_FR (out_FRdoublek)); + } + restore_float_register_busy (cpu, -1, 1, in_FRj, 1, out_FRk, 1); + restore_float_register_busy (cpu, -1, 1, in_FRdoublej, 2, out_FRdoublek, 2); + + /* The latency of FRk will be at least the latency of the other inputs. */ + update_FR_latency (cpu, out_FRk, ps->post_wait); + update_FRdouble_latency (cpu, out_FRdoublek, ps->post_wait); + + if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING)) + { + /* FNER has a latency of 14 cycles. */ + update_SPR_latency (cpu, FNER_FOR_FR (out_FRk), ps->post_wait); + update_SPR_latency (cpu, FNER_FOR_FR (out_FRdoublek), ps->post_wait); + } + + /* Once initiated, post-processing will take 14 cycles. */ + update_FR_ptime (cpu, out_FRk, 14); + update_FRdouble_ptime (cpu, out_FRdoublek, 14); + + if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING)) + { + /* FNER has a latency of 14 cycles. */ + update_SPR_ptime (cpu, FNER_FOR_FR (out_FRk), 14); + update_SPR_ptime (cpu, FNER_FOR_FR (out_FRdoublek), 14); + } + + /* The latency of the sqrt unit will be the latency of the other + inputs plus 14 cycles. */ + update_fsqrt_resource_latency (cpu, slot, ps->post_wait + 14); + + fr550_reset_fr_flags (cpu, out_FRk); + if (out_FRdoublek != -1) + { + fr550_reset_fr_flags (cpu, out_FRdoublek); + fr550_reset_fr_flags (cpu, out_FRdoublek + 1); + } + + /* the media point unit resource has a latency of 16 cycles */ + update_media_resource_latency (cpu, slot, cycles + 16); + + return cycles; +} + +int +frvbf_model_fr550_u_float_compare (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_FRi, INT in_FRj, + INT in_FRdoublei, INT in_FRdoublej, + INT out_FCCi_2) +{ + int cycles; + FRV_PROFILE_STATE *ps; + FRV_VLIW *vliw; + int slot; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + /* The preprocessing can execute right away. */ + cycles = idesc->timing->units[unit_num].done; + + /* The post processing must wait if there is a dependency on a FR + which is not ready yet. */ + adjust_float_register_busy (cpu, in_FRi, 1, in_FRj, 1, -1, 1); + adjust_float_register_busy (cpu, in_FRdoublei, 2, in_FRdoublej, 2, -1, 1); + ps = CPU_PROFILE_STATE (cpu); + ps->post_wait = cycles; + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_float (cpu, slot); + post_wait_for_FR (cpu, in_FRi); + post_wait_for_FR (cpu, in_FRj); + post_wait_for_FRdouble (cpu, in_FRdoublei); + post_wait_for_FRdouble (cpu, in_FRdoublej); + post_wait_for_CCR (cpu, out_FCCi_2); + restore_float_register_busy (cpu, in_FRi, 1, in_FRj, 1, -1, 1); + restore_float_register_busy (cpu, in_FRdoublei, 2, in_FRdoublej, 2, -1, 1); + + /* The latency of FCCi_2 will be the latency of the other inputs plus 2 + cycles. */ + update_CCR_latency (cpu, out_FCCi_2, ps->post_wait + 2); + + /* the media point unit resource has a latency of 4 cycles */ + update_media_resource_latency (cpu, slot, cycles + 4); + + set_use_is_ccr_complex (cpu, out_FCCi_2); + + return cycles; +} + +int +frvbf_model_fr550_u_float_dual_compare (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_FRi, INT in_FRj, + INT out_FCCi_2) +{ + int cycles; + INT dual_FRi; + INT dual_FRj; + INT dual_FCCi_2; + FRV_PROFILE_STATE *ps; + FRV_VLIW *vliw; + int slot; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + /* The preprocessing can execute right away. */ + cycles = idesc->timing->units[unit_num].done; + + /* The post processing must wait if there is a dependency on a FR + which is not ready yet. */ + ps = CPU_PROFILE_STATE (cpu); + ps->post_wait = cycles; + dual_FRi = DUAL_REG (in_FRi); + dual_FRj = DUAL_REG (in_FRj); + dual_FCCi_2 = out_FCCi_2 + 1; + adjust_float_register_busy (cpu, in_FRi, 2, in_FRj, 2, -1, 1); + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_float (cpu, slot); + post_wait_for_FR (cpu, in_FRi); + post_wait_for_FR (cpu, in_FRj); + post_wait_for_FR (cpu, dual_FRi); + post_wait_for_FR (cpu, dual_FRj); + post_wait_for_CCR (cpu, out_FCCi_2); + post_wait_for_CCR (cpu, dual_FCCi_2); + restore_float_register_busy (cpu, in_FRi, 2, in_FRj, 2, -1, 1); + + /* The latency of FCCi_2 will be the latency of the other inputs plus 3 + cycles. */ + update_CCR_latency (cpu, out_FCCi_2, ps->post_wait + 3); + update_CCR_latency (cpu, dual_FCCi_2, ps->post_wait + 3); + + set_use_is_ccr_complex (cpu, out_FCCi_2); + if (dual_FCCi_2 >= 0) + set_use_is_ccr_complex (cpu, dual_FCCi_2); + + /* the media point unit resource has a latency of 5 cycles */ + update_media_resource_latency (cpu, slot, cycles + 5); + + return cycles; +} + +int +frvbf_model_fr550_u_float_convert (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_FRj, INT in_FRintj, INT in_FRdoublej, + INT out_FRk, INT out_FRintk, + INT out_FRdoublek) +{ + int cycles; + FRV_PROFILE_STATE *ps; + FRV_VLIW *vliw; + int slot; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + /* The preprocessing can execute right away. */ + cycles = idesc->timing->units[unit_num].done; + + /* The post processing must wait if there is a dependency on a FR + which is not ready yet. */ + ps = CPU_PROFILE_STATE (cpu); + ps->post_wait = cycles; + adjust_float_register_busy (cpu, -1, 1, in_FRj, 1, out_FRk, 1); + adjust_float_register_busy (cpu, -1, 1, in_FRintj, 1, out_FRintk, 1); + adjust_float_register_busy (cpu, -1, 1, in_FRdoublej, 2, out_FRdoublek, 2); + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_float (cpu, slot); + post_wait_for_FR (cpu, in_FRj); + post_wait_for_FR (cpu, in_FRintj); + post_wait_for_FRdouble (cpu, in_FRdoublej); + post_wait_for_FR (cpu, out_FRk); + post_wait_for_FR (cpu, out_FRintk); + post_wait_for_FRdouble (cpu, out_FRdoublek); + if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING)) + { + post_wait_for_SPR (cpu, FNER_FOR_FR (out_FRk)); + post_wait_for_SPR (cpu, FNER_FOR_FR (out_FRintk)); + post_wait_for_SPR (cpu, FNER_FOR_FR (out_FRdoublek)); + } + restore_float_register_busy (cpu, -1, 1, in_FRj, 1, out_FRk, 1); + restore_float_register_busy (cpu, -1, 1, in_FRintj, 1, out_FRintk, 1); + restore_float_register_busy (cpu, -1, 1, in_FRdoublej, 2, out_FRdoublek, 2); + + /* The latency of FRk will be at least the latency of the other inputs. */ + update_FR_latency (cpu, out_FRk, ps->post_wait); + update_FR_latency (cpu, out_FRintk, ps->post_wait); + update_FRdouble_latency (cpu, out_FRdoublek, ps->post_wait); + + if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING)) + { + update_SPR_latency (cpu, FNER_FOR_FR (out_FRk), ps->post_wait); + update_SPR_latency (cpu, FNER_FOR_FR (out_FRintk), ps->post_wait); + update_SPR_latency (cpu, FNER_FOR_FR (out_FRdoublek), ps->post_wait); + } + + /* Once initiated, post-processing will take 2 cycles. */ + update_FR_ptime (cpu, out_FRk, 2); + update_FR_ptime (cpu, out_FRintk, 2); + update_FRdouble_ptime (cpu, out_FRdoublek, 2); + + if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING)) + { + update_SPR_ptime (cpu, FNER_FOR_FR (out_FRk), 2); + update_SPR_ptime (cpu, FNER_FOR_FR (out_FRintk), 2); + update_SPR_ptime (cpu, FNER_FOR_FR (out_FRdoublek), 2); + } + + /* Mark this use of the register as a floating point op. */ + if (out_FRk >= 0) + set_use_is_fr_complex_2 (cpu, out_FRk); + if (out_FRintk >= 0) + set_use_is_fr_complex_2 (cpu, out_FRintk); + if (out_FRdoublek >= 0) + { + set_use_is_fr_complex_2 (cpu, out_FRdoublek); + set_use_is_fr_complex_2 (cpu, out_FRdoublek + 1); + } + + /* the media point unit resource has a latency of 4 cycles */ + update_media_resource_latency (cpu, slot, cycles + 4); + + return cycles; +} + +int +frvbf_model_fr550_u_spr2gr (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_spr, INT out_GRj) +{ + /* Modelling for this unit is the same as for fr500. */ + return frvbf_model_fr500_u_spr2gr (cpu, idesc, unit_num, referenced, + in_spr, out_GRj); +} + +int +frvbf_model_fr550_u_gr2spr (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_GRj, INT out_spr) +{ + int cycles; + + 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. */ + vliw_wait_for_GR (cpu, in_GRj); + vliw_wait_for_SPR (cpu, out_spr); + handle_resource_wait (cpu); + load_wait_for_GR (cpu, in_GRj); + trace_vliw_wait_cycles (cpu); + return 0; + } + + cycles = idesc->timing->units[unit_num].done; + +#if 0 + /* The latency of spr is ? cycles. */ + update_SPR_latency (cpu, out_spr, cycles + ?); +#endif + + return cycles; +} + +int +frvbf_model_fr550_u_gr2fr (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_GRj, INT out_FRk) +{ + int cycles; + + 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 14-15 in the LSI. */ + adjust_float_register_busy (cpu, -1, 1, -1, 1, out_FRk, 1); + vliw_wait_for_GR (cpu, in_GRj); + vliw_wait_for_FR (cpu, out_FRk); + handle_resource_wait (cpu); + load_wait_for_GR (cpu, in_GRj); + load_wait_for_FR (cpu, out_FRk); + trace_vliw_wait_cycles (cpu); + return 0; + } + + /* The latency of FRk is 1 cycles. */ + cycles = idesc->timing->units[unit_num].done; + update_FR_latency (cpu, out_FRk, cycles + 1); + + set_use_is_fr_complex_1 (cpu, out_FRk); + + return cycles; +} + +int +frvbf_model_fr550_u_swap (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_GRi, INT in_GRj, INT out_GRk) +{ + int cycles; + + 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. */ + vliw_wait_for_GR (cpu, in_GRi); + vliw_wait_for_GR (cpu, in_GRj); + vliw_wait_for_GR (cpu, out_GRk); + 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; + } + + cycles = idesc->timing->units[unit_num].done; + + /* The latency of GRk will depend on how long it takes to swap + the the data from the cache or memory. */ + update_GR_latency_for_swap (cpu, out_GRk, cycles); + + return cycles; +} + +int +frvbf_model_fr550_u_fr2fr (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_FRj, INT out_FRk) +{ + int cycles; + + 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 14-15 in the LSI. */ + adjust_float_register_busy (cpu, -1, 1, in_FRj, 1, out_FRk, 1); + vliw_wait_for_FR (cpu, in_FRj); + vliw_wait_for_FR (cpu, out_FRk); + handle_resource_wait (cpu); + load_wait_for_FR (cpu, in_FRj); + load_wait_for_FR (cpu, out_FRk); + trace_vliw_wait_cycles (cpu); + return 0; + } + + /* The latency of FRj is 2 cycles. */ + cycles = idesc->timing->units[unit_num].done; + update_FR_latency (cpu, out_FRk, cycles + 2); + + set_use_is_fr_complex_2 (cpu, out_FRk); + + return cycles; +} + +int +frvbf_model_fr550_u_fr2gr (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_FRk, INT out_GRj) +{ + int cycles; + + 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 14-15 in the LSI. */ + adjust_float_register_busy (cpu, in_FRk, 1, -1, 1, -1, 1); + vliw_wait_for_FR (cpu, in_FRk); + vliw_wait_for_GR (cpu, out_GRj); + handle_resource_wait (cpu); + load_wait_for_FR (cpu, in_FRk); + load_wait_for_GR (cpu, out_GRj); + trace_vliw_wait_cycles (cpu); + return 0; + } + + /* The latency of GRj is 1 cycle. */ + cycles = idesc->timing->units[unit_num].done; + update_GR_latency (cpu, out_GRj, cycles + 1); + + return cycles; +} + +int +frvbf_model_fr550_u_clrgr (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_GRk) +{ + /* Modelling for this unit is the same as for fr500. */ + return frvbf_model_fr500_u_clrgr (cpu, idesc, unit_num, referenced, in_GRk); +} + +int +frvbf_model_fr550_u_clrfr (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_FRk) +{ + /* Modelling for this unit is the same as for fr500. */ + return frvbf_model_fr500_u_clrfr (cpu, idesc, unit_num, referenced, in_FRk); +} + +int +frvbf_model_fr550_u_commit (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_GRk, INT in_FRk) +{ + /* Modelling for this unit is the same as for fr500. */ + return frvbf_model_fr500_u_commit (cpu, idesc, unit_num, referenced, + in_GRk, in_FRk); +} + +int +frvbf_model_fr550_u_media (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_FRi, INT in_FRj, INT out_FRk) +{ + int cycles; + FRV_PROFILE_STATE *ps; + FRV_VLIW *vliw; + int slot; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + /* The preprocessing can execute right away. */ + cycles = idesc->timing->units[unit_num].done; + + /* If the previous use of the registers was a media op, + then their latency may be less than previously recorded. + See Table 14-15 in the LSI. */ + adjust_float_register_busy_for_media (cpu, in_FRi, 1, in_FRj, 1, out_FRk, 1); + + /* The post processing must wait if there is a dependency on a FR + which is not ready yet. */ + ps = CPU_PROFILE_STATE (cpu); + ps->post_wait = cycles; + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_media (cpu, slot); + post_wait_for_FR (cpu, in_FRi); + post_wait_for_FR (cpu, in_FRj); + post_wait_for_FR (cpu, out_FRk); + + /* Restore the busy cycles of the registers we used. */ + restore_float_register_busy_for_media (cpu, in_FRi, 1, in_FRj, 1, out_FRk, 1); + + /* The latency of tht output register will be at least the latency of the + other inputs. Once initiated, post-processing will take 1 cycle. */ + if (out_FRk >= 0) + { + update_FR_latency (cpu, out_FRk, ps->post_wait); + update_FR_ptime (cpu, out_FRk, 1); + /* Mark this use of the register as a media op. */ + set_use_is_fr_complex_1 (cpu, out_FRk); + } + + /* the floating point unit resource has a latency of 3 cycles */ + update_float_resource_latency (cpu, slot, cycles + 3); + + return cycles; +} + +int +frvbf_model_fr550_u_media_quad (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_FRi, INT in_FRj, + INT out_FRk) +{ + int cycles; + INT dual_FRi; + INT dual_FRj; + INT dual_FRk; + FRV_PROFILE_STATE *ps; + FRV_VLIW *vliw; + int slot; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + /* The preprocessing can execute right away. */ + cycles = idesc->timing->units[unit_num].done; + + dual_FRi = DUAL_REG (in_FRi); + dual_FRj = DUAL_REG (in_FRj); + dual_FRk = DUAL_REG (out_FRk); + + /* The latency of the registers may be less than previously recorded, + depending on how they were used previously. + See Table 14-15 in the LSI. */ + adjust_float_register_busy_for_media (cpu, in_FRi, 2, in_FRj, 2, out_FRk, 2); + + /* The post processing must wait if there is a dependency on a FR + which is not ready yet. */ + ps = CPU_PROFILE_STATE (cpu); + ps->post_wait = cycles; + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_media (cpu, slot); + post_wait_for_FR (cpu, in_FRi); + post_wait_for_FR (cpu, dual_FRi); + post_wait_for_FR (cpu, in_FRj); + post_wait_for_FR (cpu, dual_FRj); + post_wait_for_FR (cpu, out_FRk); + post_wait_for_FR (cpu, dual_FRk); + + /* Restore the busy cycles of the registers we used. */ + restore_float_register_busy_for_media (cpu, in_FRi, 2, in_FRj, 2, out_FRk, 2); + + /* The latency of the output register will be at least the latency of the + other inputs. Once initiated, post-processing take 1 cycle. */ + update_FR_latency (cpu, out_FRk, ps->post_wait); + update_FR_ptime (cpu, out_FRk, 1); + set_use_is_fr_complex_1 (cpu, out_FRk); + + if (dual_FRk >= 0) + { + update_FR_latency (cpu, dual_FRk, ps->post_wait); + update_FR_ptime (cpu, dual_FRk, 1); + set_use_is_fr_complex_1 (cpu, dual_FRk); + } + + /* the floating point unit resource has a latency of 3 cycles */ + update_float_resource_latency (cpu, slot, cycles + 3); + + return cycles; +} + +int +frvbf_model_fr550_u_media_dual_expand (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_FRi, INT out_FRk) +{ + int cycles; + INT dual_FRk; + FRV_PROFILE_STATE *ps; + FRV_VLIW *vliw; + int slot; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + /* The preprocessing can execute right away. */ + cycles = idesc->timing->units[unit_num].done; + + /* If the previous use of the registers was a media op, + then their latency will be less than previously recorded. + See Table 14-15 in the LSI. */ + dual_FRk = DUAL_REG (out_FRk); + adjust_float_register_busy_for_media (cpu, in_FRi, 1, -1, 1, out_FRk, 2); + + /* The post processing must wait if there is a dependency on a FR + which is not ready yet. */ + ps = CPU_PROFILE_STATE (cpu); + ps->post_wait = cycles; + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_media (cpu, slot); + post_wait_for_FR (cpu, in_FRi); + post_wait_for_FR (cpu, out_FRk); + post_wait_for_FR (cpu, dual_FRk); + + /* Restore the busy cycles of the registers we used. */ + restore_float_register_busy_for_media (cpu, in_FRi, 1, -1, 1, out_FRk, 2); + + /* The latency of the output register will be at least the latency of the + other inputs. Once initiated, post-processing will take 1 cycle. */ + update_FR_latency (cpu, out_FRk, ps->post_wait); + update_FR_ptime (cpu, out_FRk, 1); + set_use_is_fr_complex_1 (cpu, out_FRk); + + if (dual_FRk >= 0) + { + update_FR_latency (cpu, dual_FRk, ps->post_wait); + update_FR_ptime (cpu, dual_FRk, 1); + set_use_is_fr_complex_1 (cpu, dual_FRk); + } + + /* the floating point unit resource has a latency of 3 cycles */ + update_float_resource_latency (cpu, slot, cycles + 3); + + return cycles; +} + +int +frvbf_model_fr550_u_media_3_dual (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_FRi, INT out_FRk) +{ + int cycles; + INT dual_FRi; + FRV_PROFILE_STATE *ps; + FRV_VLIW *vliw; + int slot; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + /* The preprocessing can execute right away. */ + cycles = idesc->timing->units[unit_num].done; + + dual_FRi = DUAL_REG (in_FRi); + + /* The latency of the registers may be less than previously recorded, + depending on how they were used previously. + See Table 14-15 in the LSI. */ + adjust_float_register_busy_for_media (cpu, in_FRi, 2, -1, 1, out_FRk, 1); + + /* The post processing must wait if there is a dependency on a FR + which is not ready yet. */ + ps = CPU_PROFILE_STATE (cpu); + ps->post_wait = cycles; + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_media (cpu, slot); + post_wait_for_FR (cpu, in_FRi); + post_wait_for_FR (cpu, dual_FRi); + post_wait_for_FR (cpu, out_FRk); + + /* Restore the busy cycles of the registers we used. */ + restore_float_register_busy_for_media (cpu, in_FRi, 2, -1, 1, out_FRk, 1); + + /* The latency of the output register will be at least the latency of the + other inputs. Once initiated, post-processing takes 1 cycle. */ + update_FR_latency (cpu, out_FRk, ps->post_wait); + update_FR_ptime (cpu, out_FRk, 1); + + set_use_is_fr_complex_1 (cpu, out_FRk); + + /* the floating point unit resource has a latency of 3 cycles */ + update_float_resource_latency (cpu, slot, cycles + 3); + + return cycles; +} + +int +frvbf_model_fr550_u_media_3_acc (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_FRj, INT in_ACC40Si, + INT out_FRk) +{ + int cycles; + FRV_PROFILE_STATE *ps; + FRV_VLIW *vliw; + int slot; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + /* The preprocessing can execute right away. */ + cycles = idesc->timing->units[unit_num].done; + + /* If the previous use of the registers was a media op, + then their latency will be less than previously recorded. + See Table 14-15 in the LSI. */ + adjust_float_register_busy_for_media (cpu, -1, 1, in_FRj, 1, out_FRk, 1); + + /* The post processing must wait if there is a dependency on a FR + which is not ready yet. */ + ps = CPU_PROFILE_STATE (cpu); + ps->post_wait = cycles; + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_media (cpu, slot); + post_wait_for_FR (cpu, in_FRj); + post_wait_for_FR (cpu, out_FRk); + post_wait_for_ACC (cpu, in_ACC40Si); + + /* Restore the busy cycles of the registers we used. */ + restore_float_register_busy_for_media (cpu, -1, 1, in_FRj, 1, out_FRk, 1); + + /* The latency of tht output register will be at least the latency of the + other inputs. Once initiated, post-processing will take 1 cycle. */ + update_FR_latency (cpu, out_FRk, ps->post_wait); + update_FR_ptime (cpu, out_FRk, 1); + + set_use_is_fr_complex_1 (cpu, out_FRk); + + /* the floating point unit resource has a latency of 3 cycles */ + update_float_resource_latency (cpu, slot, cycles + 3); + + return cycles; +} + +int +frvbf_model_fr550_u_media_3_acc_dual (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_ACC40Si, INT out_FRk) +{ + int cycles; + FRV_PROFILE_STATE *ps; + INT ACC40Si_1; + INT dual_FRk; + FRV_VLIW *vliw; + int slot; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + /* The preprocessing can execute right away. */ + cycles = idesc->timing->units[unit_num].done; + + ACC40Si_1 = DUAL_REG (in_ACC40Si); + dual_FRk = DUAL_REG (out_FRk); + + /* If the previous use of the registers was a media op, + then their latency will be less than previously recorded. + See Table 14-15 in the LSI. */ + adjust_float_register_busy_for_media (cpu, -1, 1, -1, 1, out_FRk, 2); + + /* The post processing must wait if there is a dependency on a FR + which is not ready yet. */ + ps = CPU_PROFILE_STATE (cpu); + ps->post_wait = cycles; + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_media (cpu, slot); + post_wait_for_ACC (cpu, in_ACC40Si); + post_wait_for_ACC (cpu, ACC40Si_1); + post_wait_for_FR (cpu, out_FRk); + post_wait_for_FR (cpu, dual_FRk); + + /* Restore the busy cycles of the registers we used. */ + restore_float_register_busy_for_media (cpu, -1, 1, -1, 1, out_FRk, 2); + + /* The latency of the output register will be at least the latency of the + other inputs. Once initiated, post-processing will take 1 cycle. */ + update_FR_latency (cpu, out_FRk, ps->post_wait); + update_FR_ptime (cpu, out_FRk, 1); + set_use_is_fr_complex_1 (cpu, out_FRk); + if (dual_FRk >= 0) + { + update_FR_latency (cpu, dual_FRk, ps->post_wait); + update_FR_ptime (cpu, dual_FRk, 1); + set_use_is_fr_complex_1 (cpu, dual_FRk); + } + + /* the floating point unit resource has a latency of 3 cycles */ + update_float_resource_latency (cpu, slot, cycles + 3); + + return cycles; +} + +int +frvbf_model_fr550_u_media_3_wtacc (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_FRi, INT out_ACC40Sk) +{ + int cycles; + FRV_PROFILE_STATE *ps; + FRV_VLIW *vliw; + int slot; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + /* The preprocessing can execute right away. */ + cycles = idesc->timing->units[unit_num].done; + + ps = CPU_PROFILE_STATE (cpu); + + /* The latency of the registers may be less than previously recorded, + depending on how they were used previously. + See Table 14-15 in the LSI. */ + adjust_float_register_busy_for_media (cpu, in_FRi, 1, -1, 1, -1, 1); + + /* The post processing must wait if there is a dependency on a FR + which is not ready yet. */ + ps->post_wait = cycles; + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_media (cpu, slot); + post_wait_for_FR (cpu, in_FRi); + post_wait_for_ACC (cpu, out_ACC40Sk); + + /* Restore the busy cycles of the registers we used. */ + restore_float_register_busy_for_media (cpu, in_FRi, 1, -1, 1, -1, 1); + + /* The latency of the output register will be at least the latency of the + other inputs. Once initiated, post-processing will take 1 cycle. */ + update_ACC_latency (cpu, out_ACC40Sk, ps->post_wait); + update_ACC_ptime (cpu, out_ACC40Sk, 1); + set_use_is_acc_mmac (cpu, out_ACC40Sk); + + /* the floating point unit resource has a latency of 3 cycles */ + update_float_resource_latency (cpu, slot, cycles + 3); + + return cycles; +} + +int +frvbf_model_fr550_u_media_3_mclracc (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced) +{ + int cycles; + FRV_PROFILE_STATE *ps; + FRV_VLIW *vliw; + int slot; + int i; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + /* The preprocessing can execute right away. */ + cycles = idesc->timing->units[unit_num].done; + + ps = CPU_PROFILE_STATE (cpu); + + /* The post processing must wait if there is a dependency on a FR + which is not ready yet. */ + ps->post_wait = cycles; + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_media (cpu, slot); + + /* If A was 1 and the accumulator was ACC0, then we must check all + accumulators. Otherwise just wait for the specified accumulator. */ + if (ps->mclracc_A && ps->mclracc_acc == 0) + { + for (i = 0; i < 8; ++i) + post_wait_for_ACC (cpu, i); + } + else + post_wait_for_ACC (cpu, ps->mclracc_acc); + + /* The latency of the output registers will be at least the latency of the + other inputs. Once initiated, post-processing will take 1 cycle. */ + if (ps->mclracc_A && ps->mclracc_acc == 0) + { + for (i = 0; i < 8; ++i) + { + update_ACC_latency (cpu, i, ps->post_wait); + update_ACC_ptime (cpu, i, 1); + set_use_is_acc_mmac (cpu, i); + } + } + else + { + update_ACC_latency (cpu, ps->mclracc_acc, ps->post_wait); + update_ACC_ptime (cpu, ps->mclracc_acc, 1); + set_use_is_acc_mmac (cpu, ps->mclracc_acc); + } + + /* the floating point unit resource has a latency of 3 cycles */ + update_float_resource_latency (cpu, slot, cycles + 3); + + return cycles; +} + +int +frvbf_model_fr550_u_media_set (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT out_FRk) +{ + int cycles; + FRV_PROFILE_STATE *ps; + FRV_VLIW *vliw; + int slot; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + /* The preprocessing can execute right away. */ + cycles = idesc->timing->units[unit_num].done; + + /* If the previous use of the registers was a media op, + then their latency will be less than previously recorded. + See Table 14-15 in the LSI. */ + adjust_float_register_busy_for_media (cpu, -1, 1, -1, 1, out_FRk, 1); + + /* The post processing must wait if there is a dependency on a FR + which is not ready yet. */ + ps = CPU_PROFILE_STATE (cpu); + ps->post_wait = cycles; + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_media (cpu, slot); + post_wait_for_FR (cpu, out_FRk); + + /* Restore the busy cycles of the registers we used. */ + restore_float_register_busy_for_media (cpu, -1, 1, -1, 1, out_FRk, 1); + + /* The latency of the output register will be at least the latency of the + other inputs. Once initiated, post-processing takes 1 cycle. */ + update_FR_latency (cpu, out_FRk, ps->post_wait); + update_FR_ptime (cpu, out_FRk, 1); + fr550_reset_acc_flags (cpu, out_FRk); + + /* the floating point unit resource has a latency of 3 cycles */ + update_float_resource_latency (cpu, slot, cycles + 3); + + return cycles; +} + +int +frvbf_model_fr550_u_media_4 (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_FRi, INT in_FRj, + INT out_ACC40Sk, INT out_ACC40Uk) +{ + int cycles; + INT dual_ACC40Sk; + INT dual_ACC40Uk; + FRV_PROFILE_STATE *ps; + FRV_VLIW *vliw; + int slot; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + /* The preprocessing can execute right away. */ + cycles = idesc->timing->units[unit_num].done; + + ps = CPU_PROFILE_STATE (cpu); + dual_ACC40Sk = DUAL_REG (out_ACC40Sk); + dual_ACC40Uk = DUAL_REG (out_ACC40Uk); + + /* The latency of the registers may be less than previously recorded, + depending on how they were used previously. + See Table 14-15 in the LSI. */ + adjust_acc_busy_for_mmac (cpu, -1, 1, out_ACC40Sk, 2); + adjust_acc_busy_for_mmac (cpu, -1, 1, out_ACC40Uk, 2); + + /* The post processing must wait if there is a dependency on a FR + which is not ready yet. */ + ps->post_wait = cycles; + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_media (cpu, slot); + post_wait_for_FR (cpu, in_FRi); + post_wait_for_FR (cpu, in_FRj); + post_wait_for_ACC (cpu, out_ACC40Sk); + post_wait_for_ACC (cpu, dual_ACC40Sk); + post_wait_for_ACC (cpu, out_ACC40Uk); + post_wait_for_ACC (cpu, dual_ACC40Uk); + + /* Restore the busy cycles of the registers we used. */ + restore_acc_busy_for_mmac (cpu, -1, 1, out_ACC40Sk, 2); + restore_acc_busy_for_mmac (cpu, -1, 1, out_ACC40Uk, 2); + + /* The latency of the output register will be at least the latency of the + other inputs. Once initiated, post-processing will take 1 cycles. */ + if (out_ACC40Sk >= 0) + { + update_ACC_latency (cpu, out_ACC40Sk, ps->post_wait + 1); + set_use_is_acc_mmac (cpu, out_ACC40Sk); + } + if (dual_ACC40Sk >= 0) + { + update_ACC_latency (cpu, dual_ACC40Sk, ps->post_wait + 1); + set_use_is_acc_mmac (cpu, dual_ACC40Sk); + } + if (out_ACC40Uk >= 0) + { + update_ACC_latency (cpu, out_ACC40Uk, ps->post_wait + 1); + set_use_is_acc_mmac (cpu, out_ACC40Uk); + } + if (dual_ACC40Uk >= 0) + { + update_ACC_latency (cpu, dual_ACC40Uk, ps->post_wait + 1); + set_use_is_acc_mmac (cpu, dual_ACC40Uk); + } + + /* the floating point unit resource has a latency of 3 cycles */ + update_float_resource_latency (cpu, slot, cycles + 3); + + return cycles; +} + +int +frvbf_model_fr550_u_media_4_acc (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_ACC40Si, INT out_ACC40Sk) +{ + int cycles; + INT ACC40Si_1; + FRV_PROFILE_STATE *ps; + FRV_VLIW *vliw; + int slot; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + /* The preprocessing can execute right away. */ + cycles = idesc->timing->units[unit_num].done; + + ACC40Si_1 = DUAL_REG (in_ACC40Si); + + ps = CPU_PROFILE_STATE (cpu); + /* The latency of the registers may be less than previously recorded, + depending on how they were used previously. + See Table 14-15 in the LSI. */ + adjust_acc_busy_for_mmac (cpu, in_ACC40Si, 2, out_ACC40Sk, 1); + + /* The post processing must wait if there is a dependency on a register + which is not ready yet. */ + ps->post_wait = cycles; + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_media (cpu, slot); + post_wait_for_ACC (cpu, in_ACC40Si); + post_wait_for_ACC (cpu, ACC40Si_1); + post_wait_for_ACC (cpu, out_ACC40Sk); + + /* Restore the busy cycles of the registers we used. */ + restore_acc_busy_for_mmac (cpu, in_ACC40Si, 2, out_ACC40Sk, 1); + + /* The latency of the output register will be at least the latency of the + other inputs. Once initiated, post-processing will take 1 cycle. */ + update_ACC_latency (cpu, out_ACC40Sk, ps->post_wait + 1); + set_use_is_acc_mmac (cpu, out_ACC40Sk); + + /* the floating point unit resource has a latency of 3 cycles */ + update_float_resource_latency (cpu, slot, cycles + 3); + + return cycles; +} + +int +frvbf_model_fr550_u_media_4_acc_dual (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_ACC40Si, INT out_ACC40Sk) +{ + int cycles; + INT ACC40Si_1; + INT ACC40Si_2; + INT ACC40Si_3; + INT ACC40Sk_1; + FRV_PROFILE_STATE *ps; + FRV_VLIW *vliw; + int slot; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + /* The preprocessing can execute right away. */ + cycles = idesc->timing->units[unit_num].done; + + ACC40Si_1 = DUAL_REG (in_ACC40Si); + ACC40Si_2 = DUAL_REG (ACC40Si_1); + ACC40Si_3 = DUAL_REG (ACC40Si_2); + ACC40Sk_1 = DUAL_REG (out_ACC40Sk); + + ps = CPU_PROFILE_STATE (cpu); + /* The latency of the registers may be less than previously recorded, + depending on how they were used previously. + See Table 14-15 in the LSI. */ + adjust_acc_busy_for_mmac (cpu, in_ACC40Si, 4, out_ACC40Sk, 2); + + /* The post processing must wait if there is a dependency on a register + which is not ready yet. */ + ps->post_wait = cycles; + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_media (cpu, slot); + post_wait_for_ACC (cpu, in_ACC40Si); + post_wait_for_ACC (cpu, ACC40Si_1); + post_wait_for_ACC (cpu, ACC40Si_2); + post_wait_for_ACC (cpu, ACC40Si_3); + post_wait_for_ACC (cpu, out_ACC40Sk); + post_wait_for_ACC (cpu, ACC40Sk_1); + + /* Restore the busy cycles of the registers we used. */ + restore_acc_busy_for_mmac (cpu, in_ACC40Si, 4, out_ACC40Sk, 2); + + /* The latency of the output register will be at least the latency of the + other inputs. Once initiated, post-processing will take 1 cycle. */ + update_ACC_latency (cpu, out_ACC40Sk, ps->post_wait + 1); + set_use_is_acc_mmac (cpu, out_ACC40Sk); + if (ACC40Sk_1 >= 0) + { + update_ACC_latency (cpu, ACC40Sk_1, ps->post_wait + 1); + set_use_is_acc_mmac (cpu, ACC40Sk_1); + } + + /* the floating point unit resource has a latency of 3 cycles */ + update_float_resource_latency (cpu, slot, cycles + 3); + + return cycles; +} + +int +frvbf_model_fr550_u_media_4_add_sub (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_ACC40Si, INT out_ACC40Sk) +{ + int cycles; + INT ACC40Si_1; + INT ACC40Sk_1; + FRV_PROFILE_STATE *ps; + FRV_VLIW *vliw; + int slot; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + /* The preprocessing can execute right away. */ + cycles = idesc->timing->units[unit_num].done; + + ACC40Si_1 = DUAL_REG (in_ACC40Si); + ACC40Sk_1 = DUAL_REG (out_ACC40Sk); + + ps = CPU_PROFILE_STATE (cpu); + /* The latency of the registers may be less than previously recorded, + depending on how they were used previously. + See Table 14-15 in the LSI. */ + adjust_acc_busy_for_mmac (cpu, in_ACC40Si, 2, out_ACC40Sk, 2); + + /* The post processing must wait if there is a dependency on a register + which is not ready yet. */ + ps->post_wait = cycles; + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_media (cpu, slot); + post_wait_for_ACC (cpu, in_ACC40Si); + post_wait_for_ACC (cpu, ACC40Si_1); + post_wait_for_ACC (cpu, out_ACC40Sk); + post_wait_for_ACC (cpu, ACC40Sk_1); + + /* Restore the busy cycles of the registers we used. */ + restore_acc_busy_for_mmac (cpu, in_ACC40Si, 2, out_ACC40Sk, 2); + + /* The latency of the output register will be at least the latency of the + other inputs. Once initiated, post-processing will take 1 cycle. */ + update_ACC_latency (cpu, out_ACC40Sk, ps->post_wait + 1); + set_use_is_acc_mmac (cpu, out_ACC40Sk); + if (ACC40Sk_1 >= 0) + { + update_ACC_latency (cpu, ACC40Sk_1, ps->post_wait + 1); + set_use_is_acc_mmac (cpu, ACC40Sk_1); + } + + /* the floating point unit resource has a latency of 3 cycles */ + update_float_resource_latency (cpu, slot, cycles + 3); + + return cycles; +} + +int +frvbf_model_fr550_u_media_4_add_sub_dual (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_ACC40Si, INT out_ACC40Sk) +{ + int cycles; + INT ACC40Si_1; + INT ACC40Si_2; + INT ACC40Si_3; + INT ACC40Sk_1; + INT ACC40Sk_2; + INT ACC40Sk_3; + FRV_PROFILE_STATE *ps; + FRV_VLIW *vliw; + int slot; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + /* The preprocessing can execute right away. */ + cycles = idesc->timing->units[unit_num].done; + + ACC40Si_1 = DUAL_REG (in_ACC40Si); + ACC40Si_2 = DUAL_REG (ACC40Si_1); + ACC40Si_3 = DUAL_REG (ACC40Si_2); + ACC40Sk_1 = DUAL_REG (out_ACC40Sk); + ACC40Sk_2 = DUAL_REG (ACC40Sk_1); + ACC40Sk_3 = DUAL_REG (ACC40Sk_2); + + ps = CPU_PROFILE_STATE (cpu); + /* The latency of the registers may be less than previously recorded, + depending on how they were used previously. + See Table 14-15 in the LSI. */ + adjust_acc_busy_for_mmac (cpu, in_ACC40Si, 4, out_ACC40Sk, 4); + + /* The post processing must wait if there is a dependency on a register + which is not ready yet. */ + ps->post_wait = cycles; + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_media (cpu, slot); + post_wait_for_ACC (cpu, in_ACC40Si); + post_wait_for_ACC (cpu, ACC40Si_1); + post_wait_for_ACC (cpu, ACC40Si_2); + post_wait_for_ACC (cpu, ACC40Si_3); + post_wait_for_ACC (cpu, out_ACC40Sk); + post_wait_for_ACC (cpu, ACC40Sk_1); + post_wait_for_ACC (cpu, ACC40Sk_2); + post_wait_for_ACC (cpu, ACC40Sk_3); + + /* Restore the busy cycles of the registers we used. */ + restore_acc_busy_for_mmac (cpu, in_ACC40Si, 4, out_ACC40Sk, 4); + + /* The latency of the output register will be at least the latency of the + other inputs. Once initiated, post-processing will take 1 cycle. */ + update_ACC_latency (cpu, out_ACC40Sk, ps->post_wait + 1); + set_use_is_acc_mmac (cpu, out_ACC40Sk); + if (ACC40Sk_1 >= 0) + { + update_ACC_latency (cpu, ACC40Sk_1, ps->post_wait + 1); + set_use_is_acc_mmac (cpu, ACC40Sk_1); + } + if (ACC40Sk_2 >= 0) + { + update_ACC_latency (cpu, ACC40Sk_2, ps->post_wait + 1); + set_use_is_acc_mmac (cpu, ACC40Sk_2); + } + if (ACC40Sk_3 >= 0) + { + update_ACC_latency (cpu, ACC40Sk_3, ps->post_wait + 1); + set_use_is_acc_mmac (cpu, ACC40Sk_3); + } + + /* the floating point unit resource has a latency of 3 cycles */ + update_float_resource_latency (cpu, slot, cycles + 3); + + return cycles; +} + +int +frvbf_model_fr550_u_media_4_quad (SIM_CPU *cpu, const IDESC *idesc, + int unit_num, int referenced, + INT in_FRi, INT in_FRj, + INT out_ACC40Sk, INT out_ACC40Uk) +{ + int cycles; + INT dual_FRi; + INT dual_FRj; + INT ACC40Sk_1; + INT ACC40Sk_2; + INT ACC40Sk_3; + INT ACC40Uk_1; + INT ACC40Uk_2; + INT ACC40Uk_3; + FRV_PROFILE_STATE *ps; + FRV_VLIW *vliw; + int slot; + + if (model_insn == FRV_INSN_MODEL_PASS_1) + return 0; + + /* The preprocessing can execute right away. */ + cycles = idesc->timing->units[unit_num].done; + + dual_FRi = DUAL_REG (in_FRi); + dual_FRj = DUAL_REG (in_FRj); + ACC40Sk_1 = DUAL_REG (out_ACC40Sk); + ACC40Sk_2 = DUAL_REG (ACC40Sk_1); + ACC40Sk_3 = DUAL_REG (ACC40Sk_2); + ACC40Uk_1 = DUAL_REG (out_ACC40Uk); + ACC40Uk_2 = DUAL_REG (ACC40Uk_1); + ACC40Uk_3 = DUAL_REG (ACC40Uk_2); + + ps = CPU_PROFILE_STATE (cpu); + /* The latency of the registers may be less than previously recorded, + depending on how they were used previously. + See Table 14-15 in the LSI. */ + adjust_float_register_busy_for_media (cpu, in_FRi, 2, in_FRj, 2, -1, 1); + adjust_acc_busy_for_mmac (cpu, -1, 1, out_ACC40Sk, 4); + adjust_acc_busy_for_mmac (cpu, -1, 1, out_ACC40Uk, 4); + + /* The post processing must wait if there is a dependency on a FR + which is not ready yet. */ + ps->post_wait = cycles; + vliw = CPU_VLIW (cpu); + slot = vliw->next_slot - 1; + slot = (*vliw->current_vliw)[slot] - UNIT_FM0; + post_wait_for_media (cpu, slot); + post_wait_for_FR (cpu, in_FRi); + post_wait_for_FR (cpu, dual_FRi); + post_wait_for_FR (cpu, in_FRj); + post_wait_for_FR (cpu, dual_FRj); + post_wait_for_ACC (cpu, out_ACC40Sk); + post_wait_for_ACC (cpu, ACC40Sk_1); + post_wait_for_ACC (cpu, ACC40Sk_2); + post_wait_for_ACC (cpu, ACC40Sk_3); + post_wait_for_ACC (cpu, out_ACC40Uk); + post_wait_for_ACC (cpu, ACC40Uk_1); + post_wait_for_ACC (cpu, ACC40Uk_2); + post_wait_for_ACC (cpu, ACC40Uk_3); + + /* Restore the busy cycles of the registers we used. */ + restore_float_register_busy_for_media (cpu, in_FRi, 2, in_FRj, 2, -1, 1); + restore_acc_busy_for_mmac (cpu, -1, 1, out_ACC40Sk, 4); + restore_acc_busy_for_mmac (cpu, -1, 1, out_ACC40Uk, 4); + + /* The latency of the output register will be at least the latency of the + other inputs. Once initiated, post-processing will take 1 cycle. */ + if (out_ACC40Sk >= 0) + { + update_ACC_latency (cpu, out_ACC40Sk, ps->post_wait + 1); + + set_use_is_acc_mmac (cpu, out_ACC40Sk); + if (ACC40Sk_1 >= 0) + { + update_ACC_latency (cpu, ACC40Sk_1, ps->post_wait + 1); + + set_use_is_acc_mmac (cpu, ACC40Sk_1); + } + if (ACC40Sk_2 >= 0) + { + update_ACC_latency (cpu, ACC40Sk_2, ps->post_wait + 1); + + set_use_is_acc_mmac (cpu, ACC40Sk_2); + } + if (ACC40Sk_3 >= 0) + { + update_ACC_latency (cpu, ACC40Sk_3, ps->post_wait + 1); + + set_use_is_acc_mmac (cpu, ACC40Sk_3); + } + } + else if (out_ACC40Uk >= 0) + { + update_ACC_latency (cpu, out_ACC40Uk, ps->post_wait + 1); + + set_use_is_acc_mmac (cpu, out_ACC40Uk); + if (ACC40Uk_1 >= 0) + { + update_ACC_latency (cpu, ACC40Uk_1, ps->post_wait + 1); + + set_use_is_acc_mmac (cpu, ACC40Uk_1); + } + if (ACC40Uk_2 >= 0) + { + update_ACC_latency (cpu, ACC40Uk_2, ps->post_wait + 1); + + set_use_is_acc_mmac (cpu, ACC40Uk_2); + } + if (ACC40Uk_3 >= 0) + { + update_ACC_latency (cpu, ACC40Uk_3, ps->post_wait + 1); + + set_use_is_acc_mmac (cpu, ACC40Uk_3); + } + } + + /* the floating point unit resource has a latency of 3 cycles */ + update_float_resource_latency (cpu, slot, cycles + 3); + + return cycles; +} + +#endif /* WITH_PROFILE_MODEL_P */ |