* Fixed testcase. 1,$ s/ITOP 412/ITOP 421/
[deliverable/binutils-gdb.git] / sim / ppc / interrupts.c
CommitLineData
a983c8f0
MM
1/* This file is part of the program psim.
2
3 Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
4
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.
9
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.
14
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.
18
19 */
20
21
22#ifndef _INTERRUPTS_C_
23#define _INTERRUPTS_C_
24
a983c8f0
MM
25#include <signal.h>
26
27#include "cpu.h"
28#include "idecode.h"
29#include "os_emul.h"
30
31
32/* Operating environment support code
33
34 Unlike the VEA, the OEA must fully model the effect an interrupt
35 has on the processors state.
36
37 Each function below return updated values for registers effected by
38 interrupts */
39
40
93fac324 41msreg STATIC_INLINE_INTERRUPTS
a983c8f0
MM
42interrupt_msr(msreg old_msr,
43 msreg msr_clear,
44 msreg msr_set)
45{
46 msreg msr_set_to_0 = (msr_branch_trace_enable
47 | msr_data_relocate
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
54 | msr_problem_state
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)
59 | msr_64bit_mode)
60 & ~msr_clear)
61 | msr_set);
62 return new_msr;
63}
64
65
93fac324 66msreg STATIC_INLINE_INTERRUPTS
a983c8f0
MM
67interrupt_srr1(msreg old_msr,
68 msreg srr1_clear,
69 msreg srr1_set)
70{
71 spreg srr1_mask = (MASK(0,32)
72 | MASK(37, 41)
73 | MASK(48, 63));
74 spreg srr1 = (old_msr & srr1_mask & ~srr1_clear) | srr1_set;
75 return srr1;
76}
77
78
93fac324 79unsigned_word STATIC_INLINE_INTERRUPTS
a983c8f0
MM
80interrupt_base_ea(msreg msr)
81{
82 if (msr & msr_interrupt_prefix)
83 return MASK(0, 43);
84 else
85 return 0;
86}
87
88
89/* finish off an interrupt for the OEA model, updating all registers
90 and forcing a restart of the processor */
91
93fac324 92unsigned_word STATIC_INLINE_INTERRUPTS
a983c8f0
MM
93perform_oea_interrupt(cpu *processor,
94 unsigned_word cia,
95 unsigned_word vector_offset,
96 msreg msr_clear,
97 msreg msr_set,
98 msreg srr1_clear,
99 msreg srr1_set)
100{
101 msreg old_msr = MSR;
102 msreg new_msr = interrupt_msr(old_msr, msr_clear, msr_set);
103 unsigned_word nia;
104 if (!(old_msr & msr_recoverable_interrupt))
105 error("perform_oea_interrupt() recoverable_interrupt bit clear, cia=0x%x, msr=0x%x\n",
106 cia, old_msr);
107 SRR0 = (spreg)(cia);
108 SRR1 = interrupt_srr1(old_msr, srr1_clear, srr1_set);
109 MSR = new_msr;
110 nia = interrupt_base_ea(new_msr) + vector_offset;
111 cpu_synchronize_context(processor);
112 return nia;
113}
114
115
93fac324
MM
116void INLINE_INTERRUPTS
117machine_check_interrupt(cpu *processor,
118 unsigned_word cia)
a983c8f0
MM
119{
120 switch (CURRENT_ENVIRONMENT) {
121
122 case USER_ENVIRONMENT:
123 case VIRTUAL_ENVIRONMENT:
124 error("%s - cia=0x%x\n",
125 "machine_check_interrupt", cia);
126
127 case OPERATING_ENVIRONMENT:
128 cia = perform_oea_interrupt(processor, cia, 0x00200, 0, 0, 0, 0);
129 cpu_restart(processor, cia);
130
131 default:
132 error("machine_check_interrupt() - internal error\n");
133
134 }
135}
136
137
93fac324 138void INLINE_INTERRUPTS
a983c8f0
MM
139data_storage_interrupt(cpu *processor,
140 unsigned_word cia,
141 unsigned_word ea,
142 storage_interrupt_reasons reason,
143 int is_store)
144{
145 switch (CURRENT_ENVIRONMENT) {
146
147 case USER_ENVIRONMENT:
148 case VIRTUAL_ENVIRONMENT:
149 error("data_storage_interrupt() should not be called in VEA mode\n");
150
151 case OPERATING_ENVIRONMENT:
152 {
153 spreg direction = (is_store ? dsisr_store_operation : 0);
154 switch (reason) {
155 case direct_store_storage_interrupt:
156 DSISR = dsisr_direct_store_error_exception | direction;
157 break;
158 case hash_table_miss_storage_interrupt:
159 DSISR = dsisr_hash_table_or_dbat_miss | direction;
160 break;
161 case protection_violation_storage_interrupt:
162 DSISR = dsisr_protection_violation | direction;
163 break;
164 case earwax_violation_storage_interrupt:
165 DSISR = dsisr_earwax_violation | direction;
166 break;
167 case segment_table_miss_storage_interrupt:
168 DSISR = dsisr_segment_table_miss | direction;
169 break;
170 case earwax_disabled_storage_interrupt:
171 DSISR = dsisr_earwax_disabled | direction;
172 break;
173 default:
174 error("data_storage_interrupt: unknown reason %d\n", reason);
175 break;
176 }
177 DAR = (spreg)ea;
178 cia = perform_oea_interrupt(processor, cia, 0x00300, 0, 0, 0, 0);
179 cpu_restart(processor, cia);
180 }
181
182 default:
183 error("data_storage_interrupt() - internal error\n");
184
185 }
186}
187
188
93fac324 189void INLINE_INTERRUPTS
a983c8f0
MM
190instruction_storage_interrupt(cpu *processor,
191 unsigned_word cia,
192 storage_interrupt_reasons reason)
193{
194 switch (CURRENT_ENVIRONMENT) {
195
196 case USER_ENVIRONMENT:
197 case VIRTUAL_ENVIRONMENT:
198 error("instruction_storage_interrupt - cia=0x%x - not implemented\n",
199 cia);
200
201 case OPERATING_ENVIRONMENT:
202 {
a983c8f0
MM
203 msreg srr1_set;
204 switch(reason) {
205 case hash_table_miss_storage_interrupt:
206 srr1_set = srr1_hash_table_or_ibat_miss;
207 break;
208 case direct_store_storage_interrupt:
209 srr1_set = srr1_direct_store_error_exception;
210 break;
211 case protection_violation_storage_interrupt:
212 srr1_set = srr1_protection_violation;
213 break;
214 case segment_table_miss_storage_interrupt:
215 srr1_set = srr1_segment_table_miss;
216 break;
217 default:
218 srr1_set = 0;
219 error("instruction_storage_interrupt: unknown reason %d\n", reason);
220 break;
221 }
222 cia = perform_oea_interrupt(processor, cia, 0x00400, 0, 0, 0, srr1_set);
223 cpu_restart(processor, cia);
224 }
225
226 default:
227 error("instruction_storage_interrupt() - internal error\n");
228
229 }
230}
231
232
233
93fac324
MM
234void INLINE_INTERRUPTS
235alignment_interrupt(cpu *processor,
236 unsigned_word cia,
237 unsigned_word ra)
a983c8f0
MM
238{
239 switch (CURRENT_ENVIRONMENT) {
240
241 case USER_ENVIRONMENT:
242 case VIRTUAL_ENVIRONMENT:
243 error("%s - cia=0x%x, ra=0x%x\n",
244 "alignment_interrupt", cia, ra);
245
246 case OPERATING_ENVIRONMENT:
247 DAR = (spreg)ra;
248 DSISR = 0; /* FIXME */
249 cia = perform_oea_interrupt(processor, cia, 0x00600, 0, 0, 0, 0);
250 cpu_restart(processor, cia);
251
252 default:
253 error("alignment_interrupt() - internal error\n");
254
255 }
256}
257
258
259
260
93fac324 261void INLINE_INTERRUPTS
a983c8f0
MM
262program_interrupt(cpu *processor,
263 unsigned_word cia,
264 program_interrupt_reasons reason)
265{
266 switch (CURRENT_ENVIRONMENT) {
267
268 case USER_ENVIRONMENT:
269 case VIRTUAL_ENVIRONMENT:
270 switch (reason) {
271 default:
272 error("%s - cia=0x%x, reason=%d - not implemented\n",
273 "program_interrupt", cia, reason);
274 }
275
276 case OPERATING_ENVIRONMENT:
277 {
278 msreg srr1_set;
279 switch (reason) {
280 case illegal_instruction_program_interrupt:
281 srr1_set = srr1_illegal_instruction;
282 break;
283 case privileged_instruction_program_interrupt:
284 srr1_set = srr1_priviliged_instruction;
285 break;
286 case trap_program_interrupt:
287 srr1_set = srr1_trap;
288 break;
289 default:
290 srr1_set = 0;
291 error("program_interrupt - cia=0x%x, reason=%d(%s) - not implemented\n",
292 cia, reason);
293 }
294 cia = perform_oea_interrupt(processor, cia, 0x00700, 0, 0, 0, srr1_set);
295 cpu_restart(processor, cia);
296 }
297
298 default:
299 error("program_interrupt() - internal error\n");
300
301 }
302}
303
304
93fac324 305void INLINE_INTERRUPTS
a983c8f0
MM
306floating_point_unavailable_interrupt(cpu *processor,
307 unsigned_word cia)
308{
309 switch (CURRENT_ENVIRONMENT) {
310
311 case USER_ENVIRONMENT:
312 case VIRTUAL_ENVIRONMENT:
313 error("%s - cia=0x%x - not implemented\n",
314 "floating_point_unavailable_interrupt", cia);
315
316 case OPERATING_ENVIRONMENT:
317 cia = perform_oea_interrupt(processor, cia, 0x00800, 0, 0, 0, 0);
318 cpu_restart(processor, cia);
319
320 default:
321 error("floating_point_unavailable_interrupt() - internal error\n");
322
323 }
324}
325
326
93fac324 327void INLINE_INTERRUPTS
a983c8f0
MM
328system_call_interrupt(cpu *processor,
329 unsigned_word cia)
330{
331 switch (CURRENT_ENVIRONMENT) {
332
333 case USER_ENVIRONMENT:
334 case VIRTUAL_ENVIRONMENT:
93fac324 335 os_emul_system_call(processor, cia);
a983c8f0
MM
336 cpu_restart(processor, cia+4);
337
338 case OPERATING_ENVIRONMENT:
339 cia = perform_oea_interrupt(processor, cia+4, 0x00c00, 0, 0, 0, 0);
340 cpu_restart(processor, cia);
341
342 default:
343 error("system_call_interrupt() - internal error\n");
344
345 }
346}
347
93fac324 348void INLINE_INTERRUPTS
a983c8f0
MM
349trace_interrupt(cpu *processor,
350 unsigned_word cia);
351
93fac324 352void INLINE_INTERRUPTS
a983c8f0
MM
353floating_point_assist_interrupt(cpu *processor,
354 unsigned_word cia)
355{
356 switch (CURRENT_ENVIRONMENT) {
357
358 case USER_ENVIRONMENT:
359 case VIRTUAL_ENVIRONMENT:
360 error("%s - cia=0x%x - not implemented\n",
361 "floating_point_assist_interrupt", cia);
362
363 case OPERATING_ENVIRONMENT:
364 cia = perform_oea_interrupt(processor, cia, 0x00e00, 0, 0, 0, 0);
365 cpu_restart(processor, cia);
366
367 default:
368 error("floating_point_assist_interrupt() - internal error\n");
369
370 }
371}
372
373
374
375/* handle an externally generated event */
376
93fac324 377int INLINE_INTERRUPTS
a983c8f0
MM
378decrementer_interrupt(cpu *processor)
379{
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);
385 return 1;
386 }
387 else {
388 return 0;
389 }
390}
391
93fac324 392int INLINE_INTERRUPTS
a983c8f0
MM
393external_interrupt(cpu *processor)
394{
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);
400 return 1;
401 }
402 else {
403 return 0; /* not delivered */
404 }
405}
406
407
408#endif /* _INTERRUPTS_C_ */
This page took 0.111957 seconds and 4 git commands to generate.