ld: Require GCC 5 for Build pr25749-1b (-pie -fPIE)
[deliverable/binutils-gdb.git] / sim / frv / profile.c
index 1a59e4a89a7f41afd3541d0a1e83f3900f29bf23..14c4cfec362e2cf561d82fa741870a9a918e6090 100644 (file)
@@ -1,23 +1,22 @@
 /* frv simulator machine independent profiling code.
 
-   Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 1998-2020 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
@@ -31,12 +30,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "profile.h"
 #include "profile-fr400.h"
 #include "profile-fr500.h"
+#include "profile-fr550.h"
 
 static void
 reset_gr_flags (SIM_CPU *cpu, INT gr)
 {
   SIM_DESC sd = CPU_STATE (cpu);
-  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400)
+  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400
+      || STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450)
     fr400_reset_gr_flags (cpu, gr);
   /* Other machines have no gr flags right now.  */
 }
@@ -45,7 +46,8 @@ static void
 reset_fr_flags (SIM_CPU *cpu, INT fr)
 {
   SIM_DESC sd = CPU_STATE (cpu);
-  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400)
+  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400
+      || STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450)
     fr400_reset_fr_flags (cpu, fr);
   else if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr500)
     fr500_reset_fr_flags (cpu, fr);
@@ -55,7 +57,8 @@ static void
 reset_acc_flags (SIM_CPU *cpu, INT acc)
 {
   SIM_DESC sd = CPU_STATE (cpu);
-  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400)
+  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400
+      || STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450)
     fr400_reset_acc_flags (cpu, acc);
   /* Other machines have no acc flags right now.  */
 }
@@ -677,10 +680,13 @@ update_latencies (SIM_CPU *cpu, int cycles)
   int *fdiv;
   int *fsqrt;
   int *idiv;
+  int *flt;
+  int *media;
   int *ccr;
   int *gr  = ps->gr_busy;
   int *fr  = ps->fr_busy;
   int *acc = ps->acc_busy;
+  int *spr;
   /* This loop handles GR, FR and ACC registers.  */
   for (i = 0; i < 64; ++i)
     {
@@ -734,6 +740,16 @@ update_latencies (SIM_CPU *cpu, int cycles)
        *ccr -= cycles;
       ++ccr;
     }
+  /* This loop handles SPR registers.  */
+  spr = ps->spr_busy;
+  for (i = 0; i < 4096; ++i)
+    {
+      if (*spr <= cycles)
+       *spr = 0;
+      else
+       *spr -= cycles;
+      ++spr;
+    }
   /* This loop handles resources.  */
   idiv = ps->idiv_busy;
   fdiv = ps->fdiv_busy;
@@ -747,6 +763,16 @@ update_latencies (SIM_CPU *cpu, int cycles)
       ++fdiv;
       ++fsqrt;
     }
+  /* Float and media units can occur in 4 slots on some machines.  */
+  flt = ps->float_busy;
+  media = ps->media_busy;
+  for (i = 0; i < 4; ++i)
+    {
+      *flt = (*flt <= cycles) ? 0 : (*flt - cycles);
+      *media = (*media <= cycles) ? 0 : (*media - cycles);
+      ++flt;
+      ++media;
+    }
 }
 
 /* Print information about the wait for the given number of cycles.  */
@@ -805,10 +831,12 @@ update_target_latencies (SIM_CPU *cpu)
   int *gr_lat  = ps->gr_latency;
   int *fr_lat  = ps->fr_latency;
   int *acc_lat = ps->acc_latency;
+  int *spr_lat;
   int *ccr;
   int *gr = ps->gr_busy;
   int  *fr = ps->fr_busy;
   int  *acc = ps->acc_busy;
+  int *spr;
   /* This loop handles GR, FR and ACC registers.  */
   for (i = 0; i < 64; ++i)
     {
@@ -843,6 +871,18 @@ update_target_latencies (SIM_CPU *cpu)
        }
       ++ccr; ++ccr_lat;
     }
+  /* This loop handles SPR registers.  */
+  spr = ps->spr_busy;
+  spr_lat = ps->spr_latency;
+  for (i = 0; i < 4096; ++i)
+    {
+      if (*spr_lat)
+       {
+         *spr = *spr_lat;
+         *spr_lat = 0;
+       }
+      ++spr; ++spr_lat;
+    }
 }
 
 /* Run the caches until all pending cache flushes are complete.  */
@@ -888,11 +928,15 @@ frvbf_model_insn_before (SIM_CPU *cpu, int first_p)
   switch (STATE_ARCHITECTURE (sd)->mach)
     {
     case bfd_mach_fr400:
+    case bfd_mach_fr450:
       fr400_model_insn_before (cpu, first_p);
       break;
     case bfd_mach_fr500:
       fr500_model_insn_before (cpu, first_p);
       break;
+    case bfd_mach_fr550:
+      fr550_model_insn_before (cpu, first_p);
+      break;
     default:
       break;
     }
@@ -951,11 +995,15 @@ frvbf_model_insn_after (SIM_CPU *cpu, int last_p, int cycles)
   switch (STATE_ARCHITECTURE (sd)->mach)
     {
     case bfd_mach_fr400:
+    case bfd_mach_fr450:
       fr400_model_insn_after (cpu, last_p, cycles);
       break;
     case bfd_mach_fr500:
       fr500_model_insn_after (cpu, last_p, cycles);
       break;
+    case bfd_mach_fr550:
+      fr550_model_insn_after (cpu, last_p, cycles);
+      break;
     default:
       break;
     }
@@ -1130,6 +1178,52 @@ update_FRdouble_latency_for_load (SIM_CPU *cpu, INT out_FR, int cycles)
 /* Top up the post-processing time of the given FR by the given number of
    cycles.  */
 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;
+    }
+}
+
+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;
+       }
+    }
+}
+
+/* Top up the post-processing time of the given ACC by the given number of
+   cycles.  */
+void
 update_ACC_ptime (SIM_CPU *cpu, INT out_ACC, int cycles)
 {
   if (out_ACC >= 0)
@@ -1142,6 +1236,21 @@ update_ACC_ptime (SIM_CPU *cpu, INT out_ACC, int cycles)
     }
 }
 
+/* Top up the post-processing time of the given SPR by the given number of
+   cycles.  */
+void
+update_SPR_ptime (SIM_CPU *cpu, INT out_SPR, int cycles)
+{
+  if (out_SPR >= 0)
+    {
+      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
+      /* No load can be pending on this register. Apply the cycles
+        directly to the latency of the register.  */
+      int *spr = ps->spr_latency;
+      spr[out_SPR] += cycles;
+    }
+}
+
 void
 decrease_ACC_busy (SIM_CPU *cpu, INT out_ACC, int cycles)
 {
@@ -1156,6 +1265,24 @@ decrease_ACC_busy (SIM_CPU *cpu, INT out_ACC, int cycles)
     }
 }
 
+void
+increase_ACC_busy (SIM_CPU *cpu, INT out_ACC, int cycles)
+{
+  if (out_ACC >= 0)
+    {
+      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
+      int *acc = ps->acc_busy;
+      acc[out_ACC] += cycles;
+    }
+}
+
+void
+enforce_full_acc_latency (SIM_CPU *cpu, INT in_ACC)
+{
+  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
+  ps->acc_busy_adjust [in_ACC] = -1;
+}
+
 void
 decrease_FR_busy (SIM_CPU *cpu, INT out_FR, int cycles)
 {
@@ -1207,6 +1334,19 @@ update_CCR_latency (SIM_CPU *cpu, INT out_CCR, int cycles)
     }
 }
 
+/* Top up the latency of the given SPR by the given number of cycles.  */
+void
+update_SPR_latency (SIM_CPU *cpu, INT out_SPR, int cycles)
+{
+  if (out_SPR >= 0)
+    {
+      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
+      int *spr = ps->spr_latency;
+      if (spr[out_SPR] < cycles)
+       spr[out_SPR] = cycles;
+    }
+}
+
 /* Top up the latency of the given integer division resource by the given
    number of cycles.  */
 void
@@ -1241,6 +1381,27 @@ update_fsqrt_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
   r[in_resource] = cycles;
 }
 
+/* Set the latency of the given resource to the given number of cycles.  */
+void
+update_float_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
+{
+  /* operate directly on the busy cycles since each resource can only
+     be used once in a VLIW insn.  */
+  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
+  int *r = ps->float_busy;
+  r[in_resource] = cycles;
+}
+
+void
+update_media_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
+{
+  /* operate directly on the busy cycles since each resource can only
+     be used once in a VLIW insn.  */
+  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
+  int *r = ps->media_busy;
+  r[in_resource] = cycles;
+}
+
 /* Set the branch penalty to the given number of cycles.  */
 void
 update_branch_penalty (SIM_CPU *cpu, int cycles)
@@ -1376,6 +1537,23 @@ vliw_wait_for_ACC (SIM_CPU *cpu, INT in_ACC)
     }
 }
 
+/* Check the availability of the given SPR register and update the number
+   of cycles the current VLIW insn must wait until it is available.  */
+void
+vliw_wait_for_SPR (SIM_CPU *cpu, INT in_SPR)
+{
+  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
+  int *spr = ps->spr_busy;
+  /* If the latency of the register is greater than the current wait
+     then update the current wait.  */
+  if (in_SPR >= 0 && spr[in_SPR] > ps->vliw_wait)
+    {
+      if (TRACE_INSN_P (cpu))
+       sprintf (hazard_name, "Data hazard for spr %d:", in_SPR);
+      ps->vliw_wait = spr[in_SPR];
+    }
+}
+
 /* Check the availability of the given integer division resource and update
    the number of cycles the current VLIW insn must wait until it is available.
 */
@@ -1410,7 +1588,7 @@ vliw_wait_for_fdiv_resource (SIM_CPU *cpu, INT in_resource)
     {
       if (TRACE_INSN_P (cpu))
        {
-         sprintf (hazard_name, "Resource hazard for integer division in slot I%d:", in_resource);
+         sprintf (hazard_name, "Resource hazard for floating point division in slot F%d:", in_resource);
        }
       ps->vliw_wait = r[in_resource];
     }
@@ -1430,7 +1608,47 @@ vliw_wait_for_fsqrt_resource (SIM_CPU *cpu, INT in_resource)
     {
       if (TRACE_INSN_P (cpu))
        {
-         sprintf (hazard_name, "Resource hazard for integer division in slot I%d:", in_resource);
+         sprintf (hazard_name, "Resource hazard for square root in slot F%d:", in_resource);
+       }
+      ps->vliw_wait = r[in_resource];
+    }
+}
+
+/* Check the availability of the given float unit resource and update
+   the number of cycles the current VLIW insn must wait until it is available.
+*/
+void
+vliw_wait_for_float_resource (SIM_CPU *cpu, INT in_resource)
+{
+  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
+  int *r = ps->float_busy;
+  /* If the latency of the resource is greater than the current wait
+     then update the current wait.  */
+  if (r[in_resource] > ps->vliw_wait)
+    {
+      if (TRACE_INSN_P (cpu))
+       {
+         sprintf (hazard_name, "Resource hazard for floating point unit in slot F%d:", in_resource);
+       }
+      ps->vliw_wait = r[in_resource];
+    }
+}
+
+/* Check the availability of the given media unit resource and update
+   the number of cycles the current VLIW insn must wait until it is available.
+*/
+void
+vliw_wait_for_media_resource (SIM_CPU *cpu, INT in_resource)
+{
+  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
+  int *r = ps->media_busy;
+  /* If the latency of the resource is greater than the current wait
+     then update the current wait.  */
+  if (r[in_resource] > ps->vliw_wait)
+    {
+      if (TRACE_INSN_P (cpu))
+       {
+         sprintf (hazard_name, "Resource hazard for media unit in slot M%d:", in_resource);
        }
       ps->vliw_wait = r[in_resource];
     }
@@ -1638,6 +1856,20 @@ post_wait_for_CCR (SIM_CPU *cpu, INT in_CCR)
     }
 }
 
+int
+post_wait_for_SPR (SIM_CPU *cpu, INT in_SPR)
+{
+  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
+  int *spr = ps->spr_busy;
+
+  if (in_SPR >= 0 && spr[in_SPR] > ps->post_wait)
+    {
+      ps->post_wait = spr[in_SPR];
+      if (TRACE_INSN_P (cpu))
+       sprintf (hazard_name, "Data hazard for spr[%d]:", in_SPR);
+    }
+}
+
 int
 post_wait_for_fdiv (SIM_CPU *cpu, INT slot)
 {
@@ -1674,6 +1906,42 @@ post_wait_for_fsqrt (SIM_CPU *cpu, INT slot)
     }
 }
 
+int
+post_wait_for_float (SIM_CPU *cpu, INT slot)
+{
+  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
+  int *flt = ps->float_busy;
+
+  /* Multiple floating point square roots in the same slot need only wait 1
+     extra cycle.  */
+  if (flt[slot] > ps->post_wait)
+    {
+      ps->post_wait = flt[slot];
+      if (TRACE_INSN_P (cpu))
+       {
+         sprintf (hazard_name, "Resource hazard for floating point unit in slot F%d:", slot);
+       }
+    }
+}
+
+int
+post_wait_for_media (SIM_CPU *cpu, INT slot)
+{
+  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
+  int *media = ps->media_busy;
+
+  /* Multiple floating point square roots in the same slot need only wait 1
+     extra cycle.  */
+  if (media[slot] > ps->post_wait)
+    {
+      ps->post_wait = media[slot];
+      if (TRACE_INSN_P (cpu))
+       {
+         sprintf (hazard_name, "Resource hazard for media unit in slot M%d:", slot);
+       }
+    }
+}
+
 /* Print cpu-specific profile information.  */
 #define COMMAS(n) sim_add_commas (comma_buf, sizeof (comma_buf), (n))
 
@@ -1706,12 +1974,15 @@ print_cache (SIM_CPU *cpu, FRV_CACHE *cache, const char *cache_name)
   sim_io_printf (sd, "\n");
 }
 
+/* This table must correspond to the UNIT_ATTR table in
+   opcodes/frv-desc.h. Only the units up to UNIT_C need be
+   listed since the others cannot occur after mapping.  */
 static char *
 slot_names[] =
 {
   "none",
-  "I0", "I1", "I01",
-  "FM1", "FM1", "FM01",
+  "I0", "I1", "I01", "I2", "I3", "IALL",
+  "FM0", "FM1", "FM01", "FM2", "FM3", "FMALL", "FMLOW",
   "B0", "B1", "B01",
   "C"
 };
@@ -1747,12 +2018,15 @@ print_parallel (SIM_CPU *cpu, int verbose)
       int max_name_len = 0;
       for (i = UNIT_NIL + 1; i < UNIT_NUM_UNITS; ++i)
        {
-         int len;
-         if (INSNS_IN_SLOT (i) > max_val)
-           max_val = INSNS_IN_SLOT (i);
-         len = strlen (slot_names[i]);
-         if (len > max_name_len)
-           max_name_len = len;
+         if (INSNS_IN_SLOT (i))
+           {
+             int len;
+             if (INSNS_IN_SLOT (i) > max_val)
+               max_val = INSNS_IN_SLOT (i);
+             len = strlen (slot_names[i]);
+             if (len > max_name_len)
+               max_name_len = len;
+           }
        }
       if (max_val > 0)
        {
@@ -1767,7 +2041,7 @@ print_parallel (SIM_CPU *cpu, int verbose)
                                 max_name_len, slot_names[i],
                                 max_val < 10000 ? 5 : 10,
                                 COMMAS (INSNS_IN_SLOT (i)));
-                 sim_profile_print_bar (sd, PROFILE_HISTOGRAM_WIDTH,
+                 sim_profile_print_bar (sd, cpu, PROFILE_HISTOGRAM_WIDTH,
                                         INSNS_IN_SLOT (i),
                                         max_val);
                  sim_io_printf (sd, "\n");
This page took 0.028795 seconds and 4 git commands to generate.