]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/mn10300/dv-mn103cpu.c
Update years in copyright notice for the GDB files.
[thirdparty/binutils-gdb.git] / sim / mn10300 / dv-mn103cpu.c
CommitLineData
c906108c
SS
1/* This file is part of the program GDB, the GNU debugger.
2
8acc9f48 3 Copyright (C) 1998-2013 Free Software Foundation, Inc.
c906108c
SS
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
4744ac1b 8 the Free Software Foundation; either version 3 of the License, or
c906108c 9 (at your option) any later version.
4744ac1b 10
c906108c
SS
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.
4744ac1b 15
c906108c 16 You should have received a copy of the GNU General Public License
4744ac1b 17 along with this program. If not, see <http://www.gnu.org/licenses/>.
c906108c
SS
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};