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