aboutsummaryrefslogtreecommitdiff
path: root/sim/mn10300/interp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sim/mn10300/interp.c')
-rw-r--r--sim/mn10300/interp.c269
1 files changed, 119 insertions, 150 deletions
diff --git a/sim/mn10300/interp.c b/sim/mn10300/interp.c
index eede9a7..4c14b70 100644
--- a/sim/mn10300/interp.c
+++ b/sim/mn10300/interp.c
@@ -3,6 +3,7 @@
#if WITH_COMMON
#include "sim-main.h"
#include "sim-options.h"
+#include "sim-hw.h"
#else
#include "mn10300_sim.h"
#endif
@@ -892,151 +893,6 @@ sim_load (sd, prog, abfd, from_tty)
/* For compatibility */
SIM_DESC simulator;
-/* mn10300 interrupt model */
-
-enum interrupt_type
-{
- int_reset,
- int_nmi,
- int_intov1,
- int_intp10,
- int_intp11,
- int_intp12,
- int_intp13,
- int_intcm4,
- num_int_types
-};
-
-char *interrupt_names[] = {
- "reset",
- "nmi",
- "intov1",
- "intp10",
- "intp11",
- "intp12",
- "intp13",
- "intcm4",
- NULL
-};
-
-
-static void
-do_interrupt (sd, data)
- SIM_DESC sd;
- void *data;
-{
-#if 0
- char **interrupt_name = (char**)data;
- enum interrupt_type inttype;
- inttype = (interrupt_name - STATE_WATCHPOINTS (sd)->interrupt_names);
-
- /* For a hardware reset, drop everything and jump to the start
- address */
- if (inttype == int_reset)
- {
- PC = 0;
- PSW = 0x20;
- ECR = 0;
- sim_engine_restart (sd, NULL, NULL, NULL_CIA);
- }
-
- /* Deliver an NMI when allowed */
- if (inttype == int_nmi)
- {
- if (PSW & PSW_NP)
- {
- /* We're already working on an NMI, so this one must wait
- around until the previous one is done. The processor
- ignores subsequent NMIs, so we don't need to count them.
- Just keep re-scheduling a single NMI until it manages to
- be delivered */
- if (STATE_CPU (sd, 0)->pending_nmi != NULL)
- sim_events_deschedule (sd, STATE_CPU (sd, 0)->pending_nmi);
- STATE_CPU (sd, 0)->pending_nmi =
- sim_events_schedule (sd, 1, do_interrupt, data);
- return;
- }
- else
- {
- /* NMI can be delivered. Do not deschedule pending_nmi as
- that, if still in the event queue, is a second NMI that
- needs to be delivered later. */
- FEPC = PC;
- FEPSW = PSW;
- /* Set the FECC part of the ECR. */
- ECR &= 0x0000ffff;
- ECR |= 0x10;
- PSW |= PSW_NP;
- PSW &= ~PSW_EP;
- PSW |= PSW_ID;
- PC = 0x10;
- sim_engine_restart (sd, NULL, NULL, NULL_CIA);
- }
- }
-
- /* deliver maskable interrupt when allowed */
- if (inttype > int_nmi && inttype < num_int_types)
- {
- if ((PSW & PSW_NP) || (PSW & PSW_ID))
- {
- /* Can't deliver this interrupt, reschedule it for later */
- sim_events_schedule (sd, 1, do_interrupt, data);
- return;
- }
- else
- {
- /* save context */
- EIPC = PC;
- EIPSW = PSW;
- /* Disable further interrupts. */
- PSW |= PSW_ID;
- /* Indicate that we're doing interrupt not exception processing. */
- PSW &= ~PSW_EP;
- /* Clear the EICC part of the ECR, will set below. */
- ECR &= 0xffff0000;
- switch (inttype)
- {
- case int_intov1:
- PC = 0x80;
- ECR |= 0x80;
- break;
- case int_intp10:
- PC = 0x90;
- ECR |= 0x90;
- break;
- case int_intp11:
- PC = 0xa0;
- ECR |= 0xa0;
- break;
- case int_intp12:
- PC = 0xb0;
- ECR |= 0xb0;
- break;
- case int_intp13:
- PC = 0xc0;
- ECR |= 0xc0;
- break;
- case int_intcm4:
- PC = 0xd0;
- ECR |= 0xd0;
- break;
- default:
- /* Should never be possible. */
- sim_engine_abort (sd, NULL, NULL_CIA,
- "do_interrupt - internal error - bad switch");
- break;
- }
- }
- sim_engine_restart (sd, NULL, NULL, NULL_CIA);
- }
-
- /* some other interrupt? */
- sim_engine_abort (sd, NULL, NULL_CIA,
- "do_interrupt - internal error - interrupt %d unknown",
- inttype);
-#endif /* 0 */
-}
-
/* These default values correspond to expected usage for the chip. */
SIM_DESC
@@ -1047,6 +903,7 @@ sim_open (kind, cb, abfd, argv)
char **argv;
{
SIM_DESC sd = sim_state_alloc (kind, cb);
+ struct hw *hw;
mn10300_callback = cb;
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
@@ -1054,19 +911,20 @@ sim_open (kind, cb, abfd, argv)
/* for compatibility */
simulator = sd;
- /* FIXME: should be better way of setting up interrupts */
+ /* FIXME: should be better way of setting up interrupts. For
+ moment, only support watchpoints causing a breakpoint (gdb
+ halt). */
STATE_WATCHPOINTS (sd)->pc = &(PC);
STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
- STATE_WATCHPOINTS (sd)->interrupt_handler = do_interrupt;
- STATE_WATCHPOINTS (sd)->interrupt_names = interrupt_names;
+ STATE_WATCHPOINTS (sd)->interrupt_handler = NULL;
+ STATE_WATCHPOINTS (sd)->interrupt_names = NULL;
if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
return 0;
/* Allocate core managed memory */
-
- /* "Mirror" the ROM addresses below 1MB. */
sim_do_command (sd, "memory region 0,0x100000");
+ sim_do_command (sd, "memory region 0x40000000,0x100000");
/* getopt will print the error message so we just have to exit if this fails.
FIXME: Hmmm... in the case of gdb we need getopt to call
@@ -1079,6 +937,117 @@ sim_open (kind, cb, abfd, argv)
return 0;
}
+ hw = hw_tree_create (sd, "core");
+ hw_tree_parse (hw, "/");
+ if (STATE_VERBOSE_P (sd))
+ hw_tree_parse (hw, "/trace? true");
+
+
+ /* interrupt controller */
+
+ hw_tree_parse (hw, "/mn103int@0x34000100");
+ if (STATE_VERBOSE_P (sd))
+ hw_tree_parse (hw, "/mn103int/trace? true");
+ hw_tree_parse (hw, "/mn103int/reg 0x34000100 0x68 0x34000200 0x8 0x3400280 0x8");
+
+ /* NMI input's */
+ hw_tree_parse (hw, "/glue@0x30000000");
+ if (STATE_VERBOSE_P (sd))
+ hw_tree_parse (hw, "/glue@0x30000000/trace? true");
+ hw_tree_parse (hw, "/glue@0x30000000/reg 0x30000000 16");
+ hw_tree_parse (hw, "/glue@0x30000000 > int1 nmirq /mn103int");
+ hw_tree_parse (hw, "/glue@0x30000000 > int2 watchdog /mn103int");
+ hw_tree_parse (hw, "/glue@0x30000000 > int3 syserr /mn103int");
+
+ /* NMI output */
+ hw_tree_parse (hw, "/mn103int > nmi int0 /glue@0x30000000");
+
+ /* ACK input */
+ hw_tree_parse (hw, "/glue@0x30002000");
+ if (STATE_VERBOSE_P (sd))
+ hw_tree_parse (hw, "/glue@0x30002000/trace? true");
+ hw_tree_parse (hw, "/glue@0x30002000/reg 0x30002000 4");
+ hw_tree_parse (hw, "/glue@0x30002000 > int ack /mn103int");
+
+ /* LEVEL output */
+ hw_tree_parse (hw, "/glue@0x30004000");
+ if (STATE_VERBOSE_P (sd))
+ hw_tree_parse (hw, "/glue@0x30004000/trace? true");
+ hw_tree_parse (hw, "/glue@0x30004000/reg 0x30004000 4");
+ hw_tree_parse (hw, "/mn103int > level int /glue@0x30004000");
+
+ /* A bunch of interrupt inputs */
+ hw_tree_parse (hw, "/glue@0x30006000");
+ if (STATE_VERBOSE_P (sd))
+ hw_tree_parse (hw, "/glue@0x30006000/trace? true");
+ hw_tree_parse (hw, "/glue@0x30006000/reg 0x30006000 16");
+ hw_tree_parse (hw, "/glue@0x30006000 > int0 irq-0 /mn103int");
+ hw_tree_parse (hw, "/glue@0x30006000 > int1 irq-1 /mn103int");
+ hw_tree_parse (hw, "/glue@0x30006000 > int2 irq-2 /mn103int");
+ hw_tree_parse (hw, "/glue@0x30006000 > int3 irq-3 /mn103int");
+
+
+ /* processor interrupt device */
+
+ /* the device */
+ hw_tree_parse (hw, "/mn103cpu@0x20000000");
+ if (STATE_VERBOSE_P (sd))
+ hw_tree_parse (hw, "/mn103cpu@0x20000000/trace? true");
+ hw_tree_parse (hw, "/mn103cpu@0x20000000/reg 0x20000000 0x42");
+
+ /* DEBUG: ACK output wired upto a glue device */
+ hw_tree_parse (hw, "/glue@0x20002000");
+ if (STATE_VERBOSE_P (sd))
+ hw_tree_parse (hw, "/glue@0x20002000/trace? true");
+ hw_tree_parse (hw, "/glue@0x20002000/reg 0x20002000 4");
+ hw_tree_parse (hw, "/mn103cpu > ack int0 /glue@0x20002000");
+
+ /* DEBUG: RESET/NMI/LEVEL wired up to a glue device */
+ hw_tree_parse (hw, "/glue@0x20004000");
+ if (STATE_VERBOSE_P (sd))
+ hw_tree_parse (hw, "/glue@0x20004000/trace? true");
+ hw_tree_parse (hw, "/glue@0x20004000/reg 0x20004000 12");
+ hw_tree_parse (hw, "/glue@0x20004000 > int0 reset /mn103cpu");
+ hw_tree_parse (hw, "/glue@0x20004000 > int1 nmi /mn103cpu");
+ hw_tree_parse (hw, "/glue@0x20004000 > int2 level /mn103cpu");
+
+ /* The processor wired up to the real interrupt controller */
+ hw_tree_parse (hw, "/mn103cpu > ack ack /mn103int");
+ hw_tree_parse (hw, "/mn103int > level level /mn103cpu");
+ hw_tree_parse (hw, "/mn103int > nmi nmi /mn103cpu");
+
+
+ /* PAL */
+
+ /* the device */
+ hw_tree_parse (hw, "/pal@0x31000000");
+ if (STATE_VERBOSE_P (sd))
+ hw_tree_parse (hw, "/pal@0x31000000/trace? true");
+ hw_tree_parse (hw, "/pal@0x31000000/reg 0x31000000 64");
+
+ /* DEBUG: PAL wired up to a glue device */
+ hw_tree_parse (hw, "/glue@0x31002000");
+ if (STATE_VERBOSE_P (sd))
+ hw_tree_parse (hw, "/glue@0x31002000/trace? true");
+ hw_tree_parse (hw, "/glue@0x31002000/reg 0x31002000 16");
+ hw_tree_parse (hw, "/pal@0x31000000 > countdown int0 /glue@0x31002000");
+ hw_tree_parse (hw, "/pal@0x31000000 > timer int1 /glue@0x31002000");
+ hw_tree_parse (hw, "/pal@0x31000000 > int int2 /glue@0x31002000");
+ hw_tree_parse (hw, "/glue@0x31002000 > int0 int3 /glue@0x31002000");
+ hw_tree_parse (hw, "/glue@0x31002000 > int1 int3 /glue@0x31002000");
+ hw_tree_parse (hw, "/glue@0x31002000 > int2 int3 /glue@0x31002000");
+
+ /* The PAL wired up to the real interrupt controller */
+ hw_tree_parse (hw, "/pal@0x31000000 > countdown irq-0 /mn103int");
+ hw_tree_parse (hw, "/pal@0x31000000 > timer irq-1 /mn103int");
+ hw_tree_parse (hw, "/pal@0x31000000 > int irq-2 /mn103int");
+
+
+
+ hw_tree_finish (hw);
+ if (STATE_VERBOSE_P (sd))
+ hw_tree_print (hw);
+
/* check for/establish the a reference program image */
if (sim_analyze_program (sd,
(STATE_PROG_ARGV (sd) != NULL