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