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