xref: /netbsd-src/external/gpl3/gdb/dist/sim/mn10300/dv-mn103cpu.c (revision 0388e998654430ce19a2917dec7ff0950bcf2e1c)
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 };
437