xref: /netbsd-src/external/gpl3/gdb.old/dist/sim/frv/cache.c (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
1 /* frv cache model.
2    Copyright (C) 1999-2023 Free Software Foundation, Inc.
3    Contributed by Red Hat.
4 
5 This file is part of the GNU simulators.
6 
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 /* This must come before any other includes.  */
21 #include "defs.h"
22 
23 #define WANT_CPU frvbf
24 #define WANT_CPU_FRVBF
25 
26 #include "libiberty.h"
27 #include "sim-main.h"
28 #include "cache.h"
29 #include "bfd.h"
30 #include <stdlib.h>
31 
32 void
33 frv_cache_init (SIM_CPU *cpu, FRV_CACHE *cache)
34 {
35   int elements;
36   int i, j;
37   SIM_DESC sd;
38 
39   /* Set defaults for fields which are not initialized.  */
40   sd = CPU_STATE (cpu);
41   switch (STATE_ARCHITECTURE (sd)->mach)
42     {
43     case bfd_mach_fr400:
44     case bfd_mach_fr450:
45       if (cache->configured_sets == 0)
46 	cache->configured_sets = 512;
47       if (cache->configured_ways == 0)
48 	cache->configured_ways = 2;
49       if (cache->line_size == 0)
50 	cache->line_size = 32;
51       if (cache->memory_latency == 0)
52 	cache->memory_latency = 20;
53       break;
54     case bfd_mach_fr550:
55       if (cache->configured_sets == 0)
56 	cache->configured_sets = 128;
57       if (cache->configured_ways == 0)
58 	cache->configured_ways = 4;
59       if (cache->line_size == 0)
60 	cache->line_size = 64;
61       if (cache->memory_latency == 0)
62 	cache->memory_latency = 20;
63       break;
64     default:
65       if (cache->configured_sets == 0)
66 	cache->configured_sets = 64;
67       if (cache->configured_ways == 0)
68 	cache->configured_ways = 4;
69       if (cache->line_size == 0)
70 	cache->line_size = 64;
71       if (cache->memory_latency == 0)
72 	cache->memory_latency = 20;
73       break;
74     }
75 
76   frv_cache_reconfigure (cpu, cache);
77 
78   /* First allocate the cache storage based on the given dimensions.  */
79   elements = cache->sets * cache->ways;
80   cache->tag_storage = (FRV_CACHE_TAG *)
81     zalloc (elements * sizeof (*cache->tag_storage));
82   cache->data_storage = (char *) xmalloc (elements * cache->line_size);
83 
84   /* Initialize the pipelines and status buffers.  */
85   for (i = LS; i < FRV_CACHE_PIPELINES; ++i)
86     {
87       cache->pipeline[i].requests = NULL;
88       cache->pipeline[i].status.flush.valid = 0;
89       cache->pipeline[i].status.return_buffer.valid = 0;
90       cache->pipeline[i].status.return_buffer.data
91 	= (char *) xmalloc (cache->line_size);
92       for (j = FIRST_STAGE; j < FRV_CACHE_STAGES; ++j)
93 	cache->pipeline[i].stages[j].request = NULL;
94     }
95   cache->BARS.valid = 0;
96   cache->NARS.valid = 0;
97 
98   /* Now set the cache state.  */
99   cache->cpu = cpu;
100   cache->statistics.accesses = 0;
101   cache->statistics.hits = 0;
102 }
103 
104 void
105 frv_cache_term (FRV_CACHE *cache)
106 {
107   /* Free the cache storage.  */
108   free (cache->tag_storage);
109   free (cache->data_storage);
110   free (cache->pipeline[LS].status.return_buffer.data);
111   free (cache->pipeline[LD].status.return_buffer.data);
112 }
113 
114 /* Reset the cache configuration based on registers in the cpu.  */
115 void
116 frv_cache_reconfigure (SIM_CPU *current_cpu, FRV_CACHE *cache)
117 {
118   int ihsr8;
119   int icdm;
120   SIM_DESC sd;
121 
122   /* Set defaults for fields which are not initialized.  */
123   sd = CPU_STATE (current_cpu);
124   switch (STATE_ARCHITECTURE (sd)->mach)
125     {
126     case bfd_mach_fr550:
127       if (cache == CPU_INSN_CACHE (current_cpu))
128 	{
129 	  ihsr8 = GET_IHSR8 ();
130 	  icdm = GET_IHSR8_ICDM (ihsr8);
131 	  /* If IHSR8.ICDM is set, then the cache becomes a one way cache.  */
132 	  if (icdm)
133 	    {
134 	      cache->sets = cache->sets * cache->ways;
135 	      cache->ways = 1;
136 	      break;
137 	    }
138 	}
139       /* fall through */
140     default:
141       /* Set the cache to its original settings.  */
142       cache->sets = cache->configured_sets;
143       cache->ways = cache->configured_ways;
144       break;
145     }
146 }
147 
148 /* Determine whether the given cache is enabled.  */
149 int
150 frv_cache_enabled (FRV_CACHE *cache)
151 {
152   SIM_CPU *current_cpu = cache->cpu;
153   int hsr0 = GET_HSR0 ();
154   if (GET_HSR0_ICE (hsr0) && cache == CPU_INSN_CACHE (current_cpu))
155     return 1;
156   if (GET_HSR0_DCE (hsr0) && cache == CPU_DATA_CACHE (current_cpu))
157     return 1;
158   return 0;
159 }
160 
161 /* Determine whether the given address is RAM access, assuming that HSR0.RME
162    is set.  */
163 static int
164 ram_access (FRV_CACHE *cache, USI address)
165 {
166   int ihsr8;
167   int cwe;
168   USI start, end, way_size;
169   SIM_CPU *current_cpu = cache->cpu;
170   SIM_DESC sd = CPU_STATE (current_cpu);
171 
172   switch (STATE_ARCHITECTURE (sd)->mach)
173     {
174     case bfd_mach_fr550:
175       /* IHSR8.DCWE or IHSR8.ICWE deternines which ways get RAM access.  */
176       ihsr8 = GET_IHSR8 ();
177       if (cache == CPU_INSN_CACHE (current_cpu))
178 	{
179 	  start = 0xfe000000;
180 	  end = 0xfe008000;
181 	  cwe = GET_IHSR8_ICWE (ihsr8);
182 	}
183       else
184 	{
185 	  start = 0xfe400000;
186 	  end = 0xfe408000;
187 	  cwe = GET_IHSR8_DCWE (ihsr8);
188 	}
189       way_size = (end - start) / 4;
190       end -= way_size * cwe;
191       return address >= start && address < end;
192     default:
193       break;
194     }
195 
196   return 1; /* RAM access */
197 }
198 
199 /* Determine whether the given address should be accessed without using
200    the cache.  */
201 static int
202 non_cache_access (FRV_CACHE *cache, USI address)
203 {
204   int hsr0;
205   SIM_DESC sd;
206   SIM_CPU *current_cpu = cache->cpu;
207 
208   sd = CPU_STATE (current_cpu);
209   switch (STATE_ARCHITECTURE (sd)->mach)
210     {
211     case bfd_mach_fr400:
212     case bfd_mach_fr450:
213       if (address >= 0xff000000
214 	  || (address >= 0xfe000000 && address <= 0xfeffffff))
215 	return 1; /* non-cache access */
216       break;
217     case bfd_mach_fr550:
218       if (address >= 0xff000000
219 	  || (address >= 0xfeff0000 && address <= 0xfeffffff))
220 	return 1; /* non-cache access */
221       if (cache == CPU_INSN_CACHE (current_cpu))
222 	{
223 	  if (address >= 0xfe000000 && address <= 0xfe007fff)
224 	    return 1; /* non-cache access */
225 	}
226       else if (address >= 0xfe400000 && address <= 0xfe407fff)
227 	return 1; /* non-cache access */
228       break;
229     default:
230       if (address >= 0xff000000
231 	  || (address >= 0xfeff0000 && address <= 0xfeffffff))
232 	return 1; /* non-cache access */
233       if (cache == CPU_INSN_CACHE (current_cpu))
234 	{
235 	  if (address >= 0xfe000000 && address <= 0xfe003fff)
236 	    return 1; /* non-cache access */
237 	}
238       else if (address >= 0xfe400000 && address <= 0xfe403fff)
239 	return 1; /* non-cache access */
240       break;
241     }
242 
243   hsr0 = GET_HSR0 ();
244   if (GET_HSR0_RME (hsr0))
245     return ram_access (cache, address);
246 
247   return 0; /* cache-access */
248 }
249 
250 /* Find the cache line corresponding to the given address.
251    If it is found then 'return_tag' is set to point to the tag for that line
252    and 1 is returned.
253    If it is not found, 'return_tag' is set to point to the tag for the least
254    recently used line and 0 is returned.
255 */
256 static int
257 get_tag (FRV_CACHE *cache, SI address, FRV_CACHE_TAG **return_tag)
258 {
259   int set;
260   int way;
261   int bits;
262   USI tag;
263   FRV_CACHE_TAG *found;
264   FRV_CACHE_TAG *available;
265 
266   ++cache->statistics.accesses;
267 
268   /* First calculate which set this address will fall into. Do this by
269      shifting out the bits representing the offset within the line and
270      then keeping enough bits to index the set.  */
271   set = address & ~(cache->line_size - 1);
272   for (bits = cache->line_size - 1; bits != 0; bits >>= 1)
273     set >>= 1;
274   set &= (cache->sets - 1);
275 
276   /* Now search the set for a valid tag which matches this address.  At the
277      same time make note of the least recently used tag, which we will return
278      if no match is found.  */
279   available = NULL;
280   tag = CACHE_ADDRESS_TAG (cache, address);
281   for (way = 0; way < cache->ways; ++way)
282     {
283       found = CACHE_TAG (cache, set, way);
284       /* This tag is available as the least recently used if it is the
285 	 least recently used seen so far and it is not locked.  */
286       if (! found->locked && (available == NULL || available->lru > found->lru))
287 	available = found;
288       if (found->valid && found->tag == tag)
289 	{
290 	  *return_tag = found;
291 	  ++cache->statistics.hits;
292 	  return 1; /* found it */
293 	}
294     }
295 
296   *return_tag = available;
297   return 0; /* not found */
298 }
299 
300 /* Write the given data out to memory.  */
301 static void
302 write_data_to_memory (FRV_CACHE *cache, SI address, char *data, int length)
303 {
304   SIM_CPU *cpu = cache->cpu;
305   IADDR pc = CPU_PC_GET (cpu);
306   int write_index = 0;
307 
308   switch (length)
309     {
310     case 1:
311     default:
312       PROFILE_COUNT_WRITE (cpu, address, MODE_QI);
313       break;
314     case 2:
315       PROFILE_COUNT_WRITE (cpu, address, MODE_HI);
316       break;
317     case 4:
318       PROFILE_COUNT_WRITE (cpu, address, MODE_SI);
319       break;
320     case 8:
321       PROFILE_COUNT_WRITE (cpu, address, MODE_DI);
322       break;
323     }
324 
325   for (write_index = 0; write_index < length; ++write_index)
326     {
327       /* TODO: Better way to copy memory than a byte at a time?  */
328       sim_core_write_unaligned_1 (cpu, pc, write_map, address + write_index,
329 				  data[write_index]);
330     }
331 }
332 
333 /* Write a cache line out to memory.  */
334 static void
335 write_line_to_memory (FRV_CACHE *cache, FRV_CACHE_TAG *tag)
336 {
337   SI address = tag->tag;
338   int set = CACHE_TAG_SET_NUMBER (cache, tag);
339   int bits;
340   for (bits = cache->line_size - 1; bits != 0; bits >>= 1)
341     set <<= 1;
342   address |= set;
343   write_data_to_memory (cache, address, tag->line, cache->line_size);
344 }
345 
346 static void
347 read_data_from_memory (SIM_CPU *current_cpu, SI address, char *buffer,
348 		       int length)
349 {
350   PCADDR pc = CPU_PC_GET (current_cpu);
351   int i;
352   PROFILE_COUNT_READ (current_cpu, address, MODE_QI);
353   for (i = 0; i < length; ++i)
354     {
355       /* TODO: Better way to copy memory than a byte at a time?  */
356       buffer[i] = sim_core_read_unaligned_1 (current_cpu, pc, read_map,
357 					     address + i);
358     }
359 }
360 
361 /* Fill the given cache line from memory.  */
362 static void
363 fill_line_from_memory (FRV_CACHE *cache, FRV_CACHE_TAG *tag, SI address)
364 {
365   PCADDR pc;
366   int line_alignment;
367   SI read_address;
368   SIM_CPU *current_cpu = cache->cpu;
369 
370   /* If this line is already valid and the cache is in copy-back mode, then
371      write this line to memory before refilling it.
372      Check the dirty bit first, since it is less likely to be set.  */
373   if (tag->dirty && tag->valid)
374     {
375       int hsr0 = GET_HSR0 ();
376       if (GET_HSR0_CBM (hsr0))
377 	write_line_to_memory (cache, tag);
378     }
379   else if (tag->line == NULL)
380     {
381       int line_index = tag - cache->tag_storage;
382       tag->line = cache->data_storage + (line_index * cache->line_size);
383     }
384 
385   pc = CPU_PC_GET (current_cpu);
386   line_alignment = cache->line_size - 1;
387   read_address = address & ~line_alignment;
388   read_data_from_memory (current_cpu, read_address, tag->line,
389 			 cache->line_size);
390   tag->tag = CACHE_ADDRESS_TAG (cache, address);
391   tag->valid = 1;
392 }
393 
394 /* Update the LRU information for the tags in the same set as the given tag.  */
395 static void
396 set_most_recently_used (FRV_CACHE *cache, FRV_CACHE_TAG *tag)
397 {
398   /* All tags in the same set are contiguous, so find the beginning of the
399      set by aligning to the size of a set.  */
400   FRV_CACHE_TAG *item = cache->tag_storage + CACHE_TAG_SET_START (cache, tag);
401   FRV_CACHE_TAG *limit = item + cache->ways;
402 
403   while (item < limit)
404     {
405       if (item->lru > tag->lru)
406 	--item->lru;
407       ++item;
408     }
409   tag->lru = cache->ways; /* Mark as most recently used.  */
410 }
411 
412 /* Update the LRU information for the tags in the same set as the given tag.  */
413 static void
414 set_least_recently_used (FRV_CACHE *cache, FRV_CACHE_TAG *tag)
415 {
416   /* All tags in the same set are contiguous, so find the beginning of the
417      set by aligning to the size of a set.  */
418   FRV_CACHE_TAG *item = cache->tag_storage + CACHE_TAG_SET_START (cache, tag);
419   FRV_CACHE_TAG *limit = item + cache->ways;
420 
421   while (item < limit)
422     {
423       if (item->lru != 0 && item->lru < tag->lru)
424 	++item->lru;
425       ++item;
426     }
427   tag->lru = 0; /* Mark as least recently used.  */
428 }
429 
430 /* Find the line containing the given address and load it if it is not
431    already loaded.
432    Returns the tag of the requested line.  */
433 static FRV_CACHE_TAG *
434 find_or_retrieve_cache_line (FRV_CACHE *cache, SI address)
435 {
436   /* See if this data is already in the cache.  */
437   FRV_CACHE_TAG *tag;
438   int found = get_tag (cache, address, &tag);
439 
440   /* Fill the line from memory, if it is not valid.  */
441   if (! found)
442     {
443       /* The tag could be NULL is all ways in the set were used and locked.  */
444       if (tag == NULL)
445 	return tag;
446 
447       fill_line_from_memory (cache, tag, address);
448       tag->dirty = 0;
449     }
450 
451   /* Update the LRU information for the tags in this set.  */
452   set_most_recently_used (cache, tag);
453 
454   return tag;
455 }
456 
457 static void
458 copy_line_to_return_buffer (FRV_CACHE *cache, int pipe, FRV_CACHE_TAG *tag,
459 			    SI address)
460 {
461   /* A cache line was available for the data.
462      Copy the data from the cache line to the output buffer.  */
463   memcpy (cache->pipeline[pipe].status.return_buffer.data,
464 	  tag->line, cache->line_size);
465   cache->pipeline[pipe].status.return_buffer.address
466     = address & ~(cache->line_size - 1);
467   cache->pipeline[pipe].status.return_buffer.valid = 1;
468 }
469 
470 static void
471 copy_memory_to_return_buffer (FRV_CACHE *cache, int pipe, SI address)
472 {
473   address &= ~(cache->line_size - 1);
474   read_data_from_memory (cache->cpu, address,
475 			 cache->pipeline[pipe].status.return_buffer.data,
476 			 cache->line_size);
477   cache->pipeline[pipe].status.return_buffer.address = address;
478   cache->pipeline[pipe].status.return_buffer.valid = 1;
479 }
480 
481 static void
482 set_return_buffer_reqno (FRV_CACHE *cache, int pipe, unsigned reqno)
483 {
484   cache->pipeline[pipe].status.return_buffer.reqno = reqno;
485 }
486 
487 /* Read data from the given cache.
488    Returns the number of cycles required to obtain the data.  */
489 int
490 frv_cache_read (FRV_CACHE *cache, int pipe, SI address)
491 {
492   FRV_CACHE_TAG *tag;
493 
494   if (non_cache_access (cache, address))
495     {
496       copy_memory_to_return_buffer (cache, pipe, address);
497       return 1;
498     }
499 
500   tag = find_or_retrieve_cache_line (cache, address);
501 
502   if (tag == NULL)
503     return 0; /* Indicate non-cache-access.  */
504 
505   /* A cache line was available for the data.
506      Copy the data from the cache line to the output buffer.  */
507   copy_line_to_return_buffer (cache, pipe, tag, address);
508 
509   return 1; /* TODO - number of cycles unknown */
510 }
511 
512 /* Writes data through the given cache.
513    The data is assumed to be in target endian order.
514    Returns the number of cycles required to write the data.  */
515 int
516 frv_cache_write (FRV_CACHE *cache, SI address, char *data, unsigned length)
517 {
518   int copy_back;
519 
520   /* See if this data is already in the cache.  */
521   SIM_CPU *current_cpu = cache->cpu;
522   USI hsr0 = GET_HSR0 ();
523   FRV_CACHE_TAG *tag;
524   int found;
525 
526   if (non_cache_access (cache, address))
527     {
528       write_data_to_memory (cache, address, data, length);
529       return 1;
530     }
531 
532   found = get_tag (cache, address, &tag);
533 
534   /* Write the data to the cache line if one was available and if it is
535      either a hit or a miss in copy-back mode.
536      The tag may be NULL if all ways were in use and locked on a miss.
537   */
538   copy_back = GET_HSR0_CBM (GET_HSR0 ());
539   if (tag != NULL && (found || copy_back))
540     {
541       int line_offset;
542       /* Load the line from memory first, if it was a miss.  */
543       if (! found)
544 	fill_line_from_memory (cache, tag, address);
545       line_offset = address & (cache->line_size - 1);
546       memcpy (tag->line + line_offset, data, length);
547       tag->dirty = 1;
548 
549       /* Update the LRU information for the tags in this set.  */
550       set_most_recently_used (cache, tag);
551     }
552 
553   /* Write the data to memory if there was no line available or we are in
554      write-through (not copy-back mode).  */
555   if (tag == NULL || ! copy_back)
556     {
557       write_data_to_memory (cache, address, data, length);
558       if (tag != NULL)
559 	tag->dirty = 0;
560     }
561 
562   return 1; /* TODO - number of cycles unknown */
563 }
564 
565 /* Preload the cache line containing the given address. Lock the
566    data if requested.
567    Returns the number of cycles required to write the data.  */
568 int
569 frv_cache_preload (FRV_CACHE *cache, SI address, USI length, int lock)
570 {
571   int offset;
572   int lines;
573 
574   if (non_cache_access (cache, address))
575     return 1;
576 
577   /* preload at least 1 line.  */
578   if (length == 0)
579     length = 1;
580 
581   offset = address & (cache->line_size - 1);
582   lines = 1 + (offset + length - 1) / cache->line_size;
583 
584   /* Careful with this loop -- length is unsigned.  */
585   for (/**/; lines > 0; --lines)
586     {
587       FRV_CACHE_TAG *tag = find_or_retrieve_cache_line (cache, address);
588       if (lock && tag != NULL)
589 	tag->locked = 1;
590       address += cache->line_size;
591     }
592 
593   return 1; /* TODO - number of cycles unknown */
594 }
595 
596 /* Unlock the cache line containing the given address.
597    Returns the number of cycles required to unlock the line.  */
598 int
599 frv_cache_unlock (FRV_CACHE *cache, SI address)
600 {
601   FRV_CACHE_TAG *tag;
602   int found;
603 
604   if (non_cache_access (cache, address))
605     return 1;
606 
607   found = get_tag (cache, address, &tag);
608 
609   if (found)
610     tag->locked = 0;
611 
612   return 1; /* TODO - number of cycles unknown */
613 }
614 
615 static void
616 invalidate_return_buffer (FRV_CACHE *cache, SI address)
617 {
618   /* If this address is in one of the return buffers, then invalidate that
619      return buffer.  */
620   address &= ~(cache->line_size - 1);
621   if (address == cache->pipeline[LS].status.return_buffer.address)
622     cache->pipeline[LS].status.return_buffer.valid = 0;
623   if (address == cache->pipeline[LD].status.return_buffer.address)
624     cache->pipeline[LD].status.return_buffer.valid = 0;
625 }
626 
627 /* Invalidate the cache line containing the given address. Flush the
628    data if requested.
629    Returns the number of cycles required to write the data.  */
630 int
631 frv_cache_invalidate (FRV_CACHE *cache, SI address, int flush)
632 {
633   /* See if this data is already in the cache.  */
634   FRV_CACHE_TAG *tag;
635   int found;
636 
637   /* Check for non-cache access.  This operation is still perfromed even if
638      the cache is not currently enabled.  */
639   if (non_cache_access (cache, address))
640     return 1;
641 
642   /* If the line is found, invalidate it. If a flush is requested, then flush
643      it if it is dirty.  */
644   found = get_tag (cache, address, &tag);
645   if (found)
646     {
647       SIM_CPU *cpu;
648       /* If a flush is requested, then flush it if it is dirty.  */
649       if (tag->dirty && flush)
650 	write_line_to_memory (cache, tag);
651       set_least_recently_used (cache, tag);
652       tag->valid = 0;
653       tag->locked = 0;
654 
655       /* If this is the insn cache, then flush the cpu's scache as well.  */
656       cpu = cache->cpu;
657       if (cache == CPU_INSN_CACHE (cpu))
658 	scache_flush_cpu (cpu);
659     }
660 
661   invalidate_return_buffer (cache, address);
662 
663   return 1; /* TODO - number of cycles unknown */
664 }
665 
666 /* Invalidate the entire cache. Flush the data if requested.  */
667 int
668 frv_cache_invalidate_all (FRV_CACHE *cache, int flush)
669 {
670   /* See if this data is already in the cache.  */
671   int elements = cache->sets * cache->ways;
672   FRV_CACHE_TAG *tag = cache->tag_storage;
673   SIM_CPU *cpu;
674   int i;
675 
676   for(i = 0; i < elements; ++i, ++tag)
677     {
678       /* If a flush is requested, then flush it if it is dirty.  */
679       if (tag->valid && tag->dirty && flush)
680 	write_line_to_memory (cache, tag);
681       tag->valid = 0;
682       tag->locked = 0;
683     }
684 
685 
686   /* If this is the insn cache, then flush the cpu's scache as well.  */
687   cpu = cache->cpu;
688   if (cache == CPU_INSN_CACHE (cpu))
689     scache_flush_cpu (cpu);
690 
691   /* Invalidate both return buffers.  */
692   cache->pipeline[LS].status.return_buffer.valid = 0;
693   cache->pipeline[LD].status.return_buffer.valid = 0;
694 
695   return 1; /* TODO - number of cycles unknown */
696 }
697 
698 /* ---------------------------------------------------------------------------
699    Functions for operating the cache in cycle accurate mode.
700    -------------------------------------------------------------------------  */
701 /* Convert a VLIW slot to a cache pipeline index.  */
702 static int
703 convert_slot_to_index (int slot)
704 {
705   switch (slot)
706     {
707     case UNIT_I0:
708     case UNIT_C:
709       return LS;
710     case UNIT_I1:
711       return LD;
712     default:
713       abort ();
714     }
715   return 0;
716 }
717 
718 /* Allocate free chains of cache requests.  */
719 #define FREE_CHAIN_SIZE 16
720 static FRV_CACHE_REQUEST *frv_cache_request_free_chain = NULL;
721 static FRV_CACHE_REQUEST *frv_store_request_free_chain = NULL;
722 
723 static void
724 allocate_new_cache_requests (void)
725 {
726   int i;
727   frv_cache_request_free_chain = xmalloc (FREE_CHAIN_SIZE
728 					  * sizeof (FRV_CACHE_REQUEST));
729   for (i = 0; i < FREE_CHAIN_SIZE - 1; ++i)
730     {
731       frv_cache_request_free_chain[i].next
732 	= & frv_cache_request_free_chain[i + 1];
733     }
734 
735   frv_cache_request_free_chain[FREE_CHAIN_SIZE - 1].next = NULL;
736 }
737 
738 /* Return the next free request in the queue for the given cache pipeline.  */
739 static FRV_CACHE_REQUEST *
740 new_cache_request (void)
741 {
742   FRV_CACHE_REQUEST *req;
743 
744   /* Allocate new elements for the free chain if necessary.  */
745   if (frv_cache_request_free_chain == NULL)
746     allocate_new_cache_requests ();
747 
748   req = frv_cache_request_free_chain;
749   frv_cache_request_free_chain = req->next;
750 
751   return req;
752 }
753 
754 /* Return the given cache request to the free chain.  */
755 static void
756 free_cache_request (FRV_CACHE_REQUEST *req)
757 {
758   if (req->kind == req_store)
759     {
760       req->next = frv_store_request_free_chain;
761       frv_store_request_free_chain = req;
762     }
763   else
764     {
765       req->next = frv_cache_request_free_chain;
766       frv_cache_request_free_chain = req;
767     }
768 }
769 
770 /* Search the free chain for an existing store request with a buffer that's
771    large enough.  */
772 static FRV_CACHE_REQUEST *
773 new_store_request (int length)
774 {
775   FRV_CACHE_REQUEST *prev = NULL;
776   FRV_CACHE_REQUEST *req;
777   for (req = frv_store_request_free_chain; req != NULL; req = req->next)
778     {
779       if (req->u.store.length == length)
780 	break;
781       prev = req;
782     }
783   if (req != NULL)
784     {
785       if (prev == NULL)
786 	frv_store_request_free_chain = req->next;
787       else
788 	prev->next = req->next;
789       return req;
790     }
791 
792   /* No existing request buffer was found, so make a new one.  */
793   req = new_cache_request ();
794   req->kind = req_store;
795   req->u.store.data = xmalloc (length);
796   req->u.store.length = length;
797   return req;
798 }
799 
800 /* Remove the given request from the given pipeline.  */
801 static void
802 pipeline_remove_request (FRV_CACHE_PIPELINE *p, FRV_CACHE_REQUEST *request)
803 {
804   FRV_CACHE_REQUEST *next = request->next;
805   FRV_CACHE_REQUEST *prev = request->prev;
806 
807   if (prev == NULL)
808     p->requests = next;
809   else
810     prev->next = next;
811 
812   if (next != NULL)
813     next->prev = prev;
814 }
815 
816 /* Add the given request to the given pipeline.  */
817 static void
818 pipeline_add_request (FRV_CACHE_PIPELINE *p, FRV_CACHE_REQUEST *request)
819 {
820   FRV_CACHE_REQUEST *prev = NULL;
821   FRV_CACHE_REQUEST *item;
822 
823   /* Add the request in priority order.  0 is the highest priority.  */
824   for (item = p->requests; item != NULL; item = item->next)
825     {
826       if (item->priority > request->priority)
827 	break;
828       prev = item;
829     }
830 
831   request->next = item;
832   request->prev = prev;
833   if (prev == NULL)
834     p->requests = request;
835   else
836     prev->next = request;
837   if (item != NULL)
838     item->prev = request;
839 }
840 
841 /* Requeu the given request from the last of the given pipeline.  */
842 static void
843 pipeline_requeue_request (FRV_CACHE_PIPELINE *p)
844 {
845   FRV_CACHE_STAGE *stage = & p->stages[LAST_STAGE];
846   FRV_CACHE_REQUEST *req = stage->request;
847   stage->request = NULL;
848   pipeline_add_request (p, req);
849 }
850 
851 /* Return the priority lower than the lowest one in this cache pipeline.
852    0 is the highest priority.  */
853 static int
854 next_priority (FRV_CACHE *cache, FRV_CACHE_PIPELINE *pipeline)
855 {
856   int i, j;
857   int pipe;
858   int lowest = 0;
859   FRV_CACHE_REQUEST *req;
860 
861   /* Check the priorities of any queued items.  */
862   for (req = pipeline->requests; req != NULL; req = req->next)
863     if (req->priority > lowest)
864       lowest = req->priority;
865 
866   /* Check the priorities of items in the pipeline stages.  */
867   for (i = FIRST_STAGE; i < FRV_CACHE_STAGES; ++i)
868     {
869       FRV_CACHE_STAGE *stage = & pipeline->stages[i];
870       if (stage->request != NULL && stage->request->priority > lowest)
871         lowest = stage->request->priority;
872     }
873 
874   /* Check the priorities of load requests waiting in WAR.  These are one
875      higher than the request that spawned them.  */
876   for (i = 0; i < NUM_WARS; ++i)
877     {
878       FRV_CACHE_WAR *war = & pipeline->WAR[i];
879       if (war->valid && war->priority > lowest)
880 	lowest = war->priority + 1;
881     }
882 
883   /* Check the priorities of any BARS or NARS associated with this pipeline.
884      These are one higher than the request that spawned them.  */
885   pipe = pipeline - cache->pipeline;
886   if (cache->BARS.valid && cache->BARS.pipe == pipe
887       && cache->BARS.priority > lowest)
888     lowest = cache->BARS.priority + 1;
889   if (cache->NARS.valid && cache->NARS.pipe == pipe
890       && cache->NARS.priority > lowest)
891     lowest = cache->NARS.priority + 1;
892 
893   /* Return a priority 2 lower than the lowest found.  This allows a WAR
894      request to be generated with a priority greater than this but less than
895      the next higher priority request.  */
896   return lowest + 2;
897 }
898 
899 static void
900 add_WAR_request (FRV_CACHE_PIPELINE* pipeline, FRV_CACHE_WAR *war)
901 {
902   /* Add the load request to the indexed pipeline.  */
903   FRV_CACHE_REQUEST *req = new_cache_request ();
904   req->kind = req_WAR;
905   req->reqno = war->reqno;
906   req->priority = war->priority;
907   req->address = war->address;
908   req->u.WAR.preload = war->preload;
909   req->u.WAR.lock = war->lock;
910   pipeline_add_request (pipeline, req);
911 }
912 
913 /* Remove the next request from the given pipeline and return it.  */
914 static FRV_CACHE_REQUEST *
915 pipeline_next_request (FRV_CACHE_PIPELINE *p)
916 {
917   FRV_CACHE_REQUEST *first = p->requests;
918   if (first != NULL)
919     pipeline_remove_request (p, first);
920   return first;
921 }
922 
923 /* Return the request which is at the given stage of the given pipeline.  */
924 static FRV_CACHE_REQUEST *
925 pipeline_stage_request (FRV_CACHE_PIPELINE *p, int stage)
926 {
927   return p->stages[stage].request;
928 }
929 
930 static void
931 advance_pipelines (FRV_CACHE *cache)
932 {
933   int stage;
934   int pipe;
935   FRV_CACHE_PIPELINE *pipelines = cache->pipeline;
936 
937   /* Free the final stage requests.  */
938   for (pipe = 0; pipe < FRV_CACHE_PIPELINES; ++pipe)
939     {
940       FRV_CACHE_REQUEST *req = pipelines[pipe].stages[LAST_STAGE].request;
941       if (req != NULL)
942 	free_cache_request (req);
943     }
944 
945   /* Shuffle the requests along the pipeline.  */
946   for (stage = LAST_STAGE; stage > FIRST_STAGE; --stage)
947     {
948       for (pipe = 0; pipe < FRV_CACHE_PIPELINES; ++pipe)
949 	pipelines[pipe].stages[stage] = pipelines[pipe].stages[stage - 1];
950     }
951 
952   /* Add a new request to the pipeline.  */
953   for (pipe = 0; pipe < FRV_CACHE_PIPELINES; ++pipe)
954     pipelines[pipe].stages[FIRST_STAGE].request
955       = pipeline_next_request (& pipelines[pipe]);
956 }
957 
958 /* Handle a request for a load from the given address.  */
959 void
960 frv_cache_request_load (FRV_CACHE *cache, unsigned reqno, SI address, int slot)
961 {
962   FRV_CACHE_REQUEST *req;
963 
964   /* slot is a UNIT_*.  Convert it to a cache pipeline index.  */
965   int pipe = convert_slot_to_index (slot);
966   FRV_CACHE_PIPELINE *pipeline = & cache->pipeline[pipe];
967 
968   /* Add the load request to the indexed pipeline.  */
969   req = new_cache_request ();
970   req->kind = req_load;
971   req->reqno = reqno;
972   req->priority = next_priority (cache, pipeline);
973   req->address = address;
974 
975   pipeline_add_request (pipeline, req);
976 }
977 
978 void
979 frv_cache_request_store (FRV_CACHE *cache, SI address,
980 			 int slot, char *data, unsigned length)
981 {
982   FRV_CACHE_REQUEST *req;
983 
984   /* slot is a UNIT_*.  Convert it to a cache pipeline index.  */
985   int pipe = convert_slot_to_index (slot);
986   FRV_CACHE_PIPELINE *pipeline = & cache->pipeline[pipe];
987 
988   /* Add the load request to the indexed pipeline.  */
989   req = new_store_request (length);
990   req->kind = req_store;
991   req->reqno = NO_REQNO;
992   req->priority = next_priority (cache, pipeline);
993   req->address = address;
994   req->u.store.length = length;
995   memcpy (req->u.store.data, data, length);
996 
997   pipeline_add_request (pipeline, req);
998   invalidate_return_buffer (cache, address);
999 }
1000 
1001 /* Handle a request to invalidate the cache line containing the given address.
1002    Flush the data if requested.  */
1003 void
1004 frv_cache_request_invalidate (FRV_CACHE *cache, unsigned reqno, SI address,
1005 			      int slot, int all, int flush)
1006 {
1007   FRV_CACHE_REQUEST *req;
1008 
1009   /* slot is a UNIT_*.  Convert it to a cache pipeline index.  */
1010   int pipe = convert_slot_to_index (slot);
1011   FRV_CACHE_PIPELINE *pipeline = & cache->pipeline[pipe];
1012 
1013   /* Add the load request to the indexed pipeline.  */
1014   req = new_cache_request ();
1015   req->kind = req_invalidate;
1016   req->reqno = reqno;
1017   req->priority = next_priority (cache, pipeline);
1018   req->address = address;
1019   req->u.invalidate.all = all;
1020   req->u.invalidate.flush = flush;
1021 
1022   pipeline_add_request (pipeline, req);
1023 }
1024 
1025 /* Handle a request to preload the cache line containing the given address.  */
1026 void
1027 frv_cache_request_preload (FRV_CACHE *cache, SI address,
1028 			   int slot, int length, int lock)
1029 {
1030   FRV_CACHE_REQUEST *req;
1031 
1032   /* slot is a UNIT_*.  Convert it to a cache pipeline index.  */
1033   int pipe = convert_slot_to_index (slot);
1034   FRV_CACHE_PIPELINE *pipeline = & cache->pipeline[pipe];
1035 
1036   /* Add the load request to the indexed pipeline.  */
1037   req = new_cache_request ();
1038   req->kind = req_preload;
1039   req->reqno = NO_REQNO;
1040   req->priority = next_priority (cache, pipeline);
1041   req->address = address;
1042   req->u.preload.length = length;
1043   req->u.preload.lock = lock;
1044 
1045   pipeline_add_request (pipeline, req);
1046   invalidate_return_buffer (cache, address);
1047 }
1048 
1049 /* Handle a request to unlock the cache line containing the given address.  */
1050 void
1051 frv_cache_request_unlock (FRV_CACHE *cache, SI address, int slot)
1052 {
1053   FRV_CACHE_REQUEST *req;
1054 
1055   /* slot is a UNIT_*.  Convert it to a cache pipeline index.  */
1056   int pipe = convert_slot_to_index (slot);
1057   FRV_CACHE_PIPELINE *pipeline = & cache->pipeline[pipe];
1058 
1059   /* Add the load request to the indexed pipeline.  */
1060   req = new_cache_request ();
1061   req->kind = req_unlock;
1062   req->reqno = NO_REQNO;
1063   req->priority = next_priority (cache, pipeline);
1064   req->address = address;
1065 
1066   pipeline_add_request (pipeline, req);
1067 }
1068 
1069 /* Check whether this address interferes with a pending request of
1070    higher priority.  */
1071 static int
1072 address_interference (FRV_CACHE *cache, SI address, FRV_CACHE_REQUEST *req,
1073 		      int pipe)
1074 {
1075   int i, j;
1076   int line_mask = ~(cache->line_size - 1);
1077   int other_pipe;
1078   int priority = req->priority;
1079   FRV_CACHE_REQUEST *other_req;
1080   SI other_address;
1081   SI all_address;
1082 
1083   address &= line_mask;
1084   all_address = -1 & line_mask;
1085 
1086   /* Check for collisions in the queue for this pipeline.  */
1087   for (other_req = cache->pipeline[pipe].requests;
1088        other_req != NULL;
1089        other_req = other_req->next)
1090     {
1091       other_address = other_req->address & line_mask;
1092       if ((address == other_address || address == all_address)
1093 	  && priority > other_req->priority)
1094 	return 1;
1095     }
1096 
1097   /* Check for a collision in the the other pipeline.  */
1098   other_pipe = pipe ^ 1;
1099   other_req = cache->pipeline[other_pipe].stages[LAST_STAGE].request;
1100   if (other_req != NULL)
1101     {
1102       other_address = other_req->address & line_mask;
1103       if (address == other_address || address == all_address)
1104 	return 1;
1105     }
1106 
1107   /* Check for a collision with load requests waiting in WAR.  */
1108   for (i = LS; i < FRV_CACHE_PIPELINES; ++i)
1109     {
1110       for (j = 0; j < NUM_WARS; ++j)
1111 	{
1112 	  FRV_CACHE_WAR *war = & cache->pipeline[i].WAR[j];
1113 	  if (war->valid
1114 	      && (address == (war->address & line_mask)
1115 		  || address == all_address)
1116 	      && priority > war->priority)
1117 	    return 1;
1118 	}
1119       /* If this is not a WAR request, then yield to any WAR requests in
1120 	 either pipeline or to a higher priority request in the same pipeline.
1121       */
1122       if (req->kind != req_WAR)
1123 	{
1124 	  for (j = FIRST_STAGE; j < FRV_CACHE_STAGES; ++j)
1125 	    {
1126 	      other_req = cache->pipeline[i].stages[j].request;
1127 	      if (other_req != NULL)
1128 		{
1129 		  if (other_req->kind == req_WAR)
1130 		    return 1;
1131 		  if (i == pipe
1132 		      && (address == (other_req->address & line_mask)
1133 			  || address == all_address)
1134 		      && priority > other_req->priority)
1135 		    return 1;
1136 		}
1137 	    }
1138 	}
1139     }
1140 
1141   /* Check for a collision with load requests waiting in ARS.  */
1142   if (cache->BARS.valid
1143       && (address == (cache->BARS.address & line_mask)
1144 	  || address == all_address)
1145       && priority > cache->BARS.priority)
1146     return 1;
1147   if (cache->NARS.valid
1148       && (address == (cache->NARS.address & line_mask)
1149 	  || address == all_address)
1150       && priority > cache->NARS.priority)
1151     return 1;
1152 
1153   return 0;
1154 }
1155 
1156 /* Wait for a free WAR register in BARS or NARS.  */
1157 static void
1158 wait_for_WAR (FRV_CACHE* cache, int pipe, FRV_CACHE_REQUEST *req)
1159 {
1160   FRV_CACHE_WAR war;
1161   FRV_CACHE_PIPELINE *pipeline = & cache->pipeline[pipe];
1162 
1163   if (! cache->BARS.valid)
1164     {
1165       cache->BARS.pipe = pipe;
1166       cache->BARS.reqno = req->reqno;
1167       cache->BARS.address = req->address;
1168       cache->BARS.priority = req->priority - 1;
1169       switch (req->kind)
1170 	{
1171 	case req_load:
1172 	  cache->BARS.preload = 0;
1173 	  cache->BARS.lock = 0;
1174 	  break;
1175 	case req_store:
1176 	  cache->BARS.preload = 1;
1177 	  cache->BARS.lock = 0;
1178 	  break;
1179 	case req_preload:
1180 	  cache->BARS.preload = 1;
1181 	  cache->BARS.lock = req->u.preload.lock;
1182 	  break;
1183 	}
1184       cache->BARS.valid = 1;
1185       return;
1186     }
1187   if (! cache->NARS.valid)
1188     {
1189       cache->NARS.pipe = pipe;
1190       cache->NARS.reqno = req->reqno;
1191       cache->NARS.address = req->address;
1192       cache->NARS.priority = req->priority - 1;
1193       switch (req->kind)
1194 	{
1195 	case req_load:
1196 	  cache->NARS.preload = 0;
1197 	  cache->NARS.lock = 0;
1198 	  break;
1199 	case req_store:
1200 	  cache->NARS.preload = 1;
1201 	  cache->NARS.lock = 0;
1202 	  break;
1203 	case req_preload:
1204 	  cache->NARS.preload = 1;
1205 	  cache->NARS.lock = req->u.preload.lock;
1206 	  break;
1207 	}
1208       cache->NARS.valid = 1;
1209       return;
1210     }
1211   /* All wait registers are busy, so resubmit this request.  */
1212   pipeline_requeue_request (pipeline);
1213 }
1214 
1215 /* Find a free WAR register and wait for memory to fetch the data.  */
1216 static void
1217 wait_in_WAR (FRV_CACHE* cache, int pipe, FRV_CACHE_REQUEST *req)
1218 {
1219   int war;
1220   FRV_CACHE_PIPELINE *pipeline = & cache->pipeline[pipe];
1221 
1222   /* Find a valid WAR to  hold this request.  */
1223   for (war = 0; war < NUM_WARS; ++war)
1224     if (! pipeline->WAR[war].valid)
1225       break;
1226   if (war >= NUM_WARS)
1227     {
1228       wait_for_WAR (cache, pipe, req);
1229       return;
1230     }
1231 
1232   pipeline->WAR[war].address = req->address;
1233   pipeline->WAR[war].reqno = req->reqno;
1234   pipeline->WAR[war].priority = req->priority - 1;
1235   pipeline->WAR[war].latency = cache->memory_latency + 1;
1236   switch (req->kind)
1237     {
1238     case req_load:
1239       pipeline->WAR[war].preload = 0;
1240       pipeline->WAR[war].lock = 0;
1241       break;
1242     case req_store:
1243       pipeline->WAR[war].preload = 1;
1244       pipeline->WAR[war].lock = 0;
1245       break;
1246     case req_preload:
1247       pipeline->WAR[war].preload = 1;
1248       pipeline->WAR[war].lock = req->u.preload.lock;
1249       break;
1250     }
1251   pipeline->WAR[war].valid = 1;
1252 }
1253 
1254 static void
1255 handle_req_load (FRV_CACHE *cache, int pipe, FRV_CACHE_REQUEST *req)
1256 {
1257   FRV_CACHE_TAG *tag;
1258   SI address = req->address;
1259 
1260   /* If this address interferes with an existing request, then requeue it.  */
1261   if (address_interference (cache, address, req, pipe))
1262     {
1263       pipeline_requeue_request (& cache->pipeline[pipe]);
1264       return;
1265     }
1266 
1267   if (frv_cache_enabled (cache) && ! non_cache_access (cache, address))
1268     {
1269       int found = get_tag (cache, address, &tag);
1270 
1271       /* If the data was found, return it to the caller.  */
1272       if (found)
1273 	{
1274 	  set_most_recently_used (cache, tag);
1275 	  copy_line_to_return_buffer (cache, pipe, tag, address);
1276 	  set_return_buffer_reqno (cache, pipe, req->reqno);
1277 	  return;
1278 	}
1279     }
1280 
1281   /* The data is not in the cache or this is a non-cache access.  We need to
1282      wait for the memory unit to fetch it.  Store this request in the WAR in
1283      the meantime.  */
1284   wait_in_WAR (cache, pipe, req);
1285 }
1286 
1287 static void
1288 handle_req_preload (FRV_CACHE *cache, int pipe, FRV_CACHE_REQUEST *req)
1289 {
1290   int found;
1291   FRV_CACHE_WAR war;
1292   FRV_CACHE_TAG *tag;
1293   int length;
1294   int lock;
1295   int offset;
1296   int lines;
1297   int line;
1298   SI address = req->address;
1299   SI cur_address;
1300 
1301   if (! frv_cache_enabled (cache) || non_cache_access (cache, address))
1302     return;
1303 
1304   /* preload at least 1 line.  */
1305   length = req->u.preload.length;
1306   if (length == 0)
1307     length = 1;
1308 
1309   /* Make sure that this request does not interfere with a pending request.  */
1310   offset = address & (cache->line_size - 1);
1311   lines = 1 + (offset + length - 1) / cache->line_size;
1312   cur_address = address & ~(cache->line_size - 1);
1313   for (line = 0; line < lines; ++line)
1314     {
1315       /* If this address interferes with an existing request,
1316 	 then requeue it.  */
1317       if (address_interference (cache, cur_address, req, pipe))
1318 	{
1319 	  pipeline_requeue_request (& cache->pipeline[pipe]);
1320 	  return;
1321 	}
1322       cur_address += cache->line_size;
1323     }
1324 
1325   /* Now process each cache line.  */
1326   /* Careful with this loop -- length is unsigned.  */
1327   lock = req->u.preload.lock;
1328   cur_address = address & ~(cache->line_size - 1);
1329   for (line = 0; line < lines; ++line)
1330     {
1331       /* If the data was found, then lock it if requested.  */
1332       found = get_tag (cache, cur_address, &tag);
1333       if (found)
1334 	{
1335 	  if (lock)
1336 	    tag->locked = 1;
1337 	}
1338       else
1339 	{
1340 	  /* The data is not in the cache.  We need to wait for the memory
1341 	     unit to fetch it.  Store this request in the WAR in the meantime.
1342 	  */
1343 	  wait_in_WAR (cache, pipe, req);
1344 	}
1345       cur_address += cache->line_size;
1346     }
1347 }
1348 
1349 static void
1350 handle_req_store (FRV_CACHE *cache, int pipe, FRV_CACHE_REQUEST *req)
1351 {
1352   SIM_CPU *current_cpu;
1353   FRV_CACHE_TAG *tag;
1354   int found;
1355   int copy_back;
1356   SI address = req->address;
1357   char *data = req->u.store.data;
1358   int length = req->u.store.length;
1359 
1360   /* If this address interferes with an existing request, then requeue it.  */
1361   if (address_interference (cache, address, req, pipe))
1362     {
1363       pipeline_requeue_request (& cache->pipeline[pipe]);
1364       return;
1365     }
1366 
1367   /* Non-cache access. Write the data directly to memory.  */
1368   if (! frv_cache_enabled (cache) || non_cache_access (cache, address))
1369     {
1370       write_data_to_memory (cache, address, data, length);
1371       return;
1372     }
1373 
1374   /* See if the data is in the cache.  */
1375   found = get_tag (cache, address, &tag);
1376 
1377   /* Write the data to the cache line if one was available and if it is
1378      either a hit or a miss in copy-back mode.
1379      The tag may be NULL if all ways were in use and locked on a miss.
1380   */
1381   current_cpu = cache->cpu;
1382   copy_back = GET_HSR0_CBM (GET_HSR0 ());
1383   if (tag != NULL && (found || copy_back))
1384     {
1385       int line_offset;
1386       /* Load the line from memory first, if it was a miss.  */
1387       if (! found)
1388 	{
1389 	  /* We need to wait for the memory unit to fetch the data.
1390 	     Store this request in the WAR and requeue the store request.  */
1391 	  wait_in_WAR (cache, pipe, req);
1392 	  pipeline_requeue_request (& cache->pipeline[pipe]);
1393 	  /* Decrement the counts of accesses and hits because when the requeued
1394 	     request is processed again, it will appear to be a new access and
1395 	     a hit.  */
1396 	  --cache->statistics.accesses;
1397 	  --cache->statistics.hits;
1398 	  return;
1399 	}
1400       line_offset = address & (cache->line_size - 1);
1401       memcpy (tag->line + line_offset, data, length);
1402       invalidate_return_buffer (cache, address);
1403       tag->dirty = 1;
1404 
1405       /* Update the LRU information for the tags in this set.  */
1406       set_most_recently_used (cache, tag);
1407     }
1408 
1409   /* Write the data to memory if there was no line available or we are in
1410      write-through (not copy-back mode).  */
1411   if (tag == NULL || ! copy_back)
1412     {
1413       write_data_to_memory (cache, address, data, length);
1414       if (tag != NULL)
1415 	tag->dirty = 0;
1416     }
1417 }
1418 
1419 static void
1420 handle_req_invalidate (FRV_CACHE *cache, int pipe, FRV_CACHE_REQUEST *req)
1421 {
1422   FRV_CACHE_PIPELINE *pipeline = & cache->pipeline[pipe];
1423   SI address = req->address;
1424   SI interfere_address = req->u.invalidate.all ? -1 : address;
1425 
1426   /* If this address interferes with an existing request, then requeue it.  */
1427   if (address_interference (cache, interfere_address, req, pipe))
1428     {
1429       pipeline_requeue_request (pipeline);
1430       return;
1431     }
1432 
1433   /* Invalidate the cache line now.  This function already checks for
1434      non-cache access.  */
1435   if (req->u.invalidate.all)
1436     frv_cache_invalidate_all (cache, req->u.invalidate.flush);
1437   else
1438     frv_cache_invalidate (cache, address, req->u.invalidate.flush);
1439   if (req->u.invalidate.flush)
1440     {
1441       pipeline->status.flush.reqno = req->reqno;
1442       pipeline->status.flush.address = address;
1443       pipeline->status.flush.valid = 1;
1444     }
1445 }
1446 
1447 static void
1448 handle_req_unlock (FRV_CACHE *cache, int pipe, FRV_CACHE_REQUEST *req)
1449 {
1450   FRV_CACHE_PIPELINE *pipeline = & cache->pipeline[pipe];
1451   SI address = req->address;
1452 
1453   /* If this address interferes with an existing request, then requeue it.  */
1454   if (address_interference (cache, address, req, pipe))
1455     {
1456       pipeline_requeue_request (pipeline);
1457       return;
1458     }
1459 
1460   /* Unlock the cache line.  This function checks for non-cache access.  */
1461   frv_cache_unlock (cache, address);
1462 }
1463 
1464 static void
1465 handle_req_WAR (FRV_CACHE *cache, int pipe, FRV_CACHE_REQUEST *req)
1466 {
1467   char *buffer;
1468   FRV_CACHE_TAG *tag;
1469   SI address = req->address;
1470 
1471   if (frv_cache_enabled (cache) && ! non_cache_access (cache, address))
1472     {
1473       /* Look for the data in the cache.  The statistics of cache hit or
1474 	 miss have already been recorded, so save and restore the stats before
1475 	 and after obtaining the cache line.  */
1476       FRV_CACHE_STATISTICS save_stats = cache->statistics;
1477       tag = find_or_retrieve_cache_line (cache, address);
1478       cache->statistics = save_stats;
1479       if (tag != NULL)
1480 	{
1481 	  if (! req->u.WAR.preload)
1482 	    {
1483 	      copy_line_to_return_buffer (cache, pipe, tag, address);
1484 	      set_return_buffer_reqno (cache, pipe, req->reqno);
1485 	    }
1486 	  else
1487 	    {
1488 	      invalidate_return_buffer (cache, address);
1489 	      if (req->u.WAR.lock)
1490 		tag->locked = 1;
1491 	    }
1492 	  return;
1493 	}
1494     }
1495 
1496   /* All cache lines in the set were locked, so just copy the data to the
1497      return buffer directly.  */
1498   if (! req->u.WAR.preload)
1499     {
1500       copy_memory_to_return_buffer (cache, pipe, address);
1501       set_return_buffer_reqno (cache, pipe, req->reqno);
1502     }
1503 }
1504 
1505 /* Resolve any conflicts and/or execute the given requests.  */
1506 static void
1507 arbitrate_requests (FRV_CACHE *cache)
1508 {
1509   int pipe;
1510   /* Simply execute the requests in the final pipeline stages.  */
1511   for (pipe = LS; pipe < FRV_CACHE_PIPELINES; ++pipe)
1512     {
1513       FRV_CACHE_REQUEST *req
1514 	= pipeline_stage_request (& cache->pipeline[pipe], LAST_STAGE);
1515       /* Make sure that there is a request to handle.  */
1516       if (req == NULL)
1517 	continue;
1518 
1519       /* Handle the request.  */
1520       switch (req->kind)
1521 	{
1522 	case req_load:
1523 	  handle_req_load (cache, pipe, req);
1524 	  break;
1525 	case req_store:
1526 	  handle_req_store (cache, pipe, req);
1527 	  break;
1528 	case req_invalidate:
1529 	  handle_req_invalidate (cache, pipe, req);
1530 	  break;
1531 	case req_preload:
1532 	  handle_req_preload (cache, pipe, req);
1533 	  break;
1534 	case req_unlock:
1535 	  handle_req_unlock (cache, pipe, req);
1536 	  break;
1537 	case req_WAR:
1538 	  handle_req_WAR (cache, pipe, req);
1539 	  break;
1540 	default:
1541 	  abort ();
1542 	}
1543     }
1544 }
1545 
1546 /* Move a waiting ARS register to a free WAR register.  */
1547 static void
1548 move_ARS_to_WAR (FRV_CACHE *cache, int pipe, FRV_CACHE_WAR *war)
1549 {
1550   /* If BARS is valid for this pipe, then move it to the given WAR. Move
1551      NARS to BARS if it is valid.  */
1552   if (cache->BARS.valid && cache->BARS.pipe == pipe)
1553     {
1554       war->address = cache->BARS.address;
1555       war->reqno = cache->BARS.reqno;
1556       war->priority = cache->BARS.priority;
1557       war->preload = cache->BARS.preload;
1558       war->lock = cache->BARS.lock;
1559       war->latency = cache->memory_latency + 1;
1560       war->valid = 1;
1561       if (cache->NARS.valid)
1562 	{
1563 	  cache->BARS = cache->NARS;
1564 	  cache->NARS.valid = 0;
1565 	}
1566       else
1567 	cache->BARS.valid = 0;
1568       return;
1569     }
1570   /* If NARS is valid for this pipe, then move it to the given WAR.  */
1571   if (cache->NARS.valid && cache->NARS.pipe == pipe)
1572     {
1573       war->address = cache->NARS.address;
1574       war->reqno = cache->NARS.reqno;
1575       war->priority = cache->NARS.priority;
1576       war->preload = cache->NARS.preload;
1577       war->lock = cache->NARS.lock;
1578       war->latency = cache->memory_latency + 1;
1579       war->valid = 1;
1580       cache->NARS.valid = 0;
1581     }
1582 }
1583 
1584 /* Decrease the latencies of the various states in the cache.  */
1585 static void
1586 decrease_latencies (FRV_CACHE *cache)
1587 {
1588   int pipe, j;
1589   /* Check the WAR registers.  */
1590   for (pipe = LS; pipe < FRV_CACHE_PIPELINES; ++pipe)
1591     {
1592       FRV_CACHE_PIPELINE *pipeline = & cache->pipeline[pipe];
1593       for (j = 0; j < NUM_WARS; ++j)
1594 	{
1595 	  FRV_CACHE_WAR *war = & pipeline->WAR[j];
1596 	  if (war->valid)
1597 	    {
1598 	      --war->latency;
1599 	      /* If the latency has expired, then submit a WAR request to the
1600 		 pipeline.  */
1601 	      if (war->latency <= 0)
1602 		{
1603 		  add_WAR_request (pipeline, war);
1604 		  war->valid = 0;
1605 		  move_ARS_to_WAR (cache, pipe, war);
1606 		}
1607 	    }
1608 	}
1609     }
1610 }
1611 
1612 /* Run the cache for the given number of cycles.  */
1613 void
1614 frv_cache_run (FRV_CACHE *cache, int cycles)
1615 {
1616   int i;
1617   for (i = 0; i < cycles; ++i)
1618     {
1619       advance_pipelines (cache);
1620       arbitrate_requests (cache);
1621       decrease_latencies (cache);
1622     }
1623 }
1624 
1625 int
1626 frv_cache_read_passive_SI (FRV_CACHE *cache, SI address, SI *value)
1627 {
1628   SI offset;
1629   FRV_CACHE_TAG *tag;
1630 
1631   if (non_cache_access (cache, address))
1632     return 0;
1633 
1634   {
1635     FRV_CACHE_STATISTICS save_stats = cache->statistics;
1636     int found = get_tag (cache, address, &tag);
1637     cache->statistics = save_stats;
1638 
1639     if (! found)
1640       return 0; /* Indicate non-cache-access.  */
1641   }
1642 
1643   /* A cache line was available for the data.
1644      Extract the target data from the line.  */
1645   offset = address & (cache->line_size - 1);
1646   *value = T2H_4 (*(SI *)(tag->line + offset));
1647   return 1;
1648 }
1649 
1650 /* Check the return buffers of the data cache to see if the requested data is
1651    available.  */
1652 int
1653 frv_cache_data_in_buffer (FRV_CACHE* cache, int pipe, SI address,
1654 			  unsigned reqno)
1655 {
1656   return cache->pipeline[pipe].status.return_buffer.valid
1657     && cache->pipeline[pipe].status.return_buffer.reqno == reqno
1658     && cache->pipeline[pipe].status.return_buffer.address <= address
1659     && cache->pipeline[pipe].status.return_buffer.address + cache->line_size
1660        > address;
1661 }
1662 
1663 /* Check to see if the requested data has been flushed.  */
1664 int
1665 frv_cache_data_flushed (FRV_CACHE* cache, int pipe, SI address, unsigned reqno)
1666 {
1667   return cache->pipeline[pipe].status.flush.valid
1668     && cache->pipeline[pipe].status.flush.reqno == reqno
1669     && cache->pipeline[pipe].status.flush.address <= address
1670     && cache->pipeline[pipe].status.flush.address + cache->line_size
1671        > address;
1672 }
1673