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
25 /* The TRACE manifests enable the provision of extra features. If they
26 are not defined then a simpler (quicker) simulator is constructed
27 without the required run-time checks, etc. */
28 #if 1 /* 0 to allow user build selection, 1 to force inclusion */
34 #include "sim-utils.h"
35 #include "sim-options.h"
36 #include "sim-assert.h"
62 #include "libiberty.h"
64 #include "gdb/callback.h" /* GDB simulator callback interface */
65 #include "gdb/remote-sim.h" /* GDB simulator interface */
73 char* pr_addr
PARAMS ((SIM_ADDR addr
));
74 char* pr_uword64
PARAMS ((uword64 addr
));
77 /* Within interp.c we refer to the sim_state and sim_cpu directly. */
82 /* The following reserved instruction value is used when a simulator
83 trap is required. NOTE: Care must be taken, since this value may be
84 used in later revisions of the MIPS ISA. */
86 #define RSVD_INSTRUCTION (0x00000005)
87 #define RSVD_INSTRUCTION_MASK (0xFC00003F)
89 #define RSVD_INSTRUCTION_ARG_SHIFT 6
90 #define RSVD_INSTRUCTION_ARG_MASK 0xFFFFF
93 /* Bits in the Debug register */
94 #define Debug_DBD 0x80000000 /* Debug Branch Delay */
95 #define Debug_DM 0x40000000 /* Debug Mode */
96 #define Debug_DBp 0x00000002 /* Debug Breakpoint indicator */
98 /*---------------------------------------------------------------------------*/
99 /*-- GDB simulator interface ------------------------------------------------*/
100 /*---------------------------------------------------------------------------*/
102 static void ColdReset
PARAMS((SIM_DESC sd
));
104 /*---------------------------------------------------------------------------*/
108 #define DELAYSLOT() {\
109 if (STATE & simDELAYSLOT)\
110 sim_io_eprintf(sd,"Delay slot already activated (branch in delay slot?)\n");\
111 STATE |= simDELAYSLOT;\
114 #define JALDELAYSLOT() {\
116 STATE |= simJALDELAYSLOT;\
120 STATE &= ~simDELAYSLOT;\
121 STATE |= simSKIPNEXT;\
124 #define CANCELDELAYSLOT() {\
126 STATE &= ~(simDELAYSLOT | simJALDELAYSLOT);\
129 #define INDELAYSLOT() ((STATE & simDELAYSLOT) != 0)
130 #define INJALDELAYSLOT() ((STATE & simJALDELAYSLOT) != 0)
132 /* Note that the monitor code essentially assumes this layout of memory.
133 If you change these, change the monitor code, too. */
134 /* FIXME Currently addresses are truncated to 32-bits, see
135 mips/sim-main.c:address_translation(). If that changes, then these
136 values will need to be extended, and tested for more carefully. */
137 #define K0BASE (0x80000000)
138 #define K0SIZE (0x20000000)
139 #define K1BASE (0xA0000000)
140 #define K1SIZE (0x20000000)
142 /* Simple run-time monitor support.
144 We emulate the monitor by placing magic reserved instructions at
145 the monitor's entry points; when we hit these instructions, instead
146 of raising an exception (as we would normally), we look at the
147 instruction and perform the appropriate monitory operation.
149 `*_monitor_base' are the physical addresses at which the corresponding
150 monitor vectors are located. `0' means none. By default,
152 The RSVD_INSTRUCTION... macros specify the magic instructions we
153 use at the monitor entry points. */
154 static int firmware_option_p
= 0;
155 static SIM_ADDR idt_monitor_base
= 0xBFC00000;
156 static SIM_ADDR pmon_monitor_base
= 0xBFC00500;
157 static SIM_ADDR lsipmon_monitor_base
= 0xBFC00200;
159 static SIM_RC
sim_firmware_command (SIM_DESC sd
, char* arg
);
162 #define MEM_SIZE (8 << 20) /* 8 MBytes */
166 static char *tracefile
= "trace.din"; /* default filename for trace log */
167 FILE *tracefh
= NULL
;
168 static void open_trace
PARAMS((SIM_DESC sd
));
171 static const char * get_insn_name (sim_cpu
*, int);
173 /* simulation target board. NULL=canonical */
174 static char* board
= NULL
;
177 static DECLARE_OPTION_HANDLER (mips_option_handler
);
180 OPTION_DINERO_TRACE
= OPTION_START
,
187 static int display_mem_info
= 0;
190 mips_option_handler (sd
, cpu
, opt
, arg
, is_command
)
200 case OPTION_DINERO_TRACE
: /* ??? */
202 /* Eventually the simTRACE flag could be treated as a toggle, to
203 allow external control of the program points being traced
204 (i.e. only from main onwards, excluding the run-time setup,
206 for (cpu_nr
= 0; cpu_nr
< MAX_NR_PROCESSORS
; cpu_nr
++)
208 sim_cpu
*cpu
= STATE_CPU (sd
, cpu_nr
);
211 else if (strcmp (arg
, "yes") == 0)
213 else if (strcmp (arg
, "no") == 0)
215 else if (strcmp (arg
, "on") == 0)
217 else if (strcmp (arg
, "off") == 0)
221 fprintf (stderr
, "Unrecognized dinero-trace option `%s'\n", arg
);
228 Simulator constructed without dinero tracing support (for performance).\n\
229 Re-compile simulator with \"-DTRACE\" to enable this option.\n");
233 case OPTION_DINERO_FILE
:
235 if (optarg
!= NULL
) {
237 tmp
= (char *)malloc(strlen(optarg
) + 1);
240 sim_io_printf(sd
,"Failed to allocate buffer for tracefile name \"%s\"\n",optarg
);
246 sim_io_printf(sd
,"Placing trace information into file \"%s\"\n",tracefile
);
252 case OPTION_FIRMWARE
:
253 return sim_firmware_command (sd
, arg
);
259 board
= zalloc(strlen(arg
) + 1);
265 case OPTION_INFO_MEMORY
:
266 display_mem_info
= 1;
274 static const OPTION mips_options
[] =
276 { {"dinero-trace", optional_argument
, NULL
, OPTION_DINERO_TRACE
},
277 '\0', "on|off", "Enable dinero tracing",
278 mips_option_handler
},
279 { {"dinero-file", required_argument
, NULL
, OPTION_DINERO_FILE
},
280 '\0', "FILE", "Write dinero trace to FILE",
281 mips_option_handler
},
282 { {"firmware", required_argument
, NULL
, OPTION_FIRMWARE
},
283 '\0', "[idt|pmon|lsipmon|none][@ADDRESS]", "Emulate ROM monitor",
284 mips_option_handler
},
285 { {"board", required_argument
, NULL
, OPTION_BOARD
},
286 '\0', "none" /* rely on compile-time string concatenation for other options */
288 #define BOARD_JMR3904 "jmr3904"
290 #define BOARD_JMR3904_PAL "jmr3904pal"
291 "|" BOARD_JMR3904_PAL
292 #define BOARD_JMR3904_DEBUG "jmr3904debug"
293 "|" BOARD_JMR3904_DEBUG
294 #define BOARD_BSP "bsp"
297 , "Customize simulation for a particular board.", mips_option_handler
},
299 /* These next two options have the same names as ones found in the
300 memory_options[] array in common/sim-memopt.c. This is because
301 the intention is to provide an alternative handler for those two
302 options. We need an alternative handler because the memory
303 regions are not set up until after the command line arguments
304 have been parsed, and so we cannot display the memory info whilst
305 processing the command line. There is a hack in sim_open to
306 remove these handlers when we want the real --memory-info option
308 { { "info-memory", no_argument
, NULL
, OPTION_INFO_MEMORY
},
309 '\0', NULL
, "List configured memory regions", mips_option_handler
},
310 { { "memory-info", no_argument
, NULL
, OPTION_INFO_MEMORY
},
311 '\0', NULL
, NULL
, mips_option_handler
},
313 { {NULL
, no_argument
, NULL
, 0}, '\0', NULL
, NULL
, NULL
}
317 int interrupt_pending
;
320 interrupt_event (SIM_DESC sd
, void *data
)
322 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
323 address_word cia
= CIA_GET (cpu
);
326 interrupt_pending
= 0;
327 SignalExceptionInterrupt (1); /* interrupt "1" */
329 else if (!interrupt_pending
)
330 sim_events_schedule (sd
, 1, interrupt_event
, data
);
334 /*---------------------------------------------------------------------------*/
335 /*-- Device registration hook -----------------------------------------------*/
336 /*---------------------------------------------------------------------------*/
337 static void device_init(SIM_DESC sd
) {
339 extern void register_devices(SIM_DESC
);
340 register_devices(sd
);
344 /*---------------------------------------------------------------------------*/
345 /*-- GDB simulator interface ------------------------------------------------*/
346 /*---------------------------------------------------------------------------*/
349 sim_open (kind
, cb
, abfd
, argv
)
355 SIM_DESC sd
= sim_state_alloc (kind
, cb
);
356 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
358 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
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 #ifdef SIM_HAVE_FLATMEM
403 mem_size
= STATE_MEM_SIZE (sd
);
405 for (entry
= STATE_MEMOPT (sd
); entry
!= NULL
; entry
= entry
->next
)
407 /* If we find an entry at address 0, then we will end up
408 allocating a new buffer in the "memory alias" command
409 below. The region at address 0 will be deleted. */
410 address_word size
= (entry
->modulo
!= 0
411 ? entry
->modulo
: entry
->nr_bytes
);
413 && (!match
|| entry
->level
< match
->level
))
415 else if (entry
->addr
== K0BASE
|| entry
->addr
== K1BASE
)
420 for (alias
= entry
->alias
; alias
!= NULL
; alias
= alias
->next
)
423 && (!match
|| entry
->level
< match
->level
))
425 else if (alias
->addr
== K0BASE
|| alias
->addr
== K1BASE
)
435 /* Get existing memory region size. */
436 mem_size
= (match
->modulo
!= 0
437 ? match
->modulo
: match
->nr_bytes
);
438 /* Delete old region. */
439 sim_do_commandf (sd
, "memory delete %d:0x%lx@%d",
440 match
->space
, match
->addr
, match
->level
);
442 else if (mem_size
== 0)
444 /* Limit to KSEG1 size (512MB) */
445 if (mem_size
> K1SIZE
)
447 /* memory alias K1BASE@1,K1SIZE%MEMSIZE,K0BASE */
448 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x",
449 K1BASE
, K1SIZE
, (long)mem_size
, K0BASE
);
454 else if (board
!= NULL
455 && (strcmp(board
, BOARD_BSP
) == 0))
459 STATE_ENVIRONMENT (sd
) = OPERATING_ENVIRONMENT
;
461 /* ROM: 0x9FC0_0000 - 0x9FFF_FFFF and 0xBFC0_0000 - 0xBFFF_FFFF */
462 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx,0x%0x",
464 4 * 1024 * 1024, /* 4 MB */
467 /* SRAM: 0x8000_0000 - 0x803F_FFFF and 0xA000_0000 - 0xA03F_FFFF */
468 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx,0x%0x",
470 4 * 1024 * 1024, /* 4 MB */
473 /* DRAM: 0x8800_0000 - 0x89FF_FFFF and 0xA800_0000 - 0xA9FF_FFFF */
474 for (i
=0; i
<8; i
++) /* 32 MB total */
476 unsigned size
= 4 * 1024 * 1024; /* 4 MB */
477 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx,0x%0x",
478 0x88000000 + (i
* size
),
480 0xA8000000 + (i
* size
));
484 else if (board
!= NULL
485 && (strcmp(board
, BOARD_JMR3904
) == 0 ||
486 strcmp(board
, BOARD_JMR3904_PAL
) == 0 ||
487 strcmp(board
, BOARD_JMR3904_DEBUG
) == 0))
489 /* match VIRTUAL memory layout of JMR-TX3904 board */
492 /* --- disable monitor unless forced on by user --- */
494 if (! firmware_option_p
)
496 idt_monitor_base
= 0;
497 pmon_monitor_base
= 0;
498 lsipmon_monitor_base
= 0;
501 /* --- environment --- */
503 STATE_ENVIRONMENT (sd
) = OPERATING_ENVIRONMENT
;
507 /* ROM: 0x9FC0_0000 - 0x9FFF_FFFF and 0xBFC0_0000 - 0xBFFF_FFFF */
508 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx,0x%0x",
510 4 * 1024 * 1024, /* 4 MB */
513 /* SRAM: 0x8000_0000 - 0x803F_FFFF and 0xA000_0000 - 0xA03F_FFFF */
514 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx,0x%0x",
516 4 * 1024 * 1024, /* 4 MB */
519 /* DRAM: 0x8800_0000 - 0x89FF_FFFF and 0xA800_0000 - 0xA9FF_FFFF */
520 for (i
=0; i
<8; i
++) /* 32 MB total */
522 unsigned size
= 4 * 1024 * 1024; /* 4 MB */
523 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx,0x%0x",
524 0x88000000 + (i
* size
),
526 0xA8000000 + (i
* size
));
529 /* Dummy memory regions for unsimulated devices - sorted by address */
531 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xB1000000, 0x400); /* ISA I/O */
532 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xB2100000, 0x004); /* ISA ctl */
533 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xB2500000, 0x004); /* LED/switch */
534 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xB2700000, 0x004); /* RTC */
535 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xB3C00000, 0x004); /* RTC */
536 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xFFFF8000, 0x900); /* DRAMC */
537 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xFFFF9000, 0x200); /* EBIF */
538 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xFFFFE000, 0x01c); /* EBIF */
539 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xFFFFF500, 0x300); /* PIO */
542 /* --- simulated devices --- */
543 sim_hw_parse (sd
, "/tx3904irc@0xffffc000/reg 0xffffc000 0x20");
544 sim_hw_parse (sd
, "/tx3904cpu");
545 sim_hw_parse (sd
, "/tx3904tmr@0xfffff000/reg 0xfffff000 0x100");
546 sim_hw_parse (sd
, "/tx3904tmr@0xfffff100/reg 0xfffff100 0x100");
547 sim_hw_parse (sd
, "/tx3904tmr@0xfffff200/reg 0xfffff200 0x100");
548 sim_hw_parse (sd
, "/tx3904sio@0xfffff300/reg 0xfffff300 0x100");
550 /* FIXME: poking at dv-sockser internals, use tcp backend if
551 --sockser_addr option was given.*/
552 extern char* sockser_addr
;
553 if(sockser_addr
== NULL
)
554 sim_hw_parse (sd
, "/tx3904sio@0xfffff300/backend stdio");
556 sim_hw_parse (sd
, "/tx3904sio@0xfffff300/backend tcp");
558 sim_hw_parse (sd
, "/tx3904sio@0xfffff400/reg 0xfffff400 0x100");
559 sim_hw_parse (sd
, "/tx3904sio@0xfffff400/backend stdio");
561 /* -- device connections --- */
562 sim_hw_parse (sd
, "/tx3904irc > ip level /tx3904cpu");
563 sim_hw_parse (sd
, "/tx3904tmr@0xfffff000 > int tmr0 /tx3904irc");
564 sim_hw_parse (sd
, "/tx3904tmr@0xfffff100 > int tmr1 /tx3904irc");
565 sim_hw_parse (sd
, "/tx3904tmr@0xfffff200 > int tmr2 /tx3904irc");
566 sim_hw_parse (sd
, "/tx3904sio@0xfffff300 > int sio0 /tx3904irc");
567 sim_hw_parse (sd
, "/tx3904sio@0xfffff400 > int sio1 /tx3904irc");
569 /* add PAL timer & I/O module */
570 if(! strcmp(board
, BOARD_JMR3904_PAL
))
573 sim_hw_parse (sd
, "/pal@0xffff0000");
574 sim_hw_parse (sd
, "/pal@0xffff0000/reg 0xffff0000 64");
576 /* wire up interrupt ports to irc */
577 sim_hw_parse (sd
, "/pal@0x31000000 > countdown tmr0 /tx3904irc");
578 sim_hw_parse (sd
, "/pal@0x31000000 > timer tmr1 /tx3904irc");
579 sim_hw_parse (sd
, "/pal@0x31000000 > int int0 /tx3904irc");
582 if(! strcmp(board
, BOARD_JMR3904_DEBUG
))
584 /* -- DEBUG: glue interrupt generators --- */
585 sim_hw_parse (sd
, "/glue@0xffff0000/reg 0xffff0000 0x50");
586 sim_hw_parse (sd
, "/glue@0xffff0000 > int0 int0 /tx3904irc");
587 sim_hw_parse (sd
, "/glue@0xffff0000 > int1 int1 /tx3904irc");
588 sim_hw_parse (sd
, "/glue@0xffff0000 > int2 int2 /tx3904irc");
589 sim_hw_parse (sd
, "/glue@0xffff0000 > int3 int3 /tx3904irc");
590 sim_hw_parse (sd
, "/glue@0xffff0000 > int4 int4 /tx3904irc");
591 sim_hw_parse (sd
, "/glue@0xffff0000 > int5 int5 /tx3904irc");
592 sim_hw_parse (sd
, "/glue@0xffff0000 > int6 int6 /tx3904irc");
593 sim_hw_parse (sd
, "/glue@0xffff0000 > int7 int7 /tx3904irc");
594 sim_hw_parse (sd
, "/glue@0xffff0000 > int8 dmac0 /tx3904irc");
595 sim_hw_parse (sd
, "/glue@0xffff0000 > int9 dmac1 /tx3904irc");
596 sim_hw_parse (sd
, "/glue@0xffff0000 > int10 dmac2 /tx3904irc");
597 sim_hw_parse (sd
, "/glue@0xffff0000 > int11 dmac3 /tx3904irc");
598 sim_hw_parse (sd
, "/glue@0xffff0000 > int12 sio0 /tx3904irc");
599 sim_hw_parse (sd
, "/glue@0xffff0000 > int13 sio1 /tx3904irc");
600 sim_hw_parse (sd
, "/glue@0xffff0000 > int14 tmr0 /tx3904irc");
601 sim_hw_parse (sd
, "/glue@0xffff0000 > int15 tmr1 /tx3904irc");
602 sim_hw_parse (sd
, "/glue@0xffff0000 > int16 tmr2 /tx3904irc");
603 sim_hw_parse (sd
, "/glue@0xffff0000 > int17 nmi /tx3904cpu");
610 if (display_mem_info
)
612 struct option_list
* ol
;
613 struct option_list
* prev
;
615 /* This is a hack. We want to execute the real --memory-info command
616 line switch which is handled in common/sim-memopts.c, not the
617 override we have defined in this file. So we remove the
618 mips_options array from the state options list. This is safe
619 because we have now processed all of the command line. */
620 for (ol
= STATE_OPTIONS (sd
), prev
= NULL
;
622 prev
= ol
, ol
= ol
->next
)
623 if (ol
->options
== mips_options
)
626 SIM_ASSERT (ol
!= NULL
);
629 STATE_OPTIONS (sd
) = ol
->next
;
631 prev
->next
= ol
->next
;
633 sim_do_commandf (sd
, "memory-info");
636 /* check for/establish the a reference program image */
637 if (sim_analyze_program (sd
,
638 (STATE_PROG_ARGV (sd
) != NULL
639 ? *STATE_PROG_ARGV (sd
)
643 sim_module_uninstall (sd
);
647 /* Configure/verify the target byte order and other runtime
648 configuration options */
649 if (sim_config (sd
) != SIM_RC_OK
)
651 sim_module_uninstall (sd
);
655 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
657 /* Uninstall the modules to avoid memory leaks,
658 file descriptor leaks, etc. */
659 sim_module_uninstall (sd
);
663 /* verify assumptions the simulator made about the host type system.
664 This macro does not return if there is a problem */
665 SIM_ASSERT (sizeof(int) == (4 * sizeof(char)));
666 SIM_ASSERT (sizeof(word64
) == (8 * sizeof(char)));
668 /* This is NASTY, in that we are assuming the size of specific
672 for (rn
= 0; (rn
< (LAST_EMBED_REGNUM
+ 1)); rn
++)
675 cpu
->register_widths
[rn
] = WITH_TARGET_WORD_BITSIZE
;
676 else if ((rn
>= FGR_BASE
) && (rn
< (FGR_BASE
+ NR_FGR
)))
677 cpu
->register_widths
[rn
] = WITH_TARGET_FLOATING_POINT_BITSIZE
;
678 else if ((rn
>= 33) && (rn
<= 37))
679 cpu
->register_widths
[rn
] = WITH_TARGET_WORD_BITSIZE
;
680 else if ((rn
== SRIDX
)
683 || ((rn
>= 72) && (rn
<= 89)))
684 cpu
->register_widths
[rn
] = 32;
686 cpu
->register_widths
[rn
] = 0;
693 if (STATE
& simTRACE
)
698 sim_io_eprintf (sd, "idt@%x pmon@%x lsipmon@%x\n",
701 lsipmon_monitor_base);
704 /* Write the monitor trap address handlers into the monitor (eeprom)
705 address space. This can only be done once the target endianness
706 has been determined. */
707 if (idt_monitor_base
!= 0)
710 unsigned idt_monitor_size
= 1 << 11;
712 /* the default monitor region */
713 sim_do_commandf (sd
, "memory region 0x%x,0x%x",
714 idt_monitor_base
, idt_monitor_size
);
716 /* Entry into the IDT monitor is via fixed address vectors, and
717 not using machine instructions. To avoid clashing with use of
718 the MIPS TRAP system, we place our own (simulator specific)
719 "undefined" instructions into the relevant vector slots. */
720 for (loop
= 0; (loop
< idt_monitor_size
); loop
+= 4)
722 address_word vaddr
= (idt_monitor_base
+ loop
);
723 unsigned32 insn
= (RSVD_INSTRUCTION
|
724 (((loop
>> 2) & RSVD_INSTRUCTION_ARG_MASK
)
725 << RSVD_INSTRUCTION_ARG_SHIFT
));
727 sim_write (sd
, vaddr
, (char *)&insn
, sizeof (insn
));
731 if ((pmon_monitor_base
!= 0) || (lsipmon_monitor_base
!= 0))
733 /* The PMON monitor uses the same address space, but rather than
734 branching into it the address of a routine is loaded. We can
735 cheat for the moment, and direct the PMON routine to IDT style
736 instructions within the monitor space. This relies on the IDT
737 monitor not using the locations from 0xBFC00500 onwards as its
740 for (loop
= 0; (loop
< 24); loop
++)
742 unsigned32 value
= ((0x500 - 8) / 8); /* default UNDEFINED reason code */
758 value
= ((0x500 - 16) / 8); /* not an IDT reason code */
760 case 8: /* cliexit */
763 case 11: /* flush_cache */
768 SIM_ASSERT (idt_monitor_base
!= 0);
769 value
= ((unsigned int) idt_monitor_base
+ (value
* 8));
772 if (pmon_monitor_base
!= 0)
774 address_word vaddr
= (pmon_monitor_base
+ (loop
* 4));
775 sim_write (sd
, vaddr
, (char *)&value
, sizeof (value
));
778 if (lsipmon_monitor_base
!= 0)
780 address_word vaddr
= (lsipmon_monitor_base
+ (loop
* 4));
781 sim_write (sd
, vaddr
, (char *)&value
, sizeof (value
));
785 /* Write an abort sequence into the TRAP (common) exception vector
786 addresses. This is to catch code executing a TRAP (et.al.)
787 instruction without installing a trap handler. */
788 if ((idt_monitor_base
!= 0) ||
789 (pmon_monitor_base
!= 0) ||
790 (lsipmon_monitor_base
!= 0))
792 unsigned32 halt
[2] = { 0x2404002f /* addiu r4, r0, 47 */,
793 HALT_INSTRUCTION
/* BREAK */ };
796 sim_write (sd
, 0x80000000, (char *) halt
, sizeof (halt
));
797 sim_write (sd
, 0x80000180, (char *) halt
, sizeof (halt
));
798 sim_write (sd
, 0x80000200, (char *) halt
, sizeof (halt
));
799 /* XXX: Write here unconditionally? */
800 sim_write (sd
, 0xBFC00200, (char *) halt
, sizeof (halt
));
801 sim_write (sd
, 0xBFC00380, (char *) halt
, sizeof (halt
));
802 sim_write (sd
, 0xBFC00400, (char *) halt
, sizeof (halt
));
816 tracefh
= fopen(tracefile
,"wb+");
819 sim_io_eprintf(sd
,"Failed to create file \"%s\", writing trace information to stderr.\n",tracefile
);
825 /* Return name of an insn, used by insn profiling. */
827 get_insn_name (sim_cpu
*cpu
, int i
)
829 return itable
[i
].name
;
833 sim_close (sd
, quitting
)
838 printf("DBG: sim_close: entered (quitting = %d)\n",quitting
);
842 /* "quitting" is non-zero if we cannot hang on errors */
844 /* shut down modules */
845 sim_module_uninstall (sd
);
847 /* Ensure that any resources allocated through the callback
848 mechanism are released: */
849 sim_io_shutdown (sd
);
852 if (tracefh
!= NULL
&& tracefh
!= stderr
)
857 /* FIXME - free SD */
864 sim_write (sd
,addr
,buffer
,size
)
867 unsigned char *buffer
;
871 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
873 /* Return the number of bytes written, or zero if error. */
875 sim_io_printf(sd
,"sim_write(0x%s,buffer,%d);\n",pr_addr(addr
),size
);
878 /* We use raw read and write routines, since we do not want to count
879 the GDB memory accesses in our statistics gathering. */
881 for (index
= 0; index
< size
; index
++)
883 address_word vaddr
= (address_word
)addr
+ index
;
886 if (!address_translation (SD
, CPU
, NULL_CIA
, vaddr
, isDATA
, isSTORE
, &paddr
, &cca
, isRAW
))
888 if (sim_core_write_buffer (SD
, CPU
, read_map
, buffer
+ index
, paddr
, 1) != 1)
896 sim_read (sd
,addr
,buffer
,size
)
899 unsigned char *buffer
;
903 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
905 /* Return the number of bytes read, or zero if error. */
907 sim_io_printf(sd
,"sim_read(0x%s,buffer,%d);\n",pr_addr(addr
),size
);
910 for (index
= 0; (index
< size
); index
++)
912 address_word vaddr
= (address_word
)addr
+ index
;
915 if (!address_translation (SD
, CPU
, NULL_CIA
, vaddr
, isDATA
, isLOAD
, &paddr
, &cca
, isRAW
))
917 if (sim_core_read_buffer (SD
, CPU
, read_map
, buffer
+ index
, paddr
, 1) != 1)
925 sim_store_register (sd
,rn
,memory
,length
)
928 unsigned char *memory
;
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 sim_io_printf(sd
,"sim_store_register(%d,*memory=0x%s);\n",rn
,pr_addr(*((SIM_ADDR
*)memory
)));
938 /* Unfortunately this suffers from the same problem as the register
939 numbering one. We need to know what the width of each logical
940 register number is for the architecture being simulated. */
942 if (cpu
->register_widths
[rn
] == 0)
944 sim_io_eprintf(sd
,"Invalid register width for %d (register store ignored)\n",rn
);
950 if (rn
>= FGR_BASE
&& rn
< FGR_BASE
+ NR_FGR
)
952 cpu
->fpr_state
[rn
- FGR_BASE
] = fmt_uninterpreted
;
953 if (cpu
->register_widths
[rn
] == 32)
957 cpu
->fgr
[rn
- FGR_BASE
] =
958 (unsigned32
) T2H_8 (*(unsigned64
*)memory
);
963 cpu
->fgr
[rn
- FGR_BASE
] = T2H_4 (*(unsigned32
*)memory
);
971 cpu
->fgr
[rn
- FGR_BASE
] = T2H_8 (*(unsigned64
*)memory
);
976 cpu
->fgr
[rn
- FGR_BASE
] = T2H_4 (*(unsigned32
*)memory
);
982 if (cpu
->register_widths
[rn
] == 32)
987 (unsigned32
) T2H_8 (*(unsigned64
*)memory
);
992 cpu
->registers
[rn
] = T2H_4 (*(unsigned32
*)memory
);
1000 cpu
->registers
[rn
] = T2H_8 (*(unsigned64
*)memory
);
1005 cpu
->registers
[rn
] = (signed32
) T2H_4(*(unsigned32
*)memory
);
1014 sim_fetch_register (sd
,rn
,memory
,length
)
1017 unsigned char *memory
;
1020 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
1021 /* NOTE: gdb (the client) stores registers in target byte order
1022 while the simulator uses host byte order */
1024 #if 0 /* FIXME: doesn't compile */
1025 sim_io_printf(sd
,"sim_fetch_register(%d=0x%s,mem) : place simulator registers into memory\n",rn
,pr_addr(registers
[rn
]));
1029 if (cpu
->register_widths
[rn
] == 0)
1031 sim_io_eprintf (sd
, "Invalid register width for %d (register fetch ignored)\n",rn
);
1037 /* Any floating point register */
1038 if (rn
>= FGR_BASE
&& rn
< FGR_BASE
+ NR_FGR
)
1040 if (cpu
->register_widths
[rn
] == 32)
1044 *(unsigned64
*)memory
=
1045 H2T_8 ((unsigned32
) (cpu
->fgr
[rn
- FGR_BASE
]));
1050 *(unsigned32
*)memory
= H2T_4 (cpu
->fgr
[rn
- FGR_BASE
]);
1058 *(unsigned64
*)memory
= H2T_8 (cpu
->fgr
[rn
- FGR_BASE
]);
1063 *(unsigned32
*)memory
= H2T_4 ((unsigned32
)(cpu
->fgr
[rn
- FGR_BASE
]));
1069 if (cpu
->register_widths
[rn
] == 32)
1073 *(unsigned64
*)memory
=
1074 H2T_8 ((unsigned32
) (cpu
->registers
[rn
]));
1079 *(unsigned32
*)memory
= H2T_4 ((unsigned32
)(cpu
->registers
[rn
]));
1087 *(unsigned64
*)memory
=
1088 H2T_8 ((unsigned64
) (cpu
->registers
[rn
]));
1093 *(unsigned32
*)memory
= H2T_4 ((unsigned32
)(cpu
->registers
[rn
]));
1103 sim_create_inferior (sd
, abfd
, argv
,env
)
1111 #if 0 /* FIXME: doesn't compile */
1112 printf("DBG: sim_create_inferior entered: start_address = 0x%s\n",
1121 /* override PC value set by ColdReset () */
1123 for (cpu_nr
= 0; cpu_nr
< sim_engine_nr_cpus (sd
); cpu_nr
++)
1125 sim_cpu
*cpu
= STATE_CPU (sd
, cpu_nr
);
1126 CIA_SET (cpu
, (unsigned64
) bfd_get_start_address (abfd
));
1130 #if 0 /* def DEBUG */
1133 /* We should really place the argv slot values into the argument
1134 registers, and onto the stack as required. However, this
1135 assumes that we have a stack defined, which is not
1136 necessarily true at the moment. */
1138 sim_io_printf(sd
,"sim_create_inferior() : passed arguments ignored\n");
1139 for (cptr
= argv
; (cptr
&& *cptr
); cptr
++)
1140 printf("DBG: arg \"%s\"\n",*cptr
);
1148 sim_do_command (sd
,cmd
)
1152 if (sim_args_command (sd
, cmd
) != SIM_RC_OK
)
1153 sim_io_printf (sd
, "Error: \"%s\" is not a valid MIPS simulator command.\n",
1157 /*---------------------------------------------------------------------------*/
1158 /*-- Private simulator support interface ------------------------------------*/
1159 /*---------------------------------------------------------------------------*/
1161 /* Read a null terminated string from memory, return in a buffer */
1163 fetch_str (SIM_DESC sd
,
1169 while (sim_read (sd
, addr
+ nr
, &null
, 1) == 1 && null
!= 0)
1171 buf
= NZALLOC (char, nr
+ 1);
1172 sim_read (sd
, addr
, buf
, nr
);
1177 /* Implements the "sim firmware" command:
1178 sim firmware NAME[@ADDRESS] --- emulate ROM monitor named NAME.
1179 NAME can be idt, pmon, or lsipmon. If omitted, ADDRESS
1180 defaults to the normal address for that monitor.
1181 sim firmware none --- don't emulate any ROM monitor. Useful
1182 if you need a clean address space. */
1184 sim_firmware_command (SIM_DESC sd
, char *arg
)
1186 int address_present
= 0;
1189 /* Signal occurrence of this option. */
1190 firmware_option_p
= 1;
1192 /* Parse out the address, if present. */
1194 char *p
= strchr (arg
, '@');
1198 address_present
= 1;
1199 p
++; /* skip over @ */
1201 address
= strtoul (p
, &q
, 0);
1204 sim_io_printf (sd
, "Invalid address given to the"
1205 "`sim firmware NAME@ADDRESS' command: %s\n",
1212 address_present
= 0;
1213 address
= -1; /* Dummy value. */
1217 if (! strncmp (arg
, "idt", 3))
1219 idt_monitor_base
= address_present
? address
: 0xBFC00000;
1220 pmon_monitor_base
= 0;
1221 lsipmon_monitor_base
= 0;
1223 else if (! strncmp (arg
, "pmon", 4))
1225 /* pmon uses indirect calls. Hook into implied idt. */
1226 pmon_monitor_base
= address_present
? address
: 0xBFC00500;
1227 idt_monitor_base
= pmon_monitor_base
- 0x500;
1228 lsipmon_monitor_base
= 0;
1230 else if (! strncmp (arg
, "lsipmon", 7))
1232 /* lsipmon uses indirect calls. Hook into implied idt. */
1233 pmon_monitor_base
= 0;
1234 lsipmon_monitor_base
= address_present
? address
: 0xBFC00200;
1235 idt_monitor_base
= lsipmon_monitor_base
- 0x200;
1237 else if (! strncmp (arg
, "none", 4))
1239 if (address_present
)
1242 "The `sim firmware none' command does "
1243 "not take an `ADDRESS' argument.\n");
1246 idt_monitor_base
= 0;
1247 pmon_monitor_base
= 0;
1248 lsipmon_monitor_base
= 0;
1252 sim_io_printf (sd
, "\
1253 Unrecognized name given to the `sim firmware NAME' command: %s\n\
1254 Recognized firmware names are: `idt', `pmon', `lsipmon', and `none'.\n",
1264 /* Simple monitor interface (currently setup for the IDT and PMON monitors) */
1266 sim_monitor (SIM_DESC sd
,
1269 unsigned int reason
)
1272 printf("DBG: sim_monitor: entered (reason = %d)\n",reason
);
1275 /* The IDT monitor actually allows two instructions per vector
1276 slot. However, the simulator currently causes a trap on each
1277 individual instruction. We cheat, and lose the bottom bit. */
1280 /* The following callback functions are available, however the
1281 monitor we are simulating does not make use of them: get_errno,
1282 isatty, lseek, rename, system, time and unlink */
1286 case 6: /* int open(char *path,int flags) */
1288 char *path
= fetch_str (sd
, A0
);
1289 V0
= sim_io_open (sd
, path
, (int)A1
);
1294 case 7: /* int read(int file,char *ptr,int len) */
1298 char *buf
= zalloc (nr
);
1299 V0
= sim_io_read (sd
, fd
, buf
, nr
);
1300 sim_write (sd
, A1
, buf
, nr
);
1305 case 8: /* int write(int file,char *ptr,int len) */
1309 char *buf
= zalloc (nr
);
1310 sim_read (sd
, A1
, buf
, nr
);
1311 V0
= sim_io_write (sd
, fd
, buf
, nr
);
1313 sim_io_flush_stdout (sd
);
1315 sim_io_flush_stderr (sd
);
1320 case 10: /* int close(int file) */
1322 V0
= sim_io_close (sd
, (int)A0
);
1326 case 2: /* Densan monitor: char inbyte(int waitflag) */
1328 if (A0
== 0) /* waitflag == NOWAIT */
1329 V0
= (unsigned_word
)-1;
1331 /* Drop through to case 11 */
1333 case 11: /* char inbyte(void) */
1336 /* ensure that all output has gone... */
1337 sim_io_flush_stdout (sd
);
1338 if (sim_io_read_stdin (sd
, &tmp
, sizeof(char)) != sizeof(char))
1340 sim_io_error(sd
,"Invalid return from character read");
1341 V0
= (unsigned_word
)-1;
1344 V0
= (unsigned_word
)tmp
;
1348 case 3: /* Densan monitor: void co(char chr) */
1349 case 12: /* void outbyte(char chr) : write a byte to "stdout" */
1351 char tmp
= (char)(A0
& 0xFF);
1352 sim_io_write_stdout (sd
, &tmp
, sizeof(char));
1356 case 17: /* void _exit() */
1358 sim_io_eprintf (sd
, "sim_monitor(17): _exit(int reason) to be coded\n");
1359 sim_engine_halt (SD
, CPU
, NULL
, NULL_CIA
, sim_exited
,
1360 (unsigned int)(A0
& 0xFFFFFFFF));
1364 case 28: /* PMON flush_cache */
1367 case 55: /* void get_mem_info(unsigned int *ptr) */
1368 /* in: A0 = pointer to three word memory location */
1369 /* out: [A0 + 0] = size */
1370 /* [A0 + 4] = instruction cache size */
1371 /* [A0 + 8] = data cache size */
1374 unsigned_4 zero
= 0;
1375 address_word mem_size
;
1376 sim_memopt
*entry
, *match
= NULL
;
1378 /* Search for memory region mapped to KSEG0 or KSEG1. */
1379 for (entry
= STATE_MEMOPT (sd
);
1381 entry
= entry
->next
)
1383 if ((entry
->addr
== K0BASE
|| entry
->addr
== K1BASE
)
1384 && (!match
|| entry
->level
< match
->level
))
1389 for (alias
= entry
->alias
;
1391 alias
= alias
->next
)
1392 if ((alias
->addr
== K0BASE
|| alias
->addr
== K1BASE
)
1393 && (!match
|| entry
->level
< match
->level
))
1398 /* Get region size, limit to KSEG1 size (512MB). */
1399 SIM_ASSERT (match
!= NULL
);
1400 mem_size
= (match
->modulo
!= 0
1401 ? match
->modulo
: match
->nr_bytes
);
1402 if (mem_size
> K1SIZE
)
1407 sim_write (sd
, A0
+ 0, (char *)&value
, 4);
1408 sim_write (sd
, A0
+ 4, (char *)&zero
, 4);
1409 sim_write (sd
, A0
+ 8, (char *)&zero
, 4);
1410 /* sim_io_eprintf (sd, "sim: get_mem_info() deprecated\n"); */
1414 case 158: /* PMON printf */
1415 /* in: A0 = pointer to format string */
1416 /* A1 = optional argument 1 */
1417 /* A2 = optional argument 2 */
1418 /* A3 = optional argument 3 */
1420 /* The following is based on the PMON printf source */
1422 address_word s
= A0
;
1424 signed_word
*ap
= &A1
; /* 1st argument */
1425 /* This isn't the quickest way, since we call the host print
1426 routine for every character almost. But it does avoid
1427 having to allocate and manage a temporary string buffer. */
1428 /* TODO: Include check that we only use three arguments (A1,
1430 while (sim_read (sd
, s
++, &c
, 1) && c
!= '\0')
1435 enum {FMT_RJUST
, FMT_LJUST
, FMT_RJUST0
, FMT_CENTER
} fmt
= FMT_RJUST
;
1436 int width
= 0, trunc
= 0, haddot
= 0, longlong
= 0;
1437 while (sim_read (sd
, s
++, &c
, 1) && c
!= '\0')
1439 if (strchr ("dobxXulscefg%", c
))
1454 else if (c
>= '1' && c
<= '9')
1458 while (sim_read (sd
, s
++, &c
, 1) == 1 && isdigit (c
))
1461 n
= (unsigned int)strtol(tmp
,NULL
,10);
1474 sim_io_printf (sd
, "%%");
1479 address_word p
= *ap
++;
1481 while (sim_read (sd
, p
++, &ch
, 1) == 1 && ch
!= '\0')
1482 sim_io_printf(sd
, "%c", ch
);
1485 sim_io_printf(sd
,"(null)");
1488 sim_io_printf (sd
, "%c", (int)*ap
++);
1493 sim_read (sd
, s
++, &c
, 1);
1497 sim_read (sd
, s
++, &c
, 1);
1500 if (strchr ("dobxXu", c
))
1502 word64 lv
= (word64
) *ap
++;
1504 sim_io_printf(sd
,"<binary not supported>");
1507 sprintf (tmp
, "%%%s%c", longlong
? "ll" : "", c
);
1509 sim_io_printf(sd
, tmp
, lv
);
1511 sim_io_printf(sd
, tmp
, (int)lv
);
1514 else if (strchr ("eEfgG", c
))
1516 double dbl
= *(double*)(ap
++);
1517 sprintf (tmp
, "%%%d.%d%c", width
, trunc
, c
);
1518 sim_io_printf (sd
, tmp
, dbl
);
1524 sim_io_printf(sd
, "%c", c
);
1530 /* Unknown reason. */
1536 /* Store a word into memory. */
1539 store_word (SIM_DESC sd
,
1548 if ((vaddr
& 3) != 0)
1549 SignalExceptionAddressStore ();
1552 if (AddressTranslation (vaddr
, isDATA
, isSTORE
, &paddr
, &uncached
,
1555 const uword64 mask
= 7;
1559 paddr
= (paddr
& ~mask
) | ((paddr
& mask
) ^ (ReverseEndian
<< 2));
1560 byte
= (vaddr
& mask
) ^ (BigEndianCPU
<< 2);
1561 memval
= ((uword64
) val
) << (8 * byte
);
1562 StoreMemory (uncached
, AccessLength_WORD
, memval
, 0, paddr
, vaddr
,
1568 /* Load a word from memory. */
1571 load_word (SIM_DESC sd
,
1576 if ((vaddr
& 3) != 0)
1578 SIM_CORE_SIGNAL (SD
, cpu
, cia
, read_map
, AccessLength_WORD
+1, vaddr
, read_transfer
, sim_core_unaligned_signal
);
1585 if (AddressTranslation (vaddr
, isDATA
, isLOAD
, &paddr
, &uncached
,
1588 const uword64 mask
= 0x7;
1589 const unsigned int reverse
= ReverseEndian
? 1 : 0;
1590 const unsigned int bigend
= BigEndianCPU
? 1 : 0;
1594 paddr
= (paddr
& ~mask
) | ((paddr
& mask
) ^ (reverse
<< 2));
1595 LoadMemory (&memval
,NULL
,uncached
, AccessLength_WORD
, paddr
, vaddr
,
1597 byte
= (vaddr
& mask
) ^ (bigend
<< 2);
1598 return EXTEND32 (memval
>> (8 * byte
));
1605 /* Simulate the mips16 entry and exit pseudo-instructions. These
1606 would normally be handled by the reserved instruction exception
1607 code, but for ease of simulation we just handle them directly. */
1610 mips16_entry (SIM_DESC sd
,
1615 int aregs
, sregs
, rreg
;
1618 printf("DBG: mips16_entry: entered (insn = 0x%08X)\n",insn
);
1621 aregs
= (insn
& 0x700) >> 8;
1622 sregs
= (insn
& 0x0c0) >> 6;
1623 rreg
= (insn
& 0x020) >> 5;
1625 /* This should be checked by the caller. */
1634 /* This is the entry pseudo-instruction. */
1636 for (i
= 0; i
< aregs
; i
++)
1637 store_word (SD
, CPU
, cia
, (uword64
) (SP
+ 4 * i
), GPR
[i
+ 4]);
1645 store_word (SD
, CPU
, cia
, (uword64
) tsp
, RA
);
1648 for (i
= 0; i
< sregs
; i
++)
1651 store_word (SD
, CPU
, cia
, (uword64
) tsp
, GPR
[16 + i
]);
1659 /* This is the exit pseudo-instruction. */
1666 RA
= load_word (SD
, CPU
, cia
, (uword64
) tsp
);
1669 for (i
= 0; i
< sregs
; i
++)
1672 GPR
[i
+ 16] = load_word (SD
, CPU
, cia
, (uword64
) tsp
);
1677 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
1681 FGR
[0] = WORD64LO (GPR
[4]);
1682 FPR_STATE
[0] = fmt_uninterpreted
;
1684 else if (aregs
== 6)
1686 FGR
[0] = WORD64LO (GPR
[5]);
1687 FGR
[1] = WORD64LO (GPR
[4]);
1688 FPR_STATE
[0] = fmt_uninterpreted
;
1689 FPR_STATE
[1] = fmt_uninterpreted
;
1698 /*-- trace support ----------------------------------------------------------*/
1700 /* The TRACE support is provided (if required) in the memory accessing
1701 routines. Since we are also providing the architecture specific
1702 features, the architecture simulation code can also deal with
1703 notifying the TRACE world of cache flushes, etc. Similarly we do
1704 not need to provide profiling support in the simulator engine,
1705 since we can sample in the instruction fetch control loop. By
1706 defining the TRACE manifest, we add tracing as a run-time
1710 /* Tracing by default produces "din" format (as required by
1711 dineroIII). Each line of such a trace file *MUST* have a din label
1712 and address field. The rest of the line is ignored, so comments can
1713 be included if desired. The first field is the label which must be
1714 one of the following values:
1719 3 escape record (treated as unknown access type)
1720 4 escape record (causes cache flush)
1722 The address field is a 32bit (lower-case) hexadecimal address
1723 value. The address should *NOT* be preceded by "0x".
1725 The size of the memory transfer is not important when dealing with
1726 cache lines (as long as no more than a cache line can be
1727 transferred in a single operation :-), however more information
1728 could be given following the dineroIII requirement to allow more
1729 complete memory and cache simulators to provide better
1730 results. i.e. the University of Pisa has a cache simulator that can
1731 also take bus size and speed as (variable) inputs to calculate
1732 complete system performance (a much more useful ability when trying
1733 to construct an end product, rather than a processor). They
1734 currently have an ARM version of their tool called ChARM. */
1738 dotrace (SIM_DESC sd
,
1746 if (STATE
& simTRACE
) {
1748 fprintf(tracefh
,"%d %s ; width %d ; ",
1752 va_start(ap
,comment
);
1753 vfprintf(tracefh
,comment
,ap
);
1755 fprintf(tracefh
,"\n");
1757 /* NOTE: Since the "din" format will only accept 32bit addresses, and
1758 we may be generating 64bit ones, we should put the hi-32bits of the
1759 address into the comment field. */
1761 /* TODO: Provide a buffer for the trace lines. We can then avoid
1762 performing writes until the buffer is filled, or the file is
1765 /* NOTE: We could consider adding a comment field to the "din" file
1766 produced using type 3 markers (unknown access). This would then
1767 allow information about the program that the "din" is for, and
1768 the MIPs world that was being simulated, to be placed into the
1775 /*---------------------------------------------------------------------------*/
1776 /*-- simulator engine -------------------------------------------------------*/
1777 /*---------------------------------------------------------------------------*/
1780 ColdReset (SIM_DESC sd
)
1783 for (cpu_nr
= 0; cpu_nr
< sim_engine_nr_cpus (sd
); cpu_nr
++)
1785 sim_cpu
*cpu
= STATE_CPU (sd
, cpu_nr
);
1786 /* RESET: Fixed PC address: */
1787 PC
= (unsigned_word
) UNSIGNED64 (0xFFFFFFFFBFC00000);
1788 /* The reset vector address is in the unmapped, uncached memory space. */
1790 SR
&= ~(status_SR
| status_TS
| status_RP
);
1791 SR
|= (status_ERL
| status_BEV
);
1793 /* Cheat and allow access to the complete register set immediately */
1794 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
1795 && WITH_TARGET_WORD_BITSIZE
== 64)
1796 SR
|= status_FR
; /* 64bit registers */
1798 /* Ensure that any instructions with pending register updates are
1800 PENDING_INVALIDATE();
1802 /* Initialise the FPU registers to the unknown state */
1803 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
1806 for (rn
= 0; (rn
< 32); rn
++)
1807 FPR_STATE
[rn
] = fmt_uninterpreted
;
1810 /* Initialise the Config0 register. */
1811 C0_CONFIG
= 0x80000000 /* Config1 present */
1812 | 2; /* KSEG0 uncached */
1813 if (WITH_TARGET_WORD_BITSIZE
== 64)
1815 /* FIXME Currently mips/sim-main.c:address_translation()
1816 truncates all addresses to 32-bits. */
1817 if (0 && WITH_TARGET_ADDRESS_BITSIZE
== 64)
1818 C0_CONFIG
|= (2 << 13); /* MIPS64, 64-bit addresses */
1820 C0_CONFIG
|= (1 << 13); /* MIPS64, 32-bit addresses */
1823 C0_CONFIG
|= 0x00008000; /* Big Endian */
1830 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
1831 /* Signal an exception condition. This will result in an exception
1832 that aborts the instruction. The instruction operation pseudocode
1833 will never see a return from this function call. */
1836 signal_exception (SIM_DESC sd
,
1844 sim_io_printf(sd
,"DBG: SignalException(%d) PC = 0x%s\n",exception
,pr_addr(cia
));
1847 /* Ensure that any active atomic read/modify/write operation will fail: */
1850 /* Save registers before interrupt dispatching */
1851 #ifdef SIM_CPU_EXCEPTION_TRIGGER
1852 SIM_CPU_EXCEPTION_TRIGGER(sd
, cpu
, cia
);
1855 switch (exception
) {
1857 case DebugBreakPoint
:
1858 if (! (Debug
& Debug_DM
))
1864 Debug
|= Debug_DBD
; /* signaled from within in delay slot */
1865 DEPC
= cia
- 4; /* reference the branch instruction */
1869 Debug
&= ~Debug_DBD
; /* not signaled from within a delay slot */
1873 Debug
|= Debug_DM
; /* in debugging mode */
1874 Debug
|= Debug_DBp
; /* raising a DBp exception */
1876 sim_engine_restart (SD
, CPU
, NULL
, NULL_CIA
);
1880 case ReservedInstruction
:
1883 unsigned int instruction
;
1884 va_start(ap
,exception
);
1885 instruction
= va_arg(ap
,unsigned int);
1887 /* Provide simple monitor support using ReservedInstruction
1888 exceptions. The following code simulates the fixed vector
1889 entry points into the IDT monitor by causing a simulator
1890 trap, performing the monitor operation, and returning to
1891 the address held in the $ra register (standard PCS return
1892 address). This means we only need to pre-load the vector
1893 space with suitable instruction values. For systems were
1894 actual trap instructions are used, we would not need to
1895 perform this magic. */
1896 if ((instruction
& RSVD_INSTRUCTION_MASK
) == RSVD_INSTRUCTION
)
1898 int reason
= (instruction
>> RSVD_INSTRUCTION_ARG_SHIFT
) & RSVD_INSTRUCTION_ARG_MASK
;
1899 if (!sim_monitor (SD
, CPU
, cia
, reason
))
1900 sim_io_error (sd
, "sim_monitor: unhandled reason = %d, pc = 0x%s\n", reason
, pr_addr (cia
));
1902 /* NOTE: This assumes that a branch-and-link style
1903 instruction was used to enter the vector (which is the
1904 case with the current IDT monitor). */
1905 sim_engine_restart (SD
, CPU
, NULL
, RA
);
1907 /* Look for the mips16 entry and exit instructions, and
1908 simulate a handler for them. */
1909 else if ((cia
& 1) != 0
1910 && (instruction
& 0xf81f) == 0xe809
1911 && (instruction
& 0x0c0) != 0x0c0)
1913 mips16_entry (SD
, CPU
, cia
, instruction
);
1914 sim_engine_restart (sd
, NULL
, NULL
, NULL_CIA
);
1916 /* else fall through to normal exception processing */
1917 sim_io_eprintf(sd
,"ReservedInstruction at PC = 0x%s\n", pr_addr (cia
));
1921 /* Store exception code into current exception id variable (used
1924 /* TODO: If not simulating exceptions then stop the simulator
1925 execution. At the moment we always stop the simulation. */
1927 #ifdef SUBTARGET_R3900
1928 /* update interrupt-related registers */
1930 /* insert exception code in bits 6:2 */
1931 CAUSE
= LSMASKED32(CAUSE
, 31, 7) | LSINSERTED32(exception
, 6, 2);
1932 /* shift IE/KU history bits left */
1933 SR
= LSMASKED32(SR
, 31, 4) | LSINSERTED32(LSEXTRACTED32(SR
, 3, 0), 5, 2);
1935 if (STATE
& simDELAYSLOT
)
1937 STATE
&= ~simDELAYSLOT
;
1939 EPC
= (cia
- 4); /* reference the branch instruction */
1944 if (SR
& status_BEV
)
1945 PC
= (signed)0xBFC00000 + 0x180;
1947 PC
= (signed)0x80000000 + 0x080;
1949 /* See figure 5-17 for an outline of the code below */
1950 if (! (SR
& status_EXL
))
1952 CAUSE
= (exception
<< 2);
1953 if (STATE
& simDELAYSLOT
)
1955 STATE
&= ~simDELAYSLOT
;
1957 EPC
= (cia
- 4); /* reference the branch instruction */
1961 /* FIXME: TLB et.al. */
1962 /* vector = 0x180; */
1966 CAUSE
= (exception
<< 2);
1967 /* vector = 0x180; */
1970 /* Store exception code into current exception id variable (used
1973 if (SR
& status_BEV
)
1974 PC
= (signed)0xBFC00200 + 0x180;
1976 PC
= (signed)0x80000000 + 0x180;
1979 switch ((CAUSE
>> 2) & 0x1F)
1982 /* Interrupts arrive during event processing, no need to
1988 #ifdef SUBTARGET_3900
1989 /* Exception vector: BEV=0 BFC00000 / BEF=1 BFC00000 */
1990 PC
= (signed)0xBFC00000;
1991 #endif /* SUBTARGET_3900 */
1994 case TLBModification
:
1999 case InstructionFetch
:
2001 /* The following is so that the simulator will continue from the
2002 exception handler address. */
2003 sim_engine_halt (SD
, CPU
, NULL
, PC
,
2004 sim_stopped
, SIM_SIGBUS
);
2006 case ReservedInstruction
:
2007 case CoProcessorUnusable
:
2009 sim_engine_halt (SD
, CPU
, NULL
, PC
,
2010 sim_stopped
, SIM_SIGILL
);
2012 case IntegerOverflow
:
2014 sim_engine_halt (SD
, CPU
, NULL
, PC
,
2015 sim_stopped
, SIM_SIGFPE
);
2018 sim_engine_halt (SD
, CPU
, NULL
, PC
, sim_stopped
, SIM_SIGTRAP
);
2023 sim_engine_restart (SD
, CPU
, NULL
, PC
);
2028 sim_engine_halt (SD
, CPU
, NULL
, PC
,
2029 sim_stopped
, SIM_SIGTRAP
);
2031 default: /* Unknown internal exception */
2033 sim_engine_halt (SD
, CPU
, NULL
, PC
,
2034 sim_stopped
, SIM_SIGABRT
);
2038 case SimulatorFault
:
2042 va_start(ap
,exception
);
2043 msg
= va_arg(ap
,char *);
2045 sim_engine_abort (SD
, CPU
, NULL_CIA
,
2046 "FATAL: Simulator error \"%s\"\n",msg
);
2055 /* This function implements what the MIPS32 and MIPS64 ISAs define as
2056 "UNPREDICTABLE" behaviour.
2058 About UNPREDICTABLE behaviour they say: "UNPREDICTABLE results
2059 may vary from processor implementation to processor implementation,
2060 instruction to instruction, or as a function of time on the same
2061 implementation or instruction. Software can never depend on results
2062 that are UNPREDICTABLE. ..." (MIPS64 Architecture for Programmers
2063 Volume II, The MIPS64 Instruction Set. MIPS Document MD00087 revision
2066 For UNPREDICTABLE behaviour, we print a message, if possible print
2067 the offending instructions mips.igen instruction name (provided by
2068 the caller), and stop the simulator.
2070 XXX FIXME: eventually, stopping the simulator should be made conditional
2071 on a command-line option. */
2073 unpredictable_action(sim_cpu
*cpu
, address_word cia
)
2075 SIM_DESC sd
= CPU_STATE(cpu
);
2077 sim_io_eprintf(sd
, "UNPREDICTABLE: PC = 0x%s\n", pr_addr (cia
));
2078 sim_engine_halt (SD
, CPU
, NULL
, cia
, sim_stopped
, SIM_SIGABRT
);
2082 /*-- co-processor support routines ------------------------------------------*/
2085 CoProcPresent(unsigned int coproc_number
)
2087 /* Return TRUE if simulator provides a model for the given co-processor number */
2092 cop_lw (SIM_DESC sd
,
2097 unsigned int memword
)
2102 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
2105 printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%s\n",memword
,pr_addr(memword
));
2107 StoreFPR(coproc_reg
,fmt_uninterpreted_32
,(uword64
)memword
);
2112 #if 0 /* this should be controlled by a configuration option */
2113 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
));
2122 cop_ld (SIM_DESC sd
,
2131 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
) );
2134 switch (coproc_num
) {
2136 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
2138 StoreFPR(coproc_reg
,fmt_uninterpreted_64
,memword
);
2143 #if 0 /* this message should be controlled by a configuration option */
2144 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
));
2156 cop_sw (SIM_DESC sd
,
2162 unsigned int value
= 0;
2167 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
2169 value
= (unsigned int)ValueFPR(coproc_reg
,fmt_uninterpreted_32
);
2174 #if 0 /* should be controlled by configuration option */
2175 sim_io_printf(sd
,"COP_SW(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num
,coproc_reg
,pr_addr(cia
));
2184 cop_sd (SIM_DESC sd
,
2194 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
2196 value
= ValueFPR(coproc_reg
,fmt_uninterpreted_64
);
2201 #if 0 /* should be controlled by configuration option */
2202 sim_io_printf(sd
,"COP_SD(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num
,coproc_reg
,pr_addr(cia
));
2214 decode_coproc (SIM_DESC sd
,
2217 unsigned int instruction
)
2219 int coprocnum
= ((instruction
>> 26) & 3);
2223 case 0: /* standard CPU control and cache registers */
2225 int code
= ((instruction
>> 21) & 0x1F);
2226 int rt
= ((instruction
>> 16) & 0x1F);
2227 int rd
= ((instruction
>> 11) & 0x1F);
2228 int tail
= instruction
& 0x3ff;
2229 /* R4000 Users Manual (second edition) lists the following CP0
2231 CODE><-RT><RD-><--TAIL--->
2232 DMFC0 Doubleword Move From CP0 (VR4100 = 01000000001tttttddddd00000000000)
2233 DMTC0 Doubleword Move To CP0 (VR4100 = 01000000101tttttddddd00000000000)
2234 MFC0 word Move From CP0 (VR4100 = 01000000000tttttddddd00000000000)
2235 MTC0 word Move To CP0 (VR4100 = 01000000100tttttddddd00000000000)
2236 TLBR Read Indexed TLB Entry (VR4100 = 01000010000000000000000000000001)
2237 TLBWI Write Indexed TLB Entry (VR4100 = 01000010000000000000000000000010)
2238 TLBWR Write Random TLB Entry (VR4100 = 01000010000000000000000000000110)
2239 TLBP Probe TLB for Matching Entry (VR4100 = 01000010000000000000000000001000)
2240 CACHE Cache operation (VR4100 = 101111bbbbbpppppiiiiiiiiiiiiiiii)
2241 ERET Exception return (VR4100 = 01000010000000000000000000011000)
2243 if (((code
== 0x00) || (code
== 0x04) /* MFC0 / MTC0 */
2244 || (code
== 0x01) || (code
== 0x05)) /* DMFC0 / DMTC0 */
2247 /* Clear double/single coprocessor move bit. */
2250 /* M[TF]C0 (32 bits) | DM[TF]C0 (64 bits) */
2252 switch (rd
) /* NOTEs: Standard CP0 registers */
2254 /* 0 = Index R4000 VR4100 VR4300 */
2255 /* 1 = Random R4000 VR4100 VR4300 */
2256 /* 2 = EntryLo0 R4000 VR4100 VR4300 */
2257 /* 3 = EntryLo1 R4000 VR4100 VR4300 */
2258 /* 4 = Context R4000 VR4100 VR4300 */
2259 /* 5 = PageMask R4000 VR4100 VR4300 */
2260 /* 6 = Wired R4000 VR4100 VR4300 */
2261 /* 8 = BadVAddr R4000 VR4100 VR4300 */
2262 /* 9 = Count R4000 VR4100 VR4300 */
2263 /* 10 = EntryHi R4000 VR4100 VR4300 */
2264 /* 11 = Compare R4000 VR4100 VR4300 */
2265 /* 12 = SR R4000 VR4100 VR4300 */
2266 #ifdef SUBTARGET_R3900
2268 /* 3 = Config R3900 */
2270 /* 7 = Cache R3900 */
2272 /* 15 = PRID R3900 */
2278 /* 8 = BadVAddr R4000 VR4100 VR4300 */
2280 GPR
[rt
] = (signed_word
) (signed_address
) COP0_BADVADDR
;
2282 COP0_BADVADDR
= GPR
[rt
];
2285 #endif /* SUBTARGET_R3900 */
2292 /* 13 = Cause R4000 VR4100 VR4300 */
2299 /* 14 = EPC R4000 VR4100 VR4300 */
2302 GPR
[rt
] = (signed_word
) (signed_address
) EPC
;
2306 /* 15 = PRId R4000 VR4100 VR4300 */
2307 #ifdef SUBTARGET_R3900
2316 /* 16 = Config R4000 VR4100 VR4300 */
2319 GPR
[rt
] = C0_CONFIG
;
2321 /* only bottom three bits are writable */
2322 C0_CONFIG
= (C0_CONFIG
& ~0x7) | (GPR
[rt
] & 0x7);
2325 #ifdef SUBTARGET_R3900
2334 /* 17 = LLAddr R4000 VR4100 VR4300 */
2336 /* 18 = WatchLo R4000 VR4100 VR4300 */
2337 /* 19 = WatchHi R4000 VR4100 VR4300 */
2338 /* 20 = XContext R4000 VR4100 VR4300 */
2339 /* 26 = PErr or ECC R4000 VR4100 VR4300 */
2340 /* 27 = CacheErr R4000 VR4100 */
2341 /* 28 = TagLo R4000 VR4100 VR4300 */
2342 /* 29 = TagHi R4000 VR4100 VR4300 */
2343 /* 30 = ErrorEPC R4000 VR4100 VR4300 */
2344 if (STATE_VERBOSE_P(SD
))
2346 "Warning: PC 0x%lx:interp.c decode_coproc DEADC0DE\n",
2347 (unsigned long)cia
);
2348 GPR
[rt
] = 0xDEADC0DE; /* CPR[0,rd] */
2349 /* CPR[0,rd] = GPR[rt]; */
2352 GPR
[rt
] = (signed_word
) (signed32
) COP0_GPR
[rd
];
2354 COP0_GPR
[rd
] = GPR
[rt
];
2357 sim_io_printf(sd
,"Warning: MFC0 %d,%d ignored, PC=%08x (architecture specific)\n",rt
,rd
, (unsigned)cia
);
2359 sim_io_printf(sd
,"Warning: MTC0 %d,%d ignored, PC=%08x (architecture specific)\n",rt
,rd
, (unsigned)cia
);
2363 else if ((code
== 0x00 || code
== 0x01)
2366 /* [D]MFC0 RT,C0_CONFIG,SEL */
2368 switch (tail
& 0x07)
2374 /* MIPS32 r/o Config1:
2377 /* MIPS16 implemented.
2378 XXX How to check configuration? */
2380 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
2381 /* MDMX & FPU implemented */
2385 /* MIPS32 r/o Config2:
2390 /* MIPS32 r/o Config3:
2391 SmartMIPS implemented. */
2397 else if (code
== 0x10 && (tail
& 0x3f) == 0x18)
2400 if (SR
& status_ERL
)
2402 /* Oops, not yet available */
2403 sim_io_printf(sd
,"Warning: ERET when SR[ERL] set not handled yet");
2413 else if (code
== 0x10 && (tail
& 0x3f) == 0x10)
2416 #ifdef SUBTARGET_R3900
2417 /* TX39: Copy IEp/KUp -> IEc/KUc, and IEo/KUo -> IEp/KUp */
2419 /* shift IE/KU history bits right */
2420 SR
= LSMASKED32(SR
, 31, 4) | LSINSERTED32(LSEXTRACTED32(SR
, 5, 2), 3, 0);
2422 /* TODO: CACHE register */
2423 #endif /* SUBTARGET_R3900 */
2425 else if (code
== 0x10 && (tail
& 0x3f) == 0x1F)
2433 sim_io_eprintf(sd
,"Unrecognised COP0 instruction 0x%08X at PC = 0x%s : No handler present\n",instruction
,pr_addr(cia
));
2434 /* TODO: When executing an ERET or RFE instruction we should
2435 clear LLBIT, to ensure that any out-standing atomic
2436 read/modify/write sequence fails. */
2440 case 2: /* co-processor 2 */
2447 sim_io_eprintf(sd
, "COP2 instruction 0x%08X at PC = 0x%s : No handler present\n",
2448 instruction
,pr_addr(cia
));
2453 case 1: /* should not occur (FPU co-processor) */
2454 case 3: /* should not occur (FPU co-processor) */
2455 SignalException(ReservedInstruction
,instruction
);
2463 /* This code copied from gdb's utils.c. Would like to share this code,
2464 but don't know of a common place where both could get to it. */
2466 /* Temporary storage using circular buffer */
2472 static char buf
[NUMCELLS
][CELLSIZE
];
2474 if (++cell
>=NUMCELLS
) cell
=0;
2478 /* Print routines to handle variable size regs, etc */
2480 /* Eliminate warning from compiler on 32-bit systems */
2481 static int thirty_two
= 32;
2487 char *paddr_str
=get_cell();
2488 switch (sizeof(addr
))
2491 sprintf(paddr_str
,"%08lx%08lx",
2492 (unsigned long)(addr
>>thirty_two
),(unsigned long)(addr
&0xffffffff));
2495 sprintf(paddr_str
,"%08lx",(unsigned long)addr
);
2498 sprintf(paddr_str
,"%04x",(unsigned short)(addr
&0xffff));
2501 sprintf(paddr_str
,"%x",addr
);
2510 char *paddr_str
=get_cell();
2511 sprintf(paddr_str
,"%08lx%08lx",
2512 (unsigned long)(addr
>>thirty_two
),(unsigned long)(addr
&0xffffffff));
2518 mips_core_signal (SIM_DESC sd
,
2524 transfer_type transfer
,
2525 sim_core_signals sig
)
2527 const char *copy
= (transfer
== read_transfer
? "read" : "write");
2528 address_word ip
= CIA_ADDR (cia
);
2532 case sim_core_unmapped_signal
:
2533 sim_io_eprintf (sd
, "mips-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
2535 (unsigned long) addr
, (unsigned long) ip
);
2536 COP0_BADVADDR
= addr
;
2537 SignalExceptionDataReference();
2540 case sim_core_unaligned_signal
:
2541 sim_io_eprintf (sd
, "mips-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n",
2543 (unsigned long) addr
, (unsigned long) ip
);
2544 COP0_BADVADDR
= addr
;
2545 if(transfer
== read_transfer
)
2546 SignalExceptionAddressLoad();
2548 SignalExceptionAddressStore();
2552 sim_engine_abort (sd
, cpu
, cia
,
2553 "mips_core_signal - internal error - bad switch");
2559 mips_cpu_exception_trigger(SIM_DESC sd
, sim_cpu
* cpu
, address_word cia
)
2561 ASSERT(cpu
!= NULL
);
2563 if(cpu
->exc_suspended
> 0)
2564 sim_io_eprintf(sd
, "Warning, nested exception triggered (%d)\n", cpu
->exc_suspended
);
2567 memcpy(cpu
->exc_trigger_registers
, cpu
->registers
, sizeof(cpu
->exc_trigger_registers
));
2568 cpu
->exc_suspended
= 0;
2572 mips_cpu_exception_suspend(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
2574 ASSERT(cpu
!= NULL
);
2576 if(cpu
->exc_suspended
> 0)
2577 sim_io_eprintf(sd
, "Warning, nested exception signal (%d then %d)\n",
2578 cpu
->exc_suspended
, exception
);
2580 memcpy(cpu
->exc_suspend_registers
, cpu
->registers
, sizeof(cpu
->exc_suspend_registers
));
2581 memcpy(cpu
->registers
, cpu
->exc_trigger_registers
, sizeof(cpu
->registers
));
2582 cpu
->exc_suspended
= exception
;
2586 mips_cpu_exception_resume(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
2588 ASSERT(cpu
!= NULL
);
2590 if(exception
== 0 && cpu
->exc_suspended
> 0)
2592 /* warn not for breakpoints */
2593 if(cpu
->exc_suspended
!= sim_signal_to_host(sd
, SIM_SIGTRAP
))
2594 sim_io_eprintf(sd
, "Warning, resuming but ignoring pending exception signal (%d)\n",
2595 cpu
->exc_suspended
);
2597 else if(exception
!= 0 && cpu
->exc_suspended
> 0)
2599 if(exception
!= cpu
->exc_suspended
)
2600 sim_io_eprintf(sd
, "Warning, resuming with mismatched exception signal (%d vs %d)\n",
2601 cpu
->exc_suspended
, exception
);
2603 memcpy(cpu
->registers
, cpu
->exc_suspend_registers
, sizeof(cpu
->registers
));
2605 else if(exception
!= 0 && cpu
->exc_suspended
== 0)
2607 sim_io_eprintf(sd
, "Warning, ignoring spontanous exception signal (%d)\n", exception
);
2609 cpu
->exc_suspended
= 0;
2613 /*---------------------------------------------------------------------------*/
2614 /*> EOF interp.c <*/