OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [sim/] [mn10300/] [dv-mn103cpu.c] - Blame information for rev 337

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 24 jeremybenn
/*  This file is part of the program GDB, the GNU debugger.
2
 
3
    Copyright (C) 1998, 2007, 2008 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 3 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, see <http://www.gnu.org/licenses/>.
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
 
96
enum { NR_VECTORS = 7, };
97
 
98
 
99
/* The interrupt controller register address blocks */
100
 
101
struct mn103cpu_block {
102
  unsigned_word base;
103
  unsigned_word bound;
104
};
105
 
106
 
107
struct 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
 
123
enum {
124
  RESET_PORT,
125
  NMI_PORT,
126
  LEVEL_PORT,
127
};
128
 
129
 
130
/* output port ID's */
131
 
132
enum {
133
  ACK_PORT,
134
};
135
 
136
static 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
 
153
static hw_io_read_buffer_method mn103cpu_io_read_buffer;
154
static hw_io_write_buffer_method mn103cpu_io_write_buffer;
155
static hw_port_event_method mn103cpu_port_event;
156
 
157
static void
158
attach_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
 
188
static void
189
mn103cpu_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
 
212
static void
213
deliver_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
 
275
static void
276
mn103cpu_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
 
317
enum 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
 
330
static enum mn103cpu_regs
331
decode_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
 
350
static unsigned
351
mn103cpu_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
 
389
static unsigned
390
mn103cpu_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
 
427
const struct hw_descriptor dv_mn103cpu_descriptor[] = {
428
  { "mn103cpu", mn103cpu_finish, },
429
  { NULL },
430
};

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.