]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/frv/profile.c
Update years in copyright notice for the GDB files.
[thirdparty/binutils-gdb.git] / sim / frv / profile.c
CommitLineData
b34f6357
DB
1/* frv simulator machine independent profiling code.
2
8acc9f48 3 Copyright (C) 1998-2013 Free Software Foundation, Inc.
b34f6357
DB
4 Contributed by Red Hat
5
6This file is part of the GNU simulators.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
4744ac1b
JB
10the Free Software Foundation; either version 3 of the License, or
11(at your option) any later version.
b34f6357
DB
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
4744ac1b
JB
18You should have received a copy of the GNU General Public License
19along with this program. If not, see <http://www.gnu.org/licenses/>.
b34f6357
DB
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"
e930b1f5 33#include "profile-fr550.h"
b34f6357
DB
34
35static void
36reset_gr_flags (SIM_CPU *cpu, INT gr)
37{
38 SIM_DESC sd = CPU_STATE (cpu);
676a64f4
RS
39 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400
40 || STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450)
b34f6357
DB
41 fr400_reset_gr_flags (cpu, gr);
42 /* Other machines have no gr flags right now. */
43}
44
45static void
46reset_fr_flags (SIM_CPU *cpu, INT fr)
47{
48 SIM_DESC sd = CPU_STATE (cpu);
676a64f4
RS
49 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400
50 || STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450)
b34f6357
DB
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
56static void
57reset_acc_flags (SIM_CPU *cpu, INT acc)
58{
59 SIM_DESC sd = CPU_STATE (cpu);
676a64f4
RS
60 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400
61 || STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450)
b34f6357
DB
62 fr400_reset_acc_flags (cpu, acc);
63 /* Other machines have no acc flags right now. */
64}
65
66static void
67reset_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
75void
76set_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
86void
87set_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
96int
97use_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. */
108enum FRV_INSN_MODELING model_insn = FRV_INSN_NO_MODELING;
109
110/* static buffer for the name of the currently most restrictive hazard. */
111static char hazard_name[100] = "";
112
113/* Print information about the wait applied to an entire VLIW insn. */
114FRV_INSN_FETCH_BUFFER frv_insn_fetch_buffer[]
115= {
116 {1, NO_REQNO}, {1, NO_REQNO} /* init with impossible address. */
117};
118
119enum 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. */
131typedef 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 */
149struct
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. */
159void
160request_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. */
198void
199request_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. */
227void
228request_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. */
256void
257request_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. */
288void
289request_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
313static void
314submit_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. */
342static void
343activate_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 */
361int
362load_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. */
396static int
397flush_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
417static void
418remove_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). */
454static void
455copy_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
557static int
558request_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. */
599static void
600run_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
651static void
652apply_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. */
674static void
675update_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;
e930b1f5
DB
683 int *flt;
684 int *media;
b34f6357
DB
685 int *ccr;
686 int *gr = ps->gr_busy;
687 int *fr = ps->fr_busy;
688 int *acc = ps->acc_busy;
153431d6 689 int *spr;
b34f6357
DB
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 }
153431d6
DB
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 }
b34f6357
DB
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 }
e930b1f5
DB
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 }
b34f6357
DB
776}
777
778/* Print information about the wait for the given number of cycles. */
779void
780frv_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
790void
791trace_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. */
801void
802frv_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
810void
811handle_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. */
824static void
825update_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;
153431d6 834 int *spr_lat;
b34f6357
DB
835 int *ccr;
836 int *gr = ps->gr_busy;
837 int *fr = ps->fr_busy;
838 int *acc = ps->acc_busy;
153431d6 839 int *spr;
b34f6357
DB
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 }
153431d6
DB
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 }
b34f6357
DB
886}
887
888/* Run the caches until all pending cache flushes are complete. */
889static void
890wait_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. */
909void
910frvbf_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:
676a64f4 931 case bfd_mach_fr450:
b34f6357
DB
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;
e930b1f5
DB
937 case bfd_mach_fr550:
938 fr550_model_insn_before (cpu, first_p);
939 break;
b34f6357
DB
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
953void
954frvbf_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:
676a64f4 998 case bfd_mach_fr450:
b34f6357
DB
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;
e930b1f5
DB
1004 case bfd_mach_fr550:
1005 fr550_model_insn_after (cpu, last_p, cycles);
1006 break;
b34f6357
DB
1007 default:
1008 break;
1009 }
1010}
1011
1012USI
1013frvbf_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. */
1022void
1023update_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
1034void
1035decrease_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. */
1046void
1047update_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
1060void
1061update_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
1080void
1081update_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
1102void
1103update_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. */
1109void
1110update_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. */
1122void
1123update_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
1136void
1137update_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
1156void
1157update_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. */
1180void
1c453cd6
DB
1181update_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
1199void
1200update_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. */
1226void
b34f6357
DB
1227update_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
1c453cd6
DB
1239/* Top up the post-processing time of the given SPR by the given number of
1240 cycles. */
1241void
1242update_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
b34f6357
DB
1254void
1255decrease_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
1c453cd6
DB
1268void
1269increase_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
1279void
1280enforce_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
b34f6357
DB
1286void
1287decrease_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
1300void
1301increase_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. */
1312void
1313update_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. */
1325void
1326update_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
153431d6
DB
1337/* Top up the latency of the given SPR by the given number of cycles. */
1338void
1339update_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
b34f6357
DB
1350/* Top up the latency of the given integer division resource by the given
1351 number of cycles. */
1352void
1353update_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. */
1363void
1364update_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. */
1374void
1375update_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
e930b1f5
DB
1384/* Set the latency of the given resource to the given number of cycles. */
1385void
1386update_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
1395void
1396update_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
b34f6357
DB
1405/* Set the branch penalty to the given number of cycles. */
1406void
1407update_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. */
1417void
1418vliw_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. */
1434void
1435vliw_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. */
1460void
1461vliw_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. */
1477void
1478vliw_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. */
1503void
1504vliw_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. */
1525void
1526vliw_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
153431d6
DB
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. */
1542void
1543vliw_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
b34f6357
DB
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*/
1560void
1561vliw_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*/
1580void
1581vliw_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 {
1c453cd6 1591 sprintf (hazard_name, "Resource hazard for floating point division in slot F%d:", in_resource);
b34f6357
DB
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*/
1600void
1601vliw_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 {
1c453cd6 1611 sprintf (hazard_name, "Resource hazard for square root in slot F%d:", in_resource);
b34f6357
DB
1612 }
1613 ps->vliw_wait = r[in_resource];
1614 }
1615}
1616
e930b1f5
DB
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*/
1620void
1621vliw_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*/
1640void
1641vliw_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
b34f6357
DB
1657/* Run the caches until all requests for the given register(s) are satisfied. */
1658void
1659load_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
1680void
1681load_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
1714void
1715load_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
1736void
1737load_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
1778void
1779enforce_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. */
1787int
1788post_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. */
1803int
1804post_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
1826int
1827post_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
1840int
1841post_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
1c453cd6
DB
1859int
1860post_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
b34f6357
DB
1873int
1874post_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
1891int
1892post_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
e930b1f5
DB
1909int
1910post_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
1927int
1928post_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
b34f6357
DB
1945/* Print cpu-specific profile information. */
1946#define COMMAS(n) sim_add_commas (comma_buf, sizeof (comma_buf), (n))
1947
1948static void
1949print_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
ba9c4053
DB
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. */
b34f6357
DB
1980static char *
1981slot_names[] =
1982{
1983 "none",
e930b1f5
DB
1984 "I0", "I1", "I01", "I2", "I3", "IALL",
1985 "FM0", "FM1", "FM01", "FM2", "FM3", "FMALL", "FMLOW",
b34f6357
DB
1986 "B0", "B1", "B01",
1987 "C"
1988};
1989
1990static void
1991print_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 {
ba9c4053
DB
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 }
b34f6357
DB
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)));
f9bdfd29 2044 sim_profile_print_bar (sd, cpu, PROFILE_HISTOGRAM_WIDTH,
b34f6357
DB
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
2056void
2057frv_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. */
2080SI frv_ref_SI (SI ref) {return ref;}
2081#endif /* WITH_PROFILE_MODEL_P */