TX19 uses igen by default.
[deliverable/binutils-gdb.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 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 sim_cpu *processor,
283 sim_cia cia)
284 {
285 struct mn103cpu *controller = hw_data (me);
286
287 /* Schedule our event handler *now* */
288 if (controller->pending_handler == NULL)
289 controller->pending_handler =
290 hw_event_queue_schedule (me, 0, deliver_mn103cpu_interrupt, NULL);
291
292 switch (my_port)
293 {
294
295 case RESET_PORT:
296 controller->pending_reset = 1;
297 HW_TRACE ((me, "port-in reset"));
298 break;
299
300 case NMI_PORT:
301 controller->pending_nmi = 1;
302 HW_TRACE ((me, "port-in nmi"));
303 break;
304
305 case LEVEL_PORT:
306 controller->pending_level = level;
307 HW_TRACE ((me, "port-in level=%d", level));
308 break;
309
310 default:
311 hw_abort (me, "bad switch");
312 break;
313
314 }
315 }
316
317
318 /* Read/write to a CPU register */
319
320 enum mn103cpu_regs {
321 INVALID_REG,
322 IVR0_REG,
323 IVR1_REG,
324 IVR2_REG,
325 IVR3_REG,
326 IVR4_REG,
327 IVR5_REG,
328 IVR6_REG,
329 IMCR_REG,
330 CPUM_REG,
331 };
332
333 static enum mn103cpu_regs
334 decode_mn103cpu_addr (struct hw *me,
335 struct mn103cpu *controller,
336 unsigned_word base)
337 {
338 switch (base - controller->block.base)
339 {
340 case 0x000: return IVR0_REG;
341 case 0x004: return IVR1_REG;
342 case 0x008: return IVR2_REG;
343 case 0x00c: return IVR3_REG;
344 case 0x010: return IVR4_REG;
345 case 0x014: return IVR5_REG;
346 case 0x018: return IVR6_REG;
347 case 0x020: return IMCR_REG;
348 case 0x040: return CPUM_REG;
349 default: return INVALID_REG;
350 }
351 }
352
353 static unsigned
354 mn103cpu_io_read_buffer (struct hw *me,
355 void *dest,
356 int space,
357 unsigned_word base,
358 unsigned nr_bytes,
359 sim_cpu *processor,
360 sim_cia cia)
361 {
362 struct mn103cpu *controller = hw_data (me);
363 unsigned16 val = 0;
364 enum mn103cpu_regs reg = decode_mn103cpu_addr (me, controller, base);
365
366 switch (reg)
367 {
368 case IVR0_REG:
369 case IVR1_REG:
370 case IVR2_REG:
371 case IVR3_REG:
372 case IVR4_REG:
373 case IVR5_REG:
374 case IVR6_REG:
375 val = controller->interrupt_vector[reg - IVR0_REG];
376 break;
377 case IMCR_REG:
378 val = controller->internal_memory_control;
379 break;
380 case CPUM_REG:
381 val = controller->cpu_mode;
382 break;
383 default:
384 /* just ignore the read */
385 break;
386 }
387
388 if (nr_bytes == 2)
389 *(unsigned16*) dest = H2LE_2 (val);
390
391 return nr_bytes;
392 }
393
394 static unsigned
395 mn103cpu_io_write_buffer (struct hw *me,
396 const void *source,
397 int space,
398 unsigned_word base,
399 unsigned nr_bytes,
400 sim_cpu *cpu,
401 sim_cia cia)
402 {
403 struct mn103cpu *controller = hw_data (me);
404 unsigned16 val;
405 enum mn103cpu_regs reg;
406
407 if (nr_bytes != 2)
408 hw_abort (me, "must be two byte write");
409
410 reg = decode_mn103cpu_addr (me, controller, base);
411 val = LE2H_2 (* (unsigned16 *) source);
412
413 switch (reg)
414 {
415 case IVR0_REG:
416 case IVR1_REG:
417 case IVR2_REG:
418 case IVR3_REG:
419 case IVR4_REG:
420 case IVR5_REG:
421 case IVR6_REG:
422 controller->interrupt_vector[reg - IVR0_REG] = val;
423 HW_TRACE ((me, "ivr%d = 0x%04lx", reg - IVR0_REG, (long) val));
424 break;
425 default:
426 /* just ignore the write */
427 break;
428 }
429
430 return nr_bytes;
431 }
432
433
434 const struct hw_device_descriptor dv_mn103cpu_descriptor[] = {
435 { "mn103cpu", mn103cpu_finish, },
436 { NULL },
437 };
This page took 0.046089 seconds and 4 git commands to generate.