/* frv simulator fr500 dependent profiling code.
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1998-2019 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.
+the Free Software Foundation; either version 3 of the License, 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.
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define WANT_CPU
update_CCR_latency (cpu, out_ICCi_1, cycles + 19);
set_use_is_cc_complex (cpu, out_ICCi_1);
+ if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING))
+ {
+ /* GNER has a latency of 18 cycles. */
+ update_SPR_latency (cpu, GNER_FOR_GR (out_GRk), cycles + 18);
+ }
+
/* the idiv resource has a latency of 18 cycles! */
update_idiv_resource_latency (cpu, slot, cycles + 18);
INT in_ICCi_2, INT in_FCCi_2)
{
int cycles;
- FRV_PROFILE_STATE *ps;
if (model_insn == FRV_INSN_MODEL_PASS_1)
{
INT in_ICCi_3, INT in_FCCi_3)
{
int cycles;
- FRV_PROFILE_STATE *ps;
if (model_insn == FRV_INSN_MODEL_PASS_1)
{
return cycles;
}
+int
+frvbf_model_fr500_u_clrgr (SIM_CPU *cpu, const IDESC *idesc,
+ int unit_num, int referenced,
+ INT in_GRk)
+{
+ int cycles;
+
+ if (model_insn == FRV_INSN_MODEL_PASS_1)
+ {
+ /* Wait for both GNER registers or just the one specified. */
+ if (in_GRk == -1)
+ {
+ vliw_wait_for_SPR (cpu, H_SPR_GNER0);
+ vliw_wait_for_SPR (cpu, H_SPR_GNER1);
+ }
+ else
+ vliw_wait_for_SPR (cpu, GNER_FOR_GR (in_GRk));
+ 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_clrfr (SIM_CPU *cpu, const IDESC *idesc,
+ int unit_num, int referenced,
+ INT in_FRk)
+{
+ int cycles;
+
+ if (model_insn == FRV_INSN_MODEL_PASS_1)
+ {
+ /* Wait for both GNER registers or just the one specified. */
+ if (in_FRk == -1)
+ {
+ vliw_wait_for_SPR (cpu, H_SPR_FNER0);
+ vliw_wait_for_SPR (cpu, H_SPR_FNER1);
+ }
+ else
+ vliw_wait_for_SPR (cpu, FNER_FOR_FR (in_FRk));
+ 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_commit (SIM_CPU *cpu, const IDESC *idesc,
+ int unit_num, int referenced,
+ INT in_GRk, INT in_FRk)
+{
+ int cycles;
+
+ if (model_insn == FRV_INSN_MODEL_PASS_1)
+ {
+ /* If GR is specified, then FR is not and vice-versa. If neither is
+ then it's a commitga or commitfa. Check the insn attribute to
+ figure out which. */
+ if (in_GRk != -1)
+ vliw_wait_for_SPR (cpu, GNER_FOR_GR (in_GRk));
+ else if (in_FRk != -1)
+ vliw_wait_for_SPR (cpu, FNER_FOR_FR (in_FRk));
+ else if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_FR_ACCESS))
+ {
+ vliw_wait_for_SPR (cpu, H_SPR_FNER0);
+ vliw_wait_for_SPR (cpu, H_SPR_FNER1);
+ }
+ else
+ {
+ vliw_wait_for_SPR (cpu, H_SPR_GNER0);
+ vliw_wait_for_SPR (cpu, H_SPR_GNER1);
+ }
+ 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,
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);
+ 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);
+ }
+
+ if (out_GRk >= 0)
+ set_use_is_gr_complex (cpu, out_GRk);
+ if (out_GRdoublek != -1)
+ {
+ set_use_is_gr_complex (cpu, out_GRdoublek);
+ set_use_is_gr_complex (cpu, out_GRdoublek + 1);
+ }
return cycles;
}
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);
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);
+ }
+
fr500_reset_fr_flags (cpu, out_FRk);
return 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. */
+ which is not ready yet. */
+ vliw_wait_for_SPR (cpu, in_spr);
vliw_wait_for_GR (cpu, out_GRj);
handle_resource_wait (cpu);
load_wait_for_GR (cpu, out_GRj);
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);
+ adjust_float_register_busy (cpu, -1, -1, out_FRk, 1);
}
vliw_wait_for_GR (cpu, in_GRj);
vliw_wait_for_FR (cpu, out_FRk);
decrease_GR_busy (cpu, in_GRj, 1);
}
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 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,
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, in_FRj, out_FRk, 1);
restore_double_register_busy (cpu, in_FRdoublei, in_FRdoublej, out_FRdoublek,
1);
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 3 cycles. */
update_FR_ptime (cpu, out_FRk, 3);
update_FRdouble_ptime (cpu, out_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 (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);
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, 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,
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)
set_use_is_fpop (cpu, out_FRk);
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));
vliw = CPU_VLIW (cpu);
slot = vliw->next_slot - 1;
slot = (*vliw->current_vliw)[slot] - UNIT_FM0;
update_FR_latency (cpu, out_FRk, ps->post_wait);
update_FR_ptime (cpu, out_FRk, 10);
+ if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING))
+ {
+ /* FNER has a latency of 10 cycles. */
+ update_SPR_latency (cpu, FNER_FOR_FR (out_FRk), ps->post_wait);
+ update_SPR_ptime (cpu, FNER_FOR_FR (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);
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));
vliw = CPU_VLIW (cpu);
slot = vliw->next_slot - 1;
slot = (*vliw->current_vliw)[slot] - UNIT_FM0;
/* 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);
/* Once initiated, post-processing will take 15 cycles. */
update_FR_ptime (cpu, out_FRk, 15);
update_FRdouble_ptime (cpu, out_FRdoublek, 15);
+ if (CGEN_ATTR_VALUE(idesc, idesc->attrs, CGEN_INSN_NON_EXCEPTING))
+ update_SPR_ptime (cpu, FNER_FOR_FR (out_FRk), 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);
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, 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);
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 3 cycles. */
update_FR_ptime (cpu, out_FRk, 3);
update_FR_ptime (cpu, out_FRintk, 3);
update_FRdouble_ptime (cpu, out_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 (out_FRintk), 3);
+ update_SPR_ptime (cpu, FNER_FOR_FR (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 (dual_FRk >= 0)
fr[dual_FRk] += busy_adjustment[2];
- /* The latency of tht output register will be at least the latency of the
+ /* The latency of the 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);