[binutils, ARM, 4/16] BF insns infrastructure with array of relocs in struct arm_it
[binutils-gdb.git] / sim / mn10300 / dv-mn103cpu.c
blob51cae7b6880476bcff72319c5dca89c30e61c348
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/>.
22 #include "sim-main.h"
23 #include "hw-main.h"
25 /* DEVICE
28 mn103cpu - mn10300 cpu virtual device
31 DESCRIPTION
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.
39 PROPERTIES
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.
51 PORTS
54 reset (input)
56 Currently ignored.
59 nmi (input)
61 Deliver a non-maskable interrupt to the processor.
64 level (input)
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.
71 ack (output)
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.
78 BUGS
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
89 delivery possible.
94 /* The interrupt vectors */
96 enum { NR_VECTORS = 7, };
99 /* The interrupt controller register address blocks */
101 struct mn103cpu_block {
102 unsigned_word base;
103 unsigned_word bound;
107 struct mn103cpu {
108 struct mn103cpu_block block;
109 struct hw_event *pending_handler;
110 int pending_level;
111 int pending_nmi;
112 int pending_reset;
113 /* the visible registers */
114 unsigned16 interrupt_vector[NR_VECTORS];
115 unsigned16 internal_memory_control;
116 unsigned16 cpu_mode;
121 /* input port ID's */
123 enum {
124 RESET_PORT,
125 NMI_PORT,
126 LEVEL_PORT,
130 /* output port ID's */
132 enum {
133 ACK_PORT,
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, },
146 { NULL, },
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;
157 static void
158 attach_mn103cpu_regs (struct hw *me,
159 struct mn103cpu *controller)
161 unsigned_word attach_address;
162 int attach_space;
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, &reg))
168 hw_abort (me, "\"reg\" property must contain three addr/size entries");
169 hw_unit_address_to_attach_address (hw_parent (me),
170 &reg.address,
171 &attach_space,
172 &attach_address,
173 me);
174 controller->block.base = attach_address;
175 hw_unit_size_to_attach_size (hw_parent (me),
176 &reg.size,
177 &attach_size, 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,
184 me);
188 static void
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 */
205 /* ... */
210 /* An event arrives on an interrupt port */
212 static void
213 deliver_mn103cpu_interrupt (struct hw *me,
214 void *data)
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);
232 PSW &= ~PSW_IE;
233 SP = SP - 8;
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)
239 && (PSW & PSW_IE))
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);
245 PSW &= ~PSW_IE;
246 PSW &= ~PSW_LM;
247 PSW |= INSERT_PSW_LM (controller->pending_level);
248 SP = SP - 8;
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);
265 else
267 /* Don't bother re-scheduling the interrupt handler as there is
268 nothing to deliver */
269 controller->pending_handler = NULL;
275 static void
276 mn103cpu_port_event (struct hw *me,
277 int my_port,
278 struct hw *source,
279 int source_port,
280 int level)
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);
289 switch (my_port)
292 case RESET_PORT:
293 controller->pending_reset = 1;
294 HW_TRACE ((me, "port-in reset"));
295 break;
297 case NMI_PORT:
298 controller->pending_nmi = 1;
299 HW_TRACE ((me, "port-in nmi"));
300 break;
302 case LEVEL_PORT:
303 controller->pending_level = level;
304 HW_TRACE ((me, "port-in level=%d", level));
305 break;
307 default:
308 hw_abort (me, "bad switch");
309 break;
315 /* Read/write to a CPU register */
317 enum mn103cpu_regs {
318 INVALID_REG,
319 IVR0_REG,
320 IVR1_REG,
321 IVR2_REG,
322 IVR3_REG,
323 IVR4_REG,
324 IVR5_REG,
325 IVR6_REG,
326 IMCR_REG,
327 CPUM_REG,
330 static enum mn103cpu_regs
331 decode_mn103cpu_addr (struct hw *me,
332 struct mn103cpu *controller,
333 unsigned_word base)
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;
350 static unsigned
351 mn103cpu_io_read_buffer (struct hw *me,
352 void *dest,
353 int space,
354 unsigned_word base,
355 unsigned nr_bytes)
357 struct mn103cpu *controller = hw_data (me);
358 unsigned16 val = 0;
359 enum mn103cpu_regs reg = decode_mn103cpu_addr (me, controller, base);
361 switch (reg)
363 case IVR0_REG:
364 case IVR1_REG:
365 case IVR2_REG:
366 case IVR3_REG:
367 case IVR4_REG:
368 case IVR5_REG:
369 case IVR6_REG:
370 val = controller->interrupt_vector[reg - IVR0_REG];
371 break;
372 case IMCR_REG:
373 val = controller->internal_memory_control;
374 break;
375 case CPUM_REG:
376 val = controller->cpu_mode;
377 break;
378 default:
379 /* just ignore the read */
380 break;
383 if (nr_bytes == 2)
384 *(unsigned16*) dest = H2LE_2 (val);
386 return nr_bytes;
389 static unsigned
390 mn103cpu_io_write_buffer (struct hw *me,
391 const void *source,
392 int space,
393 unsigned_word base,
394 unsigned nr_bytes)
396 struct mn103cpu *controller = hw_data (me);
397 unsigned16 val;
398 enum mn103cpu_regs reg;
400 if (nr_bytes != 2)
401 hw_abort (me, "must be two byte write");
403 reg = decode_mn103cpu_addr (me, controller, base);
404 val = LE2H_2 (* (unsigned16 *) source);
406 switch (reg)
408 case IVR0_REG:
409 case IVR1_REG:
410 case IVR2_REG:
411 case IVR3_REG:
412 case IVR4_REG:
413 case IVR5_REG:
414 case IVR6_REG:
415 controller->interrupt_vector[reg - IVR0_REG] = val;
416 HW_TRACE ((me, "ivr%d = 0x%04lx", reg - IVR0_REG, (long) val));
417 break;
418 default:
419 /* just ignore the write */
420 break;
423 return nr_bytes;
427 const struct hw_descriptor dv_mn103cpu_descriptor[] = {
428 { "mn103cpu", mn103cpu_finish, },
429 { NULL },