profile.c revision 1.12 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