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