Automatic Copyright Year update after running gdb/copyright.py
[deliverable/binutils-gdb.git] / sim / mn10300 / dv-mn103cpu.c
1 /* This file is part of the program GDB, the GNU debugger.
2
3 Copyright (C) 1998-2022 Free Software Foundation, Inc.
4 Contributed by Cygnus Solutions.
5
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.
10
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.
15
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/>.
18
19 */
20
21 /* This must come before any other includes. */
22 #include "defs.h"
23
24 #include "sim-main.h"
25 #include "hw-main.h"
26
27 /* DEVICE
28
29
30 mn103cpu - mn10300 cpu virtual device
31
32
33 DESCRIPTION
34
35
36 Implements the external mn10300 functionality. This includes the
37 delivery of interrupts generated from other devices and the
38 handling of device specific registers.
39
40
41 PROPERTIES
42
43
44 reg = <address> <size>
45
46 Specify the address of the mn10300's control register block. This
47 block contains the Interrupt Vector Registers.
48
49 The reg property value `0x20000000 0x42' locates the register block
50 at the address specified in the mn10300 user guide.
51
52
53 PORTS
54
55
56 reset (input)
57
58 Currently ignored.
59
60
61 nmi (input)
62
63 Deliver a non-maskable interrupt to the processor.
64
65
66 level (input)
67
68 Maskable interrupt level port port. The interrupt controller
69 notifies the processor of any change in the level of pending
70 requested interrupts via this port.
71
72
73 ack (output)
74
75 Output signal indicating that the processor is delivering a level
76 interrupt. The value passed with the event specifies the level of
77 the interrupt being delivered.
78
79
80 BUGS
81
82
83 When delivering an interrupt, this code assumes that there is only
84 one processor (number 0).
85
86 This code does not attempt to be efficient at handling pending
87 interrupts. It simply schedules the interrupt delivery handler
88 every instruction cycle until all pending interrupts go away. An
89 alternative implementation might modify instructions that change
90 the PSW and have them check to see if the change makes an interrupt
91 delivery possible.
92
93 */
94
95
96 /* The interrupt vectors */
97
98 enum { NR_VECTORS = 7, };
99
100
101 /* The interrupt controller register address blocks */
102
103 struct mn103cpu_block {
104 unsigned_word base;
105 unsigned_word bound;
106 };
107
108
109 struct mn103cpu {
110 struct mn103cpu_block block;
111 struct hw_event *pending_handler;
112 int pending_level;
113 int pending_nmi;
114 int pending_reset;
115 /* the visible registers */
116 unsigned16 interrupt_vector[NR_VECTORS];
117 unsigned16 internal_memory_control;
118 unsigned16 cpu_mode;
119 };
120
121
122
123 /* input port ID's */
124
125 enum {
126 RESET_PORT,
127 NMI_PORT,
128 LEVEL_PORT,
129 };
130
131
132 /* output port ID's */
133
134 enum {
135 ACK_PORT,
136 };
137
138 static const struct hw_port_descriptor mn103cpu_ports[] = {
139
140 /* interrupt inputs */
141 { "reset", RESET_PORT, 0, input_port, },
142 { "nmi", NMI_PORT, 0, input_port, },
143 { "level", LEVEL_PORT, 0, input_port, },
144
145 /* interrupt ack (latch) output from cpu */
146 { "ack", ACK_PORT, 0, output_port, },
147
148 { NULL, },
149 };
150
151
152 /* Finish off the partially created hw device. Attach our local
153 callbacks. Wire up our port names etc */
154
155 static hw_io_read_buffer_method mn103cpu_io_read_buffer;
156 static hw_io_write_buffer_method mn103cpu_io_write_buffer;
157 static hw_port_event_method mn103cpu_port_event;
158
159 static void
160 attach_mn103cpu_regs (struct hw *me,
161 struct mn103cpu *controller)
162 {
163 unsigned_word attach_address;
164 int attach_space;
165 unsigned attach_size;
166 reg_property_spec reg;
167 if (hw_find_property (me, "reg") == NULL)
168 hw_abort (me, "Missing \"reg\" property");
169 if (!hw_find_reg_array_property (me, "reg", 0, &reg))
170 hw_abort (me, "\"reg\" property must contain three addr/size entries");
171 hw_unit_address_to_attach_address (hw_parent (me),
172 &reg.address,
173 &attach_space,
174 &attach_address,
175 me);
176 controller->block.base = attach_address;
177 hw_unit_size_to_attach_size (hw_parent (me),
178 &reg.size,
179 &attach_size, me);
180 controller->block.bound = attach_address + (attach_size - 1);
181 if ((controller->block.base & 3) != 0)
182 hw_abort (me, "cpu register block must be 4 byte aligned");
183 hw_attach_address (hw_parent (me),
184 0,
185 attach_space, attach_address, attach_size,
186 me);
187 }
188
189
190 static void
191 mn103cpu_finish (struct hw *me)
192 {
193 struct mn103cpu *controller;
194
195 controller = HW_ZALLOC (me, struct mn103cpu);
196 set_hw_data (me, controller);
197 set_hw_io_read_buffer (me, mn103cpu_io_read_buffer);
198 set_hw_io_write_buffer (me, mn103cpu_io_write_buffer);
199 set_hw_ports (me, mn103cpu_ports);
200 set_hw_port_event (me, mn103cpu_port_event);
201
202 /* Attach ourself to our parent bus */
203 attach_mn103cpu_regs (me, controller);
204
205 /* Initialize the read-only registers */
206 controller->pending_level = 7; /* FIXME */
207 /* ... */
208 }
209
210
211
212 /* An event arrives on an interrupt port */
213
214 static void
215 deliver_mn103cpu_interrupt (struct hw *me,
216 void *data)
217 {
218 struct mn103cpu *controller = hw_data (me);
219 SIM_DESC simulator = hw_system (me);
220 sim_cpu *cpu = STATE_CPU (simulator, 0);
221
222 if (controller->pending_reset)
223 {
224 controller->pending_reset = 0;
225 /* need to clear all registers et.al! */
226 HW_TRACE ((me, "Reset!"));
227 hw_abort (me, "Reset!");
228 }
229 else if (controller->pending_nmi)
230 {
231 controller->pending_nmi = 0;
232 store_word (SP - 4, CPU_PC_GET (cpu));
233 store_half (SP - 8, PSW);
234 PSW &= ~PSW_IE;
235 SP = SP - 8;
236 CPU_PC_SET (cpu, 0x40000008);
237 HW_TRACE ((me, "nmi pc=0x%08lx psw=0x%04x sp=0x%08lx",
238 (long) CPU_PC_GET (cpu), (unsigned) PSW, (long) SP));
239 }
240 else if ((controller->pending_level < EXTRACT_PSW_LM)
241 && (PSW & PSW_IE))
242 {
243 /* Don't clear pending level. Request continues to be pending
244 until the interrupt controller clears/changes it */
245 store_word (SP - 4, CPU_PC_GET (cpu));
246 store_half (SP - 8, PSW);
247 PSW &= ~PSW_IE;
248 PSW &= ~PSW_LM;
249 PSW |= INSERT_PSW_LM (controller->pending_level);
250 SP = SP - 8;
251 CPU_PC_SET (cpu, 0x40000000 + controller->interrupt_vector[controller->pending_level]);
252 HW_TRACE ((me, "port-out ack %d", controller->pending_level));
253 hw_port_event (me, ACK_PORT, controller->pending_level);
254 HW_TRACE ((me, "int level=%d pc=0x%08lx psw=0x%04x sp=0x%08lx",
255 controller->pending_level,
256 (long) CPU_PC_GET (cpu), (unsigned) PSW, (long) SP));
257 }
258
259 if (controller->pending_level < 7) /* FIXME */
260 {
261 /* As long as there is the potential need to deliver an
262 interrupt we keep rescheduling this routine. */
263 if (controller->pending_handler != NULL)
264 controller->pending_handler =
265 hw_event_queue_schedule (me, 1, deliver_mn103cpu_interrupt, NULL);
266 }
267 else
268 {
269 /* Don't bother re-scheduling the interrupt handler as there is
270 nothing to deliver */
271 controller->pending_handler = NULL;
272 }
273
274 }
275
276
277 static void
278 mn103cpu_port_event (struct hw *me,
279 int my_port,
280 struct hw *source,
281 int source_port,
282 int level)
283 {
284 struct mn103cpu *controller = hw_data (me);
285
286 /* Schedule our event handler *now* */
287 if (controller->pending_handler == NULL)
288 controller->pending_handler =
289 hw_event_queue_schedule (me, 0, deliver_mn103cpu_interrupt, NULL);
290
291 switch (my_port)
292 {
293
294 case RESET_PORT:
295 controller->pending_reset = 1;
296 HW_TRACE ((me, "port-in reset"));
297 break;
298
299 case NMI_PORT:
300 controller->pending_nmi = 1;
301 HW_TRACE ((me, "port-in nmi"));
302 break;
303
304 case LEVEL_PORT:
305 controller->pending_level = level;
306 HW_TRACE ((me, "port-in level=%d", level));
307 break;
308
309 default:
310 hw_abort (me, "bad switch");
311 break;
312
313 }
314 }
315
316
317 /* Read/write to a CPU register */
318
319 enum mn103cpu_regs {
320 INVALID_REG,
321 IVR0_REG,
322 IVR1_REG,
323 IVR2_REG,
324 IVR3_REG,
325 IVR4_REG,
326 IVR5_REG,
327 IVR6_REG,
328 IMCR_REG,
329 CPUM_REG,
330 };
331
332 static enum mn103cpu_regs
333 decode_mn103cpu_addr (struct hw *me,
334 struct mn103cpu *controller,
335 unsigned_word base)
336 {
337 switch (base - controller->block.base)
338 {
339 case 0x000: return IVR0_REG;
340 case 0x004: return IVR1_REG;
341 case 0x008: return IVR2_REG;
342 case 0x00c: return IVR3_REG;
343 case 0x010: return IVR4_REG;
344 case 0x014: return IVR5_REG;
345 case 0x018: return IVR6_REG;
346 case 0x020: return IMCR_REG;
347 case 0x040: return CPUM_REG;
348 default: return INVALID_REG;
349 }
350 }
351
352 static unsigned
353 mn103cpu_io_read_buffer (struct hw *me,
354 void *dest,
355 int space,
356 unsigned_word base,
357 unsigned nr_bytes)
358 {
359 struct mn103cpu *controller = hw_data (me);
360 unsigned16 val = 0;
361 enum mn103cpu_regs reg = decode_mn103cpu_addr (me, controller, base);
362
363 switch (reg)
364 {
365 case IVR0_REG:
366 case IVR1_REG:
367 case IVR2_REG:
368 case IVR3_REG:
369 case IVR4_REG:
370 case IVR5_REG:
371 case IVR6_REG:
372 val = controller->interrupt_vector[reg - IVR0_REG];
373 break;
374 case IMCR_REG:
375 val = controller->internal_memory_control;
376 break;
377 case CPUM_REG:
378 val = controller->cpu_mode;
379 break;
380 default:
381 /* just ignore the read */
382 break;
383 }
384
385 if (nr_bytes == 2)
386 *(unsigned16*) dest = H2LE_2 (val);
387
388 return nr_bytes;
389 }
390
391 static unsigned
392 mn103cpu_io_write_buffer (struct hw *me,
393 const void *source,
394 int space,
395 unsigned_word base,
396 unsigned nr_bytes)
397 {
398 struct mn103cpu *controller = hw_data (me);
399 unsigned16 val;
400 enum mn103cpu_regs reg;
401
402 if (nr_bytes != 2)
403 hw_abort (me, "must be two byte write");
404
405 reg = decode_mn103cpu_addr (me, controller, base);
406 val = LE2H_2 (* (unsigned16 *) source);
407
408 switch (reg)
409 {
410 case IVR0_REG:
411 case IVR1_REG:
412 case IVR2_REG:
413 case IVR3_REG:
414 case IVR4_REG:
415 case IVR5_REG:
416 case IVR6_REG:
417 controller->interrupt_vector[reg - IVR0_REG] = val;
418 HW_TRACE ((me, "ivr%d = 0x%04lx", reg - IVR0_REG, (long) val));
419 break;
420 default:
421 /* just ignore the write */
422 break;
423 }
424
425 return nr_bytes;
426 }
427
428
429 const struct hw_descriptor dv_mn103cpu_descriptor[] = {
430 { "mn103cpu", mn103cpu_finish, },
431 { NULL },
432 };
This page took 0.038486 seconds and 4 git commands to generate.