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 GU 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-base.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 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 specfies 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   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 /* input 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_callback mn103cpu_io_read_buffer;
155 static hw_io_write_buffer_callback mn103cpu_io_write_buffer;
156 static hw_port_event_callback 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_half (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_half (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, NULL, NULL_CIA);
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   /* As long as there is the potential need to deliver an interrupt we
259      keep rescheduling this routine. */
260   if (controller->pending_level < 7) /* FIXME */
261     {
262       if (controller->pending_handler != NULL)
263         controller->pending_handler =
264           hw_event_queue_schedule (me, 1, deliver_mn103cpu_interrupt, NULL);
265     }
266
267 }
268
269
270 static void
271 mn103cpu_port_event (struct hw *me,
272                      int my_port,
273                      struct hw *source,
274                      int source_port,
275                      int level,
276                      sim_cpu *processor,
277                      sim_cia cia)
278 {
279   struct mn103cpu *controller = hw_data (me);
280
281   /* Schedule our event handler *now* */
282   if (controller->pending_handler == NULL)
283     controller->pending_handler =
284       hw_event_queue_schedule (me, 0, deliver_mn103cpu_interrupt, NULL);
285
286   switch (my_port)
287     {
288       
289     case RESET_PORT:
290       controller->pending_reset = 1;
291       HW_TRACE ((me, "port-in reset"));
292       break;
293       
294     case NMI_PORT:
295       controller->pending_nmi = 1;
296       HW_TRACE ((me, "port-in nmi"));
297       break;
298       
299     case LEVEL_PORT:
300       controller->pending_level = level;
301       HW_TRACE ((me, "port-in level=%d", level));
302       break;
303       
304     default:
305       hw_abort (me, "bad switch");
306       break;
307
308     }
309 }
310
311
312 /* Read/write to a CPU register */
313
314 enum mn103cpu_regs {
315   INVALID_REG,
316   IVR0_REG,
317   IVR1_REG,
318   IVR2_REG,
319   IVR3_REG,
320   IVR4_REG,
321   IVR5_REG,
322   IVR6_REG,
323   IMCR_REG,
324   CPUM_REG,
325 };
326
327 static enum mn103cpu_regs
328 decode_mn103cpu_addr (struct hw *me,
329                       struct mn103cpu *controller,
330                       unsigned_word base)
331 {
332   switch (base - controller->block.base)
333     {
334     case 0x000: return IVR0_REG;
335     case 0x004: return IVR1_REG;
336     case 0x008: return IVR2_REG;
337     case 0x00c: return IVR3_REG;
338     case 0x010: return IVR4_REG;
339     case 0x014: return IVR5_REG;
340     case 0x018: return IVR6_REG;
341     case 0x020: return IMCR_REG;
342     case 0x040: return CPUM_REG;
343     default: return INVALID_REG;
344     }
345 }
346
347 static unsigned
348 mn103cpu_io_read_buffer (struct hw *me,
349                          void *dest,
350                          int space,
351                          unsigned_word base,
352                          unsigned nr_bytes,
353                          sim_cpu *processor,
354                          sim_cia cia)
355 {
356   struct mn103cpu *controller = hw_data (me);
357   unsigned16 val = 0;
358   enum mn103cpu_regs reg = decode_mn103cpu_addr (me, controller, base);
359
360   switch (reg)
361     {
362     case IVR0_REG:
363     case IVR1_REG:
364     case IVR2_REG:
365     case IVR3_REG:
366     case IVR4_REG:
367     case IVR5_REG:
368     case IVR6_REG:
369       val = controller->interrupt_vector[reg - IVR0_REG];
370       break;
371     case IMCR_REG:
372       val = controller->internal_memory_control;
373       break;
374     case CPUM_REG:
375       val = controller->cpu_mode;
376       break;
377     default:
378       /* just ignore the read */
379       break;
380     }
381
382   if (nr_bytes == 2)
383     *(unsigned16*) dest = H2LE_2 (val);
384
385   return nr_bytes;
386 }     
387
388 static unsigned
389 mn103cpu_io_write_buffer (struct hw *me,
390                           const void *source,
391                           int space,
392                           unsigned_word base,
393                           unsigned nr_bytes,
394                           sim_cpu *cpu,
395                           sim_cia cia)
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_device_descriptor dv_mn103cpu_descriptor[] = {
429   { "mn103cpu", mn103cpu_finish, },
430   { NULL },
431 };