1 /* This file is part of the program psim.
3 Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #ifndef _INTERRUPTS_C_
23 #define _INTERRUPTS_C_
32 /* Operating environment support code
34 Unlike the VEA, the OEA must fully model the effect an interrupt
35 has on the processors state.
37 Each function below return updated values for registers effected by
41 msreg STATIC_INLINE_INTERRUPTS
42 interrupt_msr(msreg old_msr
,
46 msreg msr_set_to_0
= (msr_branch_trace_enable
48 | msr_external_interrupt_enable
49 | msr_floating_point_exception_mode_0
50 | msr_floating_point_exception_mode_1
51 | msr_floating_point_available
52 | msr_instruction_relocate
53 | msr_power_management_enable
55 | msr_recoverable_interrupt
56 | msr_single_step_trace_enable
);
57 /* remember, in 32bit mode msr_64bit_mode is zero */
58 msreg new_msr
= ((((old_msr
& ~msr_set_to_0
)
66 msreg STATIC_INLINE_INTERRUPTS
67 interrupt_srr1(msreg old_msr
,
71 spreg srr1_mask
= (MASK(0,32)
74 spreg srr1
= (old_msr
& srr1_mask
& ~srr1_clear
) | srr1_set
;
79 unsigned_word STATIC_INLINE_INTERRUPTS
80 interrupt_base_ea(msreg msr
)
82 if (msr
& msr_interrupt_prefix
)
89 /* finish off an interrupt for the OEA model, updating all registers
90 and forcing a restart of the processor */
92 unsigned_word STATIC_INLINE_INTERRUPTS
93 perform_oea_interrupt(cpu
*processor
,
95 unsigned_word vector_offset
,
102 msreg new_msr
= interrupt_msr(old_msr
, msr_clear
, msr_set
);
104 if (!(old_msr
& msr_recoverable_interrupt
))
105 error("perform_oea_interrupt() recoverable_interrupt bit clear, cia=0x%x, msr=0x%x\n",
108 SRR1
= interrupt_srr1(old_msr
, srr1_clear
, srr1_set
);
110 nia
= interrupt_base_ea(new_msr
) + vector_offset
;
111 cpu_synchronize_context(processor
);
116 void INLINE_INTERRUPTS
117 machine_check_interrupt(cpu
*processor
,
120 switch (CURRENT_ENVIRONMENT
) {
122 case USER_ENVIRONMENT
:
123 case VIRTUAL_ENVIRONMENT
:
124 error("%s - cia=0x%x\n",
125 "machine_check_interrupt", cia
);
127 case OPERATING_ENVIRONMENT
:
128 cia
= perform_oea_interrupt(processor
, cia
, 0x00200, 0, 0, 0, 0);
129 cpu_restart(processor
, cia
);
132 error("machine_check_interrupt() - internal error\n");
138 void INLINE_INTERRUPTS
139 data_storage_interrupt(cpu
*processor
,
142 storage_interrupt_reasons reason
,
145 switch (CURRENT_ENVIRONMENT
) {
147 case USER_ENVIRONMENT
:
148 case VIRTUAL_ENVIRONMENT
:
149 error("data_storage_interrupt() should not be called in VEA mode\n");
151 case OPERATING_ENVIRONMENT
:
153 spreg direction
= (is_store
? dsisr_store_operation
: 0);
155 case direct_store_storage_interrupt
:
156 DSISR
= dsisr_direct_store_error_exception
| direction
;
158 case hash_table_miss_storage_interrupt
:
159 DSISR
= dsisr_hash_table_or_dbat_miss
| direction
;
161 case protection_violation_storage_interrupt
:
162 DSISR
= dsisr_protection_violation
| direction
;
164 case earwax_violation_storage_interrupt
:
165 DSISR
= dsisr_earwax_violation
| direction
;
167 case segment_table_miss_storage_interrupt
:
168 DSISR
= dsisr_segment_table_miss
| direction
;
170 case earwax_disabled_storage_interrupt
:
171 DSISR
= dsisr_earwax_disabled
| direction
;
174 error("data_storage_interrupt: unknown reason %d\n", reason
);
178 cia
= perform_oea_interrupt(processor
, cia
, 0x00300, 0, 0, 0, 0);
179 cpu_restart(processor
, cia
);
183 error("data_storage_interrupt() - internal error\n");
189 void INLINE_INTERRUPTS
190 instruction_storage_interrupt(cpu
*processor
,
192 storage_interrupt_reasons reason
)
194 switch (CURRENT_ENVIRONMENT
) {
196 case USER_ENVIRONMENT
:
197 case VIRTUAL_ENVIRONMENT
:
198 error("instruction_storage_interrupt - cia=0x%x - not implemented\n",
201 case OPERATING_ENVIRONMENT
:
205 case hash_table_miss_storage_interrupt
:
206 srr1_set
= srr1_hash_table_or_ibat_miss
;
208 case direct_store_storage_interrupt
:
209 srr1_set
= srr1_direct_store_error_exception
;
211 case protection_violation_storage_interrupt
:
212 srr1_set
= srr1_protection_violation
;
214 case segment_table_miss_storage_interrupt
:
215 srr1_set
= srr1_segment_table_miss
;
219 error("instruction_storage_interrupt: unknown reason %d\n", reason
);
222 cia
= perform_oea_interrupt(processor
, cia
, 0x00400, 0, 0, 0, srr1_set
);
223 cpu_restart(processor
, cia
);
227 error("instruction_storage_interrupt() - internal error\n");
234 void INLINE_INTERRUPTS
235 alignment_interrupt(cpu
*processor
,
239 switch (CURRENT_ENVIRONMENT
) {
241 case USER_ENVIRONMENT
:
242 case VIRTUAL_ENVIRONMENT
:
243 error("%s - cia=0x%x, ra=0x%x\n",
244 "alignment_interrupt", cia
, ra
);
246 case OPERATING_ENVIRONMENT
:
248 DSISR
= 0; /* FIXME */
249 cia
= perform_oea_interrupt(processor
, cia
, 0x00600, 0, 0, 0, 0);
250 cpu_restart(processor
, cia
);
253 error("alignment_interrupt() - internal error\n");
261 void INLINE_INTERRUPTS
262 program_interrupt(cpu
*processor
,
264 program_interrupt_reasons reason
)
266 switch (CURRENT_ENVIRONMENT
) {
268 case USER_ENVIRONMENT
:
269 case VIRTUAL_ENVIRONMENT
:
272 error("%s - cia=0x%x, reason=%d - not implemented\n",
273 "program_interrupt", cia
, reason
);
276 case OPERATING_ENVIRONMENT
:
280 case illegal_instruction_program_interrupt
:
281 srr1_set
= srr1_illegal_instruction
;
283 case privileged_instruction_program_interrupt
:
284 srr1_set
= srr1_priviliged_instruction
;
286 case trap_program_interrupt
:
287 srr1_set
= srr1_trap
;
291 error("program_interrupt - cia=0x%x, reason=%d(%s) - not implemented\n",
294 cia
= perform_oea_interrupt(processor
, cia
, 0x00700, 0, 0, 0, srr1_set
);
295 cpu_restart(processor
, cia
);
299 error("program_interrupt() - internal error\n");
305 void INLINE_INTERRUPTS
306 floating_point_unavailable_interrupt(cpu
*processor
,
309 switch (CURRENT_ENVIRONMENT
) {
311 case USER_ENVIRONMENT
:
312 case VIRTUAL_ENVIRONMENT
:
313 error("%s - cia=0x%x - not implemented\n",
314 "floating_point_unavailable_interrupt", cia
);
316 case OPERATING_ENVIRONMENT
:
317 cia
= perform_oea_interrupt(processor
, cia
, 0x00800, 0, 0, 0, 0);
318 cpu_restart(processor
, cia
);
321 error("floating_point_unavailable_interrupt() - internal error\n");
327 void INLINE_INTERRUPTS
328 system_call_interrupt(cpu
*processor
,
331 switch (CURRENT_ENVIRONMENT
) {
333 case USER_ENVIRONMENT
:
334 case VIRTUAL_ENVIRONMENT
:
335 os_emul_system_call(processor
, cia
);
336 cpu_restart(processor
, cia
+4);
338 case OPERATING_ENVIRONMENT
:
339 cia
= perform_oea_interrupt(processor
, cia
+4, 0x00c00, 0, 0, 0, 0);
340 cpu_restart(processor
, cia
);
343 error("system_call_interrupt() - internal error\n");
348 void INLINE_INTERRUPTS
349 trace_interrupt(cpu
*processor
,
352 void INLINE_INTERRUPTS
353 floating_point_assist_interrupt(cpu
*processor
,
356 switch (CURRENT_ENVIRONMENT
) {
358 case USER_ENVIRONMENT
:
359 case VIRTUAL_ENVIRONMENT
:
360 error("%s - cia=0x%x - not implemented\n",
361 "floating_point_assist_interrupt", cia
);
363 case OPERATING_ENVIRONMENT
:
364 cia
= perform_oea_interrupt(processor
, cia
, 0x00e00, 0, 0, 0, 0);
365 cpu_restart(processor
, cia
);
368 error("floating_point_assist_interrupt() - internal error\n");
375 /* handle an externally generated event */
377 int INLINE_INTERRUPTS
378 decrementer_interrupt(cpu
*processor
)
380 if (cpu_registers(processor
)->msr
& msr_external_interrupt_enable
) {
381 unsigned_word cia
= cpu_get_program_counter(processor
);
382 unsigned_word nia
= perform_oea_interrupt(processor
,
383 cia
, 0x00900, 0, 0, 0, 0);
384 cpu_set_program_counter(processor
, nia
);
392 int INLINE_INTERRUPTS
393 external_interrupt(cpu
*processor
)
395 if (cpu_registers(processor
)->msr
& msr_external_interrupt_enable
) {
396 unsigned_word cia
= cpu_get_program_counter(processor
);
397 unsigned_word nia
= perform_oea_interrupt(processor
,
398 cia
, 0x00500, 0, 0, 0, 0);
399 cpu_set_program_counter(processor
, nia
);
403 return 0; /* not delivered */
408 #endif /* _INTERRUPTS_C_ */