1/* frv simulator machine independent profiling code.
2
3   Copyright (C) 1998, 1999, 2000, 2001, 2003, 2007
4   Free Software Foundation, Inc.
5   Contributed by Red Hat
6
7This file is part of the GNU simulators.
8
9This program is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 3 of the License, or
12(at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22*/
23#define WANT_CPU
24#define WANT_CPU_FRVBF
25
26#include "sim-main.h"
27#include "bfd.h"
28
29#if WITH_PROFILE_MODEL_P
30
31#include "profile.h"
32#include "profile-fr400.h"
33#include "profile-fr500.h"
34#include "profile-fr550.h"
35
36static void
37reset_gr_flags (SIM_CPU *cpu, INT gr)
38{
39  SIM_DESC sd = CPU_STATE (cpu);
40  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400
41      || STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450)
42    fr400_reset_gr_flags (cpu, gr);
43  /* Other machines have no gr flags right now.  */
44}
45
46static void
47reset_fr_flags (SIM_CPU *cpu, INT fr)
48{
49  SIM_DESC sd = CPU_STATE (cpu);
50  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400
51      || STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450)
52    fr400_reset_fr_flags (cpu, fr);
53  else if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr500)
54    fr500_reset_fr_flags (cpu, fr);
55}
56
57static void
58reset_acc_flags (SIM_CPU *cpu, INT acc)
59{
60  SIM_DESC sd = CPU_STATE (cpu);
61  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400
62      || STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450)
63    fr400_reset_acc_flags (cpu, acc);
64  /* Other machines have no acc flags right now.  */
65}
66
67static void
68reset_cc_flags (SIM_CPU *cpu, INT cc)
69{
70  SIM_DESC sd = CPU_STATE (cpu);
71  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr500)
72    fr500_reset_cc_flags (cpu, cc);
73  /* Other machines have no cc flags.  */
74}
75
76void
77set_use_is_gr_complex (SIM_CPU *cpu, INT gr)
78{
79  if (gr != -1)
80    {
81      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
82      reset_gr_flags (cpu, gr);
83      ps->cur_gr_complex |= (((DI)1) << gr);
84    }
85}
86
87void
88set_use_not_gr_complex (SIM_CPU *cpu, INT gr)
89{
90  if (gr != -1)
91    {
92      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
93      ps->cur_gr_complex &= ~(((DI)1) << gr);
94    }
95}
96
97int
98use_is_gr_complex (SIM_CPU *cpu, INT gr)
99{
100  if (gr != -1)
101    {
102      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
103      return ps->cur_gr_complex & (((DI)1) << gr);
104    }
105  return 0;
106}
107
108/* Globals flag indicates whether this insn is being modeled.  */
109enum FRV_INSN_MODELING model_insn = FRV_INSN_NO_MODELING;
110
111/* static buffer for the name of the currently most restrictive hazard.  */
112static char hazard_name[100] = "";
113
114/* Print information about the wait applied to an entire VLIW insn.  */
115FRV_INSN_FETCH_BUFFER frv_insn_fetch_buffer[]
116= {
117  {1, NO_REQNO}, {1, NO_REQNO} /* init with impossible address.  */
118};
119
120enum cache_request
121{
122  cache_load,
123  cache_invalidate,
124  cache_flush,
125  cache_preload,
126  cache_unlock
127};
128
129/* A queue of load requests from the data cache. Use to keep track of loads
130   which are still pending.  */
131/* TODO -- some of these are mutually exclusive and can use a union.  */
132typedef struct
133{
134  FRV_CACHE *cache;
135  unsigned reqno;
136  SI address;
137  int length;
138  int is_signed;
139  int regnum;
140  int cycles;
141  int regtype;
142  int lock;
143  int all;
144  int slot;
145  int active;
146  enum cache_request request;
147} CACHE_QUEUE_ELEMENT;
148
149#define CACHE_QUEUE_SIZE 64 /* TODO -- make queue dynamic */
150struct
151{
152  unsigned reqno;
153  int ix;
154  CACHE_QUEUE_ELEMENT q[CACHE_QUEUE_SIZE];
155} cache_queue = {0, 0};
156
157/* Queue a request for a load from the cache. The load will be queued as
158   'inactive' and will be requested after the given number
159   of cycles have passed from the point the load is activated.  */
160void
161request_cache_load (SIM_CPU *cpu, INT regnum, int regtype, int cycles)
162{
163  CACHE_QUEUE_ELEMENT *q;
164  FRV_VLIW *vliw;
165  int slot;
166
167  /* For a conditional load which was not executed, CPU_LOAD_LENGTH will be
168     zero.  */
169  if (CPU_LOAD_LENGTH (cpu) == 0)
170    return;
171
172  if (cache_queue.ix >= CACHE_QUEUE_SIZE)
173    abort (); /* TODO: Make the queue dynamic */
174
175  q = & cache_queue.q[cache_queue.ix];
176  ++cache_queue.ix;
177
178  q->reqno = cache_queue.reqno++;
179  q->request = cache_load;
180  q->cache = CPU_DATA_CACHE (cpu);
181  q->address = CPU_LOAD_ADDRESS (cpu);
182  q->length = CPU_LOAD_LENGTH (cpu);
183  q->is_signed = CPU_LOAD_SIGNED (cpu);
184  q->regnum = regnum;
185  q->regtype = regtype;
186  q->cycles = cycles;
187  q->active = 0;
188
189  vliw = CPU_VLIW (cpu);
190  slot = vliw->next_slot - 1;
191  q->slot = (*vliw->current_vliw)[slot];
192
193  CPU_LOAD_LENGTH (cpu) = 0;
194}
195
196/* Queue a request to flush the cache. The request will be queued as
197   'inactive' and will be requested after the given number
198   of cycles have passed from the point the request is activated.  */
199void
200request_cache_flush (SIM_CPU *cpu, FRV_CACHE *cache, int cycles)
201{
202  CACHE_QUEUE_ELEMENT *q;
203  FRV_VLIW *vliw;
204  int slot;
205
206  if (cache_queue.ix >= CACHE_QUEUE_SIZE)
207    abort (); /* TODO: Make the queue dynamic */
208
209  q = & cache_queue.q[cache_queue.ix];
210  ++cache_queue.ix;
211
212  q->reqno = cache_queue.reqno++;
213  q->request = cache_flush;
214  q->cache = cache;
215  q->address = CPU_LOAD_ADDRESS (cpu);
216  q->all = CPU_PROFILE_STATE (cpu)->all_cache_entries;
217  q->cycles = cycles;
218  q->active = 0;
219
220  vliw = CPU_VLIW (cpu);
221  slot = vliw->next_slot - 1;
222  q->slot = (*vliw->current_vliw)[slot];
223}
224
225/* Queue a request to invalidate the cache. The request will be queued as
226   'inactive' and will be requested after the given number
227   of cycles have passed from the point the request is activated.  */
228void
229request_cache_invalidate (SIM_CPU *cpu, FRV_CACHE *cache, int cycles)
230{
231  CACHE_QUEUE_ELEMENT *q;
232  FRV_VLIW *vliw;
233  int slot;
234
235  if (cache_queue.ix >= CACHE_QUEUE_SIZE)
236    abort (); /* TODO: Make the queue dynamic */
237
238  q = & cache_queue.q[cache_queue.ix];
239  ++cache_queue.ix;
240
241  q->reqno = cache_queue.reqno++;
242  q->request = cache_invalidate;
243  q->cache = cache;
244  q->address = CPU_LOAD_ADDRESS (cpu);
245  q->all = CPU_PROFILE_STATE (cpu)->all_cache_entries;
246  q->cycles = cycles;
247  q->active = 0;
248
249  vliw = CPU_VLIW (cpu);
250  slot = vliw->next_slot - 1;
251  q->slot = (*vliw->current_vliw)[slot];
252}
253
254/* Queue a request to preload the cache. The request will be queued as
255   'inactive' and will be requested after the given number
256   of cycles have passed from the point the request is activated.  */
257void
258request_cache_preload (SIM_CPU *cpu, FRV_CACHE *cache, int cycles)
259{
260  CACHE_QUEUE_ELEMENT *q;
261  FRV_VLIW *vliw;
262  int slot;
263
264  if (cache_queue.ix >= CACHE_QUEUE_SIZE)
265    abort (); /* TODO: Make the queue dynamic */
266
267  q = & cache_queue.q[cache_queue.ix];
268  ++cache_queue.ix;
269
270  q->reqno = cache_queue.reqno++;
271  q->request = cache_preload;
272  q->cache = cache;
273  q->address = CPU_LOAD_ADDRESS (cpu);
274  q->length = CPU_LOAD_LENGTH (cpu);
275  q->lock = CPU_LOAD_LOCK (cpu);
276  q->cycles = cycles;
277  q->active = 0;
278
279  vliw = CPU_VLIW (cpu);
280  slot = vliw->next_slot - 1;
281  q->slot = (*vliw->current_vliw)[slot];
282
283  CPU_LOAD_LENGTH (cpu) = 0;
284}
285
286/* Queue a request to unlock the cache. The request will be queued as
287   'inactive' and will be requested after the given number
288   of cycles have passed from the point the request is activated.  */
289void
290request_cache_unlock (SIM_CPU *cpu, FRV_CACHE *cache, int cycles)
291{
292  CACHE_QUEUE_ELEMENT *q;
293  FRV_VLIW *vliw;
294  int slot;
295
296  if (cache_queue.ix >= CACHE_QUEUE_SIZE)
297    abort (); /* TODO: Make the queue dynamic */
298
299  q = & cache_queue.q[cache_queue.ix];
300  ++cache_queue.ix;
301
302  q->reqno = cache_queue.reqno++;
303  q->request = cache_unlock;
304  q->cache = cache;
305  q->address = CPU_LOAD_ADDRESS (cpu);
306  q->cycles = cycles;
307  q->active = 0;
308
309  vliw = CPU_VLIW (cpu);
310  slot = vliw->next_slot - 1;
311  q->slot = (*vliw->current_vliw)[slot];
312}
313
314static void
315submit_cache_request (CACHE_QUEUE_ELEMENT *q)
316{
317  switch (q->request)
318    {
319    case cache_load:
320      frv_cache_request_load (q->cache, q->reqno, q->address, q->slot);
321      break;
322    case cache_flush:
323      frv_cache_request_invalidate (q->cache, q->reqno, q->address, q->slot,
324				    q->all, 1/*flush*/);
325      break;
326    case cache_invalidate:
327      frv_cache_request_invalidate (q->cache, q->reqno, q->address, q->slot,
328				   q->all, 0/*flush*/);
329      break;
330    case cache_preload:
331      frv_cache_request_preload (q->cache, q->address, q->slot,
332				 q->length, q->lock);
333      break;
334    case cache_unlock:
335      frv_cache_request_unlock (q->cache, q->address, q->slot);
336      break;
337    default:
338      abort ();
339    }
340}
341
342/* Activate all inactive load requests.  */
343static void
344activate_cache_requests (SIM_CPU *cpu)
345{
346  int i;
347  for (i = 0; i < cache_queue.ix; ++i)
348    {
349      CACHE_QUEUE_ELEMENT *q = & cache_queue.q[i];
350      if (! q->active)
351	{
352	  q->active = 1;
353	  /* Submit the request now if the cycle count is zero.  */
354	  if (q->cycles == 0)
355	    submit_cache_request (q);
356	}
357    }
358}
359
360/* Check to see if a load is pending which affects the given register(s).
361 */
362int
363load_pending_for_register (SIM_CPU *cpu, int regnum, int words, int regtype)
364{
365  int i;
366  for (i = 0; i < cache_queue.ix; ++i)
367    {
368      CACHE_QUEUE_ELEMENT *q = & cache_queue.q[i];
369
370      /* Must be the same kind of register.  */
371      if (! q->active || q->request != cache_load || q->regtype != regtype)
372	continue;
373
374      /* If the registers numbers are equal, then we have a match.  */
375      if (q->regnum == regnum)
376	return 1; /* load pending */
377
378      /* Check for overlap of a load with a multi-word register.  */
379      if (regnum < q->regnum)
380	{
381	  if (regnum + words > q->regnum)
382	    return 1;
383	}
384      /* Check for overlap of a multi-word load with the register.  */
385      else
386	{
387	  int data_words = (q->length + sizeof (SI) - 1) / sizeof (SI);
388	  if (q->regnum + data_words > regnum)
389	    return 1;
390	}
391    }
392
393  return 0; /* no load pending */
394}
395
396/* Check to see if a cache flush pending which affects the given address.  */
397static int
398flush_pending_for_address (SIM_CPU *cpu, SI address)
399{
400  int line_mask = ~(CPU_DATA_CACHE (cpu)->line_size - 1);
401  int i;
402  for (i = 0; i < cache_queue.ix; ++i)
403    {
404      CACHE_QUEUE_ELEMENT *q = & cache_queue.q[i];
405
406      /* Must be the same kind of request and active.  */
407      if (! q->active || q->request != cache_flush)
408	continue;
409
410      /* If the addresses are equal, then we have a match.  */
411      if ((q->address & line_mask) == (address & line_mask))
412	return 1; /* flush pending */
413    }
414
415  return 0; /* no flush pending */
416}
417
418static void
419remove_cache_queue_element (SIM_CPU *cpu, int i)
420{
421  /* If we are removing the load of a FR register, then remember which one(s).
422   */
423  CACHE_QUEUE_ELEMENT q = cache_queue.q[i];
424
425  for (--cache_queue.ix; i < cache_queue.ix; ++i)
426    cache_queue.q[i] = cache_queue.q[i + 1];
427
428  /* If we removed a load of a FR register, check to see if any other loads
429     of that register is still queued. If not, then apply the queued post
430     processing time of that register to its latency.  Also apply
431     1 extra cycle of latency to the register since it was a floating point
432     load.  */
433  if (q.request == cache_load && q.regtype != REGTYPE_NONE)
434    {
435      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
436      int data_words = (q.length + sizeof (SI) - 1) / sizeof (SI);
437      int j;
438      for (j = 0; j < data_words; ++j)
439	{
440	  int regnum = q.regnum + j;
441	  if (! load_pending_for_register (cpu, regnum, 1, q.regtype))
442	    {
443	      if (q.regtype == REGTYPE_FR)
444		{
445		  int *fr = ps->fr_busy;
446		  fr[regnum] += 1 + ps->fr_ptime[regnum];
447		  ps->fr_ptime[regnum] = 0;
448		}
449	    }
450	}
451    }
452}
453
454/* Copy data from the cache buffer to the target register(s).  */
455static void
456copy_load_data (SIM_CPU *current_cpu, FRV_CACHE *cache, int slot,
457		CACHE_QUEUE_ELEMENT *q)
458{
459  switch (q->length)
460    {
461    case 1:
462      if (q->regtype == REGTYPE_FR)
463	{
464	  if (q->is_signed)
465	    {
466	      QI value = CACHE_RETURN_DATA (cache, slot, q->address, QI, 1);
467	      SET_H_FR (q->regnum, value);
468	    }
469	  else
470	    {
471	      UQI value = CACHE_RETURN_DATA (cache, slot, q->address, UQI, 1);
472	      SET_H_FR (q->regnum, value);
473	    }
474	}
475      else
476	{
477	  if (q->is_signed)
478	    {
479	      QI value = CACHE_RETURN_DATA (cache, slot, q->address, QI, 1);
480	      SET_H_GR (q->regnum, value);
481	    }
482	  else
483	    {
484	      UQI value = CACHE_RETURN_DATA (cache, slot, q->address, UQI, 1);
485	      SET_H_GR (q->regnum, value);
486	    }
487	}
488      break;
489    case 2:
490      if (q->regtype == REGTYPE_FR)
491	{
492	  if (q->is_signed)
493	    {
494	      HI value = CACHE_RETURN_DATA (cache, slot, q->address, HI, 2);
495	      SET_H_FR (q->regnum, value);
496	    }
497	  else
498	    {
499	      UHI value = CACHE_RETURN_DATA (cache, slot, q->address, UHI, 2);
500	      SET_H_FR (q->regnum, value);
501	    }
502	}
503      else
504	{
505	  if (q->is_signed)
506	    {
507	      HI value = CACHE_RETURN_DATA (cache, slot, q->address, HI, 2);
508	      SET_H_GR (q->regnum, value);
509	    }
510	  else
511	    {
512	      UHI value = CACHE_RETURN_DATA (cache, slot, q->address, UHI, 2);
513	      SET_H_GR (q->regnum, value);
514	    }
515	}
516      break;
517    case 4:
518      if (q->regtype == REGTYPE_FR)
519	{
520	  SET_H_FR (q->regnum,
521		    CACHE_RETURN_DATA (cache, slot, q->address, SF, 4));
522	}
523      else
524	{
525	  SET_H_GR (q->regnum,
526		    CACHE_RETURN_DATA (cache, slot, q->address, SI, 4));
527	}
528      break;
529    case 8:
530      if (q->regtype == REGTYPE_FR)
531	{
532	  SET_H_FR_DOUBLE (q->regnum,
533			   CACHE_RETURN_DATA (cache, slot, q->address, DF, 8));
534	}
535      else
536	{
537	  SET_H_GR_DOUBLE (q->regnum,
538			   CACHE_RETURN_DATA (cache, slot, q->address, DI, 8));
539	}
540      break;
541    case 16:
542      if (q->regtype == REGTYPE_FR)
543	frvbf_h_fr_quad_set_handler (current_cpu, q->regnum,
544				     CACHE_RETURN_DATA_ADDRESS (cache, slot,
545								q->address,
546								16));
547      else
548	frvbf_h_gr_quad_set_handler (current_cpu, q->regnum,
549				     CACHE_RETURN_DATA_ADDRESS (cache, slot,
550								q->address,
551								16));
552      break;
553    default:
554      abort ();
555    }
556}
557
558static int
559request_complete (SIM_CPU *cpu, CACHE_QUEUE_ELEMENT *q)
560{
561  FRV_CACHE* cache;
562  if (! q->active || q->cycles > 0)
563    return 0;
564
565  cache = CPU_DATA_CACHE (cpu);
566  switch (q->request)
567    {
568    case cache_load:
569      /* For loads, we must wait until the data is returned from the cache.  */
570      if (frv_cache_data_in_buffer (cache, 0, q->address, q->reqno))
571	{
572	  copy_load_data (cpu, cache, 0, q);
573	  return 1;
574	}
575      if (frv_cache_data_in_buffer (cache, 1, q->address, q->reqno))
576	{
577	  copy_load_data (cpu, cache, 1, q);
578	  return 1;
579	}
580      break;
581
582    case cache_flush:
583      /* We must wait until the data is flushed.  */
584      if (frv_cache_data_flushed (cache, 0, q->address, q->reqno))
585	return 1;
586      if (frv_cache_data_flushed (cache, 1, q->address, q->reqno))
587	return 1;
588      break;
589
590    default:
591      /* All other requests are complete once they've been made.  */
592      return 1;
593    }
594
595  return 0;
596}
597
598/* Run the insn and data caches through the given number of cycles, taking
599   note of load requests which are fullfilled as a result.  */
600static void
601run_caches (SIM_CPU *cpu, int cycles)
602{
603  FRV_CACHE* data_cache = CPU_DATA_CACHE (cpu);
604  FRV_CACHE* insn_cache = CPU_INSN_CACHE (cpu);
605  int i;
606  /* For each cycle, run the caches, noting which requests have been fullfilled
607     and submitting new requests on their designated cycles.  */
608  for (i = 0; i < cycles; ++i)
609    {
610      int j;
611      /* Run the caches through 1 cycle.  */
612      frv_cache_run (data_cache, 1);
613      frv_cache_run (insn_cache, 1);
614
615      /* Note whether prefetched insn data has been loaded yet.  */
616      for (j = LS; j < FRV_CACHE_PIPELINES; ++j)
617	{
618	  if (frv_insn_fetch_buffer[j].reqno != NO_REQNO
619	      && frv_cache_data_in_buffer (insn_cache, j,
620					   frv_insn_fetch_buffer[j].address,
621					   frv_insn_fetch_buffer[j].reqno))
622	    frv_insn_fetch_buffer[j].reqno = NO_REQNO;
623	}
624
625      /* Check to see which requests have been satisfied and which should
626	 be submitted now.  */
627      for (j = 0; j < cache_queue.ix; ++j)
628	{
629	  CACHE_QUEUE_ELEMENT *q = & cache_queue.q[j];
630	  if (! q->active)
631	    continue;
632
633	  /* If a load has been satisfied, complete the operation and remove it
634	     from the queue.  */
635	  if (request_complete (cpu, q))
636	    {
637	      remove_cache_queue_element (cpu, j);
638	      --j;
639	      continue;
640	    }
641
642	  /* Decrease the cycle count of each queued request.
643	     Submit a request for each queued request whose cycle count has
644	     become zero.  */
645	  --q->cycles;
646	  if (q->cycles == 0)
647	    submit_cache_request (q);
648	}
649    }
650}
651
652static void
653apply_latency_adjustments (SIM_CPU *cpu)
654{
655  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
656  int i;
657  /* update the latencies of the registers.  */
658  int *fr  = ps->fr_busy;
659  int *acc = ps->acc_busy;
660  for (i = 0; i < 64; ++i)
661    {
662      if (ps->fr_busy_adjust[i] > 0)
663	*fr -= ps->fr_busy_adjust[i]; /* OK if it goes negative.  */
664      if (ps->acc_busy_adjust[i] > 0)
665	*acc -= ps->acc_busy_adjust[i]; /* OK if it goes negative.  */
666      ++fr;
667      ++acc;
668    }
669}
670
671/* Account for the number of cycles which have just passed in the latency of
672   various system elements.  Works for negative cycles too so that latency
673   can be extended in the case of insn fetch latency.
674   If negative or zero, then no adjustment is necessary.  */
675static void
676update_latencies (SIM_CPU *cpu, int cycles)
677{
678  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
679  int i;
680  /* update the latencies of the registers.  */
681  int *fdiv;
682  int *fsqrt;
683  int *idiv;
684  int *flt;
685  int *media;
686  int *ccr;
687  int *gr  = ps->gr_busy;
688  int *fr  = ps->fr_busy;
689  int *acc = ps->acc_busy;
690  int *spr;
691  /* This loop handles GR, FR and ACC registers.  */
692  for (i = 0; i < 64; ++i)
693    {
694      if (*gr <= cycles)
695	{
696	  *gr = 0;
697	  reset_gr_flags (cpu, i);
698	}
699      else
700	*gr -= cycles;
701      /* If the busy drops to 0, then mark the register as
702	 "not in use".  */
703      if (*fr <= cycles)
704	{
705	  int *fr_lat = ps->fr_latency + i;
706	  *fr = 0;
707	  ps->fr_busy_adjust[i] = 0;
708	  /* Only clear flags if this register has no target latency.  */
709	  if (*fr_lat == 0)
710	    reset_fr_flags (cpu, i);
711	}
712      else
713	*fr -= cycles;
714      /* If the busy drops to 0, then mark the register as
715	 "not in use".  */
716      if (*acc <= cycles)
717	{
718	  int *acc_lat = ps->acc_latency + i;
719	  *acc = 0;
720	  ps->acc_busy_adjust[i] = 0;
721	  /* Only clear flags if this register has no target latency.  */
722	  if (*acc_lat == 0)
723	    reset_acc_flags (cpu, i);
724	}
725      else
726	*acc -= cycles;
727      ++gr;
728      ++fr;
729      ++acc;
730    }
731  /* This loop handles CCR registers.  */
732  ccr = ps->ccr_busy;
733  for (i = 0; i < 8; ++i)
734    {
735      if (*ccr <= cycles)
736	{
737	  *ccr = 0;
738	  reset_cc_flags (cpu, i);
739	}
740      else
741	*ccr -= cycles;
742      ++ccr;
743    }
744  /* This loop handles SPR registers.  */
745  spr = ps->spr_busy;
746  for (i = 0; i < 4096; ++i)
747    {
748      if (*spr <= cycles)
749	*spr = 0;
750      else
751	*spr -= cycles;
752      ++spr;
753    }
754  /* This loop handles resources.  */
755  idiv = ps->idiv_busy;
756  fdiv = ps->fdiv_busy;
757  fsqrt = ps->fsqrt_busy;
758  for (i = 0; i < 2; ++i)
759    {
760      *idiv = (*idiv <= cycles) ? 0 : (*idiv - cycles);
761      *fdiv = (*fdiv <= cycles) ? 0 : (*fdiv - cycles);
762      *fsqrt = (*fsqrt <= cycles) ? 0 : (*fsqrt - cycles);
763      ++idiv;
764      ++fdiv;
765      ++fsqrt;
766    }
767  /* Float and media units can occur in 4 slots on some machines.  */
768  flt = ps->float_busy;
769  media = ps->media_busy;
770  for (i = 0; i < 4; ++i)
771    {
772      *flt = (*flt <= cycles) ? 0 : (*flt - cycles);
773      *media = (*media <= cycles) ? 0 : (*media - cycles);
774      ++flt;
775      ++media;
776    }
777}
778
779/* Print information about the wait for the given number of cycles.  */
780void
781frv_model_trace_wait_cycles (SIM_CPU *cpu, int cycles, const char *hazard_name)
782{
783  if (TRACE_INSN_P (cpu) && cycles > 0)
784    {
785      SIM_DESC sd = CPU_STATE (cpu);
786      trace_printf (sd, cpu, "**** %s wait %d cycles ***\n",
787		    hazard_name, cycles);
788    }
789}
790
791void
792trace_vliw_wait_cycles (SIM_CPU *cpu)
793{
794  if (TRACE_INSN_P (cpu))
795    {
796      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
797      frv_model_trace_wait_cycles (cpu, ps->vliw_wait, hazard_name);
798    }
799}
800
801/* Wait for the given number of cycles.  */
802void
803frv_model_advance_cycles (SIM_CPU *cpu, int cycles)
804{
805  PROFILE_DATA *p = CPU_PROFILE_DATA (cpu);
806  update_latencies (cpu, cycles);
807  run_caches (cpu, cycles);
808  PROFILE_MODEL_TOTAL_CYCLES (p) += cycles;
809}
810
811void
812handle_resource_wait (SIM_CPU *cpu)
813{
814  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
815  if (ps->vliw_wait != 0)
816    frv_model_advance_cycles (cpu, ps->vliw_wait);
817  if (ps->vliw_load_stall > ps->vliw_wait)
818    ps->vliw_load_stall -= ps->vliw_wait;
819  else
820    ps->vliw_load_stall = 0;
821}
822
823/* Account for the number of cycles until these resources will be available
824   again.  */
825static void
826update_target_latencies (SIM_CPU *cpu)
827{
828  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
829  int i;
830  /* update the latencies of the registers.  */
831  int *ccr_lat;
832  int *gr_lat  = ps->gr_latency;
833  int *fr_lat  = ps->fr_latency;
834  int *acc_lat = ps->acc_latency;
835  int *spr_lat;
836  int *ccr;
837  int *gr = ps->gr_busy;
838  int  *fr = ps->fr_busy;
839  int  *acc = ps->acc_busy;
840  int *spr;
841  /* This loop handles GR, FR and ACC registers.  */
842  for (i = 0; i < 64; ++i)
843    {
844      if (*gr_lat)
845	{
846	  *gr = *gr_lat;
847	  *gr_lat = 0;
848	}
849      if (*fr_lat)
850	{
851	  *fr = *fr_lat;
852	  *fr_lat = 0;
853	}
854      if (*acc_lat)
855	{
856	  *acc = *acc_lat;
857	  *acc_lat = 0;
858	}
859      ++gr; ++gr_lat;
860      ++fr; ++fr_lat;
861      ++acc; ++acc_lat;
862    }
863  /* This loop handles CCR registers.  */
864  ccr = ps->ccr_busy;
865  ccr_lat = ps->ccr_latency;
866  for (i = 0; i < 8; ++i)
867    {
868      if (*ccr_lat)
869	{
870	  *ccr = *ccr_lat;
871	  *ccr_lat = 0;
872	}
873      ++ccr; ++ccr_lat;
874    }
875  /* This loop handles SPR registers.  */
876  spr = ps->spr_busy;
877  spr_lat = ps->spr_latency;
878  for (i = 0; i < 4096; ++i)
879    {
880      if (*spr_lat)
881	{
882	  *spr = *spr_lat;
883	  *spr_lat = 0;
884	}
885      ++spr; ++spr_lat;
886    }
887}
888
889/* Run the caches until all pending cache flushes are complete.  */
890static void
891wait_for_flush (SIM_CPU *cpu)
892{
893  SI address = CPU_LOAD_ADDRESS (cpu);
894  int wait = 0;
895  while (flush_pending_for_address (cpu, address))
896    {
897      frv_model_advance_cycles (cpu, 1);
898      ++wait;
899    }
900  if (TRACE_INSN_P (cpu) && wait)
901    {
902      sprintf (hazard_name, "Data cache flush address %p:", address);
903      frv_model_trace_wait_cycles (cpu, wait, hazard_name);
904    }
905}
906
907/* Initialize cycle counting for an insn.
908   FIRST_P is non-zero if this is the first insn in a set of parallel
909   insns.  */
910void
911frvbf_model_insn_before (SIM_CPU *cpu, int first_p)
912{
913  SIM_DESC sd = CPU_STATE (cpu);
914  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
915
916  ps->vliw_wait = 0;
917  ps->post_wait = 0;
918  memset (ps->fr_busy_adjust, 0, sizeof (ps->fr_busy_adjust));
919  memset (ps->acc_busy_adjust, 0, sizeof (ps->acc_busy_adjust));
920
921  if (first_p)
922    {
923      ps->vliw_insns++;
924      ps->vliw_cycles = 0;
925      ps->vliw_branch_taken = 0;
926      ps->vliw_load_stall = 0;
927    }
928
929  switch (STATE_ARCHITECTURE (sd)->mach)
930    {
931    case bfd_mach_fr400:
932    case bfd_mach_fr450:
933      fr400_model_insn_before (cpu, first_p);
934      break;
935    case bfd_mach_fr500:
936      fr500_model_insn_before (cpu, first_p);
937      break;
938    case bfd_mach_fr550:
939      fr550_model_insn_before (cpu, first_p);
940      break;
941    default:
942      break;
943    }
944
945  if (first_p)
946    wait_for_flush (cpu);
947}
948
949/* Record the cycles computed for an insn.
950   LAST_P is non-zero if this is the last insn in a set of parallel insns,
951   and we update the total cycle count.
952   CYCLES is the cycle count of the insn.  */
953
954void
955frvbf_model_insn_after (SIM_CPU *cpu, int last_p, int cycles)
956{
957  PROFILE_DATA *p = CPU_PROFILE_DATA (cpu);
958  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
959  SIM_DESC sd = CPU_STATE (cpu);
960
961  PROFILE_MODEL_CUR_INSN_CYCLES (p) = cycles;
962
963  /* The number of cycles for a VLIW insn is the maximum number of cycles
964     used by any individual insn within it.  */
965  if (cycles > ps->vliw_cycles)
966    ps->vliw_cycles = cycles;
967
968  if (last_p)
969    {
970      /*  This is the last insn in a VLIW insn.  */
971      struct frv_interrupt_timer *timer = & frv_interrupt_state.timer;
972
973      activate_cache_requests (cpu); /* before advancing cycles.  */
974      apply_latency_adjustments (cpu); /* must go first.  */
975      update_target_latencies (cpu); /* must go next.  */
976      frv_model_advance_cycles (cpu, ps->vliw_cycles);
977
978      PROFILE_MODEL_LOAD_STALL_CYCLES (p) += ps->vliw_load_stall;
979
980      /* Check the interrupt timer.  cycles contains the total cycle count.  */
981      if (timer->enabled)
982	{
983	  cycles = PROFILE_MODEL_TOTAL_CYCLES (p);
984	  if (timer->current % timer->value
985	      + (cycles - timer->current) >= timer->value)
986	    frv_queue_external_interrupt (cpu, timer->interrupt);
987	  timer->current = cycles;
988	}
989
990      ps->past_first_p = 0; /* Next one will be the first in a new VLIW.  */
991      ps->branch_address = -1;
992    }
993  else
994    ps->past_first_p = 1;
995
996  switch (STATE_ARCHITECTURE (sd)->mach)
997    {
998    case bfd_mach_fr400:
999    case bfd_mach_fr450:
1000      fr400_model_insn_after (cpu, last_p, cycles);
1001      break;
1002    case bfd_mach_fr500:
1003      fr500_model_insn_after (cpu, last_p, cycles);
1004      break;
1005    case bfd_mach_fr550:
1006      fr550_model_insn_after (cpu, last_p, cycles);
1007      break;
1008    default:
1009      break;
1010    }
1011}
1012
1013USI
1014frvbf_model_branch (SIM_CPU *current_cpu, PCADDR target, int hint)
1015{
1016  /* Record the hint and branch address for use in profiling.  */
1017  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu);
1018  ps->branch_hint = hint;
1019  ps->branch_address = target;
1020}
1021
1022/* Top up the latency of the given GR by the given number of cycles.  */
1023void
1024update_GR_latency (SIM_CPU *cpu, INT out_GR, int cycles)
1025{
1026  if (out_GR >= 0)
1027    {
1028      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1029      int *gr = ps->gr_latency;
1030      if (gr[out_GR] < cycles)
1031	gr[out_GR] = cycles;
1032    }
1033}
1034
1035void
1036decrease_GR_busy (SIM_CPU *cpu, INT in_GR, int cycles)
1037{
1038  if (in_GR >= 0)
1039    {
1040      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1041      int *gr = ps->gr_busy;
1042      gr[in_GR] -= cycles;
1043    }
1044}
1045
1046/* Top up the latency of the given double GR by the number of cycles.  */
1047void
1048update_GRdouble_latency (SIM_CPU *cpu, INT out_GR, int cycles)
1049{
1050  if (out_GR >= 0)
1051    {
1052      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1053      int *gr = ps->gr_latency;
1054      if (gr[out_GR] < cycles)
1055	gr[out_GR] = cycles;
1056      if (out_GR < 63 && gr[out_GR + 1] < cycles)
1057	gr[out_GR + 1] = cycles;
1058    }
1059}
1060
1061void
1062update_GR_latency_for_load (SIM_CPU *cpu, INT out_GR, int cycles)
1063{
1064  if (out_GR >= 0)
1065    {
1066      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1067      int *gr = ps->gr_latency;
1068
1069      /* The latency of the GR will be at least the number of cycles used
1070	 by the insn.  */
1071      if (gr[out_GR] < cycles)
1072	gr[out_GR] = cycles;
1073
1074      /* The latency will also depend on how long it takes to retrieve the
1075	 data from the cache or memory.  Assume that the load is issued
1076	 after the last cycle of the insn.  */
1077      request_cache_load (cpu, out_GR, REGTYPE_NONE, cycles);
1078    }
1079}
1080
1081void
1082update_GRdouble_latency_for_load (SIM_CPU *cpu, INT out_GR, int cycles)
1083{
1084  if (out_GR >= 0)
1085    {
1086      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1087      int *gr = ps->gr_latency;
1088
1089      /* The latency of the GR will be at least the number of cycles used
1090	 by the insn.  */
1091      if (gr[out_GR] < cycles)
1092	gr[out_GR] = cycles;
1093      if (out_GR < 63 && gr[out_GR + 1] < cycles)
1094	gr[out_GR + 1] = cycles;
1095
1096      /* The latency will also depend on how long it takes to retrieve the
1097	 data from the cache or memory.  Assume that the load is issued
1098	 after the last cycle of the insn.  */
1099      request_cache_load (cpu, out_GR, REGTYPE_NONE, cycles);
1100    }
1101}
1102
1103void
1104update_GR_latency_for_swap (SIM_CPU *cpu, INT out_GR, int cycles)
1105{
1106  update_GR_latency_for_load (cpu, out_GR, cycles);
1107}
1108
1109/* Top up the latency of the given FR by the given number of cycles.  */
1110void
1111update_FR_latency (SIM_CPU *cpu, INT out_FR, int cycles)
1112{
1113  if (out_FR >= 0)
1114    {
1115      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1116      int *fr = ps->fr_latency;
1117      if (fr[out_FR] < cycles)
1118	fr[out_FR] = cycles;
1119    }
1120}
1121
1122/* Top up the latency of the given double FR by the number of cycles.  */
1123void
1124update_FRdouble_latency (SIM_CPU *cpu, INT out_FR, int cycles)
1125{
1126  if (out_FR >= 0)
1127    {
1128      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1129      int *fr = ps->fr_latency;
1130      if (fr[out_FR] < cycles)
1131	fr[out_FR] = cycles;
1132      if (out_FR < 63 && fr[out_FR + 1] < cycles)
1133	fr[out_FR + 1] = cycles;
1134    }
1135}
1136
1137void
1138update_FR_latency_for_load (SIM_CPU *cpu, INT out_FR, int cycles)
1139{
1140  if (out_FR >= 0)
1141    {
1142      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1143      int *fr = ps->fr_latency;
1144
1145      /* The latency of the FR will be at least the number of cycles used
1146	 by the insn.  */
1147      if (fr[out_FR] < cycles)
1148	fr[out_FR] = cycles;
1149
1150      /* The latency will also depend on how long it takes to retrieve the
1151	 data from the cache or memory.  Assume that the load is issued
1152	 after the last cycle of the insn.  */
1153      request_cache_load (cpu, out_FR, REGTYPE_FR, cycles);
1154    }
1155}
1156
1157void
1158update_FRdouble_latency_for_load (SIM_CPU *cpu, INT out_FR, int cycles)
1159{
1160  if (out_FR >= 0)
1161    {
1162      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1163      int *fr = ps->fr_latency;
1164
1165      /* The latency of the FR will be at least the number of cycles used
1166	 by the insn.  */
1167      if (fr[out_FR] < cycles)
1168	fr[out_FR] = cycles;
1169      if (out_FR < 63 && fr[out_FR + 1] < cycles)
1170	fr[out_FR + 1] = cycles;
1171
1172      /* The latency will also depend on how long it takes to retrieve the
1173	 data from the cache or memory.  Assume that the load is issued
1174	 after the last cycle of the insn.  */
1175      request_cache_load (cpu, out_FR, REGTYPE_FR, cycles);
1176    }
1177}
1178
1179/* Top up the post-processing time of the given FR by the given number of
1180   cycles.  */
1181void
1182update_FR_ptime (SIM_CPU *cpu, INT out_FR, int cycles)
1183{
1184  if (out_FR >= 0)
1185    {
1186      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1187      /* If a load is pending on this register, then add the cycles to
1188	 the post processing time for this register. Otherwise apply it
1189	 directly to the latency of the register.  */
1190      if (! load_pending_for_register (cpu, out_FR, 1, REGTYPE_FR))
1191	{
1192	  int *fr = ps->fr_latency;
1193	  fr[out_FR] += cycles;
1194	}
1195      else
1196	ps->fr_ptime[out_FR] += cycles;
1197    }
1198}
1199
1200void
1201update_FRdouble_ptime (SIM_CPU *cpu, INT out_FR, int cycles)
1202{
1203  if (out_FR >= 0)
1204    {
1205      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1206      /* If a load is pending on this register, then add the cycles to
1207	 the post processing time for this register. Otherwise apply it
1208	 directly to the latency of the register.  */
1209      if (! load_pending_for_register (cpu, out_FR, 2, REGTYPE_FR))
1210	{
1211	  int *fr = ps->fr_latency;
1212	  fr[out_FR] += cycles;
1213	  if (out_FR < 63)
1214	    fr[out_FR + 1] += cycles;
1215	}
1216      else
1217	{
1218	  ps->fr_ptime[out_FR] += cycles;
1219	  if (out_FR < 63)
1220	    ps->fr_ptime[out_FR + 1] += cycles;
1221	}
1222    }
1223}
1224
1225/* Top up the post-processing time of the given ACC by the given number of
1226   cycles.  */
1227void
1228update_ACC_ptime (SIM_CPU *cpu, INT out_ACC, int cycles)
1229{
1230  if (out_ACC >= 0)
1231    {
1232      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1233      /* No load can be pending on this register. Apply the cycles
1234	 directly to the latency of the register.  */
1235      int *acc = ps->acc_latency;
1236      acc[out_ACC] += cycles;
1237    }
1238}
1239
1240/* Top up the post-processing time of the given SPR by the given number of
1241   cycles.  */
1242void
1243update_SPR_ptime (SIM_CPU *cpu, INT out_SPR, int cycles)
1244{
1245  if (out_SPR >= 0)
1246    {
1247      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1248      /* No load can be pending on this register. Apply the cycles
1249	 directly to the latency of the register.  */
1250      int *spr = ps->spr_latency;
1251      spr[out_SPR] += cycles;
1252    }
1253}
1254
1255void
1256decrease_ACC_busy (SIM_CPU *cpu, INT out_ACC, int cycles)
1257{
1258  if (out_ACC >= 0)
1259    {
1260      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1261      int *acc = ps->acc_busy;
1262      acc[out_ACC] -= cycles;
1263      if (ps->acc_busy_adjust[out_ACC] >= 0
1264	  && cycles > ps->acc_busy_adjust[out_ACC])
1265	ps->acc_busy_adjust[out_ACC] = cycles;
1266    }
1267}
1268
1269void
1270increase_ACC_busy (SIM_CPU *cpu, INT out_ACC, int cycles)
1271{
1272  if (out_ACC >= 0)
1273    {
1274      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1275      int *acc = ps->acc_busy;
1276      acc[out_ACC] += cycles;
1277    }
1278}
1279
1280void
1281enforce_full_acc_latency (SIM_CPU *cpu, INT in_ACC)
1282{
1283  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1284  ps->acc_busy_adjust [in_ACC] = -1;
1285}
1286
1287void
1288decrease_FR_busy (SIM_CPU *cpu, INT out_FR, int cycles)
1289{
1290  if (out_FR >= 0)
1291    {
1292      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1293      int *fr = ps->fr_busy;
1294      fr[out_FR] -= cycles;
1295      if (ps->fr_busy_adjust[out_FR] >= 0
1296	  && cycles > ps->fr_busy_adjust[out_FR])
1297	ps->fr_busy_adjust[out_FR] = cycles;
1298    }
1299}
1300
1301void
1302increase_FR_busy (SIM_CPU *cpu, INT out_FR, int cycles)
1303{
1304  if (out_FR >= 0)
1305    {
1306      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1307      int *fr = ps->fr_busy;
1308      fr[out_FR] += cycles;
1309    }
1310}
1311
1312/* Top up the latency of the given ACC by the given number of cycles.  */
1313void
1314update_ACC_latency (SIM_CPU *cpu, INT out_ACC, int cycles)
1315{
1316  if (out_ACC >= 0)
1317    {
1318      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1319      int *acc = ps->acc_latency;
1320      if (acc[out_ACC] < cycles)
1321	acc[out_ACC] = cycles;
1322    }
1323}
1324
1325/* Top up the latency of the given CCR by the given number of cycles.  */
1326void
1327update_CCR_latency (SIM_CPU *cpu, INT out_CCR, int cycles)
1328{
1329  if (out_CCR >= 0)
1330    {
1331      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1332      int *ccr = ps->ccr_latency;
1333      if (ccr[out_CCR] < cycles)
1334	ccr[out_CCR] = cycles;
1335    }
1336}
1337
1338/* Top up the latency of the given SPR by the given number of cycles.  */
1339void
1340update_SPR_latency (SIM_CPU *cpu, INT out_SPR, int cycles)
1341{
1342  if (out_SPR >= 0)
1343    {
1344      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1345      int *spr = ps->spr_latency;
1346      if (spr[out_SPR] < cycles)
1347	spr[out_SPR] = cycles;
1348    }
1349}
1350
1351/* Top up the latency of the given integer division resource by the given
1352   number of cycles.  */
1353void
1354update_idiv_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
1355{
1356  /* operate directly on the busy cycles since each resource can only
1357     be used once in a VLIW insn.  */
1358  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1359  int *r = ps->idiv_busy;
1360  r[in_resource] = cycles;
1361}
1362
1363/* Set the latency of the given resource to the given number of cycles.  */
1364void
1365update_fdiv_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
1366{
1367  /* operate directly on the busy cycles since each resource can only
1368     be used once in a VLIW insn.  */
1369  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1370  int *r = ps->fdiv_busy;
1371  r[in_resource] = cycles;
1372}
1373
1374/* Set the latency of the given resource to the given number of cycles.  */
1375void
1376update_fsqrt_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
1377{
1378  /* operate directly on the busy cycles since each resource can only
1379     be used once in a VLIW insn.  */
1380  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1381  int *r = ps->fsqrt_busy;
1382  r[in_resource] = cycles;
1383}
1384
1385/* Set the latency of the given resource to the given number of cycles.  */
1386void
1387update_float_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
1388{
1389  /* operate directly on the busy cycles since each resource can only
1390     be used once in a VLIW insn.  */
1391  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1392  int *r = ps->float_busy;
1393  r[in_resource] = cycles;
1394}
1395
1396void
1397update_media_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
1398{
1399  /* operate directly on the busy cycles since each resource can only
1400     be used once in a VLIW insn.  */
1401  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1402  int *r = ps->media_busy;
1403  r[in_resource] = cycles;
1404}
1405
1406/* Set the branch penalty to the given number of cycles.  */
1407void
1408update_branch_penalty (SIM_CPU *cpu, int cycles)
1409{
1410  /* operate directly on the busy cycles since only one branch can occur
1411     in a VLIW insn.  */
1412  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1413  ps->branch_penalty = cycles;
1414}
1415
1416/* Check the availability of the given GR register and update the number
1417   of cycles the current VLIW insn must wait until it is available.  */
1418void
1419vliw_wait_for_GR (SIM_CPU *cpu, INT in_GR)
1420{
1421  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1422  int *gr = ps->gr_busy;
1423  /* If the latency of the register is greater than the current wait
1424     then update the current wait.  */
1425  if (in_GR >= 0 && gr[in_GR] > ps->vliw_wait)
1426    {
1427      if (TRACE_INSN_P (cpu))
1428	sprintf (hazard_name, "Data hazard for gr%d:", in_GR);
1429      ps->vliw_wait = gr[in_GR];
1430    }
1431}
1432
1433/* Check the availability of the given GR register and update the number
1434   of cycles the current VLIW insn must wait until it is available.  */
1435void
1436vliw_wait_for_GRdouble (SIM_CPU *cpu, INT in_GR)
1437{
1438  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1439  int *gr = ps->gr_busy;
1440  /* If the latency of the register is greater than the current wait
1441     then update the current wait.  */
1442  if (in_GR >= 0)
1443    {
1444      if (gr[in_GR] > ps->vliw_wait)
1445	{
1446	  if (TRACE_INSN_P (cpu))
1447	    sprintf (hazard_name, "Data hazard for gr%d:", in_GR);
1448	  ps->vliw_wait = gr[in_GR];
1449	}
1450      if (in_GR < 63 && gr[in_GR + 1] > ps->vliw_wait)
1451	{
1452	  if (TRACE_INSN_P (cpu))
1453	    sprintf (hazard_name, "Data hazard for gr%d:", in_GR + 1);
1454	  ps->vliw_wait = gr[in_GR + 1];
1455	}
1456    }
1457}
1458
1459/* Check the availability of the given FR register and update the number
1460   of cycles the current VLIW insn must wait until it is available.  */
1461void
1462vliw_wait_for_FR (SIM_CPU *cpu, INT in_FR)
1463{
1464  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1465  int *fr = ps->fr_busy;
1466  /* If the latency of the register is greater than the current wait
1467     then update the current wait.  */
1468  if (in_FR >= 0 && fr[in_FR] > ps->vliw_wait)
1469    {
1470      if (TRACE_INSN_P (cpu))
1471	sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
1472      ps->vliw_wait = fr[in_FR];
1473    }
1474}
1475
1476/* Check the availability of the given GR register and update the number
1477   of cycles the current VLIW insn must wait until it is available.  */
1478void
1479vliw_wait_for_FRdouble (SIM_CPU *cpu, INT in_FR)
1480{
1481  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1482  int *fr = ps->fr_busy;
1483  /* If the latency of the register is greater than the current wait
1484     then update the current wait.  */
1485  if (in_FR >= 0)
1486    {
1487      if (fr[in_FR] > ps->vliw_wait)
1488	{
1489	  if (TRACE_INSN_P (cpu))
1490	    sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
1491	  ps->vliw_wait = fr[in_FR];
1492	}
1493      if (in_FR < 63 && fr[in_FR + 1] > ps->vliw_wait)
1494	{
1495	  if (TRACE_INSN_P (cpu))
1496	    sprintf (hazard_name, "Data hazard for fr%d:", in_FR + 1);
1497	  ps->vliw_wait = fr[in_FR + 1];
1498	}
1499    }
1500}
1501
1502/* Check the availability of the given CCR register and update the number
1503   of cycles the current VLIW insn must wait until it is available.  */
1504void
1505vliw_wait_for_CCR (SIM_CPU *cpu, INT in_CCR)
1506{
1507  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1508  int *ccr = ps->ccr_busy;
1509  /* If the latency of the register is greater than the current wait
1510     then update the current wait.  */
1511  if (in_CCR >= 0 && ccr[in_CCR] > ps->vliw_wait)
1512    {
1513      if (TRACE_INSN_P (cpu))
1514	{
1515	  if (in_CCR > 3)
1516	    sprintf (hazard_name, "Data hazard for icc%d:", in_CCR-4);
1517	  else
1518	    sprintf (hazard_name, "Data hazard for fcc%d:", in_CCR);
1519	}
1520      ps->vliw_wait = ccr[in_CCR];
1521    }
1522}
1523
1524/* Check the availability of the given ACC register and update the number
1525   of cycles the current VLIW insn must wait until it is available.  */
1526void
1527vliw_wait_for_ACC (SIM_CPU *cpu, INT in_ACC)
1528{
1529  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1530  int *acc = ps->acc_busy;
1531  /* If the latency of the register is greater than the current wait
1532     then update the current wait.  */
1533  if (in_ACC >= 0 && acc[in_ACC] > ps->vliw_wait)
1534    {
1535      if (TRACE_INSN_P (cpu))
1536	sprintf (hazard_name, "Data hazard for acc%d:", in_ACC);
1537      ps->vliw_wait = acc[in_ACC];
1538    }
1539}
1540
1541/* Check the availability of the given SPR register and update the number
1542   of cycles the current VLIW insn must wait until it is available.  */
1543void
1544vliw_wait_for_SPR (SIM_CPU *cpu, INT in_SPR)
1545{
1546  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1547  int *spr = ps->spr_busy;
1548  /* If the latency of the register is greater than the current wait
1549     then update the current wait.  */
1550  if (in_SPR >= 0 && spr[in_SPR] > ps->vliw_wait)
1551    {
1552      if (TRACE_INSN_P (cpu))
1553	sprintf (hazard_name, "Data hazard for spr %d:", in_SPR);
1554      ps->vliw_wait = spr[in_SPR];
1555    }
1556}
1557
1558/* Check the availability of the given integer division resource and update
1559   the number of cycles the current VLIW insn must wait until it is available.
1560*/
1561void
1562vliw_wait_for_idiv_resource (SIM_CPU *cpu, INT in_resource)
1563{
1564  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1565  int *r = ps->idiv_busy;
1566  /* If the latency of the resource is greater than the current wait
1567     then update the current wait.  */
1568  if (r[in_resource] > ps->vliw_wait)
1569    {
1570      if (TRACE_INSN_P (cpu))
1571	{
1572	  sprintf (hazard_name, "Resource hazard for integer division in slot I%d:", in_resource);
1573	}
1574      ps->vliw_wait = r[in_resource];
1575    }
1576}
1577
1578/* Check the availability of the given float division resource and update
1579   the number of cycles the current VLIW insn must wait until it is available.
1580*/
1581void
1582vliw_wait_for_fdiv_resource (SIM_CPU *cpu, INT in_resource)
1583{
1584  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1585  int *r = ps->fdiv_busy;
1586  /* If the latency of the resource is greater than the current wait
1587     then update the current wait.  */
1588  if (r[in_resource] > ps->vliw_wait)
1589    {
1590      if (TRACE_INSN_P (cpu))
1591	{
1592	  sprintf (hazard_name, "Resource hazard for floating point division in slot F%d:", in_resource);
1593	}
1594      ps->vliw_wait = r[in_resource];
1595    }
1596}
1597
1598/* Check the availability of the given float square root resource and update
1599   the number of cycles the current VLIW insn must wait until it is available.
1600*/
1601void
1602vliw_wait_for_fsqrt_resource (SIM_CPU *cpu, INT in_resource)
1603{
1604  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1605  int *r = ps->fsqrt_busy;
1606  /* If the latency of the resource is greater than the current wait
1607     then update the current wait.  */
1608  if (r[in_resource] > ps->vliw_wait)
1609    {
1610      if (TRACE_INSN_P (cpu))
1611	{
1612	  sprintf (hazard_name, "Resource hazard for square root in slot F%d:", in_resource);
1613	}
1614      ps->vliw_wait = r[in_resource];
1615    }
1616}
1617
1618/* Check the availability of the given float unit resource and update
1619   the number of cycles the current VLIW insn must wait until it is available.
1620*/
1621void
1622vliw_wait_for_float_resource (SIM_CPU *cpu, INT in_resource)
1623{
1624  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1625  int *r = ps->float_busy;
1626  /* If the latency of the resource is greater than the current wait
1627     then update the current wait.  */
1628  if (r[in_resource] > ps->vliw_wait)
1629    {
1630      if (TRACE_INSN_P (cpu))
1631	{
1632	  sprintf (hazard_name, "Resource hazard for floating point unit in slot F%d:", in_resource);
1633	}
1634      ps->vliw_wait = r[in_resource];
1635    }
1636}
1637
1638/* Check the availability of the given media unit resource and update
1639   the number of cycles the current VLIW insn must wait until it is available.
1640*/
1641void
1642vliw_wait_for_media_resource (SIM_CPU *cpu, INT in_resource)
1643{
1644  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1645  int *r = ps->media_busy;
1646  /* If the latency of the resource is greater than the current wait
1647     then update the current wait.  */
1648  if (r[in_resource] > ps->vliw_wait)
1649    {
1650      if (TRACE_INSN_P (cpu))
1651	{
1652	  sprintf (hazard_name, "Resource hazard for media unit in slot M%d:", in_resource);
1653	}
1654      ps->vliw_wait = r[in_resource];
1655    }
1656}
1657
1658/* Run the caches until all requests for the given register(s) are satisfied. */
1659void
1660load_wait_for_GR (SIM_CPU *cpu, INT in_GR)
1661{
1662  if (in_GR >= 0)
1663    {
1664      int wait = 0;
1665      while (load_pending_for_register (cpu, in_GR, 1/*words*/, REGTYPE_NONE))
1666	{
1667	  frv_model_advance_cycles (cpu, 1);
1668	  ++wait;
1669	}
1670      if (wait)
1671	{
1672	  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1673	  ps->vliw_wait += wait;
1674	  ps->vliw_load_stall += wait;
1675	  if (TRACE_INSN_P (cpu))
1676	    sprintf (hazard_name, "Data hazard for gr%d:", in_GR);
1677	}
1678    }
1679}
1680
1681void
1682load_wait_for_FR (SIM_CPU *cpu, INT in_FR)
1683{
1684  if (in_FR >= 0)
1685    {
1686      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1687      int *fr;
1688      int wait = 0;
1689      while (load_pending_for_register (cpu, in_FR, 1/*words*/, REGTYPE_FR))
1690	{
1691	  frv_model_advance_cycles (cpu, 1);
1692	  ++wait;
1693	}
1694      /* Post processing time may have been added to the register's
1695	 latency after the loads were processed. Account for that too.
1696      */
1697      fr = ps->fr_busy;
1698      if (fr[in_FR])
1699	{
1700	  wait += fr[in_FR];
1701	  frv_model_advance_cycles (cpu, fr[in_FR]);
1702	}
1703      /* Update the vliw_wait with the number of cycles we waited for the
1704	 load and any post-processing.  */
1705      if (wait)
1706	{
1707	  ps->vliw_wait += wait;
1708	  ps->vliw_load_stall += wait;
1709	  if (TRACE_INSN_P (cpu))
1710	    sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
1711	}
1712    }
1713}
1714
1715void
1716load_wait_for_GRdouble (SIM_CPU *cpu, INT in_GR)
1717{
1718  if (in_GR >= 0)
1719    {
1720      int wait = 0;
1721      while (load_pending_for_register (cpu, in_GR, 2/*words*/, REGTYPE_NONE))
1722	{
1723	  frv_model_advance_cycles (cpu, 1);
1724	  ++wait;
1725	}
1726      if (wait)
1727	{
1728	  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1729	  ps->vliw_wait += wait;
1730	  ps->vliw_load_stall += wait;
1731	  if (TRACE_INSN_P (cpu))
1732	    sprintf (hazard_name, "Data hazard for gr%d:", in_GR);
1733	}
1734    }
1735}
1736
1737void
1738load_wait_for_FRdouble (SIM_CPU *cpu, INT in_FR)
1739{
1740  if (in_FR >= 0)
1741    {
1742      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1743      int *fr;
1744      int wait = 0;
1745      while (load_pending_for_register (cpu, in_FR, 2/*words*/, REGTYPE_FR))
1746	{
1747	  frv_model_advance_cycles (cpu, 1);
1748	  ++wait;
1749	}
1750      /* Post processing time may have been added to the registers'
1751	 latencies after the loads were processed. Account for that too.
1752      */
1753      fr = ps->fr_busy;
1754      if (fr[in_FR])
1755	{
1756	  wait += fr[in_FR];
1757	  frv_model_advance_cycles (cpu, fr[in_FR]);
1758	}
1759      if (in_FR < 63)
1760	{
1761	  if (fr[in_FR + 1])
1762	    {
1763	      wait += fr[in_FR + 1];
1764	      frv_model_advance_cycles (cpu, fr[in_FR + 1]);
1765	    }
1766	}
1767      /* Update the vliw_wait with the number of cycles we waited for the
1768	 load and any post-processing.  */
1769      if (wait)
1770	{
1771	  ps->vliw_wait += wait;
1772	  ps->vliw_load_stall += wait;
1773	  if (TRACE_INSN_P (cpu))
1774	    sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
1775	}
1776    }
1777}
1778
1779void
1780enforce_full_fr_latency (SIM_CPU *cpu, INT in_FR)
1781{
1782  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1783  ps->fr_busy_adjust [in_FR] = -1;
1784}
1785
1786/* Calculate how long the post processing for a floating point insn must
1787   wait for resources to become available.  */
1788int
1789post_wait_for_FR (SIM_CPU *cpu, INT in_FR)
1790{
1791  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1792  int *fr = ps->fr_busy;
1793
1794  if (in_FR >= 0 && fr[in_FR] > ps->post_wait)
1795    {
1796      ps->post_wait = fr[in_FR];
1797      if (TRACE_INSN_P (cpu))
1798	sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
1799    }
1800}
1801
1802/* Calculate how long the post processing for a floating point insn must
1803   wait for resources to become available.  */
1804int
1805post_wait_for_FRdouble (SIM_CPU *cpu, INT in_FR)
1806{
1807  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1808  int *fr = ps->fr_busy;
1809
1810  if (in_FR >= 0)
1811    {
1812      if (fr[in_FR] > ps->post_wait)
1813	{
1814	  ps->post_wait = fr[in_FR];
1815	  if (TRACE_INSN_P (cpu))
1816	    sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
1817	}
1818      if (in_FR < 63 && fr[in_FR + 1] > ps->post_wait)
1819	{
1820	  ps->post_wait = fr[in_FR + 1];
1821	  if (TRACE_INSN_P (cpu))
1822	    sprintf (hazard_name, "Data hazard for fr%d:", in_FR + 1);
1823	}
1824    }
1825}
1826
1827int
1828post_wait_for_ACC (SIM_CPU *cpu, INT in_ACC)
1829{
1830  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1831  int *acc = ps->acc_busy;
1832
1833  if (in_ACC >= 0 && acc[in_ACC] > ps->post_wait)
1834    {
1835      ps->post_wait = acc[in_ACC];
1836      if (TRACE_INSN_P (cpu))
1837	sprintf (hazard_name, "Data hazard for acc%d:", in_ACC);
1838    }
1839}
1840
1841int
1842post_wait_for_CCR (SIM_CPU *cpu, INT in_CCR)
1843{
1844  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1845  int *ccr = ps->ccr_busy;
1846
1847  if (in_CCR >= 0 && ccr[in_CCR] > ps->post_wait)
1848    {
1849      ps->post_wait = ccr[in_CCR];
1850      if (TRACE_INSN_P (cpu))
1851	{
1852	  if (in_CCR > 3)
1853	    sprintf (hazard_name, "Data hazard for icc%d:", in_CCR - 4);
1854	  else
1855	    sprintf (hazard_name, "Data hazard for fcc%d:", in_CCR);
1856	}
1857    }
1858}
1859
1860int
1861post_wait_for_SPR (SIM_CPU *cpu, INT in_SPR)
1862{
1863  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1864  int *spr = ps->spr_busy;
1865
1866  if (in_SPR >= 0 && spr[in_SPR] > ps->post_wait)
1867    {
1868      ps->post_wait = spr[in_SPR];
1869      if (TRACE_INSN_P (cpu))
1870	sprintf (hazard_name, "Data hazard for spr[%d]:", in_SPR);
1871    }
1872}
1873
1874int
1875post_wait_for_fdiv (SIM_CPU *cpu, INT slot)
1876{
1877  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1878  int *fdiv = ps->fdiv_busy;
1879
1880  /* Multiple floating point divisions in the same slot need only wait 1
1881     extra cycle.  */
1882  if (fdiv[slot] > 0 && 1 > ps->post_wait)
1883    {
1884      ps->post_wait = 1;
1885      if (TRACE_INSN_P (cpu))
1886	{
1887	  sprintf (hazard_name, "Resource hazard for floating point division in slot F%d:", slot);
1888	}
1889    }
1890}
1891
1892int
1893post_wait_for_fsqrt (SIM_CPU *cpu, INT slot)
1894{
1895  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1896  int *fsqrt = ps->fsqrt_busy;
1897
1898  /* Multiple floating point square roots in the same slot need only wait 1
1899     extra cycle.  */
1900  if (fsqrt[slot] > 0 && 1 > ps->post_wait)
1901    {
1902      ps->post_wait = 1;
1903      if (TRACE_INSN_P (cpu))
1904	{
1905	  sprintf (hazard_name, "Resource hazard for square root in slot F%d:", slot);
1906	}
1907    }
1908}
1909
1910int
1911post_wait_for_float (SIM_CPU *cpu, INT slot)
1912{
1913  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1914  int *flt = ps->float_busy;
1915
1916  /* Multiple floating point square roots in the same slot need only wait 1
1917     extra cycle.  */
1918  if (flt[slot] > ps->post_wait)
1919    {
1920      ps->post_wait = flt[slot];
1921      if (TRACE_INSN_P (cpu))
1922	{
1923	  sprintf (hazard_name, "Resource hazard for floating point unit in slot F%d:", slot);
1924	}
1925    }
1926}
1927
1928int
1929post_wait_for_media (SIM_CPU *cpu, INT slot)
1930{
1931  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1932  int *media = ps->media_busy;
1933
1934  /* Multiple floating point square roots in the same slot need only wait 1
1935     extra cycle.  */
1936  if (media[slot] > ps->post_wait)
1937    {
1938      ps->post_wait = media[slot];
1939      if (TRACE_INSN_P (cpu))
1940	{
1941	  sprintf (hazard_name, "Resource hazard for media unit in slot M%d:", slot);
1942	}
1943    }
1944}
1945
1946/* Print cpu-specific profile information.  */
1947#define COMMAS(n) sim_add_commas (comma_buf, sizeof (comma_buf), (n))
1948
1949static void
1950print_cache (SIM_CPU *cpu, FRV_CACHE *cache, const char *cache_name)
1951{
1952  SIM_DESC sd = CPU_STATE (cpu);
1953
1954  if (cache != NULL)
1955    {
1956      char comma_buf[20];
1957      unsigned accesses;
1958
1959      sim_io_printf (sd, "  %s Cache\n\n", cache_name);
1960      accesses = cache->statistics.accesses;
1961      sim_io_printf (sd, "    Total accesses:  %s\n", COMMAS (accesses));
1962      if (accesses != 0)
1963	{
1964	  float rate;
1965	  unsigned hits = cache->statistics.hits;
1966	  sim_io_printf (sd, "    Hits:            %s\n", COMMAS (hits));
1967	  rate = (float)hits / accesses;
1968	  sim_io_printf (sd, "    Hit rate:        %.2f%%\n", rate * 100);
1969	}
1970    }
1971  else
1972    sim_io_printf (sd, "  Model %s has no %s cache\n",
1973		   MODEL_NAME (CPU_MODEL (cpu)), cache_name);
1974
1975  sim_io_printf (sd, "\n");
1976}
1977
1978/* This table must correspond to the UNIT_ATTR table in
1979   opcodes/frv-desc.h. Only the units up to UNIT_C need be
1980   listed since the others cannot occur after mapping.  */
1981static char *
1982slot_names[] =
1983{
1984  "none",
1985  "I0", "I1", "I01", "I2", "I3", "IALL",
1986  "FM0", "FM1", "FM01", "FM2", "FM3", "FMALL", "FMLOW",
1987  "B0", "B1", "B01",
1988  "C"
1989};
1990
1991static void
1992print_parallel (SIM_CPU *cpu, int verbose)
1993{
1994  SIM_DESC sd = CPU_STATE (cpu);
1995  PROFILE_DATA *p = CPU_PROFILE_DATA (cpu);
1996  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1997  unsigned total, vliw;
1998  char comma_buf[20];
1999  float average;
2000
2001  sim_io_printf (sd, "Model %s Parallelization\n\n",
2002		 MODEL_NAME (CPU_MODEL (cpu)));
2003
2004  total = PROFILE_TOTAL_INSN_COUNT (p);
2005  sim_io_printf (sd, "  Total instructions:           %s\n", COMMAS (total));
2006  vliw = ps->vliw_insns;
2007  sim_io_printf (sd, "  VLIW instructions:            %s\n", COMMAS (vliw));
2008  average = (float)total / vliw;
2009  sim_io_printf (sd, "  Average VLIW length:          %.2f\n", average);
2010  average = (float)PROFILE_MODEL_TOTAL_CYCLES (p) / vliw;
2011  sim_io_printf (sd, "  Cycles per VLIW instruction:  %.2f\n", average);
2012  average = (float)total / PROFILE_MODEL_TOTAL_CYCLES (p);
2013  sim_io_printf (sd, "  Instructions per cycle:       %.2f\n", average);
2014
2015  if (verbose)
2016    {
2017      int i;
2018      int max_val = 0;
2019      int max_name_len = 0;
2020      for (i = UNIT_NIL + 1; i < UNIT_NUM_UNITS; ++i)
2021	{
2022	  if (INSNS_IN_SLOT (i))
2023	    {
2024	      int len;
2025	      if (INSNS_IN_SLOT (i) > max_val)
2026		max_val = INSNS_IN_SLOT (i);
2027	      len = strlen (slot_names[i]);
2028	      if (len > max_name_len)
2029		max_name_len = len;
2030	    }
2031	}
2032      if (max_val > 0)
2033	{
2034	  sim_io_printf (sd, "\n");
2035	  sim_io_printf (sd, "  Instructions per slot:\n");
2036	  sim_io_printf (sd, "\n");
2037	  for (i = UNIT_NIL + 1; i < UNIT_NUM_UNITS; ++i)
2038	    {
2039	      if (INSNS_IN_SLOT (i) != 0)
2040		{
2041		  sim_io_printf (sd, "  %*s: %*s: ",
2042				 max_name_len, slot_names[i],
2043				 max_val < 10000 ? 5 : 10,
2044				 COMMAS (INSNS_IN_SLOT (i)));
2045		  sim_profile_print_bar (sd, PROFILE_HISTOGRAM_WIDTH,
2046					 INSNS_IN_SLOT (i),
2047					 max_val);
2048		  sim_io_printf (sd, "\n");
2049		}
2050	    }
2051	} /* details to print */
2052    } /* verbose */
2053
2054  sim_io_printf (sd, "\n");
2055}
2056
2057void
2058frv_profile_info (SIM_CPU *cpu, int verbose)
2059{
2060  /* FIXME: Need to add smp support.  */
2061  PROFILE_DATA *p = CPU_PROFILE_DATA (cpu);
2062
2063#if WITH_PROFILE_PARALLEL_P
2064  if (PROFILE_FLAGS (p) [PROFILE_PARALLEL_IDX])
2065    print_parallel (cpu, verbose);
2066#endif
2067
2068#if WITH_PROFILE_CACHE_P
2069  if (PROFILE_FLAGS (p) [PROFILE_CACHE_IDX])
2070    {
2071      SIM_DESC sd = CPU_STATE (cpu);
2072      sim_io_printf (sd, "Model %s Cache Statistics\n\n",
2073		     MODEL_NAME (CPU_MODEL (cpu)));
2074      print_cache (cpu, CPU_INSN_CACHE (cpu), "Instruction");
2075      print_cache (cpu, CPU_DATA_CACHE (cpu), "Data");
2076    }
2077#endif /* WITH_PROFILE_CACHE_P */
2078}
2079
2080/* A hack to get registers referenced for profiling.  */
2081SI frv_ref_SI (SI ref) {return ref;}
2082#endif /* WITH_PROFILE_MODEL_P */
2083