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.
21 The IDT monitor (found on the VR4300 board), seems to lie about
22 register contents. It seems to treat the registers as sign-extended
23 32-bit values. This cause *REAL* problems when single-stepping 64-bit
28 /* The TRACE manifests enable the provision of extra features. If they
29 are not defined then a simpler (quicker) simulator is constructed
30 without the required run-time checks, etc. */
31 #if 1 /* 0 to allow user build selection, 1 to force inclusion */
37 #include "sim-utils.h"
38 #include "sim-options.h"
39 #include "sim-assert.h"
65 #include "libiberty.h"
67 #include "callback.h" /* GDB simulator callback interface */
68 #include "remote-sim.h" /* GDB simulator interface */
76 char* pr_addr
PARAMS ((SIM_ADDR addr
));
77 char* pr_uword64
PARAMS ((uword64 addr
));
80 /* Within interp.c we refer to the sim_state and sim_cpu directly. */
85 /* The following reserved instruction value is used when a simulator
86 trap is required. NOTE: Care must be taken, since this value may be
87 used in later revisions of the MIPS ISA. */
89 #define RSVD_INSTRUCTION (0x00000005)
90 #define RSVD_INSTRUCTION_MASK (0xFC00003F)
92 #define RSVD_INSTRUCTION_ARG_SHIFT 6
93 #define RSVD_INSTRUCTION_ARG_MASK 0xFFFFF
96 /* Bits in the Debug register */
97 #define Debug_DBD 0x80000000 /* Debug Branch Delay */
98 #define Debug_DM 0x40000000 /* Debug Mode */
99 #define Debug_DBp 0x00000002 /* Debug Breakpoint indicator */
101 /*---------------------------------------------------------------------------*/
102 /*-- GDB simulator interface ------------------------------------------------*/
103 /*---------------------------------------------------------------------------*/
105 static void ColdReset
PARAMS((SIM_DESC sd
));
107 /*---------------------------------------------------------------------------*/
111 #define DELAYSLOT() {\
112 if (STATE & simDELAYSLOT)\
113 sim_io_eprintf(sd,"Delay slot already activated (branch in delay slot?)\n");\
114 STATE |= simDELAYSLOT;\
117 #define JALDELAYSLOT() {\
119 STATE |= simJALDELAYSLOT;\
123 STATE &= ~simDELAYSLOT;\
124 STATE |= simSKIPNEXT;\
127 #define CANCELDELAYSLOT() {\
129 STATE &= ~(simDELAYSLOT | simJALDELAYSLOT);\
132 #define INDELAYSLOT() ((STATE & simDELAYSLOT) != 0)
133 #define INJALDELAYSLOT() ((STATE & simJALDELAYSLOT) != 0)
135 /* Note that the monitor code essentially assumes this layout of memory.
136 If you change these, change the monitor code, too. */
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 (2 << 20)
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
,
188 mips_option_handler (sd
, cpu
, opt
, arg
, is_command
)
198 case OPTION_DINERO_TRACE
: /* ??? */
200 /* Eventually the simTRACE flag could be treated as a toggle, to
201 allow external control of the program points being traced
202 (i.e. only from main onwards, excluding the run-time setup,
204 for (cpu_nr
= 0; cpu_nr
< MAX_NR_PROCESSORS
; cpu_nr
++)
206 sim_cpu
*cpu
= STATE_CPU (sd
, cpu_nr
);
209 else if (strcmp (arg
, "yes") == 0)
211 else if (strcmp (arg
, "no") == 0)
213 else if (strcmp (arg
, "on") == 0)
215 else if (strcmp (arg
, "off") == 0)
219 fprintf (stderr
, "Unrecognized dinero-trace option `%s'\n", arg
);
226 Simulator constructed without dinero tracing support (for performance).\n\
227 Re-compile simulator with \"-DTRACE\" to enable this option.\n");
231 case OPTION_DINERO_FILE
:
233 if (optarg
!= NULL
) {
235 tmp
= (char *)malloc(strlen(optarg
) + 1);
238 sim_io_printf(sd
,"Failed to allocate buffer for tracefile name \"%s\"\n",optarg
);
244 sim_io_printf(sd
,"Placing trace information into file \"%s\"\n",tracefile
);
250 case OPTION_FIRMWARE
:
251 return sim_firmware_command (sd
, arg
);
257 board
= zalloc(strlen(arg
) + 1);
268 static const OPTION mips_options
[] =
270 { {"dinero-trace", optional_argument
, NULL
, OPTION_DINERO_TRACE
},
271 '\0', "on|off", "Enable dinero tracing",
272 mips_option_handler
},
273 { {"dinero-file", required_argument
, NULL
, OPTION_DINERO_FILE
},
274 '\0', "FILE", "Write dinero trace to FILE",
275 mips_option_handler
},
276 { {"firmware", required_argument
, NULL
, OPTION_FIRMWARE
},
277 '\0', "[idt|pmon|lsipmon|none][@ADDRESS]", "Emulate ROM monitor",
278 mips_option_handler
},
279 { {"board", required_argument
, NULL
, OPTION_BOARD
},
280 '\0', "none" /* rely on compile-time string concatenation for other options */
282 #define BOARD_JMR3904 "jmr3904"
284 #define BOARD_JMR3904_PAL "jmr3904pal"
285 "|" BOARD_JMR3904_PAL
286 #define BOARD_JMR3904_DEBUG "jmr3904debug"
287 "|" BOARD_JMR3904_DEBUG
288 #define BOARD_BSP "bsp"
291 , "Customize simulation for a particular board.", mips_option_handler
},
293 { {NULL
, no_argument
, NULL
, 0}, '\0', NULL
, NULL
, NULL
}
297 int interrupt_pending
;
300 interrupt_event (SIM_DESC sd
, void *data
)
302 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
303 address_word cia
= CIA_GET (cpu
);
306 interrupt_pending
= 0;
307 SignalExceptionInterrupt (1); /* interrupt "1" */
309 else if (!interrupt_pending
)
310 sim_events_schedule (sd
, 1, interrupt_event
, data
);
314 /*---------------------------------------------------------------------------*/
315 /*-- Device registration hook -----------------------------------------------*/
316 /*---------------------------------------------------------------------------*/
317 static void device_init(SIM_DESC sd
) {
319 extern void register_devices(SIM_DESC
);
320 register_devices(sd
);
324 /*---------------------------------------------------------------------------*/
325 /*-- GDB simulator interface ------------------------------------------------*/
326 /*---------------------------------------------------------------------------*/
329 sim_open (kind
, cb
, abfd
, argv
)
335 SIM_DESC sd
= sim_state_alloc (kind
, cb
);
336 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
338 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
340 /* FIXME: watchpoints code shouldn't need this */
341 STATE_WATCHPOINTS (sd
)->pc
= &(PC
);
342 STATE_WATCHPOINTS (sd
)->sizeof_pc
= sizeof (PC
);
343 STATE_WATCHPOINTS (sd
)->interrupt_handler
= interrupt_event
;
345 /* Initialize the mechanism for doing insn profiling. */
346 CPU_INSN_NAME (cpu
) = get_insn_name
;
347 CPU_MAX_INSNS (cpu
) = nr_itable_entries
;
351 if (sim_pre_argv_init (sd
, argv
[0]) != SIM_RC_OK
)
353 sim_add_option_table (sd
, NULL
, mips_options
);
356 /* getopt will print the error message so we just have to exit if this fails.
357 FIXME: Hmmm... in the case of gdb we need getopt to call
359 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
361 /* Uninstall the modules to avoid memory leaks,
362 file descriptor leaks, etc. */
363 sim_module_uninstall (sd
);
367 /* handle board-specific memory maps */
370 /* Allocate core managed memory */
373 /* For compatibility with the old code - under this (at level one)
374 are the kernel spaces K0 & K1. Both of these map to a single
375 smaller sub region */
376 sim_do_command(sd
," memory region 0x7fff8000,0x8000") ; /* MTZ- 32 k stack */
377 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x",
379 MEM_SIZE
, /* actual size */
384 else if (board
!= NULL
385 && (strcmp(board
, BOARD_BSP
) == 0))
389 STATE_ENVIRONMENT (sd
) = OPERATING_ENVIRONMENT
;
391 /* ROM: 0x9FC0_0000 - 0x9FFF_FFFF and 0xBFC0_0000 - 0xBFFF_FFFF */
392 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx,0x%0x",
394 4 * 1024 * 1024, /* 4 MB */
397 /* SRAM: 0x8000_0000 - 0x803F_FFFF and 0xA000_0000 - 0xA03F_FFFF */
398 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx,0x%0x",
400 4 * 1024 * 1024, /* 4 MB */
403 /* DRAM: 0x8800_0000 - 0x89FF_FFFF and 0xA800_0000 - 0xA9FF_FFFF */
404 for (i
=0; i
<8; i
++) /* 32 MB total */
406 unsigned size
= 4 * 1024 * 1024; /* 4 MB */
407 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx,0x%0x",
408 0x88000000 + (i
* size
),
410 0xA8000000 + (i
* size
));
414 else if (board
!= NULL
415 && (strcmp(board
, BOARD_JMR3904
) == 0 ||
416 strcmp(board
, BOARD_JMR3904_PAL
) == 0 ||
417 strcmp(board
, BOARD_JMR3904_DEBUG
) == 0))
419 /* match VIRTUAL memory layout of JMR-TX3904 board */
422 /* --- disable monitor unless forced on by user --- */
424 if (! firmware_option_p
)
426 idt_monitor_base
= 0;
427 pmon_monitor_base
= 0;
428 lsipmon_monitor_base
= 0;
431 /* --- environment --- */
433 STATE_ENVIRONMENT (sd
) = OPERATING_ENVIRONMENT
;
437 /* ROM: 0x9FC0_0000 - 0x9FFF_FFFF and 0xBFC0_0000 - 0xBFFF_FFFF */
438 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx,0x%0x",
440 4 * 1024 * 1024, /* 4 MB */
443 /* SRAM: 0x8000_0000 - 0x803F_FFFF and 0xA000_0000 - 0xA03F_FFFF */
444 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx,0x%0x",
446 4 * 1024 * 1024, /* 4 MB */
449 /* DRAM: 0x8800_0000 - 0x89FF_FFFF and 0xA800_0000 - 0xA9FF_FFFF */
450 for (i
=0; i
<8; i
++) /* 32 MB total */
452 unsigned size
= 4 * 1024 * 1024; /* 4 MB */
453 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx,0x%0x",
454 0x88000000 + (i
* size
),
456 0xA8000000 + (i
* size
));
459 /* Dummy memory regions for unsimulated devices - sorted by address */
461 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xB1000000, 0x400); /* ISA I/O */
462 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xB2100000, 0x004); /* ISA ctl */
463 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xB2500000, 0x004); /* LED/switch */
464 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xB2700000, 0x004); /* RTC */
465 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xB3C00000, 0x004); /* RTC */
466 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xFFFF8000, 0x900); /* DRAMC */
467 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xFFFF9000, 0x200); /* EBIF */
468 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xFFFFE000, 0x01c); /* EBIF */
469 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx", 0xFFFFF500, 0x300); /* PIO */
472 /* --- simulated devices --- */
473 sim_hw_parse (sd
, "/tx3904irc@0xffffc000/reg 0xffffc000 0x20");
474 sim_hw_parse (sd
, "/tx3904cpu");
475 sim_hw_parse (sd
, "/tx3904tmr@0xfffff000/reg 0xfffff000 0x100");
476 sim_hw_parse (sd
, "/tx3904tmr@0xfffff100/reg 0xfffff100 0x100");
477 sim_hw_parse (sd
, "/tx3904tmr@0xfffff200/reg 0xfffff200 0x100");
478 sim_hw_parse (sd
, "/tx3904sio@0xfffff300/reg 0xfffff300 0x100");
480 /* FIXME: poking at dv-sockser internals, use tcp backend if
481 --sockser_addr option was given.*/
482 extern char* sockser_addr
;
483 if(sockser_addr
== NULL
)
484 sim_hw_parse (sd
, "/tx3904sio@0xfffff300/backend stdio");
486 sim_hw_parse (sd
, "/tx3904sio@0xfffff300/backend tcp");
488 sim_hw_parse (sd
, "/tx3904sio@0xfffff400/reg 0xfffff400 0x100");
489 sim_hw_parse (sd
, "/tx3904sio@0xfffff400/backend stdio");
491 /* -- device connections --- */
492 sim_hw_parse (sd
, "/tx3904irc > ip level /tx3904cpu");
493 sim_hw_parse (sd
, "/tx3904tmr@0xfffff000 > int tmr0 /tx3904irc");
494 sim_hw_parse (sd
, "/tx3904tmr@0xfffff100 > int tmr1 /tx3904irc");
495 sim_hw_parse (sd
, "/tx3904tmr@0xfffff200 > int tmr2 /tx3904irc");
496 sim_hw_parse (sd
, "/tx3904sio@0xfffff300 > int sio0 /tx3904irc");
497 sim_hw_parse (sd
, "/tx3904sio@0xfffff400 > int sio1 /tx3904irc");
499 /* add PAL timer & I/O module */
500 if(! strcmp(board
, BOARD_JMR3904_PAL
))
503 sim_hw_parse (sd
, "/pal@0xffff0000");
504 sim_hw_parse (sd
, "/pal@0xffff0000/reg 0xffff0000 64");
506 /* wire up interrupt ports to irc */
507 sim_hw_parse (sd
, "/pal@0x31000000 > countdown tmr0 /tx3904irc");
508 sim_hw_parse (sd
, "/pal@0x31000000 > timer tmr1 /tx3904irc");
509 sim_hw_parse (sd
, "/pal@0x31000000 > int int0 /tx3904irc");
512 if(! strcmp(board
, BOARD_JMR3904_DEBUG
))
514 /* -- DEBUG: glue interrupt generators --- */
515 sim_hw_parse (sd
, "/glue@0xffff0000/reg 0xffff0000 0x50");
516 sim_hw_parse (sd
, "/glue@0xffff0000 > int0 int0 /tx3904irc");
517 sim_hw_parse (sd
, "/glue@0xffff0000 > int1 int1 /tx3904irc");
518 sim_hw_parse (sd
, "/glue@0xffff0000 > int2 int2 /tx3904irc");
519 sim_hw_parse (sd
, "/glue@0xffff0000 > int3 int3 /tx3904irc");
520 sim_hw_parse (sd
, "/glue@0xffff0000 > int4 int4 /tx3904irc");
521 sim_hw_parse (sd
, "/glue@0xffff0000 > int5 int5 /tx3904irc");
522 sim_hw_parse (sd
, "/glue@0xffff0000 > int6 int6 /tx3904irc");
523 sim_hw_parse (sd
, "/glue@0xffff0000 > int7 int7 /tx3904irc");
524 sim_hw_parse (sd
, "/glue@0xffff0000 > int8 dmac0 /tx3904irc");
525 sim_hw_parse (sd
, "/glue@0xffff0000 > int9 dmac1 /tx3904irc");
526 sim_hw_parse (sd
, "/glue@0xffff0000 > int10 dmac2 /tx3904irc");
527 sim_hw_parse (sd
, "/glue@0xffff0000 > int11 dmac3 /tx3904irc");
528 sim_hw_parse (sd
, "/glue@0xffff0000 > int12 sio0 /tx3904irc");
529 sim_hw_parse (sd
, "/glue@0xffff0000 > int13 sio1 /tx3904irc");
530 sim_hw_parse (sd
, "/glue@0xffff0000 > int14 tmr0 /tx3904irc");
531 sim_hw_parse (sd
, "/glue@0xffff0000 > int15 tmr1 /tx3904irc");
532 sim_hw_parse (sd
, "/glue@0xffff0000 > int16 tmr2 /tx3904irc");
533 sim_hw_parse (sd
, "/glue@0xffff0000 > int17 nmi /tx3904cpu");
541 /* check for/establish the a reference program image */
542 if (sim_analyze_program (sd
,
543 (STATE_PROG_ARGV (sd
) != NULL
544 ? *STATE_PROG_ARGV (sd
)
548 sim_module_uninstall (sd
);
552 /* Configure/verify the target byte order and other runtime
553 configuration options */
554 if (sim_config (sd
) != SIM_RC_OK
)
556 sim_module_uninstall (sd
);
560 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
562 /* Uninstall the modules to avoid memory leaks,
563 file descriptor leaks, etc. */
564 sim_module_uninstall (sd
);
568 /* verify assumptions the simulator made about the host type system.
569 This macro does not return if there is a problem */
570 SIM_ASSERT (sizeof(int) == (4 * sizeof(char)));
571 SIM_ASSERT (sizeof(word64
) == (8 * sizeof(char)));
573 /* This is NASTY, in that we are assuming the size of specific
577 for (rn
= 0; (rn
< (LAST_EMBED_REGNUM
+ 1)); rn
++)
580 cpu
->register_widths
[rn
] = WITH_TARGET_WORD_BITSIZE
;
581 else if ((rn
>= FGRIDX
) && (rn
< (FGRIDX
+ NR_FGR
)))
582 cpu
->register_widths
[rn
] = WITH_TARGET_FLOATING_POINT_BITSIZE
;
583 else if ((rn
>= 33) && (rn
<= 37))
584 cpu
->register_widths
[rn
] = WITH_TARGET_WORD_BITSIZE
;
585 else if ((rn
== SRIDX
)
588 || ((rn
>= 72) && (rn
<= 89)))
589 cpu
->register_widths
[rn
] = 32;
591 cpu
->register_widths
[rn
] = 0;
598 if (STATE
& simTRACE
)
603 sim_io_eprintf (sd, "idt@%x pmon@%x lsipmon@%x\n",
606 lsipmon_monitor_base);
609 /* Write the monitor trap address handlers into the monitor (eeprom)
610 address space. This can only be done once the target endianness
611 has been determined. */
612 if (idt_monitor_base
!= 0)
615 unsigned idt_monitor_size
= 1 << 11;
617 /* the default monitor region */
618 sim_do_commandf (sd
, "memory region 0x%x,0x%x",
619 idt_monitor_base
, idt_monitor_size
);
621 /* Entry into the IDT monitor is via fixed address vectors, and
622 not using machine instructions. To avoid clashing with use of
623 the MIPS TRAP system, we place our own (simulator specific)
624 "undefined" instructions into the relevant vector slots. */
625 for (loop
= 0; (loop
< idt_monitor_size
); loop
+= 4)
627 address_word vaddr
= (idt_monitor_base
+ loop
);
628 unsigned32 insn
= (RSVD_INSTRUCTION
|
629 (((loop
>> 2) & RSVD_INSTRUCTION_ARG_MASK
)
630 << RSVD_INSTRUCTION_ARG_SHIFT
));
632 sim_write (sd
, vaddr
, (char *)&insn
, sizeof (insn
));
636 if ((pmon_monitor_base
!= 0) || (lsipmon_monitor_base
!= 0))
638 /* The PMON monitor uses the same address space, but rather than
639 branching into it the address of a routine is loaded. We can
640 cheat for the moment, and direct the PMON routine to IDT style
641 instructions within the monitor space. This relies on the IDT
642 monitor not using the locations from 0xBFC00500 onwards as its
645 for (loop
= 0; (loop
< 24); loop
++)
647 unsigned32 value
= ((0x500 - 8) / 8); /* default UNDEFINED reason code */
663 value
= ((0x500 - 16) / 8); /* not an IDT reason code */
665 case 8: /* cliexit */
668 case 11: /* flush_cache */
673 SIM_ASSERT (idt_monitor_base
!= 0);
674 value
= ((unsigned int) idt_monitor_base
+ (value
* 8));
677 if (pmon_monitor_base
!= 0)
679 address_word vaddr
= (pmon_monitor_base
+ (loop
* 4));
680 sim_write (sd
, vaddr
, (char *)&value
, sizeof (value
));
683 if (lsipmon_monitor_base
!= 0)
685 address_word vaddr
= (lsipmon_monitor_base
+ (loop
* 4));
686 sim_write (sd
, vaddr
, (char *)&value
, sizeof (value
));
690 /* Write an abort sequence into the TRAP (common) exception vector
691 addresses. This is to catch code executing a TRAP (et.al.)
692 instruction without installing a trap handler. */
693 if ((idt_monitor_base
!= 0) ||
694 (pmon_monitor_base
!= 0) ||
695 (lsipmon_monitor_base
!= 0))
697 unsigned32 halt
[2] = { 0x2404002f /* addiu r4, r0, 47 */,
698 HALT_INSTRUCTION
/* BREAK */ };
701 sim_write (sd
, 0x80000000, (char *) halt
, sizeof (halt
));
702 sim_write (sd
, 0x80000180, (char *) halt
, sizeof (halt
));
703 sim_write (sd
, 0x80000200, (char *) halt
, sizeof (halt
));
704 /* XXX: Write here unconditionally? */
705 sim_write (sd
, 0xBFC00200, (char *) halt
, sizeof (halt
));
706 sim_write (sd
, 0xBFC00380, (char *) halt
, sizeof (halt
));
707 sim_write (sd
, 0xBFC00400, (char *) halt
, sizeof (halt
));
721 tracefh
= fopen(tracefile
,"wb+");
724 sim_io_eprintf(sd
,"Failed to create file \"%s\", writing trace information to stderr.\n",tracefile
);
730 /* Return name of an insn, used by insn profiling. */
732 get_insn_name (sim_cpu
*cpu
, int i
)
734 return itable
[i
].name
;
738 sim_close (sd
, quitting
)
743 printf("DBG: sim_close: entered (quitting = %d)\n",quitting
);
747 /* "quitting" is non-zero if we cannot hang on errors */
749 /* shut down modules */
750 sim_module_uninstall (sd
);
752 /* Ensure that any resources allocated through the callback
753 mechanism are released: */
754 sim_io_shutdown (sd
);
757 if (tracefh
!= NULL
&& tracefh
!= stderr
)
762 /* FIXME - free SD */
769 sim_write (sd
,addr
,buffer
,size
)
772 unsigned char *buffer
;
776 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
778 /* Return the number of bytes written, or zero if error. */
780 sim_io_printf(sd
,"sim_write(0x%s,buffer,%d);\n",pr_addr(addr
),size
);
783 /* We use raw read and write routines, since we do not want to count
784 the GDB memory accesses in our statistics gathering. */
786 for (index
= 0; index
< size
; index
++)
788 address_word vaddr
= (address_word
)addr
+ index
;
791 if (!address_translation (SD
, CPU
, NULL_CIA
, vaddr
, isDATA
, isSTORE
, &paddr
, &cca
, isRAW
))
793 if (sim_core_write_buffer (SD
, CPU
, read_map
, buffer
+ index
, paddr
, 1) != 1)
801 sim_read (sd
,addr
,buffer
,size
)
804 unsigned char *buffer
;
808 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
810 /* Return the number of bytes read, or zero if error. */
812 sim_io_printf(sd
,"sim_read(0x%s,buffer,%d);\n",pr_addr(addr
),size
);
815 for (index
= 0; (index
< size
); index
++)
817 address_word vaddr
= (address_word
)addr
+ index
;
820 if (!address_translation (SD
, CPU
, NULL_CIA
, vaddr
, isDATA
, isLOAD
, &paddr
, &cca
, isRAW
))
822 if (sim_core_read_buffer (SD
, CPU
, read_map
, buffer
+ index
, paddr
, 1) != 1)
830 sim_store_register (sd
,rn
,memory
,length
)
833 unsigned char *memory
;
836 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
837 /* NOTE: gdb (the client) stores registers in target byte order
838 while the simulator uses host byte order */
840 sim_io_printf(sd
,"sim_store_register(%d,*memory=0x%s);\n",rn
,pr_addr(*((SIM_ADDR
*)memory
)));
843 /* Unfortunately this suffers from the same problem as the register
844 numbering one. We need to know what the width of each logical
845 register number is for the architecture being simulated. */
847 if (cpu
->register_widths
[rn
] == 0)
849 sim_io_eprintf(sd
,"Invalid register width for %d (register store ignored)\n",rn
);
855 if (rn
>= FGRIDX
&& rn
< FGRIDX
+ NR_FGR
)
857 cpu
->fpr_state
[rn
- FGRIDX
] = fmt_uninterpreted
;
858 if (cpu
->register_widths
[rn
] == 32)
862 cpu
->fgr
[rn
- FGRIDX
] =
863 (unsigned32
) T2H_8 (*(unsigned64
*)memory
);
868 cpu
->fgr
[rn
- FGRIDX
] = T2H_4 (*(unsigned32
*)memory
);
874 cpu
->fgr
[rn
- FGRIDX
] = T2H_8 (*(unsigned64
*)memory
);
879 if (cpu
->register_widths
[rn
] == 32)
884 (unsigned32
) T2H_8 (*(unsigned64
*)memory
);
889 cpu
->registers
[rn
] = T2H_4 (*(unsigned32
*)memory
);
895 cpu
->registers
[rn
] = T2H_8 (*(unsigned64
*)memory
);
903 sim_fetch_register (sd
,rn
,memory
,length
)
906 unsigned char *memory
;
909 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
910 /* NOTE: gdb (the client) stores registers in target byte order
911 while the simulator uses host byte order */
913 #if 0 /* FIXME: doesn't compile */
914 sim_io_printf(sd
,"sim_fetch_register(%d=0x%s,mem) : place simulator registers into memory\n",rn
,pr_addr(registers
[rn
]));
918 if (cpu
->register_widths
[rn
] == 0)
920 sim_io_eprintf (sd
, "Invalid register width for %d (register fetch ignored)\n",rn
);
926 /* Any floating point register */
927 if (rn
>= FGRIDX
&& rn
< FGRIDX
+ NR_FGR
)
929 if (cpu
->register_widths
[rn
] == 32)
933 *(unsigned64
*)memory
=
934 H2T_8 ((unsigned32
) (cpu
->fgr
[rn
- FGRIDX
]));
939 *(unsigned32
*)memory
= H2T_4 (cpu
->fgr
[rn
- FGRIDX
]);
945 *(unsigned64
*)memory
= H2T_8 (cpu
->fgr
[rn
- FGRIDX
]);
950 if (cpu
->register_widths
[rn
] == 32)
954 *(unsigned64
*)memory
=
955 H2T_8 ((unsigned32
) (cpu
->registers
[rn
]));
960 *(unsigned32
*)memory
= H2T_4 ((unsigned32
)(cpu
->registers
[rn
]));
966 *(unsigned64
*)memory
= H2T_8 ((unsigned64
)(cpu
->registers
[rn
]));
975 sim_create_inferior (sd
, abfd
, argv
,env
)
983 #if 0 /* FIXME: doesn't compile */
984 printf("DBG: sim_create_inferior entered: start_address = 0x%s\n",
993 /* override PC value set by ColdReset () */
995 for (cpu_nr
= 0; cpu_nr
< sim_engine_nr_cpus (sd
); cpu_nr
++)
997 sim_cpu
*cpu
= STATE_CPU (sd
, cpu_nr
);
998 CIA_SET (cpu
, (unsigned64
) bfd_get_start_address (abfd
));
1002 #if 0 /* def DEBUG */
1005 /* We should really place the argv slot values into the argument
1006 registers, and onto the stack as required. However, this
1007 assumes that we have a stack defined, which is not
1008 necessarily true at the moment. */
1010 sim_io_printf(sd
,"sim_create_inferior() : passed arguments ignored\n");
1011 for (cptr
= argv
; (cptr
&& *cptr
); cptr
++)
1012 printf("DBG: arg \"%s\"\n",*cptr
);
1020 sim_do_command (sd
,cmd
)
1024 if (sim_args_command (sd
, cmd
) != SIM_RC_OK
)
1025 sim_io_printf (sd
, "Error: \"%s\" is not a valid MIPS simulator command.\n",
1029 /*---------------------------------------------------------------------------*/
1030 /*-- Private simulator support interface ------------------------------------*/
1031 /*---------------------------------------------------------------------------*/
1033 /* Read a null terminated string from memory, return in a buffer */
1035 fetch_str (SIM_DESC sd
,
1041 while (sim_read (sd
, addr
+ nr
, &null
, 1) == 1 && null
!= 0)
1043 buf
= NZALLOC (char, nr
+ 1);
1044 sim_read (sd
, addr
, buf
, nr
);
1049 /* Implements the "sim firmware" command:
1050 sim firmware NAME[@ADDRESS] --- emulate ROM monitor named NAME.
1051 NAME can be idt, pmon, or lsipmon. If omitted, ADDRESS
1052 defaults to the normal address for that monitor.
1053 sim firmware none --- don't emulate any ROM monitor. Useful
1054 if you need a clean address space. */
1056 sim_firmware_command (SIM_DESC sd
, char *arg
)
1058 int address_present
= 0;
1061 /* Signal occurrence of this option. */
1062 firmware_option_p
= 1;
1064 /* Parse out the address, if present. */
1066 char *p
= strchr (arg
, '@');
1070 address_present
= 1;
1071 p
++; /* skip over @ */
1073 address
= strtoul (p
, &q
, 0);
1076 sim_io_printf (sd
, "Invalid address given to the"
1077 "`sim firmware NAME@ADDRESS' command: %s\n",
1083 address_present
= 0;
1086 if (! strncmp (arg
, "idt", 3))
1088 idt_monitor_base
= address_present
? address
: 0xBFC00000;
1089 pmon_monitor_base
= 0;
1090 lsipmon_monitor_base
= 0;
1092 else if (! strncmp (arg
, "pmon", 4))
1094 /* pmon uses indirect calls. Hook into implied idt. */
1095 pmon_monitor_base
= address_present
? address
: 0xBFC00500;
1096 idt_monitor_base
= pmon_monitor_base
- 0x500;
1097 lsipmon_monitor_base
= 0;
1099 else if (! strncmp (arg
, "lsipmon", 7))
1101 /* lsipmon uses indirect calls. Hook into implied idt. */
1102 pmon_monitor_base
= 0;
1103 lsipmon_monitor_base
= address_present
? address
: 0xBFC00200;
1104 idt_monitor_base
= lsipmon_monitor_base
- 0x200;
1106 else if (! strncmp (arg
, "none", 4))
1108 if (address_present
)
1111 "The `sim firmware none' command does "
1112 "not take an `ADDRESS' argument.\n");
1115 idt_monitor_base
= 0;
1116 pmon_monitor_base
= 0;
1117 lsipmon_monitor_base
= 0;
1121 sim_io_printf (sd
, "\
1122 Unrecognized name given to the `sim firmware NAME' command: %s\n\
1123 Recognized firmware names are: `idt', `pmon', `lsipmon', and `none'.\n",
1133 /* Simple monitor interface (currently setup for the IDT and PMON monitors) */
1135 sim_monitor (SIM_DESC sd
,
1138 unsigned int reason
)
1141 printf("DBG: sim_monitor: entered (reason = %d)\n",reason
);
1144 /* The IDT monitor actually allows two instructions per vector
1145 slot. However, the simulator currently causes a trap on each
1146 individual instruction. We cheat, and lose the bottom bit. */
1149 /* The following callback functions are available, however the
1150 monitor we are simulating does not make use of them: get_errno,
1151 isatty, lseek, rename, system, time and unlink */
1155 case 6: /* int open(char *path,int flags) */
1157 char *path
= fetch_str (sd
, A0
);
1158 V0
= sim_io_open (sd
, path
, (int)A1
);
1163 case 7: /* int read(int file,char *ptr,int len) */
1167 char *buf
= zalloc (nr
);
1168 V0
= sim_io_read (sd
, fd
, buf
, nr
);
1169 sim_write (sd
, A1
, buf
, nr
);
1174 case 8: /* int write(int file,char *ptr,int len) */
1178 char *buf
= zalloc (nr
);
1179 sim_read (sd
, A1
, buf
, nr
);
1180 V0
= sim_io_write (sd
, fd
, buf
, nr
);
1185 case 10: /* int close(int file) */
1187 V0
= sim_io_close (sd
, (int)A0
);
1191 case 2: /* Densan monitor: char inbyte(int waitflag) */
1193 if (A0
== 0) /* waitflag == NOWAIT */
1194 V0
= (unsigned_word
)-1;
1196 /* Drop through to case 11 */
1198 case 11: /* char inbyte(void) */
1201 /* ensure that all output has gone... */
1202 sim_io_flush_stdout (sd
);
1203 if (sim_io_read_stdin (sd
, &tmp
, sizeof(char)) != sizeof(char))
1205 sim_io_error(sd
,"Invalid return from character read");
1206 V0
= (unsigned_word
)-1;
1209 V0
= (unsigned_word
)tmp
;
1213 case 3: /* Densan monitor: void co(char chr) */
1214 case 12: /* void outbyte(char chr) : write a byte to "stdout" */
1216 char tmp
= (char)(A0
& 0xFF);
1217 sim_io_write_stdout (sd
, &tmp
, sizeof(char));
1221 case 17: /* void _exit() */
1223 sim_io_eprintf (sd
, "sim_monitor(17): _exit(int reason) to be coded\n");
1224 sim_engine_halt (SD
, CPU
, NULL
, NULL_CIA
, sim_exited
,
1225 (unsigned int)(A0
& 0xFFFFFFFF));
1229 case 28 : /* PMON flush_cache */
1232 case 55: /* void get_mem_info(unsigned int *ptr) */
1233 /* in: A0 = pointer to three word memory location */
1234 /* out: [A0 + 0] = size */
1235 /* [A0 + 4] = instruction cache size */
1236 /* [A0 + 8] = data cache size */
1238 unsigned_4 value
= MEM_SIZE
/* FIXME STATE_MEM_SIZE (sd) */;
1239 unsigned_4 zero
= 0;
1241 sim_write (sd
, A0
+ 0, (char *)&value
, 4);
1242 sim_write (sd
, A0
+ 4, (char *)&zero
, 4);
1243 sim_write (sd
, A0
+ 8, (char *)&zero
, 4);
1244 /* sim_io_eprintf (sd, "sim: get_mem_info() depreciated\n"); */
1248 case 158 : /* PMON printf */
1249 /* in: A0 = pointer to format string */
1250 /* A1 = optional argument 1 */
1251 /* A2 = optional argument 2 */
1252 /* A3 = optional argument 3 */
1254 /* The following is based on the PMON printf source */
1256 address_word s
= A0
;
1258 signed_word
*ap
= &A1
; /* 1st argument */
1259 /* This isn't the quickest way, since we call the host print
1260 routine for every character almost. But it does avoid
1261 having to allocate and manage a temporary string buffer. */
1262 /* TODO: Include check that we only use three arguments (A1,
1264 while (sim_read (sd
, s
++, &c
, 1) && c
!= '\0')
1269 enum {FMT_RJUST
, FMT_LJUST
, FMT_RJUST0
, FMT_CENTER
} fmt
= FMT_RJUST
;
1270 int width
= 0, trunc
= 0, haddot
= 0, longlong
= 0;
1271 while (sim_read (sd
, s
++, &c
, 1) && c
!= '\0')
1273 if (strchr ("dobxXulscefg%", c
))
1288 else if (c
>= '1' && c
<= '9')
1292 while (sim_read (sd
, s
++, &c
, 1) == 1 && isdigit (c
))
1295 n
= (unsigned int)strtol(tmp
,NULL
,10);
1308 sim_io_printf (sd
, "%%");
1313 address_word p
= *ap
++;
1315 while (sim_read (sd
, p
++, &ch
, 1) == 1 && ch
!= '\0')
1316 sim_io_printf(sd
, "%c", ch
);
1319 sim_io_printf(sd
,"(null)");
1322 sim_io_printf (sd
, "%c", (int)*ap
++);
1327 sim_read (sd
, s
++, &c
, 1);
1331 sim_read (sd
, s
++, &c
, 1);
1334 if (strchr ("dobxXu", c
))
1336 word64 lv
= (word64
) *ap
++;
1338 sim_io_printf(sd
,"<binary not supported>");
1341 sprintf (tmp
, "%%%s%c", longlong
? "ll" : "", c
);
1343 sim_io_printf(sd
, tmp
, lv
);
1345 sim_io_printf(sd
, tmp
, (int)lv
);
1348 else if (strchr ("eEfgG", c
))
1350 double dbl
= *(double*)(ap
++);
1351 sprintf (tmp
, "%%%d.%d%c", width
, trunc
, c
);
1352 sim_io_printf (sd
, tmp
, dbl
);
1358 sim_io_printf(sd
, "%c", c
);
1364 sim_io_error (sd
, "TODO: sim_monitor(%d) : PC = 0x%s\n",
1365 reason
, pr_addr(cia
));
1371 /* Store a word into memory. */
1374 store_word (SIM_DESC sd
,
1383 if ((vaddr
& 3) != 0)
1384 SignalExceptionAddressStore ();
1387 if (AddressTranslation (vaddr
, isDATA
, isSTORE
, &paddr
, &uncached
,
1390 const uword64 mask
= 7;
1394 paddr
= (paddr
& ~mask
) | ((paddr
& mask
) ^ (ReverseEndian
<< 2));
1395 byte
= (vaddr
& mask
) ^ (BigEndianCPU
<< 2);
1396 memval
= ((uword64
) val
) << (8 * byte
);
1397 StoreMemory (uncached
, AccessLength_WORD
, memval
, 0, paddr
, vaddr
,
1403 /* Load a word from memory. */
1406 load_word (SIM_DESC sd
,
1411 if ((vaddr
& 3) != 0)
1413 SIM_CORE_SIGNAL (SD
, cpu
, cia
, read_map
, AccessLength_WORD
+1, vaddr
, read_transfer
, sim_core_unaligned_signal
);
1420 if (AddressTranslation (vaddr
, isDATA
, isLOAD
, &paddr
, &uncached
,
1423 const uword64 mask
= 0x7;
1424 const unsigned int reverse
= ReverseEndian
? 1 : 0;
1425 const unsigned int bigend
= BigEndianCPU
? 1 : 0;
1429 paddr
= (paddr
& ~mask
) | ((paddr
& mask
) ^ (reverse
<< 2));
1430 LoadMemory (&memval
,NULL
,uncached
, AccessLength_WORD
, paddr
, vaddr
,
1432 byte
= (vaddr
& mask
) ^ (bigend
<< 2);
1433 return SIGNEXTEND (((memval
>> (8 * byte
)) & 0xffffffff), 32);
1440 /* Simulate the mips16 entry and exit pseudo-instructions. These
1441 would normally be handled by the reserved instruction exception
1442 code, but for ease of simulation we just handle them directly. */
1445 mips16_entry (SIM_DESC sd
,
1450 int aregs
, sregs
, rreg
;
1453 printf("DBG: mips16_entry: entered (insn = 0x%08X)\n",insn
);
1456 aregs
= (insn
& 0x700) >> 8;
1457 sregs
= (insn
& 0x0c0) >> 6;
1458 rreg
= (insn
& 0x020) >> 5;
1460 /* This should be checked by the caller. */
1469 /* This is the entry pseudo-instruction. */
1471 for (i
= 0; i
< aregs
; i
++)
1472 store_word (SD
, CPU
, cia
, (uword64
) (SP
+ 4 * i
), GPR
[i
+ 4]);
1480 store_word (SD
, CPU
, cia
, (uword64
) tsp
, RA
);
1483 for (i
= 0; i
< sregs
; i
++)
1486 store_word (SD
, CPU
, cia
, (uword64
) tsp
, GPR
[16 + i
]);
1494 /* This is the exit pseudo-instruction. */
1501 RA
= load_word (SD
, CPU
, cia
, (uword64
) tsp
);
1504 for (i
= 0; i
< sregs
; i
++)
1507 GPR
[i
+ 16] = load_word (SD
, CPU
, cia
, (uword64
) tsp
);
1512 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
1516 FGR
[0] = WORD64LO (GPR
[4]);
1517 FPR_STATE
[0] = fmt_uninterpreted
;
1519 else if (aregs
== 6)
1521 FGR
[0] = WORD64LO (GPR
[5]);
1522 FGR
[1] = WORD64LO (GPR
[4]);
1523 FPR_STATE
[0] = fmt_uninterpreted
;
1524 FPR_STATE
[1] = fmt_uninterpreted
;
1533 /*-- trace support ----------------------------------------------------------*/
1535 /* The TRACE support is provided (if required) in the memory accessing
1536 routines. Since we are also providing the architecture specific
1537 features, the architecture simulation code can also deal with
1538 notifying the TRACE world of cache flushes, etc. Similarly we do
1539 not need to provide profiling support in the simulator engine,
1540 since we can sample in the instruction fetch control loop. By
1541 defining the TRACE manifest, we add tracing as a run-time
1545 /* Tracing by default produces "din" format (as required by
1546 dineroIII). Each line of such a trace file *MUST* have a din label
1547 and address field. The rest of the line is ignored, so comments can
1548 be included if desired. The first field is the label which must be
1549 one of the following values:
1554 3 escape record (treated as unknown access type)
1555 4 escape record (causes cache flush)
1557 The address field is a 32bit (lower-case) hexadecimal address
1558 value. The address should *NOT* be preceded by "0x".
1560 The size of the memory transfer is not important when dealing with
1561 cache lines (as long as no more than a cache line can be
1562 transferred in a single operation :-), however more information
1563 could be given following the dineroIII requirement to allow more
1564 complete memory and cache simulators to provide better
1565 results. i.e. the University of Pisa has a cache simulator that can
1566 also take bus size and speed as (variable) inputs to calculate
1567 complete system performance (a much more useful ability when trying
1568 to construct an end product, rather than a processor). They
1569 currently have an ARM version of their tool called ChARM. */
1573 dotrace (SIM_DESC sd
,
1581 if (STATE
& simTRACE
) {
1583 fprintf(tracefh
,"%d %s ; width %d ; ",
1587 va_start(ap
,comment
);
1588 vfprintf(tracefh
,comment
,ap
);
1590 fprintf(tracefh
,"\n");
1592 /* NOTE: Since the "din" format will only accept 32bit addresses, and
1593 we may be generating 64bit ones, we should put the hi-32bits of the
1594 address into the comment field. */
1596 /* TODO: Provide a buffer for the trace lines. We can then avoid
1597 performing writes until the buffer is filled, or the file is
1600 /* NOTE: We could consider adding a comment field to the "din" file
1601 produced using type 3 markers (unknown access). This would then
1602 allow information about the program that the "din" is for, and
1603 the MIPs world that was being simulated, to be placed into the
1610 /*---------------------------------------------------------------------------*/
1611 /*-- simulator engine -------------------------------------------------------*/
1612 /*---------------------------------------------------------------------------*/
1615 ColdReset (SIM_DESC sd
)
1618 for (cpu_nr
= 0; cpu_nr
< sim_engine_nr_cpus (sd
); cpu_nr
++)
1620 sim_cpu
*cpu
= STATE_CPU (sd
, cpu_nr
);
1621 /* RESET: Fixed PC address: */
1622 PC
= (unsigned_word
) UNSIGNED64 (0xFFFFFFFFBFC00000);
1623 /* The reset vector address is in the unmapped, uncached memory space. */
1625 SR
&= ~(status_SR
| status_TS
| status_RP
);
1626 SR
|= (status_ERL
| status_BEV
);
1628 /* Cheat and allow access to the complete register set immediately */
1629 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
1630 && WITH_TARGET_WORD_BITSIZE
== 64)
1631 SR
|= status_FR
; /* 64bit registers */
1633 /* Ensure that any instructions with pending register updates are
1635 PENDING_INVALIDATE();
1637 /* Initialise the FPU registers to the unknown state */
1638 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
1641 for (rn
= 0; (rn
< 32); rn
++)
1642 FPR_STATE
[rn
] = fmt_uninterpreted
;
1651 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
1652 /* Signal an exception condition. This will result in an exception
1653 that aborts the instruction. The instruction operation pseudocode
1654 will never see a return from this function call. */
1657 signal_exception (SIM_DESC sd
,
1665 sim_io_printf(sd
,"DBG: SignalException(%d) PC = 0x%s\n",exception
,pr_addr(cia
));
1668 /* Ensure that any active atomic read/modify/write operation will fail: */
1671 /* Save registers before interrupt dispatching */
1672 #ifdef SIM_CPU_EXCEPTION_TRIGGER
1673 SIM_CPU_EXCEPTION_TRIGGER(sd
, cpu
, cia
);
1676 switch (exception
) {
1678 case DebugBreakPoint
:
1679 if (! (Debug
& Debug_DM
))
1685 Debug
|= Debug_DBD
; /* signaled from within in delay slot */
1686 DEPC
= cia
- 4; /* reference the branch instruction */
1690 Debug
&= ~Debug_DBD
; /* not signaled from within a delay slot */
1694 Debug
|= Debug_DM
; /* in debugging mode */
1695 Debug
|= Debug_DBp
; /* raising a DBp exception */
1697 sim_engine_restart (SD
, CPU
, NULL
, NULL_CIA
);
1701 case ReservedInstruction
:
1704 unsigned int instruction
;
1705 va_start(ap
,exception
);
1706 instruction
= va_arg(ap
,unsigned int);
1708 /* Provide simple monitor support using ReservedInstruction
1709 exceptions. The following code simulates the fixed vector
1710 entry points into the IDT monitor by causing a simulator
1711 trap, performing the monitor operation, and returning to
1712 the address held in the $ra register (standard PCS return
1713 address). This means we only need to pre-load the vector
1714 space with suitable instruction values. For systems were
1715 actual trap instructions are used, we would not need to
1716 perform this magic. */
1717 if ((instruction
& RSVD_INSTRUCTION_MASK
) == RSVD_INSTRUCTION
)
1719 sim_monitor (SD
, CPU
, cia
, ((instruction
>> RSVD_INSTRUCTION_ARG_SHIFT
) & RSVD_INSTRUCTION_ARG_MASK
) );
1720 /* NOTE: This assumes that a branch-and-link style
1721 instruction was used to enter the vector (which is the
1722 case with the current IDT monitor). */
1723 sim_engine_restart (SD
, CPU
, NULL
, RA
);
1725 /* Look for the mips16 entry and exit instructions, and
1726 simulate a handler for them. */
1727 else if ((cia
& 1) != 0
1728 && (instruction
& 0xf81f) == 0xe809
1729 && (instruction
& 0x0c0) != 0x0c0)
1731 mips16_entry (SD
, CPU
, cia
, instruction
);
1732 sim_engine_restart (sd
, NULL
, NULL
, NULL_CIA
);
1734 /* else fall through to normal exception processing */
1735 sim_io_eprintf(sd
,"ReservedInstruction at PC = 0x%s\n", pr_addr (cia
));
1739 /* Store exception code into current exception id variable (used
1742 /* TODO: If not simulating exceptions then stop the simulator
1743 execution. At the moment we always stop the simulation. */
1745 #ifdef SUBTARGET_R3900
1746 /* update interrupt-related registers */
1748 /* insert exception code in bits 6:2 */
1749 CAUSE
= LSMASKED32(CAUSE
, 31, 7) | LSINSERTED32(exception
, 6, 2);
1750 /* shift IE/KU history bits left */
1751 SR
= LSMASKED32(SR
, 31, 4) | LSINSERTED32(LSEXTRACTED32(SR
, 3, 0), 5, 2);
1753 if (STATE
& simDELAYSLOT
)
1755 STATE
&= ~simDELAYSLOT
;
1757 EPC
= (cia
- 4); /* reference the branch instruction */
1762 if (SR
& status_BEV
)
1763 PC
= (signed)0xBFC00000 + 0x180;
1765 PC
= (signed)0x80000000 + 0x080;
1767 /* See figure 5-17 for an outline of the code below */
1768 if (! (SR
& status_EXL
))
1770 CAUSE
= (exception
<< 2);
1771 if (STATE
& simDELAYSLOT
)
1773 STATE
&= ~simDELAYSLOT
;
1775 EPC
= (cia
- 4); /* reference the branch instruction */
1779 /* FIXME: TLB et.al. */
1780 /* vector = 0x180; */
1784 CAUSE
= (exception
<< 2);
1785 /* vector = 0x180; */
1788 /* Store exception code into current exception id variable (used
1791 if (SR
& status_BEV
)
1792 PC
= (signed)0xBFC00200 + 0x180;
1794 PC
= (signed)0x80000000 + 0x180;
1797 switch ((CAUSE
>> 2) & 0x1F)
1800 /* Interrupts arrive during event processing, no need to
1806 #ifdef SUBTARGET_3900
1807 /* Exception vector: BEV=0 BFC00000 / BEF=1 BFC00000 */
1808 PC
= (signed)0xBFC00000;
1809 #endif SUBTARGET_3900
1812 case TLBModification
:
1817 case InstructionFetch
:
1819 /* The following is so that the simulator will continue from the
1820 exception handler address. */
1821 sim_engine_halt (SD
, CPU
, NULL
, PC
,
1822 sim_stopped
, SIM_SIGBUS
);
1824 case ReservedInstruction
:
1825 case CoProcessorUnusable
:
1827 sim_engine_halt (SD
, CPU
, NULL
, PC
,
1828 sim_stopped
, SIM_SIGILL
);
1830 case IntegerOverflow
:
1832 sim_engine_halt (SD
, CPU
, NULL
, PC
,
1833 sim_stopped
, SIM_SIGFPE
);
1836 sim_engine_halt (SD
, CPU
, NULL
, PC
, sim_stopped
, SIM_SIGTRAP
);
1841 sim_engine_restart (SD
, CPU
, NULL
, PC
);
1846 sim_engine_halt (SD
, CPU
, NULL
, PC
,
1847 sim_stopped
, SIM_SIGTRAP
);
1849 default : /* Unknown internal exception */
1851 sim_engine_halt (SD
, CPU
, NULL
, PC
,
1852 sim_stopped
, SIM_SIGABRT
);
1856 case SimulatorFault
:
1860 va_start(ap
,exception
);
1861 msg
= va_arg(ap
,char *);
1863 sim_engine_abort (SD
, CPU
, NULL_CIA
,
1864 "FATAL: Simulator error \"%s\"\n",msg
);
1873 #if defined(WARN_RESULT)
1874 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
1875 /* This function indicates that the result of the operation is
1876 undefined. However, this should not affect the instruction
1877 stream. All that is meant to happen is that the destination
1878 register is set to an undefined result. To keep the simulator
1879 simple, we just don't bother updating the destination register, so
1880 the overall result will be undefined. If desired we can stop the
1881 simulator by raising a pseudo-exception. */
1882 #define UndefinedResult() undefined_result (sd,cia)
1884 undefined_result(sd
,cia
)
1888 sim_io_eprintf(sd
,"UndefinedResult: PC = 0x%s\n",pr_addr(cia
));
1889 #if 0 /* Disabled for the moment, since it actually happens a lot at the moment. */
1894 #endif /* WARN_RESULT */
1896 /*-- FPU support routines ---------------------------------------------------*/
1898 /* Numbers are held in normalized form. The SINGLE and DOUBLE binary
1899 formats conform to ANSI/IEEE Std 754-1985. */
1900 /* SINGLE precision floating:
1901 * seeeeeeeefffffffffffffffffffffff
1903 * e = 8bits = exponent
1904 * f = 23bits = fraction
1906 /* SINGLE precision fixed:
1907 * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
1909 * i = 31bits = integer
1911 /* DOUBLE precision floating:
1912 * seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
1914 * e = 11bits = exponent
1915 * f = 52bits = fraction
1917 /* DOUBLE precision fixed:
1918 * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
1920 * i = 63bits = integer
1923 /* Extract sign-bit: */
1924 #define FP_S_s(v) (((v) & ((unsigned)1 << 31)) ? 1 : 0)
1925 #define FP_D_s(v) (((v) & ((uword64)1 << 63)) ? 1 : 0)
1926 /* Extract biased exponent: */
1927 #define FP_S_be(v) (((v) >> 23) & 0xFF)
1928 #define FP_D_be(v) (((v) >> 52) & 0x7FF)
1929 /* Extract unbiased Exponent: */
1930 #define FP_S_e(v) (FP_S_be(v) - 0x7F)
1931 #define FP_D_e(v) (FP_D_be(v) - 0x3FF)
1932 /* Extract complete fraction field: */
1933 #define FP_S_f(v) ((v) & ~((unsigned)0x1FF << 23))
1934 #define FP_D_f(v) ((v) & ~((uword64)0xFFF << 52))
1935 /* Extract numbered fraction bit: */
1936 #define FP_S_fb(b,v) (((v) & (1 << (23 - (b)))) ? 1 : 0)
1937 #define FP_D_fb(b,v) (((v) & (1 << (52 - (b)))) ? 1 : 0)
1939 /* Explicit QNaN values used when value required: */
1940 #define FPQNaN_SINGLE (0x7FBFFFFF)
1941 #define FPQNaN_WORD (0x7FFFFFFF)
1942 #define FPQNaN_DOUBLE (((uword64)0x7FF7FFFF << 32) | 0xFFFFFFFF)
1943 #define FPQNaN_LONG (((uword64)0x7FFFFFFF << 32) | 0xFFFFFFFF)
1945 /* Explicit Infinity values used when required: */
1946 #define FPINF_SINGLE (0x7F800000)
1947 #define FPINF_DOUBLE (((uword64)0x7FF00000 << 32) | 0x00000000)
1949 #define RMMODE(v) (((v) == FP_RM_NEAREST) ? "Round" : (((v) == FP_RM_TOZERO) ? "Trunc" : (((v) == FP_RM_TOPINF) ? "Ceil" : "Floor")))
1950 #define DOFMT(v) (((v) == fmt_single) ? "single" : (((v) == fmt_double) ? "double" : (((v) == fmt_word) ? "word" : (((v) == fmt_long) ? "long" : (((v) == fmt_unknown) ? "<unknown>" : (((v) == fmt_uninterpreted) ? "<uninterpreted>" : (((v) == fmt_uninterpreted_32) ? "<uninterpreted_32>" : (((v) == fmt_uninterpreted_64) ? "<uninterpreted_64>" : "<format error>"))))))))
1953 value_fpr (SIM_DESC sd
,
1962 /* Treat unused register values, as fixed-point 64bit values: */
1963 if ((fmt
== fmt_uninterpreted
) || (fmt
== fmt_unknown
))
1965 /* If request to read data as "uninterpreted", then use the current
1967 fmt
= FPR_STATE
[fpr
];
1972 /* For values not yet accessed, set to the desired format: */
1973 if (FPR_STATE
[fpr
] == fmt_uninterpreted
) {
1974 FPR_STATE
[fpr
] = fmt
;
1976 printf("DBG: Register %d was fmt_uninterpreted. Now %s\n",fpr
,DOFMT(fmt
));
1979 if (fmt
!= FPR_STATE
[fpr
]) {
1980 sim_io_eprintf(sd
,"FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",fpr
,DOFMT(FPR_STATE
[fpr
]),DOFMT(fmt
),pr_addr(cia
));
1981 FPR_STATE
[fpr
] = fmt_unknown
;
1984 if (FPR_STATE
[fpr
] == fmt_unknown
) {
1985 /* Set QNaN value: */
1988 value
= FPQNaN_SINGLE
;
1992 value
= FPQNaN_DOUBLE
;
1996 value
= FPQNaN_WORD
;
2000 value
= FPQNaN_LONG
;
2007 } else if (SizeFGR() == 64) {
2011 value
= (FGR
[fpr
] & 0xFFFFFFFF);
2014 case fmt_uninterpreted
:
2028 value
= (FGR
[fpr
] & 0xFFFFFFFF);
2031 case fmt_uninterpreted
:
2034 if ((fpr
& 1) == 0) { /* even registers only */
2036 printf("DBG: ValueFPR: FGR[%d] = %s, FGR[%d] = %s\n",
2037 fpr
+1, pr_uword64( (uword64
) FGR
[fpr
+1] ),
2038 fpr
, pr_uword64( (uword64
) FGR
[fpr
] ));
2040 value
= ((((uword64
)FGR
[fpr
+1]) << 32) | (FGR
[fpr
] & 0xFFFFFFFF));
2042 SignalException(ReservedInstruction
,0);
2053 SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR()");
2056 printf("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d\n",fpr
,DOFMT(fmt
),pr_uword64(value
),pr_addr(cia
),SizeFGR());
2063 store_fpr (SIM_DESC sd
,
2073 printf("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d,\n",fpr
,DOFMT(fmt
),pr_uword64(value
),pr_addr(cia
),SizeFGR());
2076 if (SizeFGR() == 64) {
2078 case fmt_uninterpreted_32
:
2079 fmt
= fmt_uninterpreted
;
2082 if (STATE_VERBOSE_P(SD
))
2083 sim_io_eprintf (SD
, "Warning: PC 0x%s: interp.c store_fpr DEADCODE\n",
2085 FGR
[fpr
] = (((uword64
)0xDEADC0DE << 32) | (value
& 0xFFFFFFFF));
2086 FPR_STATE
[fpr
] = fmt
;
2089 case fmt_uninterpreted_64
:
2090 fmt
= fmt_uninterpreted
;
2091 case fmt_uninterpreted
:
2095 FPR_STATE
[fpr
] = fmt
;
2099 FPR_STATE
[fpr
] = fmt_unknown
;
2105 case fmt_uninterpreted_32
:
2106 fmt
= fmt_uninterpreted
;
2109 FGR
[fpr
] = (value
& 0xFFFFFFFF);
2110 FPR_STATE
[fpr
] = fmt
;
2113 case fmt_uninterpreted_64
:
2114 fmt
= fmt_uninterpreted
;
2115 case fmt_uninterpreted
:
2118 if ((fpr
& 1) == 0) { /* even register number only */
2119 FGR
[fpr
+1] = (value
>> 32);
2120 FGR
[fpr
] = (value
& 0xFFFFFFFF);
2121 FPR_STATE
[fpr
+ 1] = fmt
;
2122 FPR_STATE
[fpr
] = fmt
;
2124 FPR_STATE
[fpr
] = fmt_unknown
;
2125 FPR_STATE
[fpr
+ 1] = fmt_unknown
;
2126 SignalException(ReservedInstruction
,0);
2131 FPR_STATE
[fpr
] = fmt_unknown
;
2136 #if defined(WARN_RESULT)
2139 #endif /* WARN_RESULT */
2142 SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR()");
2145 printf("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",fpr
,pr_uword64(FGR
[fpr
]),DOFMT(fmt
));
2162 sim_fpu_32to (&wop
, op
);
2163 boolean
= sim_fpu_is_nan (&wop
);
2170 sim_fpu_64to (&wop
, op
);
2171 boolean
= sim_fpu_is_nan (&wop
);
2175 fprintf (stderr
, "Bad switch\n");
2180 printf("DBG: NaN: returning %d for 0x%s (format = %s)\n",boolean
,pr_addr(op
),DOFMT(fmt
));
2194 printf("DBG: Infinity: format %s 0x%s\n",DOFMT(fmt
),pr_addr(op
));
2201 sim_fpu_32to (&wop
, op
);
2202 boolean
= sim_fpu_is_infinity (&wop
);
2208 sim_fpu_64to (&wop
, op
);
2209 boolean
= sim_fpu_is_infinity (&wop
);
2213 printf("DBG: TODO: unrecognised format (%s) for Infinity check\n",DOFMT(fmt
));
2218 printf("DBG: Infinity: returning %d for 0x%s (format = %s)\n",boolean
,pr_addr(op
),DOFMT(fmt
));
2232 /* Argument checking already performed by the FPCOMPARE code */
2235 printf("DBG: Less: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2238 /* The format type should already have been checked: */
2244 sim_fpu_32to (&wop1
, op1
);
2245 sim_fpu_32to (&wop2
, op2
);
2246 boolean
= sim_fpu_is_lt (&wop1
, &wop2
);
2253 sim_fpu_64to (&wop1
, op1
);
2254 sim_fpu_64to (&wop2
, op2
);
2255 boolean
= sim_fpu_is_lt (&wop1
, &wop2
);
2259 fprintf (stderr
, "Bad switch\n");
2264 printf("DBG: Less: returning %d (format = %s)\n",boolean
,DOFMT(fmt
));
2278 /* Argument checking already performed by the FPCOMPARE code */
2281 printf("DBG: Equal: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2284 /* The format type should already have been checked: */
2290 sim_fpu_32to (&wop1
, op1
);
2291 sim_fpu_32to (&wop2
, op2
);
2292 boolean
= sim_fpu_is_eq (&wop1
, &wop2
);
2299 sim_fpu_64to (&wop1
, op1
);
2300 sim_fpu_64to (&wop2
, op2
);
2301 boolean
= sim_fpu_is_eq (&wop1
, &wop2
);
2305 fprintf (stderr
, "Bad switch\n");
2310 printf("DBG: Equal: returning %d (format = %s)\n",boolean
,DOFMT(fmt
));
2317 AbsoluteValue(op
,fmt
)
2324 printf("DBG: AbsoluteValue: %s: op = 0x%s\n",DOFMT(fmt
),pr_addr(op
));
2327 /* The format type should already have been checked: */
2333 sim_fpu_32to (&wop
, op
);
2334 sim_fpu_abs (&wop
, &wop
);
2335 sim_fpu_to32 (&ans
, &wop
);
2343 sim_fpu_64to (&wop
, op
);
2344 sim_fpu_abs (&wop
, &wop
);
2345 sim_fpu_to64 (&ans
, &wop
);
2350 fprintf (stderr
, "Bad switch\n");
2365 printf("DBG: Negate: %s: op = 0x%s\n",DOFMT(fmt
),pr_addr(op
));
2368 /* The format type should already have been checked: */
2374 sim_fpu_32to (&wop
, op
);
2375 sim_fpu_neg (&wop
, &wop
);
2376 sim_fpu_to32 (&ans
, &wop
);
2384 sim_fpu_64to (&wop
, op
);
2385 sim_fpu_neg (&wop
, &wop
);
2386 sim_fpu_to64 (&ans
, &wop
);
2391 fprintf (stderr
, "Bad switch\n");
2407 printf("DBG: Add: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2410 /* The registers must specify FPRs valid for operands of type
2411 "fmt". If they are not valid, the result is undefined. */
2413 /* The format type should already have been checked: */
2421 sim_fpu_32to (&wop1
, op1
);
2422 sim_fpu_32to (&wop2
, op2
);
2423 sim_fpu_add (&ans
, &wop1
, &wop2
);
2424 sim_fpu_to32 (&res
, &ans
);
2434 sim_fpu_64to (&wop1
, op1
);
2435 sim_fpu_64to (&wop2
, op2
);
2436 sim_fpu_add (&ans
, &wop1
, &wop2
);
2437 sim_fpu_to64 (&res
, &ans
);
2442 fprintf (stderr
, "Bad switch\n");
2447 printf("DBG: Add: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2462 printf("DBG: Sub: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2465 /* The registers must specify FPRs valid for operands of type
2466 "fmt". If they are not valid, the result is undefined. */
2468 /* The format type should already have been checked: */
2476 sim_fpu_32to (&wop1
, op1
);
2477 sim_fpu_32to (&wop2
, op2
);
2478 sim_fpu_sub (&ans
, &wop1
, &wop2
);
2479 sim_fpu_to32 (&res
, &ans
);
2489 sim_fpu_64to (&wop1
, op1
);
2490 sim_fpu_64to (&wop2
, op2
);
2491 sim_fpu_sub (&ans
, &wop1
, &wop2
);
2492 sim_fpu_to64 (&res
, &ans
);
2497 fprintf (stderr
, "Bad switch\n");
2502 printf("DBG: Sub: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2509 Multiply(op1
,op2
,fmt
)
2517 printf("DBG: Multiply: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2520 /* The registers must specify FPRs valid for operands of type
2521 "fmt". If they are not valid, the result is undefined. */
2523 /* The format type should already have been checked: */
2531 sim_fpu_32to (&wop1
, op1
);
2532 sim_fpu_32to (&wop2
, op2
);
2533 sim_fpu_mul (&ans
, &wop1
, &wop2
);
2534 sim_fpu_to32 (&res
, &ans
);
2544 sim_fpu_64to (&wop1
, op1
);
2545 sim_fpu_64to (&wop2
, op2
);
2546 sim_fpu_mul (&ans
, &wop1
, &wop2
);
2547 sim_fpu_to64 (&res
, &ans
);
2552 fprintf (stderr
, "Bad switch\n");
2557 printf("DBG: Multiply: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2572 printf("DBG: Divide: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2575 /* The registers must specify FPRs valid for operands of type
2576 "fmt". If they are not valid, the result is undefined. */
2578 /* The format type should already have been checked: */
2586 sim_fpu_32to (&wop1
, op1
);
2587 sim_fpu_32to (&wop2
, op2
);
2588 sim_fpu_div (&ans
, &wop1
, &wop2
);
2589 sim_fpu_to32 (&res
, &ans
);
2599 sim_fpu_64to (&wop1
, op1
);
2600 sim_fpu_64to (&wop2
, op2
);
2601 sim_fpu_div (&ans
, &wop1
, &wop2
);
2602 sim_fpu_to64 (&res
, &ans
);
2607 fprintf (stderr
, "Bad switch\n");
2612 printf("DBG: Divide: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2626 printf("DBG: Recip: %s: op = 0x%s\n",DOFMT(fmt
),pr_addr(op
));
2629 /* The registers must specify FPRs valid for operands of type
2630 "fmt". If they are not valid, the result is undefined. */
2632 /* The format type should already have been checked: */
2639 sim_fpu_32to (&wop
, op
);
2640 sim_fpu_inv (&ans
, &wop
);
2641 sim_fpu_to32 (&res
, &ans
);
2650 sim_fpu_64to (&wop
, op
);
2651 sim_fpu_inv (&ans
, &wop
);
2652 sim_fpu_to64 (&res
, &ans
);
2657 fprintf (stderr
, "Bad switch\n");
2662 printf("DBG: Recip: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2676 printf("DBG: SquareRoot: %s: op = 0x%s\n",DOFMT(fmt
),pr_addr(op
));
2679 /* The registers must specify FPRs valid for operands of type
2680 "fmt". If they are not valid, the result is undefined. */
2682 /* The format type should already have been checked: */
2689 sim_fpu_32to (&wop
, op
);
2690 sim_fpu_sqrt (&ans
, &wop
);
2691 sim_fpu_to32 (&res
, &ans
);
2700 sim_fpu_64to (&wop
, op
);
2701 sim_fpu_sqrt (&ans
, &wop
);
2702 sim_fpu_to64 (&res
, &ans
);
2707 fprintf (stderr
, "Bad switch\n");
2712 printf("DBG: SquareRoot: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2728 printf("DBG: Max: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2731 /* The registers must specify FPRs valid for operands of type
2732 "fmt". If they are not valid, the result is undefined. */
2734 /* The format type should already have been checked: */
2741 sim_fpu_32to (&wop1
, op1
);
2742 sim_fpu_32to (&wop2
, op2
);
2743 cmp
= sim_fpu_cmp (&wop1
, &wop2
);
2750 sim_fpu_64to (&wop1
, op1
);
2751 sim_fpu_64to (&wop2
, op2
);
2752 cmp
= sim_fpu_cmp (&wop1
, &wop2
);
2756 fprintf (stderr
, "Bad switch\n");
2762 case SIM_FPU_IS_SNAN
:
2763 case SIM_FPU_IS_QNAN
:
2765 case SIM_FPU_IS_NINF
:
2766 case SIM_FPU_IS_NNUMBER
:
2767 case SIM_FPU_IS_NDENORM
:
2768 case SIM_FPU_IS_NZERO
:
2769 result
= op2
; /* op1 - op2 < 0 */
2770 case SIM_FPU_IS_PINF
:
2771 case SIM_FPU_IS_PNUMBER
:
2772 case SIM_FPU_IS_PDENORM
:
2773 case SIM_FPU_IS_PZERO
:
2774 result
= op1
; /* op1 - op2 > 0 */
2776 fprintf (stderr
, "Bad switch\n");
2781 printf("DBG: Max: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2798 printf("DBG: Min: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2801 /* The registers must specify FPRs valid for operands of type
2802 "fmt". If they are not valid, the result is undefined. */
2804 /* The format type should already have been checked: */
2811 sim_fpu_32to (&wop1
, op1
);
2812 sim_fpu_32to (&wop2
, op2
);
2813 cmp
= sim_fpu_cmp (&wop1
, &wop2
);
2820 sim_fpu_64to (&wop1
, op1
);
2821 sim_fpu_64to (&wop2
, op2
);
2822 cmp
= sim_fpu_cmp (&wop1
, &wop2
);
2826 fprintf (stderr
, "Bad switch\n");
2832 case SIM_FPU_IS_SNAN
:
2833 case SIM_FPU_IS_QNAN
:
2835 case SIM_FPU_IS_NINF
:
2836 case SIM_FPU_IS_NNUMBER
:
2837 case SIM_FPU_IS_NDENORM
:
2838 case SIM_FPU_IS_NZERO
:
2839 result
= op1
; /* op1 - op2 < 0 */
2840 case SIM_FPU_IS_PINF
:
2841 case SIM_FPU_IS_PNUMBER
:
2842 case SIM_FPU_IS_PDENORM
:
2843 case SIM_FPU_IS_PZERO
:
2844 result
= op2
; /* op1 - op2 > 0 */
2846 fprintf (stderr
, "Bad switch\n");
2851 printf("DBG: Min: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2859 convert (SIM_DESC sd
,
2868 sim_fpu_round round
;
2869 unsigned32 result32
;
2870 unsigned64 result64
;
2873 #if 0 /* FIXME: doesn't compile */
2874 printf("DBG: Convert: mode %s : op 0x%s : from %s : to %s : (PC = 0x%s)\n",RMMODE(rm
),pr_addr(op
),DOFMT(from
),DOFMT(to
),pr_addr(IPC
));
2881 /* Round result to nearest representable value. When two
2882 representable values are equally near, round to the value
2883 that has a least significant bit of zero (i.e. is even). */
2884 round
= sim_fpu_round_near
;
2887 /* Round result to the value closest to, and not greater in
2888 magnitude than, the result. */
2889 round
= sim_fpu_round_zero
;
2892 /* Round result to the value closest to, and not less than,
2894 round
= sim_fpu_round_up
;
2898 /* Round result to the value closest to, and not greater than,
2900 round
= sim_fpu_round_down
;
2904 fprintf (stderr
, "Bad switch\n");
2908 /* Convert the input to sim_fpu internal format */
2912 sim_fpu_64to (&wop
, op
);
2915 sim_fpu_32to (&wop
, op
);
2918 sim_fpu_i32to (&wop
, op
, round
);
2921 sim_fpu_i64to (&wop
, op
, round
);
2924 fprintf (stderr
, "Bad switch\n");
2928 /* Convert sim_fpu format into the output */
2929 /* The value WOP is converted to the destination format, rounding
2930 using mode RM. When the destination is a fixed-point format, then
2931 a source value of Infinity, NaN or one which would round to an
2932 integer outside the fixed point range then an IEEE Invalid
2933 Operation condition is raised. */
2937 sim_fpu_round_32 (&wop
, round
, 0);
2938 sim_fpu_to32 (&result32
, &wop
);
2939 result64
= result32
;
2942 sim_fpu_round_64 (&wop
, round
, 0);
2943 sim_fpu_to64 (&result64
, &wop
);
2946 sim_fpu_to32i (&result32
, &wop
, round
);
2947 result64
= result32
;
2950 sim_fpu_to64i (&result64
, &wop
, round
);
2954 fprintf (stderr
, "Bad switch\n");
2959 printf("DBG: Convert: returning 0x%s (to format = %s)\n",pr_addr(result64
),DOFMT(to
));
2966 /*-- co-processor support routines ------------------------------------------*/
2969 CoProcPresent(unsigned int coproc_number
)
2971 /* Return TRUE if simulator provides a model for the given co-processor number */
2976 cop_lw (SIM_DESC sd
,
2981 unsigned int memword
)
2986 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
2989 printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%s\n",memword
,pr_addr(memword
));
2991 StoreFPR(coproc_reg
,fmt_word
,(uword64
)memword
);
2992 FPR_STATE
[coproc_reg
] = fmt_uninterpreted
;
2997 #if 0 /* this should be controlled by a configuration option */
2998 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
));
3007 cop_ld (SIM_DESC sd
,
3016 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
) );
3019 switch (coproc_num
) {
3021 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
3023 StoreFPR(coproc_reg
,fmt_uninterpreted
,memword
);
3028 #if 0 /* this message should be controlled by a configuration option */
3029 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
));
3041 cop_sw (SIM_DESC sd
,
3047 unsigned int value
= 0;
3052 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
3055 hold
= FPR_STATE
[coproc_reg
];
3056 FPR_STATE
[coproc_reg
] = fmt_word
;
3057 value
= (unsigned int)ValueFPR(coproc_reg
,fmt_uninterpreted
);
3058 FPR_STATE
[coproc_reg
] = hold
;
3063 #if 0 /* should be controlled by configuration option */
3064 sim_io_printf(sd
,"COP_SW(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num
,coproc_reg
,pr_addr(cia
));
3073 cop_sd (SIM_DESC sd
,
3083 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
3085 value
= ValueFPR(coproc_reg
,fmt_uninterpreted
);
3090 #if 0 /* should be controlled by configuration option */
3091 sim_io_printf(sd
,"COP_SD(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num
,coproc_reg
,pr_addr(cia
));
3103 decode_coproc (SIM_DESC sd
,
3106 unsigned int instruction
)
3108 int coprocnum
= ((instruction
>> 26) & 3);
3112 case 0: /* standard CPU control and cache registers */
3114 int code
= ((instruction
>> 21) & 0x1F);
3115 int rt
= ((instruction
>> 16) & 0x1F);
3116 int rd
= ((instruction
>> 11) & 0x1F);
3117 int tail
= instruction
& 0x3ff;
3118 /* R4000 Users Manual (second edition) lists the following CP0
3120 CODE><-RT><RD-><--TAIL--->
3121 DMFC0 Doubleword Move From CP0 (VR4100 = 01000000001tttttddddd00000000000)
3122 DMTC0 Doubleword Move To CP0 (VR4100 = 01000000101tttttddddd00000000000)
3123 MFC0 word Move From CP0 (VR4100 = 01000000000tttttddddd00000000000)
3124 MTC0 word Move To CP0 (VR4100 = 01000000100tttttddddd00000000000)
3125 TLBR Read Indexed TLB Entry (VR4100 = 01000010000000000000000000000001)
3126 TLBWI Write Indexed TLB Entry (VR4100 = 01000010000000000000000000000010)
3127 TLBWR Write Random TLB Entry (VR4100 = 01000010000000000000000000000110)
3128 TLBP Probe TLB for Matching Entry (VR4100 = 01000010000000000000000000001000)
3129 CACHE Cache operation (VR4100 = 101111bbbbbpppppiiiiiiiiiiiiiiii)
3130 ERET Exception return (VR4100 = 01000010000000000000000000011000)
3132 if (((code
== 0x00) || (code
== 0x04) /* MFC0 / MTC0 */
3133 || (code
== 0x01) || (code
== 0x05)) /* DMFC0 / DMTC0 */
3136 /* Clear double/single coprocessor move bit. */
3139 /* M[TF]C0 (32 bits) | DM[TF]C0 (64 bits) */
3141 switch (rd
) /* NOTEs: Standard CP0 registers */
3143 /* 0 = Index R4000 VR4100 VR4300 */
3144 /* 1 = Random R4000 VR4100 VR4300 */
3145 /* 2 = EntryLo0 R4000 VR4100 VR4300 */
3146 /* 3 = EntryLo1 R4000 VR4100 VR4300 */
3147 /* 4 = Context R4000 VR4100 VR4300 */
3148 /* 5 = PageMask R4000 VR4100 VR4300 */
3149 /* 6 = Wired R4000 VR4100 VR4300 */
3150 /* 8 = BadVAddr R4000 VR4100 VR4300 */
3151 /* 9 = Count R4000 VR4100 VR4300 */
3152 /* 10 = EntryHi R4000 VR4100 VR4300 */
3153 /* 11 = Compare R4000 VR4100 VR4300 */
3154 /* 12 = SR R4000 VR4100 VR4300 */
3155 #ifdef SUBTARGET_R3900
3157 /* 3 = Config R3900 */
3159 /* 7 = Cache R3900 */
3161 /* 15 = PRID R3900 */
3167 /* 8 = BadVAddr R4000 VR4100 VR4300 */
3169 GPR
[rt
] = COP0_BADVADDR
;
3171 COP0_BADVADDR
= GPR
[rt
];
3174 #endif /* SUBTARGET_R3900 */
3181 /* 13 = Cause R4000 VR4100 VR4300 */
3188 /* 14 = EPC R4000 VR4100 VR4300 */
3191 GPR
[rt
] = (signed_word
) (signed_address
) EPC
;
3195 /* 15 = PRId R4000 VR4100 VR4300 */
3196 #ifdef SUBTARGET_R3900
3205 /* 16 = Config R4000 VR4100 VR4300 */
3208 GPR
[rt
] = C0_CONFIG
;
3210 C0_CONFIG
= GPR
[rt
];
3213 #ifdef SUBTARGET_R3900
3222 /* 17 = LLAddr R4000 VR4100 VR4300 */
3224 /* 18 = WatchLo R4000 VR4100 VR4300 */
3225 /* 19 = WatchHi R4000 VR4100 VR4300 */
3226 /* 20 = XContext R4000 VR4100 VR4300 */
3227 /* 26 = PErr or ECC R4000 VR4100 VR4300 */
3228 /* 27 = CacheErr R4000 VR4100 */
3229 /* 28 = TagLo R4000 VR4100 VR4300 */
3230 /* 29 = TagHi R4000 VR4100 VR4300 */
3231 /* 30 = ErrorEPC R4000 VR4100 VR4300 */
3232 if (STATE_VERBOSE_P(SD
))
3234 "Warning: PC 0x%lx:interp.c decode_coproc DEADC0DE\n",
3235 (unsigned long)cia
);
3236 GPR
[rt
] = 0xDEADC0DE; /* CPR[0,rd] */
3237 /* CPR[0,rd] = GPR[rt]; */
3240 GPR
[rt
] = (signed_word
) (signed32
) COP0_GPR
[rd
];
3242 COP0_GPR
[rd
] = GPR
[rt
];
3245 sim_io_printf(sd
,"Warning: MFC0 %d,%d ignored, PC=%08x (architecture specific)\n",rt
,rd
, (unsigned)cia
);
3247 sim_io_printf(sd
,"Warning: MTC0 %d,%d ignored, PC=%08x (architecture specific)\n",rt
,rd
, (unsigned)cia
);
3251 else if (code
== 0x10 && (tail
& 0x3f) == 0x18)
3254 if (SR
& status_ERL
)
3256 /* Oops, not yet available */
3257 sim_io_printf(sd
,"Warning: ERET when SR[ERL] set not handled yet");
3267 else if (code
== 0x10 && (tail
& 0x3f) == 0x10)
3270 #ifdef SUBTARGET_R3900
3271 /* TX39: Copy IEp/KUp -> IEc/KUc, and IEo/KUo -> IEp/KUp */
3273 /* shift IE/KU history bits right */
3274 SR
= LSMASKED32(SR
, 31, 4) | LSINSERTED32(LSEXTRACTED32(SR
, 5, 2), 3, 0);
3276 /* TODO: CACHE register */
3277 #endif /* SUBTARGET_R3900 */
3279 else if (code
== 0x10 && (tail
& 0x3f) == 0x1F)
3287 sim_io_eprintf(sd
,"Unrecognised COP0 instruction 0x%08X at PC = 0x%s : No handler present\n",instruction
,pr_addr(cia
));
3288 /* TODO: When executing an ERET or RFE instruction we should
3289 clear LLBIT, to ensure that any out-standing atomic
3290 read/modify/write sequence fails. */
3294 case 2: /* co-processor 2 */
3301 sim_io_eprintf(sd
, "COP2 instruction 0x%08X at PC = 0x%s : No handler present\n",
3302 instruction
,pr_addr(cia
));
3307 case 1: /* should not occur (FPU co-processor) */
3308 case 3: /* should not occur (FPU co-processor) */
3309 SignalException(ReservedInstruction
,instruction
);
3317 /* This code copied from gdb's utils.c. Would like to share this code,
3318 but don't know of a common place where both could get to it. */
3320 /* Temporary storage using circular buffer */
3326 static char buf
[NUMCELLS
][CELLSIZE
];
3328 if (++cell
>=NUMCELLS
) cell
=0;
3332 /* Print routines to handle variable size regs, etc */
3334 /* Eliminate warning from compiler on 32-bit systems */
3335 static int thirty_two
= 32;
3341 char *paddr_str
=get_cell();
3342 switch (sizeof(addr
))
3345 sprintf(paddr_str
,"%08lx%08lx",
3346 (unsigned long)(addr
>>thirty_two
),(unsigned long)(addr
&0xffffffff));
3349 sprintf(paddr_str
,"%08lx",(unsigned long)addr
);
3352 sprintf(paddr_str
,"%04x",(unsigned short)(addr
&0xffff));
3355 sprintf(paddr_str
,"%x",addr
);
3364 char *paddr_str
=get_cell();
3365 sprintf(paddr_str
,"%08lx%08lx",
3366 (unsigned long)(addr
>>thirty_two
),(unsigned long)(addr
&0xffffffff));
3372 mips_core_signal (SIM_DESC sd
,
3378 transfer_type transfer
,
3379 sim_core_signals sig
)
3381 const char *copy
= (transfer
== read_transfer
? "read" : "write");
3382 address_word ip
= CIA_ADDR (cia
);
3386 case sim_core_unmapped_signal
:
3387 sim_io_eprintf (sd
, "mips-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
3389 (unsigned long) addr
, (unsigned long) ip
);
3390 COP0_BADVADDR
= addr
;
3391 SignalExceptionDataReference();
3394 case sim_core_unaligned_signal
:
3395 sim_io_eprintf (sd
, "mips-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n",
3397 (unsigned long) addr
, (unsigned long) ip
);
3398 COP0_BADVADDR
= addr
;
3399 if(transfer
== read_transfer
)
3400 SignalExceptionAddressLoad();
3402 SignalExceptionAddressStore();
3406 sim_engine_abort (sd
, cpu
, cia
,
3407 "mips_core_signal - internal error - bad switch");
3413 mips_cpu_exception_trigger(SIM_DESC sd
, sim_cpu
* cpu
, address_word cia
)
3415 ASSERT(cpu
!= NULL
);
3417 if(cpu
->exc_suspended
> 0)
3418 sim_io_eprintf(sd
, "Warning, nested exception triggered (%d)\n", cpu
->exc_suspended
);
3421 memcpy(cpu
->exc_trigger_registers
, cpu
->registers
, sizeof(cpu
->exc_trigger_registers
));
3422 cpu
->exc_suspended
= 0;
3426 mips_cpu_exception_suspend(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
3428 ASSERT(cpu
!= NULL
);
3430 if(cpu
->exc_suspended
> 0)
3431 sim_io_eprintf(sd
, "Warning, nested exception signal (%d then %d)\n",
3432 cpu
->exc_suspended
, exception
);
3434 memcpy(cpu
->exc_suspend_registers
, cpu
->registers
, sizeof(cpu
->exc_suspend_registers
));
3435 memcpy(cpu
->registers
, cpu
->exc_trigger_registers
, sizeof(cpu
->registers
));
3436 cpu
->exc_suspended
= exception
;
3440 mips_cpu_exception_resume(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
3442 ASSERT(cpu
!= NULL
);
3444 if(exception
== 0 && cpu
->exc_suspended
> 0)
3446 /* warn not for breakpoints */
3447 if(cpu
->exc_suspended
!= sim_signal_to_host(sd
, SIM_SIGTRAP
))
3448 sim_io_eprintf(sd
, "Warning, resuming but ignoring pending exception signal (%d)\n",
3449 cpu
->exc_suspended
);
3451 else if(exception
!= 0 && cpu
->exc_suspended
> 0)
3453 if(exception
!= cpu
->exc_suspended
)
3454 sim_io_eprintf(sd
, "Warning, resuming with mismatched exception signal (%d vs %d)\n",
3455 cpu
->exc_suspended
, exception
);
3457 memcpy(cpu
->registers
, cpu
->exc_suspend_registers
, sizeof(cpu
->registers
));
3459 else if(exception
!= 0 && cpu
->exc_suspended
== 0)
3461 sim_io_eprintf(sd
, "Warning, ignoring spontanous exception signal (%d)\n", exception
);
3463 cpu
->exc_suspended
= 0;
3467 /*---------------------------------------------------------------------------*/
3468 /*> EOF interp.c <*/