2 /* Simulator for the MIPS architecture.
4 This file is part of the MIPS sim
6 THIS SOFTWARE IS NOT COPYRIGHTED
8 Cygnus offers the following for use in the public domain. Cygnus
9 makes no warranty with regard to the software or it's performance
10 and the user accepts the software "AS IS" with all faults.
12 CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
13 THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 The IDT monitor (found on the VR4300 board), seems to lie about
19 register contents. It seems to treat the registers as sign-extended
20 32-bit values. This cause *REAL* problems when single-stepping 64-bit
28 #include "sim-utils.h"
29 #include "sim-options.h"
30 #include "sim-assert.h"
56 #include "libiberty.h"
58 #include "gdb/callback.h" /* GDB simulator callback interface */
59 #include "gdb/remote-sim.h" /* GDB simulator interface */
61 char* pr_addr (SIM_ADDR addr
);
62 char* pr_uword64 (uword64 addr
);
65 /* Within interp.c we refer to the sim_state and sim_cpu directly. */
70 /* The following reserved instruction value is used when a simulator
71 trap is required. NOTE: Care must be taken, since this value may be
72 used in later revisions of the MIPS ISA. */
74 #define RSVD_INSTRUCTION (0x00000039)
75 #define RSVD_INSTRUCTION_MASK (0xFC00003F)
77 #define RSVD_INSTRUCTION_ARG_SHIFT 6
78 #define RSVD_INSTRUCTION_ARG_MASK 0xFFFFF
81 /* Bits in the Debug register */
82 #define Debug_DBD 0x80000000 /* Debug Branch Delay */
83 #define Debug_DM 0x40000000 /* Debug Mode */
84 #define Debug_DBp 0x00000002 /* Debug Breakpoint indicator */
86 /*---------------------------------------------------------------------------*/
87 /*-- GDB simulator interface ------------------------------------------------*/
88 /*---------------------------------------------------------------------------*/
90 static void ColdReset (SIM_DESC sd
);
92 /*---------------------------------------------------------------------------*/
96 #define DELAYSLOT() {\
97 if (STATE & simDELAYSLOT)\
98 sim_io_eprintf(sd,"Delay slot already activated (branch in delay slot?)\n");\
99 STATE |= simDELAYSLOT;\
102 #define JALDELAYSLOT() {\
104 STATE |= simJALDELAYSLOT;\
108 STATE &= ~simDELAYSLOT;\
109 STATE |= simSKIPNEXT;\
112 #define CANCELDELAYSLOT() {\
114 STATE &= ~(simDELAYSLOT | simJALDELAYSLOT);\
117 #define INDELAYSLOT() ((STATE & simDELAYSLOT) != 0)
118 #define INJALDELAYSLOT() ((STATE & simJALDELAYSLOT) != 0)
120 /* Note that the monitor code essentially assumes this layout of memory.
121 If you change these, change the monitor code, too. */
122 /* FIXME Currently addresses are truncated to 32-bits, see
123 mips/sim-main.c:address_translation(). If that changes, then these
124 values will need to be extended, and tested for more carefully. */
125 #define K0BASE (0x80000000)
126 #define K0SIZE (0x20000000)
127 #define K1BASE (0xA0000000)
128 #define K1SIZE (0x20000000)
130 /* Simple run-time monitor support.
132 We emulate the monitor by placing magic reserved instructions at
133 the monitor's entry points; when we hit these instructions, instead
134 of raising an exception (as we would normally), we look at the
135 instruction and perform the appropriate monitory operation.
137 `*_monitor_base' are the physical addresses at which the corresponding
138 monitor vectors are located. `0' means none. By default,
140 The RSVD_INSTRUCTION... macros specify the magic instructions we
141 use at the monitor entry points. */
142 static int firmware_option_p
= 0;
143 static SIM_ADDR idt_monitor_base
= 0xBFC00000;
144 static SIM_ADDR pmon_monitor_base
= 0xBFC00500;
145 static SIM_ADDR lsipmon_monitor_base
= 0xBFC00200;
147 static SIM_RC
sim_firmware_command (SIM_DESC sd
, char* arg
);
149 #define MEM_SIZE (8 << 20) /* 8 MBytes */
153 static char *tracefile
= "trace.din"; /* default filename for trace log */
154 FILE *tracefh
= NULL
;
155 static void open_trace (SIM_DESC sd
);
157 #define open_trace(sd)
160 static const char * get_insn_name (sim_cpu
*, int);
162 /* simulation target board. NULL=canonical */
163 static char* board
= NULL
;
166 static DECLARE_OPTION_HANDLER (mips_option_handler
);
169 OPTION_DINERO_TRACE
= OPTION_START
,
176 static int display_mem_info
= 0;
179 mips_option_handler (SIM_DESC sd
, sim_cpu
*cpu
, int opt
, char *arg
,
185 case OPTION_DINERO_TRACE
: /* ??? */
187 /* Eventually the simTRACE flag could be treated as a toggle, to
188 allow external control of the program points being traced
189 (i.e. only from main onwards, excluding the run-time setup,
191 for (cpu_nr
= 0; cpu_nr
< MAX_NR_PROCESSORS
; cpu_nr
++)
193 sim_cpu
*cpu
= STATE_CPU (sd
, cpu_nr
);
196 else if (strcmp (arg
, "yes") == 0)
198 else if (strcmp (arg
, "no") == 0)
200 else if (strcmp (arg
, "on") == 0)
202 else if (strcmp (arg
, "off") == 0)
206 fprintf (stderr
, "Unrecognized dinero-trace option `%s'\n", arg
);
211 #else /* !WITH_TRACE_ANY_P */
213 Simulator constructed without dinero tracing support (for performance).\n\
214 Re-compile simulator with \"-DWITH_TRACE_ANY_P\" to enable this option.\n");
216 #endif /* !WITH_TRACE_ANY_P */
218 case OPTION_DINERO_FILE
:
220 if (optarg
!= NULL
) {
222 tmp
= (char *)malloc(strlen(optarg
) + 1);
225 sim_io_printf(sd
,"Failed to allocate buffer for tracefile name \"%s\"\n",optarg
);
231 sim_io_printf(sd
,"Placing trace information into file \"%s\"\n",tracefile
);
234 #endif /* WITH_TRACE_ANY_P */
237 case OPTION_FIRMWARE
:
238 return sim_firmware_command (sd
, arg
);
244 board
= zalloc(strlen(arg
) + 1);
250 case OPTION_INFO_MEMORY
:
251 display_mem_info
= 1;
259 static const OPTION mips_options
[] =
261 { {"dinero-trace", optional_argument
, NULL
, OPTION_DINERO_TRACE
},
262 '\0', "on|off", "Enable dinero tracing",
263 mips_option_handler
},
264 { {"dinero-file", required_argument
, NULL
, OPTION_DINERO_FILE
},
265 '\0', "FILE", "Write dinero trace to FILE",
266 mips_option_handler
},
267 { {"firmware", required_argument
, NULL
, OPTION_FIRMWARE
},
268 '\0', "[idt|pmon|lsipmon|none][@ADDRESS]", "Emulate ROM monitor",
269 mips_option_handler
},
270 { {"board", required_argument
, NULL
, OPTION_BOARD
},
271 '\0', "none" /* rely on compile-time string concatenation for other options */
273 #define BOARD_JMR3904 "jmr3904"
275 #define BOARD_JMR3904_PAL "jmr3904pal"
276 "|" BOARD_JMR3904_PAL
277 #define BOARD_JMR3904_DEBUG "jmr3904debug"
278 "|" BOARD_JMR3904_DEBUG
279 #define BOARD_BSP "bsp"
282 , "Customize simulation for a particular board.", mips_option_handler
},
284 /* These next two options have the same names as ones found in the
285 memory_options[] array in common/sim-memopt.c. This is because
286 the intention is to provide an alternative handler for those two
287 options. We need an alternative handler because the memory
288 regions are not set up until after the command line arguments
289 have been parsed, and so we cannot display the memory info whilst
290 processing the command line. There is a hack in sim_open to
291 remove these handlers when we want the real --memory-info option
293 { { "info-memory", no_argument
, NULL
, OPTION_INFO_MEMORY
},
294 '\0', NULL
, "List configured memory regions", mips_option_handler
},
295 { { "memory-info", no_argument
, NULL
, OPTION_INFO_MEMORY
},
296 '\0', NULL
, NULL
, mips_option_handler
},
298 { {NULL
, no_argument
, NULL
, 0}, '\0', NULL
, NULL
, NULL
}
302 int interrupt_pending
;
305 interrupt_event (SIM_DESC sd
, void *data
)
307 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
308 address_word cia
= CPU_PC_GET (cpu
);
311 interrupt_pending
= 0;
312 SignalExceptionInterrupt (1); /* interrupt "1" */
314 else if (!interrupt_pending
)
315 sim_events_schedule (sd
, 1, interrupt_event
, data
);
319 /*---------------------------------------------------------------------------*/
320 /*-- Device registration hook -----------------------------------------------*/
321 /*---------------------------------------------------------------------------*/
322 static void device_init(SIM_DESC sd
) {
324 extern void register_devices(SIM_DESC
);
325 register_devices(sd
);
329 /*---------------------------------------------------------------------------*/
330 /*-- GDB simulator interface ------------------------------------------------*/
331 /*---------------------------------------------------------------------------*/
334 mips_pc_get (sim_cpu
*cpu
)
340 mips_pc_set (sim_cpu
*cpu
, sim_cia pc
)
346 sim_open (SIM_OPEN_KIND kind
, host_callback
*cb
, struct bfd
*abfd
, char **argv
)
349 SIM_DESC sd
= sim_state_alloc (kind
, cb
);
352 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
354 /* The cpu data is kept in a separately allocated chunk of memory. */
355 if (sim_cpu_alloc_all (sd
, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK
)
358 cpu
= STATE_CPU (sd
, 0); /* FIXME */
360 /* FIXME: watchpoints code shouldn't need this */
361 STATE_WATCHPOINTS (sd
)->pc
= &(PC
);
362 STATE_WATCHPOINTS (sd
)->sizeof_pc
= sizeof (PC
);
363 STATE_WATCHPOINTS (sd
)->interrupt_handler
= interrupt_event
;
365 /* Initialize the mechanism for doing insn profiling. */
366 CPU_INSN_NAME (cpu
) = get_insn_name
;
367 CPU_MAX_INSNS (cpu
) = nr_itable_entries
;
371 if (sim_pre_argv_init (sd
, argv
[0]) != SIM_RC_OK
)
373 sim_add_option_table (sd
, NULL
, mips_options
);
376 /* getopt will print the error message so we just have to exit if this fails.
377 FIXME: Hmmm... in the case of gdb we need getopt to call
379 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
381 /* Uninstall the modules to avoid memory leaks,
382 file descriptor leaks, etc. */
383 sim_module_uninstall (sd
);
387 /* handle board-specific memory maps */
390 /* Allocate core managed memory */
391 sim_memopt
*entry
, *match
= NULL
;
392 address_word mem_size
= 0;
395 /* For compatibility with the old code - under this (at level one)
396 are the kernel spaces K0 & K1. Both of these map to a single
397 smaller sub region */
398 sim_do_command(sd
," memory region 0x7fff8000,0x8000") ; /* MTZ- 32 k stack */
400 /* Look for largest memory region defined on command-line at
402 for (entry
= STATE_MEMOPT (sd
); entry
!= NULL
; entry
= entry
->next
)
404 /* If we find an entry at address 0, then we will end up
405 allocating a new buffer in the "memory alias" command
406 below. The region at address 0 will be deleted. */
407 address_word size
= (entry
->modulo
!= 0
408 ? entry
->modulo
: entry
->nr_bytes
);
410 && (!match
|| entry
->level
< match
->level
))
412 else if (entry
->addr
== K0BASE
|| entry
->addr
== K1BASE
)
417 for (alias
= entry
->alias
; alias
!= NULL
; alias
= alias
->next
)
420 && (!match
|| entry
->level
< match
->level
))
422 else if (alias
->addr
== K0BASE
|| alias
->addr
== K1BASE
)
432 /* Get existing memory region size. */
433 mem_size
= (match
->modulo
!= 0
434 ? match
->modulo
: match
->nr_bytes
);
435 /* Delete old region. */
436 sim_do_commandf (sd
, "memory delete %d:0x%lx@%d",
437 match
->space
, match
->addr
, match
->level
);
439 else if (mem_size
== 0)
441 /* Limit to KSEG1 size (512MB) */
442 if (mem_size
> K1SIZE
)
444 /* memory alias K1BASE@1,K1SIZE%MEMSIZE,K0BASE */
445 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x",
446 K1BASE
, K1SIZE
, (long)mem_size
, K0BASE
);
451 else if (board
!= NULL
452 && (strcmp(board
, BOARD_BSP
) == 0))
456 STATE_ENVIRONMENT (sd
) = OPERATING_ENVIRONMENT
;
458 /* ROM: 0x9FC0_0000 - 0x9FFF_FFFF and 0xBFC0_0000 - 0xBFFF_FFFF */
459 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx,0x%0x",
461 4 * 1024 * 1024, /* 4 MB */
464 /* SRAM: 0x8000_0000 - 0x803F_FFFF and 0xA000_0000 - 0xA03F_FFFF */
465 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx,0x%0x",
467 4 * 1024 * 1024, /* 4 MB */
470 /* DRAM: 0x8800_0000 - 0x89FF_FFFF and 0xA800_0000 - 0xA9FF_FFFF */
471 for (i
=0; i
<8; i
++) /* 32 MB total */
473 unsigned size
= 4 * 1024 * 1024; /* 4 MB */
474 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx,0x%0x",
475 0x88000000 + (i
* size
),
477 0xA8000000 + (i
* size
));
481 else if (board
!= NULL
482 && (strcmp(board
, BOARD_JMR3904
) == 0 ||
483 strcmp(board
, BOARD_JMR3904_PAL
) == 0 ||
484 strcmp(board
, BOARD_JMR3904_DEBUG
) == 0))
486 /* match VIRTUAL memory layout of JMR-TX3904 board */
489 /* --- disable monitor unless forced on by user --- */
491 if (! firmware_option_p
)
493 idt_monitor_base
= 0;
494 pmon_monitor_base
= 0;
495 lsipmon_monitor_base
= 0;
498 /* --- environment --- */
500 STATE_ENVIRONMENT (sd
) = OPERATING_ENVIRONMENT
;
504 /* ROM: 0x9FC0_0000 - 0x9FFF_FFFF and 0xBFC0_0000 - 0xBFFF_FFFF */
505 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx,0x%0x",
507 4 * 1024 * 1024, /* 4 MB */
510 /* SRAM: 0x8000_0000 - 0x803F_FFFF and 0xA000_0000 - 0xA03F_FFFF */
511 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx,0x%0x",
513 4 * 1024 * 1024, /* 4 MB */
516 /* DRAM: 0x8800_0000 - 0x89FF_FFFF and 0xA800_0000 - 0xA9FF_FFFF */
517 for (i
=0; i
<8; i
++) /* 32 MB total */
519 unsigned size
= 4 * 1024 * 1024; /* 4 MB */
520 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx,0x%0x",
521 0x88000000 + (i
* size
),
523 0xA8000000 + (i
* size
));
526 /* Dummy memory regions for unsimulated devices - sorted by address */
528 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xB1000000, 0x400); /* ISA I/O */
529 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xB2100000, 0x004); /* ISA ctl */
530 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xB2500000, 0x004); /* LED/switch */
531 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xB2700000, 0x004); /* RTC */
532 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xB3C00000, 0x004); /* RTC */
533 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xFFFF8000, 0x900); /* DRAMC */
534 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xFFFF9000, 0x200); /* EBIF */
535 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xFFFFE000, 0x01c); /* EBIF */
536 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xFFFFF500, 0x300); /* PIO */
539 /* --- simulated devices --- */
540 sim_hw_parse (sd
, "/tx3904irc@0xffffc000/reg 0xffffc000 0x20");
541 sim_hw_parse (sd
, "/tx3904cpu");
542 sim_hw_parse (sd
, "/tx3904tmr@0xfffff000/reg 0xfffff000 0x100");
543 sim_hw_parse (sd
, "/tx3904tmr@0xfffff100/reg 0xfffff100 0x100");
544 sim_hw_parse (sd
, "/tx3904tmr@0xfffff200/reg 0xfffff200 0x100");
545 sim_hw_parse (sd
, "/tx3904sio@0xfffff300/reg 0xfffff300 0x100");
547 /* FIXME: poking at dv-sockser internals, use tcp backend if
548 --sockser_addr option was given.*/
549 extern char* sockser_addr
;
550 if(sockser_addr
== NULL
)
551 sim_hw_parse (sd
, "/tx3904sio@0xfffff300/backend stdio");
553 sim_hw_parse (sd
, "/tx3904sio@0xfffff300/backend tcp");
555 sim_hw_parse (sd
, "/tx3904sio@0xfffff400/reg 0xfffff400 0x100");
556 sim_hw_parse (sd
, "/tx3904sio@0xfffff400/backend stdio");
558 /* -- device connections --- */
559 sim_hw_parse (sd
, "/tx3904irc > ip level /tx3904cpu");
560 sim_hw_parse (sd
, "/tx3904tmr@0xfffff000 > int tmr0 /tx3904irc");
561 sim_hw_parse (sd
, "/tx3904tmr@0xfffff100 > int tmr1 /tx3904irc");
562 sim_hw_parse (sd
, "/tx3904tmr@0xfffff200 > int tmr2 /tx3904irc");
563 sim_hw_parse (sd
, "/tx3904sio@0xfffff300 > int sio0 /tx3904irc");
564 sim_hw_parse (sd
, "/tx3904sio@0xfffff400 > int sio1 /tx3904irc");
566 /* add PAL timer & I/O module */
567 if(! strcmp(board
, BOARD_JMR3904_PAL
))
570 sim_hw_parse (sd
, "/pal@0xffff0000");
571 sim_hw_parse (sd
, "/pal@0xffff0000/reg 0xffff0000 64");
573 /* wire up interrupt ports to irc */
574 sim_hw_parse (sd
, "/pal@0x31000000 > countdown tmr0 /tx3904irc");
575 sim_hw_parse (sd
, "/pal@0x31000000 > timer tmr1 /tx3904irc");
576 sim_hw_parse (sd
, "/pal@0x31000000 > int int0 /tx3904irc");
579 if(! strcmp(board
, BOARD_JMR3904_DEBUG
))
581 /* -- DEBUG: glue interrupt generators --- */
582 sim_hw_parse (sd
, "/glue@0xffff0000/reg 0xffff0000 0x50");
583 sim_hw_parse (sd
, "/glue@0xffff0000 > int0 int0 /tx3904irc");
584 sim_hw_parse (sd
, "/glue@0xffff0000 > int1 int1 /tx3904irc");
585 sim_hw_parse (sd
, "/glue@0xffff0000 > int2 int2 /tx3904irc");
586 sim_hw_parse (sd
, "/glue@0xffff0000 > int3 int3 /tx3904irc");
587 sim_hw_parse (sd
, "/glue@0xffff0000 > int4 int4 /tx3904irc");
588 sim_hw_parse (sd
, "/glue@0xffff0000 > int5 int5 /tx3904irc");
589 sim_hw_parse (sd
, "/glue@0xffff0000 > int6 int6 /tx3904irc");
590 sim_hw_parse (sd
, "/glue@0xffff0000 > int7 int7 /tx3904irc");
591 sim_hw_parse (sd
, "/glue@0xffff0000 > int8 dmac0 /tx3904irc");
592 sim_hw_parse (sd
, "/glue@0xffff0000 > int9 dmac1 /tx3904irc");
593 sim_hw_parse (sd
, "/glue@0xffff0000 > int10 dmac2 /tx3904irc");
594 sim_hw_parse (sd
, "/glue@0xffff0000 > int11 dmac3 /tx3904irc");
595 sim_hw_parse (sd
, "/glue@0xffff0000 > int12 sio0 /tx3904irc");
596 sim_hw_parse (sd
, "/glue@0xffff0000 > int13 sio1 /tx3904irc");
597 sim_hw_parse (sd
, "/glue@0xffff0000 > int14 tmr0 /tx3904irc");
598 sim_hw_parse (sd
, "/glue@0xffff0000 > int15 tmr1 /tx3904irc");
599 sim_hw_parse (sd
, "/glue@0xffff0000 > int16 tmr2 /tx3904irc");
600 sim_hw_parse (sd
, "/glue@0xffff0000 > int17 nmi /tx3904cpu");
607 if (display_mem_info
)
609 struct option_list
* ol
;
610 struct option_list
* prev
;
612 /* This is a hack. We want to execute the real --memory-info command
613 line switch which is handled in common/sim-memopts.c, not the
614 override we have defined in this file. So we remove the
615 mips_options array from the state options list. This is safe
616 because we have now processed all of the command line. */
617 for (ol
= STATE_OPTIONS (sd
), prev
= NULL
;
619 prev
= ol
, ol
= ol
->next
)
620 if (ol
->options
== mips_options
)
623 SIM_ASSERT (ol
!= NULL
);
626 STATE_OPTIONS (sd
) = ol
->next
;
628 prev
->next
= ol
->next
;
630 sim_do_commandf (sd
, "memory-info");
633 /* check for/establish the a reference program image */
634 if (sim_analyze_program (sd
,
635 (STATE_PROG_ARGV (sd
) != NULL
636 ? *STATE_PROG_ARGV (sd
)
640 sim_module_uninstall (sd
);
644 /* Configure/verify the target byte order and other runtime
645 configuration options */
646 if (sim_config (sd
) != SIM_RC_OK
)
648 sim_module_uninstall (sd
);
652 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
654 /* Uninstall the modules to avoid memory leaks,
655 file descriptor leaks, etc. */
656 sim_module_uninstall (sd
);
660 /* verify assumptions the simulator made about the host type system.
661 This macro does not return if there is a problem */
662 SIM_ASSERT (sizeof(int) == (4 * sizeof(char)));
663 SIM_ASSERT (sizeof(word64
) == (8 * sizeof(char)));
665 /* This is NASTY, in that we are assuming the size of specific
669 for (rn
= 0; (rn
< (LAST_EMBED_REGNUM
+ 1)); rn
++)
672 cpu
->register_widths
[rn
] = WITH_TARGET_WORD_BITSIZE
;
673 else if ((rn
>= FGR_BASE
) && (rn
< (FGR_BASE
+ NR_FGR
)))
674 cpu
->register_widths
[rn
] = WITH_TARGET_FLOATING_POINT_BITSIZE
;
675 else if ((rn
>= 33) && (rn
<= 37))
676 cpu
->register_widths
[rn
] = WITH_TARGET_WORD_BITSIZE
;
677 else if ((rn
== SRIDX
)
680 || ((rn
>= 72) && (rn
<= 89)))
681 cpu
->register_widths
[rn
] = 32;
683 cpu
->register_widths
[rn
] = 0;
689 if (STATE
& simTRACE
)
693 sim_io_eprintf (sd, "idt@%x pmon@%x lsipmon@%x\n",
696 lsipmon_monitor_base);
699 /* Write the monitor trap address handlers into the monitor (eeprom)
700 address space. This can only be done once the target endianness
701 has been determined. */
702 if (idt_monitor_base
!= 0)
705 unsigned idt_monitor_size
= 1 << 11;
707 /* the default monitor region */
708 sim_do_commandf (sd
, "memory region 0x%x,0x%x",
709 idt_monitor_base
, idt_monitor_size
);
711 /* Entry into the IDT monitor is via fixed address vectors, and
712 not using machine instructions. To avoid clashing with use of
713 the MIPS TRAP system, we place our own (simulator specific)
714 "undefined" instructions into the relevant vector slots. */
715 for (loop
= 0; (loop
< idt_monitor_size
); loop
+= 4)
717 address_word vaddr
= (idt_monitor_base
+ loop
);
718 unsigned32 insn
= (RSVD_INSTRUCTION
|
719 (((loop
>> 2) & RSVD_INSTRUCTION_ARG_MASK
)
720 << RSVD_INSTRUCTION_ARG_SHIFT
));
722 sim_write (sd
, vaddr
, (unsigned char *)&insn
, sizeof (insn
));
726 if ((pmon_monitor_base
!= 0) || (lsipmon_monitor_base
!= 0))
728 /* The PMON monitor uses the same address space, but rather than
729 branching into it the address of a routine is loaded. We can
730 cheat for the moment, and direct the PMON routine to IDT style
731 instructions within the monitor space. This relies on the IDT
732 monitor not using the locations from 0xBFC00500 onwards as its
735 for (loop
= 0; (loop
< 24); loop
++)
737 unsigned32 value
= ((0x500 - 8) / 8); /* default UNDEFINED reason code */
753 value
= ((0x500 - 16) / 8); /* not an IDT reason code */
755 case 8: /* cliexit */
758 case 11: /* flush_cache */
763 SIM_ASSERT (idt_monitor_base
!= 0);
764 value
= ((unsigned int) idt_monitor_base
+ (value
* 8));
767 if (pmon_monitor_base
!= 0)
769 address_word vaddr
= (pmon_monitor_base
+ (loop
* 4));
770 sim_write (sd
, vaddr
, (unsigned char *)&value
, sizeof (value
));
773 if (lsipmon_monitor_base
!= 0)
775 address_word vaddr
= (lsipmon_monitor_base
+ (loop
* 4));
776 sim_write (sd
, vaddr
, (unsigned char *)&value
, sizeof (value
));
780 /* Write an abort sequence into the TRAP (common) exception vector
781 addresses. This is to catch code executing a TRAP (et.al.)
782 instruction without installing a trap handler. */
783 if ((idt_monitor_base
!= 0) ||
784 (pmon_monitor_base
!= 0) ||
785 (lsipmon_monitor_base
!= 0))
787 unsigned32 halt
[2] = { 0x2404002f /* addiu r4, r0, 47 */,
788 HALT_INSTRUCTION
/* BREAK */ };
791 sim_write (sd
, 0x80000000, (unsigned char *) halt
, sizeof (halt
));
792 sim_write (sd
, 0x80000180, (unsigned char *) halt
, sizeof (halt
));
793 sim_write (sd
, 0x80000200, (unsigned char *) halt
, sizeof (halt
));
794 /* XXX: Write here unconditionally? */
795 sim_write (sd
, 0xBFC00200, (unsigned char *) halt
, sizeof (halt
));
796 sim_write (sd
, 0xBFC00380, (unsigned char *) halt
, sizeof (halt
));
797 sim_write (sd
, 0xBFC00400, (unsigned char *) halt
, sizeof (halt
));
801 /* CPU specific initialization. */
802 for (i
= 0; i
< MAX_NR_PROCESSORS
; ++i
)
804 SIM_CPU
*cpu
= STATE_CPU (sd
, i
);
806 CPU_PC_FETCH (cpu
) = mips_pc_get
;
807 CPU_PC_STORE (cpu
) = mips_pc_set
;
815 open_trace (SIM_DESC sd
)
817 tracefh
= fopen(tracefile
,"wb+");
820 sim_io_eprintf(sd
,"Failed to create file \"%s\", writing trace information to stderr.\n",tracefile
);
826 /* Return name of an insn, used by insn profiling. */
828 get_insn_name (sim_cpu
*cpu
, int i
)
830 return itable
[i
].name
;
834 mips_sim_close (SIM_DESC sd
, int quitting
)
837 if (tracefh
!= NULL
&& tracefh
!= stderr
)
844 sim_store_register (SIM_DESC sd
, int rn
, unsigned char *memory
, int length
)
846 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
847 /* NOTE: gdb (the client) stores registers in target byte order
848 while the simulator uses host byte order */
850 sim_io_printf(sd
,"sim_store_register(%d,*memory=0x%s);\n",rn
,pr_addr(*((SIM_ADDR
*)memory
)));
853 /* Unfortunately this suffers from the same problem as the register
854 numbering one. We need to know what the width of each logical
855 register number is for the architecture being simulated. */
857 if (cpu
->register_widths
[rn
] == 0)
859 sim_io_eprintf(sd
,"Invalid register width for %d (register store ignored)\n",rn
);
865 if (rn
>= FGR_BASE
&& rn
< FGR_BASE
+ NR_FGR
)
867 cpu
->fpr_state
[rn
- FGR_BASE
] = fmt_uninterpreted
;
868 if (cpu
->register_widths
[rn
] == 32)
872 cpu
->fgr
[rn
- FGR_BASE
] =
873 (unsigned32
) T2H_8 (*(unsigned64
*)memory
);
878 cpu
->fgr
[rn
- FGR_BASE
] = T2H_4 (*(unsigned32
*)memory
);
886 cpu
->fgr
[rn
- FGR_BASE
] = T2H_8 (*(unsigned64
*)memory
);
891 cpu
->fgr
[rn
- FGR_BASE
] = T2H_4 (*(unsigned32
*)memory
);
897 if (cpu
->register_widths
[rn
] == 32)
902 (unsigned32
) T2H_8 (*(unsigned64
*)memory
);
907 cpu
->registers
[rn
] = T2H_4 (*(unsigned32
*)memory
);
915 cpu
->registers
[rn
] = T2H_8 (*(unsigned64
*)memory
);
920 cpu
->registers
[rn
] = (signed32
) T2H_4(*(unsigned32
*)memory
);
929 sim_fetch_register (SIM_DESC sd
, int rn
, unsigned char *memory
, int length
)
931 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
932 /* NOTE: gdb (the client) stores registers in target byte order
933 while the simulator uses host byte order */
935 #if 0 /* FIXME: doesn't compile */
936 sim_io_printf(sd
,"sim_fetch_register(%d=0x%s,mem) : place simulator registers into memory\n",rn
,pr_addr(registers
[rn
]));
940 if (cpu
->register_widths
[rn
] == 0)
942 sim_io_eprintf (sd
, "Invalid register width for %d (register fetch ignored)\n",rn
);
948 /* Any floating point register */
949 if (rn
>= FGR_BASE
&& rn
< FGR_BASE
+ NR_FGR
)
951 if (cpu
->register_widths
[rn
] == 32)
955 *(unsigned64
*)memory
=
956 H2T_8 ((unsigned32
) (cpu
->fgr
[rn
- FGR_BASE
]));
961 *(unsigned32
*)memory
= H2T_4 (cpu
->fgr
[rn
- FGR_BASE
]);
969 *(unsigned64
*)memory
= H2T_8 (cpu
->fgr
[rn
- FGR_BASE
]);
974 *(unsigned32
*)memory
= H2T_4 ((unsigned32
)(cpu
->fgr
[rn
- FGR_BASE
]));
980 if (cpu
->register_widths
[rn
] == 32)
984 *(unsigned64
*)memory
=
985 H2T_8 ((unsigned32
) (cpu
->registers
[rn
]));
990 *(unsigned32
*)memory
= H2T_4 ((unsigned32
)(cpu
->registers
[rn
]));
998 *(unsigned64
*)memory
=
999 H2T_8 ((unsigned64
) (cpu
->registers
[rn
]));
1004 *(unsigned32
*)memory
= H2T_4 ((unsigned32
)(cpu
->registers
[rn
]));
1013 sim_create_inferior (SIM_DESC sd
, struct bfd
*abfd
, char **argv
, char **env
)
1017 #if 0 /* FIXME: doesn't compile */
1018 printf("DBG: sim_create_inferior entered: start_address = 0x%s\n",
1027 /* override PC value set by ColdReset () */
1029 for (cpu_nr
= 0; cpu_nr
< sim_engine_nr_cpus (sd
); cpu_nr
++)
1031 sim_cpu
*cpu
= STATE_CPU (sd
, cpu_nr
);
1032 CPU_PC_SET (cpu
, (unsigned64
) bfd_get_start_address (abfd
));
1036 #if 0 /* def DEBUG */
1039 /* We should really place the argv slot values into the argument
1040 registers, and onto the stack as required. However, this
1041 assumes that we have a stack defined, which is not
1042 necessarily true at the moment. */
1044 sim_io_printf(sd
,"sim_create_inferior() : passed arguments ignored\n");
1045 for (cptr
= argv
; (cptr
&& *cptr
); cptr
++)
1046 printf("DBG: arg \"%s\"\n",*cptr
);
1053 /*---------------------------------------------------------------------------*/
1054 /*-- Private simulator support interface ------------------------------------*/
1055 /*---------------------------------------------------------------------------*/
1057 /* Read a null terminated string from memory, return in a buffer */
1059 fetch_str (SIM_DESC sd
,
1065 while (sim_read (sd
, addr
+ nr
, &null
, 1) == 1 && null
!= 0)
1067 buf
= NZALLOC (char, nr
+ 1);
1068 sim_read (sd
, addr
, (unsigned char *)buf
, nr
);
1073 /* Implements the "sim firmware" command:
1074 sim firmware NAME[@ADDRESS] --- emulate ROM monitor named NAME.
1075 NAME can be idt, pmon, or lsipmon. If omitted, ADDRESS
1076 defaults to the normal address for that monitor.
1077 sim firmware none --- don't emulate any ROM monitor. Useful
1078 if you need a clean address space. */
1080 sim_firmware_command (SIM_DESC sd
, char *arg
)
1082 int address_present
= 0;
1085 /* Signal occurrence of this option. */
1086 firmware_option_p
= 1;
1088 /* Parse out the address, if present. */
1090 char *p
= strchr (arg
, '@');
1094 address_present
= 1;
1095 p
++; /* skip over @ */
1097 address
= strtoul (p
, &q
, 0);
1100 sim_io_printf (sd
, "Invalid address given to the"
1101 "`sim firmware NAME@ADDRESS' command: %s\n",
1108 address_present
= 0;
1109 address
= -1; /* Dummy value. */
1113 if (! strncmp (arg
, "idt", 3))
1115 idt_monitor_base
= address_present
? address
: 0xBFC00000;
1116 pmon_monitor_base
= 0;
1117 lsipmon_monitor_base
= 0;
1119 else if (! strncmp (arg
, "pmon", 4))
1121 /* pmon uses indirect calls. Hook into implied idt. */
1122 pmon_monitor_base
= address_present
? address
: 0xBFC00500;
1123 idt_monitor_base
= pmon_monitor_base
- 0x500;
1124 lsipmon_monitor_base
= 0;
1126 else if (! strncmp (arg
, "lsipmon", 7))
1128 /* lsipmon uses indirect calls. Hook into implied idt. */
1129 pmon_monitor_base
= 0;
1130 lsipmon_monitor_base
= address_present
? address
: 0xBFC00200;
1131 idt_monitor_base
= lsipmon_monitor_base
- 0x200;
1133 else if (! strncmp (arg
, "none", 4))
1135 if (address_present
)
1138 "The `sim firmware none' command does "
1139 "not take an `ADDRESS' argument.\n");
1142 idt_monitor_base
= 0;
1143 pmon_monitor_base
= 0;
1144 lsipmon_monitor_base
= 0;
1148 sim_io_printf (sd
, "\
1149 Unrecognized name given to the `sim firmware NAME' command: %s\n\
1150 Recognized firmware names are: `idt', `pmon', `lsipmon', and `none'.\n",
1160 /* Simple monitor interface (currently setup for the IDT and PMON monitors) */
1162 sim_monitor (SIM_DESC sd
,
1165 unsigned int reason
)
1168 printf("DBG: sim_monitor: entered (reason = %d)\n",reason
);
1171 /* The IDT monitor actually allows two instructions per vector
1172 slot. However, the simulator currently causes a trap on each
1173 individual instruction. We cheat, and lose the bottom bit. */
1176 /* The following callback functions are available, however the
1177 monitor we are simulating does not make use of them: get_errno,
1178 isatty, lseek, rename, system, time and unlink */
1182 case 6: /* int open(char *path,int flags) */
1184 char *path
= fetch_str (sd
, A0
);
1185 V0
= sim_io_open (sd
, path
, (int)A1
);
1190 case 7: /* int read(int file,char *ptr,int len) */
1194 char *buf
= zalloc (nr
);
1195 V0
= sim_io_read (sd
, fd
, buf
, nr
);
1196 sim_write (sd
, A1
, (unsigned char *)buf
, nr
);
1201 case 8: /* int write(int file,char *ptr,int len) */
1205 char *buf
= zalloc (nr
);
1206 sim_read (sd
, A1
, (unsigned char *)buf
, nr
);
1207 V0
= sim_io_write (sd
, fd
, buf
, nr
);
1209 sim_io_flush_stdout (sd
);
1211 sim_io_flush_stderr (sd
);
1216 case 10: /* int close(int file) */
1218 V0
= sim_io_close (sd
, (int)A0
);
1222 case 2: /* Densan monitor: char inbyte(int waitflag) */
1224 if (A0
== 0) /* waitflag == NOWAIT */
1225 V0
= (unsigned_word
)-1;
1227 /* Drop through to case 11 */
1229 case 11: /* char inbyte(void) */
1232 /* ensure that all output has gone... */
1233 sim_io_flush_stdout (sd
);
1234 if (sim_io_read_stdin (sd
, &tmp
, sizeof(char)) != sizeof(char))
1236 sim_io_error(sd
,"Invalid return from character read");
1237 V0
= (unsigned_word
)-1;
1240 V0
= (unsigned_word
)tmp
;
1244 case 3: /* Densan monitor: void co(char chr) */
1245 case 12: /* void outbyte(char chr) : write a byte to "stdout" */
1247 char tmp
= (char)(A0
& 0xFF);
1248 sim_io_write_stdout (sd
, &tmp
, sizeof(char));
1252 case 17: /* void _exit() */
1254 sim_io_eprintf (sd
, "sim_monitor(17): _exit(int reason) to be coded\n");
1255 sim_engine_halt (SD
, CPU
, NULL
, NULL_CIA
, sim_exited
,
1256 (unsigned int)(A0
& 0xFFFFFFFF));
1260 case 28: /* PMON flush_cache */
1263 case 55: /* void get_mem_info(unsigned int *ptr) */
1264 /* in: A0 = pointer to three word memory location */
1265 /* out: [A0 + 0] = size */
1266 /* [A0 + 4] = instruction cache size */
1267 /* [A0 + 8] = data cache size */
1270 unsigned_4 zero
= 0;
1271 address_word mem_size
;
1272 sim_memopt
*entry
, *match
= NULL
;
1274 /* Search for memory region mapped to KSEG0 or KSEG1. */
1275 for (entry
= STATE_MEMOPT (sd
);
1277 entry
= entry
->next
)
1279 if ((entry
->addr
== K0BASE
|| entry
->addr
== K1BASE
)
1280 && (!match
|| entry
->level
< match
->level
))
1285 for (alias
= entry
->alias
;
1287 alias
= alias
->next
)
1288 if ((alias
->addr
== K0BASE
|| alias
->addr
== K1BASE
)
1289 && (!match
|| entry
->level
< match
->level
))
1294 /* Get region size, limit to KSEG1 size (512MB). */
1295 SIM_ASSERT (match
!= NULL
);
1296 mem_size
= (match
->modulo
!= 0
1297 ? match
->modulo
: match
->nr_bytes
);
1298 if (mem_size
> K1SIZE
)
1303 sim_write (sd
, A0
+ 0, (unsigned char *)&value
, 4);
1304 sim_write (sd
, A0
+ 4, (unsigned char *)&zero
, 4);
1305 sim_write (sd
, A0
+ 8, (unsigned char *)&zero
, 4);
1306 /* sim_io_eprintf (sd, "sim: get_mem_info() deprecated\n"); */
1310 case 158: /* PMON printf */
1311 /* in: A0 = pointer to format string */
1312 /* A1 = optional argument 1 */
1313 /* A2 = optional argument 2 */
1314 /* A3 = optional argument 3 */
1316 /* The following is based on the PMON printf source */
1318 address_word s
= A0
;
1320 signed_word
*ap
= &A1
; /* 1st argument */
1321 /* This isn't the quickest way, since we call the host print
1322 routine for every character almost. But it does avoid
1323 having to allocate and manage a temporary string buffer. */
1324 /* TODO: Include check that we only use three arguments (A1,
1326 while (sim_read (sd
, s
++, &c
, 1) && c
!= '\0')
1331 enum {FMT_RJUST
, FMT_LJUST
, FMT_RJUST0
, FMT_CENTER
} fmt
= FMT_RJUST
;
1332 int width
= 0, trunc
= 0, haddot
= 0, longlong
= 0;
1333 while (sim_read (sd
, s
++, &c
, 1) && c
!= '\0')
1335 if (strchr ("dobxXulscefg%", c
))
1350 else if (c
>= '1' && c
<= '9')
1354 while (sim_read (sd
, s
++, &c
, 1) == 1 && isdigit (c
))
1357 n
= (unsigned int)strtol(tmp
,NULL
,10);
1370 sim_io_printf (sd
, "%%");
1375 address_word p
= *ap
++;
1377 while (sim_read (sd
, p
++, &ch
, 1) == 1 && ch
!= '\0')
1378 sim_io_printf(sd
, "%c", ch
);
1381 sim_io_printf(sd
,"(null)");
1384 sim_io_printf (sd
, "%c", (int)*ap
++);
1389 sim_read (sd
, s
++, &c
, 1);
1393 sim_read (sd
, s
++, &c
, 1);
1396 if (strchr ("dobxXu", c
))
1398 word64 lv
= (word64
) *ap
++;
1400 sim_io_printf(sd
,"<binary not supported>");
1403 sprintf (tmp
, "%%%s%c", longlong
? "ll" : "", c
);
1405 sim_io_printf(sd
, tmp
, lv
);
1407 sim_io_printf(sd
, tmp
, (int)lv
);
1410 else if (strchr ("eEfgG", c
))
1412 double dbl
= *(double*)(ap
++);
1413 sprintf (tmp
, "%%%d.%d%c", width
, trunc
, c
);
1414 sim_io_printf (sd
, tmp
, dbl
);
1420 sim_io_printf(sd
, "%c", c
);
1426 /* Unknown reason. */
1432 /* Store a word into memory. */
1435 store_word (SIM_DESC sd
,
1441 address_word paddr
= vaddr
;
1443 if ((vaddr
& 3) != 0)
1444 SignalExceptionAddressStore ();
1447 const uword64 mask
= 7;
1451 paddr
= (paddr
& ~mask
) | ((paddr
& mask
) ^ (ReverseEndian
<< 2));
1452 byte
= (vaddr
& mask
) ^ (BigEndianCPU
<< 2);
1453 memval
= ((uword64
) val
) << (8 * byte
);
1454 StoreMemory (AccessLength_WORD
, memval
, 0, paddr
, vaddr
,
1459 /* Load a word from memory. */
1462 load_word (SIM_DESC sd
,
1467 if ((vaddr
& 3) != 0)
1469 SIM_CORE_SIGNAL (SD
, cpu
, cia
, read_map
, AccessLength_WORD
+1, vaddr
, read_transfer
, sim_core_unaligned_signal
);
1473 address_word paddr
= vaddr
;
1474 const uword64 mask
= 0x7;
1475 const unsigned int reverse
= ReverseEndian
? 1 : 0;
1476 const unsigned int bigend
= BigEndianCPU
? 1 : 0;
1480 paddr
= (paddr
& ~mask
) | ((paddr
& mask
) ^ (reverse
<< 2));
1481 LoadMemory (&memval
, NULL
, AccessLength_WORD
, paddr
, vaddr
, isDATA
,
1483 byte
= (vaddr
& mask
) ^ (bigend
<< 2);
1484 return EXTEND32 (memval
>> (8 * byte
));
1490 /* Simulate the mips16 entry and exit pseudo-instructions. These
1491 would normally be handled by the reserved instruction exception
1492 code, but for ease of simulation we just handle them directly. */
1495 mips16_entry (SIM_DESC sd
,
1500 int aregs
, sregs
, rreg
;
1503 printf("DBG: mips16_entry: entered (insn = 0x%08X)\n",insn
);
1506 aregs
= (insn
& 0x700) >> 8;
1507 sregs
= (insn
& 0x0c0) >> 6;
1508 rreg
= (insn
& 0x020) >> 5;
1510 /* This should be checked by the caller. */
1519 /* This is the entry pseudo-instruction. */
1521 for (i
= 0; i
< aregs
; i
++)
1522 store_word (SD
, CPU
, cia
, (uword64
) (SP
+ 4 * i
), GPR
[i
+ 4]);
1530 store_word (SD
, CPU
, cia
, (uword64
) tsp
, RA
);
1533 for (i
= 0; i
< sregs
; i
++)
1536 store_word (SD
, CPU
, cia
, (uword64
) tsp
, GPR
[16 + i
]);
1544 /* This is the exit pseudo-instruction. */
1551 RA
= load_word (SD
, CPU
, cia
, (uword64
) tsp
);
1554 for (i
= 0; i
< sregs
; i
++)
1557 GPR
[i
+ 16] = load_word (SD
, CPU
, cia
, (uword64
) tsp
);
1562 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
1566 FGR
[0] = WORD64LO (GPR
[4]);
1567 FPR_STATE
[0] = fmt_uninterpreted
;
1569 else if (aregs
== 6)
1571 FGR
[0] = WORD64LO (GPR
[5]);
1572 FGR
[1] = WORD64LO (GPR
[4]);
1573 FPR_STATE
[0] = fmt_uninterpreted
;
1574 FPR_STATE
[1] = fmt_uninterpreted
;
1583 /*-- trace support ----------------------------------------------------------*/
1585 /* The trace support is provided (if required) in the memory accessing
1586 routines. Since we are also providing the architecture specific
1587 features, the architecture simulation code can also deal with
1588 notifying the trace world of cache flushes, etc. Similarly we do
1589 not need to provide profiling support in the simulator engine,
1590 since we can sample in the instruction fetch control loop. By
1591 defining the trace manifest, we add tracing as a run-time
1594 #if WITH_TRACE_ANY_P
1595 /* Tracing by default produces "din" format (as required by
1596 dineroIII). Each line of such a trace file *MUST* have a din label
1597 and address field. The rest of the line is ignored, so comments can
1598 be included if desired. The first field is the label which must be
1599 one of the following values:
1604 3 escape record (treated as unknown access type)
1605 4 escape record (causes cache flush)
1607 The address field is a 32bit (lower-case) hexadecimal address
1608 value. The address should *NOT* be preceded by "0x".
1610 The size of the memory transfer is not important when dealing with
1611 cache lines (as long as no more than a cache line can be
1612 transferred in a single operation :-), however more information
1613 could be given following the dineroIII requirement to allow more
1614 complete memory and cache simulators to provide better
1615 results. i.e. the University of Pisa has a cache simulator that can
1616 also take bus size and speed as (variable) inputs to calculate
1617 complete system performance (a much more useful ability when trying
1618 to construct an end product, rather than a processor). They
1619 currently have an ARM version of their tool called ChARM. */
1623 dotrace (SIM_DESC sd
,
1631 if (STATE
& simTRACE
) {
1633 fprintf(tracefh
,"%d %s ; width %d ; ",
1637 va_start(ap
,comment
);
1638 vfprintf(tracefh
,comment
,ap
);
1640 fprintf(tracefh
,"\n");
1642 /* NOTE: Since the "din" format will only accept 32bit addresses, and
1643 we may be generating 64bit ones, we should put the hi-32bits of the
1644 address into the comment field. */
1646 /* TODO: Provide a buffer for the trace lines. We can then avoid
1647 performing writes until the buffer is filled, or the file is
1650 /* NOTE: We could consider adding a comment field to the "din" file
1651 produced using type 3 markers (unknown access). This would then
1652 allow information about the program that the "din" is for, and
1653 the MIPs world that was being simulated, to be placed into the
1658 #endif /* WITH_TRACE_ANY_P */
1660 /*---------------------------------------------------------------------------*/
1661 /*-- simulator engine -------------------------------------------------------*/
1662 /*---------------------------------------------------------------------------*/
1665 ColdReset (SIM_DESC sd
)
1668 for (cpu_nr
= 0; cpu_nr
< sim_engine_nr_cpus (sd
); cpu_nr
++)
1670 sim_cpu
*cpu
= STATE_CPU (sd
, cpu_nr
);
1671 /* RESET: Fixed PC address: */
1672 PC
= (unsigned_word
) UNSIGNED64 (0xFFFFFFFFBFC00000);
1673 /* The reset vector address is in the unmapped, uncached memory space. */
1675 SR
&= ~(status_SR
| status_TS
| status_RP
);
1676 SR
|= (status_ERL
| status_BEV
);
1678 /* Cheat and allow access to the complete register set immediately */
1679 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
1680 && WITH_TARGET_WORD_BITSIZE
== 64)
1681 SR
|= status_FR
; /* 64bit registers */
1683 /* Ensure that any instructions with pending register updates are
1685 PENDING_INVALIDATE();
1687 /* Initialise the FPU registers to the unknown state */
1688 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
1691 for (rn
= 0; (rn
< 32); rn
++)
1692 FPR_STATE
[rn
] = fmt_uninterpreted
;
1695 /* Initialise the Config0 register. */
1696 C0_CONFIG
= 0x80000000 /* Config1 present */
1697 | 2; /* KSEG0 uncached */
1698 if (WITH_TARGET_WORD_BITSIZE
== 64)
1700 /* FIXME Currently mips/sim-main.c:address_translation()
1701 truncates all addresses to 32-bits. */
1702 if (0 && WITH_TARGET_ADDRESS_BITSIZE
== 64)
1703 C0_CONFIG
|= (2 << 13); /* MIPS64, 64-bit addresses */
1705 C0_CONFIG
|= (1 << 13); /* MIPS64, 32-bit addresses */
1708 C0_CONFIG
|= 0x00008000; /* Big Endian */
1715 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
1716 /* Signal an exception condition. This will result in an exception
1717 that aborts the instruction. The instruction operation pseudocode
1718 will never see a return from this function call. */
1721 signal_exception (SIM_DESC sd
,
1729 sim_io_printf(sd
,"DBG: SignalException(%d) PC = 0x%s\n",exception
,pr_addr(cia
));
1732 /* Ensure that any active atomic read/modify/write operation will fail: */
1735 /* Save registers before interrupt dispatching */
1736 #ifdef SIM_CPU_EXCEPTION_TRIGGER
1737 SIM_CPU_EXCEPTION_TRIGGER(sd
, cpu
, cia
);
1740 switch (exception
) {
1742 case DebugBreakPoint
:
1743 if (! (Debug
& Debug_DM
))
1749 Debug
|= Debug_DBD
; /* signaled from within in delay slot */
1750 DEPC
= cia
- 4; /* reference the branch instruction */
1754 Debug
&= ~Debug_DBD
; /* not signaled from within a delay slot */
1758 Debug
|= Debug_DM
; /* in debugging mode */
1759 Debug
|= Debug_DBp
; /* raising a DBp exception */
1761 sim_engine_restart (SD
, CPU
, NULL
, NULL_CIA
);
1765 case ReservedInstruction
:
1768 unsigned int instruction
;
1769 va_start(ap
,exception
);
1770 instruction
= va_arg(ap
,unsigned int);
1772 /* Provide simple monitor support using ReservedInstruction
1773 exceptions. The following code simulates the fixed vector
1774 entry points into the IDT monitor by causing a simulator
1775 trap, performing the monitor operation, and returning to
1776 the address held in the $ra register (standard PCS return
1777 address). This means we only need to pre-load the vector
1778 space with suitable instruction values. For systems were
1779 actual trap instructions are used, we would not need to
1780 perform this magic. */
1781 if ((instruction
& RSVD_INSTRUCTION_MASK
) == RSVD_INSTRUCTION
)
1783 int reason
= (instruction
>> RSVD_INSTRUCTION_ARG_SHIFT
) & RSVD_INSTRUCTION_ARG_MASK
;
1784 if (!sim_monitor (SD
, CPU
, cia
, reason
))
1785 sim_io_error (sd
, "sim_monitor: unhandled reason = %d, pc = 0x%s\n", reason
, pr_addr (cia
));
1787 /* NOTE: This assumes that a branch-and-link style
1788 instruction was used to enter the vector (which is the
1789 case with the current IDT monitor). */
1790 sim_engine_restart (SD
, CPU
, NULL
, RA
);
1792 /* Look for the mips16 entry and exit instructions, and
1793 simulate a handler for them. */
1794 else if ((cia
& 1) != 0
1795 && (instruction
& 0xf81f) == 0xe809
1796 && (instruction
& 0x0c0) != 0x0c0)
1798 mips16_entry (SD
, CPU
, cia
, instruction
);
1799 sim_engine_restart (sd
, NULL
, NULL
, NULL_CIA
);
1801 /* else fall through to normal exception processing */
1802 sim_io_eprintf(sd
,"ReservedInstruction at PC = 0x%s\n", pr_addr (cia
));
1806 /* Store exception code into current exception id variable (used
1809 /* TODO: If not simulating exceptions then stop the simulator
1810 execution. At the moment we always stop the simulation. */
1812 #ifdef SUBTARGET_R3900
1813 /* update interrupt-related registers */
1815 /* insert exception code in bits 6:2 */
1816 CAUSE
= LSMASKED32(CAUSE
, 31, 7) | LSINSERTED32(exception
, 6, 2);
1817 /* shift IE/KU history bits left */
1818 SR
= LSMASKED32(SR
, 31, 4) | LSINSERTED32(LSEXTRACTED32(SR
, 3, 0), 5, 2);
1820 if (STATE
& simDELAYSLOT
)
1822 STATE
&= ~simDELAYSLOT
;
1824 EPC
= (cia
- 4); /* reference the branch instruction */
1829 if (SR
& status_BEV
)
1830 PC
= (signed)0xBFC00000 + 0x180;
1832 PC
= (signed)0x80000000 + 0x080;
1834 /* See figure 5-17 for an outline of the code below */
1835 if (! (SR
& status_EXL
))
1837 CAUSE
= (exception
<< 2);
1838 if (STATE
& simDELAYSLOT
)
1840 STATE
&= ~simDELAYSLOT
;
1842 EPC
= (cia
- 4); /* reference the branch instruction */
1846 /* FIXME: TLB et.al. */
1847 /* vector = 0x180; */
1851 CAUSE
= (exception
<< 2);
1852 /* vector = 0x180; */
1855 /* Store exception code into current exception id variable (used
1858 if (SR
& status_BEV
)
1859 PC
= (signed)0xBFC00200 + 0x180;
1861 PC
= (signed)0x80000000 + 0x180;
1864 switch ((CAUSE
>> 2) & 0x1F)
1867 /* Interrupts arrive during event processing, no need to
1873 #ifdef SUBTARGET_3900
1874 /* Exception vector: BEV=0 BFC00000 / BEF=1 BFC00000 */
1875 PC
= (signed)0xBFC00000;
1876 #endif /* SUBTARGET_3900 */
1879 case TLBModification
:
1884 case InstructionFetch
:
1886 /* The following is so that the simulator will continue from the
1887 exception handler address. */
1888 sim_engine_halt (SD
, CPU
, NULL
, PC
,
1889 sim_stopped
, SIM_SIGBUS
);
1891 case ReservedInstruction
:
1892 case CoProcessorUnusable
:
1894 sim_engine_halt (SD
, CPU
, NULL
, PC
,
1895 sim_stopped
, SIM_SIGILL
);
1897 case IntegerOverflow
:
1899 sim_engine_halt (SD
, CPU
, NULL
, PC
,
1900 sim_stopped
, SIM_SIGFPE
);
1903 sim_engine_halt (SD
, CPU
, NULL
, PC
, sim_stopped
, SIM_SIGTRAP
);
1908 sim_engine_restart (SD
, CPU
, NULL
, PC
);
1913 sim_engine_halt (SD
, CPU
, NULL
, PC
,
1914 sim_stopped
, SIM_SIGTRAP
);
1916 default: /* Unknown internal exception */
1918 sim_engine_halt (SD
, CPU
, NULL
, PC
,
1919 sim_stopped
, SIM_SIGABRT
);
1923 case SimulatorFault
:
1927 va_start(ap
,exception
);
1928 msg
= va_arg(ap
,char *);
1930 sim_engine_abort (SD
, CPU
, NULL_CIA
,
1931 "FATAL: Simulator error \"%s\"\n",msg
);
1940 /* This function implements what the MIPS32 and MIPS64 ISAs define as
1941 "UNPREDICTABLE" behaviour.
1943 About UNPREDICTABLE behaviour they say: "UNPREDICTABLE results
1944 may vary from processor implementation to processor implementation,
1945 instruction to instruction, or as a function of time on the same
1946 implementation or instruction. Software can never depend on results
1947 that are UNPREDICTABLE. ..." (MIPS64 Architecture for Programmers
1948 Volume II, The MIPS64 Instruction Set. MIPS Document MD00087 revision
1951 For UNPREDICTABLE behaviour, we print a message, if possible print
1952 the offending instructions mips.igen instruction name (provided by
1953 the caller), and stop the simulator.
1955 XXX FIXME: eventually, stopping the simulator should be made conditional
1956 on a command-line option. */
1958 unpredictable_action(sim_cpu
*cpu
, address_word cia
)
1960 SIM_DESC sd
= CPU_STATE(cpu
);
1962 sim_io_eprintf(sd
, "UNPREDICTABLE: PC = 0x%s\n", pr_addr (cia
));
1963 sim_engine_halt (SD
, CPU
, NULL
, cia
, sim_stopped
, SIM_SIGABRT
);
1967 /*-- co-processor support routines ------------------------------------------*/
1970 CoProcPresent(unsigned int coproc_number
)
1972 /* Return TRUE if simulator provides a model for the given co-processor number */
1977 cop_lw (SIM_DESC sd
,
1982 unsigned int memword
)
1987 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
1990 printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%s\n",memword
,pr_addr(memword
));
1992 StoreFPR(coproc_reg
,fmt_uninterpreted_32
,(uword64
)memword
);
1997 #if 0 /* this should be controlled by a configuration option */
1998 sim_io_printf(sd
,"COP_LW(%d,%d,0x%08X) at PC = 0x%s : TODO (architecture specific)\n",coproc_num
,coproc_reg
,memword
,pr_addr(cia
));
2007 cop_ld (SIM_DESC sd
,
2016 printf("DBG: COP_LD: coproc_num = %d, coproc_reg = %d, value = 0x%s : PC = 0x%s\n", coproc_num
, coproc_reg
, pr_uword64(memword
), pr_addr(cia
) );
2019 switch (coproc_num
) {
2021 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
2023 StoreFPR(coproc_reg
,fmt_uninterpreted_64
,memword
);
2028 #if 0 /* this message should be controlled by a configuration option */
2029 sim_io_printf(sd
,"COP_LD(%d,%d,0x%s) at PC = 0x%s : TODO (architecture specific)\n",coproc_num
,coproc_reg
,pr_addr(memword
),pr_addr(cia
));
2041 cop_sw (SIM_DESC sd
,
2047 unsigned int value
= 0;
2052 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
2054 value
= (unsigned int)ValueFPR(coproc_reg
,fmt_uninterpreted_32
);
2059 #if 0 /* should be controlled by configuration option */
2060 sim_io_printf(sd
,"COP_SW(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num
,coproc_reg
,pr_addr(cia
));
2069 cop_sd (SIM_DESC sd
,
2079 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
2081 value
= ValueFPR(coproc_reg
,fmt_uninterpreted_64
);
2086 #if 0 /* should be controlled by configuration option */
2087 sim_io_printf(sd
,"COP_SD(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num
,coproc_reg
,pr_addr(cia
));
2099 decode_coproc (SIM_DESC sd
,
2102 unsigned int instruction
,
2111 case 0: /* standard CPU control and cache registers */
2113 /* R4000 Users Manual (second edition) lists the following CP0
2115 CODE><-RT><RD-><--TAIL--->
2116 DMFC0 Doubleword Move From CP0 (VR4100 = 01000000001tttttddddd00000000000)
2117 DMTC0 Doubleword Move To CP0 (VR4100 = 01000000101tttttddddd00000000000)
2118 MFC0 word Move From CP0 (VR4100 = 01000000000tttttddddd00000000000)
2119 MTC0 word Move To CP0 (VR4100 = 01000000100tttttddddd00000000000)
2120 TLBR Read Indexed TLB Entry (VR4100 = 01000010000000000000000000000001)
2121 TLBWI Write Indexed TLB Entry (VR4100 = 01000010000000000000000000000010)
2122 TLBWR Write Random TLB Entry (VR4100 = 01000010000000000000000000000110)
2123 TLBP Probe TLB for Matching Entry (VR4100 = 01000010000000000000000000001000)
2124 CACHE Cache operation (VR4100 = 101111bbbbbpppppiiiiiiiiiiiiiiii)
2125 ERET Exception return (VR4100 = 01000010000000000000000000011000)
2127 if (((op
== cp0_mfc0
) || (op
== cp0_mtc0
) /* MFC0 / MTC0 */
2128 || (op
== cp0_dmfc0
) || (op
== cp0_dmtc0
)) /* DMFC0 / DMTC0 */
2131 switch (rd
) /* NOTEs: Standard CP0 registers */
2133 /* 0 = Index R4000 VR4100 VR4300 */
2134 /* 1 = Random R4000 VR4100 VR4300 */
2135 /* 2 = EntryLo0 R4000 VR4100 VR4300 */
2136 /* 3 = EntryLo1 R4000 VR4100 VR4300 */
2137 /* 4 = Context R4000 VR4100 VR4300 */
2138 /* 5 = PageMask R4000 VR4100 VR4300 */
2139 /* 6 = Wired R4000 VR4100 VR4300 */
2140 /* 8 = BadVAddr R4000 VR4100 VR4300 */
2141 /* 9 = Count R4000 VR4100 VR4300 */
2142 /* 10 = EntryHi R4000 VR4100 VR4300 */
2143 /* 11 = Compare R4000 VR4100 VR4300 */
2144 /* 12 = SR R4000 VR4100 VR4300 */
2145 #ifdef SUBTARGET_R3900
2147 /* 3 = Config R3900 */
2149 /* 7 = Cache R3900 */
2151 /* 15 = PRID R3900 */
2157 /* 8 = BadVAddr R4000 VR4100 VR4300 */
2158 if (op
== cp0_mfc0
|| op
== cp0_dmfc0
)
2159 GPR
[rt
] = (signed_word
) (signed_address
) COP0_BADVADDR
;
2161 COP0_BADVADDR
= GPR
[rt
];
2164 #endif /* SUBTARGET_R3900 */
2166 if (op
== cp0_mfc0
|| op
== cp0_dmfc0
)
2171 /* 13 = Cause R4000 VR4100 VR4300 */
2173 if (op
== cp0_mfc0
|| op
== cp0_dmfc0
)
2178 /* 14 = EPC R4000 VR4100 VR4300 */
2180 if (op
== cp0_mfc0
|| op
== cp0_dmfc0
)
2181 GPR
[rt
] = (signed_word
) (signed_address
) EPC
;
2185 /* 15 = PRId R4000 VR4100 VR4300 */
2186 #ifdef SUBTARGET_R3900
2189 if (op
== cp0_mfc0
|| op
== cp0_dmfc0
)
2195 /* 16 = Config R4000 VR4100 VR4300 */
2197 if (op
== cp0_mfc0
|| op
== cp0_dmfc0
)
2198 GPR
[rt
] = C0_CONFIG
;
2200 /* only bottom three bits are writable */
2201 C0_CONFIG
= (C0_CONFIG
& ~0x7) | (GPR
[rt
] & 0x7);
2204 #ifdef SUBTARGET_R3900
2207 if (op
== cp0_mfc0
|| op
== cp0_dmfc0
)
2213 /* 17 = LLAddr R4000 VR4100 VR4300 */
2215 /* 18 = WatchLo R4000 VR4100 VR4300 */
2216 /* 19 = WatchHi R4000 VR4100 VR4300 */
2217 /* 20 = XContext R4000 VR4100 VR4300 */
2218 /* 26 = PErr or ECC R4000 VR4100 VR4300 */
2219 /* 27 = CacheErr R4000 VR4100 */
2220 /* 28 = TagLo R4000 VR4100 VR4300 */
2221 /* 29 = TagHi R4000 VR4100 VR4300 */
2222 /* 30 = ErrorEPC R4000 VR4100 VR4300 */
2223 if (STATE_VERBOSE_P(SD
))
2225 "Warning: PC 0x%lx:interp.c decode_coproc DEADC0DE\n",
2226 (unsigned long)cia
);
2227 GPR
[rt
] = 0xDEADC0DE; /* CPR[0,rd] */
2228 /* CPR[0,rd] = GPR[rt]; */
2230 if (op
== cp0_mfc0
|| op
== cp0_dmfc0
)
2231 GPR
[rt
] = (signed_word
) (signed32
) COP0_GPR
[rd
];
2233 COP0_GPR
[rd
] = GPR
[rt
];
2236 sim_io_printf(sd
,"Warning: MFC0 %d,%d ignored, PC=%08x (architecture specific)\n",rt
,rd
, (unsigned)cia
);
2238 sim_io_printf(sd
,"Warning: MTC0 %d,%d ignored, PC=%08x (architecture specific)\n",rt
,rd
, (unsigned)cia
);
2242 else if ((op
== cp0_mfc0
|| op
== cp0_dmfc0
)
2245 /* [D]MFC0 RT,C0_CONFIG,SEL */
2253 /* MIPS32 r/o Config1:
2256 /* MIPS16 implemented.
2257 XXX How to check configuration? */
2259 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
2260 /* MDMX & FPU implemented */
2264 /* MIPS32 r/o Config2:
2269 /* MIPS32 r/o Config3:
2270 SmartMIPS implemented. */
2276 else if (op
== cp0_eret
&& sel
== 0x18)
2279 if (SR
& status_ERL
)
2281 /* Oops, not yet available */
2282 sim_io_printf(sd
,"Warning: ERET when SR[ERL] set not handled yet");
2292 else if (op
== cp0_rfe
&& sel
== 0x10)
2295 #ifdef SUBTARGET_R3900
2296 /* TX39: Copy IEp/KUp -> IEc/KUc, and IEo/KUo -> IEp/KUp */
2298 /* shift IE/KU history bits right */
2299 SR
= LSMASKED32(SR
, 31, 4) | LSINSERTED32(LSEXTRACTED32(SR
, 5, 2), 3, 0);
2301 /* TODO: CACHE register */
2302 #endif /* SUBTARGET_R3900 */
2304 else if (op
== cp0_deret
&& sel
== 0x1F)
2312 sim_io_eprintf(sd
,"Unrecognised COP0 instruction 0x%08X at PC = 0x%s : No handler present\n",instruction
,pr_addr(cia
));
2313 /* TODO: When executing an ERET or RFE instruction we should
2314 clear LLBIT, to ensure that any out-standing atomic
2315 read/modify/write sequence fails. */
2319 case 2: /* co-processor 2 */
2326 sim_io_eprintf(sd
, "COP2 instruction 0x%08X at PC = 0x%s : No handler present\n",
2327 instruction
,pr_addr(cia
));
2332 case 1: /* should not occur (FPU co-processor) */
2333 case 3: /* should not occur (FPU co-processor) */
2334 SignalException(ReservedInstruction
,instruction
);
2342 /* This code copied from gdb's utils.c. Would like to share this code,
2343 but don't know of a common place where both could get to it. */
2345 /* Temporary storage using circular buffer */
2351 static char buf
[NUMCELLS
][CELLSIZE
];
2353 if (++cell
>=NUMCELLS
) cell
=0;
2357 /* Print routines to handle variable size regs, etc */
2359 /* Eliminate warning from compiler on 32-bit systems */
2360 static int thirty_two
= 32;
2363 pr_addr (SIM_ADDR addr
)
2365 char *paddr_str
=get_cell();
2366 switch (sizeof(addr
))
2369 sprintf(paddr_str
,"%08lx%08lx",
2370 (unsigned long)(addr
>>thirty_two
),(unsigned long)(addr
&0xffffffff));
2373 sprintf(paddr_str
,"%08lx",(unsigned long)addr
);
2376 sprintf(paddr_str
,"%04x",(unsigned short)(addr
&0xffff));
2379 sprintf(paddr_str
,"%x",addr
);
2385 pr_uword64 (uword64 addr
)
2387 char *paddr_str
=get_cell();
2388 sprintf(paddr_str
,"%08lx%08lx",
2389 (unsigned long)(addr
>>thirty_two
),(unsigned long)(addr
&0xffffffff));
2395 mips_core_signal (SIM_DESC sd
,
2401 transfer_type transfer
,
2402 sim_core_signals sig
)
2404 const char *copy
= (transfer
== read_transfer
? "read" : "write");
2405 address_word ip
= CIA_ADDR (cia
);
2409 case sim_core_unmapped_signal
:
2410 sim_io_eprintf (sd
, "mips-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
2412 (unsigned long) addr
, (unsigned long) ip
);
2413 COP0_BADVADDR
= addr
;
2414 SignalExceptionDataReference();
2417 case sim_core_unaligned_signal
:
2418 sim_io_eprintf (sd
, "mips-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n",
2420 (unsigned long) addr
, (unsigned long) ip
);
2421 COP0_BADVADDR
= addr
;
2422 if(transfer
== read_transfer
)
2423 SignalExceptionAddressLoad();
2425 SignalExceptionAddressStore();
2429 sim_engine_abort (sd
, cpu
, cia
,
2430 "mips_core_signal - internal error - bad switch");
2436 mips_cpu_exception_trigger(SIM_DESC sd
, sim_cpu
* cpu
, address_word cia
)
2438 ASSERT(cpu
!= NULL
);
2440 if(cpu
->exc_suspended
> 0)
2441 sim_io_eprintf(sd
, "Warning, nested exception triggered (%d)\n", cpu
->exc_suspended
);
2444 memcpy(cpu
->exc_trigger_registers
, cpu
->registers
, sizeof(cpu
->exc_trigger_registers
));
2445 cpu
->exc_suspended
= 0;
2449 mips_cpu_exception_suspend(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
2451 ASSERT(cpu
!= NULL
);
2453 if(cpu
->exc_suspended
> 0)
2454 sim_io_eprintf(sd
, "Warning, nested exception signal (%d then %d)\n",
2455 cpu
->exc_suspended
, exception
);
2457 memcpy(cpu
->exc_suspend_registers
, cpu
->registers
, sizeof(cpu
->exc_suspend_registers
));
2458 memcpy(cpu
->registers
, cpu
->exc_trigger_registers
, sizeof(cpu
->registers
));
2459 cpu
->exc_suspended
= exception
;
2463 mips_cpu_exception_resume(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
2465 ASSERT(cpu
!= NULL
);
2467 if(exception
== 0 && cpu
->exc_suspended
> 0)
2469 /* warn not for breakpoints */
2470 if(cpu
->exc_suspended
!= sim_signal_to_host(sd
, SIM_SIGTRAP
))
2471 sim_io_eprintf(sd
, "Warning, resuming but ignoring pending exception signal (%d)\n",
2472 cpu
->exc_suspended
);
2474 else if(exception
!= 0 && cpu
->exc_suspended
> 0)
2476 if(exception
!= cpu
->exc_suspended
)
2477 sim_io_eprintf(sd
, "Warning, resuming with mismatched exception signal (%d vs %d)\n",
2478 cpu
->exc_suspended
, exception
);
2480 memcpy(cpu
->registers
, cpu
->exc_suspend_registers
, sizeof(cpu
->registers
));
2482 else if(exception
!= 0 && cpu
->exc_suspended
== 0)
2484 sim_io_eprintf(sd
, "Warning, ignoring spontanous exception signal (%d)\n", exception
);
2486 cpu
->exc_suspended
= 0;
2490 /*---------------------------------------------------------------------------*/
2491 /*> EOF interp.c <*/