xref: /netbsd-src/external/gpl3/gdb/dist/sim/frv/profile.c (revision 854b025f2fdbc2b8be5b6915e0337cc556c8c54d)
14e98e3e1Schristos /* frv simulator machine independent profiling code.
24e98e3e1Schristos 
3*854b025fSchristos    Copyright (C) 1998-2024 Free Software Foundation, Inc.
44e98e3e1Schristos    Contributed by Red Hat
54e98e3e1Schristos 
64e98e3e1Schristos This file is part of the GNU simulators.
74e98e3e1Schristos 
84e98e3e1Schristos This program is free software; you can redistribute it and/or modify
94e98e3e1Schristos it under the terms of the GNU General Public License as published by
104e98e3e1Schristos the Free Software Foundation; either version 3 of the License, or
114e98e3e1Schristos (at your option) any later version.
124e98e3e1Schristos 
134e98e3e1Schristos This program is distributed in the hope that it will be useful,
144e98e3e1Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
154e98e3e1Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
164e98e3e1Schristos GNU General Public License for more details.
174e98e3e1Schristos 
184e98e3e1Schristos You should have received a copy of the GNU General Public License
194b169a6bSchristos along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
204e98e3e1Schristos 
214b169a6bSchristos /* This must come before any other includes.  */
224b169a6bSchristos #include "defs.h"
234b169a6bSchristos 
244e98e3e1Schristos #define WANT_CPU
254e98e3e1Schristos #define WANT_CPU_FRVBF
264e98e3e1Schristos 
274e98e3e1Schristos #include "sim-main.h"
284e98e3e1Schristos #include "bfd.h"
294b169a6bSchristos #include <stdlib.h>
304e98e3e1Schristos 
314e98e3e1Schristos #if WITH_PROFILE_MODEL_P
324e98e3e1Schristos 
334e98e3e1Schristos #include "profile.h"
344e98e3e1Schristos #include "profile-fr400.h"
354e98e3e1Schristos #include "profile-fr500.h"
364e98e3e1Schristos #include "profile-fr550.h"
374e98e3e1Schristos 
384e98e3e1Schristos static void
394e98e3e1Schristos reset_gr_flags (SIM_CPU *cpu, INT gr)
404e98e3e1Schristos {
414e98e3e1Schristos   SIM_DESC sd = CPU_STATE (cpu);
424e98e3e1Schristos   if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400
434e98e3e1Schristos       || STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450)
444e98e3e1Schristos     fr400_reset_gr_flags (cpu, gr);
454e98e3e1Schristos   /* Other machines have no gr flags right now.  */
464e98e3e1Schristos }
474e98e3e1Schristos 
484e98e3e1Schristos static void
494e98e3e1Schristos reset_fr_flags (SIM_CPU *cpu, INT fr)
504e98e3e1Schristos {
514e98e3e1Schristos   SIM_DESC sd = CPU_STATE (cpu);
524e98e3e1Schristos   if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400
534e98e3e1Schristos       || STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450)
544e98e3e1Schristos     fr400_reset_fr_flags (cpu, fr);
554e98e3e1Schristos   else if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr500)
564e98e3e1Schristos     fr500_reset_fr_flags (cpu, fr);
574e98e3e1Schristos }
584e98e3e1Schristos 
594e98e3e1Schristos static void
604e98e3e1Schristos reset_acc_flags (SIM_CPU *cpu, INT acc)
614e98e3e1Schristos {
624e98e3e1Schristos   SIM_DESC sd = CPU_STATE (cpu);
634e98e3e1Schristos   if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400
644e98e3e1Schristos       || STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450)
654e98e3e1Schristos     fr400_reset_acc_flags (cpu, acc);
664e98e3e1Schristos   /* Other machines have no acc flags right now.  */
674e98e3e1Schristos }
684e98e3e1Schristos 
694e98e3e1Schristos static void
704e98e3e1Schristos reset_cc_flags (SIM_CPU *cpu, INT cc)
714e98e3e1Schristos {
724e98e3e1Schristos   SIM_DESC sd = CPU_STATE (cpu);
734e98e3e1Schristos   if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr500)
744e98e3e1Schristos     fr500_reset_cc_flags (cpu, cc);
754e98e3e1Schristos   /* Other machines have no cc flags.  */
764e98e3e1Schristos }
774e98e3e1Schristos 
784e98e3e1Schristos void
794e98e3e1Schristos set_use_is_gr_complex (SIM_CPU *cpu, INT gr)
804e98e3e1Schristos {
814e98e3e1Schristos   if (gr != -1)
824e98e3e1Schristos     {
834e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
844e98e3e1Schristos       reset_gr_flags (cpu, gr);
854e98e3e1Schristos       ps->cur_gr_complex |= (((DI)1) << gr);
864e98e3e1Schristos     }
874e98e3e1Schristos }
884e98e3e1Schristos 
894e98e3e1Schristos void
904e98e3e1Schristos set_use_not_gr_complex (SIM_CPU *cpu, INT gr)
914e98e3e1Schristos {
924e98e3e1Schristos   if (gr != -1)
934e98e3e1Schristos     {
944e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
954e98e3e1Schristos       ps->cur_gr_complex &= ~(((DI)1) << gr);
964e98e3e1Schristos     }
974e98e3e1Schristos }
984e98e3e1Schristos 
994e98e3e1Schristos int
1004e98e3e1Schristos use_is_gr_complex (SIM_CPU *cpu, INT gr)
1014e98e3e1Schristos {
1024e98e3e1Schristos   if (gr != -1)
1034e98e3e1Schristos     {
1044e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
1054e98e3e1Schristos       return ps->cur_gr_complex & (((DI)1) << gr);
1064e98e3e1Schristos     }
1074e98e3e1Schristos   return 0;
1084e98e3e1Schristos }
1094e98e3e1Schristos 
1104e98e3e1Schristos /* Globals flag indicates whether this insn is being modeled.  */
1114e98e3e1Schristos enum FRV_INSN_MODELING model_insn = FRV_INSN_NO_MODELING;
1124e98e3e1Schristos 
1134e98e3e1Schristos /* static buffer for the name of the currently most restrictive hazard.  */
1144e98e3e1Schristos static char hazard_name[100] = "";
1154e98e3e1Schristos 
1164e98e3e1Schristos /* Print information about the wait applied to an entire VLIW insn.  */
1174e98e3e1Schristos FRV_INSN_FETCH_BUFFER frv_insn_fetch_buffer[]
1184e98e3e1Schristos = {
1194e98e3e1Schristos   {1, NO_REQNO}, {1, NO_REQNO} /* init with impossible address.  */
1204e98e3e1Schristos };
1214e98e3e1Schristos 
1224e98e3e1Schristos enum cache_request
1234e98e3e1Schristos {
1244e98e3e1Schristos   cache_load,
1254e98e3e1Schristos   cache_invalidate,
1264e98e3e1Schristos   cache_flush,
1274e98e3e1Schristos   cache_preload,
1284e98e3e1Schristos   cache_unlock
1294e98e3e1Schristos };
1304e98e3e1Schristos 
1314e98e3e1Schristos /* A queue of load requests from the data cache. Use to keep track of loads
1324e98e3e1Schristos    which are still pending.  */
1334e98e3e1Schristos /* TODO -- some of these are mutually exclusive and can use a union.  */
1344e98e3e1Schristos typedef struct
1354e98e3e1Schristos {
1364e98e3e1Schristos   FRV_CACHE *cache;
1374e98e3e1Schristos   unsigned reqno;
1384e98e3e1Schristos   SI address;
1394e98e3e1Schristos   int length;
1404e98e3e1Schristos   int is_signed;
1414e98e3e1Schristos   int regnum;
1424e98e3e1Schristos   int cycles;
1434e98e3e1Schristos   int regtype;
1444e98e3e1Schristos   int lock;
1454e98e3e1Schristos   int all;
1464e98e3e1Schristos   int slot;
1474e98e3e1Schristos   int active;
1484e98e3e1Schristos   enum cache_request request;
1494e98e3e1Schristos } CACHE_QUEUE_ELEMENT;
1504e98e3e1Schristos 
1514e98e3e1Schristos #define CACHE_QUEUE_SIZE 64 /* TODO -- make queue dynamic */
1524e98e3e1Schristos struct
1534e98e3e1Schristos {
1544e98e3e1Schristos   unsigned reqno;
1554e98e3e1Schristos   int ix;
1564e98e3e1Schristos   CACHE_QUEUE_ELEMENT q[CACHE_QUEUE_SIZE];
1574e98e3e1Schristos } cache_queue = {0, 0};
1584e98e3e1Schristos 
1594e98e3e1Schristos /* Queue a request for a load from the cache. The load will be queued as
1604e98e3e1Schristos    'inactive' and will be requested after the given number
1614e98e3e1Schristos    of cycles have passed from the point the load is activated.  */
1624e98e3e1Schristos void
1634e98e3e1Schristos request_cache_load (SIM_CPU *cpu, INT regnum, int regtype, int cycles)
1644e98e3e1Schristos {
1654e98e3e1Schristos   CACHE_QUEUE_ELEMENT *q;
1664e98e3e1Schristos   FRV_VLIW *vliw;
1674e98e3e1Schristos   int slot;
1684e98e3e1Schristos 
1694e98e3e1Schristos   /* For a conditional load which was not executed, CPU_LOAD_LENGTH will be
1704e98e3e1Schristos      zero.  */
1714e98e3e1Schristos   if (CPU_LOAD_LENGTH (cpu) == 0)
1724e98e3e1Schristos     return;
1734e98e3e1Schristos 
1744e98e3e1Schristos   if (cache_queue.ix >= CACHE_QUEUE_SIZE)
1754e98e3e1Schristos     abort (); /* TODO: Make the queue dynamic */
1764e98e3e1Schristos 
1774e98e3e1Schristos   q = & cache_queue.q[cache_queue.ix];
1784e98e3e1Schristos   ++cache_queue.ix;
1794e98e3e1Schristos 
1804e98e3e1Schristos   q->reqno = cache_queue.reqno++;
1814e98e3e1Schristos   q->request = cache_load;
1824e98e3e1Schristos   q->cache = CPU_DATA_CACHE (cpu);
1834e98e3e1Schristos   q->address = CPU_LOAD_ADDRESS (cpu);
1844e98e3e1Schristos   q->length = CPU_LOAD_LENGTH (cpu);
1854e98e3e1Schristos   q->is_signed = CPU_LOAD_SIGNED (cpu);
1864e98e3e1Schristos   q->regnum = regnum;
1874e98e3e1Schristos   q->regtype = regtype;
1884e98e3e1Schristos   q->cycles = cycles;
1894e98e3e1Schristos   q->active = 0;
1904e98e3e1Schristos 
1914e98e3e1Schristos   vliw = CPU_VLIW (cpu);
1924e98e3e1Schristos   slot = vliw->next_slot - 1;
1934e98e3e1Schristos   q->slot = (*vliw->current_vliw)[slot];
1944e98e3e1Schristos 
1954e98e3e1Schristos   CPU_LOAD_LENGTH (cpu) = 0;
1964e98e3e1Schristos }
1974e98e3e1Schristos 
1984e98e3e1Schristos /* Queue a request to flush the cache. The request will be queued as
1994e98e3e1Schristos    'inactive' and will be requested after the given number
2004e98e3e1Schristos    of cycles have passed from the point the request is activated.  */
2014e98e3e1Schristos void
2024e98e3e1Schristos request_cache_flush (SIM_CPU *cpu, FRV_CACHE *cache, int cycles)
2034e98e3e1Schristos {
2044e98e3e1Schristos   CACHE_QUEUE_ELEMENT *q;
2054e98e3e1Schristos   FRV_VLIW *vliw;
2064e98e3e1Schristos   int slot;
2074e98e3e1Schristos 
2084e98e3e1Schristos   if (cache_queue.ix >= CACHE_QUEUE_SIZE)
2094e98e3e1Schristos     abort (); /* TODO: Make the queue dynamic */
2104e98e3e1Schristos 
2114e98e3e1Schristos   q = & cache_queue.q[cache_queue.ix];
2124e98e3e1Schristos   ++cache_queue.ix;
2134e98e3e1Schristos 
2144e98e3e1Schristos   q->reqno = cache_queue.reqno++;
2154e98e3e1Schristos   q->request = cache_flush;
2164e98e3e1Schristos   q->cache = cache;
2174e98e3e1Schristos   q->address = CPU_LOAD_ADDRESS (cpu);
2184e98e3e1Schristos   q->all = CPU_PROFILE_STATE (cpu)->all_cache_entries;
2194e98e3e1Schristos   q->cycles = cycles;
2204e98e3e1Schristos   q->active = 0;
2214e98e3e1Schristos 
2224e98e3e1Schristos   vliw = CPU_VLIW (cpu);
2234e98e3e1Schristos   slot = vliw->next_slot - 1;
2244e98e3e1Schristos   q->slot = (*vliw->current_vliw)[slot];
2254e98e3e1Schristos }
2264e98e3e1Schristos 
2274e98e3e1Schristos /* Queue a request to invalidate the cache. The request will be queued as
2284e98e3e1Schristos    'inactive' and will be requested after the given number
2294e98e3e1Schristos    of cycles have passed from the point the request is activated.  */
2304e98e3e1Schristos void
2314e98e3e1Schristos request_cache_invalidate (SIM_CPU *cpu, FRV_CACHE *cache, int cycles)
2324e98e3e1Schristos {
2334e98e3e1Schristos   CACHE_QUEUE_ELEMENT *q;
2344e98e3e1Schristos   FRV_VLIW *vliw;
2354e98e3e1Schristos   int slot;
2364e98e3e1Schristos 
2374e98e3e1Schristos   if (cache_queue.ix >= CACHE_QUEUE_SIZE)
2384e98e3e1Schristos     abort (); /* TODO: Make the queue dynamic */
2394e98e3e1Schristos 
2404e98e3e1Schristos   q = & cache_queue.q[cache_queue.ix];
2414e98e3e1Schristos   ++cache_queue.ix;
2424e98e3e1Schristos 
2434e98e3e1Schristos   q->reqno = cache_queue.reqno++;
2444e98e3e1Schristos   q->request = cache_invalidate;
2454e98e3e1Schristos   q->cache = cache;
2464e98e3e1Schristos   q->address = CPU_LOAD_ADDRESS (cpu);
2474e98e3e1Schristos   q->all = CPU_PROFILE_STATE (cpu)->all_cache_entries;
2484e98e3e1Schristos   q->cycles = cycles;
2494e98e3e1Schristos   q->active = 0;
2504e98e3e1Schristos 
2514e98e3e1Schristos   vliw = CPU_VLIW (cpu);
2524e98e3e1Schristos   slot = vliw->next_slot - 1;
2534e98e3e1Schristos   q->slot = (*vliw->current_vliw)[slot];
2544e98e3e1Schristos }
2554e98e3e1Schristos 
2564e98e3e1Schristos /* Queue a request to preload the cache. The request will be queued as
2574e98e3e1Schristos    'inactive' and will be requested after the given number
2584e98e3e1Schristos    of cycles have passed from the point the request is activated.  */
2594e98e3e1Schristos void
2604e98e3e1Schristos request_cache_preload (SIM_CPU *cpu, FRV_CACHE *cache, int cycles)
2614e98e3e1Schristos {
2624e98e3e1Schristos   CACHE_QUEUE_ELEMENT *q;
2634e98e3e1Schristos   FRV_VLIW *vliw;
2644e98e3e1Schristos   int slot;
2654e98e3e1Schristos 
2664e98e3e1Schristos   if (cache_queue.ix >= CACHE_QUEUE_SIZE)
2674e98e3e1Schristos     abort (); /* TODO: Make the queue dynamic */
2684e98e3e1Schristos 
2694e98e3e1Schristos   q = & cache_queue.q[cache_queue.ix];
2704e98e3e1Schristos   ++cache_queue.ix;
2714e98e3e1Schristos 
2724e98e3e1Schristos   q->reqno = cache_queue.reqno++;
2734e98e3e1Schristos   q->request = cache_preload;
2744e98e3e1Schristos   q->cache = cache;
2754e98e3e1Schristos   q->address = CPU_LOAD_ADDRESS (cpu);
2764e98e3e1Schristos   q->length = CPU_LOAD_LENGTH (cpu);
2774e98e3e1Schristos   q->lock = CPU_LOAD_LOCK (cpu);
2784e98e3e1Schristos   q->cycles = cycles;
2794e98e3e1Schristos   q->active = 0;
2804e98e3e1Schristos 
2814e98e3e1Schristos   vliw = CPU_VLIW (cpu);
2824e98e3e1Schristos   slot = vliw->next_slot - 1;
2834e98e3e1Schristos   q->slot = (*vliw->current_vliw)[slot];
2844e98e3e1Schristos 
2854e98e3e1Schristos   CPU_LOAD_LENGTH (cpu) = 0;
2864e98e3e1Schristos }
2874e98e3e1Schristos 
2884e98e3e1Schristos /* Queue a request to unlock the cache. The request will be queued as
2894e98e3e1Schristos    'inactive' and will be requested after the given number
2904e98e3e1Schristos    of cycles have passed from the point the request is activated.  */
2914e98e3e1Schristos void
2924e98e3e1Schristos request_cache_unlock (SIM_CPU *cpu, FRV_CACHE *cache, int cycles)
2934e98e3e1Schristos {
2944e98e3e1Schristos   CACHE_QUEUE_ELEMENT *q;
2954e98e3e1Schristos   FRV_VLIW *vliw;
2964e98e3e1Schristos   int slot;
2974e98e3e1Schristos 
2984e98e3e1Schristos   if (cache_queue.ix >= CACHE_QUEUE_SIZE)
2994e98e3e1Schristos     abort (); /* TODO: Make the queue dynamic */
3004e98e3e1Schristos 
3014e98e3e1Schristos   q = & cache_queue.q[cache_queue.ix];
3024e98e3e1Schristos   ++cache_queue.ix;
3034e98e3e1Schristos 
3044e98e3e1Schristos   q->reqno = cache_queue.reqno++;
3054e98e3e1Schristos   q->request = cache_unlock;
3064e98e3e1Schristos   q->cache = cache;
3074e98e3e1Schristos   q->address = CPU_LOAD_ADDRESS (cpu);
3084e98e3e1Schristos   q->cycles = cycles;
3094e98e3e1Schristos   q->active = 0;
3104e98e3e1Schristos 
3114e98e3e1Schristos   vliw = CPU_VLIW (cpu);
3124e98e3e1Schristos   slot = vliw->next_slot - 1;
3134e98e3e1Schristos   q->slot = (*vliw->current_vliw)[slot];
3144e98e3e1Schristos }
3154e98e3e1Schristos 
3164e98e3e1Schristos static void
3174e98e3e1Schristos submit_cache_request (CACHE_QUEUE_ELEMENT *q)
3184e98e3e1Schristos {
3194e98e3e1Schristos   switch (q->request)
3204e98e3e1Schristos     {
3214e98e3e1Schristos     case cache_load:
3224e98e3e1Schristos       frv_cache_request_load (q->cache, q->reqno, q->address, q->slot);
3234e98e3e1Schristos       break;
3244e98e3e1Schristos     case cache_flush:
3254e98e3e1Schristos       frv_cache_request_invalidate (q->cache, q->reqno, q->address, q->slot,
3264e98e3e1Schristos 				    q->all, 1/*flush*/);
3274e98e3e1Schristos       break;
3284e98e3e1Schristos     case cache_invalidate:
3294e98e3e1Schristos       frv_cache_request_invalidate (q->cache, q->reqno, q->address, q->slot,
3304e98e3e1Schristos 				   q->all, 0/*flush*/);
3314e98e3e1Schristos       break;
3324e98e3e1Schristos     case cache_preload:
3334e98e3e1Schristos       frv_cache_request_preload (q->cache, q->address, q->slot,
3344e98e3e1Schristos 				 q->length, q->lock);
3354e98e3e1Schristos       break;
3364e98e3e1Schristos     case cache_unlock:
3374e98e3e1Schristos       frv_cache_request_unlock (q->cache, q->address, q->slot);
3384e98e3e1Schristos       break;
3394e98e3e1Schristos     default:
3404e98e3e1Schristos       abort ();
3414e98e3e1Schristos     }
3424e98e3e1Schristos }
3434e98e3e1Schristos 
3444e98e3e1Schristos /* Activate all inactive load requests.  */
3454e98e3e1Schristos static void
3464e98e3e1Schristos activate_cache_requests (SIM_CPU *cpu)
3474e98e3e1Schristos {
3484e98e3e1Schristos   int i;
3494e98e3e1Schristos   for (i = 0; i < cache_queue.ix; ++i)
3504e98e3e1Schristos     {
3514e98e3e1Schristos       CACHE_QUEUE_ELEMENT *q = & cache_queue.q[i];
3524e98e3e1Schristos       if (! q->active)
3534e98e3e1Schristos 	{
3544e98e3e1Schristos 	  q->active = 1;
3554e98e3e1Schristos 	  /* Submit the request now if the cycle count is zero.  */
3564e98e3e1Schristos 	  if (q->cycles == 0)
3574e98e3e1Schristos 	    submit_cache_request (q);
3584e98e3e1Schristos 	}
3594e98e3e1Schristos     }
3604e98e3e1Schristos }
3614e98e3e1Schristos 
3624e98e3e1Schristos /* Check to see if a load is pending which affects the given register(s).
3634e98e3e1Schristos  */
3644e98e3e1Schristos int
3654e98e3e1Schristos load_pending_for_register (SIM_CPU *cpu, int regnum, int words, int regtype)
3664e98e3e1Schristos {
3674e98e3e1Schristos   int i;
3684e98e3e1Schristos   for (i = 0; i < cache_queue.ix; ++i)
3694e98e3e1Schristos     {
3704e98e3e1Schristos       CACHE_QUEUE_ELEMENT *q = & cache_queue.q[i];
3714e98e3e1Schristos 
3724e98e3e1Schristos       /* Must be the same kind of register.  */
3734e98e3e1Schristos       if (! q->active || q->request != cache_load || q->regtype != regtype)
3744e98e3e1Schristos 	continue;
3754e98e3e1Schristos 
3764e98e3e1Schristos       /* If the registers numbers are equal, then we have a match.  */
3774e98e3e1Schristos       if (q->regnum == regnum)
3784e98e3e1Schristos 	return 1; /* load pending */
3794e98e3e1Schristos 
3804e98e3e1Schristos       /* Check for overlap of a load with a multi-word register.  */
3814e98e3e1Schristos       if (regnum < q->regnum)
3824e98e3e1Schristos 	{
3834e98e3e1Schristos 	  if (regnum + words > q->regnum)
3844e98e3e1Schristos 	    return 1;
3854e98e3e1Schristos 	}
3864e98e3e1Schristos       /* Check for overlap of a multi-word load with the register.  */
3874e98e3e1Schristos       else
3884e98e3e1Schristos 	{
3894e98e3e1Schristos 	  int data_words = (q->length + sizeof (SI) - 1) / sizeof (SI);
3904e98e3e1Schristos 	  if (q->regnum + data_words > regnum)
3914e98e3e1Schristos 	    return 1;
3924e98e3e1Schristos 	}
3934e98e3e1Schristos     }
3944e98e3e1Schristos 
3954e98e3e1Schristos   return 0; /* no load pending */
3964e98e3e1Schristos }
3974e98e3e1Schristos 
3984e98e3e1Schristos /* Check to see if a cache flush pending which affects the given address.  */
3994e98e3e1Schristos static int
4004e98e3e1Schristos flush_pending_for_address (SIM_CPU *cpu, SI address)
4014e98e3e1Schristos {
4024e98e3e1Schristos   int line_mask = ~(CPU_DATA_CACHE (cpu)->line_size - 1);
4034e98e3e1Schristos   int i;
4044e98e3e1Schristos   for (i = 0; i < cache_queue.ix; ++i)
4054e98e3e1Schristos     {
4064e98e3e1Schristos       CACHE_QUEUE_ELEMENT *q = & cache_queue.q[i];
4074e98e3e1Schristos 
4084e98e3e1Schristos       /* Must be the same kind of request and active.  */
4094e98e3e1Schristos       if (! q->active || q->request != cache_flush)
4104e98e3e1Schristos 	continue;
4114e98e3e1Schristos 
4124e98e3e1Schristos       /* If the addresses are equal, then we have a match.  */
4134e98e3e1Schristos       if ((q->address & line_mask) == (address & line_mask))
4144e98e3e1Schristos 	return 1; /* flush pending */
4154e98e3e1Schristos     }
4164e98e3e1Schristos 
4174e98e3e1Schristos   return 0; /* no flush pending */
4184e98e3e1Schristos }
4194e98e3e1Schristos 
4204e98e3e1Schristos static void
4214e98e3e1Schristos remove_cache_queue_element (SIM_CPU *cpu, int i)
4224e98e3e1Schristos {
4234e98e3e1Schristos   /* If we are removing the load of a FR register, then remember which one(s).
4244e98e3e1Schristos    */
4254e98e3e1Schristos   CACHE_QUEUE_ELEMENT q = cache_queue.q[i];
4264e98e3e1Schristos 
4274e98e3e1Schristos   for (--cache_queue.ix; i < cache_queue.ix; ++i)
4284e98e3e1Schristos     cache_queue.q[i] = cache_queue.q[i + 1];
4294e98e3e1Schristos 
4304e98e3e1Schristos   /* If we removed a load of a FR register, check to see if any other loads
4314e98e3e1Schristos      of that register is still queued. If not, then apply the queued post
4324e98e3e1Schristos      processing time of that register to its latency.  Also apply
4334e98e3e1Schristos      1 extra cycle of latency to the register since it was a floating point
4344e98e3e1Schristos      load.  */
4354e98e3e1Schristos   if (q.request == cache_load && q.regtype != REGTYPE_NONE)
4364e98e3e1Schristos     {
4374e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
4384e98e3e1Schristos       int data_words = (q.length + sizeof (SI) - 1) / sizeof (SI);
4394e98e3e1Schristos       int j;
4404e98e3e1Schristos       for (j = 0; j < data_words; ++j)
4414e98e3e1Schristos 	{
4424e98e3e1Schristos 	  int regnum = q.regnum + j;
4434e98e3e1Schristos 	  if (! load_pending_for_register (cpu, regnum, 1, q.regtype))
4444e98e3e1Schristos 	    {
4454e98e3e1Schristos 	      if (q.regtype == REGTYPE_FR)
4464e98e3e1Schristos 		{
4474e98e3e1Schristos 		  int *fr = ps->fr_busy;
4484e98e3e1Schristos 		  fr[regnum] += 1 + ps->fr_ptime[regnum];
4494e98e3e1Schristos 		  ps->fr_ptime[regnum] = 0;
4504e98e3e1Schristos 		}
4514e98e3e1Schristos 	    }
4524e98e3e1Schristos 	}
4534e98e3e1Schristos     }
4544e98e3e1Schristos }
4554e98e3e1Schristos 
4564e98e3e1Schristos /* Copy data from the cache buffer to the target register(s).  */
4574e98e3e1Schristos static void
4584e98e3e1Schristos copy_load_data (SIM_CPU *current_cpu, FRV_CACHE *cache, int slot,
4594e98e3e1Schristos 		CACHE_QUEUE_ELEMENT *q)
4604e98e3e1Schristos {
4614e98e3e1Schristos   switch (q->length)
4624e98e3e1Schristos     {
4634e98e3e1Schristos     case 1:
4644e98e3e1Schristos       if (q->regtype == REGTYPE_FR)
4654e98e3e1Schristos 	{
4664e98e3e1Schristos 	  if (q->is_signed)
4674e98e3e1Schristos 	    {
4684e98e3e1Schristos 	      QI value = CACHE_RETURN_DATA (cache, slot, q->address, QI, 1);
4694e98e3e1Schristos 	      SET_H_FR (q->regnum, value);
4704e98e3e1Schristos 	    }
4714e98e3e1Schristos 	  else
4724e98e3e1Schristos 	    {
4734e98e3e1Schristos 	      UQI value = CACHE_RETURN_DATA (cache, slot, q->address, UQI, 1);
4744e98e3e1Schristos 	      SET_H_FR (q->regnum, value);
4754e98e3e1Schristos 	    }
4764e98e3e1Schristos 	}
4774e98e3e1Schristos       else
4784e98e3e1Schristos 	{
4794e98e3e1Schristos 	  if (q->is_signed)
4804e98e3e1Schristos 	    {
4814e98e3e1Schristos 	      QI value = CACHE_RETURN_DATA (cache, slot, q->address, QI, 1);
4824e98e3e1Schristos 	      SET_H_GR (q->regnum, value);
4834e98e3e1Schristos 	    }
4844e98e3e1Schristos 	  else
4854e98e3e1Schristos 	    {
4864e98e3e1Schristos 	      UQI value = CACHE_RETURN_DATA (cache, slot, q->address, UQI, 1);
4874e98e3e1Schristos 	      SET_H_GR (q->regnum, value);
4884e98e3e1Schristos 	    }
4894e98e3e1Schristos 	}
4904e98e3e1Schristos       break;
4914e98e3e1Schristos     case 2:
4924e98e3e1Schristos       if (q->regtype == REGTYPE_FR)
4934e98e3e1Schristos 	{
4944e98e3e1Schristos 	  if (q->is_signed)
4954e98e3e1Schristos 	    {
4964e98e3e1Schristos 	      HI value = CACHE_RETURN_DATA (cache, slot, q->address, HI, 2);
4974e98e3e1Schristos 	      SET_H_FR (q->regnum, value);
4984e98e3e1Schristos 	    }
4994e98e3e1Schristos 	  else
5004e98e3e1Schristos 	    {
5014e98e3e1Schristos 	      UHI value = CACHE_RETURN_DATA (cache, slot, q->address, UHI, 2);
5024e98e3e1Schristos 	      SET_H_FR (q->regnum, value);
5034e98e3e1Schristos 	    }
5044e98e3e1Schristos 	}
5054e98e3e1Schristos       else
5064e98e3e1Schristos 	{
5074e98e3e1Schristos 	  if (q->is_signed)
5084e98e3e1Schristos 	    {
5094e98e3e1Schristos 	      HI value = CACHE_RETURN_DATA (cache, slot, q->address, HI, 2);
5104e98e3e1Schristos 	      SET_H_GR (q->regnum, value);
5114e98e3e1Schristos 	    }
5124e98e3e1Schristos 	  else
5134e98e3e1Schristos 	    {
5144e98e3e1Schristos 	      UHI value = CACHE_RETURN_DATA (cache, slot, q->address, UHI, 2);
5154e98e3e1Schristos 	      SET_H_GR (q->regnum, value);
5164e98e3e1Schristos 	    }
5174e98e3e1Schristos 	}
5184e98e3e1Schristos       break;
5194e98e3e1Schristos     case 4:
5204e98e3e1Schristos       if (q->regtype == REGTYPE_FR)
5214e98e3e1Schristos 	{
5224e98e3e1Schristos 	  SET_H_FR (q->regnum,
5234e98e3e1Schristos 		    CACHE_RETURN_DATA (cache, slot, q->address, SF, 4));
5244e98e3e1Schristos 	}
5254e98e3e1Schristos       else
5264e98e3e1Schristos 	{
5274e98e3e1Schristos 	  SET_H_GR (q->regnum,
5284e98e3e1Schristos 		    CACHE_RETURN_DATA (cache, slot, q->address, SI, 4));
5294e98e3e1Schristos 	}
5304e98e3e1Schristos       break;
5314e98e3e1Schristos     case 8:
5324e98e3e1Schristos       if (q->regtype == REGTYPE_FR)
5334e98e3e1Schristos 	{
5344e98e3e1Schristos 	  SET_H_FR_DOUBLE (q->regnum,
5354e98e3e1Schristos 			   CACHE_RETURN_DATA (cache, slot, q->address, DF, 8));
5364e98e3e1Schristos 	}
5374e98e3e1Schristos       else
5384e98e3e1Schristos 	{
5394e98e3e1Schristos 	  SET_H_GR_DOUBLE (q->regnum,
5404e98e3e1Schristos 			   CACHE_RETURN_DATA (cache, slot, q->address, DI, 8));
5414e98e3e1Schristos 	}
5424e98e3e1Schristos       break;
5434e98e3e1Schristos     case 16:
5444e98e3e1Schristos       if (q->regtype == REGTYPE_FR)
5454e98e3e1Schristos 	frvbf_h_fr_quad_set_handler (current_cpu, q->regnum,
5464e98e3e1Schristos 				     CACHE_RETURN_DATA_ADDRESS (cache, slot,
5474e98e3e1Schristos 								q->address,
5484e98e3e1Schristos 								16));
5494e98e3e1Schristos       else
5504e98e3e1Schristos 	frvbf_h_gr_quad_set_handler (current_cpu, q->regnum,
5514e98e3e1Schristos 				     CACHE_RETURN_DATA_ADDRESS (cache, slot,
5524e98e3e1Schristos 								q->address,
5534e98e3e1Schristos 								16));
5544e98e3e1Schristos       break;
5554e98e3e1Schristos     default:
5564e98e3e1Schristos       abort ();
5574e98e3e1Schristos     }
5584e98e3e1Schristos }
5594e98e3e1Schristos 
5604e98e3e1Schristos static int
5614e98e3e1Schristos request_complete (SIM_CPU *cpu, CACHE_QUEUE_ELEMENT *q)
5624e98e3e1Schristos {
5634e98e3e1Schristos   FRV_CACHE* cache;
5644e98e3e1Schristos   if (! q->active || q->cycles > 0)
5654e98e3e1Schristos     return 0;
5664e98e3e1Schristos 
5674e98e3e1Schristos   cache = CPU_DATA_CACHE (cpu);
5684e98e3e1Schristos   switch (q->request)
5694e98e3e1Schristos     {
5704e98e3e1Schristos     case cache_load:
5714e98e3e1Schristos       /* For loads, we must wait until the data is returned from the cache.  */
5724e98e3e1Schristos       if (frv_cache_data_in_buffer (cache, 0, q->address, q->reqno))
5734e98e3e1Schristos 	{
5744e98e3e1Schristos 	  copy_load_data (cpu, cache, 0, q);
5754e98e3e1Schristos 	  return 1;
5764e98e3e1Schristos 	}
5774e98e3e1Schristos       if (frv_cache_data_in_buffer (cache, 1, q->address, q->reqno))
5784e98e3e1Schristos 	{
5794e98e3e1Schristos 	  copy_load_data (cpu, cache, 1, q);
5804e98e3e1Schristos 	  return 1;
5814e98e3e1Schristos 	}
5824e98e3e1Schristos       break;
5834e98e3e1Schristos 
5844e98e3e1Schristos     case cache_flush:
5854e98e3e1Schristos       /* We must wait until the data is flushed.  */
5864e98e3e1Schristos       if (frv_cache_data_flushed (cache, 0, q->address, q->reqno))
5874e98e3e1Schristos 	return 1;
5884e98e3e1Schristos       if (frv_cache_data_flushed (cache, 1, q->address, q->reqno))
5894e98e3e1Schristos 	return 1;
5904e98e3e1Schristos       break;
5914e98e3e1Schristos 
5924e98e3e1Schristos     default:
5934e98e3e1Schristos       /* All other requests are complete once they've been made.  */
5944e98e3e1Schristos       return 1;
5954e98e3e1Schristos     }
5964e98e3e1Schristos 
5974e98e3e1Schristos   return 0;
5984e98e3e1Schristos }
5994e98e3e1Schristos 
6004e98e3e1Schristos /* Run the insn and data caches through the given number of cycles, taking
6014e98e3e1Schristos    note of load requests which are fullfilled as a result.  */
6024e98e3e1Schristos static void
6034e98e3e1Schristos run_caches (SIM_CPU *cpu, int cycles)
6044e98e3e1Schristos {
6054e98e3e1Schristos   FRV_CACHE* data_cache = CPU_DATA_CACHE (cpu);
6064e98e3e1Schristos   FRV_CACHE* insn_cache = CPU_INSN_CACHE (cpu);
6074e98e3e1Schristos   int i;
6084e98e3e1Schristos   /* For each cycle, run the caches, noting which requests have been fullfilled
6094e98e3e1Schristos      and submitting new requests on their designated cycles.  */
6104e98e3e1Schristos   for (i = 0; i < cycles; ++i)
6114e98e3e1Schristos     {
6124e98e3e1Schristos       int j;
6134e98e3e1Schristos       /* Run the caches through 1 cycle.  */
6144e98e3e1Schristos       frv_cache_run (data_cache, 1);
6154e98e3e1Schristos       frv_cache_run (insn_cache, 1);
6164e98e3e1Schristos 
6174e98e3e1Schristos       /* Note whether prefetched insn data has been loaded yet.  */
6184e98e3e1Schristos       for (j = LS; j < FRV_CACHE_PIPELINES; ++j)
6194e98e3e1Schristos 	{
6204e98e3e1Schristos 	  if (frv_insn_fetch_buffer[j].reqno != NO_REQNO
6214e98e3e1Schristos 	      && frv_cache_data_in_buffer (insn_cache, j,
6224e98e3e1Schristos 					   frv_insn_fetch_buffer[j].address,
6234e98e3e1Schristos 					   frv_insn_fetch_buffer[j].reqno))
6244e98e3e1Schristos 	    frv_insn_fetch_buffer[j].reqno = NO_REQNO;
6254e98e3e1Schristos 	}
6264e98e3e1Schristos 
6274e98e3e1Schristos       /* Check to see which requests have been satisfied and which should
6284e98e3e1Schristos 	 be submitted now.  */
6294e98e3e1Schristos       for (j = 0; j < cache_queue.ix; ++j)
6304e98e3e1Schristos 	{
6314e98e3e1Schristos 	  CACHE_QUEUE_ELEMENT *q = & cache_queue.q[j];
6324e98e3e1Schristos 	  if (! q->active)
6334e98e3e1Schristos 	    continue;
6344e98e3e1Schristos 
6354e98e3e1Schristos 	  /* If a load has been satisfied, complete the operation and remove it
6364e98e3e1Schristos 	     from the queue.  */
6374e98e3e1Schristos 	  if (request_complete (cpu, q))
6384e98e3e1Schristos 	    {
6394e98e3e1Schristos 	      remove_cache_queue_element (cpu, j);
6404e98e3e1Schristos 	      --j;
6414e98e3e1Schristos 	      continue;
6424e98e3e1Schristos 	    }
6434e98e3e1Schristos 
6444e98e3e1Schristos 	  /* Decrease the cycle count of each queued request.
6454e98e3e1Schristos 	     Submit a request for each queued request whose cycle count has
6464e98e3e1Schristos 	     become zero.  */
6474e98e3e1Schristos 	  --q->cycles;
6484e98e3e1Schristos 	  if (q->cycles == 0)
6494e98e3e1Schristos 	    submit_cache_request (q);
6504e98e3e1Schristos 	}
6514e98e3e1Schristos     }
6524e98e3e1Schristos }
6534e98e3e1Schristos 
6544e98e3e1Schristos static void
6554e98e3e1Schristos apply_latency_adjustments (SIM_CPU *cpu)
6564e98e3e1Schristos {
6574e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
6584e98e3e1Schristos   int i;
6594e98e3e1Schristos   /* update the latencies of the registers.  */
6604e98e3e1Schristos   int *fr  = ps->fr_busy;
6614e98e3e1Schristos   int *acc = ps->acc_busy;
6624e98e3e1Schristos   for (i = 0; i < 64; ++i)
6634e98e3e1Schristos     {
6644e98e3e1Schristos       if (ps->fr_busy_adjust[i] > 0)
6654e98e3e1Schristos 	*fr -= ps->fr_busy_adjust[i]; /* OK if it goes negative.  */
6664e98e3e1Schristos       if (ps->acc_busy_adjust[i] > 0)
6674e98e3e1Schristos 	*acc -= ps->acc_busy_adjust[i]; /* OK if it goes negative.  */
6684e98e3e1Schristos       ++fr;
6694e98e3e1Schristos       ++acc;
6704e98e3e1Schristos     }
6714e98e3e1Schristos }
6724e98e3e1Schristos 
6734e98e3e1Schristos /* Account for the number of cycles which have just passed in the latency of
6744e98e3e1Schristos    various system elements.  Works for negative cycles too so that latency
6754e98e3e1Schristos    can be extended in the case of insn fetch latency.
6764e98e3e1Schristos    If negative or zero, then no adjustment is necessary.  */
6774e98e3e1Schristos static void
6784e98e3e1Schristos update_latencies (SIM_CPU *cpu, int cycles)
6794e98e3e1Schristos {
6804e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
6814e98e3e1Schristos   int i;
6824e98e3e1Schristos   /* update the latencies of the registers.  */
6834e98e3e1Schristos   int *fdiv;
6844e98e3e1Schristos   int *fsqrt;
6854e98e3e1Schristos   int *idiv;
6864e98e3e1Schristos   int *flt;
6874e98e3e1Schristos   int *media;
6884e98e3e1Schristos   int *ccr;
6894e98e3e1Schristos   int *gr  = ps->gr_busy;
6904e98e3e1Schristos   int *fr  = ps->fr_busy;
6914e98e3e1Schristos   int *acc = ps->acc_busy;
6924e98e3e1Schristos   int *spr;
6934e98e3e1Schristos   /* This loop handles GR, FR and ACC registers.  */
6944e98e3e1Schristos   for (i = 0; i < 64; ++i)
6954e98e3e1Schristos     {
6964e98e3e1Schristos       if (*gr <= cycles)
6974e98e3e1Schristos 	{
6984e98e3e1Schristos 	  *gr = 0;
6994e98e3e1Schristos 	  reset_gr_flags (cpu, i);
7004e98e3e1Schristos 	}
7014e98e3e1Schristos       else
7024e98e3e1Schristos 	*gr -= cycles;
7034e98e3e1Schristos       /* If the busy drops to 0, then mark the register as
7044e98e3e1Schristos 	 "not in use".  */
7054e98e3e1Schristos       if (*fr <= cycles)
7064e98e3e1Schristos 	{
7074e98e3e1Schristos 	  int *fr_lat = ps->fr_latency + i;
7084e98e3e1Schristos 	  *fr = 0;
7094e98e3e1Schristos 	  ps->fr_busy_adjust[i] = 0;
7104e98e3e1Schristos 	  /* Only clear flags if this register has no target latency.  */
7114e98e3e1Schristos 	  if (*fr_lat == 0)
7124e98e3e1Schristos 	    reset_fr_flags (cpu, i);
7134e98e3e1Schristos 	}
7144e98e3e1Schristos       else
7154e98e3e1Schristos 	*fr -= cycles;
7164e98e3e1Schristos       /* If the busy drops to 0, then mark the register as
7174e98e3e1Schristos 	 "not in use".  */
7184e98e3e1Schristos       if (*acc <= cycles)
7194e98e3e1Schristos 	{
7204e98e3e1Schristos 	  int *acc_lat = ps->acc_latency + i;
7214e98e3e1Schristos 	  *acc = 0;
7224e98e3e1Schristos 	  ps->acc_busy_adjust[i] = 0;
7234e98e3e1Schristos 	  /* Only clear flags if this register has no target latency.  */
7244e98e3e1Schristos 	  if (*acc_lat == 0)
7254e98e3e1Schristos 	    reset_acc_flags (cpu, i);
7264e98e3e1Schristos 	}
7274e98e3e1Schristos       else
7284e98e3e1Schristos 	*acc -= cycles;
7294e98e3e1Schristos       ++gr;
7304e98e3e1Schristos       ++fr;
7314e98e3e1Schristos       ++acc;
7324e98e3e1Schristos     }
7334e98e3e1Schristos   /* This loop handles CCR registers.  */
7344e98e3e1Schristos   ccr = ps->ccr_busy;
7354e98e3e1Schristos   for (i = 0; i < 8; ++i)
7364e98e3e1Schristos     {
7374e98e3e1Schristos       if (*ccr <= cycles)
7384e98e3e1Schristos 	{
7394e98e3e1Schristos 	  *ccr = 0;
7404e98e3e1Schristos 	  reset_cc_flags (cpu, i);
7414e98e3e1Schristos 	}
7424e98e3e1Schristos       else
7434e98e3e1Schristos 	*ccr -= cycles;
7444e98e3e1Schristos       ++ccr;
7454e98e3e1Schristos     }
7464e98e3e1Schristos   /* This loop handles SPR registers.  */
7474e98e3e1Schristos   spr = ps->spr_busy;
7484e98e3e1Schristos   for (i = 0; i < 4096; ++i)
7494e98e3e1Schristos     {
7504e98e3e1Schristos       if (*spr <= cycles)
7514e98e3e1Schristos 	*spr = 0;
7524e98e3e1Schristos       else
7534e98e3e1Schristos 	*spr -= cycles;
7544e98e3e1Schristos       ++spr;
7554e98e3e1Schristos     }
7564e98e3e1Schristos   /* This loop handles resources.  */
7574e98e3e1Schristos   idiv = ps->idiv_busy;
7584e98e3e1Schristos   fdiv = ps->fdiv_busy;
7594e98e3e1Schristos   fsqrt = ps->fsqrt_busy;
7604e98e3e1Schristos   for (i = 0; i < 2; ++i)
7614e98e3e1Schristos     {
7624e98e3e1Schristos       *idiv = (*idiv <= cycles) ? 0 : (*idiv - cycles);
7634e98e3e1Schristos       *fdiv = (*fdiv <= cycles) ? 0 : (*fdiv - cycles);
7644e98e3e1Schristos       *fsqrt = (*fsqrt <= cycles) ? 0 : (*fsqrt - cycles);
7654e98e3e1Schristos       ++idiv;
7664e98e3e1Schristos       ++fdiv;
7674e98e3e1Schristos       ++fsqrt;
7684e98e3e1Schristos     }
7694e98e3e1Schristos   /* Float and media units can occur in 4 slots on some machines.  */
7704e98e3e1Schristos   flt = ps->float_busy;
7714e98e3e1Schristos   media = ps->media_busy;
7724e98e3e1Schristos   for (i = 0; i < 4; ++i)
7734e98e3e1Schristos     {
7744e98e3e1Schristos       *flt = (*flt <= cycles) ? 0 : (*flt - cycles);
7754e98e3e1Schristos       *media = (*media <= cycles) ? 0 : (*media - cycles);
7764e98e3e1Schristos       ++flt;
7774e98e3e1Schristos       ++media;
7784e98e3e1Schristos     }
7794e98e3e1Schristos }
7804e98e3e1Schristos 
7814e98e3e1Schristos /* Print information about the wait for the given number of cycles.  */
7824e98e3e1Schristos void
7834e98e3e1Schristos frv_model_trace_wait_cycles (SIM_CPU *cpu, int cycles, const char *hazard_name)
7844e98e3e1Schristos {
7854e98e3e1Schristos   if (TRACE_INSN_P (cpu) && cycles > 0)
7864e98e3e1Schristos     {
7874e98e3e1Schristos       SIM_DESC sd = CPU_STATE (cpu);
7884e98e3e1Schristos       trace_printf (sd, cpu, "**** %s wait %d cycles ***\n",
7894e98e3e1Schristos 		    hazard_name, cycles);
7904e98e3e1Schristos     }
7914e98e3e1Schristos }
7924e98e3e1Schristos 
7934e98e3e1Schristos void
7944e98e3e1Schristos trace_vliw_wait_cycles (SIM_CPU *cpu)
7954e98e3e1Schristos {
7964e98e3e1Schristos   if (TRACE_INSN_P (cpu))
7974e98e3e1Schristos     {
7984e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
7994e98e3e1Schristos       frv_model_trace_wait_cycles (cpu, ps->vliw_wait, hazard_name);
8004e98e3e1Schristos     }
8014e98e3e1Schristos }
8024e98e3e1Schristos 
8034e98e3e1Schristos /* Wait for the given number of cycles.  */
8044e98e3e1Schristos void
8054e98e3e1Schristos frv_model_advance_cycles (SIM_CPU *cpu, int cycles)
8064e98e3e1Schristos {
8074e98e3e1Schristos   PROFILE_DATA *p = CPU_PROFILE_DATA (cpu);
8084e98e3e1Schristos   update_latencies (cpu, cycles);
8094e98e3e1Schristos   run_caches (cpu, cycles);
8104e98e3e1Schristos   PROFILE_MODEL_TOTAL_CYCLES (p) += cycles;
8114e98e3e1Schristos }
8124e98e3e1Schristos 
8134e98e3e1Schristos void
8144e98e3e1Schristos handle_resource_wait (SIM_CPU *cpu)
8154e98e3e1Schristos {
8164e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
8174e98e3e1Schristos   if (ps->vliw_wait != 0)
8184e98e3e1Schristos     frv_model_advance_cycles (cpu, ps->vliw_wait);
8194e98e3e1Schristos   if (ps->vliw_load_stall > ps->vliw_wait)
8204e98e3e1Schristos     ps->vliw_load_stall -= ps->vliw_wait;
8214e98e3e1Schristos   else
8224e98e3e1Schristos     ps->vliw_load_stall = 0;
8234e98e3e1Schristos }
8244e98e3e1Schristos 
8254e98e3e1Schristos /* Account for the number of cycles until these resources will be available
8264e98e3e1Schristos    again.  */
8274e98e3e1Schristos static void
8284e98e3e1Schristos update_target_latencies (SIM_CPU *cpu)
8294e98e3e1Schristos {
8304e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
8314e98e3e1Schristos   int i;
8324e98e3e1Schristos   /* update the latencies of the registers.  */
8334e98e3e1Schristos   int *ccr_lat;
8344e98e3e1Schristos   int *gr_lat  = ps->gr_latency;
8354e98e3e1Schristos   int *fr_lat  = ps->fr_latency;
8364e98e3e1Schristos   int *acc_lat = ps->acc_latency;
8374e98e3e1Schristos   int *spr_lat;
8384e98e3e1Schristos   int *ccr;
8394e98e3e1Schristos   int *gr = ps->gr_busy;
8404e98e3e1Schristos   int  *fr = ps->fr_busy;
8414e98e3e1Schristos   int  *acc = ps->acc_busy;
8424e98e3e1Schristos   int *spr;
8434e98e3e1Schristos   /* This loop handles GR, FR and ACC registers.  */
8444e98e3e1Schristos   for (i = 0; i < 64; ++i)
8454e98e3e1Schristos     {
8464e98e3e1Schristos       if (*gr_lat)
8474e98e3e1Schristos 	{
8484e98e3e1Schristos 	  *gr = *gr_lat;
8494e98e3e1Schristos 	  *gr_lat = 0;
8504e98e3e1Schristos 	}
8514e98e3e1Schristos       if (*fr_lat)
8524e98e3e1Schristos 	{
8534e98e3e1Schristos 	  *fr = *fr_lat;
8544e98e3e1Schristos 	  *fr_lat = 0;
8554e98e3e1Schristos 	}
8564e98e3e1Schristos       if (*acc_lat)
8574e98e3e1Schristos 	{
8584e98e3e1Schristos 	  *acc = *acc_lat;
8594e98e3e1Schristos 	  *acc_lat = 0;
8604e98e3e1Schristos 	}
8614e98e3e1Schristos       ++gr; ++gr_lat;
8624e98e3e1Schristos       ++fr; ++fr_lat;
8634e98e3e1Schristos       ++acc; ++acc_lat;
8644e98e3e1Schristos     }
8654e98e3e1Schristos   /* This loop handles CCR registers.  */
8664e98e3e1Schristos   ccr = ps->ccr_busy;
8674e98e3e1Schristos   ccr_lat = ps->ccr_latency;
8684e98e3e1Schristos   for (i = 0; i < 8; ++i)
8694e98e3e1Schristos     {
8704e98e3e1Schristos       if (*ccr_lat)
8714e98e3e1Schristos 	{
8724e98e3e1Schristos 	  *ccr = *ccr_lat;
8734e98e3e1Schristos 	  *ccr_lat = 0;
8744e98e3e1Schristos 	}
8754e98e3e1Schristos       ++ccr; ++ccr_lat;
8764e98e3e1Schristos     }
8774e98e3e1Schristos   /* This loop handles SPR registers.  */
8784e98e3e1Schristos   spr = ps->spr_busy;
8794e98e3e1Schristos   spr_lat = ps->spr_latency;
8804e98e3e1Schristos   for (i = 0; i < 4096; ++i)
8814e98e3e1Schristos     {
8824e98e3e1Schristos       if (*spr_lat)
8834e98e3e1Schristos 	{
8844e98e3e1Schristos 	  *spr = *spr_lat;
8854e98e3e1Schristos 	  *spr_lat = 0;
8864e98e3e1Schristos 	}
8874e98e3e1Schristos       ++spr; ++spr_lat;
8884e98e3e1Schristos     }
8894e98e3e1Schristos }
8904e98e3e1Schristos 
8914e98e3e1Schristos /* Run the caches until all pending cache flushes are complete.  */
8924e98e3e1Schristos static void
8934e98e3e1Schristos wait_for_flush (SIM_CPU *cpu)
8944e98e3e1Schristos {
8954e98e3e1Schristos   SI address = CPU_LOAD_ADDRESS (cpu);
8964e98e3e1Schristos   int wait = 0;
8974e98e3e1Schristos   while (flush_pending_for_address (cpu, address))
8984e98e3e1Schristos     {
8994e98e3e1Schristos       frv_model_advance_cycles (cpu, 1);
9004e98e3e1Schristos       ++wait;
9014e98e3e1Schristos     }
9024e98e3e1Schristos   if (TRACE_INSN_P (cpu) && wait)
9034e98e3e1Schristos     {
9044b169a6bSchristos       sprintf (hazard_name, "Data cache flush address %x:", address);
9054e98e3e1Schristos       frv_model_trace_wait_cycles (cpu, wait, hazard_name);
9064e98e3e1Schristos     }
9074e98e3e1Schristos }
9084e98e3e1Schristos 
9094e98e3e1Schristos /* Initialize cycle counting for an insn.
9104e98e3e1Schristos    FIRST_P is non-zero if this is the first insn in a set of parallel
9114e98e3e1Schristos    insns.  */
9124e98e3e1Schristos void
9134e98e3e1Schristos frvbf_model_insn_before (SIM_CPU *cpu, int first_p)
9144e98e3e1Schristos {
9154e98e3e1Schristos   SIM_DESC sd = CPU_STATE (cpu);
9164e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
9174e98e3e1Schristos 
9184e98e3e1Schristos   ps->vliw_wait = 0;
9194e98e3e1Schristos   ps->post_wait = 0;
9204e98e3e1Schristos   memset (ps->fr_busy_adjust, 0, sizeof (ps->fr_busy_adjust));
9214e98e3e1Schristos   memset (ps->acc_busy_adjust, 0, sizeof (ps->acc_busy_adjust));
9224e98e3e1Schristos 
9234e98e3e1Schristos   if (first_p)
9244e98e3e1Schristos     {
9254e98e3e1Schristos       ps->vliw_insns++;
9264e98e3e1Schristos       ps->vliw_cycles = 0;
9274e98e3e1Schristos       ps->vliw_branch_taken = 0;
9284e98e3e1Schristos       ps->vliw_load_stall = 0;
9294e98e3e1Schristos     }
9304e98e3e1Schristos 
9314e98e3e1Schristos   switch (STATE_ARCHITECTURE (sd)->mach)
9324e98e3e1Schristos     {
9334e98e3e1Schristos     case bfd_mach_fr400:
9344e98e3e1Schristos     case bfd_mach_fr450:
9354e98e3e1Schristos       fr400_model_insn_before (cpu, first_p);
9364e98e3e1Schristos       break;
9374e98e3e1Schristos     case bfd_mach_fr500:
9384e98e3e1Schristos       fr500_model_insn_before (cpu, first_p);
9394e98e3e1Schristos       break;
9404e98e3e1Schristos     case bfd_mach_fr550:
9414e98e3e1Schristos       fr550_model_insn_before (cpu, first_p);
9424e98e3e1Schristos       break;
9434e98e3e1Schristos     default:
9444e98e3e1Schristos       break;
9454e98e3e1Schristos     }
9464e98e3e1Schristos 
9474e98e3e1Schristos   if (first_p)
9484e98e3e1Schristos     wait_for_flush (cpu);
9494e98e3e1Schristos }
9504e98e3e1Schristos 
9514e98e3e1Schristos /* Record the cycles computed for an insn.
9524e98e3e1Schristos    LAST_P is non-zero if this is the last insn in a set of parallel insns,
9534e98e3e1Schristos    and we update the total cycle count.
9544e98e3e1Schristos    CYCLES is the cycle count of the insn.  */
9554e98e3e1Schristos 
9564e98e3e1Schristos void
9574e98e3e1Schristos frvbf_model_insn_after (SIM_CPU *cpu, int last_p, int cycles)
9584e98e3e1Schristos {
9594e98e3e1Schristos   PROFILE_DATA *p = CPU_PROFILE_DATA (cpu);
9604e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
9614e98e3e1Schristos   SIM_DESC sd = CPU_STATE (cpu);
9624e98e3e1Schristos 
9634e98e3e1Schristos   PROFILE_MODEL_CUR_INSN_CYCLES (p) = cycles;
9644e98e3e1Schristos 
9654e98e3e1Schristos   /* The number of cycles for a VLIW insn is the maximum number of cycles
9664e98e3e1Schristos      used by any individual insn within it.  */
9674e98e3e1Schristos   if (cycles > ps->vliw_cycles)
9684e98e3e1Schristos     ps->vliw_cycles = cycles;
9694e98e3e1Schristos 
9704e98e3e1Schristos   if (last_p)
9714e98e3e1Schristos     {
9724e98e3e1Schristos       /*  This is the last insn in a VLIW insn.  */
9734e98e3e1Schristos       struct frv_interrupt_timer *timer = & frv_interrupt_state.timer;
9744e98e3e1Schristos 
9754e98e3e1Schristos       activate_cache_requests (cpu); /* before advancing cycles.  */
9764e98e3e1Schristos       apply_latency_adjustments (cpu); /* must go first.  */
9774e98e3e1Schristos       update_target_latencies (cpu); /* must go next.  */
9784e98e3e1Schristos       frv_model_advance_cycles (cpu, ps->vliw_cycles);
9794e98e3e1Schristos 
9804e98e3e1Schristos       PROFILE_MODEL_LOAD_STALL_CYCLES (p) += ps->vliw_load_stall;
9814e98e3e1Schristos 
9824e98e3e1Schristos       /* Check the interrupt timer.  cycles contains the total cycle count.  */
9834e98e3e1Schristos       if (timer->enabled)
9844e98e3e1Schristos 	{
9854e98e3e1Schristos 	  cycles = PROFILE_MODEL_TOTAL_CYCLES (p);
9864e98e3e1Schristos 	  if (timer->current % timer->value
9874e98e3e1Schristos 	      + (cycles - timer->current) >= timer->value)
9884e98e3e1Schristos 	    frv_queue_external_interrupt (cpu, timer->interrupt);
9894e98e3e1Schristos 	  timer->current = cycles;
9904e98e3e1Schristos 	}
9914e98e3e1Schristos 
9924e98e3e1Schristos       ps->past_first_p = 0; /* Next one will be the first in a new VLIW.  */
9934e98e3e1Schristos       ps->branch_address = -1;
9944e98e3e1Schristos     }
9954e98e3e1Schristos   else
9964e98e3e1Schristos     ps->past_first_p = 1;
9974e98e3e1Schristos 
9984e98e3e1Schristos   switch (STATE_ARCHITECTURE (sd)->mach)
9994e98e3e1Schristos     {
10004e98e3e1Schristos     case bfd_mach_fr400:
10014e98e3e1Schristos     case bfd_mach_fr450:
10024e98e3e1Schristos       fr400_model_insn_after (cpu, last_p, cycles);
10034e98e3e1Schristos       break;
10044e98e3e1Schristos     case bfd_mach_fr500:
10054e98e3e1Schristos       fr500_model_insn_after (cpu, last_p, cycles);
10064e98e3e1Schristos       break;
10074e98e3e1Schristos     case bfd_mach_fr550:
10084e98e3e1Schristos       fr550_model_insn_after (cpu, last_p, cycles);
10094e98e3e1Schristos       break;
10104e98e3e1Schristos     default:
10114e98e3e1Schristos       break;
10124e98e3e1Schristos     }
10134e98e3e1Schristos }
10144e98e3e1Schristos 
10154b169a6bSchristos void
10164e98e3e1Schristos frvbf_model_branch (SIM_CPU *current_cpu, PCADDR target, int hint)
10174e98e3e1Schristos {
10184e98e3e1Schristos   /* Record the hint and branch address for use in profiling.  */
10194e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu);
10204e98e3e1Schristos   ps->branch_hint = hint;
10214e98e3e1Schristos   ps->branch_address = target;
10224e98e3e1Schristos }
10234e98e3e1Schristos 
10244e98e3e1Schristos /* Top up the latency of the given GR by the given number of cycles.  */
10254e98e3e1Schristos void
10264e98e3e1Schristos update_GR_latency (SIM_CPU *cpu, INT out_GR, int cycles)
10274e98e3e1Schristos {
10284e98e3e1Schristos   if (out_GR >= 0)
10294e98e3e1Schristos     {
10304e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
10314e98e3e1Schristos       int *gr = ps->gr_latency;
10324e98e3e1Schristos       if (gr[out_GR] < cycles)
10334e98e3e1Schristos 	gr[out_GR] = cycles;
10344e98e3e1Schristos     }
10354e98e3e1Schristos }
10364e98e3e1Schristos 
10374e98e3e1Schristos void
10384e98e3e1Schristos decrease_GR_busy (SIM_CPU *cpu, INT in_GR, int cycles)
10394e98e3e1Schristos {
10404e98e3e1Schristos   if (in_GR >= 0)
10414e98e3e1Schristos     {
10424e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
10434e98e3e1Schristos       int *gr = ps->gr_busy;
10444e98e3e1Schristos       gr[in_GR] -= cycles;
10454e98e3e1Schristos     }
10464e98e3e1Schristos }
10474e98e3e1Schristos 
10484e98e3e1Schristos /* Top up the latency of the given double GR by the number of cycles.  */
10494e98e3e1Schristos void
10504e98e3e1Schristos update_GRdouble_latency (SIM_CPU *cpu, INT out_GR, int cycles)
10514e98e3e1Schristos {
10524e98e3e1Schristos   if (out_GR >= 0)
10534e98e3e1Schristos     {
10544e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
10554e98e3e1Schristos       int *gr = ps->gr_latency;
10564e98e3e1Schristos       if (gr[out_GR] < cycles)
10574e98e3e1Schristos 	gr[out_GR] = cycles;
10584e98e3e1Schristos       if (out_GR < 63 && gr[out_GR + 1] < cycles)
10594e98e3e1Schristos 	gr[out_GR + 1] = cycles;
10604e98e3e1Schristos     }
10614e98e3e1Schristos }
10624e98e3e1Schristos 
10634e98e3e1Schristos void
10644e98e3e1Schristos update_GR_latency_for_load (SIM_CPU *cpu, INT out_GR, int cycles)
10654e98e3e1Schristos {
10664e98e3e1Schristos   if (out_GR >= 0)
10674e98e3e1Schristos     {
10684e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
10694e98e3e1Schristos       int *gr = ps->gr_latency;
10704e98e3e1Schristos 
10714e98e3e1Schristos       /* The latency of the GR will be at least the number of cycles used
10724e98e3e1Schristos 	 by the insn.  */
10734e98e3e1Schristos       if (gr[out_GR] < cycles)
10744e98e3e1Schristos 	gr[out_GR] = cycles;
10754e98e3e1Schristos 
10764e98e3e1Schristos       /* The latency will also depend on how long it takes to retrieve the
10774e98e3e1Schristos 	 data from the cache or memory.  Assume that the load is issued
10784e98e3e1Schristos 	 after the last cycle of the insn.  */
10794e98e3e1Schristos       request_cache_load (cpu, out_GR, REGTYPE_NONE, cycles);
10804e98e3e1Schristos     }
10814e98e3e1Schristos }
10824e98e3e1Schristos 
10834e98e3e1Schristos void
10844e98e3e1Schristos update_GRdouble_latency_for_load (SIM_CPU *cpu, INT out_GR, int cycles)
10854e98e3e1Schristos {
10864e98e3e1Schristos   if (out_GR >= 0)
10874e98e3e1Schristos     {
10884e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
10894e98e3e1Schristos       int *gr = ps->gr_latency;
10904e98e3e1Schristos 
10914e98e3e1Schristos       /* The latency of the GR will be at least the number of cycles used
10924e98e3e1Schristos 	 by the insn.  */
10934e98e3e1Schristos       if (gr[out_GR] < cycles)
10944e98e3e1Schristos 	gr[out_GR] = cycles;
10954e98e3e1Schristos       if (out_GR < 63 && gr[out_GR + 1] < cycles)
10964e98e3e1Schristos 	gr[out_GR + 1] = cycles;
10974e98e3e1Schristos 
10984e98e3e1Schristos       /* The latency will also depend on how long it takes to retrieve the
10994e98e3e1Schristos 	 data from the cache or memory.  Assume that the load is issued
11004e98e3e1Schristos 	 after the last cycle of the insn.  */
11014e98e3e1Schristos       request_cache_load (cpu, out_GR, REGTYPE_NONE, cycles);
11024e98e3e1Schristos     }
11034e98e3e1Schristos }
11044e98e3e1Schristos 
11054e98e3e1Schristos void
11064e98e3e1Schristos update_GR_latency_for_swap (SIM_CPU *cpu, INT out_GR, int cycles)
11074e98e3e1Schristos {
11084e98e3e1Schristos   update_GR_latency_for_load (cpu, out_GR, cycles);
11094e98e3e1Schristos }
11104e98e3e1Schristos 
11114e98e3e1Schristos /* Top up the latency of the given FR by the given number of cycles.  */
11124e98e3e1Schristos void
11134e98e3e1Schristos update_FR_latency (SIM_CPU *cpu, INT out_FR, int cycles)
11144e98e3e1Schristos {
11154e98e3e1Schristos   if (out_FR >= 0)
11164e98e3e1Schristos     {
11174e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
11184e98e3e1Schristos       int *fr = ps->fr_latency;
11194e98e3e1Schristos       if (fr[out_FR] < cycles)
11204e98e3e1Schristos 	fr[out_FR] = cycles;
11214e98e3e1Schristos     }
11224e98e3e1Schristos }
11234e98e3e1Schristos 
11244e98e3e1Schristos /* Top up the latency of the given double FR by the number of cycles.  */
11254e98e3e1Schristos void
11264e98e3e1Schristos update_FRdouble_latency (SIM_CPU *cpu, INT out_FR, int cycles)
11274e98e3e1Schristos {
11284e98e3e1Schristos   if (out_FR >= 0)
11294e98e3e1Schristos     {
11304e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
11314e98e3e1Schristos       int *fr = ps->fr_latency;
11324e98e3e1Schristos       if (fr[out_FR] < cycles)
11334e98e3e1Schristos 	fr[out_FR] = cycles;
11344e98e3e1Schristos       if (out_FR < 63 && fr[out_FR + 1] < cycles)
11354e98e3e1Schristos 	fr[out_FR + 1] = cycles;
11364e98e3e1Schristos     }
11374e98e3e1Schristos }
11384e98e3e1Schristos 
11394e98e3e1Schristos void
11404e98e3e1Schristos update_FR_latency_for_load (SIM_CPU *cpu, INT out_FR, int cycles)
11414e98e3e1Schristos {
11424e98e3e1Schristos   if (out_FR >= 0)
11434e98e3e1Schristos     {
11444e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
11454e98e3e1Schristos       int *fr = ps->fr_latency;
11464e98e3e1Schristos 
11474e98e3e1Schristos       /* The latency of the FR will be at least the number of cycles used
11484e98e3e1Schristos 	 by the insn.  */
11494e98e3e1Schristos       if (fr[out_FR] < cycles)
11504e98e3e1Schristos 	fr[out_FR] = cycles;
11514e98e3e1Schristos 
11524e98e3e1Schristos       /* The latency will also depend on how long it takes to retrieve the
11534e98e3e1Schristos 	 data from the cache or memory.  Assume that the load is issued
11544e98e3e1Schristos 	 after the last cycle of the insn.  */
11554e98e3e1Schristos       request_cache_load (cpu, out_FR, REGTYPE_FR, cycles);
11564e98e3e1Schristos     }
11574e98e3e1Schristos }
11584e98e3e1Schristos 
11594e98e3e1Schristos void
11604e98e3e1Schristos update_FRdouble_latency_for_load (SIM_CPU *cpu, INT out_FR, int cycles)
11614e98e3e1Schristos {
11624e98e3e1Schristos   if (out_FR >= 0)
11634e98e3e1Schristos     {
11644e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
11654e98e3e1Schristos       int *fr = ps->fr_latency;
11664e98e3e1Schristos 
11674e98e3e1Schristos       /* The latency of the FR will be at least the number of cycles used
11684e98e3e1Schristos 	 by the insn.  */
11694e98e3e1Schristos       if (fr[out_FR] < cycles)
11704e98e3e1Schristos 	fr[out_FR] = cycles;
11714e98e3e1Schristos       if (out_FR < 63 && fr[out_FR + 1] < cycles)
11724e98e3e1Schristos 	fr[out_FR + 1] = cycles;
11734e98e3e1Schristos 
11744e98e3e1Schristos       /* The latency will also depend on how long it takes to retrieve the
11754e98e3e1Schristos 	 data from the cache or memory.  Assume that the load is issued
11764e98e3e1Schristos 	 after the last cycle of the insn.  */
11774e98e3e1Schristos       request_cache_load (cpu, out_FR, REGTYPE_FR, cycles);
11784e98e3e1Schristos     }
11794e98e3e1Schristos }
11804e98e3e1Schristos 
11814e98e3e1Schristos /* Top up the post-processing time of the given FR by the given number of
11824e98e3e1Schristos    cycles.  */
11834e98e3e1Schristos void
11844e98e3e1Schristos update_FR_ptime (SIM_CPU *cpu, INT out_FR, int cycles)
11854e98e3e1Schristos {
11864e98e3e1Schristos   if (out_FR >= 0)
11874e98e3e1Schristos     {
11884e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
11894e98e3e1Schristos       /* If a load is pending on this register, then add the cycles to
11904e98e3e1Schristos 	 the post processing time for this register. Otherwise apply it
11914e98e3e1Schristos 	 directly to the latency of the register.  */
11924e98e3e1Schristos       if (! load_pending_for_register (cpu, out_FR, 1, REGTYPE_FR))
11934e98e3e1Schristos 	{
11944e98e3e1Schristos 	  int *fr = ps->fr_latency;
11954e98e3e1Schristos 	  fr[out_FR] += cycles;
11964e98e3e1Schristos 	}
11974e98e3e1Schristos       else
11984e98e3e1Schristos 	ps->fr_ptime[out_FR] += cycles;
11994e98e3e1Schristos     }
12004e98e3e1Schristos }
12014e98e3e1Schristos 
12024e98e3e1Schristos void
12034e98e3e1Schristos update_FRdouble_ptime (SIM_CPU *cpu, INT out_FR, int cycles)
12044e98e3e1Schristos {
12054e98e3e1Schristos   if (out_FR >= 0)
12064e98e3e1Schristos     {
12074e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
12084e98e3e1Schristos       /* If a load is pending on this register, then add the cycles to
12094e98e3e1Schristos 	 the post processing time for this register. Otherwise apply it
12104e98e3e1Schristos 	 directly to the latency of the register.  */
12114e98e3e1Schristos       if (! load_pending_for_register (cpu, out_FR, 2, REGTYPE_FR))
12124e98e3e1Schristos 	{
12134e98e3e1Schristos 	  int *fr = ps->fr_latency;
12144e98e3e1Schristos 	  fr[out_FR] += cycles;
12154e98e3e1Schristos 	  if (out_FR < 63)
12164e98e3e1Schristos 	    fr[out_FR + 1] += cycles;
12174e98e3e1Schristos 	}
12184e98e3e1Schristos       else
12194e98e3e1Schristos 	{
12204e98e3e1Schristos 	  ps->fr_ptime[out_FR] += cycles;
12214e98e3e1Schristos 	  if (out_FR < 63)
12224e98e3e1Schristos 	    ps->fr_ptime[out_FR + 1] += cycles;
12234e98e3e1Schristos 	}
12244e98e3e1Schristos     }
12254e98e3e1Schristos }
12264e98e3e1Schristos 
12274e98e3e1Schristos /* Top up the post-processing time of the given ACC by the given number of
12284e98e3e1Schristos    cycles.  */
12294e98e3e1Schristos void
12304e98e3e1Schristos update_ACC_ptime (SIM_CPU *cpu, INT out_ACC, int cycles)
12314e98e3e1Schristos {
12324e98e3e1Schristos   if (out_ACC >= 0)
12334e98e3e1Schristos     {
12344e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
12354e98e3e1Schristos       /* No load can be pending on this register. Apply the cycles
12364e98e3e1Schristos 	 directly to the latency of the register.  */
12374e98e3e1Schristos       int *acc = ps->acc_latency;
12384e98e3e1Schristos       acc[out_ACC] += cycles;
12394e98e3e1Schristos     }
12404e98e3e1Schristos }
12414e98e3e1Schristos 
12424e98e3e1Schristos /* Top up the post-processing time of the given SPR by the given number of
12434e98e3e1Schristos    cycles.  */
12444e98e3e1Schristos void
12454e98e3e1Schristos update_SPR_ptime (SIM_CPU *cpu, INT out_SPR, int cycles)
12464e98e3e1Schristos {
12474e98e3e1Schristos   if (out_SPR >= 0)
12484e98e3e1Schristos     {
12494e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
12504e98e3e1Schristos       /* No load can be pending on this register. Apply the cycles
12514e98e3e1Schristos 	 directly to the latency of the register.  */
12524e98e3e1Schristos       int *spr = ps->spr_latency;
12534e98e3e1Schristos       spr[out_SPR] += cycles;
12544e98e3e1Schristos     }
12554e98e3e1Schristos }
12564e98e3e1Schristos 
12574e98e3e1Schristos void
12584e98e3e1Schristos decrease_ACC_busy (SIM_CPU *cpu, INT out_ACC, int cycles)
12594e98e3e1Schristos {
12604e98e3e1Schristos   if (out_ACC >= 0)
12614e98e3e1Schristos     {
12624e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
12634e98e3e1Schristos       int *acc = ps->acc_busy;
12644e98e3e1Schristos       acc[out_ACC] -= cycles;
12654e98e3e1Schristos       if (ps->acc_busy_adjust[out_ACC] >= 0
12664e98e3e1Schristos 	  && cycles > ps->acc_busy_adjust[out_ACC])
12674e98e3e1Schristos 	ps->acc_busy_adjust[out_ACC] = cycles;
12684e98e3e1Schristos     }
12694e98e3e1Schristos }
12704e98e3e1Schristos 
12714e98e3e1Schristos void
12724e98e3e1Schristos increase_ACC_busy (SIM_CPU *cpu, INT out_ACC, int cycles)
12734e98e3e1Schristos {
12744e98e3e1Schristos   if (out_ACC >= 0)
12754e98e3e1Schristos     {
12764e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
12774e98e3e1Schristos       int *acc = ps->acc_busy;
12784e98e3e1Schristos       acc[out_ACC] += cycles;
12794e98e3e1Schristos     }
12804e98e3e1Schristos }
12814e98e3e1Schristos 
12824e98e3e1Schristos void
12834e98e3e1Schristos enforce_full_acc_latency (SIM_CPU *cpu, INT in_ACC)
12844e98e3e1Schristos {
12854e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
12864e98e3e1Schristos   ps->acc_busy_adjust [in_ACC] = -1;
12874e98e3e1Schristos }
12884e98e3e1Schristos 
12894e98e3e1Schristos void
12904e98e3e1Schristos decrease_FR_busy (SIM_CPU *cpu, INT out_FR, int cycles)
12914e98e3e1Schristos {
12924e98e3e1Schristos   if (out_FR >= 0)
12934e98e3e1Schristos     {
12944e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
12954e98e3e1Schristos       int *fr = ps->fr_busy;
12964e98e3e1Schristos       fr[out_FR] -= cycles;
12974e98e3e1Schristos       if (ps->fr_busy_adjust[out_FR] >= 0
12984e98e3e1Schristos 	  && cycles > ps->fr_busy_adjust[out_FR])
12994e98e3e1Schristos 	ps->fr_busy_adjust[out_FR] = cycles;
13004e98e3e1Schristos     }
13014e98e3e1Schristos }
13024e98e3e1Schristos 
13034e98e3e1Schristos void
13044e98e3e1Schristos increase_FR_busy (SIM_CPU *cpu, INT out_FR, int cycles)
13054e98e3e1Schristos {
13064e98e3e1Schristos   if (out_FR >= 0)
13074e98e3e1Schristos     {
13084e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
13094e98e3e1Schristos       int *fr = ps->fr_busy;
13104e98e3e1Schristos       fr[out_FR] += cycles;
13114e98e3e1Schristos     }
13124e98e3e1Schristos }
13134e98e3e1Schristos 
13144e98e3e1Schristos /* Top up the latency of the given ACC by the given number of cycles.  */
13154e98e3e1Schristos void
13164e98e3e1Schristos update_ACC_latency (SIM_CPU *cpu, INT out_ACC, int cycles)
13174e98e3e1Schristos {
13184e98e3e1Schristos   if (out_ACC >= 0)
13194e98e3e1Schristos     {
13204e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
13214e98e3e1Schristos       int *acc = ps->acc_latency;
13224e98e3e1Schristos       if (acc[out_ACC] < cycles)
13234e98e3e1Schristos 	acc[out_ACC] = cycles;
13244e98e3e1Schristos     }
13254e98e3e1Schristos }
13264e98e3e1Schristos 
13274e98e3e1Schristos /* Top up the latency of the given CCR by the given number of cycles.  */
13284e98e3e1Schristos void
13294e98e3e1Schristos update_CCR_latency (SIM_CPU *cpu, INT out_CCR, int cycles)
13304e98e3e1Schristos {
13314e98e3e1Schristos   if (out_CCR >= 0)
13324e98e3e1Schristos     {
13334e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
13344e98e3e1Schristos       int *ccr = ps->ccr_latency;
13354e98e3e1Schristos       if (ccr[out_CCR] < cycles)
13364e98e3e1Schristos 	ccr[out_CCR] = cycles;
13374e98e3e1Schristos     }
13384e98e3e1Schristos }
13394e98e3e1Schristos 
13404e98e3e1Schristos /* Top up the latency of the given SPR by the given number of cycles.  */
13414e98e3e1Schristos void
13424e98e3e1Schristos update_SPR_latency (SIM_CPU *cpu, INT out_SPR, int cycles)
13434e98e3e1Schristos {
13444e98e3e1Schristos   if (out_SPR >= 0)
13454e98e3e1Schristos     {
13464e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
13474e98e3e1Schristos       int *spr = ps->spr_latency;
13484e98e3e1Schristos       if (spr[out_SPR] < cycles)
13494e98e3e1Schristos 	spr[out_SPR] = cycles;
13504e98e3e1Schristos     }
13514e98e3e1Schristos }
13524e98e3e1Schristos 
13534e98e3e1Schristos /* Top up the latency of the given integer division resource by the given
13544e98e3e1Schristos    number of cycles.  */
13554e98e3e1Schristos void
13564e98e3e1Schristos update_idiv_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
13574e98e3e1Schristos {
13584e98e3e1Schristos   /* operate directly on the busy cycles since each resource can only
13594e98e3e1Schristos      be used once in a VLIW insn.  */
13604e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
13614e98e3e1Schristos   int *r = ps->idiv_busy;
13624e98e3e1Schristos   r[in_resource] = cycles;
13634e98e3e1Schristos }
13644e98e3e1Schristos 
13654e98e3e1Schristos /* Set the latency of the given resource to the given number of cycles.  */
13664e98e3e1Schristos void
13674e98e3e1Schristos update_fdiv_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
13684e98e3e1Schristos {
13694e98e3e1Schristos   /* operate directly on the busy cycles since each resource can only
13704e98e3e1Schristos      be used once in a VLIW insn.  */
13714e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
13724e98e3e1Schristos   int *r = ps->fdiv_busy;
13734e98e3e1Schristos   r[in_resource] = cycles;
13744e98e3e1Schristos }
13754e98e3e1Schristos 
13764e98e3e1Schristos /* Set the latency of the given resource to the given number of cycles.  */
13774e98e3e1Schristos void
13784e98e3e1Schristos update_fsqrt_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
13794e98e3e1Schristos {
13804e98e3e1Schristos   /* operate directly on the busy cycles since each resource can only
13814e98e3e1Schristos      be used once in a VLIW insn.  */
13824e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
13834e98e3e1Schristos   int *r = ps->fsqrt_busy;
13844e98e3e1Schristos   r[in_resource] = cycles;
13854e98e3e1Schristos }
13864e98e3e1Schristos 
13874e98e3e1Schristos /* Set the latency of the given resource to the given number of cycles.  */
13884e98e3e1Schristos void
13894e98e3e1Schristos update_float_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
13904e98e3e1Schristos {
13914e98e3e1Schristos   /* operate directly on the busy cycles since each resource can only
13924e98e3e1Schristos      be used once in a VLIW insn.  */
13934e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
13944e98e3e1Schristos   int *r = ps->float_busy;
13954e98e3e1Schristos   r[in_resource] = cycles;
13964e98e3e1Schristos }
13974e98e3e1Schristos 
13984e98e3e1Schristos void
13994e98e3e1Schristos update_media_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
14004e98e3e1Schristos {
14014e98e3e1Schristos   /* operate directly on the busy cycles since each resource can only
14024e98e3e1Schristos      be used once in a VLIW insn.  */
14034e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
14044e98e3e1Schristos   int *r = ps->media_busy;
14054e98e3e1Schristos   r[in_resource] = cycles;
14064e98e3e1Schristos }
14074e98e3e1Schristos 
14084e98e3e1Schristos /* Set the branch penalty to the given number of cycles.  */
14094e98e3e1Schristos void
14104e98e3e1Schristos update_branch_penalty (SIM_CPU *cpu, int cycles)
14114e98e3e1Schristos {
14124e98e3e1Schristos   /* operate directly on the busy cycles since only one branch can occur
14134e98e3e1Schristos      in a VLIW insn.  */
14144e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
14154e98e3e1Schristos   ps->branch_penalty = cycles;
14164e98e3e1Schristos }
14174e98e3e1Schristos 
14184e98e3e1Schristos /* Check the availability of the given GR register and update the number
14194e98e3e1Schristos    of cycles the current VLIW insn must wait until it is available.  */
14204e98e3e1Schristos void
14214e98e3e1Schristos vliw_wait_for_GR (SIM_CPU *cpu, INT in_GR)
14224e98e3e1Schristos {
14234e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
14244e98e3e1Schristos   int *gr = ps->gr_busy;
14254e98e3e1Schristos   /* If the latency of the register is greater than the current wait
14264e98e3e1Schristos      then update the current wait.  */
14274e98e3e1Schristos   if (in_GR >= 0 && gr[in_GR] > ps->vliw_wait)
14284e98e3e1Schristos     {
14294e98e3e1Schristos       if (TRACE_INSN_P (cpu))
14304e98e3e1Schristos 	sprintf (hazard_name, "Data hazard for gr%d:", in_GR);
14314e98e3e1Schristos       ps->vliw_wait = gr[in_GR];
14324e98e3e1Schristos     }
14334e98e3e1Schristos }
14344e98e3e1Schristos 
14354e98e3e1Schristos /* Check the availability of the given GR register and update the number
14364e98e3e1Schristos    of cycles the current VLIW insn must wait until it is available.  */
14374e98e3e1Schristos void
14384e98e3e1Schristos vliw_wait_for_GRdouble (SIM_CPU *cpu, INT in_GR)
14394e98e3e1Schristos {
14404e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
14414e98e3e1Schristos   int *gr = ps->gr_busy;
14424e98e3e1Schristos   /* If the latency of the register is greater than the current wait
14434e98e3e1Schristos      then update the current wait.  */
14444e98e3e1Schristos   if (in_GR >= 0)
14454e98e3e1Schristos     {
14464e98e3e1Schristos       if (gr[in_GR] > ps->vliw_wait)
14474e98e3e1Schristos 	{
14484e98e3e1Schristos 	  if (TRACE_INSN_P (cpu))
14494e98e3e1Schristos 	    sprintf (hazard_name, "Data hazard for gr%d:", in_GR);
14504e98e3e1Schristos 	  ps->vliw_wait = gr[in_GR];
14514e98e3e1Schristos 	}
14524e98e3e1Schristos       if (in_GR < 63 && gr[in_GR + 1] > ps->vliw_wait)
14534e98e3e1Schristos 	{
14544e98e3e1Schristos 	  if (TRACE_INSN_P (cpu))
14554e98e3e1Schristos 	    sprintf (hazard_name, "Data hazard for gr%d:", in_GR + 1);
14564e98e3e1Schristos 	  ps->vliw_wait = gr[in_GR + 1];
14574e98e3e1Schristos 	}
14584e98e3e1Schristos     }
14594e98e3e1Schristos }
14604e98e3e1Schristos 
14614e98e3e1Schristos /* Check the availability of the given FR register and update the number
14624e98e3e1Schristos    of cycles the current VLIW insn must wait until it is available.  */
14634e98e3e1Schristos void
14644e98e3e1Schristos vliw_wait_for_FR (SIM_CPU *cpu, INT in_FR)
14654e98e3e1Schristos {
14664e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
14674e98e3e1Schristos   int *fr = ps->fr_busy;
14684e98e3e1Schristos   /* If the latency of the register is greater than the current wait
14694e98e3e1Schristos      then update the current wait.  */
14704e98e3e1Schristos   if (in_FR >= 0 && fr[in_FR] > ps->vliw_wait)
14714e98e3e1Schristos     {
14724e98e3e1Schristos       if (TRACE_INSN_P (cpu))
14734e98e3e1Schristos 	sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
14744e98e3e1Schristos       ps->vliw_wait = fr[in_FR];
14754e98e3e1Schristos     }
14764e98e3e1Schristos }
14774e98e3e1Schristos 
14784e98e3e1Schristos /* Check the availability of the given GR register and update the number
14794e98e3e1Schristos    of cycles the current VLIW insn must wait until it is available.  */
14804e98e3e1Schristos void
14814e98e3e1Schristos vliw_wait_for_FRdouble (SIM_CPU *cpu, INT in_FR)
14824e98e3e1Schristos {
14834e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
14844e98e3e1Schristos   int *fr = ps->fr_busy;
14854e98e3e1Schristos   /* If the latency of the register is greater than the current wait
14864e98e3e1Schristos      then update the current wait.  */
14874e98e3e1Schristos   if (in_FR >= 0)
14884e98e3e1Schristos     {
14894e98e3e1Schristos       if (fr[in_FR] > ps->vliw_wait)
14904e98e3e1Schristos 	{
14914e98e3e1Schristos 	  if (TRACE_INSN_P (cpu))
14924e98e3e1Schristos 	    sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
14934e98e3e1Schristos 	  ps->vliw_wait = fr[in_FR];
14944e98e3e1Schristos 	}
14954e98e3e1Schristos       if (in_FR < 63 && fr[in_FR + 1] > ps->vliw_wait)
14964e98e3e1Schristos 	{
14974e98e3e1Schristos 	  if (TRACE_INSN_P (cpu))
14984e98e3e1Schristos 	    sprintf (hazard_name, "Data hazard for fr%d:", in_FR + 1);
14994e98e3e1Schristos 	  ps->vliw_wait = fr[in_FR + 1];
15004e98e3e1Schristos 	}
15014e98e3e1Schristos     }
15024e98e3e1Schristos }
15034e98e3e1Schristos 
15044e98e3e1Schristos /* Check the availability of the given CCR register and update the number
15054e98e3e1Schristos    of cycles the current VLIW insn must wait until it is available.  */
15064e98e3e1Schristos void
15074e98e3e1Schristos vliw_wait_for_CCR (SIM_CPU *cpu, INT in_CCR)
15084e98e3e1Schristos {
15094e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
15104e98e3e1Schristos   int *ccr = ps->ccr_busy;
15114e98e3e1Schristos   /* If the latency of the register is greater than the current wait
15124e98e3e1Schristos      then update the current wait.  */
15134e98e3e1Schristos   if (in_CCR >= 0 && ccr[in_CCR] > ps->vliw_wait)
15144e98e3e1Schristos     {
15154e98e3e1Schristos       if (TRACE_INSN_P (cpu))
15164e98e3e1Schristos 	{
15174e98e3e1Schristos 	  if (in_CCR > 3)
15184e98e3e1Schristos 	    sprintf (hazard_name, "Data hazard for icc%d:", in_CCR-4);
15194e98e3e1Schristos 	  else
15204e98e3e1Schristos 	    sprintf (hazard_name, "Data hazard for fcc%d:", in_CCR);
15214e98e3e1Schristos 	}
15224e98e3e1Schristos       ps->vliw_wait = ccr[in_CCR];
15234e98e3e1Schristos     }
15244e98e3e1Schristos }
15254e98e3e1Schristos 
15264e98e3e1Schristos /* Check the availability of the given ACC register and update the number
15274e98e3e1Schristos    of cycles the current VLIW insn must wait until it is available.  */
15284e98e3e1Schristos void
15294e98e3e1Schristos vliw_wait_for_ACC (SIM_CPU *cpu, INT in_ACC)
15304e98e3e1Schristos {
15314e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
15324e98e3e1Schristos   int *acc = ps->acc_busy;
15334e98e3e1Schristos   /* If the latency of the register is greater than the current wait
15344e98e3e1Schristos      then update the current wait.  */
15354e98e3e1Schristos   if (in_ACC >= 0 && acc[in_ACC] > ps->vliw_wait)
15364e98e3e1Schristos     {
15374e98e3e1Schristos       if (TRACE_INSN_P (cpu))
15384e98e3e1Schristos 	sprintf (hazard_name, "Data hazard for acc%d:", in_ACC);
15394e98e3e1Schristos       ps->vliw_wait = acc[in_ACC];
15404e98e3e1Schristos     }
15414e98e3e1Schristos }
15424e98e3e1Schristos 
15434e98e3e1Schristos /* Check the availability of the given SPR register and update the number
15444e98e3e1Schristos    of cycles the current VLIW insn must wait until it is available.  */
15454e98e3e1Schristos void
15464e98e3e1Schristos vliw_wait_for_SPR (SIM_CPU *cpu, INT in_SPR)
15474e98e3e1Schristos {
15484e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
15494e98e3e1Schristos   int *spr = ps->spr_busy;
15504e98e3e1Schristos   /* If the latency of the register is greater than the current wait
15514e98e3e1Schristos      then update the current wait.  */
15524e98e3e1Schristos   if (in_SPR >= 0 && spr[in_SPR] > ps->vliw_wait)
15534e98e3e1Schristos     {
15544e98e3e1Schristos       if (TRACE_INSN_P (cpu))
15554e98e3e1Schristos 	sprintf (hazard_name, "Data hazard for spr %d:", in_SPR);
15564e98e3e1Schristos       ps->vliw_wait = spr[in_SPR];
15574e98e3e1Schristos     }
15584e98e3e1Schristos }
15594e98e3e1Schristos 
15604e98e3e1Schristos /* Check the availability of the given integer division resource and update
15614e98e3e1Schristos    the number of cycles the current VLIW insn must wait until it is available.
15624e98e3e1Schristos */
15634e98e3e1Schristos void
15644e98e3e1Schristos vliw_wait_for_idiv_resource (SIM_CPU *cpu, INT in_resource)
15654e98e3e1Schristos {
15664e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
15674e98e3e1Schristos   int *r = ps->idiv_busy;
15684e98e3e1Schristos   /* If the latency of the resource is greater than the current wait
15694e98e3e1Schristos      then update the current wait.  */
15704e98e3e1Schristos   if (r[in_resource] > ps->vliw_wait)
15714e98e3e1Schristos     {
15724e98e3e1Schristos       if (TRACE_INSN_P (cpu))
15734e98e3e1Schristos 	{
15744e98e3e1Schristos 	  sprintf (hazard_name, "Resource hazard for integer division in slot I%d:", in_resource);
15754e98e3e1Schristos 	}
15764e98e3e1Schristos       ps->vliw_wait = r[in_resource];
15774e98e3e1Schristos     }
15784e98e3e1Schristos }
15794e98e3e1Schristos 
15804e98e3e1Schristos /* Check the availability of the given float division resource and update
15814e98e3e1Schristos    the number of cycles the current VLIW insn must wait until it is available.
15824e98e3e1Schristos */
15834e98e3e1Schristos void
15844e98e3e1Schristos vliw_wait_for_fdiv_resource (SIM_CPU *cpu, INT in_resource)
15854e98e3e1Schristos {
15864e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
15874e98e3e1Schristos   int *r = ps->fdiv_busy;
15884e98e3e1Schristos   /* If the latency of the resource is greater than the current wait
15894e98e3e1Schristos      then update the current wait.  */
15904e98e3e1Schristos   if (r[in_resource] > ps->vliw_wait)
15914e98e3e1Schristos     {
15924e98e3e1Schristos       if (TRACE_INSN_P (cpu))
15934e98e3e1Schristos 	{
15944e98e3e1Schristos 	  sprintf (hazard_name, "Resource hazard for floating point division in slot F%d:", in_resource);
15954e98e3e1Schristos 	}
15964e98e3e1Schristos       ps->vliw_wait = r[in_resource];
15974e98e3e1Schristos     }
15984e98e3e1Schristos }
15994e98e3e1Schristos 
16004e98e3e1Schristos /* Check the availability of the given float square root resource and update
16014e98e3e1Schristos    the number of cycles the current VLIW insn must wait until it is available.
16024e98e3e1Schristos */
16034e98e3e1Schristos void
16044e98e3e1Schristos vliw_wait_for_fsqrt_resource (SIM_CPU *cpu, INT in_resource)
16054e98e3e1Schristos {
16064e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
16074e98e3e1Schristos   int *r = ps->fsqrt_busy;
16084e98e3e1Schristos   /* If the latency of the resource is greater than the current wait
16094e98e3e1Schristos      then update the current wait.  */
16104e98e3e1Schristos   if (r[in_resource] > ps->vliw_wait)
16114e98e3e1Schristos     {
16124e98e3e1Schristos       if (TRACE_INSN_P (cpu))
16134e98e3e1Schristos 	{
16144e98e3e1Schristos 	  sprintf (hazard_name, "Resource hazard for square root in slot F%d:", in_resource);
16154e98e3e1Schristos 	}
16164e98e3e1Schristos       ps->vliw_wait = r[in_resource];
16174e98e3e1Schristos     }
16184e98e3e1Schristos }
16194e98e3e1Schristos 
16204e98e3e1Schristos /* Check the availability of the given float unit resource and update
16214e98e3e1Schristos    the number of cycles the current VLIW insn must wait until it is available.
16224e98e3e1Schristos */
16234e98e3e1Schristos void
16244e98e3e1Schristos vliw_wait_for_float_resource (SIM_CPU *cpu, INT in_resource)
16254e98e3e1Schristos {
16264e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
16274e98e3e1Schristos   int *r = ps->float_busy;
16284e98e3e1Schristos   /* If the latency of the resource is greater than the current wait
16294e98e3e1Schristos      then update the current wait.  */
16304e98e3e1Schristos   if (r[in_resource] > ps->vliw_wait)
16314e98e3e1Schristos     {
16324e98e3e1Schristos       if (TRACE_INSN_P (cpu))
16334e98e3e1Schristos 	{
16344e98e3e1Schristos 	  sprintf (hazard_name, "Resource hazard for floating point unit in slot F%d:", in_resource);
16354e98e3e1Schristos 	}
16364e98e3e1Schristos       ps->vliw_wait = r[in_resource];
16374e98e3e1Schristos     }
16384e98e3e1Schristos }
16394e98e3e1Schristos 
16404e98e3e1Schristos /* Check the availability of the given media unit resource and update
16414e98e3e1Schristos    the number of cycles the current VLIW insn must wait until it is available.
16424e98e3e1Schristos */
16434e98e3e1Schristos void
16444e98e3e1Schristos vliw_wait_for_media_resource (SIM_CPU *cpu, INT in_resource)
16454e98e3e1Schristos {
16464e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
16474e98e3e1Schristos   int *r = ps->media_busy;
16484e98e3e1Schristos   /* If the latency of the resource is greater than the current wait
16494e98e3e1Schristos      then update the current wait.  */
16504e98e3e1Schristos   if (r[in_resource] > ps->vliw_wait)
16514e98e3e1Schristos     {
16524e98e3e1Schristos       if (TRACE_INSN_P (cpu))
16534e98e3e1Schristos 	{
16544e98e3e1Schristos 	  sprintf (hazard_name, "Resource hazard for media unit in slot M%d:", in_resource);
16554e98e3e1Schristos 	}
16564e98e3e1Schristos       ps->vliw_wait = r[in_resource];
16574e98e3e1Schristos     }
16584e98e3e1Schristos }
16594e98e3e1Schristos 
16604e98e3e1Schristos /* Run the caches until all requests for the given register(s) are satisfied. */
16614e98e3e1Schristos void
16624e98e3e1Schristos load_wait_for_GR (SIM_CPU *cpu, INT in_GR)
16634e98e3e1Schristos {
16644e98e3e1Schristos   if (in_GR >= 0)
16654e98e3e1Schristos     {
16664e98e3e1Schristos       int wait = 0;
16674e98e3e1Schristos       while (load_pending_for_register (cpu, in_GR, 1/*words*/, REGTYPE_NONE))
16684e98e3e1Schristos 	{
16694e98e3e1Schristos 	  frv_model_advance_cycles (cpu, 1);
16704e98e3e1Schristos 	  ++wait;
16714e98e3e1Schristos 	}
16724e98e3e1Schristos       if (wait)
16734e98e3e1Schristos 	{
16744e98e3e1Schristos 	  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
16754e98e3e1Schristos 	  ps->vliw_wait += wait;
16764e98e3e1Schristos 	  ps->vliw_load_stall += wait;
16774e98e3e1Schristos 	  if (TRACE_INSN_P (cpu))
16784e98e3e1Schristos 	    sprintf (hazard_name, "Data hazard for gr%d:", in_GR);
16794e98e3e1Schristos 	}
16804e98e3e1Schristos     }
16814e98e3e1Schristos }
16824e98e3e1Schristos 
16834e98e3e1Schristos void
16844e98e3e1Schristos load_wait_for_FR (SIM_CPU *cpu, INT in_FR)
16854e98e3e1Schristos {
16864e98e3e1Schristos   if (in_FR >= 0)
16874e98e3e1Schristos     {
16884e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
16894e98e3e1Schristos       int *fr;
16904e98e3e1Schristos       int wait = 0;
16914e98e3e1Schristos       while (load_pending_for_register (cpu, in_FR, 1/*words*/, REGTYPE_FR))
16924e98e3e1Schristos 	{
16934e98e3e1Schristos 	  frv_model_advance_cycles (cpu, 1);
16944e98e3e1Schristos 	  ++wait;
16954e98e3e1Schristos 	}
16964e98e3e1Schristos       /* Post processing time may have been added to the register's
16974e98e3e1Schristos 	 latency after the loads were processed. Account for that too.
16984e98e3e1Schristos       */
16994e98e3e1Schristos       fr = ps->fr_busy;
17004e98e3e1Schristos       if (fr[in_FR])
17014e98e3e1Schristos 	{
17024e98e3e1Schristos 	  wait += fr[in_FR];
17034e98e3e1Schristos 	  frv_model_advance_cycles (cpu, fr[in_FR]);
17044e98e3e1Schristos 	}
17054e98e3e1Schristos       /* Update the vliw_wait with the number of cycles we waited for the
17064e98e3e1Schristos 	 load and any post-processing.  */
17074e98e3e1Schristos       if (wait)
17084e98e3e1Schristos 	{
17094e98e3e1Schristos 	  ps->vliw_wait += wait;
17104e98e3e1Schristos 	  ps->vliw_load_stall += wait;
17114e98e3e1Schristos 	  if (TRACE_INSN_P (cpu))
17124e98e3e1Schristos 	    sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
17134e98e3e1Schristos 	}
17144e98e3e1Schristos     }
17154e98e3e1Schristos }
17164e98e3e1Schristos 
17174e98e3e1Schristos void
17184e98e3e1Schristos load_wait_for_GRdouble (SIM_CPU *cpu, INT in_GR)
17194e98e3e1Schristos {
17204e98e3e1Schristos   if (in_GR >= 0)
17214e98e3e1Schristos     {
17224e98e3e1Schristos       int wait = 0;
17234e98e3e1Schristos       while (load_pending_for_register (cpu, in_GR, 2/*words*/, REGTYPE_NONE))
17244e98e3e1Schristos 	{
17254e98e3e1Schristos 	  frv_model_advance_cycles (cpu, 1);
17264e98e3e1Schristos 	  ++wait;
17274e98e3e1Schristos 	}
17284e98e3e1Schristos       if (wait)
17294e98e3e1Schristos 	{
17304e98e3e1Schristos 	  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
17314e98e3e1Schristos 	  ps->vliw_wait += wait;
17324e98e3e1Schristos 	  ps->vliw_load_stall += wait;
17334e98e3e1Schristos 	  if (TRACE_INSN_P (cpu))
17344e98e3e1Schristos 	    sprintf (hazard_name, "Data hazard for gr%d:", in_GR);
17354e98e3e1Schristos 	}
17364e98e3e1Schristos     }
17374e98e3e1Schristos }
17384e98e3e1Schristos 
17394e98e3e1Schristos void
17404e98e3e1Schristos load_wait_for_FRdouble (SIM_CPU *cpu, INT in_FR)
17414e98e3e1Schristos {
17424e98e3e1Schristos   if (in_FR >= 0)
17434e98e3e1Schristos     {
17444e98e3e1Schristos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
17454e98e3e1Schristos       int *fr;
17464e98e3e1Schristos       int wait = 0;
17474e98e3e1Schristos       while (load_pending_for_register (cpu, in_FR, 2/*words*/, REGTYPE_FR))
17484e98e3e1Schristos 	{
17494e98e3e1Schristos 	  frv_model_advance_cycles (cpu, 1);
17504e98e3e1Schristos 	  ++wait;
17514e98e3e1Schristos 	}
17524e98e3e1Schristos       /* Post processing time may have been added to the registers'
17534e98e3e1Schristos 	 latencies after the loads were processed. Account for that too.
17544e98e3e1Schristos       */
17554e98e3e1Schristos       fr = ps->fr_busy;
17564e98e3e1Schristos       if (fr[in_FR])
17574e98e3e1Schristos 	{
17584e98e3e1Schristos 	  wait += fr[in_FR];
17594e98e3e1Schristos 	  frv_model_advance_cycles (cpu, fr[in_FR]);
17604e98e3e1Schristos 	}
17614e98e3e1Schristos       if (in_FR < 63)
17624e98e3e1Schristos 	{
17634e98e3e1Schristos 	  if (fr[in_FR + 1])
17644e98e3e1Schristos 	    {
17654e98e3e1Schristos 	      wait += fr[in_FR + 1];
17664e98e3e1Schristos 	      frv_model_advance_cycles (cpu, fr[in_FR + 1]);
17674e98e3e1Schristos 	    }
17684e98e3e1Schristos 	}
17694e98e3e1Schristos       /* Update the vliw_wait with the number of cycles we waited for the
17704e98e3e1Schristos 	 load and any post-processing.  */
17714e98e3e1Schristos       if (wait)
17724e98e3e1Schristos 	{
17734e98e3e1Schristos 	  ps->vliw_wait += wait;
17744e98e3e1Schristos 	  ps->vliw_load_stall += wait;
17754e98e3e1Schristos 	  if (TRACE_INSN_P (cpu))
17764e98e3e1Schristos 	    sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
17774e98e3e1Schristos 	}
17784e98e3e1Schristos     }
17794e98e3e1Schristos }
17804e98e3e1Schristos 
17814e98e3e1Schristos void
17824e98e3e1Schristos enforce_full_fr_latency (SIM_CPU *cpu, INT in_FR)
17834e98e3e1Schristos {
17844e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
17854e98e3e1Schristos   ps->fr_busy_adjust [in_FR] = -1;
17864e98e3e1Schristos }
17874e98e3e1Schristos 
17884e98e3e1Schristos /* Calculate how long the post processing for a floating point insn must
17894e98e3e1Schristos    wait for resources to become available.  */
17904b169a6bSchristos void
17914e98e3e1Schristos post_wait_for_FR (SIM_CPU *cpu, INT in_FR)
17924e98e3e1Schristos {
17934e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
17944e98e3e1Schristos   int *fr = ps->fr_busy;
17954e98e3e1Schristos 
17964e98e3e1Schristos   if (in_FR >= 0 && fr[in_FR] > ps->post_wait)
17974e98e3e1Schristos     {
17984e98e3e1Schristos       ps->post_wait = fr[in_FR];
17994e98e3e1Schristos       if (TRACE_INSN_P (cpu))
18004e98e3e1Schristos 	sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
18014e98e3e1Schristos     }
18024e98e3e1Schristos }
18034e98e3e1Schristos 
18044e98e3e1Schristos /* Calculate how long the post processing for a floating point insn must
18054e98e3e1Schristos    wait for resources to become available.  */
18064b169a6bSchristos void
18074e98e3e1Schristos post_wait_for_FRdouble (SIM_CPU *cpu, INT in_FR)
18084e98e3e1Schristos {
18094e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
18104e98e3e1Schristos   int *fr = ps->fr_busy;
18114e98e3e1Schristos 
18124e98e3e1Schristos   if (in_FR >= 0)
18134e98e3e1Schristos     {
18144e98e3e1Schristos       if (fr[in_FR] > ps->post_wait)
18154e98e3e1Schristos 	{
18164e98e3e1Schristos 	  ps->post_wait = fr[in_FR];
18174e98e3e1Schristos 	  if (TRACE_INSN_P (cpu))
18184e98e3e1Schristos 	    sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
18194e98e3e1Schristos 	}
18204e98e3e1Schristos       if (in_FR < 63 && fr[in_FR + 1] > ps->post_wait)
18214e98e3e1Schristos 	{
18224e98e3e1Schristos 	  ps->post_wait = fr[in_FR + 1];
18234e98e3e1Schristos 	  if (TRACE_INSN_P (cpu))
18244e98e3e1Schristos 	    sprintf (hazard_name, "Data hazard for fr%d:", in_FR + 1);
18254e98e3e1Schristos 	}
18264e98e3e1Schristos     }
18274e98e3e1Schristos }
18284e98e3e1Schristos 
18294b169a6bSchristos void
18304e98e3e1Schristos post_wait_for_ACC (SIM_CPU *cpu, INT in_ACC)
18314e98e3e1Schristos {
18324e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
18334e98e3e1Schristos   int *acc = ps->acc_busy;
18344e98e3e1Schristos 
18354e98e3e1Schristos   if (in_ACC >= 0 && acc[in_ACC] > ps->post_wait)
18364e98e3e1Schristos     {
18374e98e3e1Schristos       ps->post_wait = acc[in_ACC];
18384e98e3e1Schristos       if (TRACE_INSN_P (cpu))
18394e98e3e1Schristos 	sprintf (hazard_name, "Data hazard for acc%d:", in_ACC);
18404e98e3e1Schristos     }
18414e98e3e1Schristos }
18424e98e3e1Schristos 
18434b169a6bSchristos void
18444e98e3e1Schristos post_wait_for_CCR (SIM_CPU *cpu, INT in_CCR)
18454e98e3e1Schristos {
18464e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
18474e98e3e1Schristos   int *ccr = ps->ccr_busy;
18484e98e3e1Schristos 
18494e98e3e1Schristos   if (in_CCR >= 0 && ccr[in_CCR] > ps->post_wait)
18504e98e3e1Schristos     {
18514e98e3e1Schristos       ps->post_wait = ccr[in_CCR];
18524e98e3e1Schristos       if (TRACE_INSN_P (cpu))
18534e98e3e1Schristos 	{
18544e98e3e1Schristos 	  if (in_CCR > 3)
18554e98e3e1Schristos 	    sprintf (hazard_name, "Data hazard for icc%d:", in_CCR - 4);
18564e98e3e1Schristos 	  else
18574e98e3e1Schristos 	    sprintf (hazard_name, "Data hazard for fcc%d:", in_CCR);
18584e98e3e1Schristos 	}
18594e98e3e1Schristos     }
18604e98e3e1Schristos }
18614e98e3e1Schristos 
18624b169a6bSchristos void
18634e98e3e1Schristos post_wait_for_SPR (SIM_CPU *cpu, INT in_SPR)
18644e98e3e1Schristos {
18654e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
18664e98e3e1Schristos   int *spr = ps->spr_busy;
18674e98e3e1Schristos 
18684e98e3e1Schristos   if (in_SPR >= 0 && spr[in_SPR] > ps->post_wait)
18694e98e3e1Schristos     {
18704e98e3e1Schristos       ps->post_wait = spr[in_SPR];
18714e98e3e1Schristos       if (TRACE_INSN_P (cpu))
18724e98e3e1Schristos 	sprintf (hazard_name, "Data hazard for spr[%d]:", in_SPR);
18734e98e3e1Schristos     }
18744e98e3e1Schristos }
18754e98e3e1Schristos 
18764b169a6bSchristos void
18774e98e3e1Schristos post_wait_for_fdiv (SIM_CPU *cpu, INT slot)
18784e98e3e1Schristos {
18794e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
18804e98e3e1Schristos   int *fdiv = ps->fdiv_busy;
18814e98e3e1Schristos 
18824e98e3e1Schristos   /* Multiple floating point divisions in the same slot need only wait 1
18834e98e3e1Schristos      extra cycle.  */
18844e98e3e1Schristos   if (fdiv[slot] > 0 && 1 > ps->post_wait)
18854e98e3e1Schristos     {
18864e98e3e1Schristos       ps->post_wait = 1;
18874e98e3e1Schristos       if (TRACE_INSN_P (cpu))
18884e98e3e1Schristos 	{
18894e98e3e1Schristos 	  sprintf (hazard_name, "Resource hazard for floating point division in slot F%d:", slot);
18904e98e3e1Schristos 	}
18914e98e3e1Schristos     }
18924e98e3e1Schristos }
18934e98e3e1Schristos 
18944b169a6bSchristos void
18954e98e3e1Schristos post_wait_for_fsqrt (SIM_CPU *cpu, INT slot)
18964e98e3e1Schristos {
18974e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
18984e98e3e1Schristos   int *fsqrt = ps->fsqrt_busy;
18994e98e3e1Schristos 
19004e98e3e1Schristos   /* Multiple floating point square roots in the same slot need only wait 1
19014e98e3e1Schristos      extra cycle.  */
19024e98e3e1Schristos   if (fsqrt[slot] > 0 && 1 > ps->post_wait)
19034e98e3e1Schristos     {
19044e98e3e1Schristos       ps->post_wait = 1;
19054e98e3e1Schristos       if (TRACE_INSN_P (cpu))
19064e98e3e1Schristos 	{
19074e98e3e1Schristos 	  sprintf (hazard_name, "Resource hazard for square root in slot F%d:", slot);
19084e98e3e1Schristos 	}
19094e98e3e1Schristos     }
19104e98e3e1Schristos }
19114e98e3e1Schristos 
19124b169a6bSchristos void
19134e98e3e1Schristos post_wait_for_float (SIM_CPU *cpu, INT slot)
19144e98e3e1Schristos {
19154e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
19164e98e3e1Schristos   int *flt = ps->float_busy;
19174e98e3e1Schristos 
19184e98e3e1Schristos   /* Multiple floating point square roots in the same slot need only wait 1
19194e98e3e1Schristos      extra cycle.  */
19204e98e3e1Schristos   if (flt[slot] > ps->post_wait)
19214e98e3e1Schristos     {
19224e98e3e1Schristos       ps->post_wait = flt[slot];
19234e98e3e1Schristos       if (TRACE_INSN_P (cpu))
19244e98e3e1Schristos 	{
19254e98e3e1Schristos 	  sprintf (hazard_name, "Resource hazard for floating point unit in slot F%d:", slot);
19264e98e3e1Schristos 	}
19274e98e3e1Schristos     }
19284e98e3e1Schristos }
19294e98e3e1Schristos 
19304b169a6bSchristos void
19314e98e3e1Schristos post_wait_for_media (SIM_CPU *cpu, INT slot)
19324e98e3e1Schristos {
19334e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
19344e98e3e1Schristos   int *media = ps->media_busy;
19354e98e3e1Schristos 
19364e98e3e1Schristos   /* Multiple floating point square roots in the same slot need only wait 1
19374e98e3e1Schristos      extra cycle.  */
19384e98e3e1Schristos   if (media[slot] > ps->post_wait)
19394e98e3e1Schristos     {
19404e98e3e1Schristos       ps->post_wait = media[slot];
19414e98e3e1Schristos       if (TRACE_INSN_P (cpu))
19424e98e3e1Schristos 	{
19434e98e3e1Schristos 	  sprintf (hazard_name, "Resource hazard for media unit in slot M%d:", slot);
19444e98e3e1Schristos 	}
19454e98e3e1Schristos     }
19464e98e3e1Schristos }
19474e98e3e1Schristos 
19484e98e3e1Schristos /* Print cpu-specific profile information.  */
19494e98e3e1Schristos #define COMMAS(n) sim_add_commas (comma_buf, sizeof (comma_buf), (n))
19504e98e3e1Schristos 
19514e98e3e1Schristos static void
19524e98e3e1Schristos print_cache (SIM_CPU *cpu, FRV_CACHE *cache, const char *cache_name)
19534e98e3e1Schristos {
19544e98e3e1Schristos   SIM_DESC sd = CPU_STATE (cpu);
19554e98e3e1Schristos 
19564e98e3e1Schristos   if (cache != NULL)
19574e98e3e1Schristos     {
19584e98e3e1Schristos       char comma_buf[20];
19594e98e3e1Schristos       unsigned accesses;
19604e98e3e1Schristos 
19614e98e3e1Schristos       sim_io_printf (sd, "  %s Cache\n\n", cache_name);
19624e98e3e1Schristos       accesses = cache->statistics.accesses;
19634e98e3e1Schristos       sim_io_printf (sd, "    Total accesses:  %s\n", COMMAS (accesses));
19644e98e3e1Schristos       if (accesses != 0)
19654e98e3e1Schristos 	{
19664e98e3e1Schristos 	  float rate;
19674e98e3e1Schristos 	  unsigned hits = cache->statistics.hits;
19684e98e3e1Schristos 	  sim_io_printf (sd, "    Hits:            %s\n", COMMAS (hits));
19694e98e3e1Schristos 	  rate = (float)hits / accesses;
19704e98e3e1Schristos 	  sim_io_printf (sd, "    Hit rate:        %.2f%%\n", rate * 100);
19714e98e3e1Schristos 	}
19724e98e3e1Schristos     }
19734e98e3e1Schristos   else
19744e98e3e1Schristos     sim_io_printf (sd, "  Model %s has no %s cache\n",
19754e98e3e1Schristos 		   MODEL_NAME (CPU_MODEL (cpu)), cache_name);
19764e98e3e1Schristos 
19774e98e3e1Schristos   sim_io_printf (sd, "\n");
19784e98e3e1Schristos }
19794e98e3e1Schristos 
19804e98e3e1Schristos /* This table must correspond to the UNIT_ATTR table in
19814e98e3e1Schristos    opcodes/frv-desc.h. Only the units up to UNIT_C need be
19824e98e3e1Schristos    listed since the others cannot occur after mapping.  */
19834e98e3e1Schristos static char *
19844e98e3e1Schristos slot_names[] =
19854e98e3e1Schristos {
19864e98e3e1Schristos   "none",
19874e98e3e1Schristos   "I0", "I1", "I01", "I2", "I3", "IALL",
19884e98e3e1Schristos   "FM0", "FM1", "FM01", "FM2", "FM3", "FMALL", "FMLOW",
19894e98e3e1Schristos   "B0", "B1", "B01",
19904e98e3e1Schristos   "C"
19914e98e3e1Schristos };
19924e98e3e1Schristos 
19934e98e3e1Schristos static void
1994*854b025fSchristos print_parallel (SIM_CPU *cpu, bool verbose)
19954e98e3e1Schristos {
19964e98e3e1Schristos   SIM_DESC sd = CPU_STATE (cpu);
19974e98e3e1Schristos   PROFILE_DATA *p = CPU_PROFILE_DATA (cpu);
19984e98e3e1Schristos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
19994e98e3e1Schristos   unsigned total, vliw;
20004e98e3e1Schristos   char comma_buf[20];
20014e98e3e1Schristos   float average;
20024e98e3e1Schristos 
20034e98e3e1Schristos   sim_io_printf (sd, "Model %s Parallelization\n\n",
20044e98e3e1Schristos 		 MODEL_NAME (CPU_MODEL (cpu)));
20054e98e3e1Schristos 
20064e98e3e1Schristos   total = PROFILE_TOTAL_INSN_COUNT (p);
20074e98e3e1Schristos   sim_io_printf (sd, "  Total instructions:           %s\n", COMMAS (total));
20084e98e3e1Schristos   vliw = ps->vliw_insns;
20094e98e3e1Schristos   sim_io_printf (sd, "  VLIW instructions:            %s\n", COMMAS (vliw));
20104e98e3e1Schristos   average = (float)total / vliw;
20114e98e3e1Schristos   sim_io_printf (sd, "  Average VLIW length:          %.2f\n", average);
20124e98e3e1Schristos   average = (float)PROFILE_MODEL_TOTAL_CYCLES (p) / vliw;
20134e98e3e1Schristos   sim_io_printf (sd, "  Cycles per VLIW instruction:  %.2f\n", average);
20144e98e3e1Schristos   average = (float)total / PROFILE_MODEL_TOTAL_CYCLES (p);
20154e98e3e1Schristos   sim_io_printf (sd, "  Instructions per cycle:       %.2f\n", average);
20164e98e3e1Schristos 
20174e98e3e1Schristos   if (verbose)
20184e98e3e1Schristos     {
20194e98e3e1Schristos       int i;
20204e98e3e1Schristos       int max_val = 0;
20214e98e3e1Schristos       int max_name_len = 0;
20224e98e3e1Schristos       for (i = UNIT_NIL + 1; i < UNIT_NUM_UNITS; ++i)
20234e98e3e1Schristos 	{
20244e98e3e1Schristos 	  if (INSNS_IN_SLOT (i))
20254e98e3e1Schristos 	    {
20264e98e3e1Schristos 	      int len;
20274e98e3e1Schristos 	      if (INSNS_IN_SLOT (i) > max_val)
20284e98e3e1Schristos 		max_val = INSNS_IN_SLOT (i);
20294e98e3e1Schristos 	      len = strlen (slot_names[i]);
20304e98e3e1Schristos 	      if (len > max_name_len)
20314e98e3e1Schristos 		max_name_len = len;
20324e98e3e1Schristos 	    }
20334e98e3e1Schristos 	}
20344e98e3e1Schristos       if (max_val > 0)
20354e98e3e1Schristos 	{
20364e98e3e1Schristos 	  sim_io_printf (sd, "\n");
20374e98e3e1Schristos 	  sim_io_printf (sd, "  Instructions per slot:\n");
20384e98e3e1Schristos 	  sim_io_printf (sd, "\n");
20394e98e3e1Schristos 	  for (i = UNIT_NIL + 1; i < UNIT_NUM_UNITS; ++i)
20404e98e3e1Schristos 	    {
20414e98e3e1Schristos 	      if (INSNS_IN_SLOT (i) != 0)
20424e98e3e1Schristos 		{
20434e98e3e1Schristos 		  sim_io_printf (sd, "  %*s: %*s: ",
20444e98e3e1Schristos 				 max_name_len, slot_names[i],
20454e98e3e1Schristos 				 max_val < 10000 ? 5 : 10,
20464e98e3e1Schristos 				 COMMAS (INSNS_IN_SLOT (i)));
20474e98e3e1Schristos 		  sim_profile_print_bar (sd, cpu, PROFILE_HISTOGRAM_WIDTH,
20484e98e3e1Schristos 					 INSNS_IN_SLOT (i),
20494e98e3e1Schristos 					 max_val);
20504e98e3e1Schristos 		  sim_io_printf (sd, "\n");
20514e98e3e1Schristos 		}
20524e98e3e1Schristos 	    }
20534e98e3e1Schristos 	} /* details to print */
20544e98e3e1Schristos     } /* verbose */
20554e98e3e1Schristos 
20564e98e3e1Schristos   sim_io_printf (sd, "\n");
20574e98e3e1Schristos }
20584e98e3e1Schristos 
20594e98e3e1Schristos void
2060*854b025fSchristos frv_profile_info (SIM_CPU *cpu, bool verbose)
20614e98e3e1Schristos {
20624e98e3e1Schristos   /* FIXME: Need to add smp support.  */
20634e98e3e1Schristos   PROFILE_DATA *p = CPU_PROFILE_DATA (cpu);
20644e98e3e1Schristos 
20654e98e3e1Schristos #if WITH_PROFILE_PARALLEL_P
20664e98e3e1Schristos   if (PROFILE_FLAGS (p) [PROFILE_PARALLEL_IDX])
20674e98e3e1Schristos     print_parallel (cpu, verbose);
20684e98e3e1Schristos #endif
20694e98e3e1Schristos 
20704e98e3e1Schristos #if WITH_PROFILE_CACHE_P
20714e98e3e1Schristos   if (PROFILE_FLAGS (p) [PROFILE_CACHE_IDX])
20724e98e3e1Schristos     {
20734e98e3e1Schristos       SIM_DESC sd = CPU_STATE (cpu);
20744e98e3e1Schristos       sim_io_printf (sd, "Model %s Cache Statistics\n\n",
20754e98e3e1Schristos 		     MODEL_NAME (CPU_MODEL (cpu)));
20764e98e3e1Schristos       print_cache (cpu, CPU_INSN_CACHE (cpu), "Instruction");
20774e98e3e1Schristos       print_cache (cpu, CPU_DATA_CACHE (cpu), "Data");
20784e98e3e1Schristos     }
20794e98e3e1Schristos #endif /* WITH_PROFILE_CACHE_P */
20804e98e3e1Schristos }
20814e98e3e1Schristos 
20824e98e3e1Schristos /* A hack to get registers referenced for profiling.  */
20834e98e3e1Schristos SI frv_ref_SI (SI ref) {return ref;}
20844e98e3e1Schristos #endif /* WITH_PROFILE_MODEL_P */
2085