Don't write to inferior_ptid in linux_get_siginfo_data
[deliverable/binutils-gdb.git] / sim / frv / profile.c
index 6ef1e3581b2b7a56ad8d6a29d07598173d0bbabf..14c4cfec362e2cf561d82fa741870a9a918e6090 100644 (file)
@@ -1,23 +1,22 @@
 /* frv simulator machine independent profiling code.
 
-   Copyright (C) 1998, 1999, 2000, 2001, 2003 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,6 +680,8 @@ 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;
@@ -758,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.  */
@@ -913,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;
     }
@@ -976,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;
     }
@@ -1155,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)
@@ -1167,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)
 {
@@ -1181,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)
 {
@@ -1279,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)
@@ -1465,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];
     }
@@ -1485,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];
     }
@@ -1693,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)
 {
@@ -1729,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))
 
@@ -1768,8 +1981,8 @@ static char *
 slot_names[] =
 {
   "none",
-  "I0", "I1", "I01", "IALL",
-  "FM0", "FM1", "FM01", "FMALL", "FMLOW",
+  "I0", "I1", "I01", "I2", "I3", "IALL",
+  "FM0", "FM1", "FM01", "FM2", "FM3", "FMALL", "FMLOW",
   "B0", "B1", "B01",
   "C"
 };
@@ -1828,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.028016 seconds and 4 git commands to generate.