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