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