1 /* This file is part of the program GDB, the GNU debugger.
3 Copyright (C) 1998, 2007 Free Software Foundation, Inc.
4 Contributed by Cygnus Solutions.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 mn103cpu - mn10300 cpu virtual device
35 Implements the external mn10300 functionality. This includes the
36 delivery of interrupts generated from other devices and the
37 handling of device specific registers.
43 reg = <address> <size>
45 Specify the address of the mn10300's control register block. This
46 block contains the Interrupt Vector Registers.
48 The reg property value `0x20000000 0x42' locates the register block
49 at the address specified in the mn10300 user guide.
62 Deliver a non-maskable interrupt to the processor.
67 Maskable interrupt level port port. The interrupt controller
68 notifies the processor of any change in the level of pending
69 requested interrupts via this port.
74 Output signal indicating that the processor is delivering a level
75 interrupt. The value passed with the event specifies the level of
76 the interrupt being delivered.
82 When delivering an interrupt, this code assumes that there is only
83 one processor (number 0).
85 This code does not attempt to be efficient at handling pending
86 interrupts. It simply schedules the interrupt delivery handler
87 every instruction cycle until all pending interrupts go away. An
88 alternative implementation might modify instructions that change
89 the PSW and have them check to see if the change makes an interrupt
95 /* The interrupt vectors */
97 enum { NR_VECTORS
= 7, };
100 /* The interrupt controller register address blocks */
102 struct mn103cpu_block
{
109 struct mn103cpu_block block
;
110 struct hw_event
*pending_handler
;
114 /* the visible registers */
115 unsigned16 interrupt_vector
[NR_VECTORS
];
116 unsigned16 internal_memory_control
;
122 /* input port ID's */
131 /* output port ID's */
137 static const struct hw_port_descriptor mn103cpu_ports
[] = {
139 /* interrupt inputs */
140 { "reset", RESET_PORT
, 0, input_port
, },
141 { "nmi", NMI_PORT
, 0, input_port
, },
142 { "level", LEVEL_PORT
, 0, input_port
, },
144 /* interrupt ack (latch) output from cpu */
145 { "ack", ACK_PORT
, 0, output_port
, },
151 /* Finish off the partially created hw device. Attach our local
152 callbacks. Wire up our port names etc */
154 static hw_io_read_buffer_method mn103cpu_io_read_buffer
;
155 static hw_io_write_buffer_method mn103cpu_io_write_buffer
;
156 static hw_port_event_method mn103cpu_port_event
;
159 attach_mn103cpu_regs (struct hw
*me
,
160 struct mn103cpu
*controller
)
162 unsigned_word attach_address
;
164 unsigned attach_size
;
165 reg_property_spec reg
;
166 if (hw_find_property (me
, "reg") == NULL
)
167 hw_abort (me
, "Missing \"reg\" property");
168 if (!hw_find_reg_array_property (me
, "reg", 0, ®
))
169 hw_abort (me
, "\"reg\" property must contain three addr/size entries");
170 hw_unit_address_to_attach_address (hw_parent (me
),
175 controller
->block
.base
= attach_address
;
176 hw_unit_size_to_attach_size (hw_parent (me
),
179 controller
->block
.bound
= attach_address
+ (attach_size
- 1);
180 if ((controller
->block
.base
& 3) != 0)
181 hw_abort (me
, "cpu register block must be 4 byte aligned");
182 hw_attach_address (hw_parent (me
),
184 attach_space
, attach_address
, attach_size
,
190 mn103cpu_finish (struct hw
*me
)
192 struct mn103cpu
*controller
;
194 controller
= HW_ZALLOC (me
, struct mn103cpu
);
195 set_hw_data (me
, controller
);
196 set_hw_io_read_buffer (me
, mn103cpu_io_read_buffer
);
197 set_hw_io_write_buffer (me
, mn103cpu_io_write_buffer
);
198 set_hw_ports (me
, mn103cpu_ports
);
199 set_hw_port_event (me
, mn103cpu_port_event
);
201 /* Attach ourself to our parent bus */
202 attach_mn103cpu_regs (me
, controller
);
204 /* Initialize the read-only registers */
205 controller
->pending_level
= 7; /* FIXME */
211 /* An event arrives on an interrupt port */
214 deliver_mn103cpu_interrupt (struct hw
*me
,
217 struct mn103cpu
*controller
= hw_data (me
);
218 SIM_DESC simulator
= hw_system (me
);
219 sim_cpu
*cpu
= STATE_CPU (simulator
, 0);
221 if (controller
->pending_reset
)
223 controller
->pending_reset
= 0;
224 /* need to clear all registers et.al! */
225 HW_TRACE ((me
, "Reset!"));
226 hw_abort (me
, "Reset!");
228 else if (controller
->pending_nmi
)
230 controller
->pending_nmi
= 0;
231 store_word (SP
- 4, CIA_GET (cpu
));
232 store_half (SP
- 8, PSW
);
235 CIA_SET (cpu
, 0x40000008);
236 HW_TRACE ((me
, "nmi pc=0x%08lx psw=0x%04x sp=0x%08lx",
237 (long) CIA_GET (cpu
), (unsigned) PSW
, (long) SP
));
239 else if ((controller
->pending_level
< EXTRACT_PSW_LM
)
242 /* Don't clear pending level. Request continues to be pending
243 until the interrupt controller clears/changes it */
244 store_word (SP
- 4, CIA_GET (cpu
));
245 store_half (SP
- 8, PSW
);
248 PSW
|= INSERT_PSW_LM (controller
->pending_level
);
250 CIA_SET (cpu
, 0x40000000 + controller
->interrupt_vector
[controller
->pending_level
]);
251 HW_TRACE ((me
, "port-out ack %d", controller
->pending_level
));
252 hw_port_event (me
, ACK_PORT
, controller
->pending_level
);
253 HW_TRACE ((me
, "int level=%d pc=0x%08lx psw=0x%04x sp=0x%08lx",
254 controller
->pending_level
,
255 (long) CIA_GET (cpu
), (unsigned) PSW
, (long) SP
));
258 if (controller
->pending_level
< 7) /* FIXME */
260 /* As long as there is the potential need to deliver an
261 interrupt we keep rescheduling this routine. */
262 if (controller
->pending_handler
!= NULL
)
263 controller
->pending_handler
=
264 hw_event_queue_schedule (me
, 1, deliver_mn103cpu_interrupt
, NULL
);
268 /* Don't bother re-scheduling the interrupt handler as there is
269 nothing to deliver */
270 controller
->pending_handler
= NULL
;
277 mn103cpu_port_event (struct hw
*me
,
283 struct mn103cpu
*controller
= hw_data (me
);
285 /* Schedule our event handler *now* */
286 if (controller
->pending_handler
== NULL
)
287 controller
->pending_handler
=
288 hw_event_queue_schedule (me
, 0, deliver_mn103cpu_interrupt
, NULL
);
294 controller
->pending_reset
= 1;
295 HW_TRACE ((me
, "port-in reset"));
299 controller
->pending_nmi
= 1;
300 HW_TRACE ((me
, "port-in nmi"));
304 controller
->pending_level
= level
;
305 HW_TRACE ((me
, "port-in level=%d", level
));
309 hw_abort (me
, "bad switch");
316 /* Read/write to a CPU register */
331 static enum mn103cpu_regs
332 decode_mn103cpu_addr (struct hw
*me
,
333 struct mn103cpu
*controller
,
336 switch (base
- controller
->block
.base
)
338 case 0x000: return IVR0_REG
;
339 case 0x004: return IVR1_REG
;
340 case 0x008: return IVR2_REG
;
341 case 0x00c: return IVR3_REG
;
342 case 0x010: return IVR4_REG
;
343 case 0x014: return IVR5_REG
;
344 case 0x018: return IVR6_REG
;
345 case 0x020: return IMCR_REG
;
346 case 0x040: return CPUM_REG
;
347 default: return INVALID_REG
;
352 mn103cpu_io_read_buffer (struct hw
*me
,
358 struct mn103cpu
*controller
= hw_data (me
);
360 enum mn103cpu_regs reg
= decode_mn103cpu_addr (me
, controller
, base
);
371 val
= controller
->interrupt_vector
[reg
- IVR0_REG
];
374 val
= controller
->internal_memory_control
;
377 val
= controller
->cpu_mode
;
380 /* just ignore the read */
385 *(unsigned16
*) dest
= H2LE_2 (val
);
391 mn103cpu_io_write_buffer (struct hw
*me
,
397 struct mn103cpu
*controller
= hw_data (me
);
399 enum mn103cpu_regs reg
;
402 hw_abort (me
, "must be two byte write");
404 reg
= decode_mn103cpu_addr (me
, controller
, base
);
405 val
= LE2H_2 (* (unsigned16
*) source
);
416 controller
->interrupt_vector
[reg
- IVR0_REG
] = val
;
417 HW_TRACE ((me
, "ivr%d = 0x%04lx", reg
- IVR0_REG
, (long) val
));
420 /* just ignore the write */
428 const struct hw_descriptor dv_mn103cpu_descriptor
[] = {
429 { "mn103cpu", mn103cpu_finish
, },