123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082 |
- /* frv simulator machine independent profiling code.
- Copyright (C) 1998-2015 Free Software Foundation, Inc.
- Contributed by Red Hat
- This file is part of the GNU simulators.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #define WANT_CPU
- #define WANT_CPU_FRVBF
- #include "sim-main.h"
- #include "bfd.h"
- #if WITH_PROFILE_MODEL_P
- #include "profile.h"
- #include "profile-fr400.h"
- #include "profile-fr500.h"
- #include "profile-fr550.h"
- static void
- reset_gr_flags (SIM_CPU *cpu, INT gr)
- {
- SIM_DESC sd = CPU_STATE (cpu);
- if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400
- || STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450)
- fr400_reset_gr_flags (cpu, gr);
- /* Other machines have no gr flags right now. */
- }
- static void
- reset_fr_flags (SIM_CPU *cpu, INT fr)
- {
- SIM_DESC sd = CPU_STATE (cpu);
- if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400
- || STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450)
- fr400_reset_fr_flags (cpu, fr);
- else if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr500)
- fr500_reset_fr_flags (cpu, fr);
- }
- static void
- reset_acc_flags (SIM_CPU *cpu, INT acc)
- {
- SIM_DESC sd = CPU_STATE (cpu);
- if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400
- || STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450)
- fr400_reset_acc_flags (cpu, acc);
- /* Other machines have no acc flags right now. */
- }
- static void
- reset_cc_flags (SIM_CPU *cpu, INT cc)
- {
- SIM_DESC sd = CPU_STATE (cpu);
- if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr500)
- fr500_reset_cc_flags (cpu, cc);
- /* Other machines have no cc flags. */
- }
- void
- set_use_is_gr_complex (SIM_CPU *cpu, INT gr)
- {
- if (gr != -1)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- reset_gr_flags (cpu, gr);
- ps->cur_gr_complex |= (((DI)1) << gr);
- }
- }
- void
- set_use_not_gr_complex (SIM_CPU *cpu, INT gr)
- {
- if (gr != -1)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- ps->cur_gr_complex &= ~(((DI)1) << gr);
- }
- }
- int
- use_is_gr_complex (SIM_CPU *cpu, INT gr)
- {
- if (gr != -1)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- return ps->cur_gr_complex & (((DI)1) << gr);
- }
- return 0;
- }
- /* Globals flag indicates whether this insn is being modeled. */
- enum FRV_INSN_MODELING model_insn = FRV_INSN_NO_MODELING;
- /* static buffer for the name of the currently most restrictive hazard. */
- static char hazard_name[100] = "";
- /* Print information about the wait applied to an entire VLIW insn. */
- FRV_INSN_FETCH_BUFFER frv_insn_fetch_buffer[]
- = {
- {1, NO_REQNO}, {1, NO_REQNO} /* init with impossible address. */
- };
- enum cache_request
- {
- cache_load,
- cache_invalidate,
- cache_flush,
- cache_preload,
- cache_unlock
- };
- /* A queue of load requests from the data cache. Use to keep track of loads
- which are still pending. */
- /* TODO -- some of these are mutually exclusive and can use a union. */
- typedef struct
- {
- FRV_CACHE *cache;
- unsigned reqno;
- SI address;
- int length;
- int is_signed;
- int regnum;
- int cycles;
- int regtype;
- int lock;
- int all;
- int slot;
- int active;
- enum cache_request request;
- } CACHE_QUEUE_ELEMENT;
- #define CACHE_QUEUE_SIZE 64 /* TODO -- make queue dynamic */
- struct
- {
- unsigned reqno;
- int ix;
- CACHE_QUEUE_ELEMENT q[CACHE_QUEUE_SIZE];
- } cache_queue = {0, 0};
- /* Queue a request for a load from the cache. The load will be queued as
- 'inactive' and will be requested after the given number
- of cycles have passed from the point the load is activated. */
- void
- request_cache_load (SIM_CPU *cpu, INT regnum, int regtype, int cycles)
- {
- CACHE_QUEUE_ELEMENT *q;
- FRV_VLIW *vliw;
- int slot;
- /* For a conditional load which was not executed, CPU_LOAD_LENGTH will be
- zero. */
- if (CPU_LOAD_LENGTH (cpu) == 0)
- return;
- if (cache_queue.ix >= CACHE_QUEUE_SIZE)
- abort (); /* TODO: Make the queue dynamic */
- q = & cache_queue.q[cache_queue.ix];
- ++cache_queue.ix;
- q->reqno = cache_queue.reqno++;
- q->request = cache_load;
- q->cache = CPU_DATA_CACHE (cpu);
- q->address = CPU_LOAD_ADDRESS (cpu);
- q->length = CPU_LOAD_LENGTH (cpu);
- q->is_signed = CPU_LOAD_SIGNED (cpu);
- q->regnum = regnum;
- q->regtype = regtype;
- q->cycles = cycles;
- q->active = 0;
- vliw = CPU_VLIW (cpu);
- slot = vliw->next_slot - 1;
- q->slot = (*vliw->current_vliw)[slot];
- CPU_LOAD_LENGTH (cpu) = 0;
- }
- /* Queue a request to flush the cache. The request will be queued as
- 'inactive' and will be requested after the given number
- of cycles have passed from the point the request is activated. */
- void
- request_cache_flush (SIM_CPU *cpu, FRV_CACHE *cache, int cycles)
- {
- CACHE_QUEUE_ELEMENT *q;
- FRV_VLIW *vliw;
- int slot;
- if (cache_queue.ix >= CACHE_QUEUE_SIZE)
- abort (); /* TODO: Make the queue dynamic */
- q = & cache_queue.q[cache_queue.ix];
- ++cache_queue.ix;
- q->reqno = cache_queue.reqno++;
- q->request = cache_flush;
- q->cache = cache;
- q->address = CPU_LOAD_ADDRESS (cpu);
- q->all = CPU_PROFILE_STATE (cpu)->all_cache_entries;
- q->cycles = cycles;
- q->active = 0;
- vliw = CPU_VLIW (cpu);
- slot = vliw->next_slot - 1;
- q->slot = (*vliw->current_vliw)[slot];
- }
- /* Queue a request to invalidate the cache. The request will be queued as
- 'inactive' and will be requested after the given number
- of cycles have passed from the point the request is activated. */
- void
- request_cache_invalidate (SIM_CPU *cpu, FRV_CACHE *cache, int cycles)
- {
- CACHE_QUEUE_ELEMENT *q;
- FRV_VLIW *vliw;
- int slot;
- if (cache_queue.ix >= CACHE_QUEUE_SIZE)
- abort (); /* TODO: Make the queue dynamic */
- q = & cache_queue.q[cache_queue.ix];
- ++cache_queue.ix;
- q->reqno = cache_queue.reqno++;
- q->request = cache_invalidate;
- q->cache = cache;
- q->address = CPU_LOAD_ADDRESS (cpu);
- q->all = CPU_PROFILE_STATE (cpu)->all_cache_entries;
- q->cycles = cycles;
- q->active = 0;
- vliw = CPU_VLIW (cpu);
- slot = vliw->next_slot - 1;
- q->slot = (*vliw->current_vliw)[slot];
- }
- /* Queue a request to preload the cache. The request will be queued as
- 'inactive' and will be requested after the given number
- of cycles have passed from the point the request is activated. */
- void
- request_cache_preload (SIM_CPU *cpu, FRV_CACHE *cache, int cycles)
- {
- CACHE_QUEUE_ELEMENT *q;
- FRV_VLIW *vliw;
- int slot;
- if (cache_queue.ix >= CACHE_QUEUE_SIZE)
- abort (); /* TODO: Make the queue dynamic */
- q = & cache_queue.q[cache_queue.ix];
- ++cache_queue.ix;
- q->reqno = cache_queue.reqno++;
- q->request = cache_preload;
- q->cache = cache;
- q->address = CPU_LOAD_ADDRESS (cpu);
- q->length = CPU_LOAD_LENGTH (cpu);
- q->lock = CPU_LOAD_LOCK (cpu);
- q->cycles = cycles;
- q->active = 0;
- vliw = CPU_VLIW (cpu);
- slot = vliw->next_slot - 1;
- q->slot = (*vliw->current_vliw)[slot];
- CPU_LOAD_LENGTH (cpu) = 0;
- }
- /* Queue a request to unlock the cache. The request will be queued as
- 'inactive' and will be requested after the given number
- of cycles have passed from the point the request is activated. */
- void
- request_cache_unlock (SIM_CPU *cpu, FRV_CACHE *cache, int cycles)
- {
- CACHE_QUEUE_ELEMENT *q;
- FRV_VLIW *vliw;
- int slot;
- if (cache_queue.ix >= CACHE_QUEUE_SIZE)
- abort (); /* TODO: Make the queue dynamic */
- q = & cache_queue.q[cache_queue.ix];
- ++cache_queue.ix;
- q->reqno = cache_queue.reqno++;
- q->request = cache_unlock;
- q->cache = cache;
- q->address = CPU_LOAD_ADDRESS (cpu);
- q->cycles = cycles;
- q->active = 0;
- vliw = CPU_VLIW (cpu);
- slot = vliw->next_slot - 1;
- q->slot = (*vliw->current_vliw)[slot];
- }
- static void
- submit_cache_request (CACHE_QUEUE_ELEMENT *q)
- {
- switch (q->request)
- {
- case cache_load:
- frv_cache_request_load (q->cache, q->reqno, q->address, q->slot);
- break;
- case cache_flush:
- frv_cache_request_invalidate (q->cache, q->reqno, q->address, q->slot,
- q->all, 1/*flush*/);
- break;
- case cache_invalidate:
- frv_cache_request_invalidate (q->cache, q->reqno, q->address, q->slot,
- q->all, 0/*flush*/);
- break;
- case cache_preload:
- frv_cache_request_preload (q->cache, q->address, q->slot,
- q->length, q->lock);
- break;
- case cache_unlock:
- frv_cache_request_unlock (q->cache, q->address, q->slot);
- break;
- default:
- abort ();
- }
- }
- /* Activate all inactive load requests. */
- static void
- activate_cache_requests (SIM_CPU *cpu)
- {
- int i;
- for (i = 0; i < cache_queue.ix; ++i)
- {
- CACHE_QUEUE_ELEMENT *q = & cache_queue.q[i];
- if (! q->active)
- {
- q->active = 1;
- /* Submit the request now if the cycle count is zero. */
- if (q->cycles == 0)
- submit_cache_request (q);
- }
- }
- }
- /* Check to see if a load is pending which affects the given register(s).
- */
- int
- load_pending_for_register (SIM_CPU *cpu, int regnum, int words, int regtype)
- {
- int i;
- for (i = 0; i < cache_queue.ix; ++i)
- {
- CACHE_QUEUE_ELEMENT *q = & cache_queue.q[i];
- /* Must be the same kind of register. */
- if (! q->active || q->request != cache_load || q->regtype != regtype)
- continue;
- /* If the registers numbers are equal, then we have a match. */
- if (q->regnum == regnum)
- return 1; /* load pending */
- /* Check for overlap of a load with a multi-word register. */
- if (regnum < q->regnum)
- {
- if (regnum + words > q->regnum)
- return 1;
- }
- /* Check for overlap of a multi-word load with the register. */
- else
- {
- int data_words = (q->length + sizeof (SI) - 1) / sizeof (SI);
- if (q->regnum + data_words > regnum)
- return 1;
- }
- }
- return 0; /* no load pending */
- }
- /* Check to see if a cache flush pending which affects the given address. */
- static int
- flush_pending_for_address (SIM_CPU *cpu, SI address)
- {
- int line_mask = ~(CPU_DATA_CACHE (cpu)->line_size - 1);
- int i;
- for (i = 0; i < cache_queue.ix; ++i)
- {
- CACHE_QUEUE_ELEMENT *q = & cache_queue.q[i];
- /* Must be the same kind of request and active. */
- if (! q->active || q->request != cache_flush)
- continue;
- /* If the addresses are equal, then we have a match. */
- if ((q->address & line_mask) == (address & line_mask))
- return 1; /* flush pending */
- }
- return 0; /* no flush pending */
- }
- static void
- remove_cache_queue_element (SIM_CPU *cpu, int i)
- {
- /* If we are removing the load of a FR register, then remember which one(s).
- */
- CACHE_QUEUE_ELEMENT q = cache_queue.q[i];
- for (--cache_queue.ix; i < cache_queue.ix; ++i)
- cache_queue.q[i] = cache_queue.q[i + 1];
- /* If we removed a load of a FR register, check to see if any other loads
- of that register is still queued. If not, then apply the queued post
- processing time of that register to its latency. Also apply
- 1 extra cycle of latency to the register since it was a floating point
- load. */
- if (q.request == cache_load && q.regtype != REGTYPE_NONE)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int data_words = (q.length + sizeof (SI) - 1) / sizeof (SI);
- int j;
- for (j = 0; j < data_words; ++j)
- {
- int regnum = q.regnum + j;
- if (! load_pending_for_register (cpu, regnum, 1, q.regtype))
- {
- if (q.regtype == REGTYPE_FR)
- {
- int *fr = ps->fr_busy;
- fr[regnum] += 1 + ps->fr_ptime[regnum];
- ps->fr_ptime[regnum] = 0;
- }
- }
- }
- }
- }
- /* Copy data from the cache buffer to the target register(s). */
- static void
- copy_load_data (SIM_CPU *current_cpu, FRV_CACHE *cache, int slot,
- CACHE_QUEUE_ELEMENT *q)
- {
- switch (q->length)
- {
- case 1:
- if (q->regtype == REGTYPE_FR)
- {
- if (q->is_signed)
- {
- QI value = CACHE_RETURN_DATA (cache, slot, q->address, QI, 1);
- SET_H_FR (q->regnum, value);
- }
- else
- {
- UQI value = CACHE_RETURN_DATA (cache, slot, q->address, UQI, 1);
- SET_H_FR (q->regnum, value);
- }
- }
- else
- {
- if (q->is_signed)
- {
- QI value = CACHE_RETURN_DATA (cache, slot, q->address, QI, 1);
- SET_H_GR (q->regnum, value);
- }
- else
- {
- UQI value = CACHE_RETURN_DATA (cache, slot, q->address, UQI, 1);
- SET_H_GR (q->regnum, value);
- }
- }
- break;
- case 2:
- if (q->regtype == REGTYPE_FR)
- {
- if (q->is_signed)
- {
- HI value = CACHE_RETURN_DATA (cache, slot, q->address, HI, 2);
- SET_H_FR (q->regnum, value);
- }
- else
- {
- UHI value = CACHE_RETURN_DATA (cache, slot, q->address, UHI, 2);
- SET_H_FR (q->regnum, value);
- }
- }
- else
- {
- if (q->is_signed)
- {
- HI value = CACHE_RETURN_DATA (cache, slot, q->address, HI, 2);
- SET_H_GR (q->regnum, value);
- }
- else
- {
- UHI value = CACHE_RETURN_DATA (cache, slot, q->address, UHI, 2);
- SET_H_GR (q->regnum, value);
- }
- }
- break;
- case 4:
- if (q->regtype == REGTYPE_FR)
- {
- SET_H_FR (q->regnum,
- CACHE_RETURN_DATA (cache, slot, q->address, SF, 4));
- }
- else
- {
- SET_H_GR (q->regnum,
- CACHE_RETURN_DATA (cache, slot, q->address, SI, 4));
- }
- break;
- case 8:
- if (q->regtype == REGTYPE_FR)
- {
- SET_H_FR_DOUBLE (q->regnum,
- CACHE_RETURN_DATA (cache, slot, q->address, DF, 8));
- }
- else
- {
- SET_H_GR_DOUBLE (q->regnum,
- CACHE_RETURN_DATA (cache, slot, q->address, DI, 8));
- }
- break;
- case 16:
- if (q->regtype == REGTYPE_FR)
- frvbf_h_fr_quad_set_handler (current_cpu, q->regnum,
- CACHE_RETURN_DATA_ADDRESS (cache, slot,
- q->address,
- 16));
- else
- frvbf_h_gr_quad_set_handler (current_cpu, q->regnum,
- CACHE_RETURN_DATA_ADDRESS (cache, slot,
- q->address,
- 16));
- break;
- default:
- abort ();
- }
- }
- static int
- request_complete (SIM_CPU *cpu, CACHE_QUEUE_ELEMENT *q)
- {
- FRV_CACHE* cache;
- if (! q->active || q->cycles > 0)
- return 0;
- cache = CPU_DATA_CACHE (cpu);
- switch (q->request)
- {
- case cache_load:
- /* For loads, we must wait until the data is returned from the cache. */
- if (frv_cache_data_in_buffer (cache, 0, q->address, q->reqno))
- {
- copy_load_data (cpu, cache, 0, q);
- return 1;
- }
- if (frv_cache_data_in_buffer (cache, 1, q->address, q->reqno))
- {
- copy_load_data (cpu, cache, 1, q);
- return 1;
- }
- break;
- case cache_flush:
- /* We must wait until the data is flushed. */
- if (frv_cache_data_flushed (cache, 0, q->address, q->reqno))
- return 1;
- if (frv_cache_data_flushed (cache, 1, q->address, q->reqno))
- return 1;
- break;
- default:
- /* All other requests are complete once they've been made. */
- return 1;
- }
- return 0;
- }
- /* Run the insn and data caches through the given number of cycles, taking
- note of load requests which are fullfilled as a result. */
- static void
- run_caches (SIM_CPU *cpu, int cycles)
- {
- FRV_CACHE* data_cache = CPU_DATA_CACHE (cpu);
- FRV_CACHE* insn_cache = CPU_INSN_CACHE (cpu);
- int i;
- /* For each cycle, run the caches, noting which requests have been fullfilled
- and submitting new requests on their designated cycles. */
- for (i = 0; i < cycles; ++i)
- {
- int j;
- /* Run the caches through 1 cycle. */
- frv_cache_run (data_cache, 1);
- frv_cache_run (insn_cache, 1);
- /* Note whether prefetched insn data has been loaded yet. */
- for (j = LS; j < FRV_CACHE_PIPELINES; ++j)
- {
- if (frv_insn_fetch_buffer[j].reqno != NO_REQNO
- && frv_cache_data_in_buffer (insn_cache, j,
- frv_insn_fetch_buffer[j].address,
- frv_insn_fetch_buffer[j].reqno))
- frv_insn_fetch_buffer[j].reqno = NO_REQNO;
- }
- /* Check to see which requests have been satisfied and which should
- be submitted now. */
- for (j = 0; j < cache_queue.ix; ++j)
- {
- CACHE_QUEUE_ELEMENT *q = & cache_queue.q[j];
- if (! q->active)
- continue;
- /* If a load has been satisfied, complete the operation and remove it
- from the queue. */
- if (request_complete (cpu, q))
- {
- remove_cache_queue_element (cpu, j);
- --j;
- continue;
- }
- /* Decrease the cycle count of each queued request.
- Submit a request for each queued request whose cycle count has
- become zero. */
- --q->cycles;
- if (q->cycles == 0)
- submit_cache_request (q);
- }
- }
- }
- static void
- apply_latency_adjustments (SIM_CPU *cpu)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int i;
- /* update the latencies of the registers. */
- int *fr = ps->fr_busy;
- int *acc = ps->acc_busy;
- for (i = 0; i < 64; ++i)
- {
- if (ps->fr_busy_adjust[i] > 0)
- *fr -= ps->fr_busy_adjust[i]; /* OK if it goes negative. */
- if (ps->acc_busy_adjust[i] > 0)
- *acc -= ps->acc_busy_adjust[i]; /* OK if it goes negative. */
- ++fr;
- ++acc;
- }
- }
- /* Account for the number of cycles which have just passed in the latency of
- various system elements. Works for negative cycles too so that latency
- can be extended in the case of insn fetch latency.
- If negative or zero, then no adjustment is necessary. */
- static void
- update_latencies (SIM_CPU *cpu, int cycles)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int i;
- /* update the latencies of the registers. */
- int *fdiv;
- int *fsqrt;
- int *idiv;
- int *flt;
- int *media;
- int *ccr;
- int *gr = ps->gr_busy;
- int *fr = ps->fr_busy;
- int *acc = ps->acc_busy;
- int *spr;
- /* This loop handles GR, FR and ACC registers. */
- for (i = 0; i < 64; ++i)
- {
- if (*gr <= cycles)
- {
- *gr = 0;
- reset_gr_flags (cpu, i);
- }
- else
- *gr -= cycles;
- /* If the busy drops to 0, then mark the register as
- "not in use". */
- if (*fr <= cycles)
- {
- int *fr_lat = ps->fr_latency + i;
- *fr = 0;
- ps->fr_busy_adjust[i] = 0;
- /* Only clear flags if this register has no target latency. */
- if (*fr_lat == 0)
- reset_fr_flags (cpu, i);
- }
- else
- *fr -= cycles;
- /* If the busy drops to 0, then mark the register as
- "not in use". */
- if (*acc <= cycles)
- {
- int *acc_lat = ps->acc_latency + i;
- *acc = 0;
- ps->acc_busy_adjust[i] = 0;
- /* Only clear flags if this register has no target latency. */
- if (*acc_lat == 0)
- reset_acc_flags (cpu, i);
- }
- else
- *acc -= cycles;
- ++gr;
- ++fr;
- ++acc;
- }
- /* This loop handles CCR registers. */
- ccr = ps->ccr_busy;
- for (i = 0; i < 8; ++i)
- {
- if (*ccr <= cycles)
- {
- *ccr = 0;
- reset_cc_flags (cpu, i);
- }
- else
- *ccr -= cycles;
- ++ccr;
- }
- /* This loop handles SPR registers. */
- spr = ps->spr_busy;
- for (i = 0; i < 4096; ++i)
- {
- if (*spr <= cycles)
- *spr = 0;
- else
- *spr -= cycles;
- ++spr;
- }
- /* This loop handles resources. */
- idiv = ps->idiv_busy;
- fdiv = ps->fdiv_busy;
- fsqrt = ps->fsqrt_busy;
- for (i = 0; i < 2; ++i)
- {
- *idiv = (*idiv <= cycles) ? 0 : (*idiv - cycles);
- *fdiv = (*fdiv <= cycles) ? 0 : (*fdiv - cycles);
- *fsqrt = (*fsqrt <= cycles) ? 0 : (*fsqrt - cycles);
- ++idiv;
- ++fdiv;
- ++fsqrt;
- }
- /* Float and media units can occur in 4 slots on some machines. */
- flt = ps->float_busy;
- media = ps->media_busy;
- for (i = 0; i < 4; ++i)
- {
- *flt = (*flt <= cycles) ? 0 : (*flt - cycles);
- *media = (*media <= cycles) ? 0 : (*media - cycles);
- ++flt;
- ++media;
- }
- }
- /* Print information about the wait for the given number of cycles. */
- void
- frv_model_trace_wait_cycles (SIM_CPU *cpu, int cycles, const char *hazard_name)
- {
- if (TRACE_INSN_P (cpu) && cycles > 0)
- {
- SIM_DESC sd = CPU_STATE (cpu);
- trace_printf (sd, cpu, "**** %s wait %d cycles ***\n",
- hazard_name, cycles);
- }
- }
- void
- trace_vliw_wait_cycles (SIM_CPU *cpu)
- {
- if (TRACE_INSN_P (cpu))
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- frv_model_trace_wait_cycles (cpu, ps->vliw_wait, hazard_name);
- }
- }
- /* Wait for the given number of cycles. */
- void
- frv_model_advance_cycles (SIM_CPU *cpu, int cycles)
- {
- PROFILE_DATA *p = CPU_PROFILE_DATA (cpu);
- update_latencies (cpu, cycles);
- run_caches (cpu, cycles);
- PROFILE_MODEL_TOTAL_CYCLES (p) += cycles;
- }
- void
- handle_resource_wait (SIM_CPU *cpu)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- if (ps->vliw_wait != 0)
- frv_model_advance_cycles (cpu, ps->vliw_wait);
- if (ps->vliw_load_stall > ps->vliw_wait)
- ps->vliw_load_stall -= ps->vliw_wait;
- else
- ps->vliw_load_stall = 0;
- }
- /* Account for the number of cycles until these resources will be available
- again. */
- static void
- update_target_latencies (SIM_CPU *cpu)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int i;
- /* update the latencies of the registers. */
- int *ccr_lat;
- int *gr_lat = ps->gr_latency;
- int *fr_lat = ps->fr_latency;
- int *acc_lat = ps->acc_latency;
- int *spr_lat;
- int *ccr;
- int *gr = ps->gr_busy;
- int *fr = ps->fr_busy;
- int *acc = ps->acc_busy;
- int *spr;
- /* This loop handles GR, FR and ACC registers. */
- for (i = 0; i < 64; ++i)
- {
- if (*gr_lat)
- {
- *gr = *gr_lat;
- *gr_lat = 0;
- }
- if (*fr_lat)
- {
- *fr = *fr_lat;
- *fr_lat = 0;
- }
- if (*acc_lat)
- {
- *acc = *acc_lat;
- *acc_lat = 0;
- }
- ++gr; ++gr_lat;
- ++fr; ++fr_lat;
- ++acc; ++acc_lat;
- }
- /* This loop handles CCR registers. */
- ccr = ps->ccr_busy;
- ccr_lat = ps->ccr_latency;
- for (i = 0; i < 8; ++i)
- {
- if (*ccr_lat)
- {
- *ccr = *ccr_lat;
- *ccr_lat = 0;
- }
- ++ccr; ++ccr_lat;
- }
- /* This loop handles SPR registers. */
- spr = ps->spr_busy;
- spr_lat = ps->spr_latency;
- for (i = 0; i < 4096; ++i)
- {
- if (*spr_lat)
- {
- *spr = *spr_lat;
- *spr_lat = 0;
- }
- ++spr; ++spr_lat;
- }
- }
- /* Run the caches until all pending cache flushes are complete. */
- static void
- wait_for_flush (SIM_CPU *cpu)
- {
- SI address = CPU_LOAD_ADDRESS (cpu);
- int wait = 0;
- while (flush_pending_for_address (cpu, address))
- {
- frv_model_advance_cycles (cpu, 1);
- ++wait;
- }
- if (TRACE_INSN_P (cpu) && wait)
- {
- sprintf (hazard_name, "Data cache flush address %p:", address);
- frv_model_trace_wait_cycles (cpu, wait, hazard_name);
- }
- }
- /* Initialize cycle counting for an insn.
- FIRST_P is non-zero if this is the first insn in a set of parallel
- insns. */
- void
- frvbf_model_insn_before (SIM_CPU *cpu, int first_p)
- {
- SIM_DESC sd = CPU_STATE (cpu);
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- ps->vliw_wait = 0;
- ps->post_wait = 0;
- memset (ps->fr_busy_adjust, 0, sizeof (ps->fr_busy_adjust));
- memset (ps->acc_busy_adjust, 0, sizeof (ps->acc_busy_adjust));
- if (first_p)
- {
- ps->vliw_insns++;
- ps->vliw_cycles = 0;
- ps->vliw_branch_taken = 0;
- ps->vliw_load_stall = 0;
- }
- switch (STATE_ARCHITECTURE (sd)->mach)
- {
- case bfd_mach_fr400:
- case bfd_mach_fr450:
- fr400_model_insn_before (cpu, first_p);
- break;
- case bfd_mach_fr500:
- fr500_model_insn_before (cpu, first_p);
- break;
- case bfd_mach_fr550:
- fr550_model_insn_before (cpu, first_p);
- break;
- default:
- break;
- }
- if (first_p)
- wait_for_flush (cpu);
- }
- /* Record the cycles computed for an insn.
- LAST_P is non-zero if this is the last insn in a set of parallel insns,
- and we update the total cycle count.
- CYCLES is the cycle count of the insn. */
- void
- frvbf_model_insn_after (SIM_CPU *cpu, int last_p, int cycles)
- {
- PROFILE_DATA *p = CPU_PROFILE_DATA (cpu);
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- SIM_DESC sd = CPU_STATE (cpu);
- PROFILE_MODEL_CUR_INSN_CYCLES (p) = cycles;
- /* The number of cycles for a VLIW insn is the maximum number of cycles
- used by any individual insn within it. */
- if (cycles > ps->vliw_cycles)
- ps->vliw_cycles = cycles;
- if (last_p)
- {
- /* This is the last insn in a VLIW insn. */
- struct frv_interrupt_timer *timer = & frv_interrupt_state.timer;
- activate_cache_requests (cpu); /* before advancing cycles. */
- apply_latency_adjustments (cpu); /* must go first. */
- update_target_latencies (cpu); /* must go next. */
- frv_model_advance_cycles (cpu, ps->vliw_cycles);
- PROFILE_MODEL_LOAD_STALL_CYCLES (p) += ps->vliw_load_stall;
- /* Check the interrupt timer. cycles contains the total cycle count. */
- if (timer->enabled)
- {
- cycles = PROFILE_MODEL_TOTAL_CYCLES (p);
- if (timer->current % timer->value
- + (cycles - timer->current) >= timer->value)
- frv_queue_external_interrupt (cpu, timer->interrupt);
- timer->current = cycles;
- }
- ps->past_first_p = 0; /* Next one will be the first in a new VLIW. */
- ps->branch_address = -1;
- }
- else
- ps->past_first_p = 1;
- switch (STATE_ARCHITECTURE (sd)->mach)
- {
- case bfd_mach_fr400:
- case bfd_mach_fr450:
- fr400_model_insn_after (cpu, last_p, cycles);
- break;
- case bfd_mach_fr500:
- fr500_model_insn_after (cpu, last_p, cycles);
- break;
- case bfd_mach_fr550:
- fr550_model_insn_after (cpu, last_p, cycles);
- break;
- default:
- break;
- }
- }
- USI
- frvbf_model_branch (SIM_CPU *current_cpu, PCADDR target, int hint)
- {
- /* Record the hint and branch address for use in profiling. */
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu);
- ps->branch_hint = hint;
- ps->branch_address = target;
- }
- /* Top up the latency of the given GR by the given number of cycles. */
- void
- update_GR_latency (SIM_CPU *cpu, INT out_GR, int cycles)
- {
- if (out_GR >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *gr = ps->gr_latency;
- if (gr[out_GR] < cycles)
- gr[out_GR] = cycles;
- }
- }
- void
- decrease_GR_busy (SIM_CPU *cpu, INT in_GR, int cycles)
- {
- if (in_GR >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *gr = ps->gr_busy;
- gr[in_GR] -= cycles;
- }
- }
- /* Top up the latency of the given double GR by the number of cycles. */
- void
- update_GRdouble_latency (SIM_CPU *cpu, INT out_GR, int cycles)
- {
- if (out_GR >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *gr = ps->gr_latency;
- if (gr[out_GR] < cycles)
- gr[out_GR] = cycles;
- if (out_GR < 63 && gr[out_GR + 1] < cycles)
- gr[out_GR + 1] = cycles;
- }
- }
- void
- update_GR_latency_for_load (SIM_CPU *cpu, INT out_GR, int cycles)
- {
- if (out_GR >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *gr = ps->gr_latency;
- /* The latency of the GR will be at least the number of cycles used
- by the insn. */
- if (gr[out_GR] < cycles)
- gr[out_GR] = cycles;
- /* The latency will also depend on how long it takes to retrieve the
- data from the cache or memory. Assume that the load is issued
- after the last cycle of the insn. */
- request_cache_load (cpu, out_GR, REGTYPE_NONE, cycles);
- }
- }
- void
- update_GRdouble_latency_for_load (SIM_CPU *cpu, INT out_GR, int cycles)
- {
- if (out_GR >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *gr = ps->gr_latency;
- /* The latency of the GR will be at least the number of cycles used
- by the insn. */
- if (gr[out_GR] < cycles)
- gr[out_GR] = cycles;
- if (out_GR < 63 && gr[out_GR + 1] < cycles)
- gr[out_GR + 1] = cycles;
- /* The latency will also depend on how long it takes to retrieve the
- data from the cache or memory. Assume that the load is issued
- after the last cycle of the insn. */
- request_cache_load (cpu, out_GR, REGTYPE_NONE, cycles);
- }
- }
- void
- update_GR_latency_for_swap (SIM_CPU *cpu, INT out_GR, int cycles)
- {
- update_GR_latency_for_load (cpu, out_GR, cycles);
- }
- /* Top up the latency of the given FR by the given number of cycles. */
- void
- update_FR_latency (SIM_CPU *cpu, INT out_FR, int cycles)
- {
- if (out_FR >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *fr = ps->fr_latency;
- if (fr[out_FR] < cycles)
- fr[out_FR] = cycles;
- }
- }
- /* Top up the latency of the given double FR by the number of cycles. */
- void
- update_FRdouble_latency (SIM_CPU *cpu, INT out_FR, int cycles)
- {
- if (out_FR >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *fr = ps->fr_latency;
- if (fr[out_FR] < cycles)
- fr[out_FR] = cycles;
- if (out_FR < 63 && fr[out_FR + 1] < cycles)
- fr[out_FR + 1] = cycles;
- }
- }
- void
- update_FR_latency_for_load (SIM_CPU *cpu, INT out_FR, int cycles)
- {
- if (out_FR >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *fr = ps->fr_latency;
- /* The latency of the FR will be at least the number of cycles used
- by the insn. */
- if (fr[out_FR] < cycles)
- fr[out_FR] = cycles;
- /* The latency will also depend on how long it takes to retrieve the
- data from the cache or memory. Assume that the load is issued
- after the last cycle of the insn. */
- request_cache_load (cpu, out_FR, REGTYPE_FR, cycles);
- }
- }
- void
- update_FRdouble_latency_for_load (SIM_CPU *cpu, INT out_FR, int cycles)
- {
- if (out_FR >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *fr = ps->fr_latency;
-
- /* The latency of the FR will be at least the number of cycles used
- by the insn. */
- if (fr[out_FR] < cycles)
- fr[out_FR] = cycles;
- if (out_FR < 63 && fr[out_FR + 1] < cycles)
- fr[out_FR + 1] = cycles;
- /* The latency will also depend on how long it takes to retrieve the
- data from the cache or memory. Assume that the load is issued
- after the last cycle of the insn. */
- request_cache_load (cpu, out_FR, REGTYPE_FR, cycles);
- }
- }
- /* Top up the post-processing time of the given FR by the given number of
- cycles. */
- void
- update_FR_ptime (SIM_CPU *cpu, INT out_FR, int cycles)
- {
- if (out_FR >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- /* If a load is pending on this register, then add the cycles to
- the post processing time for this register. Otherwise apply it
- directly to the latency of the register. */
- if (! load_pending_for_register (cpu, out_FR, 1, REGTYPE_FR))
- {
- int *fr = ps->fr_latency;
- fr[out_FR] += cycles;
- }
- else
- ps->fr_ptime[out_FR] += cycles;
- }
- }
- void
- update_FRdouble_ptime (SIM_CPU *cpu, INT out_FR, int cycles)
- {
- if (out_FR >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- /* If a load is pending on this register, then add the cycles to
- the post processing time for this register. Otherwise apply it
- directly to the latency of the register. */
- if (! load_pending_for_register (cpu, out_FR, 2, REGTYPE_FR))
- {
- int *fr = ps->fr_latency;
- fr[out_FR] += cycles;
- if (out_FR < 63)
- fr[out_FR + 1] += cycles;
- }
- else
- {
- ps->fr_ptime[out_FR] += cycles;
- if (out_FR < 63)
- ps->fr_ptime[out_FR + 1] += cycles;
- }
- }
- }
- /* Top up the post-processing time of the given ACC by the given number of
- cycles. */
- void
- update_ACC_ptime (SIM_CPU *cpu, INT out_ACC, int cycles)
- {
- if (out_ACC >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- /* No load can be pending on this register. Apply the cycles
- directly to the latency of the register. */
- int *acc = ps->acc_latency;
- acc[out_ACC] += cycles;
- }
- }
- /* Top up the post-processing time of the given SPR by the given number of
- cycles. */
- void
- update_SPR_ptime (SIM_CPU *cpu, INT out_SPR, int cycles)
- {
- if (out_SPR >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- /* No load can be pending on this register. Apply the cycles
- directly to the latency of the register. */
- int *spr = ps->spr_latency;
- spr[out_SPR] += cycles;
- }
- }
- void
- decrease_ACC_busy (SIM_CPU *cpu, INT out_ACC, int cycles)
- {
- if (out_ACC >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *acc = ps->acc_busy;
- acc[out_ACC] -= cycles;
- if (ps->acc_busy_adjust[out_ACC] >= 0
- && cycles > ps->acc_busy_adjust[out_ACC])
- ps->acc_busy_adjust[out_ACC] = cycles;
- }
- }
- void
- increase_ACC_busy (SIM_CPU *cpu, INT out_ACC, int cycles)
- {
- if (out_ACC >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *acc = ps->acc_busy;
- acc[out_ACC] += cycles;
- }
- }
- void
- enforce_full_acc_latency (SIM_CPU *cpu, INT in_ACC)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- ps->acc_busy_adjust [in_ACC] = -1;
- }
- void
- decrease_FR_busy (SIM_CPU *cpu, INT out_FR, int cycles)
- {
- if (out_FR >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *fr = ps->fr_busy;
- fr[out_FR] -= cycles;
- if (ps->fr_busy_adjust[out_FR] >= 0
- && cycles > ps->fr_busy_adjust[out_FR])
- ps->fr_busy_adjust[out_FR] = cycles;
- }
- }
- void
- increase_FR_busy (SIM_CPU *cpu, INT out_FR, int cycles)
- {
- if (out_FR >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *fr = ps->fr_busy;
- fr[out_FR] += cycles;
- }
- }
- /* Top up the latency of the given ACC by the given number of cycles. */
- void
- update_ACC_latency (SIM_CPU *cpu, INT out_ACC, int cycles)
- {
- if (out_ACC >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *acc = ps->acc_latency;
- if (acc[out_ACC] < cycles)
- acc[out_ACC] = cycles;
- }
- }
- /* Top up the latency of the given CCR by the given number of cycles. */
- void
- update_CCR_latency (SIM_CPU *cpu, INT out_CCR, int cycles)
- {
- if (out_CCR >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *ccr = ps->ccr_latency;
- if (ccr[out_CCR] < cycles)
- ccr[out_CCR] = cycles;
- }
- }
- /* Top up the latency of the given SPR by the given number of cycles. */
- void
- update_SPR_latency (SIM_CPU *cpu, INT out_SPR, int cycles)
- {
- if (out_SPR >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *spr = ps->spr_latency;
- if (spr[out_SPR] < cycles)
- spr[out_SPR] = cycles;
- }
- }
- /* Top up the latency of the given integer division resource by the given
- number of cycles. */
- void
- update_idiv_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
- {
- /* operate directly on the busy cycles since each resource can only
- be used once in a VLIW insn. */
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *r = ps->idiv_busy;
- r[in_resource] = cycles;
- }
- /* Set the latency of the given resource to the given number of cycles. */
- void
- update_fdiv_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
- {
- /* operate directly on the busy cycles since each resource can only
- be used once in a VLIW insn. */
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *r = ps->fdiv_busy;
- r[in_resource] = cycles;
- }
- /* Set the latency of the given resource to the given number of cycles. */
- void
- update_fsqrt_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
- {
- /* operate directly on the busy cycles since each resource can only
- be used once in a VLIW insn. */
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *r = ps->fsqrt_busy;
- r[in_resource] = cycles;
- }
- /* Set the latency of the given resource to the given number of cycles. */
- void
- update_float_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
- {
- /* operate directly on the busy cycles since each resource can only
- be used once in a VLIW insn. */
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *r = ps->float_busy;
- r[in_resource] = cycles;
- }
- void
- update_media_resource_latency (SIM_CPU *cpu, INT in_resource, int cycles)
- {
- /* operate directly on the busy cycles since each resource can only
- be used once in a VLIW insn. */
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *r = ps->media_busy;
- r[in_resource] = cycles;
- }
- /* Set the branch penalty to the given number of cycles. */
- void
- update_branch_penalty (SIM_CPU *cpu, int cycles)
- {
- /* operate directly on the busy cycles since only one branch can occur
- in a VLIW insn. */
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- ps->branch_penalty = cycles;
- }
- /* Check the availability of the given GR register and update the number
- of cycles the current VLIW insn must wait until it is available. */
- void
- vliw_wait_for_GR (SIM_CPU *cpu, INT in_GR)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *gr = ps->gr_busy;
- /* If the latency of the register is greater than the current wait
- then update the current wait. */
- if (in_GR >= 0 && gr[in_GR] > ps->vliw_wait)
- {
- if (TRACE_INSN_P (cpu))
- sprintf (hazard_name, "Data hazard for gr%d:", in_GR);
- ps->vliw_wait = gr[in_GR];
- }
- }
- /* Check the availability of the given GR register and update the number
- of cycles the current VLIW insn must wait until it is available. */
- void
- vliw_wait_for_GRdouble (SIM_CPU *cpu, INT in_GR)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *gr = ps->gr_busy;
- /* If the latency of the register is greater than the current wait
- then update the current wait. */
- if (in_GR >= 0)
- {
- if (gr[in_GR] > ps->vliw_wait)
- {
- if (TRACE_INSN_P (cpu))
- sprintf (hazard_name, "Data hazard for gr%d:", in_GR);
- ps->vliw_wait = gr[in_GR];
- }
- if (in_GR < 63 && gr[in_GR + 1] > ps->vliw_wait)
- {
- if (TRACE_INSN_P (cpu))
- sprintf (hazard_name, "Data hazard for gr%d:", in_GR + 1);
- ps->vliw_wait = gr[in_GR + 1];
- }
- }
- }
- /* Check the availability of the given FR register and update the number
- of cycles the current VLIW insn must wait until it is available. */
- void
- vliw_wait_for_FR (SIM_CPU *cpu, INT in_FR)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *fr = ps->fr_busy;
- /* If the latency of the register is greater than the current wait
- then update the current wait. */
- if (in_FR >= 0 && fr[in_FR] > ps->vliw_wait)
- {
- if (TRACE_INSN_P (cpu))
- sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
- ps->vliw_wait = fr[in_FR];
- }
- }
- /* Check the availability of the given GR register and update the number
- of cycles the current VLIW insn must wait until it is available. */
- void
- vliw_wait_for_FRdouble (SIM_CPU *cpu, INT in_FR)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *fr = ps->fr_busy;
- /* If the latency of the register is greater than the current wait
- then update the current wait. */
- if (in_FR >= 0)
- {
- if (fr[in_FR] > ps->vliw_wait)
- {
- if (TRACE_INSN_P (cpu))
- sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
- ps->vliw_wait = fr[in_FR];
- }
- if (in_FR < 63 && fr[in_FR + 1] > ps->vliw_wait)
- {
- if (TRACE_INSN_P (cpu))
- sprintf (hazard_name, "Data hazard for fr%d:", in_FR + 1);
- ps->vliw_wait = fr[in_FR + 1];
- }
- }
- }
- /* Check the availability of the given CCR register and update the number
- of cycles the current VLIW insn must wait until it is available. */
- void
- vliw_wait_for_CCR (SIM_CPU *cpu, INT in_CCR)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *ccr = ps->ccr_busy;
- /* If the latency of the register is greater than the current wait
- then update the current wait. */
- if (in_CCR >= 0 && ccr[in_CCR] > ps->vliw_wait)
- {
- if (TRACE_INSN_P (cpu))
- {
- if (in_CCR > 3)
- sprintf (hazard_name, "Data hazard for icc%d:", in_CCR-4);
- else
- sprintf (hazard_name, "Data hazard for fcc%d:", in_CCR);
- }
- ps->vliw_wait = ccr[in_CCR];
- }
- }
- /* Check the availability of the given ACC register and update the number
- of cycles the current VLIW insn must wait until it is available. */
- void
- vliw_wait_for_ACC (SIM_CPU *cpu, INT in_ACC)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *acc = ps->acc_busy;
- /* If the latency of the register is greater than the current wait
- then update the current wait. */
- if (in_ACC >= 0 && acc[in_ACC] > ps->vliw_wait)
- {
- if (TRACE_INSN_P (cpu))
- sprintf (hazard_name, "Data hazard for acc%d:", in_ACC);
- ps->vliw_wait = acc[in_ACC];
- }
- }
- /* Check the availability of the given SPR register and update the number
- of cycles the current VLIW insn must wait until it is available. */
- void
- vliw_wait_for_SPR (SIM_CPU *cpu, INT in_SPR)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *spr = ps->spr_busy;
- /* If the latency of the register is greater than the current wait
- then update the current wait. */
- if (in_SPR >= 0 && spr[in_SPR] > ps->vliw_wait)
- {
- if (TRACE_INSN_P (cpu))
- sprintf (hazard_name, "Data hazard for spr %d:", in_SPR);
- ps->vliw_wait = spr[in_SPR];
- }
- }
- /* Check the availability of the given integer division resource and update
- the number of cycles the current VLIW insn must wait until it is available.
- */
- void
- vliw_wait_for_idiv_resource (SIM_CPU *cpu, INT in_resource)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *r = ps->idiv_busy;
- /* If the latency of the resource is greater than the current wait
- then update the current wait. */
- if (r[in_resource] > ps->vliw_wait)
- {
- if (TRACE_INSN_P (cpu))
- {
- sprintf (hazard_name, "Resource hazard for integer division in slot I%d:", in_resource);
- }
- ps->vliw_wait = r[in_resource];
- }
- }
- /* Check the availability of the given float division resource and update
- the number of cycles the current VLIW insn must wait until it is available.
- */
- void
- vliw_wait_for_fdiv_resource (SIM_CPU *cpu, INT in_resource)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *r = ps->fdiv_busy;
- /* If the latency of the resource is greater than the current wait
- then update the current wait. */
- if (r[in_resource] > ps->vliw_wait)
- {
- if (TRACE_INSN_P (cpu))
- {
- sprintf (hazard_name, "Resource hazard for floating point division in slot F%d:", in_resource);
- }
- ps->vliw_wait = r[in_resource];
- }
- }
- /* Check the availability of the given float square root resource and update
- the number of cycles the current VLIW insn must wait until it is available.
- */
- void
- vliw_wait_for_fsqrt_resource (SIM_CPU *cpu, INT in_resource)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *r = ps->fsqrt_busy;
- /* If the latency of the resource is greater than the current wait
- then update the current wait. */
- if (r[in_resource] > ps->vliw_wait)
- {
- if (TRACE_INSN_P (cpu))
- {
- sprintf (hazard_name, "Resource hazard for square root in slot F%d:", in_resource);
- }
- ps->vliw_wait = r[in_resource];
- }
- }
- /* Check the availability of the given float unit resource and update
- the number of cycles the current VLIW insn must wait until it is available.
- */
- void
- vliw_wait_for_float_resource (SIM_CPU *cpu, INT in_resource)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *r = ps->float_busy;
- /* If the latency of the resource is greater than the current wait
- then update the current wait. */
- if (r[in_resource] > ps->vliw_wait)
- {
- if (TRACE_INSN_P (cpu))
- {
- sprintf (hazard_name, "Resource hazard for floating point unit in slot F%d:", in_resource);
- }
- ps->vliw_wait = r[in_resource];
- }
- }
- /* Check the availability of the given media unit resource and update
- the number of cycles the current VLIW insn must wait until it is available.
- */
- void
- vliw_wait_for_media_resource (SIM_CPU *cpu, INT in_resource)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *r = ps->media_busy;
- /* If the latency of the resource is greater than the current wait
- then update the current wait. */
- if (r[in_resource] > ps->vliw_wait)
- {
- if (TRACE_INSN_P (cpu))
- {
- sprintf (hazard_name, "Resource hazard for media unit in slot M%d:", in_resource);
- }
- ps->vliw_wait = r[in_resource];
- }
- }
- /* Run the caches until all requests for the given register(s) are satisfied. */
- void
- load_wait_for_GR (SIM_CPU *cpu, INT in_GR)
- {
- if (in_GR >= 0)
- {
- int wait = 0;
- while (load_pending_for_register (cpu, in_GR, 1/*words*/, REGTYPE_NONE))
- {
- frv_model_advance_cycles (cpu, 1);
- ++wait;
- }
- if (wait)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- ps->vliw_wait += wait;
- ps->vliw_load_stall += wait;
- if (TRACE_INSN_P (cpu))
- sprintf (hazard_name, "Data hazard for gr%d:", in_GR);
- }
- }
- }
- void
- load_wait_for_FR (SIM_CPU *cpu, INT in_FR)
- {
- if (in_FR >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *fr;
- int wait = 0;
- while (load_pending_for_register (cpu, in_FR, 1/*words*/, REGTYPE_FR))
- {
- frv_model_advance_cycles (cpu, 1);
- ++wait;
- }
- /* Post processing time may have been added to the register's
- latency after the loads were processed. Account for that too.
- */
- fr = ps->fr_busy;
- if (fr[in_FR])
- {
- wait += fr[in_FR];
- frv_model_advance_cycles (cpu, fr[in_FR]);
- }
- /* Update the vliw_wait with the number of cycles we waited for the
- load and any post-processing. */
- if (wait)
- {
- ps->vliw_wait += wait;
- ps->vliw_load_stall += wait;
- if (TRACE_INSN_P (cpu))
- sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
- }
- }
- }
- void
- load_wait_for_GRdouble (SIM_CPU *cpu, INT in_GR)
- {
- if (in_GR >= 0)
- {
- int wait = 0;
- while (load_pending_for_register (cpu, in_GR, 2/*words*/, REGTYPE_NONE))
- {
- frv_model_advance_cycles (cpu, 1);
- ++wait;
- }
- if (wait)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- ps->vliw_wait += wait;
- ps->vliw_load_stall += wait;
- if (TRACE_INSN_P (cpu))
- sprintf (hazard_name, "Data hazard for gr%d:", in_GR);
- }
- }
- }
- void
- load_wait_for_FRdouble (SIM_CPU *cpu, INT in_FR)
- {
- if (in_FR >= 0)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *fr;
- int wait = 0;
- while (load_pending_for_register (cpu, in_FR, 2/*words*/, REGTYPE_FR))
- {
- frv_model_advance_cycles (cpu, 1);
- ++wait;
- }
- /* Post processing time may have been added to the registers'
- latencies after the loads were processed. Account for that too.
- */
- fr = ps->fr_busy;
- if (fr[in_FR])
- {
- wait += fr[in_FR];
- frv_model_advance_cycles (cpu, fr[in_FR]);
- }
- if (in_FR < 63)
- {
- if (fr[in_FR + 1])
- {
- wait += fr[in_FR + 1];
- frv_model_advance_cycles (cpu, fr[in_FR + 1]);
- }
- }
- /* Update the vliw_wait with the number of cycles we waited for the
- load and any post-processing. */
- if (wait)
- {
- ps->vliw_wait += wait;
- ps->vliw_load_stall += wait;
- if (TRACE_INSN_P (cpu))
- sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
- }
- }
- }
- void
- enforce_full_fr_latency (SIM_CPU *cpu, INT in_FR)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- ps->fr_busy_adjust [in_FR] = -1;
- }
- /* Calculate how long the post processing for a floating point insn must
- wait for resources to become available. */
- int
- post_wait_for_FR (SIM_CPU *cpu, INT in_FR)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *fr = ps->fr_busy;
- if (in_FR >= 0 && fr[in_FR] > ps->post_wait)
- {
- ps->post_wait = fr[in_FR];
- if (TRACE_INSN_P (cpu))
- sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
- }
- }
- /* Calculate how long the post processing for a floating point insn must
- wait for resources to become available. */
- int
- post_wait_for_FRdouble (SIM_CPU *cpu, INT in_FR)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *fr = ps->fr_busy;
- if (in_FR >= 0)
- {
- if (fr[in_FR] > ps->post_wait)
- {
- ps->post_wait = fr[in_FR];
- if (TRACE_INSN_P (cpu))
- sprintf (hazard_name, "Data hazard for fr%d:", in_FR);
- }
- if (in_FR < 63 && fr[in_FR + 1] > ps->post_wait)
- {
- ps->post_wait = fr[in_FR + 1];
- if (TRACE_INSN_P (cpu))
- sprintf (hazard_name, "Data hazard for fr%d:", in_FR + 1);
- }
- }
- }
- int
- post_wait_for_ACC (SIM_CPU *cpu, INT in_ACC)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *acc = ps->acc_busy;
- if (in_ACC >= 0 && acc[in_ACC] > ps->post_wait)
- {
- ps->post_wait = acc[in_ACC];
- if (TRACE_INSN_P (cpu))
- sprintf (hazard_name, "Data hazard for acc%d:", in_ACC);
- }
- }
- int
- post_wait_for_CCR (SIM_CPU *cpu, INT in_CCR)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *ccr = ps->ccr_busy;
- if (in_CCR >= 0 && ccr[in_CCR] > ps->post_wait)
- {
- ps->post_wait = ccr[in_CCR];
- if (TRACE_INSN_P (cpu))
- {
- if (in_CCR > 3)
- sprintf (hazard_name, "Data hazard for icc%d:", in_CCR - 4);
- else
- sprintf (hazard_name, "Data hazard for fcc%d:", in_CCR);
- }
- }
- }
- int
- post_wait_for_SPR (SIM_CPU *cpu, INT in_SPR)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *spr = ps->spr_busy;
- if (in_SPR >= 0 && spr[in_SPR] > ps->post_wait)
- {
- ps->post_wait = spr[in_SPR];
- if (TRACE_INSN_P (cpu))
- sprintf (hazard_name, "Data hazard for spr[%d]:", in_SPR);
- }
- }
- int
- post_wait_for_fdiv (SIM_CPU *cpu, INT slot)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *fdiv = ps->fdiv_busy;
- /* Multiple floating point divisions in the same slot need only wait 1
- extra cycle. */
- if (fdiv[slot] > 0 && 1 > ps->post_wait)
- {
- ps->post_wait = 1;
- if (TRACE_INSN_P (cpu))
- {
- sprintf (hazard_name, "Resource hazard for floating point division in slot F%d:", slot);
- }
- }
- }
- int
- post_wait_for_fsqrt (SIM_CPU *cpu, INT slot)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *fsqrt = ps->fsqrt_busy;
- /* Multiple floating point square roots in the same slot need only wait 1
- extra cycle. */
- if (fsqrt[slot] > 0 && 1 > ps->post_wait)
- {
- ps->post_wait = 1;
- if (TRACE_INSN_P (cpu))
- {
- sprintf (hazard_name, "Resource hazard for square root in slot F%d:", slot);
- }
- }
- }
- int
- post_wait_for_float (SIM_CPU *cpu, INT slot)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *flt = ps->float_busy;
- /* Multiple floating point square roots in the same slot need only wait 1
- extra cycle. */
- if (flt[slot] > ps->post_wait)
- {
- ps->post_wait = flt[slot];
- if (TRACE_INSN_P (cpu))
- {
- sprintf (hazard_name, "Resource hazard for floating point unit in slot F%d:", slot);
- }
- }
- }
- int
- post_wait_for_media (SIM_CPU *cpu, INT slot)
- {
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- int *media = ps->media_busy;
- /* Multiple floating point square roots in the same slot need only wait 1
- extra cycle. */
- if (media[slot] > ps->post_wait)
- {
- ps->post_wait = media[slot];
- if (TRACE_INSN_P (cpu))
- {
- sprintf (hazard_name, "Resource hazard for media unit in slot M%d:", slot);
- }
- }
- }
- /* Print cpu-specific profile information. */
- #define COMMAS(n) sim_add_commas (comma_buf, sizeof (comma_buf), (n))
- static void
- print_cache (SIM_CPU *cpu, FRV_CACHE *cache, const char *cache_name)
- {
- SIM_DESC sd = CPU_STATE (cpu);
- if (cache != NULL)
- {
- char comma_buf[20];
- unsigned accesses;
- sim_io_printf (sd, " %s Cache\n\n", cache_name);
- accesses = cache->statistics.accesses;
- sim_io_printf (sd, " Total accesses: %s\n", COMMAS (accesses));
- if (accesses != 0)
- {
- float rate;
- unsigned hits = cache->statistics.hits;
- sim_io_printf (sd, " Hits: %s\n", COMMAS (hits));
- rate = (float)hits / accesses;
- sim_io_printf (sd, " Hit rate: %.2f%%\n", rate * 100);
- }
- }
- else
- sim_io_printf (sd, " Model %s has no %s cache\n",
- MODEL_NAME (CPU_MODEL (cpu)), cache_name);
- sim_io_printf (sd, "\n");
- }
- /* This table must correspond to the UNIT_ATTR table in
- opcodes/frv-desc.h. Only the units up to UNIT_C need be
- listed since the others cannot occur after mapping. */
- static char *
- slot_names[] =
- {
- "none",
- "I0", "I1", "I01", "I2", "I3", "IALL",
- "FM0", "FM1", "FM01", "FM2", "FM3", "FMALL", "FMLOW",
- "B0", "B1", "B01",
- "C"
- };
- static void
- print_parallel (SIM_CPU *cpu, int verbose)
- {
- SIM_DESC sd = CPU_STATE (cpu);
- PROFILE_DATA *p = CPU_PROFILE_DATA (cpu);
- FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu);
- unsigned total, vliw;
- char comma_buf[20];
- float average;
- sim_io_printf (sd, "Model %s Parallelization\n\n",
- MODEL_NAME (CPU_MODEL (cpu)));
- total = PROFILE_TOTAL_INSN_COUNT (p);
- sim_io_printf (sd, " Total instructions: %s\n", COMMAS (total));
- vliw = ps->vliw_insns;
- sim_io_printf (sd, " VLIW instructions: %s\n", COMMAS (vliw));
- average = (float)total / vliw;
- sim_io_printf (sd, " Average VLIW length: %.2f\n", average);
- average = (float)PROFILE_MODEL_TOTAL_CYCLES (p) / vliw;
- sim_io_printf (sd, " Cycles per VLIW instruction: %.2f\n", average);
- average = (float)total / PROFILE_MODEL_TOTAL_CYCLES (p);
- sim_io_printf (sd, " Instructions per cycle: %.2f\n", average);
- if (verbose)
- {
- int i;
- int max_val = 0;
- int max_name_len = 0;
- for (i = UNIT_NIL + 1; i < UNIT_NUM_UNITS; ++i)
- {
- if (INSNS_IN_SLOT (i))
- {
- int len;
- if (INSNS_IN_SLOT (i) > max_val)
- max_val = INSNS_IN_SLOT (i);
- len = strlen (slot_names[i]);
- if (len > max_name_len)
- max_name_len = len;
- }
- }
- if (max_val > 0)
- {
- sim_io_printf (sd, "\n");
- sim_io_printf (sd, " Instructions per slot:\n");
- sim_io_printf (sd, "\n");
- for (i = UNIT_NIL + 1; i < UNIT_NUM_UNITS; ++i)
- {
- if (INSNS_IN_SLOT (i) != 0)
- {
- sim_io_printf (sd, " %*s: %*s: ",
- max_name_len, slot_names[i],
- max_val < 10000 ? 5 : 10,
- COMMAS (INSNS_IN_SLOT (i)));
- sim_profile_print_bar (sd, cpu, PROFILE_HISTOGRAM_WIDTH,
- INSNS_IN_SLOT (i),
- max_val);
- sim_io_printf (sd, "\n");
- }
- }
- } /* details to print */
- } /* verbose */
- sim_io_printf (sd, "\n");
- }
- void
- frv_profile_info (SIM_CPU *cpu, int verbose)
- {
- /* FIXME: Need to add smp support. */
- PROFILE_DATA *p = CPU_PROFILE_DATA (cpu);
- #if WITH_PROFILE_PARALLEL_P
- if (PROFILE_FLAGS (p) [PROFILE_PARALLEL_IDX])
- print_parallel (cpu, verbose);
- #endif
- #if WITH_PROFILE_CACHE_P
- if (PROFILE_FLAGS (p) [PROFILE_CACHE_IDX])
- {
- SIM_DESC sd = CPU_STATE (cpu);
- sim_io_printf (sd, "Model %s Cache Statistics\n\n",
- MODEL_NAME (CPU_MODEL (cpu)));
- print_cache (cpu, CPU_INSN_CACHE (cpu), "Instruction");
- print_cache (cpu, CPU_DATA_CACHE (cpu), "Data");
- }
- #endif /* WITH_PROFILE_CACHE_P */
- }
- /* A hack to get registers referenced for profiling. */
- SI frv_ref_SI (SI ref) {return ref;}
- #endif /* WITH_PROFILE_MODEL_P */
|