1 1.1 christos /* This file is part of the program psim. 2 1.1 christos 3 1.1 christos Copyright 1994, 1995, 1996, 1997, 2003 Andrew Cagney 4 1.1 christos 5 1.1 christos This program is free software; you can redistribute it and/or modify 6 1.1 christos it under the terms of the GNU General Public License as published by 7 1.1.1.2 christos the Free Software Foundation; either version 3 of the License, or 8 1.1 christos (at your option) any later version. 9 1.1 christos 10 1.1 christos This program is distributed in the hope that it will be useful, 11 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 12 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 1.1 christos GNU General Public License for more details. 14 1.1 christos 15 1.1 christos You should have received a copy of the GNU General Public License 16 1.1.1.2 christos along with this program; if not, see <http://www.gnu.org/licenses/>. 17 1.1 christos 18 1.1 christos */ 19 1.1 christos 20 1.1 christos 21 1.1 christos #ifndef _INTERRUPTS_C_ 22 1.1 christos #define _INTERRUPTS_C_ 23 1.1 christos 24 1.1 christos #include <signal.h> 25 1.1 christos 26 1.1 christos #include "cpu.h" 27 1.1 christos #include "idecode.h" 28 1.1 christos #include "os_emul.h" 29 1.1 christos 30 1.1 christos 31 1.1 christos /* Operating environment support code 32 1.1 christos 33 1.1 christos Unlike the VEA, the OEA must fully model the effect an interrupt 34 1.1 christos has on the processors state. 35 1.1 christos 36 1.1 christos Each function below return updated values for registers effected by 37 1.1 christos interrupts */ 38 1.1 christos 39 1.1 christos 40 1.1 christos STATIC_INLINE_INTERRUPTS\ 41 1.1 christos (msreg) 42 1.1 christos interrupt_msr(msreg old_msr, 43 1.1 christos msreg msr_clear, 44 1.1 christos msreg msr_set) 45 1.1 christos { 46 1.1 christos msreg msr_set_to_0 = (msr_branch_trace_enable 47 1.1 christos | msr_data_relocate 48 1.1 christos | msr_external_interrupt_enable 49 1.1 christos | msr_floating_point_exception_mode_0 50 1.1 christos | msr_floating_point_exception_mode_1 51 1.1 christos | msr_floating_point_available 52 1.1 christos | msr_instruction_relocate 53 1.1 christos | msr_power_management_enable 54 1.1 christos | msr_problem_state 55 1.1 christos | msr_recoverable_interrupt 56 1.1 christos | msr_single_step_trace_enable); 57 1.1 christos /* remember, in 32bit mode msr_64bit_mode is zero */ 58 1.1 christos msreg new_msr = ((((old_msr & ~msr_set_to_0) 59 1.1 christos | msr_64bit_mode) 60 1.1 christos & ~msr_clear) 61 1.1 christos | msr_set); 62 1.1 christos return new_msr; 63 1.1 christos } 64 1.1 christos 65 1.1 christos 66 1.1 christos STATIC_INLINE_INTERRUPTS\ 67 1.1 christos (msreg) 68 1.1 christos interrupt_srr1(msreg old_msr, 69 1.1 christos msreg srr1_clear, 70 1.1 christos msreg srr1_set) 71 1.1 christos { 72 1.1 christos spreg srr1_mask = (MASK(0,32) 73 1.1 christos | MASK(37, 41) 74 1.1 christos | MASK(48, 63)); 75 1.1 christos spreg srr1 = (old_msr & srr1_mask & ~srr1_clear) | srr1_set; 76 1.1 christos return srr1; 77 1.1 christos } 78 1.1 christos 79 1.1 christos 80 1.1 christos STATIC_INLINE_INTERRUPTS\ 81 1.1 christos (unsigned_word) 82 1.1 christos interrupt_base_ea(msreg msr) 83 1.1 christos { 84 1.1 christos if (msr & msr_interrupt_prefix) 85 1.1 christos return MASK(0, 43); 86 1.1 christos else 87 1.1 christos return 0; 88 1.1 christos } 89 1.1 christos 90 1.1 christos 91 1.1 christos /* finish off an interrupt for the OEA model, updating all registers 92 1.1 christos and forcing a restart of the processor */ 93 1.1 christos 94 1.1 christos STATIC_INLINE_INTERRUPTS\ 95 1.1 christos (unsigned_word) 96 1.1 christos perform_oea_interrupt(cpu *processor, 97 1.1 christos unsigned_word cia, 98 1.1 christos unsigned_word vector_offset, 99 1.1 christos msreg msr_clear, 100 1.1 christos msreg msr_set, 101 1.1 christos msreg srr1_clear, 102 1.1 christos msreg srr1_set) 103 1.1 christos { 104 1.1 christos msreg old_msr = MSR; 105 1.1 christos msreg new_msr = interrupt_msr(old_msr, msr_clear, msr_set); 106 1.1 christos unsigned_word nia; 107 1.1 christos if (!(old_msr & msr_recoverable_interrupt)) { 108 1.1 christos cpu_error(processor, cia, 109 1.1 christos "double interrupt - MSR[RI] bit clear when attempting to deliver interrupt, cia=0x%lx, msr=0x%lx; srr0=0x%lx(cia), srr1=0x%lx(msr); trap-vector=0x%lx, trap-msr=0x%lx", 110 1.1 christos (unsigned long)cia, 111 1.1 christos (unsigned long)old_msr, 112 1.1 christos (unsigned long)SRR0, 113 1.1 christos (unsigned long)SRR1, 114 1.1 christos (unsigned long)vector_offset, 115 1.1 christos (unsigned long)new_msr); 116 1.1 christos } 117 1.1 christos SRR0 = (spreg)(cia); 118 1.1 christos SRR1 = interrupt_srr1(old_msr, srr1_clear, srr1_set); 119 1.1 christos MSR = new_msr; 120 1.1 christos nia = interrupt_base_ea(new_msr) + vector_offset; 121 1.1 christos cpu_synchronize_context(processor, cia); 122 1.1 christos return nia; 123 1.1 christos } 124 1.1 christos 125 1.1 christos 126 1.1 christos INLINE_INTERRUPTS\ 127 1.1 christos (void) 128 1.1 christos machine_check_interrupt(cpu *processor, 129 1.1 christos unsigned_word cia) 130 1.1 christos { 131 1.1 christos switch (CURRENT_ENVIRONMENT) { 132 1.1 christos 133 1.1 christos case USER_ENVIRONMENT: 134 1.1 christos case VIRTUAL_ENVIRONMENT: 135 1.1 christos cpu_error(processor, cia, "machine-check interrupt"); 136 1.1 christos 137 1.1 christos case OPERATING_ENVIRONMENT: 138 1.1 christos TRACE(trace_interrupts, ("machine-check interrupt - cia=0x%lx\n", 139 1.1 christos (unsigned long)cia)); 140 1.1 christos cia = perform_oea_interrupt(processor, cia, 0x00200, 0, 0, 0, 0); 141 1.1 christos cpu_restart(processor, cia); 142 1.1 christos 143 1.1 christos default: 144 1.1 christos error("internal error - machine_check_interrupt - bad switch"); 145 1.1 christos 146 1.1 christos } 147 1.1 christos } 148 1.1 christos 149 1.1 christos 150 1.1 christos INLINE_INTERRUPTS\ 151 1.1 christos (void) 152 1.1 christos data_storage_interrupt(cpu *processor, 153 1.1 christos unsigned_word cia, 154 1.1 christos unsigned_word ea, 155 1.1 christos storage_interrupt_reasons reason, 156 1.1 christos int is_store) 157 1.1 christos { 158 1.1 christos switch (CURRENT_ENVIRONMENT) { 159 1.1 christos 160 1.1 christos case USER_ENVIRONMENT: 161 1.1 christos case VIRTUAL_ENVIRONMENT: 162 1.1 christos error("internal error - data_storage_interrupt - should not be called in VEA mode"); 163 1.1 christos break; 164 1.1 christos 165 1.1 christos case OPERATING_ENVIRONMENT: 166 1.1 christos { 167 1.1 christos spreg direction = (is_store ? dsisr_store_operation : 0); 168 1.1 christos switch (reason) { 169 1.1 christos case direct_store_storage_interrupt: 170 1.1 christos DSISR = dsisr_direct_store_error_exception | direction; 171 1.1 christos break; 172 1.1 christos case hash_table_miss_storage_interrupt: 173 1.1 christos DSISR = dsisr_hash_table_or_dbat_miss | direction; 174 1.1 christos break; 175 1.1 christos case protection_violation_storage_interrupt: 176 1.1 christos DSISR = dsisr_protection_violation | direction; 177 1.1 christos break; 178 1.1 christos case earwax_violation_storage_interrupt: 179 1.1 christos DSISR = dsisr_earwax_violation | direction; 180 1.1 christos break; 181 1.1 christos case segment_table_miss_storage_interrupt: 182 1.1 christos DSISR = dsisr_segment_table_miss | direction; 183 1.1 christos break; 184 1.1 christos case earwax_disabled_storage_interrupt: 185 1.1 christos DSISR = dsisr_earwax_disabled | direction; 186 1.1 christos break; 187 1.1 christos default: 188 1.1 christos error("internal error - data_storage_interrupt - reason %d not implemented", reason); 189 1.1 christos break; 190 1.1 christos } 191 1.1 christos DAR = (spreg)ea; 192 1.1 christos TRACE(trace_interrupts, ("data storage interrupt - cia=0x%lx DAR=0x%lx DSISR=0x%lx\n", 193 1.1 christos (unsigned long)cia, 194 1.1 christos (unsigned long)DAR, 195 1.1 christos (unsigned long)DSISR)); 196 1.1 christos cia = perform_oea_interrupt(processor, cia, 0x00300, 0, 0, 0, 0); 197 1.1 christos cpu_restart(processor, cia); 198 1.1 christos } 199 1.1 christos 200 1.1 christos default: 201 1.1 christos error("internal error - data_storage_interrupt - bad switch"); 202 1.1 christos 203 1.1 christos } 204 1.1 christos } 205 1.1 christos 206 1.1 christos 207 1.1 christos INLINE_INTERRUPTS\ 208 1.1 christos (void) 209 1.1 christos instruction_storage_interrupt(cpu *processor, 210 1.1 christos unsigned_word cia, 211 1.1 christos storage_interrupt_reasons reason) 212 1.1 christos { 213 1.1 christos switch (CURRENT_ENVIRONMENT) { 214 1.1 christos 215 1.1 christos case USER_ENVIRONMENT: 216 1.1 christos case VIRTUAL_ENVIRONMENT: 217 1.1 christos error("internal error - instruction_storage_interrupt - should not be called in VEA mode"); 218 1.1 christos 219 1.1 christos case OPERATING_ENVIRONMENT: 220 1.1 christos { 221 1.1 christos msreg srr1_set; 222 1.1 christos switch(reason) { 223 1.1 christos case hash_table_miss_storage_interrupt: 224 1.1 christos srr1_set = srr1_hash_table_or_ibat_miss; 225 1.1 christos break; 226 1.1 christos case direct_store_storage_interrupt: 227 1.1 christos srr1_set = srr1_direct_store_error_exception; 228 1.1 christos break; 229 1.1 christos case protection_violation_storage_interrupt: 230 1.1 christos srr1_set = srr1_protection_violation; 231 1.1 christos break; 232 1.1 christos case segment_table_miss_storage_interrupt: 233 1.1 christos srr1_set = srr1_segment_table_miss; 234 1.1 christos break; 235 1.1 christos default: 236 1.1 christos srr1_set = 0; 237 1.1.1.3 christos error("internal error - instruction_storage_interrupt - reason %d not implemented", reason); 238 1.1 christos break; 239 1.1 christos } 240 1.1 christos TRACE(trace_interrupts, ("instruction storage interrupt - cia=0x%lx SRR1|=0x%lx\n", 241 1.1 christos (unsigned long)cia, 242 1.1 christos (unsigned long)srr1_set)); 243 1.1 christos cia = perform_oea_interrupt(processor, cia, 0x00400, 0, 0, 0, srr1_set); 244 1.1 christos cpu_restart(processor, cia); 245 1.1 christos } 246 1.1 christos 247 1.1 christos default: 248 1.1 christos error("internal error - instruction_storage_interrupt - bad switch"); 249 1.1 christos 250 1.1 christos } 251 1.1 christos } 252 1.1 christos 253 1.1 christos 254 1.1 christos 255 1.1 christos INLINE_INTERRUPTS\ 256 1.1 christos (void) 257 1.1 christos alignment_interrupt(cpu *processor, 258 1.1 christos unsigned_word cia, 259 1.1 christos unsigned_word ra) 260 1.1 christos { 261 1.1 christos switch (CURRENT_ENVIRONMENT) { 262 1.1 christos 263 1.1 christos case USER_ENVIRONMENT: 264 1.1 christos case VIRTUAL_ENVIRONMENT: 265 1.1.1.3 christos cpu_error(processor, cia, "alignment interrupt - ra=0x%lx", (unsigned long)ra); 266 1.1 christos 267 1.1 christos case OPERATING_ENVIRONMENT: 268 1.1 christos DAR = (spreg)ra; 269 1.1 christos DSISR = 0; /* FIXME */ 270 1.1 christos TRACE(trace_interrupts, ("alignment interrupt - cia=0x%lx DAR=0x%lx DSISR=0x%lx\n", 271 1.1 christos (unsigned long)cia, 272 1.1 christos (unsigned long)DAR, 273 1.1 christos (unsigned long)DSISR)); 274 1.1 christos cia = perform_oea_interrupt(processor, cia, 0x00600, 0, 0, 0, 0); 275 1.1 christos cpu_restart(processor, cia); 276 1.1 christos 277 1.1 christos default: 278 1.1 christos error("internal error - alignment_interrupt - bad switch"); 279 1.1 christos 280 1.1 christos } 281 1.1 christos } 282 1.1 christos 283 1.1 christos 284 1.1 christos 285 1.1 christos 286 1.1 christos INLINE_INTERRUPTS\ 287 1.1 christos (void) 288 1.1 christos program_interrupt(cpu *processor, 289 1.1 christos unsigned_word cia, 290 1.1 christos program_interrupt_reasons reason) 291 1.1 christos { 292 1.1 christos switch (CURRENT_ENVIRONMENT) { 293 1.1 christos 294 1.1 christos case USER_ENVIRONMENT: 295 1.1 christos case VIRTUAL_ENVIRONMENT: 296 1.1 christos switch (reason) { 297 1.1 christos case floating_point_enabled_program_interrupt: 298 1.1 christos cpu_error(processor, cia, "program interrupt - %s", 299 1.1 christos "floating point enabled"); 300 1.1 christos break; 301 1.1 christos case illegal_instruction_program_interrupt: 302 1.1 christos cpu_error(processor, cia, "program interrupt - %s", 303 1.1 christos "illegal instruction"); 304 1.1 christos break; 305 1.1 christos case privileged_instruction_program_interrupt: 306 1.1 christos cpu_error(processor, cia, "program interrupt - %s", 307 1.1 christos "privileged instruction"); 308 1.1 christos break; 309 1.1 christos case trap_program_interrupt: 310 1.1 christos cpu_error(processor, cia, "program interrupt - %s", 311 1.1 christos "trap"); 312 1.1 christos break; 313 1.1 christos case optional_instruction_program_interrupt: 314 1.1 christos cpu_error(processor, cia, "program interrupt - %s", 315 1.1 christos "illegal instruction (optional instruction not supported)"); 316 1.1 christos break; 317 1.1 christos case mpc860c0_instruction_program_interrupt: 318 1.1 christos cpu_error(processor, cia, "program interrupt - %s", 319 1.1 christos "problematic branch detected, see MPC860 C0 errata"); 320 1.1 christos break; 321 1.1 christos default: 322 1.1 christos error("internal error - program_interrupt - reason %d not implemented", reason); 323 1.1 christos } 324 1.1 christos 325 1.1 christos case OPERATING_ENVIRONMENT: 326 1.1 christos { 327 1.1 christos msreg srr1_set; 328 1.1 christos switch (reason) { 329 1.1 christos case floating_point_enabled_program_interrupt: 330 1.1 christos srr1_set = srr1_floating_point_enabled; 331 1.1 christos break; 332 1.1 christos case optional_instruction_program_interrupt: 333 1.1 christos case illegal_instruction_program_interrupt: 334 1.1 christos srr1_set = srr1_illegal_instruction; 335 1.1 christos break; 336 1.1 christos case privileged_instruction_program_interrupt: 337 1.1 christos srr1_set = srr1_priviliged_instruction; 338 1.1 christos break; 339 1.1 christos case trap_program_interrupt: 340 1.1 christos srr1_set = srr1_trap; 341 1.1 christos break; 342 1.1 christos case mpc860c0_instruction_program_interrupt: 343 1.1 christos srr1_set = 0; 344 1.1 christos cpu_error(processor, cia, "program interrupt - %s", 345 1.1 christos "problematic branch detected, see MPC860 C0 errata"); 346 1.1 christos break; 347 1.1 christos default: 348 1.1 christos srr1_set = 0; 349 1.1 christos error("internal error - program_interrupt - reason %d not implemented", reason); 350 1.1 christos break; 351 1.1 christos } 352 1.1 christos TRACE(trace_interrupts, ("program interrupt - cia=0x%lx SRR1|=0x%lx\n", 353 1.1 christos (unsigned long)cia, 354 1.1 christos (unsigned long)srr1_set)); 355 1.1 christos cia = perform_oea_interrupt(processor, cia, 0x00700, 0, 0, 0, srr1_set); 356 1.1 christos cpu_restart(processor, cia); 357 1.1 christos } 358 1.1 christos 359 1.1 christos default: 360 1.1 christos error("internal error - program_interrupt - bad switch"); 361 1.1 christos 362 1.1 christos } 363 1.1 christos } 364 1.1 christos 365 1.1 christos 366 1.1 christos INLINE_INTERRUPTS\ 367 1.1 christos (void) 368 1.1 christos floating_point_unavailable_interrupt(cpu *processor, 369 1.1 christos unsigned_word cia) 370 1.1 christos { 371 1.1 christos switch (CURRENT_ENVIRONMENT) { 372 1.1 christos 373 1.1 christos case USER_ENVIRONMENT: 374 1.1 christos case VIRTUAL_ENVIRONMENT: 375 1.1 christos cpu_error(processor, cia, "floating-point unavailable interrupt"); 376 1.1 christos 377 1.1 christos case OPERATING_ENVIRONMENT: 378 1.1 christos TRACE(trace_interrupts, ("floating-point unavailable interrupt - cia=0x%lx\n", 379 1.1 christos (unsigned long)cia)); 380 1.1 christos cia = perform_oea_interrupt(processor, cia, 0x00800, 0, 0, 0, 0); 381 1.1 christos cpu_restart(processor, cia); 382 1.1 christos 383 1.1 christos default: 384 1.1 christos error("internal error - floating_point_unavailable_interrupt - bad switch"); 385 1.1 christos 386 1.1 christos } 387 1.1 christos } 388 1.1 christos 389 1.1 christos 390 1.1 christos INLINE_INTERRUPTS\ 391 1.1 christos (void) 392 1.1 christos system_call_interrupt(cpu *processor, 393 1.1 christos unsigned_word cia) 394 1.1 christos { 395 1.1 christos TRACE(trace_interrupts, ("system-call interrupt - cia=0x%lx\n", (unsigned long)cia)); 396 1.1 christos 397 1.1 christos switch (CURRENT_ENVIRONMENT) { 398 1.1 christos 399 1.1 christos case USER_ENVIRONMENT: 400 1.1 christos case VIRTUAL_ENVIRONMENT: 401 1.1 christos os_emul_system_call(processor, cia); 402 1.1 christos cpu_restart(processor, cia+4); 403 1.1 christos 404 1.1 christos case OPERATING_ENVIRONMENT: 405 1.1 christos cia = perform_oea_interrupt(processor, cia+4, 0x00c00, 0, 0, 0, 0); 406 1.1 christos cpu_restart(processor, cia); 407 1.1 christos 408 1.1 christos default: 409 1.1 christos error("internal error - system_call_interrupt - bad switch"); 410 1.1 christos 411 1.1 christos } 412 1.1 christos } 413 1.1 christos 414 1.1 christos INLINE_INTERRUPTS\ 415 1.1 christos (void) 416 1.1 christos floating_point_assist_interrupt(cpu *processor, 417 1.1 christos unsigned_word cia) 418 1.1 christos { 419 1.1 christos switch (CURRENT_ENVIRONMENT) { 420 1.1 christos 421 1.1 christos case USER_ENVIRONMENT: 422 1.1 christos case VIRTUAL_ENVIRONMENT: 423 1.1 christos cpu_error(processor, cia, "floating-point assist interrupt"); 424 1.1 christos 425 1.1 christos case OPERATING_ENVIRONMENT: 426 1.1 christos TRACE(trace_interrupts, ("floating-point assist interrupt - cia=0x%lx\n", (unsigned long)cia)); 427 1.1 christos cia = perform_oea_interrupt(processor, cia, 0x00e00, 0, 0, 0, 0); 428 1.1 christos cpu_restart(processor, cia); 429 1.1 christos 430 1.1 christos default: 431 1.1 christos error("internal error - floating_point_assist_interrupt - bad switch"); 432 1.1 christos 433 1.1 christos } 434 1.1 christos } 435 1.1 christos 436 1.1 christos 437 1.1 christos 438 1.1 christos /* handle an externally generated event or an interrupt that has just 439 1.1 christos been enabled through changes to the MSR. */ 440 1.1 christos 441 1.1 christos STATIC_INLINE_INTERRUPTS\ 442 1.1 christos (void) 443 1.1 christos deliver_hardware_interrupt(void *data) 444 1.1 christos { 445 1.1 christos cpu *processor = (cpu*)data; 446 1.1 christos interrupts *ints = cpu_interrupts(processor); 447 1.1 christos ints->delivery_scheduled = NULL; 448 1.1 christos if ((cpu_registers(processor)->msr & (msr_floating_point_exception_mode_0 449 1.1 christos | msr_floating_point_exception_mode_1)) 450 1.1 christos && cpu_registers(processor)->fpscr & fpscr_fex) { 451 1.1 christos msreg srr1_set = srr1_floating_point_enabled | srr1_subsequent_instruction; 452 1.1 christos unsigned_word cia = cpu_get_program_counter(processor); 453 1.1 christos unsigned_word nia = perform_oea_interrupt(processor, 454 1.1 christos cia, 0x00700, 0, 0, 0, srr1_set); 455 1.1 christos cpu_set_program_counter(processor, nia); 456 1.1 christos } 457 1.1 christos else if (cpu_registers(processor)->msr & msr_external_interrupt_enable) { 458 1.1 christos /* external interrupts have a high priority and remain pending */ 459 1.1 christos if (ints->pending_interrupts & external_interrupt_pending) { 460 1.1 christos unsigned_word cia = cpu_get_program_counter(processor); 461 1.1 christos unsigned_word nia = perform_oea_interrupt(processor, 462 1.1 christos cia, 0x00500, 0, 0, 0, 0); 463 1.1 christos TRACE(trace_interrupts, ("external interrupt - cia=0x%lx\n", (unsigned long)cia)); 464 1.1 christos cpu_set_program_counter(processor, nia); 465 1.1 christos } 466 1.1 christos /* decrementer interrupts have a lower priority and are once only */ 467 1.1 christos else if (ints->pending_interrupts & decrementer_interrupt_pending) { 468 1.1 christos unsigned_word cia = cpu_get_program_counter(processor); 469 1.1 christos unsigned_word nia = perform_oea_interrupt(processor, 470 1.1 christos cia, 0x00900, 0, 0, 0, 0); 471 1.1 christos TRACE(trace_interrupts, ("decrementer interrupt - cia 0x%lx, time %ld\n", 472 1.1 christos (unsigned long)cia, 473 1.1 christos (unsigned long)event_queue_time(psim_event_queue(cpu_system(processor))) 474 1.1 christos )); 475 1.1 christos cpu_set_program_counter(processor, nia); 476 1.1 christos ints->pending_interrupts &= ~decrementer_interrupt_pending; 477 1.1 christos } 478 1.1 christos } 479 1.1 christos } 480 1.1 christos 481 1.1 christos STATIC_INLINE_INTERRUPTS\ 482 1.1 christos (void) 483 1.1 christos schedule_hardware_interrupt_delivery(cpu *processor) 484 1.1 christos { 485 1.1 christos interrupts *ints = cpu_interrupts(processor); 486 1.1 christos if (ints->delivery_scheduled == NULL) { 487 1.1 christos ints->delivery_scheduled = 488 1.1 christos event_queue_schedule(psim_event_queue(cpu_system(processor)), 489 1.1 christos 0, deliver_hardware_interrupt, processor); 490 1.1 christos } 491 1.1 christos } 492 1.1 christos 493 1.1 christos 494 1.1 christos INLINE_INTERRUPTS\ 495 1.1 christos (void) 496 1.1 christos check_masked_interrupts(cpu *processor) 497 1.1 christos { 498 1.1 christos if (((cpu_registers(processor)->msr & (msr_floating_point_exception_mode_0 499 1.1 christos | msr_floating_point_exception_mode_1)) 500 1.1 christos && cpu_registers(processor)->fpscr & fpscr_fex) 501 1.1 christos || ((cpu_registers(processor)->msr & msr_external_interrupt_enable) 502 1.1 christos && (cpu_interrupts(processor)->pending_interrupts))) 503 1.1 christos schedule_hardware_interrupt_delivery(processor); 504 1.1 christos } 505 1.1 christos 506 1.1 christos INLINE_INTERRUPTS\ 507 1.1 christos (void) 508 1.1 christos decrementer_interrupt(cpu *processor) 509 1.1 christos { 510 1.1 christos interrupts *ints = cpu_interrupts(processor); 511 1.1 christos ints->pending_interrupts |= decrementer_interrupt_pending; 512 1.1 christos if (cpu_registers(processor)->msr & msr_external_interrupt_enable) { 513 1.1 christos schedule_hardware_interrupt_delivery(processor); 514 1.1 christos } 515 1.1 christos } 516 1.1 christos 517 1.1 christos INLINE_INTERRUPTS\ 518 1.1 christos (void) 519 1.1 christos external_interrupt(cpu *processor, 520 1.1 christos int is_asserted) 521 1.1 christos { 522 1.1 christos interrupts *ints = cpu_interrupts(processor); 523 1.1 christos if (is_asserted) { 524 1.1 christos if (!(ints->pending_interrupts & external_interrupt_pending)) { 525 1.1 christos ints->pending_interrupts |= external_interrupt_pending; 526 1.1 christos if (cpu_registers(processor)->msr & msr_external_interrupt_enable) 527 1.1 christos schedule_hardware_interrupt_delivery(processor); 528 1.1 christos } 529 1.1 christos else { 530 1.1 christos /* check that we haven't missed out on a chance to deliver an 531 1.1 christos interrupt */ 532 1.1 christos ASSERT(!(cpu_registers(processor)->msr & msr_external_interrupt_enable)); 533 1.1 christos } 534 1.1 christos } 535 1.1 christos else { 536 1.1 christos ints->pending_interrupts &= ~external_interrupt_pending; 537 1.1 christos } 538 1.1 christos } 539 1.1 christos 540 1.1 christos #endif /* _INTERRUPTS_C_ */ 541