1 /* frv exception and interrupt support 2 Copyright (C) 1999, 2000, 2001, 2007, 2008, 2009, 2010, 2011 3 Free Software Foundation, Inc. 4 Contributed by Red Hat. 5 6 This file is part of the GNU simulators. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 20 21 #define WANT_CPU frvbf 22 #define WANT_CPU_FRVBF 23 24 #include "sim-main.h" 25 #include "bfd.h" 26 27 /* FR-V Interrupt table. 28 Describes the interrupts supported by the FR-V. 29 This table *must* be maintained in order of interrupt priority as defined by 30 frv_interrupt_kind. */ 31 #define DEFERRED 1 32 #define PRECISE 1 33 #define ITABLE_ENTRY(name, class, deferral, precision, offset) \ 34 {FRV_##name, FRV_EC_##name, class, deferral, precision, offset} 35 36 struct frv_interrupt frv_interrupt_table[NUM_FRV_INTERRUPT_KINDS] = 37 { 38 /* External interrupts */ 39 ITABLE_ENTRY(INTERRUPT_LEVEL_1, FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x21), 40 ITABLE_ENTRY(INTERRUPT_LEVEL_2, FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x22), 41 ITABLE_ENTRY(INTERRUPT_LEVEL_3, FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x23), 42 ITABLE_ENTRY(INTERRUPT_LEVEL_4, FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x24), 43 ITABLE_ENTRY(INTERRUPT_LEVEL_5, FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x25), 44 ITABLE_ENTRY(INTERRUPT_LEVEL_6, FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x26), 45 ITABLE_ENTRY(INTERRUPT_LEVEL_7, FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x27), 46 ITABLE_ENTRY(INTERRUPT_LEVEL_8, FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x28), 47 ITABLE_ENTRY(INTERRUPT_LEVEL_9, FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x29), 48 ITABLE_ENTRY(INTERRUPT_LEVEL_10, FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2a), 49 ITABLE_ENTRY(INTERRUPT_LEVEL_11, FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2b), 50 ITABLE_ENTRY(INTERRUPT_LEVEL_12, FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2c), 51 ITABLE_ENTRY(INTERRUPT_LEVEL_13, FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2d), 52 ITABLE_ENTRY(INTERRUPT_LEVEL_14, FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2e), 53 ITABLE_ENTRY(INTERRUPT_LEVEL_15, FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2f), 54 /* Software interrupt */ 55 ITABLE_ENTRY(TRAP_INSTRUCTION, FRV_SOFTWARE_INTERRUPT, !DEFERRED, !PRECISE, 0x80), 56 /* Program interrupts */ 57 ITABLE_ENTRY(COMMIT_EXCEPTION, FRV_PROGRAM_INTERRUPT, !DEFERRED, !PRECISE, 0x19), 58 ITABLE_ENTRY(DIVISION_EXCEPTION, FRV_PROGRAM_INTERRUPT, !DEFERRED, !PRECISE, 0x17), 59 ITABLE_ENTRY(DATA_STORE_ERROR, FRV_PROGRAM_INTERRUPT, !DEFERRED, !PRECISE, 0x14), 60 ITABLE_ENTRY(DATA_ACCESS_EXCEPTION, FRV_PROGRAM_INTERRUPT, !DEFERRED, !PRECISE, 0x13), 61 ITABLE_ENTRY(DATA_ACCESS_MMU_MISS, FRV_PROGRAM_INTERRUPT, !DEFERRED, !PRECISE, 0x12), 62 ITABLE_ENTRY(DATA_ACCESS_ERROR, FRV_PROGRAM_INTERRUPT, !DEFERRED, !PRECISE, 0x11), 63 ITABLE_ENTRY(MP_EXCEPTION, FRV_PROGRAM_INTERRUPT, !DEFERRED, !PRECISE, 0x0e), 64 ITABLE_ENTRY(FP_EXCEPTION, FRV_PROGRAM_INTERRUPT, !DEFERRED, !PRECISE, 0x0d), 65 ITABLE_ENTRY(MEM_ADDRESS_NOT_ALIGNED, FRV_PROGRAM_INTERRUPT, !DEFERRED, !PRECISE, 0x10), 66 ITABLE_ENTRY(REGISTER_EXCEPTION, FRV_PROGRAM_INTERRUPT, !DEFERRED, PRECISE, 0x08), 67 ITABLE_ENTRY(MP_DISABLED, FRV_PROGRAM_INTERRUPT, !DEFERRED, PRECISE, 0x0b), 68 ITABLE_ENTRY(FP_DISABLED, FRV_PROGRAM_INTERRUPT, !DEFERRED, PRECISE, 0x0a), 69 ITABLE_ENTRY(PRIVILEGED_INSTRUCTION, FRV_PROGRAM_INTERRUPT, !DEFERRED, PRECISE, 0x06), 70 ITABLE_ENTRY(ILLEGAL_INSTRUCTION, FRV_PROGRAM_INTERRUPT, !DEFERRED, PRECISE, 0x07), 71 ITABLE_ENTRY(INSTRUCTION_ACCESS_EXCEPTION, FRV_PROGRAM_INTERRUPT, !DEFERRED, PRECISE, 0x03), 72 ITABLE_ENTRY(INSTRUCTION_ACCESS_ERROR, FRV_PROGRAM_INTERRUPT, !DEFERRED, PRECISE, 0x02), 73 ITABLE_ENTRY(INSTRUCTION_ACCESS_MMU_MISS, FRV_PROGRAM_INTERRUPT, !DEFERRED, PRECISE, 0x01), 74 ITABLE_ENTRY(COMPOUND_EXCEPTION, FRV_PROGRAM_INTERRUPT, !DEFERRED, !PRECISE, 0x20), 75 /* Break interrupt */ 76 ITABLE_ENTRY(BREAK_EXCEPTION, FRV_BREAK_INTERRUPT, !DEFERRED, !PRECISE, 0xff), 77 /* Reset interrupt */ 78 ITABLE_ENTRY(RESET, FRV_RESET_INTERRUPT, !DEFERRED, !PRECISE, 0x00) 79 }; 80 81 /* The current interrupt state. */ 82 struct frv_interrupt_state frv_interrupt_state; 83 84 /* maintain the address of the start of the previous VLIW insn sequence. */ 85 IADDR previous_vliw_pc; 86 87 /* Add a break interrupt to the interrupt queue. */ 88 struct frv_interrupt_queue_element * 89 frv_queue_break_interrupt (SIM_CPU *current_cpu) 90 { 91 return frv_queue_interrupt (current_cpu, FRV_BREAK_EXCEPTION); 92 } 93 94 /* Add a software interrupt to the interrupt queue. */ 95 struct frv_interrupt_queue_element * 96 frv_queue_software_interrupt (SIM_CPU *current_cpu, SI offset) 97 { 98 struct frv_interrupt_queue_element *new_element 99 = frv_queue_interrupt (current_cpu, FRV_TRAP_INSTRUCTION); 100 101 struct frv_interrupt *interrupt = & frv_interrupt_table[new_element->kind]; 102 interrupt->handler_offset = offset; 103 104 return new_element; 105 } 106 107 /* Add a program interrupt to the interrupt queue. */ 108 struct frv_interrupt_queue_element * 109 frv_queue_program_interrupt ( 110 SIM_CPU *current_cpu, enum frv_interrupt_kind kind 111 ) 112 { 113 return frv_queue_interrupt (current_cpu, kind); 114 } 115 116 /* Add an external interrupt to the interrupt queue. */ 117 struct frv_interrupt_queue_element * 118 frv_queue_external_interrupt ( 119 SIM_CPU *current_cpu, enum frv_interrupt_kind kind 120 ) 121 { 122 if (! GET_H_PSR_ET () 123 || (kind != FRV_INTERRUPT_LEVEL_15 && kind < GET_H_PSR_PIL ())) 124 return NULL; /* Leave it for later. */ 125 126 return frv_queue_interrupt (current_cpu, kind); 127 } 128 129 /* Add any interrupt to the interrupt queue. It will be added in reverse 130 priority order. This makes it easy to find the highest priority interrupt 131 at the end of the queue and to remove it after processing. */ 132 struct frv_interrupt_queue_element * 133 frv_queue_interrupt (SIM_CPU *current_cpu, enum frv_interrupt_kind kind) 134 { 135 int i; 136 int j; 137 int limit = frv_interrupt_state.queue_index; 138 struct frv_interrupt_queue_element *new_element; 139 enum frv_interrupt_class iclass; 140 141 if (limit >= FRV_INTERRUPT_QUEUE_SIZE) 142 abort (); /* TODO: Make the queue dynamic */ 143 144 /* Find the right place in the queue. */ 145 for (i = 0; i < limit; ++i) 146 { 147 if (frv_interrupt_state.queue[i].kind >= kind) 148 break; 149 } 150 151 /* Don't queue two external interrupts of the same priority. */ 152 iclass = frv_interrupt_table[kind].iclass; 153 if (i < limit && iclass == FRV_EXTERNAL_INTERRUPT) 154 { 155 if (frv_interrupt_state.queue[i].kind == kind) 156 return & frv_interrupt_state.queue[i]; 157 } 158 159 /* Make room for the new interrupt in this spot. */ 160 for (j = limit - 1; j >= i; --j) 161 frv_interrupt_state.queue[j + 1] = frv_interrupt_state.queue[j]; 162 163 /* Add the new interrupt. */ 164 frv_interrupt_state.queue_index++; 165 new_element = & frv_interrupt_state.queue[i]; 166 new_element->kind = kind; 167 new_element->vpc = CPU_PC_GET (current_cpu); 168 new_element->u.data_written.length = 0; 169 frv_set_interrupt_queue_slot (current_cpu, new_element); 170 171 return new_element; 172 } 173 174 struct frv_interrupt_queue_element * 175 frv_queue_register_exception_interrupt (SIM_CPU *current_cpu, enum frv_rec rec) 176 { 177 struct frv_interrupt_queue_element *new_element = 178 frv_queue_program_interrupt (current_cpu, FRV_REGISTER_EXCEPTION); 179 180 new_element->u.rec = rec; 181 182 return new_element; 183 } 184 185 struct frv_interrupt_queue_element * 186 frv_queue_mem_address_not_aligned_interrupt (SIM_CPU *current_cpu, USI addr) 187 { 188 struct frv_interrupt_queue_element *new_element; 189 USI isr = GET_ISR (); 190 191 /* Make sure that this exception is not masked. */ 192 if (GET_ISR_EMAM (isr)) 193 return NULL; 194 195 /* Queue the interrupt. */ 196 new_element = frv_queue_program_interrupt (current_cpu, 197 FRV_MEM_ADDRESS_NOT_ALIGNED); 198 new_element->eaddress = addr; 199 new_element->u.data_written = frv_interrupt_state.data_written; 200 frv_interrupt_state.data_written.length = 0; 201 202 return new_element; 203 } 204 205 struct frv_interrupt_queue_element * 206 frv_queue_data_access_error_interrupt (SIM_CPU *current_cpu, USI addr) 207 { 208 struct frv_interrupt_queue_element *new_element; 209 new_element = frv_queue_program_interrupt (current_cpu, 210 FRV_DATA_ACCESS_ERROR); 211 new_element->eaddress = addr; 212 return new_element; 213 } 214 215 struct frv_interrupt_queue_element * 216 frv_queue_data_access_exception_interrupt (SIM_CPU *current_cpu) 217 { 218 return frv_queue_program_interrupt (current_cpu, FRV_DATA_ACCESS_EXCEPTION); 219 } 220 221 struct frv_interrupt_queue_element * 222 frv_queue_instruction_access_error_interrupt (SIM_CPU *current_cpu) 223 { 224 return frv_queue_program_interrupt (current_cpu, FRV_INSTRUCTION_ACCESS_ERROR); 225 } 226 227 struct frv_interrupt_queue_element * 228 frv_queue_instruction_access_exception_interrupt (SIM_CPU *current_cpu) 229 { 230 return frv_queue_program_interrupt (current_cpu, FRV_INSTRUCTION_ACCESS_EXCEPTION); 231 } 232 233 struct frv_interrupt_queue_element * 234 frv_queue_illegal_instruction_interrupt ( 235 SIM_CPU *current_cpu, const CGEN_INSN *insn 236 ) 237 { 238 SIM_DESC sd = CPU_STATE (current_cpu); 239 switch (STATE_ARCHITECTURE (sd)->mach) 240 { 241 case bfd_mach_fr400: 242 case bfd_mach_fr450: 243 case bfd_mach_fr550: 244 break; 245 default: 246 /* Some machines generate fp_exception for this case. */ 247 if (frv_is_float_insn (insn) || frv_is_media_insn (insn)) 248 { 249 struct frv_fp_exception_info fp_info = { 250 FSR_NO_EXCEPTION, FTT_SEQUENCE_ERROR 251 }; 252 return frv_queue_fp_exception_interrupt (current_cpu, & fp_info); 253 } 254 break; 255 } 256 257 return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION); 258 } 259 260 struct frv_interrupt_queue_element * 261 frv_queue_privileged_instruction_interrupt (SIM_CPU *current_cpu, const CGEN_INSN *insn) 262 { 263 /* The fr550 has no privileged instruction interrupt. It uses 264 illegal_instruction. */ 265 SIM_DESC sd = CPU_STATE (current_cpu); 266 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) 267 return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION); 268 269 return frv_queue_program_interrupt (current_cpu, FRV_PRIVILEGED_INSTRUCTION); 270 } 271 272 struct frv_interrupt_queue_element * 273 frv_queue_float_disabled_interrupt (SIM_CPU *current_cpu) 274 { 275 /* The fr550 has no fp_disabled interrupt. It uses illegal_instruction. */ 276 SIM_DESC sd = CPU_STATE (current_cpu); 277 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) 278 return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION); 279 280 return frv_queue_program_interrupt (current_cpu, FRV_FP_DISABLED); 281 } 282 283 struct frv_interrupt_queue_element * 284 frv_queue_media_disabled_interrupt (SIM_CPU *current_cpu) 285 { 286 /* The fr550 has no mp_disabled interrupt. It uses illegal_instruction. */ 287 SIM_DESC sd = CPU_STATE (current_cpu); 288 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) 289 return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION); 290 291 return frv_queue_program_interrupt (current_cpu, FRV_MP_DISABLED); 292 } 293 294 struct frv_interrupt_queue_element * 295 frv_queue_non_implemented_instruction_interrupt ( 296 SIM_CPU *current_cpu, const CGEN_INSN *insn 297 ) 298 { 299 SIM_DESC sd = CPU_STATE (current_cpu); 300 switch (STATE_ARCHITECTURE (sd)->mach) 301 { 302 case bfd_mach_fr400: 303 case bfd_mach_fr450: 304 case bfd_mach_fr550: 305 break; 306 default: 307 /* Some machines generate fp_exception or mp_exception for this case. */ 308 if (frv_is_float_insn (insn)) 309 { 310 struct frv_fp_exception_info fp_info = { 311 FSR_NO_EXCEPTION, FTT_UNIMPLEMENTED_FPOP 312 }; 313 return frv_queue_fp_exception_interrupt (current_cpu, & fp_info); 314 } 315 if (frv_is_media_insn (insn)) 316 { 317 frv_set_mp_exception_registers (current_cpu, MTT_UNIMPLEMENTED_MPOP, 318 0); 319 return NULL; /* no interrupt queued at this time. */ 320 } 321 break; 322 } 323 324 return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION); 325 } 326 327 /* Queue the given fp_exception interrupt. Also update fp_info by removing 328 masked interrupts and updating the 'slot' flield. */ 329 struct frv_interrupt_queue_element * 330 frv_queue_fp_exception_interrupt ( 331 SIM_CPU *current_cpu, struct frv_fp_exception_info *fp_info 332 ) 333 { 334 SI fsr0 = GET_FSR (0); 335 int tem = GET_FSR_TEM (fsr0); 336 int aexc = GET_FSR_AEXC (fsr0); 337 struct frv_interrupt_queue_element *new_element = NULL; 338 339 /* Update AEXC with the interrupts that are masked. */ 340 aexc |= fp_info->fsr_mask & ~tem; 341 SET_FSR_AEXC (fsr0, aexc); 342 SET_FSR (0, fsr0); 343 344 /* update fsr_mask with the exceptions that are enabled. */ 345 fp_info->fsr_mask &= tem; 346 347 /* If there is an unmasked interrupt then queue it, unless 348 this was a non-excepting insn, in which case simply set the NE 349 status registers. */ 350 if (frv_interrupt_state.ne_index != NE_NOFLAG 351 && fp_info->fsr_mask != FSR_NO_EXCEPTION) 352 { 353 SET_NE_FLAG (frv_interrupt_state.f_ne_flags, 354 frv_interrupt_state.ne_index); 355 /* TODO -- Set NESR for chips which support it. */ 356 new_element = NULL; 357 } 358 else if (fp_info->fsr_mask != FSR_NO_EXCEPTION 359 || fp_info->ftt == FTT_UNIMPLEMENTED_FPOP 360 || fp_info->ftt == FTT_SEQUENCE_ERROR 361 || fp_info->ftt == FTT_INVALID_FR) 362 { 363 new_element = frv_queue_program_interrupt (current_cpu, FRV_FP_EXCEPTION); 364 new_element->u.fp_info = *fp_info; 365 } 366 367 return new_element; 368 } 369 370 struct frv_interrupt_queue_element * 371 frv_queue_division_exception_interrupt (SIM_CPU *current_cpu, enum frv_dtt dtt) 372 { 373 struct frv_interrupt_queue_element *new_element = 374 frv_queue_program_interrupt (current_cpu, FRV_DIVISION_EXCEPTION); 375 376 new_element->u.dtt = dtt; 377 378 return new_element; 379 } 380 381 /* Check for interrupts caused by illegal insn access. These conditions are 382 checked in the order specified by the fr400 and fr500 LSI specs. */ 383 void 384 frv_detect_insn_access_interrupts (SIM_CPU *current_cpu, SCACHE *sc) 385 { 386 387 const CGEN_INSN *insn = sc->argbuf.idesc->idata; 388 SIM_DESC sd = CPU_STATE (current_cpu); 389 FRV_VLIW *vliw = CPU_VLIW (current_cpu); 390 391 /* Check for vliw constraints. */ 392 if (vliw->constraint_violation) 393 frv_queue_illegal_instruction_interrupt (current_cpu, insn); 394 /* Check for non-excepting insns. */ 395 else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_NON_EXCEPTING) 396 && ! GET_H_PSR_NEM ()) 397 frv_queue_non_implemented_instruction_interrupt (current_cpu, insn); 398 /* Check for conditional insns. */ 399 else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONDITIONAL) 400 && ! GET_H_PSR_CM ()) 401 frv_queue_non_implemented_instruction_interrupt (current_cpu, insn); 402 /* Make sure floating point support is enabled. */ 403 else if (! GET_H_PSR_EF ()) 404 { 405 /* Generate fp_disabled if it is a floating point insn or if PSR.EM is 406 off and the insns accesses a fp register. */ 407 if (frv_is_float_insn (insn) 408 || (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR_ACCESS) 409 && ! GET_H_PSR_EM ())) 410 frv_queue_float_disabled_interrupt (current_cpu); 411 } 412 /* Make sure media support is enabled. */ 413 else if (! GET_H_PSR_EM ()) 414 { 415 /* Generate mp_disabled if it is a media insn. */ 416 if (frv_is_media_insn (insn) || CGEN_INSN_NUM (insn) == FRV_INSN_MTRAP) 417 frv_queue_media_disabled_interrupt (current_cpu); 418 } 419 /* Check for privileged insns. */ 420 else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_PRIVILEGED) && 421 ! GET_H_PSR_S ()) 422 frv_queue_privileged_instruction_interrupt (current_cpu, insn); 423 #if 0 /* disable for now until we find out how FSR0.QNE gets reset. */ 424 else 425 { 426 /* Enter the halt state if FSR0.QNE is set and we are executing a 427 floating point insn, a media insn or an insn which access a FR 428 register. */ 429 SI fsr0 = GET_FSR (0); 430 if (GET_FSR_QNE (fsr0) 431 && (frv_is_float_insn (insn) || frv_is_media_insn (insn) 432 || CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR_ACCESS))) 433 { 434 sim_engine_halt (sd, current_cpu, NULL, GET_H_PC (), sim_stopped, 435 SIM_SIGINT); 436 } 437 } 438 #endif 439 } 440 441 /* Record the current VLIW slot in the given interrupt queue element. */ 442 void 443 frv_set_interrupt_queue_slot ( 444 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item 445 ) 446 { 447 FRV_VLIW *vliw = CPU_VLIW (current_cpu); 448 int slot = vliw->next_slot - 1; 449 item->slot = (*vliw->current_vliw)[slot]; 450 } 451 452 /* Handle an individual interrupt. */ 453 static void 454 handle_interrupt (SIM_CPU *current_cpu, IADDR pc) 455 { 456 struct frv_interrupt *interrupt; 457 int writeback_done = 0; 458 while (1) 459 { 460 /* Interrupts are queued in priority order with the highest priority 461 last. */ 462 int index = frv_interrupt_state.queue_index - 1; 463 struct frv_interrupt_queue_element *item 464 = & frv_interrupt_state.queue[index]; 465 interrupt = & frv_interrupt_table[item->kind]; 466 467 switch (interrupt->iclass) 468 { 469 case FRV_EXTERNAL_INTERRUPT: 470 /* Perform writeback first. This may cause a higher priority 471 interrupt. */ 472 if (! writeback_done) 473 { 474 frvbf_perform_writeback (current_cpu); 475 writeback_done = 1; 476 continue; 477 } 478 frv_external_interrupt (current_cpu, item, pc); 479 return; 480 case FRV_SOFTWARE_INTERRUPT: 481 frv_interrupt_state.queue_index = index; 482 frv_software_interrupt (current_cpu, item, pc); 483 return; 484 case FRV_PROGRAM_INTERRUPT: 485 /* If the program interrupt is not strict (imprecise), then perform 486 writeback first. This may, in turn, cause a higher priority 487 interrupt. */ 488 if (! interrupt->precise && ! writeback_done) 489 { 490 frv_interrupt_state.imprecise_interrupt = item; 491 frvbf_perform_writeback (current_cpu); 492 writeback_done = 1; 493 continue; 494 } 495 frv_interrupt_state.queue_index = index; 496 frv_program_interrupt (current_cpu, item, pc); 497 return; 498 case FRV_BREAK_INTERRUPT: 499 frv_interrupt_state.queue_index = index; 500 frv_break_interrupt (current_cpu, interrupt, pc); 501 return; 502 case FRV_RESET_INTERRUPT: 503 break; 504 default: 505 break; 506 } 507 frv_interrupt_state.queue_index = index; 508 break; /* out of loop. */ 509 } 510 511 /* We should never get here. */ 512 { 513 SIM_DESC sd = CPU_STATE (current_cpu); 514 sim_engine_abort (sd, current_cpu, pc, 515 "interrupt class not supported %d\n", 516 interrupt->iclass); 517 } 518 } 519 520 /* Check to see the if the RSTR.HR or RSTR.SR bits have been set. If so, handle 521 the appropriate reset interrupt. */ 522 static int 523 check_reset (SIM_CPU *current_cpu, IADDR pc) 524 { 525 int hsr0; 526 int hr; 527 int sr; 528 SI rstr; 529 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu); 530 IADDR address = RSTR_ADDRESS; 531 532 /* We don't want this to show up in the cache statistics, so read the 533 cache passively. */ 534 if (! frv_cache_read_passive_SI (cache, address, & rstr)) 535 rstr = sim_core_read_unaligned_4 (current_cpu, pc, read_map, address); 536 537 hr = GET_RSTR_HR (rstr); 538 sr = GET_RSTR_SR (rstr); 539 540 if (! hr && ! sr) 541 return 0; /* no reset. */ 542 543 /* Reinitialize the machine state. */ 544 if (hr) 545 frv_hardware_reset (current_cpu); 546 else 547 frv_software_reset (current_cpu); 548 549 /* Branch to the reset address. */ 550 hsr0 = GET_HSR0 (); 551 if (GET_HSR0_SA (hsr0)) 552 SET_H_PC (0xff000000); 553 else 554 SET_H_PC (0); 555 556 return 1; /* reset */ 557 } 558 559 /* Process any pending interrupt(s) after a group of parallel insns. */ 560 void 561 frv_process_interrupts (SIM_CPU *current_cpu) 562 { 563 SI NE_flags[2]; 564 /* Need to save the pc here because writeback may change it (due to a 565 branch). */ 566 IADDR pc = CPU_PC_GET (current_cpu); 567 568 /* Check for a reset before anything else. */ 569 if (check_reset (current_cpu, pc)) 570 return; 571 572 /* First queue the writes for any accumulated NE flags. */ 573 if (frv_interrupt_state.f_ne_flags[0] != 0 574 || frv_interrupt_state.f_ne_flags[1] != 0) 575 { 576 GET_NE_FLAGS (NE_flags, H_SPR_FNER0); 577 NE_flags[0] |= frv_interrupt_state.f_ne_flags[0]; 578 NE_flags[1] |= frv_interrupt_state.f_ne_flags[1]; 579 SET_NE_FLAGS (H_SPR_FNER0, NE_flags); 580 } 581 582 /* If there is no interrupt pending, then perform parallel writeback. This 583 may cause an interrupt. */ 584 if (frv_interrupt_state.queue_index <= 0) 585 frvbf_perform_writeback (current_cpu); 586 587 /* If there is an interrupt pending, then process it. */ 588 if (frv_interrupt_state.queue_index > 0) 589 handle_interrupt (current_cpu, pc); 590 } 591 592 /* Find the next available ESR and return its index */ 593 static int 594 esr_for_data_access_exception ( 595 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item 596 ) 597 { 598 SIM_DESC sd = CPU_STATE (current_cpu); 599 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) 600 return 8; /* Use ESR8, EPCR8. */ 601 602 if (item->slot == UNIT_I0) 603 return 8; /* Use ESR8, EPCR8, EAR8, EDR8. */ 604 605 return 9; /* Use ESR9, EPCR9, EAR9. */ 606 } 607 608 /* Set the next available EDR register with the data which was to be stored 609 and return the index of the register. */ 610 static int 611 set_edr_register ( 612 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, int edr_index 613 ) 614 { 615 /* EDR0, EDR4 and EDR8 are available as blocks of 4. 616 SI data uses EDR3, EDR7 and EDR11 617 DI data uses EDR2, EDR6 and EDR10 618 XI data uses EDR0, EDR4 and EDR8. */ 619 int i; 620 edr_index += 4 - item->u.data_written.length; 621 for (i = 0; i < item->u.data_written.length; ++i) 622 SET_EDR (edr_index + i, item->u.data_written.words[i]); 623 624 return edr_index; 625 }; 626 627 /* Clear ESFR0, EPCRx, ESRx, EARx and EDRx. */ 628 static void 629 clear_exception_status_registers (SIM_CPU *current_cpu) 630 { 631 int i; 632 /* It is only necessary to clear the flag bits indicating which registers 633 are valid. */ 634 SET_ESFR (0, 0); 635 SET_ESFR (1, 0); 636 637 for (i = 0; i <= 2; ++i) 638 { 639 SI esr = GET_ESR (i); 640 CLEAR_ESR_VALID (esr); 641 SET_ESR (i, esr); 642 } 643 for (i = 8; i <= 15; ++i) 644 { 645 SI esr = GET_ESR (i); 646 CLEAR_ESR_VALID (esr); 647 SET_ESR (i, esr); 648 } 649 } 650 651 /* Record state for media exception. */ 652 void 653 frv_set_mp_exception_registers ( 654 SIM_CPU *current_cpu, enum frv_msr_mtt mtt, int sie 655 ) 656 { 657 /* Record the interrupt factor in MSR0. */ 658 SI msr0 = GET_MSR (0); 659 if (GET_MSR_MTT (msr0) == MTT_NONE) 660 SET_MSR_MTT (msr0, mtt); 661 662 /* Also set the OVF bit in the appropriate MSR as well as MSR0.AOVF. */ 663 if (mtt == MTT_OVERFLOW) 664 { 665 FRV_VLIW *vliw = CPU_VLIW (current_cpu); 666 int slot = vliw->next_slot - 1; 667 SIM_DESC sd = CPU_STATE (current_cpu); 668 669 /* If this insn is in the M2 slot, then set MSR1.OVF and MSR1.SIE, 670 otherwise set MSR0.OVF and MSR0.SIE. */ 671 if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550 && (*vliw->current_vliw)[slot] == UNIT_FM1) 672 { 673 SI msr = GET_MSR (1); 674 OR_MSR_SIE (msr, sie); 675 SET_MSR_OVF (msr); 676 SET_MSR (1, msr); 677 } 678 else 679 { 680 OR_MSR_SIE (msr0, sie); 681 SET_MSR_OVF (msr0); 682 } 683 684 /* Generate the interrupt now if MSR0.MPEM is set on fr550 */ 685 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550 && GET_MSR_MPEM (msr0)) 686 frv_queue_program_interrupt (current_cpu, FRV_MP_EXCEPTION); 687 else 688 { 689 /* Regardless of the slot, set MSR0.AOVF. */ 690 SET_MSR_AOVF (msr0); 691 } 692 } 693 694 SET_MSR (0, msr0); 695 } 696 697 /* Determine the correct FQ register to use for the given exception. 698 Return -1 if a register is not available. */ 699 static int 700 fq_for_exception ( 701 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item 702 ) 703 { 704 SI fq; 705 struct frv_fp_exception_info *fp_info = & item->u.fp_info; 706 707 /* For fp_exception overflow, underflow or inexact, use FQ0 or FQ1. */ 708 if (fp_info->ftt == FTT_IEEE_754_EXCEPTION 709 && (fp_info->fsr_mask & (FSR_OVERFLOW | FSR_UNDERFLOW | FSR_INEXACT))) 710 { 711 fq = GET_FQ (0); 712 if (! GET_FQ_VALID (fq)) 713 return 0; /* FQ0 is available. */ 714 fq = GET_FQ (1); 715 if (! GET_FQ_VALID (fq)) 716 return 1; /* FQ1 is available. */ 717 718 /* No FQ register is available */ 719 { 720 SIM_DESC sd = CPU_STATE (current_cpu); 721 IADDR pc = CPU_PC_GET (current_cpu); 722 sim_engine_abort (sd, current_cpu, pc, "No FQ register available\n"); 723 } 724 return -1; 725 } 726 /* For other exceptions, use FQ2 if the insn was in slot F0/I0 and FQ3 727 otherwise. */ 728 if (item->slot == UNIT_FM0 || item->slot == UNIT_I0) 729 return 2; 730 731 return 3; 732 } 733 734 /* Set FSR0, FQ0-FQ9, depending on the interrupt. */ 735 static void 736 set_fp_exception_registers ( 737 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item 738 ) 739 { 740 int fq_index; 741 SI fq; 742 SI insn; 743 SI fsr0; 744 IADDR pc; 745 struct frv_fp_exception_info *fp_info; 746 SIM_DESC sd = CPU_STATE (current_cpu); 747 748 /* No FQ registers on fr550 */ 749 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) 750 { 751 /* Update the fsr. */ 752 fp_info = & item->u.fp_info; 753 fsr0 = GET_FSR (0); 754 SET_FSR_FTT (fsr0, fp_info->ftt); 755 SET_FSR (0, fsr0); 756 return; 757 } 758 759 /* Select an FQ and update it with the exception information. */ 760 fq_index = fq_for_exception (current_cpu, item); 761 if (fq_index == -1) 762 return; 763 764 fp_info = & item->u.fp_info; 765 fq = GET_FQ (fq_index); 766 SET_FQ_MIV (fq, MIV_FLOAT); 767 SET_FQ_SIE (fq, SIE_NIL); 768 SET_FQ_FTT (fq, fp_info->ftt); 769 SET_FQ_CEXC (fq, fp_info->fsr_mask); 770 SET_FQ_VALID (fq); 771 SET_FQ (fq_index, fq); 772 773 /* Write the failing insn into FQx.OPC. */ 774 pc = item->vpc; 775 insn = GETMEMSI (current_cpu, pc, pc); 776 SET_FQ_OPC (fq_index, insn); 777 778 /* Update the fsr. */ 779 fsr0 = GET_FSR (0); 780 SET_FSR_QNE (fsr0); /* FQ not empty */ 781 SET_FSR_FTT (fsr0, fp_info->ftt); 782 SET_FSR (0, fsr0); 783 } 784 785 /* Record the state of a division exception in the ISR. */ 786 static void 787 set_isr_exception_fields ( 788 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item 789 ) 790 { 791 USI isr = GET_ISR (); 792 int dtt = GET_ISR_DTT (isr); 793 dtt |= item->u.dtt; 794 SET_ISR_DTT (isr, dtt); 795 SET_ISR (isr); 796 } 797 798 /* Set ESFR0, EPCRx, ESRx, EARx and EDRx, according to the given program 799 interrupt. */ 800 static void 801 set_exception_status_registers ( 802 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item 803 ) 804 { 805 struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind]; 806 int slot = (item->vpc - previous_vliw_pc) / 4; 807 int reg_index = -1; 808 int set_ear = 0; 809 int set_edr = 0; 810 int set_daec = 0; 811 int set_epcr = 0; 812 SI esr = 0; 813 SIM_DESC sd = CPU_STATE (current_cpu); 814 815 /* If the interrupt is strict (precise) or the interrupt is on the insns 816 in the I0 pipe, then set the 0 registers. */ 817 if (interrupt->precise) 818 { 819 reg_index = 0; 820 if (interrupt->kind == FRV_REGISTER_EXCEPTION) 821 SET_ESR_REC (esr, item->u.rec); 822 else if (interrupt->kind == FRV_INSTRUCTION_ACCESS_EXCEPTION) 823 SET_ESR_IAEC (esr, item->u.iaec); 824 /* For fr550, don't set epcr for precise interrupts. */ 825 if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550) 826 set_epcr = 1; 827 } 828 else 829 { 830 switch (interrupt->kind) 831 { 832 case FRV_DIVISION_EXCEPTION: 833 set_isr_exception_fields (current_cpu, item); 834 /* fall thru to set reg_index. */ 835 case FRV_COMMIT_EXCEPTION: 836 /* For fr550, always use ESR0. */ 837 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) 838 reg_index = 0; 839 else if (item->slot == UNIT_I0) 840 reg_index = 0; 841 else if (item->slot == UNIT_I1) 842 reg_index = 1; 843 set_epcr = 1; 844 break; 845 case FRV_DATA_STORE_ERROR: 846 reg_index = 14; /* Use ESR14. */ 847 break; 848 case FRV_DATA_ACCESS_ERROR: 849 reg_index = 15; /* Use ESR15, EPCR15. */ 850 set_ear = 1; 851 break; 852 case FRV_DATA_ACCESS_EXCEPTION: 853 set_daec = 1; 854 /* fall through */ 855 case FRV_DATA_ACCESS_MMU_MISS: 856 case FRV_MEM_ADDRESS_NOT_ALIGNED: 857 /* Get the appropriate ESR, EPCR, EAR and EDR. 858 EAR will be set. EDR will not be set if this is a store insn. */ 859 set_ear = 1; 860 /* For fr550, never use EDRx. */ 861 if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550) 862 if (item->u.data_written.length != 0) 863 set_edr = 1; 864 reg_index = esr_for_data_access_exception (current_cpu, item); 865 set_epcr = 1; 866 break; 867 case FRV_MP_EXCEPTION: 868 /* For fr550, use EPCR2 and ESR2. */ 869 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) 870 { 871 reg_index = 2; 872 set_epcr = 1; 873 } 874 break; /* MSR0-1, FQ0-9 are already set. */ 875 case FRV_FP_EXCEPTION: 876 set_fp_exception_registers (current_cpu, item); 877 /* For fr550, use EPCR2 and ESR2. */ 878 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) 879 { 880 reg_index = 2; 881 set_epcr = 1; 882 } 883 break; 884 default: 885 { 886 SIM_DESC sd = CPU_STATE (current_cpu); 887 IADDR pc = CPU_PC_GET (current_cpu); 888 sim_engine_abort (sd, current_cpu, pc, 889 "invalid non-strict program interrupt kind: %d\n", 890 interrupt->kind); 891 break; 892 } 893 } 894 } /* non-strict (imprecise) interrupt */ 895 896 /* Now fill in the selected exception status registers. */ 897 if (reg_index != -1) 898 { 899 /* Now set the exception status registers. */ 900 SET_ESFR_FLAG (reg_index); 901 SET_ESR_EC (esr, interrupt->ec); 902 903 if (set_epcr) 904 { 905 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400) 906 SET_EPCR (reg_index, previous_vliw_pc); 907 else 908 SET_EPCR (reg_index, item->vpc); 909 } 910 911 if (set_ear) 912 { 913 SET_EAR (reg_index, item->eaddress); 914 SET_ESR_EAV (esr); 915 } 916 else 917 CLEAR_ESR_EAV (esr); 918 919 if (set_edr) 920 { 921 int edn = set_edr_register (current_cpu, item, 0/* EDR0-3 */); 922 SET_ESR_EDN (esr, edn); 923 SET_ESR_EDV (esr); 924 } 925 else 926 CLEAR_ESR_EDV (esr); 927 928 if (set_daec) 929 SET_ESR_DAEC (esr, item->u.daec); 930 931 SET_ESR_VALID (esr); 932 SET_ESR (reg_index, esr); 933 } 934 } 935 936 /* Check for compound interrupts. 937 Returns NULL if no interrupt is to be processed. */ 938 static struct frv_interrupt * 939 check_for_compound_interrupt ( 940 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item 941 ) 942 { 943 struct frv_interrupt *interrupt; 944 945 /* Set the exception status registers for the original interrupt. */ 946 set_exception_status_registers (current_cpu, item); 947 interrupt = & frv_interrupt_table[item->kind]; 948 949 if (! interrupt->precise) 950 { 951 IADDR vpc = 0; 952 int mask = 0; 953 954 vpc = item->vpc; 955 mask = (1 << item->kind); 956 957 /* Look for more queued program interrupts which are non-deferred 958 (pending inhibit), imprecise (non-strict) different than an interrupt 959 already found and caused by a different insn. A bit mask is used 960 to keep track of interrupts which have already been detected. */ 961 while (item != frv_interrupt_state.queue) 962 { 963 enum frv_interrupt_kind kind; 964 struct frv_interrupt *next_interrupt; 965 --item; 966 kind = item->kind; 967 next_interrupt = & frv_interrupt_table[kind]; 968 969 if (next_interrupt->iclass != FRV_PROGRAM_INTERRUPT) 970 break; /* no program interrupts left. */ 971 972 if (item->vpc == vpc) 973 continue; /* caused by the same insn. */ 974 975 vpc = item->vpc; 976 if (! next_interrupt->precise && ! next_interrupt->deferred) 977 { 978 if (! (mask & (1 << kind))) 979 { 980 /* Set the exception status registers for the additional 981 interrupt. */ 982 set_exception_status_registers (current_cpu, item); 983 mask |= (1 << kind); 984 interrupt = & frv_interrupt_table[FRV_COMPOUND_EXCEPTION]; 985 } 986 } 987 } 988 } 989 990 /* Return with either the original interrupt, a compound_exception, 991 or no exception. */ 992 return interrupt; 993 } 994 995 /* Handle a program interrupt. */ 996 void 997 frv_program_interrupt ( 998 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, IADDR pc 999 ) 1000 { 1001 struct frv_interrupt *interrupt; 1002 1003 clear_exception_status_registers (current_cpu); 1004 /* If two or more non-deferred imprecise (non-strict) interrupts occur 1005 on two or more insns, then generate a compound_exception. */ 1006 interrupt = check_for_compound_interrupt (current_cpu, item); 1007 if (interrupt != NULL) 1008 { 1009 frv_program_or_software_interrupt (current_cpu, interrupt, pc); 1010 frv_clear_interrupt_classes (FRV_SOFTWARE_INTERRUPT, 1011 FRV_PROGRAM_INTERRUPT); 1012 } 1013 } 1014 1015 /* Handle a software interrupt. */ 1016 void 1017 frv_software_interrupt ( 1018 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, IADDR pc 1019 ) 1020 { 1021 struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind]; 1022 frv_program_or_software_interrupt (current_cpu, interrupt, pc); 1023 } 1024 1025 /* Handle a program interrupt or a software interrupt in non-operating mode. */ 1026 void 1027 frv_non_operating_interrupt ( 1028 SIM_CPU *current_cpu, enum frv_interrupt_kind kind, IADDR pc 1029 ) 1030 { 1031 SIM_DESC sd = CPU_STATE (current_cpu); 1032 switch (kind) 1033 { 1034 case FRV_INTERRUPT_LEVEL_1: 1035 case FRV_INTERRUPT_LEVEL_2: 1036 case FRV_INTERRUPT_LEVEL_3: 1037 case FRV_INTERRUPT_LEVEL_4: 1038 case FRV_INTERRUPT_LEVEL_5: 1039 case FRV_INTERRUPT_LEVEL_6: 1040 case FRV_INTERRUPT_LEVEL_7: 1041 case FRV_INTERRUPT_LEVEL_8: 1042 case FRV_INTERRUPT_LEVEL_9: 1043 case FRV_INTERRUPT_LEVEL_10: 1044 case FRV_INTERRUPT_LEVEL_11: 1045 case FRV_INTERRUPT_LEVEL_12: 1046 case FRV_INTERRUPT_LEVEL_13: 1047 case FRV_INTERRUPT_LEVEL_14: 1048 case FRV_INTERRUPT_LEVEL_15: 1049 sim_engine_abort (sd, current_cpu, pc, 1050 "interrupt: external %d\n", kind + 1); 1051 break; 1052 case FRV_TRAP_INSTRUCTION: 1053 break; /* handle as in operating mode. */ 1054 case FRV_COMMIT_EXCEPTION: 1055 sim_engine_abort (sd, current_cpu, pc, 1056 "interrupt: commit_exception\n"); 1057 break; 1058 case FRV_DIVISION_EXCEPTION: 1059 sim_engine_abort (sd, current_cpu, pc, 1060 "interrupt: division_exception\n"); 1061 break; 1062 case FRV_DATA_STORE_ERROR: 1063 sim_engine_abort (sd, current_cpu, pc, 1064 "interrupt: data_store_error\n"); 1065 break; 1066 case FRV_DATA_ACCESS_EXCEPTION: 1067 sim_engine_abort (sd, current_cpu, pc, 1068 "interrupt: data_access_exception\n"); 1069 break; 1070 case FRV_DATA_ACCESS_MMU_MISS: 1071 sim_engine_abort (sd, current_cpu, pc, 1072 "interrupt: data_access_mmu_miss\n"); 1073 break; 1074 case FRV_DATA_ACCESS_ERROR: 1075 sim_engine_abort (sd, current_cpu, pc, 1076 "interrupt: data_access_error\n"); 1077 break; 1078 case FRV_MP_EXCEPTION: 1079 sim_engine_abort (sd, current_cpu, pc, 1080 "interrupt: mp_exception\n"); 1081 break; 1082 case FRV_FP_EXCEPTION: 1083 sim_engine_abort (sd, current_cpu, pc, 1084 "interrupt: fp_exception\n"); 1085 break; 1086 case FRV_MEM_ADDRESS_NOT_ALIGNED: 1087 sim_engine_abort (sd, current_cpu, pc, 1088 "interrupt: mem_address_not_aligned\n"); 1089 break; 1090 case FRV_REGISTER_EXCEPTION: 1091 sim_engine_abort (sd, current_cpu, pc, 1092 "interrupt: register_exception\n"); 1093 break; 1094 case FRV_MP_DISABLED: 1095 sim_engine_abort (sd, current_cpu, pc, 1096 "interrupt: mp_disabled\n"); 1097 break; 1098 case FRV_FP_DISABLED: 1099 sim_engine_abort (sd, current_cpu, pc, 1100 "interrupt: fp_disabled\n"); 1101 break; 1102 case FRV_PRIVILEGED_INSTRUCTION: 1103 sim_engine_abort (sd, current_cpu, pc, 1104 "interrupt: privileged_instruction\n"); 1105 break; 1106 case FRV_ILLEGAL_INSTRUCTION: 1107 sim_engine_abort (sd, current_cpu, pc, 1108 "interrupt: illegal_instruction\n"); 1109 break; 1110 case FRV_INSTRUCTION_ACCESS_EXCEPTION: 1111 sim_engine_abort (sd, current_cpu, pc, 1112 "interrupt: instruction_access_exception\n"); 1113 break; 1114 case FRV_INSTRUCTION_ACCESS_MMU_MISS: 1115 sim_engine_abort (sd, current_cpu, pc, 1116 "interrupt: instruction_access_mmu_miss\n"); 1117 break; 1118 case FRV_INSTRUCTION_ACCESS_ERROR: 1119 sim_engine_abort (sd, current_cpu, pc, 1120 "interrupt: insn_access_error\n"); 1121 break; 1122 case FRV_COMPOUND_EXCEPTION: 1123 sim_engine_abort (sd, current_cpu, pc, 1124 "interrupt: compound_exception\n"); 1125 break; 1126 case FRV_BREAK_EXCEPTION: 1127 sim_engine_abort (sd, current_cpu, pc, 1128 "interrupt: break_exception\n"); 1129 break; 1130 case FRV_RESET: 1131 sim_engine_abort (sd, current_cpu, pc, 1132 "interrupt: reset\n"); 1133 break; 1134 default: 1135 sim_engine_abort (sd, current_cpu, pc, 1136 "unhandled interrupt kind: %d\n", kind); 1137 break; 1138 } 1139 } 1140 1141 /* Handle a break interrupt. */ 1142 void 1143 frv_break_interrupt ( 1144 SIM_CPU *current_cpu, struct frv_interrupt *interrupt, IADDR current_pc 1145 ) 1146 { 1147 IADDR new_pc; 1148 1149 /* BPCSR=PC 1150 BPSR.BS=PSR.S 1151 BPSR.BET=PSR.ET 1152 PSR.S=1 1153 PSR.ET=0 1154 TBR.TT=0xff 1155 PC=TBR 1156 */ 1157 /* Must set PSR.S first to allow access to supervisor-only spr registers. */ 1158 SET_H_BPSR_BS (GET_H_PSR_S ()); 1159 SET_H_BPSR_BET (GET_H_PSR_ET ()); 1160 SET_H_PSR_S (1); 1161 SET_H_PSR_ET (0); 1162 /* Must set PSR.S first to allow access to supervisor-only spr registers. */ 1163 SET_H_SPR (H_SPR_BPCSR, current_pc); 1164 1165 /* Set the new PC in the TBR. */ 1166 SET_H_TBR_TT (interrupt->handler_offset); 1167 new_pc = GET_H_SPR (H_SPR_TBR); 1168 SET_H_PC (new_pc); 1169 1170 CPU_DEBUG_STATE (current_cpu) = 1; 1171 } 1172 1173 /* Handle a program interrupt or a software interrupt. */ 1174 void 1175 frv_program_or_software_interrupt ( 1176 SIM_CPU *current_cpu, struct frv_interrupt *interrupt, IADDR current_pc 1177 ) 1178 { 1179 USI new_pc; 1180 int original_psr_et; 1181 1182 /* PCSR=PC 1183 PSR.PS=PSR.S 1184 PSR.ET=0 1185 PSR.S=1 1186 if PSR.ESR==1 1187 SR0 through SR3=GR4 through GR7 1188 TBR.TT=interrupt handler offset 1189 PC=TBR 1190 */ 1191 original_psr_et = GET_H_PSR_ET (); 1192 1193 SET_H_PSR_PS (GET_H_PSR_S ()); 1194 SET_H_PSR_ET (0); 1195 SET_H_PSR_S (1); 1196 1197 /* Must set PSR.S first to allow access to supervisor-only spr registers. */ 1198 /* The PCSR depends on the precision of the interrupt. */ 1199 if (interrupt->precise) 1200 SET_H_SPR (H_SPR_PCSR, previous_vliw_pc); 1201 else 1202 SET_H_SPR (H_SPR_PCSR, current_pc); 1203 1204 /* Set the new PC in the TBR. */ 1205 SET_H_TBR_TT (interrupt->handler_offset); 1206 new_pc = GET_H_SPR (H_SPR_TBR); 1207 SET_H_PC (new_pc); 1208 1209 /* If PSR.ET was not originally set, then enter the stopped state. */ 1210 if (! original_psr_et) 1211 { 1212 SIM_DESC sd = CPU_STATE (current_cpu); 1213 frv_non_operating_interrupt (current_cpu, interrupt->kind, current_pc); 1214 sim_engine_halt (sd, current_cpu, NULL, new_pc, sim_stopped, SIM_SIGINT); 1215 } 1216 } 1217 1218 /* Handle a program interrupt or a software interrupt. */ 1219 void 1220 frv_external_interrupt ( 1221 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, IADDR pc 1222 ) 1223 { 1224 USI new_pc; 1225 struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind]; 1226 1227 /* Don't process the interrupt if PSR.ET is not set or if it is masked. 1228 Interrupt 15 is processed even if it appears to be masked. */ 1229 if (! GET_H_PSR_ET () 1230 || (interrupt->kind != FRV_INTERRUPT_LEVEL_15 1231 && interrupt->kind < GET_H_PSR_PIL ())) 1232 return; /* Leave it for later. */ 1233 1234 /* Remove the interrupt from the queue. */ 1235 --frv_interrupt_state.queue_index; 1236 1237 /* PCSR=PC 1238 PSR.PS=PSR.S 1239 PSR.ET=0 1240 PSR.S=1 1241 if PSR.ESR==1 1242 SR0 through SR3=GR4 through GR7 1243 TBR.TT=interrupt handler offset 1244 PC=TBR 1245 */ 1246 SET_H_PSR_PS (GET_H_PSR_S ()); 1247 SET_H_PSR_ET (0); 1248 SET_H_PSR_S (1); 1249 /* Must set PSR.S first to allow access to supervisor-only spr registers. */ 1250 SET_H_SPR (H_SPR_PCSR, GET_H_PC ()); 1251 1252 /* Set the new PC in the TBR. */ 1253 SET_H_TBR_TT (interrupt->handler_offset); 1254 new_pc = GET_H_SPR (H_SPR_TBR); 1255 SET_H_PC (new_pc); 1256 } 1257 1258 /* Clear interrupts which fall within the range of classes given. */ 1259 void 1260 frv_clear_interrupt_classes ( 1261 enum frv_interrupt_class low_class, enum frv_interrupt_class high_class 1262 ) 1263 { 1264 int i; 1265 int j; 1266 int limit = frv_interrupt_state.queue_index; 1267 1268 /* Find the lowest priority interrupt to be removed. */ 1269 for (i = 0; i < limit; ++i) 1270 { 1271 enum frv_interrupt_kind kind = frv_interrupt_state.queue[i].kind; 1272 struct frv_interrupt* interrupt = & frv_interrupt_table[kind]; 1273 if (interrupt->iclass >= low_class) 1274 break; 1275 } 1276 1277 /* Find the highest priority interrupt to be removed. */ 1278 for (j = limit - 1; j >= i; --j) 1279 { 1280 enum frv_interrupt_kind kind = frv_interrupt_state.queue[j].kind; 1281 struct frv_interrupt* interrupt = & frv_interrupt_table[kind]; 1282 if (interrupt->iclass <= high_class) 1283 break; 1284 } 1285 1286 /* Shuffle the remaining high priority interrupts down into the empty space 1287 left by the deleted interrupts. */ 1288 if (j >= i) 1289 { 1290 for (++j; j < limit; ++j) 1291 frv_interrupt_state.queue[i++] = frv_interrupt_state.queue[j]; 1292 frv_interrupt_state.queue_index -= (j - i); 1293 } 1294 } 1295 1296 /* Save data written to memory into the interrupt state so that it can be 1297 copied to the appropriate EDR register, if necessary, in the event of an 1298 interrupt. */ 1299 void 1300 frv_save_data_written_for_interrupts ( 1301 SIM_CPU *current_cpu, CGEN_WRITE_QUEUE_ELEMENT *item 1302 ) 1303 { 1304 /* Record the slot containing the insn doing the write in the 1305 interrupt state. */ 1306 frv_interrupt_state.slot = CGEN_WRITE_QUEUE_ELEMENT_PIPE (item); 1307 1308 /* Now record any data written to memory in the interrupt state. */ 1309 switch (CGEN_WRITE_QUEUE_ELEMENT_KIND (item)) 1310 { 1311 case CGEN_BI_WRITE: 1312 case CGEN_QI_WRITE: 1313 case CGEN_SI_WRITE: 1314 case CGEN_SF_WRITE: 1315 case CGEN_PC_WRITE: 1316 case CGEN_FN_HI_WRITE: 1317 case CGEN_FN_SI_WRITE: 1318 case CGEN_FN_SF_WRITE: 1319 case CGEN_FN_DI_WRITE: 1320 case CGEN_FN_DF_WRITE: 1321 case CGEN_FN_XI_WRITE: 1322 case CGEN_FN_PC_WRITE: 1323 break; /* Ignore writes to registers. */ 1324 case CGEN_MEM_QI_WRITE: 1325 frv_interrupt_state.data_written.length = 1; 1326 frv_interrupt_state.data_written.words[0] 1327 = item->kinds.mem_qi_write.value; 1328 break; 1329 case CGEN_MEM_HI_WRITE: 1330 frv_interrupt_state.data_written.length = 1; 1331 frv_interrupt_state.data_written.words[0] 1332 = item->kinds.mem_hi_write.value; 1333 break; 1334 case CGEN_MEM_SI_WRITE: 1335 frv_interrupt_state.data_written.length = 1; 1336 frv_interrupt_state.data_written.words[0] 1337 = item->kinds.mem_si_write.value; 1338 break; 1339 case CGEN_MEM_DI_WRITE: 1340 frv_interrupt_state.data_written.length = 2; 1341 frv_interrupt_state.data_written.words[0] 1342 = item->kinds.mem_di_write.value >> 32; 1343 frv_interrupt_state.data_written.words[1] 1344 = item->kinds.mem_di_write.value; 1345 break; 1346 case CGEN_MEM_DF_WRITE: 1347 frv_interrupt_state.data_written.length = 2; 1348 frv_interrupt_state.data_written.words[0] 1349 = item->kinds.mem_df_write.value >> 32; 1350 frv_interrupt_state.data_written.words[1] 1351 = item->kinds.mem_df_write.value; 1352 break; 1353 case CGEN_MEM_XI_WRITE: 1354 frv_interrupt_state.data_written.length = 4; 1355 frv_interrupt_state.data_written.words[0] 1356 = item->kinds.mem_xi_write.value[0]; 1357 frv_interrupt_state.data_written.words[1] 1358 = item->kinds.mem_xi_write.value[1]; 1359 frv_interrupt_state.data_written.words[2] 1360 = item->kinds.mem_xi_write.value[2]; 1361 frv_interrupt_state.data_written.words[3] 1362 = item->kinds.mem_xi_write.value[3]; 1363 break; 1364 case CGEN_FN_MEM_QI_WRITE: 1365 frv_interrupt_state.data_written.length = 1; 1366 frv_interrupt_state.data_written.words[0] 1367 = item->kinds.fn_mem_qi_write.value; 1368 break; 1369 case CGEN_FN_MEM_HI_WRITE: 1370 frv_interrupt_state.data_written.length = 1; 1371 frv_interrupt_state.data_written.words[0] 1372 = item->kinds.fn_mem_hi_write.value; 1373 break; 1374 case CGEN_FN_MEM_SI_WRITE: 1375 frv_interrupt_state.data_written.length = 1; 1376 frv_interrupt_state.data_written.words[0] 1377 = item->kinds.fn_mem_si_write.value; 1378 break; 1379 case CGEN_FN_MEM_DI_WRITE: 1380 frv_interrupt_state.data_written.length = 2; 1381 frv_interrupt_state.data_written.words[0] 1382 = item->kinds.fn_mem_di_write.value >> 32; 1383 frv_interrupt_state.data_written.words[1] 1384 = item->kinds.fn_mem_di_write.value; 1385 break; 1386 case CGEN_FN_MEM_DF_WRITE: 1387 frv_interrupt_state.data_written.length = 2; 1388 frv_interrupt_state.data_written.words[0] 1389 = item->kinds.fn_mem_df_write.value >> 32; 1390 frv_interrupt_state.data_written.words[1] 1391 = item->kinds.fn_mem_df_write.value; 1392 break; 1393 case CGEN_FN_MEM_XI_WRITE: 1394 frv_interrupt_state.data_written.length = 4; 1395 frv_interrupt_state.data_written.words[0] 1396 = item->kinds.fn_mem_xi_write.value[0]; 1397 frv_interrupt_state.data_written.words[1] 1398 = item->kinds.fn_mem_xi_write.value[1]; 1399 frv_interrupt_state.data_written.words[2] 1400 = item->kinds.fn_mem_xi_write.value[2]; 1401 frv_interrupt_state.data_written.words[3] 1402 = item->kinds.fn_mem_xi_write.value[3]; 1403 break; 1404 default: 1405 { 1406 SIM_DESC sd = CPU_STATE (current_cpu); 1407 IADDR pc = CPU_PC_GET (current_cpu); 1408 sim_engine_abort (sd, current_cpu, pc, 1409 "unknown write kind during save for interrupt\n"); 1410 } 1411 break; 1412 } 1413 } 1414