1 /* This file is part of the program GDB, the GNU debugger.
3 Copyright (C) 1998-2019 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 3 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, see <http://www.gnu.org/licenses/>.
28 mn103cpu - mn10300 cpu virtual device
34 Implements the external mn10300 functionality. This includes the
35 delivery of interrupts generated from other devices and the
36 handling of device specific registers.
42 reg = <address> <size>
44 Specify the address of the mn10300's control register block. This
45 block contains the Interrupt Vector Registers.
47 The reg property value `0x20000000 0x42' locates the register block
48 at the address specified in the mn10300 user guide.
61 Deliver a non-maskable interrupt to the processor.
66 Maskable interrupt level port port. The interrupt controller
67 notifies the processor of any change in the level of pending
68 requested interrupts via this port.
73 Output signal indicating that the processor is delivering a level
74 interrupt. The value passed with the event specifies the level of
75 the interrupt being delivered.
81 When delivering an interrupt, this code assumes that there is only
82 one processor (number 0).
84 This code does not attempt to be efficient at handling pending
85 interrupts. It simply schedules the interrupt delivery handler
86 every instruction cycle until all pending interrupts go away. An
87 alternative implementation might modify instructions that change
88 the PSW and have them check to see if the change makes an interrupt
94 /* The interrupt vectors */
96 enum { NR_VECTORS
= 7, };
99 /* The interrupt controller register address blocks */
101 struct mn103cpu_block
{
108 struct mn103cpu_block block
;
109 struct hw_event
*pending_handler
;
113 /* the visible registers */
114 unsigned16 interrupt_vector
[NR_VECTORS
];
115 unsigned16 internal_memory_control
;
121 /* input port ID's */
130 /* output port ID's */
136 static const struct hw_port_descriptor mn103cpu_ports
[] = {
138 /* interrupt inputs */
139 { "reset", RESET_PORT
, 0, input_port
, },
140 { "nmi", NMI_PORT
, 0, input_port
, },
141 { "level", LEVEL_PORT
, 0, input_port
, },
143 /* interrupt ack (latch) output from cpu */
144 { "ack", ACK_PORT
, 0, output_port
, },
150 /* Finish off the partially created hw device. Attach our local
151 callbacks. Wire up our port names etc */
153 static hw_io_read_buffer_method mn103cpu_io_read_buffer
;
154 static hw_io_write_buffer_method mn103cpu_io_write_buffer
;
155 static hw_port_event_method mn103cpu_port_event
;
158 attach_mn103cpu_regs (struct hw
*me
,
159 struct mn103cpu
*controller
)
161 unsigned_word attach_address
;
163 unsigned attach_size
;
164 reg_property_spec reg
;
165 if (hw_find_property (me
, "reg") == NULL
)
166 hw_abort (me
, "Missing \"reg\" property");
167 if (!hw_find_reg_array_property (me
, "reg", 0, ®
))
168 hw_abort (me
, "\"reg\" property must contain three addr/size entries");
169 hw_unit_address_to_attach_address (hw_parent (me
),
174 controller
->block
.base
= attach_address
;
175 hw_unit_size_to_attach_size (hw_parent (me
),
178 controller
->block
.bound
= attach_address
+ (attach_size
- 1);
179 if ((controller
->block
.base
& 3) != 0)
180 hw_abort (me
, "cpu register block must be 4 byte aligned");
181 hw_attach_address (hw_parent (me
),
183 attach_space
, attach_address
, attach_size
,
189 mn103cpu_finish (struct hw
*me
)
191 struct mn103cpu
*controller
;
193 controller
= HW_ZALLOC (me
, struct mn103cpu
);
194 set_hw_data (me
, controller
);
195 set_hw_io_read_buffer (me
, mn103cpu_io_read_buffer
);
196 set_hw_io_write_buffer (me
, mn103cpu_io_write_buffer
);
197 set_hw_ports (me
, mn103cpu_ports
);
198 set_hw_port_event (me
, mn103cpu_port_event
);
200 /* Attach ourself to our parent bus */
201 attach_mn103cpu_regs (me
, controller
);
203 /* Initialize the read-only registers */
204 controller
->pending_level
= 7; /* FIXME */
210 /* An event arrives on an interrupt port */
213 deliver_mn103cpu_interrupt (struct hw
*me
,
216 struct mn103cpu
*controller
= hw_data (me
);
217 SIM_DESC simulator
= hw_system (me
);
218 sim_cpu
*cpu
= STATE_CPU (simulator
, 0);
220 if (controller
->pending_reset
)
222 controller
->pending_reset
= 0;
223 /* need to clear all registers et.al! */
224 HW_TRACE ((me
, "Reset!"));
225 hw_abort (me
, "Reset!");
227 else if (controller
->pending_nmi
)
229 controller
->pending_nmi
= 0;
230 store_word (SP
- 4, CPU_PC_GET (cpu
));
231 store_half (SP
- 8, PSW
);
234 CPU_PC_SET (cpu
, 0x40000008);
235 HW_TRACE ((me
, "nmi pc=0x%08lx psw=0x%04x sp=0x%08lx",
236 (long) CPU_PC_GET (cpu
), (unsigned) PSW
, (long) SP
));
238 else if ((controller
->pending_level
< EXTRACT_PSW_LM
)
241 /* Don't clear pending level. Request continues to be pending
242 until the interrupt controller clears/changes it */
243 store_word (SP
- 4, CPU_PC_GET (cpu
));
244 store_half (SP
- 8, PSW
);
247 PSW
|= INSERT_PSW_LM (controller
->pending_level
);
249 CPU_PC_SET (cpu
, 0x40000000 + controller
->interrupt_vector
[controller
->pending_level
]);
250 HW_TRACE ((me
, "port-out ack %d", controller
->pending_level
));
251 hw_port_event (me
, ACK_PORT
, controller
->pending_level
);
252 HW_TRACE ((me
, "int level=%d pc=0x%08lx psw=0x%04x sp=0x%08lx",
253 controller
->pending_level
,
254 (long) CPU_PC_GET (cpu
), (unsigned) PSW
, (long) SP
));
257 if (controller
->pending_level
< 7) /* FIXME */
259 /* As long as there is the potential need to deliver an
260 interrupt we keep rescheduling this routine. */
261 if (controller
->pending_handler
!= NULL
)
262 controller
->pending_handler
=
263 hw_event_queue_schedule (me
, 1, deliver_mn103cpu_interrupt
, NULL
);
267 /* Don't bother re-scheduling the interrupt handler as there is
268 nothing to deliver */
269 controller
->pending_handler
= NULL
;
276 mn103cpu_port_event (struct hw
*me
,
282 struct mn103cpu
*controller
= hw_data (me
);
284 /* Schedule our event handler *now* */
285 if (controller
->pending_handler
== NULL
)
286 controller
->pending_handler
=
287 hw_event_queue_schedule (me
, 0, deliver_mn103cpu_interrupt
, NULL
);
293 controller
->pending_reset
= 1;
294 HW_TRACE ((me
, "port-in reset"));
298 controller
->pending_nmi
= 1;
299 HW_TRACE ((me
, "port-in nmi"));
303 controller
->pending_level
= level
;
304 HW_TRACE ((me
, "port-in level=%d", level
));
308 hw_abort (me
, "bad switch");
315 /* Read/write to a CPU register */
330 static enum mn103cpu_regs
331 decode_mn103cpu_addr (struct hw
*me
,
332 struct mn103cpu
*controller
,
335 switch (base
- controller
->block
.base
)
337 case 0x000: return IVR0_REG
;
338 case 0x004: return IVR1_REG
;
339 case 0x008: return IVR2_REG
;
340 case 0x00c: return IVR3_REG
;
341 case 0x010: return IVR4_REG
;
342 case 0x014: return IVR5_REG
;
343 case 0x018: return IVR6_REG
;
344 case 0x020: return IMCR_REG
;
345 case 0x040: return CPUM_REG
;
346 default: return INVALID_REG
;
351 mn103cpu_io_read_buffer (struct hw
*me
,
357 struct mn103cpu
*controller
= hw_data (me
);
359 enum mn103cpu_regs reg
= decode_mn103cpu_addr (me
, controller
, base
);
370 val
= controller
->interrupt_vector
[reg
- IVR0_REG
];
373 val
= controller
->internal_memory_control
;
376 val
= controller
->cpu_mode
;
379 /* just ignore the read */
384 *(unsigned16
*) dest
= H2LE_2 (val
);
390 mn103cpu_io_write_buffer (struct hw
*me
,
396 struct mn103cpu
*controller
= hw_data (me
);
398 enum mn103cpu_regs reg
;
401 hw_abort (me
, "must be two byte write");
403 reg
= decode_mn103cpu_addr (me
, controller
, base
);
404 val
= LE2H_2 (* (unsigned16
*) source
);
415 controller
->interrupt_vector
[reg
- IVR0_REG
] = val
;
416 HW_TRACE ((me
, "ivr%d = 0x%04lx", reg
- IVR0_REG
, (long) val
));
419 /* just ignore the write */
427 const struct hw_descriptor dv_mn103cpu_descriptor
[] = {
428 { "mn103cpu", mn103cpu_finish
, },