]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/mn10300/dv-mn103cpu.c
Initial creation of sourceware repository
[thirdparty/binutils-gdb.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 };