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