Emit a warning when -z relro is unsupported
[deliverable/binutils-gdb.git] / sim / frv / cache.c
index 5093f16b5ef2ed3e415d53cc8c42ca28ca93cf0b..60857d9445f2173704663195028efaec0afeb1e6 100644 (file)
@@ -1,22 +1,21 @@
 /* frv cache model.
-   Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 1999-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 frvbf
 #define WANT_CPU_FRVBF
@@ -38,20 +37,31 @@ frv_cache_init (SIM_CPU *cpu, FRV_CACHE *cache)
   switch (STATE_ARCHITECTURE (sd)->mach)
     {
     case bfd_mach_fr400:
-      if (cache->sets == 0)
-       cache->sets = 128;
-      if (cache->ways == 0)
-       cache->ways = 2;
+    case bfd_mach_fr450:
+      if (cache->configured_sets == 0)
+       cache->configured_sets = 512;
+      if (cache->configured_ways == 0)
+       cache->configured_ways = 2;
       if (cache->line_size == 0)
        cache->line_size = 32;
       if (cache->memory_latency == 0)
        cache->memory_latency = 20;
       break;
+    case bfd_mach_fr550:
+      if (cache->configured_sets == 0)
+       cache->configured_sets = 128;
+      if (cache->configured_ways == 0)
+       cache->configured_ways = 4;
+      if (cache->line_size == 0)
+       cache->line_size = 64;
+      if (cache->memory_latency == 0)
+       cache->memory_latency = 20;
+      break;
     default:
-      if (cache->sets == 0)
-       cache->sets = 64;
-      if (cache->ways == 0)
-       cache->ways = 4;
+      if (cache->configured_sets == 0)
+       cache->configured_sets = 64;
+      if (cache->configured_ways == 0)
+       cache->configured_ways = 4;
       if (cache->line_size == 0)
        cache->line_size = 64;
       if (cache->memory_latency == 0)
@@ -59,6 +69,8 @@ frv_cache_init (SIM_CPU *cpu, FRV_CACHE *cache)
       break;
     }
 
+  frv_cache_reconfigure (cpu, cache);
+
   /* First allocate the cache storage based on the given dimensions.  */
   elements = cache->sets * cache->ways;
   cache->tag_storage = (FRV_CACHE_TAG *)
@@ -95,6 +107,40 @@ frv_cache_term (FRV_CACHE *cache)
   free (cache->pipeline[LD].status.return_buffer.data);
 }
 
+/* Reset the cache configuration based on registers in the cpu.  */
+void
+frv_cache_reconfigure (SIM_CPU *current_cpu, FRV_CACHE *cache)
+{
+  int ihsr8;
+  int icdm;
+  SIM_DESC sd;
+
+  /* Set defaults for fields which are not initialized.  */
+  sd = CPU_STATE (current_cpu);
+  switch (STATE_ARCHITECTURE (sd)->mach)
+    {
+    case bfd_mach_fr550:
+      if (cache == CPU_INSN_CACHE (current_cpu))
+       {
+         ihsr8 = GET_IHSR8 ();
+         icdm = GET_IHSR8_ICDM (ihsr8);
+         /* If IHSR8.ICDM is set, then the cache becomes a one way cache.  */
+         if (icdm)
+           {
+             cache->sets = cache->sets * cache->ways;
+             cache->ways = 1;
+             break;
+           }
+       }
+      /* fall through */
+    default:
+      /* Set the cache to its original settings.  */
+      cache->sets = cache->configured_sets;
+      cache->ways = cache->configured_ways;
+      break;
+    }
+}
+
 /* Determine whether the given cache is enabled.  */
 int
 frv_cache_enabled (FRV_CACHE *cache)
@@ -108,6 +154,44 @@ frv_cache_enabled (FRV_CACHE *cache)
   return 0;
 }
 
+/* Determine whether the given address is RAM access, assuming that HSR0.RME
+   is set.  */
+static int
+ram_access (FRV_CACHE *cache, USI address) 
+{
+  int ihsr8;
+  int cwe;
+  USI start, end, way_size;
+  SIM_CPU *current_cpu = cache->cpu;
+  SIM_DESC sd = CPU_STATE (current_cpu);
+
+  switch (STATE_ARCHITECTURE (sd)->mach)
+    {
+    case bfd_mach_fr550:
+      /* IHSR8.DCWE or IHSR8.ICWE deternines which ways get RAM access.  */
+      ihsr8 = GET_IHSR8 ();
+      if (cache == CPU_INSN_CACHE (current_cpu))
+       {
+         start = 0xfe000000;
+         end = 0xfe008000;
+         cwe = GET_IHSR8_ICWE (ihsr8);
+       }
+      else
+       {
+         start = 0xfe400000;
+         end = 0xfe408000;
+         cwe = GET_IHSR8_DCWE (ihsr8);
+       }
+      way_size = (end - start) / 4;
+      end -= way_size * cwe;
+      return address >= start && address < end;
+    default:
+      break;
+    }
+
+  return 1; /* RAM access */
+}
+
 /* Determine whether the given address should be accessed without using
    the cache.  */
 static int
@@ -121,9 +205,23 @@ non_cache_access (FRV_CACHE *cache, USI address)
   switch (STATE_ARCHITECTURE (sd)->mach)
     {
     case bfd_mach_fr400:
+    case bfd_mach_fr450:
       if (address >= 0xff000000
          || address >= 0xfe000000 && address <= 0xfeffffff)
        return 1; /* non-cache access */
+      break;
+    case bfd_mach_fr550:
+      if (address >= 0xff000000
+         || address >= 0xfeff0000 && address <= 0xfeffffff)
+       return 1; /* non-cache access */
+      if (cache == CPU_INSN_CACHE (current_cpu))
+       {
+         if (address >= 0xfe000000 && address <= 0xfe007fff)
+           return 1; /* non-cache access */
+       }
+      else if (address >= 0xfe400000 && address <= 0xfe407fff)
+       return 1; /* non-cache access */
+      break;
     default:
       if (address >= 0xff000000
          || address >= 0xfeff0000 && address <= 0xfeffffff)
@@ -135,11 +233,12 @@ non_cache_access (FRV_CACHE *cache, USI address)
        }
       else if (address >= 0xfe400000 && address <= 0xfe403fff)
        return 1; /* non-cache access */
+      break;
     }
 
   hsr0 = GET_HSR0 ();
   if (GET_HSR0_RME (hsr0))
-    return 1; /* non-cache access */
+    return ram_access (cache, address);
 
   return 0; /* cache-access */
 }
@@ -1014,14 +1113,23 @@ address_interference (FRV_CACHE *cache, SI address, FRV_CACHE_REQUEST *req,
            return 1;
        }
       /* If this is not a WAR request, then yield to any WAR requests in
-        either pipeline.  */
+        either pipeline or to a higher priority request in the same pipeline.
+      */
       if (req->kind != req_WAR)
        {
          for (j = FIRST_STAGE; j < FRV_CACHE_STAGES; ++j)
            {
              other_req = cache->pipeline[i].stages[j].request;
-             if (other_req != NULL && other_req->kind == req_WAR)
-               return 1;
+             if (other_req != NULL)
+               {
+                 if (other_req->kind == req_WAR)
+                   return 1;
+                 if (i == pipe
+                     && (address == (other_req->address & line_mask) 
+                         || address == all_address)
+                     && priority > other_req->priority)
+                   return 1;
+               }
            }
        }
     }
@@ -1531,7 +1639,6 @@ frv_cache_read_passive_SI (FRV_CACHE *cache, SI address, SI *value)
   /* A cache line was available for the data.
      Extract the target data from the line.  */
   offset = address & (cache->line_size - 1);
-  offset &= ~3;
   *value = T2H_4 (*(SI *)(tag->line + offset));
   return 1;
 }
This page took 0.025979 seconds and 4 git commands to generate.