aboutsummaryrefslogtreecommitdiff
path: root/sim/frv/profile-fr500.c
diff options
context:
space:
mode:
authorDave Brolley <brolley@redhat.com>2003-08-29 16:35:47 +0000
committerDave Brolley <brolley@redhat.com>2003-08-29 16:35:47 +0000
commitb34f6357d032f4b39f9c7adb1995956d04339461 (patch)
treea77b3c9a47df5e56dc9fc85d3a2792b12cb436e8 /sim/frv/profile-fr500.c
parent60fac5b81a94dedf1997344af7a998e9ea611e55 (diff)
downloadgdb-b34f6357d032f4b39f9c7adb1995956d04339461.zip
gdb-b34f6357d032f4b39f9c7adb1995956d04339461.tar.gz
gdb-b34f6357d032f4b39f9c7adb1995956d04339461.tar.bz2
New simulator for Fujitsu frv contributed by Red Hat.
Diffstat (limited to 'sim/frv/profile-fr500.c')
-rw-r--r--sim/frv/profile-fr500.c3060
1 files changed, 3060 insertions, 0 deletions
diff --git a/sim/frv/profile-fr500.c b/sim/frv/profile-fr500.c
new file mode 100644
index 0000000..0cc8c7d
--- /dev/null
+++ b/sim/frv/profile-fr500.c
@@ -0,0 +1,3060 @@
+/* frv simulator fr500 dependent profiling code.
+
+ Copyright (C) 1998, 1999, 2000, 2001 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-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. */
+void
+fr500_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. */
+void
+fr500_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 void
+set_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 void
+set_use_not_fpop (SIM_CPU *cpu, INT fr)
+{
+ MODEL_FR500_DATA *d = CPU_MODEL_DATA (cpu);
+ d->cur_fpop &= ~(((DI)1) << (fr));
+}
+
+static int
+use_is_fpop (SIM_CPU *cpu, INT fr)
+{
+ MODEL_FR500_DATA *d = CPU_MODEL_DATA (cpu);
+ return d->prev_fpop & (((DI)1) << (fr));
+}
+
+static void
+set_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 void
+set_use_not_media (SIM_CPU *cpu, INT fr)
+{
+ MODEL_FR500_DATA *d = CPU_MODEL_DATA (cpu);
+ d->cur_media &= ~(((DI)1) << (fr));
+}
+
+static int
+use_is_media (SIM_CPU *cpu, INT fr)
+{
+ MODEL_FR500_DATA *d = CPU_MODEL_DATA (cpu);
+ return d->prev_media & (((DI)1) << (fr));
+}
+
+static void
+set_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 void
+set_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 int
+use_is_cc_complex (SIM_CPU *cpu, INT cc)
+{
+ MODEL_FR500_DATA *d = CPU_MODEL_DATA (cpu);
+ return d->prev_cc_complex & (((DI)1) << (cc));
+}
+
+void
+fr500_reset_fr_flags (SIM_CPU *cpu, INT fr)
+{
+ set_use_not_fpop (cpu, fr);
+ set_use_not_media (cpu, fr);
+}
+
+void
+fr500_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 void
+adjust_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 void
+adjust_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 void
+restore_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 void
+restore_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);
+}
+
+int
+frvbf_model_fr500_u_exec (SIM_CPU *cpu, const IDESC *idesc,
+ int unit_num, int referenced)
+{
+ return idesc->timing->units[unit_num].done;
+}
+
+int
+frvbf_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;
+}
+
+int
+frvbf_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;
+}
+
+int
+frvbf_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);
+
+ /* the idiv resource has a latency of 18 cycles! */
+ update_idiv_resource_latency (cpu, slot, cycles + 18);
+
+ return cycles;
+}
+
+int
+frvbf_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
+ 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_fr500_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;
+ 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;
+ }
+
+ cycles = idesc->timing->units[unit_num].done;
+ return cycles;
+}
+
+int
+frvbf_model_fr500_u_check (SIM_CPU *cpu, const IDESC *idesc,
+ int unit_num, int referenced,
+ INT in_ICCi_3, INT in_FCCi_3)
+{
+ 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_3 >= 0)
+ in_ICCi_3 += 4;
+
+ /* The entire VLIW insn must wait if there is a dependency on a register
+ which is not ready yet. */
+ vliw_wait_for_CCR (cpu, in_ICCi_3);
+ vliw_wait_for_CCR (cpu, in_FCCi_3);
+ handle_resource_wait (cpu);
+ trace_vliw_wait_cycles (cpu);
+ return 0;
+ }
+
+ cycles = idesc->timing->units[unit_num].done;
+ return cycles;
+}
+
+int
+frvbf_model_fr500_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;
+
+ set_use_not_gr_complex (cpu, out_GRkhi);
+ set_use_not_gr_complex (cpu, out_GRklo);
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_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.
+ 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 != out_GRdoublek
+ && in_GRi != out_GRdoublek + 1 && 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 != out_GRk && in_GRj != out_GRdoublek
+ && in_GRj != out_GRdoublek + 1 && 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_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);
+
+ set_use_is_gr_complex (cpu, out_GRk);
+ set_use_is_gr_complex (cpu, out_GRdoublek);
+ set_use_is_gr_complex (cpu, out_GRdoublek + 1);
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_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.
+ 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);
+ }
+ if (in_GRk != in_GRi && in_GRk != in_GRj && in_GRk >= 0)
+ {
+ if (use_is_gr_complex (cpu, in_GRk))
+ decrease_GR_busy (cpu, in_GRk, 1);
+ }
+ if (in_GRdoublek != in_GRi && in_GRdoublek != in_GRj
+ && in_GRdoublek + 1 != in_GRi && in_GRdoublek + 1 != in_GRj
+ && in_GRdoublek >= 0)
+ {
+ if (use_is_gr_complex (cpu, in_GRdoublek))
+ decrease_GR_busy (cpu, in_GRdoublek, 1);
+ if (use_is_gr_complex (cpu, in_GRdoublek + 1))
+ decrease_GR_busy (cpu, in_GRdoublek + 1, 1);
+ }
+ 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;
+ }
+
+ cycles = idesc->timing->units[unit_num].done;
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_u_gr_r_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 = frvbf_model_fr500_u_gr_store (cpu, idesc, unit_num, referenced,
+ in_GRi, in_GRj, in_GRk,
+ in_GRdoublek);
+
+ if (model_insn == FRV_INSN_MODEL_PASS_2)
+ {
+ if (CPU_RSTR_INVALIDATE(cpu))
+ request_cache_invalidate (cpu, CPU_DATA_CACHE (cpu), cycles);
+ }
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_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. */
+ 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);
+ }
+ if (out_FRk >= 0)
+ {
+ if (use_is_media (cpu, out_FRk))
+ decrease_FR_busy (cpu, out_FRk, 1);
+ else
+ adjust_float_register_busy (cpu, -1, -1, out_FRk, 1);
+ }
+ if (out_FRdoublek >= 0)
+ {
+ if (use_is_media (cpu, out_FRdoublek))
+ decrease_FR_busy (cpu, out_FRdoublek, 1);
+ else
+ adjust_float_register_busy (cpu, -1, -1, out_FRdoublek, 1);
+ if (use_is_media (cpu, out_FRdoublek + 1))
+ decrease_FR_busy (cpu, out_FRdoublek + 1, 1);
+ else
+ adjust_float_register_busy (cpu, -1, -1, out_FRdoublek + 1, 1);
+ }
+ 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);
+ 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);
+
+ fr500_reset_fr_flags (cpu, out_FRk);
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_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.
+ 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);
+ }
+ if (in_FRk >= 0)
+ {
+ if (use_is_media (cpu, in_FRk))
+ decrease_FR_busy (cpu, in_FRk, 1);
+ else
+ adjust_float_register_busy (cpu, -1, -1, in_FRk, 1);
+ }
+ if (in_FRdoublek >= 0)
+ {
+ if (use_is_media (cpu, in_FRdoublek))
+ decrease_FR_busy (cpu, in_FRdoublek, 1);
+ else
+ adjust_float_register_busy (cpu, -1, -1, in_FRdoublek, 1);
+ if (use_is_media (cpu, in_FRdoublek + 1))
+ decrease_FR_busy (cpu, in_FRdoublek + 1, 1);
+ else
+ adjust_float_register_busy (cpu, -1, -1, in_FRdoublek + 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;
+ }
+
+ cycles = idesc->timing->units[unit_num].done;
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_u_fr_r_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 = frvbf_model_fr500_u_fr_store (cpu, idesc, unit_num, referenced,
+ in_GRi, in_GRj, in_FRk,
+ in_FRdoublek);
+
+ if (model_insn == FRV_INSN_MODEL_PASS_2)
+ {
+ if (CPU_RSTR_INVALIDATE(cpu))
+ request_cache_invalidate (cpu, CPU_DATA_CACHE (cpu), cycles);
+ }
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_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.
+ 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);
+ 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);
+ set_use_is_gr_complex (cpu, out_GRk);
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_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. */
+ if (in_FRj >= 0)
+ {
+ if (use_is_media (cpu, in_FRj))
+ decrease_FR_busy (cpu, in_FRj, 1);
+ else
+ adjust_float_register_busy (cpu, -1, in_FRj, -1, 1);
+ }
+ if (out_FRk >= 0 && out_FRk != in_FRj)
+ {
+ if (use_is_media (cpu, out_FRk))
+ decrease_FR_busy (cpu, out_FRk, 1);
+ else
+ adjust_float_register_busy (cpu, -1, -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 3 cycles. */
+ cycles = idesc->timing->units[unit_num].done;
+ update_FR_latency (cpu, out_FRk, cycles + 3);
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_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. */
+ if (in_FRk >= 0)
+ {
+ if (use_is_media (cpu, in_FRk))
+ decrease_FR_busy (cpu, in_FRk, 1);
+ else
+ adjust_float_register_busy (cpu, -1, in_FRk, -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 2 cycles. */
+ cycles = idesc->timing->units[unit_num].done;
+ update_GR_latency (cpu, out_GRj, cycles + 2);
+ set_use_is_gr_complex (cpu, out_GRj);
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_u_spr2gr (SIM_CPU *cpu, const IDESC *idesc,
+ int unit_num, int referenced,
+ INT in_spr, 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.
+ SPR registers appear to have no latency effects. */
+ vliw_wait_for_GR (cpu, out_GRj);
+ handle_resource_wait (cpu);
+ load_wait_for_GR (cpu, out_GRj);
+ trace_vliw_wait_cycles (cpu);
+ return 0;
+ }
+
+ cycles = idesc->timing->units[unit_num].done;
+
+#if 0 /* no latency? */
+ /* The latency of GRj is 2 cycles. */
+ update_GR_latency (cpu, out_GRj, cycles + 2);
+#endif
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_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 13-8 in the LSI. */
+ if (in_GRj >= 0)
+ {
+ if (use_is_gr_complex (cpu, in_GRj))
+ decrease_GR_busy (cpu, in_GRj, 1);
+ }
+ if (out_FRk >= 0)
+ {
+ if (use_is_media (cpu, out_FRk))
+ decrease_FR_busy (cpu, out_FRk, 1);
+ else
+ adjust_float_register_busy (cpu, -1, out_FRk, -1, 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 2 cycles. */
+ cycles = idesc->timing->units[unit_num].done;
+ update_FR_latency (cpu, out_FRk, cycles + 2);
+
+ /* Mark this use of the register as NOT a floating point op. */
+ fr500_reset_fr_flags (cpu, out_FRk);
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_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.
+ 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_GRj >= 0)
+ {
+ if (use_is_gr_complex (cpu, in_GRj))
+ decrease_GR_busy (cpu, in_GRj, 1);
+ }
+ vliw_wait_for_GR (cpu, in_GRj);
+ 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_fr500_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.
+ 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);
+ 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_fr500_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.
+ 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);
+ 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_fr500_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.
+ 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);
+ 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_fr500_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.
+ 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);
+ 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_fr500_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.
+ 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);
+ 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_fr500_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.
+ 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);
+ 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_fr500_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.
+ 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);
+ 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;
+}
+
+/* Top up the post-processing time of the given FR by the given number of
+ cycles. */
+static void
+update_FR_ptime (SIM_CPU *cpu, INT out_FR, int cycles)
+{
+ if (out_FR >= 0)
+ {
+ FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
+ /* If a load is pending on this register, then add the cycles to
+ the post processing time for this register. Otherwise apply it
+ directly to the latency of the register. */
+ if (! load_pending_for_register (cpu, out_FR, 1, REGTYPE_FR))
+ {
+ int *fr = ps->fr_latency;
+ fr[out_FR] += cycles;
+ }
+ else
+ ps->fr_ptime[out_FR] += cycles;
+ }
+}
+
+static void
+update_FRdouble_ptime (SIM_CPU *cpu, INT out_FR, int cycles)
+{
+ if (out_FR >= 0)
+ {
+ FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
+ /* If a load is pending on this register, then add the cycles to
+ the post processing time for this register. Otherwise apply it
+ directly to the latency of the register. */
+ if (! load_pending_for_register (cpu, out_FR, 2, REGTYPE_FR))
+ {
+ int *fr = ps->fr_latency;
+ fr[out_FR] += cycles;
+ if (out_FR < 63)
+ fr[out_FR + 1] += cycles;
+ }
+ else
+ {
+ ps->fr_ptime[out_FR] += cycles;
+ if (out_FR < 63)
+ ps->fr_ptime[out_FR + 1] += cycles;
+ }
+ }
+}
+
+int
+frvbf_model_fr500_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;
+
+ 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, in_FRj, out_FRk, 1);
+ adjust_double_register_busy (cpu, in_FRdoublei, in_FRdoublej, out_FRdoublek,
+ 1);
+ ps = CPU_PROFILE_STATE (cpu);
+ ps->post_wait = cycles;
+ 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);
+ restore_float_register_busy (cpu, in_FRi, in_FRj, out_FRk, 1);
+ restore_double_register_busy (cpu, in_FRdoublei, in_FRdoublej, out_FRdoublek,
+ 1);
+
+ /* 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);
+
+ /* Once initiated, post-processing will take 3 cycles. */
+ update_FR_ptime (cpu, out_FRk, 3);
+ update_FRdouble_ptime (cpu, out_FRdoublek, 3);
+
+ /* Mark this use of the register as a floating point op. */
+ if (out_FRk >= 0)
+ set_use_is_fpop (cpu, out_FRk);
+ if (out_FRdoublek >= 0)
+ {
+ set_use_is_fpop (cpu, out_FRdoublek);
+ if (out_FRdoublek < 63)
+ set_use_is_fpop (cpu, out_FRdoublek + 1);
+ }
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_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;
+
+ 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, in_FRj, out_FRk, 1);
+ adjust_float_register_busy (cpu, dual_FRi, dual_FRj, dual_FRk, 1);
+ adjust_double_register_busy (cpu, in_FRdoublei, in_FRdoublej, out_FRdoublek,
+ 1);
+ adjust_double_register_busy (cpu, dual_FRdoublei, dual_FRdoublej,
+ dual_FRdoublek, 1);
+ ps = CPU_PROFILE_STATE (cpu);
+ ps->post_wait = cycles;
+ 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);
+ restore_float_register_busy (cpu, in_FRi, in_FRj, out_FRk, 1);
+ restore_float_register_busy (cpu, dual_FRi, dual_FRj, dual_FRk, 1);
+ restore_double_register_busy (cpu, in_FRdoublei, in_FRdoublej, out_FRdoublek,
+ 1);
+ restore_double_register_busy (cpu, dual_FRdoublei, dual_FRdoublej,
+ dual_FRdoublek, 1);
+
+ /* 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);
+
+ /* 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);
+
+ /* Mark this use of the register as a floating point op. */
+ if (out_FRk >= 0)
+ set_use_is_fpop (cpu, out_FRk);
+ if (dual_FRk >= 0)
+ set_use_is_fpop (cpu, dual_FRk);
+ if (out_FRdoublek >= 0)
+ {
+ set_use_is_fpop (cpu, out_FRdoublek);
+ if (out_FRdoublek < 63)
+ set_use_is_fpop (cpu, out_FRdoublek + 1);
+ }
+ if (dual_FRdoublek >= 0)
+ {
+ set_use_is_fpop (cpu, dual_FRdoublek);
+ if (dual_FRdoublek < 63)
+ set_use_is_fpop (cpu, dual_FRdoublek + 1);
+ }
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_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, in_FRj, out_FRk, 1);
+ ps = CPU_PROFILE_STATE (cpu);
+ ps->post_wait = cycles;
+ post_wait_for_FR (cpu, in_FRi);
+ post_wait_for_FR (cpu, in_FRj);
+ post_wait_for_FR (cpu, out_FRk);
+ vliw = CPU_VLIW (cpu);
+ slot = vliw->next_slot - 1;
+ slot = (*vliw->current_vliw)[slot] - UNIT_FM0;
+ post_wait_for_fdiv (cpu, slot);
+ restore_float_register_busy (cpu, in_FRi, in_FRj, out_FRk, 1);
+
+ /* The latency of FRk will be at least the latency of the other inputs. */
+ /* Once initiated, post-processing will take 10 cycles. */
+ update_FR_latency (cpu, out_FRk, ps->post_wait);
+ update_FR_ptime (cpu, out_FRk, 10);
+
+ /* 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);
+
+ /* Mark this use of the register as a floating point op. */
+ set_use_is_fpop (cpu, out_FRk);
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_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, in_FRj, out_FRk, 1);
+ adjust_double_register_busy (cpu, -1, in_FRdoublej, out_FRdoublek, 1);
+ ps = CPU_PROFILE_STATE (cpu);
+ ps->post_wait = cycles;
+ 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);
+ vliw = CPU_VLIW (cpu);
+ slot = vliw->next_slot - 1;
+ slot = (*vliw->current_vliw)[slot] - UNIT_FM0;
+ post_wait_for_fsqrt (cpu, slot);
+ restore_float_register_busy (cpu, -1, in_FRj, out_FRk, 1);
+ restore_double_register_busy (cpu, -1, in_FRdoublej, out_FRdoublek, 1);
+
+ /* 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);
+
+ /* Once initiated, post-processing will take 15 cycles. */
+ update_FR_ptime (cpu, out_FRk, 15);
+ update_FRdouble_ptime (cpu, out_FRdoublek, 15);
+
+ /* 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);
+
+ /* Mark this use of the register as a floating point op. */
+ if (out_FRk >= 0)
+ set_use_is_fpop (cpu, out_FRk);
+ if (out_FRdoublek >= 0)
+ {
+ set_use_is_fpop (cpu, out_FRdoublek);
+ if (out_FRdoublek < 63)
+ set_use_is_fpop (cpu, out_FRdoublek + 1);
+ }
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_u_float_dual_sqrt (SIM_CPU *cpu, const IDESC *idesc,
+ int unit_num, int referenced,
+ INT in_FRj, INT out_FRk)
+{
+ int cycles;
+ FRV_VLIW *vliw;
+ int slot;
+ INT dual_FRj;
+ INT dual_FRk;
+ 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. */
+ dual_FRj = DUAL_REG (in_FRj);
+ dual_FRk = DUAL_REG (out_FRk);
+ adjust_float_register_busy (cpu, -1, in_FRj, out_FRk, 1);
+ adjust_float_register_busy (cpu, -1, dual_FRj, dual_FRk, 1);
+ ps = CPU_PROFILE_STATE (cpu);
+ ps->post_wait = cycles;
+ post_wait_for_FR (cpu, in_FRj);
+ post_wait_for_FR (cpu, out_FRk);
+ post_wait_for_FR (cpu, dual_FRj);
+ post_wait_for_FR (cpu, dual_FRk);
+
+ vliw = CPU_VLIW (cpu);
+ slot = vliw->next_slot - 1;
+ slot = (*vliw->current_vliw)[slot] - UNIT_FM0;
+ post_wait_for_fsqrt (cpu, slot);
+ restore_float_register_busy (cpu, -1, in_FRj, out_FRk, 1);
+ restore_float_register_busy (cpu, -1, dual_FRj, dual_FRk, 1);
+
+ /* 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);
+
+ /* Once initiated, post-processing will take 15 cycles. */
+ update_FR_ptime (cpu, out_FRk, 15);
+ update_FR_ptime (cpu, dual_FRk, 15);
+
+ /* The latency of the sqrt unit will be at least the latency of the other
+ inputs. */
+ update_fsqrt_resource_latency (cpu, slot, ps->post_wait + 14);
+
+ /* Mark this use of the register as a floating point op. */
+ if (out_FRk >= 0)
+ set_use_is_fpop (cpu, out_FRk);
+ if (dual_FRk >= 0)
+ set_use_is_fpop (cpu, dual_FRk);
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_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;
+
+ 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_double_register_busy (cpu, in_FRdoublei, in_FRdoublej, -1, 1);
+ ps = CPU_PROFILE_STATE (cpu);
+ ps->post_wait = cycles;
+ 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_double_register_busy (cpu, in_FRdoublei, in_FRdoublej, -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);
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_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;
+
+ 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, in_FRj, -1, 1);
+ adjust_float_register_busy (cpu, dual_FRi, dual_FRj, -1, 1);
+ 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, in_FRj, -1, 1);
+ restore_float_register_busy (cpu, dual_FRi, dual_FRj, -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);
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_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;
+
+ 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, in_FRj, out_FRk, 1);
+ adjust_float_register_busy (cpu, -1, in_FRintj, out_FRintk, 1);
+ adjust_double_register_busy (cpu, -1, in_FRdoublej, out_FRdoublek, 1);
+ 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);
+ restore_float_register_busy (cpu, -1, in_FRj, out_FRk, 1);
+ restore_float_register_busy (cpu, -1, in_FRintj, out_FRintk, 1);
+ restore_double_register_busy (cpu, -1, in_FRdoublej, out_FRdoublek, 1);
+
+ /* 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);
+
+ /* Once initiated, post-processing will take 3 cycles. */
+ update_FR_ptime (cpu, out_FRk, 3);
+ update_FR_ptime (cpu, out_FRintk, 3);
+ update_FRdouble_ptime (cpu, out_FRdoublek, 3);
+
+ /* Mark this use of the register as a floating point op. */
+ if (out_FRk >= 0)
+ set_use_is_fpop (cpu, out_FRk);
+ if (out_FRintk >= 0)
+ set_use_is_fpop (cpu, out_FRintk);
+ if (out_FRdoublek >= 0)
+ {
+ set_use_is_fpop (cpu, out_FRdoublek);
+ set_use_is_fpop (cpu, out_FRdoublek + 1);
+ }
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_u_float_dual_convert (SIM_CPU *cpu, const IDESC *idesc,
+ int unit_num, int referenced,
+ INT in_FRj, INT in_FRintj,
+ INT out_FRk, INT out_FRintk)
+{
+ int cycles;
+ INT dual_FRj;
+ INT dual_FRintj;
+ INT dual_FRk;
+ INT dual_FRintk;
+ FRV_PROFILE_STATE *ps;
+
+ 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_FRj = DUAL_REG (in_FRj);
+ dual_FRintj = DUAL_REG (in_FRintj);
+ dual_FRk = DUAL_REG (out_FRk);
+ dual_FRintk = DUAL_REG (out_FRintk);
+ adjust_float_register_busy (cpu, -1, in_FRj, out_FRk, 1);
+ adjust_float_register_busy (cpu, -1, dual_FRj, dual_FRk, 1);
+ adjust_float_register_busy (cpu, -1, in_FRintj, out_FRintk, 1);
+ adjust_float_register_busy (cpu, -1, dual_FRintj, dual_FRintk, 1);
+ post_wait_for_FR (cpu, in_FRj);
+ post_wait_for_FR (cpu, in_FRintj);
+ post_wait_for_FR (cpu, out_FRk);
+ post_wait_for_FR (cpu, out_FRintk);
+ post_wait_for_FR (cpu, dual_FRj);
+ post_wait_for_FR (cpu, dual_FRintj);
+ post_wait_for_FR (cpu, dual_FRk);
+ post_wait_for_FR (cpu, dual_FRintk);
+ restore_float_register_busy (cpu, -1, in_FRj, out_FRk, 1);
+ restore_float_register_busy (cpu, -1, dual_FRj, dual_FRk, 1);
+ restore_float_register_busy (cpu, -1, in_FRintj, out_FRintk, 1);
+ restore_float_register_busy (cpu, -1, dual_FRintj, dual_FRintk, 1);
+
+ /* 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_FR_latency (cpu, dual_FRk, ps->post_wait);
+ update_FR_latency (cpu, dual_FRintk, ps->post_wait);
+
+ /* Once initiated, post-processing will take 3 cycles. */
+ update_FR_ptime (cpu, out_FRk, 3);
+ update_FR_ptime (cpu, out_FRintk, 3);
+ update_FR_ptime (cpu, dual_FRk, 3);
+ update_FR_ptime (cpu, dual_FRintk, 3);
+
+ /* Mark this use of the register as a floating point op. */
+ if (out_FRk >= 0)
+ set_use_is_fpop (cpu, out_FRk);
+ if (out_FRintk >= 0)
+ set_use_is_fpop (cpu, out_FRintk);
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_u_media (SIM_CPU *cpu, const IDESC *idesc,
+ int unit_num, int referenced,
+ INT in_FRi, INT in_FRj, INT in_ACC40Si, INT in_ACCGi,
+ INT out_FRk,
+ INT out_ACC40Sk, INT out_ACC40Uk, INT out_ACCGk)
+{
+ int cycles;
+ FRV_PROFILE_STATE *ps;
+ const CGEN_INSN *insn;
+ int is_media_s1;
+ int is_media_s2;
+ int busy_adjustment[] = {0, 0, 0};
+ int *fr;
+ int *acc;
+
+ 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);
+ insn = idesc->idata;
+
+ /* If the previous use of the registers was a media op,
+ then their latency will be less than previously recorded.
+ See Table 13-13 in the LSI. */
+ if (in_FRi >= 0)
+ {
+ if (use_is_media (cpu, in_FRi))
+ {
+ busy_adjustment[0] = 2;
+ decrease_FR_busy (cpu, in_FRi, busy_adjustment[0]);
+ }
+ else
+ enforce_full_fr_latency (cpu, in_FRi);
+ }
+ if (in_FRj >= 0 && in_FRj != in_FRi)
+ {
+ if (use_is_media (cpu, in_FRj))
+ {
+ busy_adjustment[1] = 2;
+ decrease_FR_busy (cpu, in_FRj, busy_adjustment[1]);
+ }
+ else
+ enforce_full_fr_latency (cpu, in_FRj);
+ }
+ if (out_FRk >= 0 && out_FRk != in_FRi && out_FRk != in_FRj)
+ {
+ if (use_is_media (cpu, out_FRk))
+ {
+ busy_adjustment[2] = 2;
+ decrease_FR_busy (cpu, out_FRk, busy_adjustment[2]);
+ }
+ else
+ enforce_full_fr_latency (cpu, out_FRk);
+ }
+
+ /* The post processing must wait if there is a dependency on a FR
+ which is not ready yet. */
+ ps->post_wait = cycles;
+ post_wait_for_FR (cpu, in_FRi);
+ post_wait_for_FR (cpu, in_FRj);
+ post_wait_for_FR (cpu, out_FRk);
+ post_wait_for_ACC (cpu, in_ACC40Si);
+ post_wait_for_ACC (cpu, in_ACCGi);
+ post_wait_for_ACC (cpu, out_ACC40Sk);
+ post_wait_for_ACC (cpu, out_ACC40Uk);
+ post_wait_for_ACC (cpu, out_ACCGk);
+
+ /* Restore the busy cycles of the registers we used. */
+ fr = ps->fr_busy;
+ if (in_FRi >= 0)
+ fr[in_FRi] += busy_adjustment[0];
+ if (in_FRj >= 0)
+ fr[in_FRj] += busy_adjustment[1];
+ if (out_FRk >= 0)
+ fr[out_FRk] += busy_adjustment[2];
+
+ /* The latency of tht output register will be at least the latency of the
+ other inputs. Once initiated, post-processing will take 3 cycles. */
+ if (out_FRk >= 0)
+ {
+ update_FR_latency (cpu, out_FRk, ps->post_wait);
+ update_FR_ptime (cpu, out_FRk, 3);
+ /* Mark this use of the register as a media op. */
+ set_use_is_media (cpu, out_FRk);
+ }
+ /* The latency of tht output accumulator 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);
+ if (out_ACC40Uk >= 0)
+ update_ACC_latency (cpu, out_ACC40Uk, ps->post_wait + 1);
+ if (out_ACCGk >= 0)
+ update_ACC_latency (cpu, out_ACCGk, ps->post_wait + 1);
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_u_media_quad_arith (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;
+ int busy_adjustment[] = {0, 0, 0, 0, 0, 0};
+ int *fr;
+
+ 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_FRi = DUAL_REG (in_FRi);
+ dual_FRj = DUAL_REG (in_FRj);
+ 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 13-13 in the LSI. */
+ if (use_is_media (cpu, in_FRi))
+ {
+ busy_adjustment[0] = 2;
+ decrease_FR_busy (cpu, in_FRi, busy_adjustment[0]);
+ }
+ else
+ enforce_full_fr_latency (cpu, in_FRi);
+ if (dual_FRi >= 0 && use_is_media (cpu, dual_FRi))
+ {
+ busy_adjustment[1] = 2;
+ decrease_FR_busy (cpu, dual_FRi, busy_adjustment[1]);
+ }
+ else
+ enforce_full_fr_latency (cpu, dual_FRi);
+ if (in_FRj != in_FRi)
+ {
+ if (use_is_media (cpu, in_FRj))
+ {
+ busy_adjustment[2] = 2;
+ decrease_FR_busy (cpu, in_FRj, busy_adjustment[2]);
+ }
+ else
+ enforce_full_fr_latency (cpu, in_FRj);
+ if (dual_FRj >= 0 && use_is_media (cpu, dual_FRj))
+ {
+ busy_adjustment[3] = 2;
+ decrease_FR_busy (cpu, dual_FRj, busy_adjustment[3]);
+ }
+ else
+ enforce_full_fr_latency (cpu, dual_FRj + 1);
+ }
+ if (out_FRk != in_FRi && out_FRk != in_FRj)
+ {
+ if (use_is_media (cpu, out_FRk))
+ {
+ busy_adjustment[4] = 2;
+ decrease_FR_busy (cpu, out_FRk, busy_adjustment[4]);
+ }
+ else
+ enforce_full_fr_latency (cpu, out_FRk);
+ if (dual_FRk >= 0 && use_is_media (cpu, dual_FRk))
+ {
+ busy_adjustment[5] = 2;
+ decrease_FR_busy (cpu, dual_FRk, busy_adjustment[5]);
+ }
+ else
+ enforce_full_fr_latency (cpu, dual_FRk);
+ }
+
+ /* The post processing must wait if there is a dependency on a FR
+ which is not ready yet. */
+ ps->post_wait = cycles;
+ 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. */
+ fr = ps->fr_busy;
+ fr[in_FRi] += busy_adjustment[0];
+ if (dual_FRi >= 0)
+ fr[dual_FRi] += busy_adjustment[1];
+ fr[in_FRj] += busy_adjustment[2];
+ if (dual_FRj >= 0)
+ fr[dual_FRj] += busy_adjustment[3];
+ fr[out_FRk] += busy_adjustment[4];
+ if (dual_FRk >= 0)
+ fr[dual_FRk] += busy_adjustment[5];
+
+ /* The latency of tht output register will be at least the latency of the
+ other inputs. */
+ update_FR_latency (cpu, out_FRk, ps->post_wait);
+
+ /* Once initiated, post-processing will take 3 cycles. */
+ update_FR_ptime (cpu, out_FRk, 3);
+
+ /* Mark this use of the register as a media op. */
+ set_use_is_media (cpu, out_FRk);
+ if (dual_FRk >= 0)
+ {
+ update_FR_latency (cpu, dual_FRk, ps->post_wait);
+ update_FR_ptime (cpu, dual_FRk, 3);
+ /* Mark this use of the register as a media op. */
+ set_use_is_media (cpu, dual_FRk);
+ }
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_u_media_dual_mul (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;
+ int busy_adjustment[] = {0, 0, 0, 0, 0, 0};
+ int *fr;
+ int *acc;
+
+ 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);
+
+ /* If the previous use of the registers was a media op,
+ then their latency will be less than previously recorded.
+ See Table 13-13 in the LSI. */
+ if (use_is_media (cpu, in_FRi))
+ {
+ busy_adjustment[0] = 2;
+ decrease_FR_busy (cpu, in_FRi, busy_adjustment[0]);
+ }
+ else
+ enforce_full_fr_latency (cpu, in_FRi);
+ if (in_FRj != in_FRi)
+ {
+ if (use_is_media (cpu, in_FRj))
+ {
+ busy_adjustment[1] = 2;
+ decrease_FR_busy (cpu, in_FRj, busy_adjustment[1]);
+ }
+ else
+ enforce_full_fr_latency (cpu, in_FRj);
+ }
+ if (out_ACC40Sk >= 0)
+ {
+ busy_adjustment[2] = 1;
+ decrease_ACC_busy (cpu, out_ACC40Sk, busy_adjustment[2]);
+ }
+ if (dual_ACC40Sk >= 0)
+ {
+ busy_adjustment[3] = 1;
+ decrease_ACC_busy (cpu, dual_ACC40Sk, busy_adjustment[3]);
+ }
+ if (out_ACC40Uk >= 0)
+ {
+ busy_adjustment[4] = 1;
+ decrease_ACC_busy (cpu, out_ACC40Uk, busy_adjustment[4]);
+ }
+ if (dual_ACC40Uk >= 0)
+ {
+ busy_adjustment[5] = 1;
+ decrease_ACC_busy (cpu, dual_ACC40Uk, busy_adjustment[5]);
+ }
+
+ /* The post processing must wait if there is a dependency on a FR
+ which is not ready yet. */
+ ps->post_wait = cycles;
+ 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. */
+ fr = ps->fr_busy;
+ acc = ps->acc_busy;
+ fr[in_FRi] += busy_adjustment[0];
+ fr[in_FRj] += busy_adjustment[1];
+ if (out_ACC40Sk >= 0)
+ acc[out_ACC40Sk] += busy_adjustment[2];
+ if (dual_ACC40Sk >= 0)
+ acc[dual_ACC40Sk] += busy_adjustment[3];
+ if (out_ACC40Uk >= 0)
+ acc[out_ACC40Uk] += busy_adjustment[4];
+ if (dual_ACC40Uk >= 0)
+ acc[dual_ACC40Uk] += busy_adjustment[5];
+
+ /* 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_ACC40Sk >= 0)
+ update_ACC_latency (cpu, out_ACC40Sk, ps->post_wait + 1);
+ if (dual_ACC40Sk >= 0)
+ update_ACC_latency (cpu, dual_ACC40Sk, ps->post_wait + 1);
+ if (out_ACC40Uk >= 0)
+ update_ACC_latency (cpu, out_ACC40Uk, ps->post_wait + 1);
+ if (dual_ACC40Uk >= 0)
+ update_ACC_latency (cpu, dual_ACC40Uk, ps->post_wait + 1);
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_u_media_quad_mul (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 FRi_1;
+ INT FRj_1;
+ INT ACC40Sk_1;
+ INT ACC40Sk_2;
+ INT ACC40Sk_3;
+ INT ACC40Uk_1;
+ INT ACC40Uk_2;
+ INT ACC40Uk_3;
+ FRV_PROFILE_STATE *ps;
+ int busy_adjustment[] = {0, 0, 0, 0, 0, 0, 0 ,0};
+ int *fr;
+ int *acc;
+
+ if (model_insn == FRV_INSN_MODEL_PASS_1)
+ return 0;
+
+ /* The preprocessing can execute right away. */
+ cycles = idesc->timing->units[unit_num].done;
+
+ FRi_1 = DUAL_REG (in_FRi);
+ FRj_1 = 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);
+
+ /* If the previous use of the registers was a media op,
+ then their latency will be less than previously recorded.
+ See Table 13-13 in the LSI. */
+ ps = CPU_PROFILE_STATE (cpu);
+ if (use_is_media (cpu, in_FRi))
+ {
+ busy_adjustment[0] = 2;
+ decrease_FR_busy (cpu, in_FRi, busy_adjustment[0]);
+ }
+ else
+ enforce_full_fr_latency (cpu, in_FRi);
+ if (FRi_1 >= 0)
+ {
+ if (use_is_media (cpu, FRi_1))
+ {
+ busy_adjustment[1] = 2;
+ decrease_FR_busy (cpu, FRi_1, busy_adjustment[1]);
+ }
+ else
+ enforce_full_fr_latency (cpu, FRi_1);
+ }
+ if (in_FRj != in_FRi)
+ {
+ if (use_is_media (cpu, in_FRj))
+ {
+ busy_adjustment[2] = 2;
+ decrease_FR_busy (cpu, in_FRj, busy_adjustment[2]);
+ }
+ else
+ enforce_full_fr_latency (cpu, in_FRj);
+ if (FRj_1 >= 0)
+ {
+ if (use_is_media (cpu, FRj_1))
+ {
+ busy_adjustment[3] = 2;
+ decrease_FR_busy (cpu, FRj_1, busy_adjustment[3]);
+ }
+ else
+ enforce_full_fr_latency (cpu, FRj_1);
+ }
+ }
+ if (out_ACC40Sk >= 0)
+ {
+ busy_adjustment[4] = 1;
+ decrease_ACC_busy (cpu, out_ACC40Sk, busy_adjustment[4]);
+
+ if (ACC40Sk_1 >= 0)
+ {
+ busy_adjustment[5] = 1;
+ decrease_ACC_busy (cpu, ACC40Sk_1, busy_adjustment[5]);
+ }
+ if (ACC40Sk_2 >= 0)
+ {
+ busy_adjustment[6] = 1;
+ decrease_ACC_busy (cpu, ACC40Sk_2, busy_adjustment[6]);
+ }
+ if (ACC40Sk_3 >= 0)
+ {
+ busy_adjustment[7] = 1;
+ decrease_ACC_busy (cpu, ACC40Sk_3, busy_adjustment[7]);
+ }
+ }
+ else if (out_ACC40Uk >= 0)
+ {
+ busy_adjustment[4] = 1;
+ decrease_ACC_busy (cpu, out_ACC40Uk, busy_adjustment[4]);
+
+ if (ACC40Uk_1 >= 0)
+ {
+ busy_adjustment[5] = 1;
+ decrease_ACC_busy (cpu, ACC40Uk_1, busy_adjustment[5]);
+ }
+ if (ACC40Uk_2 >= 0)
+ {
+ busy_adjustment[6] = 1;
+ decrease_ACC_busy (cpu, ACC40Uk_2, busy_adjustment[6]);
+ }
+ if (ACC40Uk_3 >= 0)
+ {
+ busy_adjustment[7] = 1;
+ decrease_ACC_busy (cpu, ACC40Uk_3, busy_adjustment[7]);
+ }
+ }
+
+ /* The post processing must wait if there is a dependency on a FR
+ which is not ready yet. */
+ ps->post_wait = cycles;
+ post_wait_for_FR (cpu, in_FRi);
+ post_wait_for_FR (cpu, FRi_1);
+ post_wait_for_FR (cpu, in_FRj);
+ post_wait_for_FR (cpu, FRj_1);
+ 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. */
+ fr = ps->fr_busy;
+ acc = ps->acc_busy;
+ fr[in_FRi] += busy_adjustment[0];
+ if (FRi_1 >= 0)
+ fr[FRi_1] += busy_adjustment[1];
+ fr[in_FRj] += busy_adjustment[2];
+ if (FRj_1 > 0)
+ fr[FRj_1] += busy_adjustment[3];
+ if (out_ACC40Sk >= 0)
+ {
+ acc[out_ACC40Sk] += busy_adjustment[4];
+ if (ACC40Sk_1 >= 0)
+ acc[ACC40Sk_1] += busy_adjustment[5];
+ if (ACC40Sk_2 >= 0)
+ acc[ACC40Sk_2] += busy_adjustment[6];
+ if (ACC40Sk_3 >= 0)
+ acc[ACC40Sk_3] += busy_adjustment[7];
+ }
+ else if (out_ACC40Uk >= 0)
+ {
+ acc[out_ACC40Uk] += busy_adjustment[4];
+ if (ACC40Uk_1 >= 0)
+ acc[ACC40Uk_1] += busy_adjustment[5];
+ if (ACC40Uk_2 >= 0)
+ acc[ACC40Uk_2] += busy_adjustment[6];
+ if (ACC40Uk_3 >= 0)
+ acc[ACC40Uk_3] += busy_adjustment[7];
+ }
+
+ /* 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_ACC40Sk >= 0)
+ {
+ update_ACC_latency (cpu, out_ACC40Sk, ps->post_wait + 1);
+ if (ACC40Sk_1 >= 0)
+ update_ACC_latency (cpu, ACC40Sk_1, ps->post_wait + 1);
+ if (ACC40Sk_2 >= 0)
+ update_ACC_latency (cpu, ACC40Sk_2, ps->post_wait + 1);
+ if (ACC40Sk_3 >= 0)
+ update_ACC_latency (cpu, ACC40Sk_3, ps->post_wait + 1);
+ }
+ else if (out_ACC40Uk >= 0)
+ {
+ update_ACC_latency (cpu, out_ACC40Uk, ps->post_wait + 1);
+ if (ACC40Uk_1 >= 0)
+ update_ACC_latency (cpu, ACC40Uk_1, ps->post_wait + 1);
+ if (ACC40Uk_2 >= 0)
+ update_ACC_latency (cpu, ACC40Uk_2, ps->post_wait + 1);
+ if (ACC40Uk_3 >= 0)
+ update_ACC_latency (cpu, ACC40Uk_3, ps->post_wait + 1);
+ }
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_u_media_quad_complex (SIM_CPU *cpu, const IDESC *idesc,
+ int unit_num, int referenced,
+ INT in_FRi, INT in_FRj,
+ INT out_ACC40Sk)
+{
+ int cycles;
+ INT FRi_1;
+ INT FRj_1;
+ INT ACC40Sk_1;
+ FRV_PROFILE_STATE *ps;
+ int busy_adjustment[] = {0, 0, 0, 0, 0, 0};
+ int *fr;
+ int *acc;
+
+ if (model_insn == FRV_INSN_MODEL_PASS_1)
+ return 0;
+
+ /* The preprocessing can execute right away. */
+ cycles = idesc->timing->units[unit_num].done;
+
+ FRi_1 = DUAL_REG (in_FRi);
+ FRj_1 = DUAL_REG (in_FRj);
+ ACC40Sk_1 = DUAL_REG (out_ACC40Sk);
+
+ /* If the previous use of the registers was a media op,
+ then their latency will be less than previously recorded.
+ See Table 13-13 in the LSI. */
+ ps = CPU_PROFILE_STATE (cpu);
+ if (use_is_media (cpu, in_FRi))
+ {
+ busy_adjustment[0] = 2;
+ decrease_FR_busy (cpu, in_FRi, busy_adjustment[0]);
+ }
+ else
+ enforce_full_fr_latency (cpu, in_FRi);
+ if (FRi_1 >= 0)
+ {
+ if (use_is_media (cpu, FRi_1))
+ {
+ busy_adjustment[1] = 2;
+ decrease_FR_busy (cpu, FRi_1, busy_adjustment[1]);
+ }
+ else
+ enforce_full_fr_latency (cpu, FRi_1);
+ }
+ if (in_FRj != in_FRi)
+ {
+ if (use_is_media (cpu, in_FRj))
+ {
+ busy_adjustment[2] = 2;
+ decrease_FR_busy (cpu, in_FRj, busy_adjustment[2]);
+ }
+ else
+ enforce_full_fr_latency (cpu, in_FRj);
+ if (FRj_1 >= 0)
+ {
+ if (use_is_media (cpu, FRj_1))
+ {
+ busy_adjustment[3] = 2;
+ decrease_FR_busy (cpu, FRj_1, busy_adjustment[3]);
+ }
+ else
+ enforce_full_fr_latency (cpu, FRj_1);
+ }
+ }
+ if (out_ACC40Sk >= 0)
+ {
+ busy_adjustment[4] = 1;
+ decrease_ACC_busy (cpu, out_ACC40Sk, busy_adjustment[4]);
+
+ if (ACC40Sk_1 >= 0)
+ {
+ busy_adjustment[5] = 1;
+ decrease_ACC_busy (cpu, ACC40Sk_1, busy_adjustment[5]);
+ }
+ }
+
+ /* The post processing must wait if there is a dependency on a FR
+ which is not ready yet. */
+ ps->post_wait = cycles;
+ post_wait_for_FR (cpu, in_FRi);
+ post_wait_for_FR (cpu, FRi_1);
+ post_wait_for_FR (cpu, in_FRj);
+ post_wait_for_FR (cpu, FRj_1);
+ post_wait_for_ACC (cpu, out_ACC40Sk);
+ post_wait_for_ACC (cpu, ACC40Sk_1);
+
+ /* Restore the busy cycles of the registers we used. */
+ fr = ps->fr_busy;
+ acc = ps->acc_busy;
+ fr[in_FRi] += busy_adjustment[0];
+ if (FRi_1 >= 0)
+ fr[FRi_1] += busy_adjustment[1];
+ fr[in_FRj] += busy_adjustment[2];
+ if (FRj_1 > 0)
+ fr[FRj_1] += busy_adjustment[3];
+ if (out_ACC40Sk >= 0)
+ {
+ acc[out_ACC40Sk] += busy_adjustment[4];
+ if (ACC40Sk_1 >= 0)
+ acc[ACC40Sk_1] += busy_adjustment[5];
+ }
+
+ /* 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_ACC40Sk >= 0)
+ {
+ update_ACC_latency (cpu, out_ACC40Sk, ps->post_wait + 1);
+ if (ACC40Sk_1 >= 0)
+ update_ACC_latency (cpu, ACC40Sk_1, ps->post_wait + 1);
+ }
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_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;
+ int busy_adjustment[] = {0, 0, 0};
+ int *fr;
+
+ 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 13-13 in the LSI. */
+ dual_FRk = DUAL_REG (out_FRk);
+ ps = CPU_PROFILE_STATE (cpu);
+ if (use_is_media (cpu, in_FRi))
+ {
+ busy_adjustment[0] = 2;
+ decrease_FR_busy (cpu, in_FRi, busy_adjustment[0]);
+ }
+ else
+ enforce_full_fr_latency (cpu, in_FRi);
+ if (out_FRk != in_FRi)
+ {
+ if (use_is_media (cpu, out_FRk))
+ {
+ busy_adjustment[1] = 2;
+ decrease_FR_busy (cpu, out_FRk, busy_adjustment[1]);
+ }
+ else
+ enforce_full_fr_latency (cpu, out_FRk);
+ }
+ if (dual_FRk >= 0 && dual_FRk != in_FRi)
+ {
+ if (use_is_media (cpu, dual_FRk))
+ {
+ busy_adjustment[2] = 2;
+ decrease_FR_busy (cpu, dual_FRk, busy_adjustment[2]);
+ }
+ else
+ enforce_full_fr_latency (cpu, dual_FRk);
+ }
+
+ /* The post processing must wait if there is a dependency on a FR
+ which is not ready yet. */
+ ps->post_wait = cycles;
+ 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. */
+ fr = ps->fr_busy;
+ fr[in_FRi] += busy_adjustment[0];
+ fr[out_FRk] += busy_adjustment[1];
+ if (dual_FRk >= 0)
+ fr[dual_FRk] += busy_adjustment[2];
+
+ /* The latency of tht output register will be at least the latency of the
+ other inputs. Once initiated, post-processing will take 3 cycles. */
+ update_FR_latency (cpu, out_FRk, ps->post_wait);
+ update_FR_ptime (cpu, out_FRk, 3);
+
+ /* Mark this use of the register as a media op. */
+ set_use_is_media (cpu, out_FRk);
+ if (dual_FRk >= 0)
+ {
+ update_FR_latency (cpu, dual_FRk, ps->post_wait);
+ update_FR_ptime (cpu, dual_FRk, 3);
+
+ /* Mark this use of the register as a media op. */
+ set_use_is_media (cpu, dual_FRk);
+ }
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_u_media_dual_unpack (SIM_CPU *cpu, const IDESC *idesc,
+ int unit_num, int referenced,
+ INT in_FRi,
+ INT out_FRk)
+{
+ int cycles;
+ INT FRi_1;
+ INT FRk_1;
+ INT FRk_2;
+ INT FRk_3;
+ FRV_PROFILE_STATE *ps;
+ int busy_adjustment[] = {0, 0, 0, 0, 0, 0};
+ int *fr;
+
+ if (model_insn == FRV_INSN_MODEL_PASS_1)
+ return 0;
+
+ /* The preprocessing can execute right away. */
+ cycles = idesc->timing->units[unit_num].done;
+
+ FRi_1 = DUAL_REG (in_FRi);
+ FRk_1 = DUAL_REG (out_FRk);
+ FRk_2 = DUAL_REG (FRk_1);
+ FRk_3 = DUAL_REG (FRk_2);
+
+ /* If the previous use of the registers was a media op,
+ then their latency will be less than previously recorded.
+ See Table 13-13 in the LSI. */
+ ps = CPU_PROFILE_STATE (cpu);
+ if (use_is_media (cpu, in_FRi))
+ {
+ busy_adjustment[0] = 2;
+ decrease_FR_busy (cpu, in_FRi, busy_adjustment[0]);
+ }
+ else
+ enforce_full_fr_latency (cpu, in_FRi);
+ if (FRi_1 >= 0 && use_is_media (cpu, FRi_1))
+ {
+ busy_adjustment[1] = 2;
+ decrease_FR_busy (cpu, FRi_1, busy_adjustment[1]);
+ }
+ else
+ enforce_full_fr_latency (cpu, FRi_1);
+ if (out_FRk != in_FRi)
+ {
+ if (use_is_media (cpu, out_FRk))
+ {
+ busy_adjustment[2] = 2;
+ decrease_FR_busy (cpu, out_FRk, busy_adjustment[2]);
+ }
+ else
+ enforce_full_fr_latency (cpu, out_FRk);
+ if (FRk_1 >= 0 && FRk_1 != in_FRi)
+ {
+ if (use_is_media (cpu, FRk_1))
+ {
+ busy_adjustment[3] = 2;
+ decrease_FR_busy (cpu, FRk_1, busy_adjustment[3]);
+ }
+ else
+ enforce_full_fr_latency (cpu, FRk_1);
+ }
+ if (FRk_2 >= 0 && FRk_2 != in_FRi)
+ {
+ if (use_is_media (cpu, FRk_2))
+ {
+ busy_adjustment[4] = 2;
+ decrease_FR_busy (cpu, FRk_2, busy_adjustment[4]);
+ }
+ else
+ enforce_full_fr_latency (cpu, FRk_2);
+ }
+ if (FRk_3 >= 0 && FRk_3 != in_FRi)
+ {
+ if (use_is_media (cpu, FRk_3))
+ {
+ busy_adjustment[5] = 2;
+ decrease_FR_busy (cpu, FRk_3, busy_adjustment[5]);
+ }
+ else
+ enforce_full_fr_latency (cpu, FRk_3);
+ }
+ }
+
+ /* The post processing must wait if there is a dependency on a FR
+ which is not ready yet. */
+ ps->post_wait = cycles;
+ post_wait_for_FR (cpu, in_FRi);
+ post_wait_for_FR (cpu, FRi_1);
+ post_wait_for_FR (cpu, out_FRk);
+ post_wait_for_FR (cpu, FRk_1);
+ post_wait_for_FR (cpu, FRk_2);
+ post_wait_for_FR (cpu, FRk_3);
+
+ /* Restore the busy cycles of the registers we used. */
+ fr = ps->fr_busy;
+ fr[in_FRi] += busy_adjustment[0];
+ if (FRi_1 >= 0)
+ fr[FRi_1] += busy_adjustment[1];
+ fr[out_FRk] += busy_adjustment[2];
+ if (FRk_1 >= 0)
+ fr[FRk_1] += busy_adjustment[3];
+ if (FRk_2 >= 0)
+ fr[FRk_2] += busy_adjustment[4];
+ if (FRk_3 >= 0)
+ fr[FRk_3] += busy_adjustment[5];
+
+ /* The latency of tht output register will be at least the latency of the
+ other inputs. Once initiated, post-processing will take 3 cycles. */
+ update_FR_latency (cpu, out_FRk, ps->post_wait);
+ update_FR_ptime (cpu, out_FRk, 3);
+
+ /* Mark this use of the register as a media op. */
+ set_use_is_media (cpu, out_FRk);
+ if (FRk_1 >= 0)
+ {
+ update_FR_latency (cpu, FRk_1, ps->post_wait);
+ update_FR_ptime (cpu, FRk_1, 3);
+
+ /* Mark this use of the register as a media op. */
+ set_use_is_media (cpu, FRk_1);
+ }
+ if (FRk_2 >= 0)
+ {
+ update_FR_latency (cpu, FRk_2, ps->post_wait);
+ update_FR_ptime (cpu, FRk_2, 3);
+
+ /* Mark this use of the register as a media op. */
+ set_use_is_media (cpu, FRk_2);
+ }
+ if (FRk_3 >= 0)
+ {
+ update_FR_latency (cpu, FRk_3, ps->post_wait);
+ update_FR_ptime (cpu, FRk_3, 3);
+
+ /* Mark this use of the register as a media op. */
+ set_use_is_media (cpu, FRk_3);
+ }
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_u_media_dual_btoh (SIM_CPU *cpu, const IDESC *idesc,
+ int unit_num, int referenced,
+ INT in_FRj,
+ INT out_FRk)
+{
+ return frvbf_model_fr500_u_media_dual_expand (cpu, idesc, unit_num,
+ referenced, in_FRj, out_FRk);
+}
+
+int
+frvbf_model_fr500_u_media_dual_htob (SIM_CPU *cpu, const IDESC *idesc,
+ int unit_num, int referenced,
+ INT in_FRj,
+ INT out_FRk)
+{
+ int cycles;
+ INT dual_FRj;
+ FRV_PROFILE_STATE *ps;
+ int busy_adjustment[] = {0, 0, 0};
+ int *fr;
+
+ 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 13-13 in the LSI. */
+ dual_FRj = DUAL_REG (in_FRj);
+ ps = CPU_PROFILE_STATE (cpu);
+ if (use_is_media (cpu, in_FRj))
+ {
+ busy_adjustment[0] = 2;
+ decrease_FR_busy (cpu, in_FRj, busy_adjustment[0]);
+ }
+ else
+ enforce_full_fr_latency (cpu, in_FRj);
+ if (dual_FRj >= 0)
+ {
+ if (use_is_media (cpu, dual_FRj))
+ {
+ busy_adjustment[1] = 2;
+ decrease_FR_busy (cpu, dual_FRj, busy_adjustment[1]);
+ }
+ else
+ enforce_full_fr_latency (cpu, dual_FRj);
+ }
+ if (out_FRk != in_FRj)
+ {
+ if (use_is_media (cpu, out_FRk))
+ {
+ busy_adjustment[2] = 2;
+ decrease_FR_busy (cpu, out_FRk, busy_adjustment[2]);
+ }
+ else
+ enforce_full_fr_latency (cpu, out_FRk);
+ }
+
+ /* The post processing must wait if there is a dependency on a FR
+ which is not ready yet. */
+ ps->post_wait = cycles;
+ post_wait_for_FR (cpu, in_FRj);
+ post_wait_for_FR (cpu, dual_FRj);
+ post_wait_for_FR (cpu, out_FRk);
+
+ /* Restore the busy cycles of the registers we used. */
+ fr = ps->fr_busy;
+ fr[in_FRj] += busy_adjustment[0];
+ if (dual_FRj >= 0)
+ fr[dual_FRj] += busy_adjustment[1];
+ fr[out_FRk] += busy_adjustment[2];
+
+ /* The latency of tht output register will be at least the latency of the
+ other inputs. */
+ update_FR_latency (cpu, out_FRk, ps->post_wait);
+
+ /* Once initiated, post-processing will take 3 cycles. */
+ update_FR_ptime (cpu, out_FRk, 3);
+
+ /* Mark this use of the register as a media op. */
+ set_use_is_media (cpu, out_FRk);
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_u_media_dual_btohe (SIM_CPU *cpu, const IDESC *idesc,
+ int unit_num, int referenced,
+ INT in_FRj,
+ INT out_FRk)
+{
+ int cycles;
+ INT FRk_1;
+ INT FRk_2;
+ INT FRk_3;
+ FRV_PROFILE_STATE *ps;
+ int busy_adjustment[] = {0, 0, 0, 0, 0};
+ int *fr;
+
+ if (model_insn == FRV_INSN_MODEL_PASS_1)
+ return 0;
+
+ /* The preprocessing can execute right away. */
+ cycles = idesc->timing->units[unit_num].done;
+
+ FRk_1 = DUAL_REG (out_FRk);
+ FRk_2 = DUAL_REG (FRk_1);
+ FRk_3 = DUAL_REG (FRk_2);
+
+ /* If the previous use of the registers was a media op,
+ then their latency will be less than previously recorded.
+ See Table 13-13 in the LSI. */
+ ps = CPU_PROFILE_STATE (cpu);
+ if (use_is_media (cpu, in_FRj))
+ {
+ busy_adjustment[0] = 2;
+ decrease_FR_busy (cpu, in_FRj, busy_adjustment[0]);
+ }
+ else
+ enforce_full_fr_latency (cpu, in_FRj);
+ if (out_FRk != in_FRj)
+ {
+ if (use_is_media (cpu, out_FRk))
+ {
+ busy_adjustment[1] = 2;
+ decrease_FR_busy (cpu, out_FRk, busy_adjustment[1]);
+ }
+ else
+ enforce_full_fr_latency (cpu, out_FRk);
+ if (FRk_1 >= 0 && FRk_1 != in_FRj)
+ {
+ if (use_is_media (cpu, FRk_1))
+ {
+ busy_adjustment[2] = 2;
+ decrease_FR_busy (cpu, FRk_1, busy_adjustment[2]);
+ }
+ else
+ enforce_full_fr_latency (cpu, FRk_1);
+ }
+ if (FRk_2 >= 0 && FRk_2 != in_FRj)
+ {
+ if (use_is_media (cpu, FRk_2))
+ {
+ busy_adjustment[3] = 2;
+ decrease_FR_busy (cpu, FRk_2, busy_adjustment[3]);
+ }
+ else
+ enforce_full_fr_latency (cpu, FRk_2);
+ }
+ if (FRk_3 >= 0 && FRk_3 != in_FRj)
+ {
+ if (use_is_media (cpu, FRk_3))
+ {
+ busy_adjustment[4] = 2;
+ decrease_FR_busy (cpu, FRk_3, busy_adjustment[4]);
+ }
+ else
+ enforce_full_fr_latency (cpu, FRk_3);
+ }
+ }
+
+ /* The post processing must wait if there is a dependency on a FR
+ which is not ready yet. */
+ ps->post_wait = cycles;
+ post_wait_for_FR (cpu, in_FRj);
+ post_wait_for_FR (cpu, out_FRk);
+ post_wait_for_FR (cpu, FRk_1);
+ post_wait_for_FR (cpu, FRk_2);
+ post_wait_for_FR (cpu, FRk_3);
+
+ /* Restore the busy cycles of the registers we used. */
+ fr = ps->fr_busy;
+ fr[in_FRj] += busy_adjustment[0];
+ fr[out_FRk] += busy_adjustment[1];
+ if (FRk_1 >= 0)
+ fr[FRk_1] += busy_adjustment[2];
+ if (FRk_2 >= 0)
+ fr[FRk_2] += busy_adjustment[3];
+ if (FRk_3 >= 0)
+ fr[FRk_3] += busy_adjustment[4];
+
+ /* The latency of tht output register will be at least the latency of the
+ other inputs. Once initiated, post-processing will take 3 cycles. */
+ update_FR_latency (cpu, out_FRk, ps->post_wait);
+ update_FR_ptime (cpu, out_FRk, 3);
+
+ /* Mark this use of the register as a media op. */
+ set_use_is_media (cpu, out_FRk);
+ if (FRk_1 >= 0)
+ {
+ update_FR_latency (cpu, FRk_1, ps->post_wait);
+ update_FR_ptime (cpu, FRk_1, 3);
+
+ /* Mark this use of the register as a media op. */
+ set_use_is_media (cpu, FRk_1);
+ }
+ if (FRk_2 >= 0)
+ {
+ update_FR_latency (cpu, FRk_2, ps->post_wait);
+ update_FR_ptime (cpu, FRk_2, 3);
+
+ /* Mark this use of the register as a media op. */
+ set_use_is_media (cpu, FRk_2);
+ }
+ if (FRk_3 >= 0)
+ {
+ update_FR_latency (cpu, FRk_3, ps->post_wait);
+ update_FR_ptime (cpu, FRk_3, 3);
+
+ /* Mark this use of the register as a media op. */
+ set_use_is_media (cpu, FRk_3);
+ }
+
+ return cycles;
+}
+
+int
+frvbf_model_fr500_u_barrier (SIM_CPU *cpu, const IDESC *idesc,
+ int unit_num, int referenced)
+{
+ int cycles;
+ if (model_insn == FRV_INSN_MODEL_PASS_1)
+ {
+ int i;
+ /* Wait for ALL resources. */
+ for (i = 0; i < 64; ++i)
+ {
+ enforce_full_fr_latency (cpu, i);
+ vliw_wait_for_GR (cpu, i);
+ vliw_wait_for_FR (cpu, i);
+ vliw_wait_for_ACC (cpu, i);
+ }
+ for (i = 0; i < 8; ++i)
+ vliw_wait_for_CCR (cpu, i);
+ for (i = 0; i < 2; ++i)
+ {
+ vliw_wait_for_idiv_resource (cpu, i);
+ vliw_wait_for_fdiv_resource (cpu, i);
+ vliw_wait_for_fsqrt_resource (cpu, i);
+ }
+ handle_resource_wait (cpu);
+ for (i = 0; i < 64; ++i)
+ {
+ load_wait_for_GR (cpu, i);
+ load_wait_for_FR (cpu, i);
+ }
+ trace_vliw_wait_cycles (cpu);
+ return 0;
+ }
+
+ cycles = idesc->timing->units[unit_num].done;
+ return cycles;
+}
+
+int
+frvbf_model_fr500_u_membar (SIM_CPU *cpu, const IDESC *idesc,
+ int unit_num, int referenced)
+{
+ int cycles;
+ if (model_insn == FRV_INSN_MODEL_PASS_1)
+ {
+ int i;
+ /* Wait for ALL resources, except GR and ICC. */
+ for (i = 0; i < 64; ++i)
+ {
+ enforce_full_fr_latency (cpu, i);
+ vliw_wait_for_FR (cpu, i);
+ vliw_wait_for_ACC (cpu, i);
+ }
+ for (i = 0; i < 4; ++i)
+ vliw_wait_for_CCR (cpu, i);
+ for (i = 0; i < 2; ++i)
+ {
+ vliw_wait_for_idiv_resource (cpu, i);
+ vliw_wait_for_fdiv_resource (cpu, i);
+ vliw_wait_for_fsqrt_resource (cpu, i);
+ }
+ handle_resource_wait (cpu);
+ for (i = 0; i < 64; ++i)
+ {
+ load_wait_for_FR (cpu, i);
+ }
+ trace_vliw_wait_cycles (cpu);
+ return 0;
+ }
+
+ cycles = idesc->timing->units[unit_num].done;
+ return cycles;
+}
+
+/* The frv machine is a fictional implementation of the fr500 which implements
+ all frv architectural features. */
+int
+frvbf_model_frv_u_exec (SIM_CPU *cpu, const IDESC *idesc,
+ int unit_num, int referenced)
+{
+ return idesc->timing->units[unit_num].done;
+}
+
+/* The simple machine is a fictional implementation of the fr500 which
+ implements limited frv architectural features. */
+int
+frvbf_model_simple_u_exec (SIM_CPU *cpu, const IDESC *idesc,
+ int unit_num, int referenced)
+{
+ return idesc->timing->units[unit_num].done;
+}
+
+/* The tomcat machine is models a prototype fr500 machine which had a few
+ bugs and restrictions to work around. */
+int
+frvbf_model_tomcat_u_exec (SIM_CPU *cpu, const IDESC *idesc,
+ int unit_num, int referenced)
+{
+ return idesc->timing->units[unit_num].done;
+}
+
+#endif /* WITH_PROFILE_MODEL_P */