| /* This file is part of the program psim. |
| |
| Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au> |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, see <http://www.gnu.org/licenses/>. |
| |
| */ |
| |
| |
| #ifndef _INTERRUPTS_H_ |
| #define _INTERRUPTS_H_ |
| |
| /* Interrupts: |
| |
| The code below handles two different types of interrupts. |
| Synchronous and Asynchronous. |
| |
| Synchronous: |
| |
| Interrupts that must immediately force either an abort or restart |
| of a current instruction are implemented by forcing an instruction |
| restart. (or to put it another way, long jump). In looking at the |
| code it may occure to you that, for some interrupts, they could |
| return instead of restarting the cpu (eg system_call). While true |
| (it once was like that) I've decided to make the behavour of all |
| interrupt routines roughly identical. |
| |
| Because, a cpu's recorded state (ie what is in the cpu structure) |
| is allowed to lag behind the cpu's true current state (eg PC not |
| updated) sycnronous interrupt handers are parameterized with the |
| the cpu being interrupted so that, as part of moddeling the |
| interrupt, the cpu's state can be updated. |
| |
| Asynchronous: |
| |
| Interrupts such as reset or external exception are delivered using |
| more normal (returning) functions. It is assumed that these |
| functions are called out side of the normal processor execution |
| cycle. */ |
| |
| |
| /* Software generated interrupts. |
| |
| The below are generated by software driven events. For instance, |
| an invalid instruction or access (virtual or physical) to an |
| invalid address */ |
| |
| typedef enum { |
| direct_store_storage_interrupt, |
| hash_table_miss_storage_interrupt, |
| protection_violation_storage_interrupt, |
| earwax_violation_storage_interrupt, |
| segment_table_miss_storage_interrupt, |
| earwax_disabled_storage_interrupt, |
| vea_storage_interrupt, |
| } storage_interrupt_reasons; |
| |
| |
| INLINE_INTERRUPTS\ |
| (void) data_storage_interrupt |
| (cpu *processor, |
| unsigned_word cia, |
| unsigned_word ea, |
| storage_interrupt_reasons reason, |
| int is_store); |
| |
| INLINE_INTERRUPTS\ |
| (void) instruction_storage_interrupt |
| (cpu *processor, |
| unsigned_word cia, |
| storage_interrupt_reasons reason); |
| |
| INLINE_INTERRUPTS\ |
| (void) alignment_interrupt |
| (cpu *processor, |
| unsigned_word cia, |
| unsigned_word ra); |
| |
| typedef enum { |
| floating_point_enabled_program_interrupt, |
| illegal_instruction_program_interrupt, |
| privileged_instruction_program_interrupt, |
| trap_program_interrupt, |
| optional_instruction_program_interrupt, /* subset of illegal instruction */ |
| mpc860c0_instruction_program_interrupt, /* fwd br, taken but not predicted, near EO page */ |
| nr_program_interrupt_reasons |
| } program_interrupt_reasons; |
| |
| INLINE_INTERRUPTS\ |
| (void) program_interrupt |
| (cpu *processor, |
| unsigned_word cia, |
| program_interrupt_reasons reason); |
| |
| INLINE_INTERRUPTS\ |
| (void) floating_point_unavailable_interrupt |
| (cpu *processor, |
| unsigned_word cia); |
| |
| INLINE_INTERRUPTS\ |
| (void) system_call_interrupt |
| (cpu *processor, |
| unsigned_word cia); |
| |
| INLINE_INTERRUPTS\ |
| (void) floating_point_assist_interrupt |
| (cpu *processor, |
| unsigned_word cia); |
| |
| INLINE_INTERRUPTS\ |
| (void) machine_check_interrupt |
| (cpu *processor, |
| unsigned_word cia); |
| |
| /* Hardware generated interrupts: |
| |
| These asynchronous hardware generated interrupts may be called at |
| any time. It is the responsibility of this (the interrupts) module |
| to ensure that interrupts are delivered correctly (when possible). |
| The delivery of these interrupts is controlled by the MSR's |
| external interrupt enable bit. When ever the MSR's value is |
| changed, the processor must call the check_masked_interrupts() |
| function in case delivery has been made possible. |
| |
| decrementer_interrupt is `edge' sensitive. Multiple edges arriving |
| before the first edge has been delivered result in only one |
| interrupt. |
| |
| external_interrupt is `level' sensitive. An external interrupt |
| will only be delivered when the external interrupt port is |
| `asserted'. While interrupts are disabled, the external interrupt |
| can be asserted and then de-asserted without an interrupt |
| eventually being delivered. */ |
| |
| enum { |
| external_interrupt_pending = 1, |
| decrementer_interrupt_pending = 2, |
| }; |
| |
| typedef struct _interrupts { |
| event_entry_tag delivery_scheduled; |
| int pending_interrupts; |
| } interrupts; |
| |
| INLINE_INTERRUPTS\ |
| (void) check_masked_interrupts |
| (cpu *processor); |
| |
| INLINE_INTERRUPTS\ |
| (void) decrementer_interrupt |
| (cpu *processor); |
| |
| INLINE_INTERRUPTS\ |
| (void) external_interrupt |
| (cpu *processor, |
| int is_asserted); |
| |
| #endif /* _INTERRUPTS_H_ */ |