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