1/*  This file is part of the program GDB, the GNU debugger.
2
3    Copyright (C) 1998, 2007 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
22#include "sim-main.h"
23#include "hw-main.h"
24
25/* DEVICE
26
27
28   mn103cpu - mn10300 cpu virtual device
29
30
31   DESCRIPTION
32
33
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.
37
38
39   PROPERTIES
40
41
42   reg = <address> <size>
43
44   Specify the address of the mn10300's control register block.  This
45   block contains the Interrupt Vector Registers.
46
47   The reg property value `0x20000000 0x42' locates the register block
48   at the address specified in the mn10300 user guide.
49
50
51   PORTS
52
53
54   reset (input)
55
56   Currently ignored.
57
58
59   nmi (input)
60
61   Deliver a non-maskable interrupt to the processor.
62
63
64   level (input)
65
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.
69
70
71   ack (output)
72
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.
76
77
78   BUGS
79
80
81   When delivering an interrupt, this code assumes that there is only
82   one processor (number 0).
83
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.
90
91   */
92
93
94/* The interrupt vectors */
95
96enum { NR_VECTORS = 7, };
97
98
99/* The interrupt controller register address blocks */
100
101struct mn103cpu_block {
102  unsigned_word base;
103  unsigned_word bound;
104};
105
106
107struct 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;
117};
118
119
120
121/* input port ID's */
122
123enum {
124  RESET_PORT,
125  NMI_PORT,
126  LEVEL_PORT,
127};
128
129
130/* output port ID's */
131
132enum {
133  ACK_PORT,
134};
135
136static const struct hw_port_descriptor mn103cpu_ports[] = {
137
138  /* interrupt inputs */
139  { "reset", RESET_PORT, 0, input_port, },
140  { "nmi", NMI_PORT, 0, input_port, },
141  { "level", LEVEL_PORT, 0, input_port, },
142
143  /* interrupt ack (latch) output from cpu */
144  { "ack", ACK_PORT, 0, output_port, },
145
146  { NULL, },
147};
148
149
150/* Finish off the partially created hw device.  Attach our local
151   callbacks.  Wire up our port names etc */
152
153static hw_io_read_buffer_method mn103cpu_io_read_buffer;
154static hw_io_write_buffer_method mn103cpu_io_write_buffer;
155static hw_port_event_method mn103cpu_port_event;
156
157static void
158attach_mn103cpu_regs (struct hw *me,
159		      struct mn103cpu *controller)
160{
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),
182		     0,
183		     attach_space, attach_address, attach_size,
184		     me);
185}
186
187
188static void
189mn103cpu_finish (struct hw *me)
190{
191  struct mn103cpu *controller;
192
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);
199
200  /* Attach ourself to our parent bus */
201  attach_mn103cpu_regs (me, controller);
202
203  /* Initialize the read-only registers */
204  controller->pending_level = 7; /* FIXME */
205  /* ... */
206}
207
208
209
210/* An event arrives on an interrupt port */
211
212static void
213deliver_mn103cpu_interrupt (struct hw *me,
214			    void *data)
215{
216  struct mn103cpu *controller = hw_data (me);
217  SIM_DESC simulator = hw_system (me);
218  sim_cpu *cpu = STATE_CPU (simulator, 0);
219
220  if (controller->pending_reset)
221    {
222      controller->pending_reset = 0;
223      /* need to clear all registers et.al! */
224      HW_TRACE ((me, "Reset!"));
225      hw_abort (me, "Reset!");
226    }
227  else if (controller->pending_nmi)
228    {
229      controller->pending_nmi = 0;
230      store_word (SP - 4, CIA_GET (cpu));
231      store_half (SP - 8, PSW);
232      PSW &= ~PSW_IE;
233      SP = SP - 8;
234      CIA_SET (cpu, 0x40000008);
235      HW_TRACE ((me, "nmi pc=0x%08lx psw=0x%04x sp=0x%08lx",
236		 (long) CIA_GET (cpu), (unsigned) PSW, (long) SP));
237    }
238  else if ((controller->pending_level < EXTRACT_PSW_LM)
239	   && (PSW & PSW_IE))
240    {
241      /* Don't clear pending level.  Request continues to be pending
242         until the interrupt controller clears/changes it */
243      store_word (SP - 4, CIA_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      CIA_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) CIA_GET (cpu), (unsigned) PSW, (long) SP));
255    }
256
257  if (controller->pending_level < 7) /* FIXME */
258    {
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);
264    }
265  else
266    {
267      /* Don't bother re-scheduling the interrupt handler as there is
268         nothing to deliver */
269      controller->pending_handler = NULL;
270    }
271
272}
273
274
275static void
276mn103cpu_port_event (struct hw *me,
277		     int my_port,
278		     struct hw *source,
279		     int source_port,
280		     int level)
281{
282  struct mn103cpu *controller = hw_data (me);
283
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);
288
289  switch (my_port)
290    {
291
292    case RESET_PORT:
293      controller->pending_reset = 1;
294      HW_TRACE ((me, "port-in reset"));
295      break;
296
297    case NMI_PORT:
298      controller->pending_nmi = 1;
299      HW_TRACE ((me, "port-in nmi"));
300      break;
301
302    case LEVEL_PORT:
303      controller->pending_level = level;
304      HW_TRACE ((me, "port-in level=%d", level));
305      break;
306
307    default:
308      hw_abort (me, "bad switch");
309      break;
310
311    }
312}
313
314
315/* Read/write to a CPU register */
316
317enum 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,
328};
329
330static enum mn103cpu_regs
331decode_mn103cpu_addr (struct hw *me,
332		      struct mn103cpu *controller,
333		      unsigned_word base)
334{
335  switch (base - controller->block.base)
336    {
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;
347    }
348}
349
350static unsigned
351mn103cpu_io_read_buffer (struct hw *me,
352			 void *dest,
353			 int space,
354			 unsigned_word base,
355			 unsigned nr_bytes)
356{
357  struct mn103cpu *controller = hw_data (me);
358  unsigned16 val = 0;
359  enum mn103cpu_regs reg = decode_mn103cpu_addr (me, controller, base);
360
361  switch (reg)
362    {
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;
381    }
382
383  if (nr_bytes == 2)
384    *(unsigned16*) dest = H2LE_2 (val);
385
386  return nr_bytes;
387}
388
389static unsigned
390mn103cpu_io_write_buffer (struct hw *me,
391			  const void *source,
392			  int space,
393			  unsigned_word base,
394			  unsigned nr_bytes)
395{
396  struct mn103cpu *controller = hw_data (me);
397  unsigned16 val;
398  enum mn103cpu_regs reg;
399
400  if (nr_bytes != 2)
401    hw_abort (me, "must be two byte write");
402
403  reg = decode_mn103cpu_addr (me, controller, base);
404  val = LE2H_2 (* (unsigned16 *) source);
405
406  switch (reg)
407    {
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;
421    }
422
423  return nr_bytes;
424}
425
426
427const struct hw_descriptor dv_mn103cpu_descriptor[] = {
428  { "mn103cpu", mn103cpu_finish, },
429  { NULL },
430};
431