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.
22 We only need to take account of the target endianness when moving data
23 between the simulator and the host. We do not need to worry about the
24 endianness of the host, since this sim code and GDB are executing in
27 The IDT monitor (found on the VR4300 board), seems to lie about
28 register contents. It seems to treat the registers as sign-extended
29 32-bit values. This cause *REAL* problems when single-stepping 64-bit
34 /* The TRACE and PROFILE manifests enable the provision of extra
35 features. If they are not defined then a simpler (quicker)
36 simulator is constructed without the required run-time checks,
38 #if 1 /* 0 to allow user build selection, 1 to force inclusion */
64 #include "libiberty.h"
66 #include "callback.h" /* GDB simulator callback interface */
67 #include "remote-sim.h" /* GDB simulator interface */
69 #include "support.h" /* internal support manifests */
74 #define SIGBUS SIGSEGV
77 /* Get the simulator engine description, without including the code: */
82 /* This variable holds the GDB view of the target endianness: */
83 extern int target_byte_order
;
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. */
88 #define RSVD_INSTRUCTION (0x7C000000)
89 #define RSVD_INSTRUCTION_AMASK (0x03FFFFFF)
91 /* NOTE: These numbers depend on the processor architecture being
94 #define TLBModification (1)
97 #define AddressLoad (4)
98 #define AddressStore (5)
99 #define InstructionFetch (6)
100 #define DataReference (7)
101 #define SystemCall (8)
102 #define BreakPoint (9)
103 #define ReservedInstruction (10)
104 #define CoProcessorUnusable (11)
105 #define IntegerOverflow (12) /* Arithmetic overflow (IDT monitor raises SIGFPE) */
110 /* The following exception code is actually private to the simulator
111 world. It is *NOT* a processor feature, and is used to signal
112 run-time errors in the simulator. */
113 #define SimulatorFault (0xFFFFFFFF)
115 /* The following are generic to all versions of the MIPS architecture
117 /* Memory Access Types (for CCA): */
119 #define CachedNoncoherent (1)
120 #define CachedCoherent (2)
123 #define isINSTRUCTION (1 == 0) /* FALSE */
124 #define isDATA (1 == 1) /* TRUE */
126 #define isLOAD (1 == 0) /* FALSE */
127 #define isSTORE (1 == 1) /* TRUE */
129 #define isREAL (1 == 0) /* FALSE */
130 #define isRAW (1 == 1) /* TRUE */
132 #define isTARGET (1 == 0) /* FALSE */
133 #define isHOST (1 == 1) /* TRUE */
135 /* The "AccessLength" specifications for Loads and Stores. NOTE: This
136 is the number of bytes minus 1. */
137 #define AccessLength_BYTE (0)
138 #define AccessLength_HALFWORD (1)
139 #define AccessLength_TRIPLEBYTE (2)
140 #define AccessLength_WORD (3)
141 #define AccessLength_QUINTIBYTE (4)
142 #define AccessLength_SEXTIBYTE (5)
143 #define AccessLength_SEPTIBYTE (6)
144 #define AccessLength_DOUBLEWORD (7)
147 /* FPU registers must be one of the following types. All other values
148 are reserved (and undefined). */
154 /* The following are well outside the normal acceptable format
155 range, and are used in the register status vector. */
156 fmt_unknown
= 0x10000000,
157 fmt_uninterpreted
= 0x20000000,
161 /* NOTE: We cannot avoid globals, since the GDB "sim_" interface does
162 not allow a private variable to be passed around. This means that
163 simulators under GDB can only be single-threaded. However, it would
164 be possible for the simulators to be multi-threaded if GDB allowed
165 for a private pointer to be maintained. i.e. a general "void **ptr"
166 variable that GDB passed around in the argument list to all of
167 sim_xxx() routines. It could be initialised to NULL by GDB, and
168 then updated by sim_open() and used by the other sim_xxx() support
169 functions. This would allow new features in the simulator world,
170 like storing a context - continuing execution to gather a result,
171 and then going back to the point where the context was saved and
172 changing some state before continuing. i.e. the ability to perform
173 UNDOs on simulations. It would also allow the simulation of
174 shared-memory multi-processor systems. */
176 static host_callback
*callback
= NULL
; /* handle onto the current callback structure */
178 /* This is nasty, since we have to rely on matching the register
179 numbers used by GDB. Unfortunately, depending on the MIPS target
180 GDB uses different register numbers. We cannot just include the
181 relevant "gdb/tm.h" link, since GDB may not be configured before
182 the sim world, and also the GDB header file requires too much other
184 /* TODO: Sort out a scheme for *KNOWING* the mapping between real
185 registers, and the numbers that GDB uses. At the moment due to the
186 order that the tools are built, we cannot rely on a configured GDB
187 world whilst constructing the simulator. This means we have to
188 assume the GDB register number mapping. */
190 #define LAST_EMBED_REGNUM (89)
193 /* To keep this default simulator simple, and fast, we use a direct
194 vector of registers. The internal simulator engine then uses
195 manifests to access the correct slot. */
196 static ut_reg registers
[LAST_EMBED_REGNUM
+ 1];
197 static int register_widths
[LAST_EMBED_REGNUM
+ 1];
199 #define GPR (®isters[0])
202 #define FGR (®isters[FGRIDX])
204 #define LO (registers[33])
205 #define HI (registers[34])
206 #define PC (registers[37])
207 #define CAUSE (registers[36])
209 #define SR (registers[SRIDX]) /* CPU status register */
211 #define FCR0 (registers[FCR0IDX]) /* really a 32bit register */
212 #define FCR31IDX (70)
213 #define FCR31 (registers[FCR31IDX]) /* really a 32bit register */
215 #define COCIDX (LAST_EMBED_REGNUM + 2) /* special case : outside the normal range */
217 /* The following are pseudonyms for standard registers */
218 #define ZERO (registers[0])
219 #define V0 (registers[2])
220 #define A0 (registers[4])
221 #define A1 (registers[5])
222 #define A2 (registers[6])
223 #define A3 (registers[7])
224 #define SP (registers[29])
225 #define RA (registers[31])
227 static ut_reg EPC
= 0; /* Exception PC */
230 /* Keep the current format state for each register: */
231 static FP_formats fpr_state
[32];
234 /* VR4300 CP0 configuration register: */
235 static unsigned int CONFIG
= 0;
237 /* The following are internal simulator state variables: */
238 static ut_reg IPC
= 0; /* internal Instruction PC */
239 static ut_reg DSPC
= 0; /* delay-slot PC */
242 /* TODO : these should be the bitmasks for these bits within the
243 status register. At the moment the following are VR4300
245 #define status_KSU_mask (0x3) /* mask for KSU bits */
246 #define status_KSU_shift (3) /* shift for field */
247 #define ksu_kernel (0x0)
248 #define ksu_supervisor (0x1)
249 #define ksu_user (0x2)
250 #define ksu_unknown (0x3)
252 #define status_RE (1 << 25) /* Reverse Endian in user mode */
253 #define status_FR (1 << 26) /* enables MIPS III additional FP registers */
254 #define status_SR (1 << 20) /* soft reset or NMI */
255 #define status_BEV (1 << 22) /* Location of general exception vectors */
256 #define status_TS (1 << 21) /* TLB shutdown has occurred */
257 #define status_ERL (1 << 2) /* Error level */
258 #define status_RP (1 << 27) /* Reduced Power mode */
260 #define config_EP_mask (0xF)
261 #define config_EP_shift (27)
262 #define config_EP_D (0x0)
263 #define config_EP_DxxDxx (0x6)
265 #define config_BE (1 << 15)
267 #define cause_BD ((unsigned)1 << 31) /* Exception in branch delay slot */
270 /* Macro to update FPSR condition-code field. This is complicated by
271 the fact that there is a hole in the index range of the bits within
272 the FCSR register. Also, the number of bits visible depends on the
273 MIPS ISA version being supported. */
274 #define SETFCC(cc,v) {\
275 int bit = ((cc == 0) ? 23 : (24 + (cc)));\
276 FCSR = ((FCSR & ~(1 << bit)) | ((v) << bit));\
278 #define GETFCC(cc) (((((cc) == 0) ? (FCSR & (1 << 23)) : (FCSR & (1 << (24 + (cc))))) != 0) ? 1 : 0)
280 /* This should be the COC1 value at the start of the preceding
282 #define PREVCOC1() ((state & simPCOC1) ? 1 : 0)
285 /* Standard FCRS bits: */
286 #define IR (0) /* Inexact Result */
287 #define UF (1) /* UnderFlow */
288 #define OF (2) /* OverFlow */
289 #define DZ (3) /* Division by Zero */
290 #define IO (4) /* Invalid Operation */
291 #define UO (5) /* Unimplemented Operation */
293 /* Get masks for individual flags: */
294 #if 1 /* SAFE version */
295 #define FP_FLAGS(b) (((unsigned)(b) < 5) ? (1 << ((b) + 2)) : 0)
296 #define FP_ENABLE(b) (((unsigned)(b) < 5) ? (1 << ((b) + 7)) : 0)
297 #define FP_CAUSE(b) (((unsigned)(b) < 6) ? (1 << ((b) + 12)) : 0)
299 #define FP_FLAGS(b) (1 << ((b) + 2))
300 #define FP_ENABLE(b) (1 << ((b) + 7))
301 #define FP_CAUSE(b) (1 << ((b) + 12))
304 #define FP_FS (1 << 24) /* MIPS III onwards : Flush to Zero */
306 #define FP_MASK_RM (0x3)
308 #define FP_RM_NEAREST (0) /* Round to nearest (Round) */
309 #define FP_RM_TOZERO (1) /* Round to zero (Trunc) */
310 #define FP_RM_TOPINF (2) /* Round to Plus infinity (Ceil) */
311 #define FP_RM_TOMINF (3) /* Round to Minus infinity (Floor) */
312 #define GETRM() (int)((FCSR >> FP_SH_RM) & FP_MASK_RM)
314 /* Slots for delayed register updates. For the moment we just have a
315 fixed number of slots (rather than a more generic, dynamic
316 system). This keeps the simulator fast. However, we only allow for
317 the register update to be delayed for a single instruction
319 #define PSLOTS (5) /* Maximum number of instruction cycles */
320 static int pending_in
;
321 static int pending_out
;
322 static int pending_total
;
323 static int pending_slot_count
[PSLOTS
];
324 static int pending_slot_reg
[PSLOTS
];
325 static ut_reg pending_slot_value
[PSLOTS
];
327 /*---------------------------------------------------------------------------*/
328 /*-- GDB simulator interface ------------------------------------------------*/
329 /*---------------------------------------------------------------------------*/
331 static void dotrace
PARAMS((FILE *tracefh
,int type
,SIM_ADDR address
,int width
,char *comment
,...));
332 static void sim_warning
PARAMS((char *fmt
,...));
333 extern void sim_error
PARAMS((char *fmt
,...));
334 static void ColdReset
PARAMS((void));
335 static int AddressTranslation
PARAMS((uword64 vAddr
,int IorD
,int LorS
,uword64
*pAddr
,int *CCA
,int host
,int raw
));
336 static void StoreMemory
PARAMS((int CCA
,int AccessLength
,uword64 MemElem
,uword64 pAddr
,uword64 vAddr
,int raw
));
337 static uword64 LoadMemory
PARAMS((int CCA
,int AccessLength
,uword64 pAddr
,uword64 vAddr
,int IorD
,int raw
));
338 static void SignalException
PARAMS((int exception
,...));
339 static void simulate
PARAMS((void));
340 static long getnum
PARAMS((char *value
));
341 extern void sim_size
PARAMS((unsigned int newsize
));
342 extern void sim_set_profile
PARAMS((int frequency
));
343 static unsigned int power2
PARAMS((unsigned int value
));
345 /*---------------------------------------------------------------------------*/
347 /* The following are not used for MIPS IV onwards: */
348 #define PENDING_FILL(r,v) {\
349 /* printf("DBG: FILL BEFORE pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total); */\
350 if (pending_slot_reg[pending_in] != (LAST_EMBED_REGNUM + 1))\
351 sim_warning("Attempt to over-write pending value");\
352 pending_slot_count[pending_in] = 2;\
353 pending_slot_reg[pending_in] = (r);\
354 pending_slot_value[pending_in] = (uword64)(v);\
355 /*printf("DBG: FILL reg %d value = 0x%08X%08X\n",(r),WORD64HI(v),WORD64LO(v));*/\
358 if (pending_in == PSLOTS)\
360 /*printf("DBG: FILL AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total);*/\
363 static int LLBIT
= 0;
364 /* LLBIT = Load-Linked bit. A bit of "virtual" state used by atomic
365 read-write instructions. It is set when a linked load occurs. It is
366 tested and cleared by the conditional store. It is cleared (during
367 other CPU operations) when a store to the location would no longer
368 be atomic. In particular, it is cleared by exception return
371 static int HIACCESS
= 0;
372 static int LOACCESS
= 0;
373 /* The HIACCESS and LOACCESS counts are used to ensure that
374 corruptions caused by using the HI or LO register to close to a
375 following operation are spotted. */
376 static ut_reg HLPC
= 0;
378 /* ??? The 4300 and a few other processors have interlocks on hi/lo register
379 reads, and hence do not have this problem. To avoid spurious warnings,
380 we just disable this always. */
384 /* If either of the preceding two instructions have accessed the HI or
385 LO registers, then the values they see should be
386 undefined. However, to keep the simulator world simple, we just let
387 them use the value read and raise a warning to notify the user: */
388 #define CHECKHILO(s) {\
389 if ((HIACCESS != 0) || (LOACCESS != 0))\
390 sim_warning("%s over-writing HI and LO registers values (PC = 0x%08X%08X HLPC = 0x%08X%08X)\n",(s),(unsigned int)(PC>>32),(unsigned int)(PC&0xFFFFFFFF),(unsigned int)(HLPC>>32),(unsigned int)(HLPC&0xFFFFFFFF));\
394 /* NOTE: We keep the following status flags as bit values (1 for true,
395 0 for false). This allows them to be used in binary boolean
396 operations without worrying about what exactly the non-zero true
400 #define UserMode ((((SR & status_KSU_mask) >> status_KSU_shift) == ksu_user) ? 1 : 0)
403 /* Hardware configuration. Affects endianness of LoadMemory and
404 StoreMemory and the endianness of Kernel and Supervisor mode
405 execution. The value is 0 for little-endian; 1 for big-endian. */
406 #define BigEndianMem ((CONFIG & config_BE) ? 1 : 0)
407 /* NOTE: Problems will occur if the simulator memory model does not
408 match the host program expectation. i.e. if the host is writing
409 big-endian values to a little-endian memory model. */
412 /* This mode is selected if in User mode with the RE bit being set in
413 SR (Status Register). It reverses the endianness of load and store
415 #define ReverseEndian (((SR & status_RE) && UserMode) ? 1 : 0)
418 /* The endianness for load and store instructions (0=little;1=big). In
419 User mode this endianness may be switched by setting the state_RE
420 bit in the SR register. Thus, BigEndianCPU may be computed as
421 (BigEndienMem EOR ReverseEndian). */
422 #define BigEndianCPU (BigEndianMem ^ ReverseEndian) /* Already bits */
424 #if !defined(FASTSIM) || defined(PROFILE)
425 /* At the moment these values will be the same, since we do not have
426 access to the pipeline cycle count information from the simulator
428 static unsigned int instruction_fetches
= 0;
429 static unsigned int instruction_fetch_overflow
= 0;
430 static unsigned int pipeline_ticks
= 0;
433 /* Flags in the "state" variable: */
434 #define simSTOP (1 << 0) /* 0 = execute; 1 = stop simulation */
435 #define simSTEP (1 << 1) /* 0 = run; 1 = single-step */
436 #define simHALTEX (1 << 2) /* 0 = run; 1 = halt on exception */
437 #define simHALTIN (1 << 3) /* 0 = run; 1 = halt on interrupt */
438 #define simTRACE (1 << 8) /* 0 = do nothing; 1 = trace address activity */
439 #define simPROFILE (1 << 9) /* 0 = do nothing; 1 = gather profiling samples */
440 #define simHOSTBE (1 << 10) /* 0 = little-endian; 1 = big-endian (host endianness) */
441 /* Whilst simSTOP is not set, the simulator control loop should just
442 keep simulating instructions. The simSTEP flag is used to force
443 single-step execution. */
444 #define simBE (1 << 16) /* 0 = little-endian; 1 = big-endian (target endianness) */
445 #define simPCOC0 (1 << 17) /* COC[1] from current */
446 #define simPCOC1 (1 << 18) /* COC[1] from previous */
447 #define simDELAYSLOT (1 << 24) /* 0 = do nothing; 1 = delay slot entry exists */
448 #define simSKIPNEXT (1 << 25) /* 0 = do nothing; 1 = skip instruction */
449 #define simEXCEPTION (1 << 26) /* 0 = no exception; 1 = exception has occurred */
450 #define simEXIT (1 << 27) /* 0 = do nothing; 1 = run-time exit() processing */
451 #define simSIGINT (1 << 28) /* 0 = do nothing; 1 = SIGINT has occured */
453 static unsigned int state
= 0;
454 static unsigned int rcexit
= 0; /* _exit() reason code holder */
456 #define DELAYSLOT() {\
457 if (state & simDELAYSLOT)\
458 sim_warning("Delay slot already activated (branch in delay slot?)");\
459 state |= simDELAYSLOT;\
463 state &= ~simDELAYSLOT;\
464 state |= simSKIPNEXT;\
467 #define K0BASE (0x80000000)
468 #define K0SIZE (0x20000000)
469 #define K1BASE (0xA0000000)
470 #define K1SIZE (0x20000000)
472 /* Very simple memory model to start with: */
473 static unsigned char *membank
= NULL
;
474 static ut_reg membank_base
= K1BASE
;
475 /* The ddb.ld linker script loads text at K1BASE+1MB, and the idt.ld linker
476 script loads text at K1BASE+128KB. We allocate 2MB, so that we have a
477 minimum of 1 MB available for the user process. We must have memory
478 above _end in order for sbrk to work. */
479 static unsigned membank_size
= (2 << 20);
481 /* Simple run-time monitor support */
482 static unsigned char *monitor
= NULL
;
483 static ut_reg monitor_base
= 0xBFC00000;
484 static unsigned monitor_size
= (1 << 11); /* power-of-2 */
486 static char *logfile
= NULL
; /* logging disabled by default */
487 static FILE *logfh
= NULL
;
490 static char *tracefile
= "trace.din"; /* default filename for trace log */
491 static FILE *tracefh
= NULL
;
492 static void open_trace
PARAMS((void));
496 static unsigned profile_frequency
= 256;
497 static unsigned profile_nsamples
= (128 << 10);
498 static unsigned short *profile_hist
= NULL
;
499 static ut_reg profile_minpc
;
500 static ut_reg profile_maxpc
;
501 static int profile_shift
= 0; /* address shift amount */
504 /* The following are used to provide shortcuts to the required version
505 of host<->target copying. This avoids run-time conditionals, which
506 would slow the simulator throughput. */
507 typedef unsigned int (*fnptr_read_word
) PARAMS((unsigned char *memory
));
508 typedef unsigned int (*fnptr_swap_word
) PARAMS((unsigned int data
));
509 typedef uword64 (*fnptr_read_long
) PARAMS((unsigned char *memory
));
510 typedef uword64 (*fnptr_swap_long
) PARAMS((uword64 data
));
512 static fnptr_read_word host_read_word
;
513 static fnptr_read_long host_read_long
;
514 static fnptr_swap_word host_swap_word
;
515 static fnptr_swap_long host_swap_long
;
517 /*---------------------------------------------------------------------------*/
518 /*-- GDB simulator interface ------------------------------------------------*/
519 /*---------------------------------------------------------------------------*/
525 if (callback
== NULL
) {
526 fprintf(stderr
,"SIM Error: sim_open() called without callbacks attached\n");
530 /* The following ensures that the standard file handles for stdin,
531 stdout and stderr are initialised: */
532 callback
->init(callback
);
536 if (state
& simEXCEPTION
) {
537 fprintf(stderr
,"This simulator is not suitable for this host configuration\n");
543 if (*((char *)&data
) != 0x12)
544 state
|= simHOSTBE
; /* big-endian host */
548 /* Check that the host FPU conforms to IEEE 754-1985 for the SINGLE
549 and DOUBLE binary formats. This is a bit nasty, requiring that we
550 trust the explicit manifests held in the source: */
553 s
[state
& simHOSTBE
? 0 : 1] = 0x40805A5A;
554 s
[state
& simHOSTBE
? 1 : 0] = 0x00000000;
556 /* TODO: We need to cope with the simulated target and the host
557 not having the same endianness. This will require the high and
558 low words of a (double) to be swapped when converting between
559 the host and the simulated target. */
561 if (((float)4.01102924346923828125 != *(float *)(s
+ ((state
& simHOSTBE
) ? 0 : 1))) || ((double)523.2939453125 != *(double *)s
)) {
562 fprintf(stderr
,"The host executing the simulator does not seem to have IEEE 754-1985 std FP\n");
563 fprintf(stderr
,"*(float *)s = %.20f (4.01102924346923828125)\n",*(float *)s
);
564 fprintf(stderr
,"*(double *)s = %.20f (523.2939453125)\n",*(double *)s
);
570 /* This is NASTY, in that we are assuming the size of specific
574 for (rn
= 0; (rn
< (LAST_EMBED_REGNUM
+ 1)); rn
++) {
576 register_widths
[rn
] = GPRLEN
;
577 else if ((rn
>= FGRIDX
) && (rn
< (FGRIDX
+ 32)))
578 register_widths
[rn
] = GPRLEN
;
579 else if ((rn
>= 33) && (rn
<= 37))
580 register_widths
[rn
] = GPRLEN
;
581 else if ((rn
== SRIDX
) || (rn
== FCR0IDX
) || (rn
== FCR31IDX
) || ((rn
>= 72) && (rn
<= 89)))
582 register_widths
[rn
] = 32;
584 register_widths
[rn
] = 0;
588 /* It would be good if we could select particular named MIPS
589 architecture simulators. However, having a pre-built, fixed
590 engine would mean including multiple engines. If the simulator is
591 changed to a run-time conditional version, then the ability to
592 select a particular architecture would be straightforward. */
598 static struct option cmdline
[] = {
602 {"profile", 0,0,'p'},
605 {"tracefile",1,0,'z'},
606 {"frequency",1,0,'y'},
607 {"samples", 1,0,'x'},
611 /* Unfortunately, getopt_long() is designed to be used with
612 vectors, where the first option is normally program name (and
613 ignored). We cheat by creating a dummy first argument, so that
614 we can use the standard argument processing. */
615 #define DUMMYARG "simulator "
616 cline
= (char *)malloc(strlen(args
) + strlen(DUMMYARG
) + 1);
618 fprintf(stderr
,"Failed to allocate memory for command line buffer\n");
621 sprintf(cline
,"%s%s",DUMMYARG
,args
);
622 argv
= buildargv(cline
);
623 for (argc
= 0; argv
[argc
]; argc
++);
625 /* Unfortunately, getopt_long() assumes that it is ignoring the
626 first argument (normally the program name). This means it
627 ignores the first option on our "args" line. */
628 optind
= 0; /* Force reset of argument processing */
630 int option_index
= 0;
632 c
= getopt_long(argc
,argv
,"hn:s:tp",cmdline
,&option_index
);
638 callback
->printf_filtered(callback
,"Usage:\n\t\
639 target sim [-h] [--log=<file>] [--name=<model>] [--size=<amount>]");
641 callback
->printf_filtered(callback
," [-t [--tracefile=<name>]]");
644 callback
->printf_filtered(callback
," [-p [--frequency=<count>] [--samples=<count>]]");
646 callback
->printf_filtered(callback
,"\n");
650 if (optarg
!= NULL
) {
652 tmp
= (char *)malloc(strlen(optarg
) + 1);
654 callback
->printf_filtered(callback
,"Failed to allocate buffer for logfile name \"%s\"\n",optarg
);
663 callback
->printf_filtered(callback
,"Explicit model selection not yet available (Ignoring \"%s\")\n",optarg
);
667 membank_size
= (unsigned)getnum(optarg
);
672 /* Eventually the simTRACE flag could be treated as a toggle, to
673 allow external control of the program points being traced
674 (i.e. only from main onwards, excluding the run-time setup,
679 Simulator constructed without tracing support (for performance).\n\
680 Re-compile simulator with \"-DTRACE\" to enable this option.\n");
686 if (optarg
!= NULL
) {
688 tmp
= (char *)malloc(strlen(optarg
) + 1);
690 callback
->printf_filtered(callback
,"Failed to allocate buffer for tracefile name \"%s\"\n",optarg
);
694 callback
->printf_filtered(callback
,"Placing trace information into file \"%s\"\n",tracefile
);
705 Simulator constructed without profiling support (for performance).\n\
706 Re-compile simulator with \"-DPROFILE\" to enable this option.\n");
707 #endif /* !PROFILE */
712 profile_nsamples
= (unsigned)getnum(optarg
);
718 sim_set_profile((int)getnum(optarg
));
723 callback
->printf_filtered(callback
,"Warning: Simulator getopt returned unrecognised code 0x%08X\n",c
);
731 callback
->printf_filtered(callback
,"Warning: Ignoring spurious non-option arguments ");
732 while (optind
< argc
)
733 callback
->printf_filtered(callback
,"\"%s\" ",argv
[optind
++]);
734 callback
->printf_filtered(callback
,"\n");
741 if (logfile
!= NULL
) {
742 if (strcmp(logfile
,"-") == 0)
745 logfh
= fopen(logfile
,"wb+");
747 callback
->printf_filtered(callback
,"Failed to create file \"%s\", writing log information to stderr.\n",tracefile
);
753 /* If the host has "mmap" available we could use it to provide a
754 very large virtual address space for the simulator, since memory
755 would only be allocated within the "mmap" space as it is
756 accessed. This can also be linked to the architecture specific
757 support, required to simulate the MMU. */
758 sim_size(membank_size
);
759 /* NOTE: The above will also have enabled any profiling state */
762 /* If we were providing a more complete I/O, co-processor or memory
763 simulation, we should perform any "device" initialisation at this
764 point. This can include pre-loading memory areas with particular
765 patterns (e.g. simulating ROM monitors). */
767 /* We can start writing to the memory, now that the processor has
769 monitor
= (unsigned char *)calloc(1,monitor_size
);
771 fprintf(stderr
,"Not enough VM for monitor simulation (%d bytes)\n",monitor_size
);
774 /* Entry into the IDT monitor is via fixed address vectors, and
775 not using machine instructions. To avoid clashing with use of
776 the MIPS TRAP system, we place our own (simulator specific)
777 "undefined" instructions into the relevant vector slots. */
778 for (loop
= 0; (loop
< monitor_size
); loop
+= 4) {
779 uword64 vaddr
= (monitor_base
+ loop
);
782 if (AddressTranslation(vaddr
,isDATA
,isSTORE
,&paddr
,&cca
,isTARGET
,isRAW
))
783 StoreMemory(cca
,AccessLength_WORD
,(RSVD_INSTRUCTION
| ((loop
>> 2) & RSVD_INSTRUCTION_AMASK
)),paddr
,vaddr
,isRAW
);
785 /* The PMON monitor uses the same address space, but rather than
786 branching into it the address of a routine is loaded. We can
787 cheat for the moment, and direct the PMON routine to IDT style
788 instructions within the monitor space. This relies on the IDT
789 monitor not using the locations from 0xBFC00500 onwards as its
791 for (loop
= 0; (loop
< 24); loop
++)
793 uword64 vaddr
= (monitor_base
+ 0x500 + (loop
* 4));
796 unsigned int value
= ((0x500 - 8) / 8); /* default UNDEFINED reason code */
816 value
= ((0x500 - 16) / 8); /* not an IDT reason code */
819 case 8: /* cliexit */
823 /* FIXME - should monitor_base be SIM_ADDR?? */
824 value
= ((unsigned int)monitor_base
+ (value
* 8));
825 if (AddressTranslation(vaddr
,isDATA
,isSTORE
,&paddr
,&cca
,isTARGET
,isRAW
))
826 StoreMemory(cca
,AccessLength_WORD
,value
,paddr
,vaddr
,isRAW
);
828 sim_error("Failed to write to monitor space 0x%08X%08X",WORD64HI(vaddr
),WORD64LO(vaddr
));
833 if (state
& simTRACE
)
844 tracefh
= fopen(tracefile
,"wb+");
847 sim_warning("Failed to create file \"%s\", writing trace information to stderr.",tracefile
);
853 /* For the profile writing, we write the data in the host
854 endianness. This unfortunately means we are assuming that the
855 profile file we create is processed on the same host executing the
856 simulator. The gmon.out file format should either have an explicit
857 endianness, or a method of encoding the endianness in the file
867 if (state
& simHOSTBE
) {
868 buff
[3] = ((val
>> 0) & 0xFF);
869 buff
[2] = ((val
>> 8) & 0xFF);
870 buff
[1] = ((val
>> 16) & 0xFF);
871 buff
[0] = ((val
>> 24) & 0xFF);
873 buff
[0] = ((val
>> 0) & 0xFF);
874 buff
[1] = ((val
>> 8) & 0xFF);
875 buff
[2] = ((val
>> 16) & 0xFF);
876 buff
[3] = ((val
>> 24) & 0xFF);
878 if (fwrite(buff
,4,1,fh
) != 1) {
879 sim_warning("Failed to write 4bytes to the profile file");
892 if (state
& simHOSTBE
) {
893 buff
[1] = ((val
>> 0) & 0xFF);
894 buff
[0] = ((val
>> 8) & 0xFF);
896 buff
[0] = ((val
>> 0) & 0xFF);
897 buff
[1] = ((val
>> 8) & 0xFF);
899 if (fwrite(buff
,2,1,fh
) != 1) {
900 sim_warning("Failed to write 2bytes to the profile file");
911 printf("DBG: sim_close: entered (quitting = %d)\n",quitting
);
914 /* Cannot assume sim_kill() has been called */
915 /* "quitting" is non-zero if we cannot hang on errors */
917 /* Ensure that any resources allocated through the callback
918 mechanism are released: */
919 callback
->shutdown(callback
);
922 if ((state
& simPROFILE
) && (profile_hist
!= NULL
)) {
923 unsigned short *p
= profile_hist
;
924 FILE *pf
= fopen("gmon.out","wb");
928 sim_warning("Failed to open \"gmon.out\" profile file");
932 printf("DBG: minpc = 0x%08X\n",(unsigned int)profile_minpc
);
933 printf("DBG: maxpc = 0x%08X\n",(unsigned int)profile_maxpc
);
935 ok
= writeout32(pf
,(unsigned int)profile_minpc
);
937 ok
= writeout32(pf
,(unsigned int)profile_maxpc
);
939 ok
= writeout32(pf
,(profile_nsamples
* 2) + 12); /* size of sample buffer (+ header) */
941 printf("DBG: nsamples = %d (size = 0x%08X)\n",profile_nsamples
,((profile_nsamples
* 2) + 12));
943 for (loop
= 0; (ok
&& (loop
< profile_nsamples
)); loop
++) {
944 ok
= writeout16(pf
,profile_hist
[loop
]);
954 state
&= ~simPROFILE
;
959 if (tracefh
!= NULL
&& tracefh
!= stderr
)
965 if (logfh
!= NULL
&& logfh
!= stdout
&& logfh
!= stderr
)
970 free(membank
); /* cfree not available on all hosts */
977 control_c (sig
, code
, scp
, addr
)
983 state
|= (simSTOP
| simSIGINT
);
987 sim_resume (step
,signal_number
)
988 int step
, signal_number
;
993 printf("DBG: sim_resume entered: step = %d, signal = %d (membank = 0x%08X)\n",step
,signal_number
,membank
);
997 state
|= simSTEP
; /* execute only a single instruction */
999 state
&= ~(simSTOP
| simSTEP
); /* execute until event */
1001 state
|= (simHALTEX
| simHALTIN
); /* treat interrupt event as exception */
1003 /* Start executing instructions from the current state (set
1004 explicitly by register updates, or by sim_create_inferior): */
1006 prev
= signal (SIGINT
, control_c
);
1010 signal (SIGINT
, prev
);
1016 sim_write (addr
,buffer
,size
)
1018 unsigned char *buffer
;
1022 uword64 vaddr
= (uword64
)addr
;
1024 /* Return the number of bytes written, or zero if error. */
1026 callback
->printf_filtered(callback
,"sim_write(0x%08X%08X,buffer,%d);\n",WORD64HI(addr
),WORD64LO(addr
),size
);
1029 /* We provide raw read and write routines, since we do not want to
1030 count the GDB memory accesses in our statistics gathering. */
1032 /* There is a lot of code duplication in the individual blocks
1033 below, but the variables are declared locally to a block to give
1034 the optimiser the best chance of improving the code. We have to
1035 perform slow byte reads from the host memory, to ensure that we
1036 get the data into the correct endianness for the (simulated)
1037 target memory world. */
1039 /* Mask count to get odd byte, odd halfword, and odd word out of the
1040 way. We can then perform doubleword transfers to and from the
1041 simulator memory for optimum performance. */
1042 if (index
&& (index
& 1)) {
1045 if (AddressTranslation(vaddr
,isDATA
,isSTORE
,&paddr
,&cca
,isTARGET
,isRAW
)) {
1046 uword64 value
= ((uword64
)(*buffer
++));
1047 StoreMemory(cca
,AccessLength_BYTE
,value
,paddr
,vaddr
,isRAW
);
1050 index
&= ~1; /* logical operations usually quicker than arithmetic on RISC systems */
1052 if (index
&& (index
& 2)) {
1055 if (AddressTranslation(vaddr
,isDATA
,isSTORE
,&paddr
,&cca
,isTARGET
,isRAW
)) {
1057 /* We need to perform the following magic to ensure that that
1058 bytes are written into same byte positions in the target memory
1059 world, regardless of the endianness of the host. */
1061 value
= ((uword64
)(*buffer
++) << 8);
1062 value
|= ((uword64
)(*buffer
++) << 0);
1064 value
= ((uword64
)(*buffer
++) << 0);
1065 value
|= ((uword64
)(*buffer
++) << 8);
1067 StoreMemory(cca
,AccessLength_HALFWORD
,value
,paddr
,vaddr
,isRAW
);
1072 if (index
&& (index
& 4)) {
1075 if (AddressTranslation(vaddr
,isDATA
,isSTORE
,&paddr
,&cca
,isTARGET
,isRAW
)) {
1078 value
= ((uword64
)(*buffer
++) << 24);
1079 value
|= ((uword64
)(*buffer
++) << 16);
1080 value
|= ((uword64
)(*buffer
++) << 8);
1081 value
|= ((uword64
)(*buffer
++) << 0);
1083 value
= ((uword64
)(*buffer
++) << 0);
1084 value
|= ((uword64
)(*buffer
++) << 8);
1085 value
|= ((uword64
)(*buffer
++) << 16);
1086 value
|= ((uword64
)(*buffer
++) << 24);
1088 StoreMemory(cca
,AccessLength_WORD
,value
,paddr
,vaddr
,isRAW
);
1093 for (;index
; index
-= 8) {
1096 if (AddressTranslation(vaddr
,isDATA
,isSTORE
,&paddr
,&cca
,isTARGET
,isRAW
)) {
1099 value
= ((uword64
)(*buffer
++) << 56);
1100 value
|= ((uword64
)(*buffer
++) << 48);
1101 value
|= ((uword64
)(*buffer
++) << 40);
1102 value
|= ((uword64
)(*buffer
++) << 32);
1103 value
|= ((uword64
)(*buffer
++) << 24);
1104 value
|= ((uword64
)(*buffer
++) << 16);
1105 value
|= ((uword64
)(*buffer
++) << 8);
1106 value
|= ((uword64
)(*buffer
++) << 0);
1108 value
= ((uword64
)(*buffer
++) << 0);
1109 value
|= ((uword64
)(*buffer
++) << 8);
1110 value
|= ((uword64
)(*buffer
++) << 16);
1111 value
|= ((uword64
)(*buffer
++) << 24);
1112 value
|= ((uword64
)(*buffer
++) << 32);
1113 value
|= ((uword64
)(*buffer
++) << 40);
1114 value
|= ((uword64
)(*buffer
++) << 48);
1115 value
|= ((uword64
)(*buffer
++) << 56);
1117 StoreMemory(cca
,AccessLength_DOUBLEWORD
,value
,paddr
,vaddr
,isRAW
);
1126 sim_read (addr
,buffer
,size
)
1128 unsigned char *buffer
;
1133 /* Return the number of bytes read, or zero if error. */
1135 callback
->printf_filtered(callback
,"sim_read(0x%08X%08X,buffer,%d);\n",WORD64HI(addr
),WORD64LO(addr
),size
);
1138 /* TODO: Perform same optimisation as the sim_write() code
1139 above. NOTE: This will require a bit more work since we will need
1140 to ensure that the source physical address is doubleword aligned
1141 before, and then deal with trailing bytes. */
1142 for (index
= 0; (index
< size
); index
++) {
1143 uword64 vaddr
,paddr
,value
;
1145 vaddr
= (uword64
)addr
+ index
;
1146 if (AddressTranslation(vaddr
,isDATA
,isLOAD
,&paddr
,&cca
,isTARGET
,isRAW
)) {
1147 value
= LoadMemory(cca
,AccessLength_BYTE
,paddr
,vaddr
,isDATA
,isRAW
);
1148 buffer
[index
] = (unsigned char)(value
&0xFF);
1157 sim_store_register (rn
,memory
)
1159 unsigned char *memory
;
1162 callback
->printf_filtered(callback
,"sim_store_register(%d,*memory=0x%08X%08X);\n",rn
,*((unsigned int *)memory
),*((unsigned int *)(memory
+ 4)));
1165 /* Unfortunately this suffers from the same problem as the register
1166 numbering one. We need to know what the width of each logical
1167 register number is for the architecture being simulated. */
1168 if (register_widths
[rn
] == 0)
1169 sim_warning("Invalid register width for %d (register store ignored)",rn
);
1171 if (register_widths
[rn
] == 32)
1172 registers
[rn
] = host_read_word(memory
);
1174 registers
[rn
] = host_read_long(memory
);
1181 sim_fetch_register (rn
,memory
)
1183 unsigned char *memory
;
1186 callback
->printf_filtered(callback
,"sim_fetch_register(%d=0x%08X%08X,mem) : place simulator registers into memory\n",rn
,WORD64HI(registers
[rn
]),WORD64LO(registers
[rn
]));
1189 if (register_widths
[rn
] == 0)
1190 sim_warning("Invalid register width for %d (register fetch ignored)",rn
);
1192 if (register_widths
[rn
] == 32)
1193 *((unsigned int *)memory
) = host_swap_word((unsigned int)(registers
[rn
] & 0xFFFFFFFF));
1194 else /* 64bit register */
1195 *((uword64
*)memory
) = host_swap_long(registers
[rn
]);
1201 sim_stop_reason (reason
,sigrc
)
1202 enum sim_stop
*reason
;
1205 /* We can have "*reason = {sim_exited, sim_stopped, sim_signalled}", so
1206 sim_exited *sigrc = argument to exit()
1207 sim_stopped *sigrc = exception number
1208 sim_signalled *sigrc = signal number
1210 if (state
& simEXCEPTION
) {
1211 /* If "sim_signalled" is used, GDB expects normal SIGNAL numbers,
1212 and not the MIPS specific exception codes. */
1214 /* For some reason, sending GDB a sim_signalled reason cause it to
1216 *reason
= sim_stopped
;
1218 *reason
= sim_signalled
;
1220 switch ((CAUSE
>> 2) & 0x1F) {
1222 *sigrc
= SIGINT
; /* wrong type of interrupt, but it will do for the moment */
1225 case TLBModification
:
1230 case InstructionFetch
:
1235 case ReservedInstruction
:
1236 case CoProcessorUnusable
:
1240 case IntegerOverflow
:
1252 default : /* Unknown internal exception */
1256 } else if (state
& simEXIT
) {
1258 printf("DBG: simEXIT (%d)\n",rcexit
);
1260 *reason
= sim_exited
;
1262 } else if (state
& simSIGINT
) {
1263 *reason
= sim_stopped
;
1265 } else { /* assume single-stepping */
1266 *reason
= sim_stopped
;
1269 state
&= ~(simEXCEPTION
| simEXIT
| simSIGINT
);
1277 /* Accessed from the GDB "info files" command: */
1279 callback
->printf_filtered(callback
,"MIPS %d-bit simulator\n",(PROCESSOR_64BIT
? 64 : 32));
1281 callback
->printf_filtered(callback
,"%s endian memory model\n",(BigEndianMem
? "Big" : "Little"));
1283 callback
->printf_filtered(callback
,"0x%08X bytes of memory at 0x%08X%08X\n",(unsigned int)membank_size
,WORD64HI(membank_base
),WORD64LO(membank_base
));
1285 #if !defined(FASTSIM)
1286 if (instruction_fetch_overflow
!= 0)
1287 callback
->printf_filtered(callback
,"Instruction fetches = 0x%08X%08X\n",instruction_fetch_overflow
,instruction_fetches
);
1289 callback
->printf_filtered(callback
,"Instruction fetches = %d\n",instruction_fetches
);
1290 callback
->printf_filtered(callback
,"Pipeline ticks = %d\n",pipeline_ticks
);
1291 /* It would be a useful feature, if when performing multi-cycle
1292 simulations (rather than single-stepping) we keep the start and
1293 end times of the execution, so that we can give a performance
1294 figure for the simulator. */
1295 #endif /* !FASTSIM */
1297 /* print information pertaining to MIPS ISA and architecture being simulated */
1298 /* things that may be interesting */
1299 /* instructions executed - if available */
1300 /* cycles executed - if available */
1301 /* pipeline stalls - if available */
1302 /* virtual time taken */
1303 /* profiling size */
1304 /* profiling frequency */
1312 sim_load (prog
,from_tty
)
1316 /* Return non-zero if the caller should handle the load. Zero if
1317 we have loaded the image. */
1322 sim_create_inferior (start_address
,argv
,env
)
1323 SIM_ADDR start_address
;
1328 printf("DBG: sim_create_inferior entered: start_address = 0x%08X\n",start_address
);
1331 /* Prepare to execute the program to be simulated */
1332 /* argv and env are NULL terminated lists of pointers */
1335 PC
= (uword64
)start_address
;
1337 /* TODO: Sort this properly. SIM_ADDR may already be a 64bit value: */
1338 PC
= SIGNEXTEND(start_address
,32);
1340 /* NOTE: GDB normally sets the PC explicitly. However, this call is
1341 used by other clients of the simulator. */
1344 #if 0 /* def DEBUG */
1345 callback
->printf_filtered(callback
,"sim_create_inferior() : passed arguments ignored\n");
1348 for (cptr
= argv
; (cptr
&& *cptr
); cptr
++)
1349 printf("DBG: arg \"%s\"\n",*cptr
);
1352 /* We should really place the argv slot values into the argument
1353 registers, and onto the stack as required. However, this
1354 assumes that we have a stack defined, which is not necessarily
1355 true at the moment. */
1365 /* This routine should be for terminating any existing simulation
1366 thread. Since we are single-threaded only at the moment, this is
1367 not an issue. It should *NOT* be used to terminate the
1369 #else /* do *NOT* call sim_close */
1370 sim_close(1); /* Do not hang on errors */
1371 /* This would also be the point where any memory mapped areas used
1372 by the simulator should be released. */
1378 sim_get_quit_code ()
1380 /* The standard MIPS PCS (Procedure Calling Standard) uses V0(r2) as
1381 the function return value. However, it may be more correct for
1382 this to return the argument to the exit() function (if
1388 sim_set_callbacks (p
)
1395 typedef enum {e_terminate
,e_help
,e_setmemsize
,e_reset
} e_cmds
;
1397 static struct t_sim_command
{
1401 } sim_commands
[] = {
1402 {e_help
, "help", ": Show MIPS simulator private commands"},
1403 {e_setmemsize
,"set-memory-size","<n> : Specify amount of memory simulated"},
1404 {e_reset
, "reset-system", ": Reset the simulated processor"},
1409 sim_do_command (cmd
)
1412 struct t_sim_command
*cptr
;
1414 if (callback
== NULL
) {
1415 fprintf(stderr
,"Simulator not enabled: \"target sim\" should be used to activate\n");
1419 if (!(cmd
&& *cmd
!= '\0'))
1422 /* NOTE: Accessed from the GDB "sim" commmand: */
1423 for (cptr
= sim_commands
; cptr
&& cptr
->name
; cptr
++)
1424 if (strncmp(cmd
,cptr
->name
,strlen(cptr
->name
)) == 0) {
1425 cmd
+= strlen(cptr
->name
);
1427 case e_help
: /* no arguments */
1428 { /* no arguments */
1429 struct t_sim_command
*lptr
;
1430 callback
->printf_filtered(callback
,"List of MIPS simulator commands:\n");
1431 for (lptr
= sim_commands
; lptr
->name
; lptr
++)
1432 callback
->printf_filtered(callback
,"%s %s\n",lptr
->name
,lptr
->help
);
1436 case e_setmemsize
: /* memory size argument */
1438 unsigned int newsize
= (unsigned int)getnum(cmd
);
1443 case e_reset
: /* no arguments */
1445 /* NOTE: See the comments in sim_open() relating to device
1450 callback
->printf_filtered(callback
,"FATAL: Matched \"%s\", but failed to match command id %d.\n",cmd
,cptr
->id
);
1457 callback
->printf_filtered(callback
,"Error: \"%s\" is not a valid MIPS simulator command.\n",cmd
);
1462 /*---------------------------------------------------------------------------*/
1463 /* NOTE: The following routines do not seem to be used by GDB at the
1464 moment. However, they may be useful to the standalone simulator
1468 /* The profiling format is described in the "gmon_out.h" header file */
1473 #if defined(PROFILE)
1474 profile_frequency
= n
;
1475 state
|= simPROFILE
;
1476 #endif /* PROFILE */
1481 sim_set_profile_size (n
)
1484 #if defined(PROFILE)
1485 if (state
& simPROFILE
) {
1488 /* Since we KNOW that the memory banks are a power-of-2 in size: */
1489 profile_nsamples
= power2(n
);
1490 profile_minpc
= membank_base
;
1491 profile_maxpc
= (membank_base
+ membank_size
);
1493 /* Just in-case we are sampling every address: NOTE: The shift
1494 right of 2 is because we only have word-aligned PC addresses. */
1495 if (profile_nsamples
> (membank_size
>> 2))
1496 profile_nsamples
= (membank_size
>> 2);
1498 /* Since we are dealing with power-of-2 values: */
1499 profile_shift
= (((membank_size
>> 2) / profile_nsamples
) - 1);
1501 bsize
= (profile_nsamples
* sizeof(unsigned short));
1502 if (profile_hist
== NULL
)
1503 profile_hist
= (unsigned short *)calloc(64,(bsize
/ 64));
1505 profile_hist
= (unsigned short *)realloc(profile_hist
,bsize
);
1506 if (profile_hist
== NULL
) {
1507 sim_warning("Failed to allocate VM for profiling buffer (0x%08X bytes)",bsize
);
1508 state
&= ~simPROFILE
;
1511 #endif /* PROFILE */
1518 unsigned int newsize
;
1521 /* Used by "run", and internally, to set the simulated memory size */
1523 callback
->printf_filtered(callback
,"Zero not valid: Memory size still 0x%08X bytes\n",membank_size
);
1526 newsize
= power2(newsize
);
1527 if (membank
== NULL
)
1528 new = (char *)calloc(64,(membank_size
/ 64));
1530 new = (char *)realloc(membank
,newsize
);
1532 if (membank
== NULL
)
1533 sim_error("Not enough VM for simulation memory of 0x%08X bytes",membank_size
);
1535 sim_warning("Failed to resize memory (still 0x%08X bytes)",membank_size
);
1537 membank_size
= (unsigned)newsize
;
1539 #if defined(PROFILE)
1540 /* Ensure that we sample across the new memory range */
1541 sim_set_profile_size(profile_nsamples
);
1542 #endif /* PROFILE */
1551 /* This routine is called by the "run" program, when detailed
1552 execution information is required. Rather than executing a single
1553 instruction, and looping around externally... we just start
1554 simulating, returning TRUE when the simulator stops (for whatever
1558 /* Ensure tracing is enabled, if available */
1559 if (tracefh
== NULL
)
1566 state
&= ~(simSTOP
| simSTEP
); /* execute until event */
1567 state
|= (simHALTEX
| simHALTIN
); /* treat interrupt event as exception */
1568 /* Start executing instructions from the current state (set
1569 explicitly by register updates, or by sim_create_inferior): */
1575 /*---------------------------------------------------------------------------*/
1576 /*-- Private simulator support interface ------------------------------------*/
1577 /*---------------------------------------------------------------------------*/
1579 /* Simple monitor interface (currently setup for the IDT and PMON monitors) */
1582 unsigned int reason
;
1584 /* The IDT monitor actually allows two instructions per vector
1585 slot. However, the simulator currently causes a trap on each
1586 individual instruction. We cheat, and lose the bottom bit. */
1589 /* The following callback functions are available, however the
1590 monitor we are simulating does not make use of them: get_errno,
1591 isatty, lseek, rename, system, time and unlink */
1593 case 6: /* int open(char *path,int flags) */
1597 if (AddressTranslation(A0
,isDATA
,isLOAD
,&paddr
,&cca
,isHOST
,isREAL
))
1598 V0
= callback
->open(callback
,(char *)((int)paddr
),(int)A1
);
1600 sim_error("Attempt to pass pointer that does not reference simulated memory");
1604 case 7: /* int read(int file,char *ptr,int len) */
1608 if (AddressTranslation(A1
,isDATA
,isLOAD
,&paddr
,&cca
,isHOST
,isREAL
))
1609 V0
= callback
->read(callback
,(int)A0
,(char *)((int)paddr
),(int)A2
);
1611 sim_error("Attempt to pass pointer that does not reference simulated memory");
1615 case 8: /* int write(int file,char *ptr,int len) */
1619 if (AddressTranslation(A1
,isDATA
,isLOAD
,&paddr
,&cca
,isHOST
,isREAL
))
1620 V0
= callback
->write(callback
,(int)A0
,(const char *)((int)paddr
),(int)A2
);
1622 sim_error("Attempt to pass pointer that does not reference simulated memory");
1626 case 10: /* int close(int file) */
1627 V0
= callback
->close(callback
,(int)A0
);
1630 case 11: /* char inbyte(void) */
1633 if (callback
->read_stdin(callback
,&tmp
,sizeof(char)) != sizeof(char)) {
1634 sim_error("Invalid return from character read");
1642 case 12: /* void outbyte(char chr) : write a byte to "stdout" */
1644 char tmp
= (char)(A0
& 0xFF);
1645 callback
->write_stdout(callback
,&tmp
,sizeof(char));
1649 case 17: /* void _exit() */
1650 sim_warning("sim_monitor(17): _exit(int reason) to be coded");
1651 state
|= (simSTOP
| simEXIT
); /* stop executing code */
1652 rcexit
= (unsigned int)(A0
& 0xFFFFFFFF);
1655 case 55: /* void get_mem_info(unsigned int *ptr) */
1656 /* in: A0 = pointer to three word memory location */
1657 /* out: [A0 + 0] = size */
1658 /* [A0 + 4] = instruction cache size */
1659 /* [A0 + 8] = data cache size */
1662 uword64 paddr
, value
;
1666 /* NOTE: We use RAW memory writes here, but since we are not
1667 gathering statistics for the monitor calls we are simulating,
1668 it is not an issue. */
1671 if (AddressTranslation(vaddr
,isDATA
,isSTORE
,&paddr
,&cca
,isTARGET
,isREAL
)) {
1672 value
= (uword64
)membank_size
;
1673 StoreMemory(cca
,AccessLength_WORD
,value
,paddr
,vaddr
,isRAW
);
1674 /* We re-do the address translations, in-case the block
1675 overlaps a memory boundary: */
1677 vaddr
+= (AccessLength_WORD
+ 1);
1678 if (AddressTranslation(vaddr
,isDATA
,isSTORE
,&paddr
,&cca
,isTARGET
,isREAL
)) {
1679 StoreMemory(cca
,AccessLength_WORD
,value
,paddr
,vaddr
,isRAW
);
1680 vaddr
+= (AccessLength_WORD
+ 1);
1681 if (AddressTranslation(vaddr
,isDATA
,isSTORE
,&paddr
,&cca
,isTARGET
,isREAL
))
1682 StoreMemory(cca
,AccessLength_WORD
,value
,paddr
,vaddr
,isRAW
);
1691 sim_error("Invalid pointer passed into monitor call");
1695 case 158 : /* PMON printf */
1696 /* in: A0 = pointer to format string */
1697 /* A1 = optional argument 1 */
1698 /* A2 = optional argument 2 */
1699 /* A3 = optional argument 3 */
1701 /* The following is based on the PMON printf source */
1705 /* This isn't the quickest way, since we call the host print
1706 routine for every character almost. But it does avoid
1707 having to allocate and manage a temporary string buffer. */
1708 if (AddressTranslation(A0
,isDATA
,isLOAD
,&paddr
,&cca
,isHOST
,isREAL
)) {
1709 char *s
= (char *)((int)paddr
);
1710 ut_reg
*ap
= &A1
; /* 1st argument */
1711 /* TODO: Include check that we only use three arguments (A1, A2 and A3) */
1715 enum {FMT_RJUST
, FMT_LJUST
, FMT_RJUST0
, FMT_CENTER
} fmt
= FMT_RJUST
;
1716 int width
= 0, trunc
= 0, haddot
= 0, longlong
= 0;
1720 if (strchr ("dobxXulscefg%", *s
))
1728 else if (*s
== '*') {
1733 } else if (*s
>= '1' && *s
<= '9') {
1736 for (t
= s
; isdigit (*s
); s
++);
1737 strncpy (tmp
, t
, s
- t
);
1739 n
= (unsigned int)strtol(tmp
,NULL
,10);
1745 } else if (*s
== '.')
1749 callback
->printf_filtered(callback
,"%%");
1750 } else if (*s
== 's') {
1751 if ((int)*ap
!= 0) {
1752 if (AddressTranslation(*ap
++,isDATA
,isLOAD
,&paddr
,&cca
,isHOST
,isREAL
)) {
1753 char *p
= (char *)((int)paddr
);;
1754 callback
->printf_filtered(callback
,p
);
1757 sim_error("Attempt to pass pointer that does not reference simulated memory");
1761 callback
->printf_filtered(callback
,"(null)");
1762 } else if (*s
== 'c') {
1764 callback
->printf_filtered(callback
,"%c",n
);
1772 if (strchr ("dobxXu", *s
)) {
1773 word64 lv
= (word64
) *ap
++;
1775 callback
->printf_filtered(callback
,"<binary not supported>");
1777 sprintf(tmp
,"%%%s%c",longlong
? "ll" : "",*s
);
1779 callback
->printf_filtered(callback
,tmp
,lv
);
1781 callback
->printf_filtered(callback
,tmp
,(int)lv
);
1783 } else if (strchr ("eEfgG", *s
)) {
1784 #ifdef _MSC_VER /* MSVC version 2.x can't convert from uword64 directly */
1785 double dbl
= (double)((word64
)*ap
++);
1787 double dbl
= (double)*ap
++;
1789 sprintf(tmp
,"%%%d.%d%c",width
,trunc
,*s
);
1790 callback
->printf_filtered(callback
,tmp
,dbl
);
1796 callback
->printf_filtered(callback
,"%c",*s
++);
1799 sim_error("Attempt to pass pointer that does not reference simulated memory");
1804 sim_warning("TODO: sim_monitor(%d) : PC = 0x%08X%08X",reason
,WORD64HI(IPC
),WORD64LO(IPC
));
1805 sim_warning("(Arguments : A0 = 0x%08X%08X : A1 = 0x%08X%08X : A2 = 0x%08X%08X : A3 = 0x%08X%08X)",WORD64HI(A0
),WORD64LO(A0
),WORD64HI(A1
),WORD64LO(A1
),WORD64HI(A2
),WORD64LO(A2
),WORD64HI(A3
),WORD64LO(A3
));
1812 sim_warning(char *fmt
,...)
1818 vsprintf (buf
, fmt
, ap
);
1821 if (logfh
!= NULL
) {
1822 fprintf(logfh
,"SIM Warning: %s\n", buf
);
1824 callback
->printf_filtered(callback
,"SIM Warning: %s\n", buf
);
1826 /* This used to call SignalException with a SimulatorFault, but that causes
1827 the simulator to exit, and that is inappropriate for a warning. */
1832 sim_error(char *fmt
,...)
1838 vsprintf (buf
, fmt
, ap
);
1841 callback
->printf_filtered(callback
,"SIM Error: %s", buf
);
1842 SignalException (SimulatorFault
, buf
);
1852 /* Round *UP* to the nearest power-of-2 if not already one */
1853 if (value
!= (value
& ~(value
- 1))) {
1854 for (tmp
= value
, loop
= 0; (tmp
!= 0); loop
++)
1856 value
= (1 << loop
);
1869 num
= strtol(value
,&end
,10);
1871 callback
->printf_filtered(callback
,"Warning: Invalid number \"%s\" ignored, using zero\n",value
);
1873 if (*end
&& ((tolower(*end
) == 'k') || (tolower(*end
) == 'm'))) {
1874 if (tolower(*end
) == 'k')
1881 callback
->printf_filtered(callback
,"Warning: Spurious characters \"%s\" at end of number ignored\n",end
);
1887 /*-- trace support ----------------------------------------------------------*/
1889 /* The TRACE support is provided (if required) in the memory accessing
1890 routines. Since we are also providing the architecture specific
1891 features, the architecture simulation code can also deal with
1892 notifying the TRACE world of cache flushes, etc. Similarly we do
1893 not need to provide profiling support in the simulator engine,
1894 since we can sample in the instruction fetch control loop. By
1895 defining the TRACE manifest, we add tracing as a run-time
1899 /* Tracing by default produces "din" format (as required by
1900 dineroIII). Each line of such a trace file *MUST* have a din label
1901 and address field. The rest of the line is ignored, so comments can
1902 be included if desired. The first field is the label which must be
1903 one of the following values:
1908 3 escape record (treated as unknown access type)
1909 4 escape record (causes cache flush)
1911 The address field is a 32bit (lower-case) hexadecimal address
1912 value. The address should *NOT* be preceded by "0x".
1914 The size of the memory transfer is not important when dealing with
1915 cache lines (as long as no more than a cache line can be
1916 transferred in a single operation :-), however more information
1917 could be given following the dineroIII requirement to allow more
1918 complete memory and cache simulators to provide better
1919 results. i.e. the University of Pisa has a cache simulator that can
1920 also take bus size and speed as (variable) inputs to calculate
1921 complete system performance (a much more useful ability when trying
1922 to construct an end product, rather than a processor). They
1923 currently have an ARM version of their tool called ChARM. */
1927 void dotrace(FILE *tracefh
,int type
,SIM_ADDR address
,int width
,char *comment
,...)
1929 if (state
& simTRACE
) {
1931 fprintf(tracefh
,"%d %08x%08x ; width %d ; ",
1933 sizeof (address
) > 4 ? (unsigned long)(address
>>32) : 0,
1934 (unsigned long)(address
&0xffffffff),width
);
1935 va_start(ap
,comment
);
1936 vfprintf(tracefh
,comment
,ap
);
1938 fprintf(tracefh
,"\n");
1940 /* NOTE: Since the "din" format will only accept 32bit addresses, and
1941 we may be generating 64bit ones, we should put the hi-32bits of the
1942 address into the comment field. */
1944 /* TODO: Provide a buffer for the trace lines. We can then avoid
1945 performing writes until the buffer is filled, or the file is
1948 /* NOTE: We could consider adding a comment field to the "din" file
1949 produced using type 3 markers (unknown access). This would then
1950 allow information about the program that the "din" is for, and
1951 the MIPs world that was being simulated, to be placed into the
1958 /*---------------------------------------------------------------------------*/
1959 /*-- host<->target transfers ------------------------------------------------*/
1960 /*---------------------------------------------------------------------------*/
1961 /* The following routines allow conditionals to be avoided during the
1962 simulation, at the cost of increasing the image and source size. */
1966 xfer_direct_word(unsigned char *memory
)
1968 xfer_direct_word(memory
)
1969 unsigned char *memory
;
1972 return *((unsigned int *)memory
);
1977 xfer_direct_long(unsigned char *memory
)
1979 xfer_direct_long(memory
)
1980 unsigned char *memory
;
1983 return *((uword64
*)memory
);
1988 swap_direct_word(unsigned int data
)
1990 swap_direct_word(data
)
1999 swap_direct_long(uword64 data
)
2001 swap_direct_long(data
)
2010 xfer_big_word(unsigned char *memory
)
2012 xfer_big_word(memory
)
2013 unsigned char *memory
;
2016 return ((memory
[0] << 24) | (memory
[1] << 16) | (memory
[2] << 8) | memory
[3]);
2021 xfer_big_long(unsigned char *memory
)
2023 xfer_big_long(memory
)
2024 unsigned char *memory
;
2027 return (((uword64
)memory
[0] << 56) | ((uword64
)memory
[1] << 48)
2028 | ((uword64
)memory
[2] << 40) | ((uword64
)memory
[3] << 32)
2029 | ((uword64
)memory
[4] << 24) | ((uword64
)memory
[5] << 16)
2030 | ((uword64
)memory
[6] << 8) | ((uword64
)memory
[7]));
2035 xfer_little_word(unsigned char *memory
)
2037 xfer_little_word(memory
)
2038 unsigned char *memory
;
2041 return ((memory
[3] << 24) | (memory
[2] << 16) | (memory
[1] << 8) | memory
[0]);
2046 xfer_little_long(unsigned char *memory
)
2048 xfer_little_long(memory
)
2049 unsigned char *memory
;
2052 return (((uword64
)memory
[7] << 56) | ((uword64
)memory
[6] << 48)
2053 | ((uword64
)memory
[5] << 40) | ((uword64
)memory
[4] << 32)
2054 | ((uword64
)memory
[3] << 24) | ((uword64
)memory
[2] << 16)
2055 | ((uword64
)memory
[1] << 8) | (uword64
)memory
[0]);
2060 swap_word(unsigned int data
)
2066 unsigned int result
;
2067 result
= data
^ ((data
<< 16) | (data
>> 16));
2068 result
&= ~0x00FF0000;
2069 data
= (data
<< 24) | (data
>> 8);
2070 return data
^ (result
>> 8);
2075 swap_long(uword64 data
)
2081 unsigned int tmphi
= WORD64HI(data
);
2082 unsigned int tmplo
= WORD64LO(data
);
2083 tmphi
= swap_word(tmphi
);
2084 tmplo
= swap_word(tmplo
);
2085 /* Now swap the HI and LO parts */
2086 return SET64LO(tmphi
) | SET64HI(tmplo
);
2089 /*---------------------------------------------------------------------------*/
2090 /*-- simulator engine -------------------------------------------------------*/
2091 /*---------------------------------------------------------------------------*/
2096 /* RESET: Fixed PC address: */
2097 PC
= (((uword64
)0xFFFFFFFF<<32) | 0xBFC00000);
2098 /* The reset vector address is in the unmapped, uncached memory space. */
2100 SR
&= ~(status_SR
| status_TS
| status_RP
);
2101 SR
|= (status_ERL
| status_BEV
);
2102 /* VR4300 starts in Big-Endian mode */
2103 CONFIG
&= ~(config_EP_mask
<< config_EP_shift
);
2104 CONFIG
|= ((config_EP_D
<< config_EP_shift
) | config_BE
);
2105 /* TODO: The VR4300 CONFIG register is not modelled fully at the moment */
2107 #if defined(HASFPU) && (GPRLEN == (64))
2108 /* Cheat and allow access to the complete register set immediately: */
2109 SR
|= status_FR
; /* 64bit registers */
2110 #endif /* HASFPU and 64bit FP registers */
2112 /* Ensure that any instructions with pending register updates are
2116 for (loop
= 0; (loop
< PSLOTS
); loop
++)
2117 pending_slot_reg
[loop
] = (LAST_EMBED_REGNUM
+ 1);
2118 pending_in
= pending_out
= pending_total
= 0;
2122 /* Initialise the FPU registers to the unknown state */
2125 for (rn
= 0; (rn
< 32); rn
++)
2126 fpr_state
[rn
] = fmt_uninterpreted
;
2130 /* In reality this check should be performed at various points
2131 within the simulation, since it is possible to change the
2132 endianness of user programs. However, we perform the check here
2133 to ensure that the start-of-day values agree: */
2134 state
|= (BigEndianCPU
? simBE
: 0);
2135 if ((target_byte_order
== 1234) != !(state
& simBE
)) {
2136 fprintf(stderr
,"ColdReset: GDB (%s) and simulator (%s) do not agree on target endianness\n",
2137 target_byte_order
== 1234 ? "little" : "big",
2138 state
& simBE
? "big" : "little");
2142 if (!(state
& simHOSTBE
) == !(state
& simBE
)) {
2143 host_read_word
= xfer_direct_word
;
2144 host_read_long
= xfer_direct_long
;
2145 host_swap_word
= swap_direct_word
;
2146 host_swap_long
= swap_direct_long
;
2147 } else if (state
& simHOSTBE
) {
2148 host_read_word
= xfer_little_word
;
2149 host_read_long
= xfer_little_long
;
2150 host_swap_word
= swap_word
;
2151 host_swap_long
= swap_long
;
2152 } else { /* HOST little-endian */
2153 host_read_word
= xfer_big_word
;
2154 host_read_long
= xfer_big_long
;
2155 host_swap_word
= swap_word
;
2156 host_swap_long
= swap_long
;
2162 /* Description from page A-22 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2163 /* Translate a virtual address to a physical address and cache
2164 coherence algorithm describing the mechanism used to resolve the
2165 memory reference. Given the virtual address vAddr, and whether the
2166 reference is to Instructions ot Data (IorD), find the corresponding
2167 physical address (pAddr) and the cache coherence algorithm (CCA)
2168 used to resolve the reference. If the virtual address is in one of
2169 the unmapped address spaces the physical address and the CCA are
2170 determined directly by the virtual address. If the virtual address
2171 is in one of the mapped address spaces then the TLB is used to
2172 determine the physical address and access type; if the required
2173 translation is not present in the TLB or the desired access is not
2174 permitted the function fails and an exception is taken.
2176 NOTE: This function is extended to return an exception state. This,
2177 along with the exception generation is used to notify whether a
2178 valid address translation occured */
2181 AddressTranslation(vAddr
,IorD
,LorS
,pAddr
,CCA
,host
,raw
)
2190 int res
= -1; /* TRUE : Assume good return */
2193 callback
->printf_filtered(callback
,"AddressTranslation(0x%08X%08X,%s,%s,...);\n",WORD64HI(vAddr
),WORD64LO(vAddr
),(IorD
? "isDATA" : "isINSTRUCTION"),(LorS
? "iSTORE" : "isLOAD"));
2196 /* Check that the address is valid for this memory model */
2198 /* For a simple (flat) memory model, we simply pass virtual
2199 addressess through (mostly) unchanged. */
2200 vAddr
&= 0xFFFFFFFF;
2202 /* Treat the kernel memory spaces identically for the moment: */
2203 if ((membank_base
== K1BASE
) && (vAddr
>= K0BASE
) && (vAddr
< (K0BASE
+ K0SIZE
)))
2204 vAddr
+= (K1BASE
- K0BASE
);
2206 /* Also assume that the K1BASE memory wraps. This is required to
2207 allow the PMON run-time __sizemem() routine to function (without
2208 having to provide exception simulation). NOTE: A kludge to work
2209 around the fact that the monitor memory is currently held in the
2211 if (((vAddr
< monitor_base
) || (vAddr
>= (monitor_base
+ monitor_size
))) && (vAddr
>= K1BASE
&& vAddr
< (K1BASE
+ K1SIZE
)))
2212 vAddr
= (K1BASE
| (vAddr
& (membank_size
- 1)));
2214 *pAddr
= vAddr
; /* default for isTARGET */
2215 *CCA
= Uncached
; /* not used for isHOST */
2217 /* NOTE: This is a duplicate of the code that appears in the
2218 LoadMemory and StoreMemory functions. They should be merged into
2219 a single function (that can be in-lined if required). */
2220 if ((vAddr
>= membank_base
) && (vAddr
< (membank_base
+ membank_size
))) {
2222 *pAddr
= (int)&membank
[((unsigned int)(vAddr
- membank_base
) & (membank_size
- 1))];
2223 } else if ((vAddr
>= monitor_base
) && (vAddr
< (monitor_base
+ monitor_size
))) {
2225 *pAddr
= (int)&monitor
[((unsigned int)(vAddr
- monitor_base
) & (monitor_size
- 1))];
2228 sim_warning("Failed: AddressTranslation(0x%08X%08X,%s,%s,...) IPC = 0x%08X%08X",WORD64HI(vAddr
),WORD64LO(vAddr
),(IorD
? "isDATA" : "isINSTRUCTION"),(LorS
? "isSTORE" : "isLOAD"),WORD64HI(IPC
),WORD64LO(IPC
));
2230 res
= 0; /* AddressTranslation has failed */
2231 *pAddr
= (SIM_ADDR
)-1;
2232 if (!raw
) /* only generate exceptions on real memory transfers */
2233 SignalException((LorS
== isSTORE
) ? AddressStore
: AddressLoad
);
2236 /* This is a normal occurance during gdb operation, for instance trying
2237 to print parameters at function start before they have been setup,
2238 and hence we should not print a warning except when debugging the
2240 sim_warning("AddressTranslation for %s %s from 0x%08X%08X failed",(IorD
? "data" : "instruction"),(LorS
? "store" : "load"),WORD64HI(vAddr
),WORD64LO(vAddr
));
2247 /* Description from page A-23 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2248 /* Prefetch data from memory. Prefetch is an advisory instruction for
2249 which an implementation specific action is taken. The action taken
2250 may increase performance, but must not change the meaning of the
2251 program, or alter architecturally-visible state. */
2253 Prefetch(CCA
,pAddr
,vAddr
,DATA
,hint
)
2261 callback
->printf_filtered(callback
,"Prefetch(%d,0x%08X%08X,0x%08X%08X,%d,%d);\n",CCA
,WORD64HI(pAddr
),WORD64LO(pAddr
),WORD64HI(vAddr
),WORD64LO(vAddr
),DATA
,hint
);
2264 /* For our simple memory model we do nothing */
2268 /* Description from page A-22 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2269 /* Load a value from memory. Use the cache and main memory as
2270 specified in the Cache Coherence Algorithm (CCA) and the sort of
2271 access (IorD) to find the contents of AccessLength memory bytes
2272 starting at physical location pAddr. The data is returned in the
2273 fixed width naturally-aligned memory element (MemElem). The
2274 low-order two (or three) bits of the address and the AccessLength
2275 indicate which of the bytes within MemElem needs to be given to the
2276 processor. If the memory access type of the reference is uncached
2277 then only the referenced bytes are read from memory and valid
2278 within the memory element. If the access type is cached, and the
2279 data is not present in cache, an implementation specific size and
2280 alignment block of memory is read and loaded into the cache to
2281 satisfy a load reference. At a minimum, the block is the entire
2284 LoadMemory(CCA
,AccessLength
,pAddr
,vAddr
,IorD
,raw
)
2295 if (membank
== NULL
)
2296 callback
->printf_filtered(callback
,"DBG: LoadMemory(%d,%d,0x%08X%08X,0x%08X%08X,%s,%s)\n",CCA
,AccessLength
,WORD64HI(pAddr
),WORD64LO(pAddr
),WORD64HI(vAddr
),WORD64LO(vAddr
),(IorD
? "isDATA" : "isINSTRUCTION"),(raw
? "isRAW" : "isREAL"));
2299 #if defined(WARN_MEM)
2300 if (CCA
!= uncached
)
2301 sim_warning("LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)",CCA
);
2303 if (((pAddr
& LOADDRMASK
) + AccessLength
) > LOADDRMASK
) {
2304 /* In reality this should be a Bus Error */
2305 sim_error("AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%08X%08X\n",AccessLength
,(LOADDRMASK
+ 1)<<2,WORD64HI(pAddr
),WORD64LO(pAddr
));
2307 #endif /* WARN_MEM */
2309 /* Decide which physical memory locations are being dealt with. At
2310 this point we should be able to split the pAddr bits into the
2311 relevant address map being simulated. If the "raw" variable is
2312 set, the memory read being performed should *NOT* update any I/O
2313 state or affect the CPU state. This also includes avoiding
2314 affecting statistics gathering. */
2316 /* If instruction fetch then we need to check that the two lo-order
2317 bits are zero, otherwise raise a InstructionFetch exception: */
2318 if ((IorD
== isINSTRUCTION
)
2319 && ((pAddr
& 0x3) != 0)
2320 && (((pAddr
& 0x1) != 0) || ((vAddr
& 0x1) == 0)))
2321 SignalException(InstructionFetch
);
2324 unsigned char *mem
= NULL
;
2328 dotrace(tracefh
,((IorD
== isDATA
) ? 0 : 2),(unsigned int)(pAddr
&0xFFFFFFFF),(AccessLength
+ 1),"load%s",((IorD
== isDATA
) ? "" : " instruction"));
2331 /* NOTE: Quicker methods of decoding the address space can be used
2332 when a real memory map is being simulated (i.e. using hi-order
2333 address bits to select device). */
2334 if ((pAddr
>= membank_base
) && (pAddr
< (membank_base
+ membank_size
))) {
2335 index
= ((unsigned int)(pAddr
- membank_base
) & (membank_size
- 1));
2337 } else if ((pAddr
>= monitor_base
) && (pAddr
< (monitor_base
+ monitor_size
))) {
2338 index
= ((unsigned int)(pAddr
- monitor_base
) & (monitor_size
- 1));
2342 sim_error("Simulator memory not found for physical address 0x%08X%08X\n",WORD64HI(pAddr
),WORD64LO(pAddr
));
2344 /* If we obtained the endianness of the host, and it is the same
2345 as the target memory system we can optimise the memory
2346 accesses. However, without that information we must perform
2347 slow transfer, and hope that the compiler optimisation will
2348 merge successive loads. */
2349 value
= 0; /* no data loaded yet */
2351 /* In reality we should always be loading a doubleword value (or
2352 word value in 32bit memory worlds). The external code then
2353 extracts the required bytes. However, to keep performance
2354 high we only load the required bytes into the relevant
2357 switch (AccessLength
) { /* big-endian memory */
2358 case AccessLength_DOUBLEWORD
:
2359 value
|= ((uword64
)mem
[index
++] << 56);
2360 case AccessLength_SEPTIBYTE
:
2361 value
|= ((uword64
)mem
[index
++] << 48);
2362 case AccessLength_SEXTIBYTE
:
2363 value
|= ((uword64
)mem
[index
++] << 40);
2364 case AccessLength_QUINTIBYTE
:
2365 value
|= ((uword64
)mem
[index
++] << 32);
2366 case AccessLength_WORD
:
2367 value
|= ((unsigned int)mem
[index
++] << 24);
2368 case AccessLength_TRIPLEBYTE
:
2369 value
|= ((unsigned int)mem
[index
++] << 16);
2370 case AccessLength_HALFWORD
:
2371 value
|= ((unsigned int)mem
[index
++] << 8);
2372 case AccessLength_BYTE
:
2373 value
|= mem
[index
];
2377 index
+= (AccessLength
+ 1);
2378 switch (AccessLength
) { /* little-endian memory */
2379 case AccessLength_DOUBLEWORD
:
2380 value
|= ((uword64
)mem
[--index
] << 56);
2381 case AccessLength_SEPTIBYTE
:
2382 value
|= ((uword64
)mem
[--index
] << 48);
2383 case AccessLength_SEXTIBYTE
:
2384 value
|= ((uword64
)mem
[--index
] << 40);
2385 case AccessLength_QUINTIBYTE
:
2386 value
|= ((uword64
)mem
[--index
] << 32);
2387 case AccessLength_WORD
:
2388 value
|= ((uword64
)mem
[--index
] << 24);
2389 case AccessLength_TRIPLEBYTE
:
2390 value
|= ((uword64
)mem
[--index
] << 16);
2391 case AccessLength_HALFWORD
:
2392 value
|= ((uword64
)mem
[--index
] << 8);
2393 case AccessLength_BYTE
:
2394 value
|= ((uword64
)mem
[--index
] << 0);
2400 printf("DBG: LoadMemory() : (offset %d) : value = 0x%08X%08X\n",(int)(pAddr
& LOADDRMASK
),WORD64HI(value
),WORD64LO(value
));
2403 /* TODO: We could try and avoid the shifts when dealing with raw
2404 memory accesses. This would mean updating the LoadMemory and
2405 StoreMemory routines to avoid shifting the data before
2406 returning or using it. */
2407 if (!raw
) { /* do nothing for raw accessess */
2409 value
<<= (((7 - (pAddr
& LOADDRMASK
)) - AccessLength
) * 8);
2410 else /* little-endian only needs to be shifted up to the correct byte offset */
2411 value
<<= ((pAddr
& LOADDRMASK
) * 8);
2415 printf("DBG: LoadMemory() : shifted value = 0x%08X%08X\n",WORD64HI(value
),WORD64LO(value
));
2423 /* Description from page A-23 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2424 /* Store a value to memory. The specified data is stored into the
2425 physical location pAddr using the memory hierarchy (data caches and
2426 main memory) as specified by the Cache Coherence Algorithm
2427 (CCA). The MemElem contains the data for an aligned, fixed-width
2428 memory element (word for 32-bit processors, doubleword for 64-bit
2429 processors), though only the bytes that will actually be stored to
2430 memory need to be valid. The low-order two (or three) bits of pAddr
2431 and the AccessLength field indicates which of the bytes within the
2432 MemElem data should actually be stored; only these bytes in memory
2435 StoreMemory(CCA
,AccessLength
,MemElem
,pAddr
,vAddr
,raw
)
2444 callback
->printf_filtered(callback
,"DBG: StoreMemory(%d,%d,0x%08X%08X,0x%08X%08X,0x%08X%08X,%s)\n",CCA
,AccessLength
,WORD64HI(MemElem
),WORD64LO(MemElem
),WORD64HI(pAddr
),WORD64LO(pAddr
),WORD64HI(vAddr
),WORD64LO(vAddr
),(raw
? "isRAW" : "isREAL"));
2447 #if defined(WARN_MEM)
2448 if (CCA
!= uncached
)
2449 sim_warning("StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)",CCA
);
2451 if (((pAddr
& LOADDRMASK
) + AccessLength
) > LOADDRMASK
)
2452 sim_error("AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%08X%08X\n",AccessLength
,(LOADDRMASK
+ 1)<<2,WORD64HI(pAddr
),WORD64LO(pAddr
));
2453 #endif /* WARN_MEM */
2457 dotrace(tracefh
,1,(unsigned int)(pAddr
&0xFFFFFFFF),(AccessLength
+ 1),"store");
2460 /* See the comments in the LoadMemory routine about optimising
2461 memory accesses. Also if we wanted to make the simulator smaller,
2462 we could merge a lot of this code with the LoadMemory
2463 routine. However, this would slow the simulator down with
2464 run-time conditionals. */
2467 unsigned char *mem
= NULL
;
2469 if ((pAddr
>= membank_base
) && (pAddr
< (membank_base
+ membank_size
))) {
2470 index
= ((unsigned int)(pAddr
- membank_base
) & (membank_size
- 1));
2472 } else if ((pAddr
>= monitor_base
) && (pAddr
< (monitor_base
+ monitor_size
))) {
2473 index
= ((unsigned int)(pAddr
- monitor_base
) & (monitor_size
- 1));
2478 sim_error("Simulator memory not found for physical address 0x%08X%08X\n",WORD64HI(pAddr
),WORD64LO(pAddr
));
2483 printf("DBG: StoreMemory: offset = %d MemElem = 0x%08X%08X\n",(unsigned int)(pAddr
& LOADDRMASK
),WORD64HI(MemElem
),WORD64LO(MemElem
));
2488 shift
= ((7 - AccessLength
) * 8);
2489 else /* real memory access */
2490 shift
= ((pAddr
& LOADDRMASK
) * 8);
2493 /* no need to shift raw little-endian data */
2495 MemElem
>>= ((pAddr
& LOADDRMASK
) * 8);
2499 printf("DBG: StoreMemory: shift = %d MemElem = 0x%08X%08X\n",shift
,WORD64HI(MemElem
),WORD64LO(MemElem
));
2503 switch (AccessLength
) { /* big-endian memory */
2504 case AccessLength_DOUBLEWORD
:
2505 mem
[index
++] = (unsigned char)(MemElem
>> 56);
2507 case AccessLength_SEPTIBYTE
:
2508 mem
[index
++] = (unsigned char)(MemElem
>> 56);
2510 case AccessLength_SEXTIBYTE
:
2511 mem
[index
++] = (unsigned char)(MemElem
>> 56);
2513 case AccessLength_QUINTIBYTE
:
2514 mem
[index
++] = (unsigned char)(MemElem
>> 56);
2516 case AccessLength_WORD
:
2517 mem
[index
++] = (unsigned char)(MemElem
>> 56);
2519 case AccessLength_TRIPLEBYTE
:
2520 mem
[index
++] = (unsigned char)(MemElem
>> 56);
2522 case AccessLength_HALFWORD
:
2523 mem
[index
++] = (unsigned char)(MemElem
>> 56);
2525 case AccessLength_BYTE
:
2526 mem
[index
++] = (unsigned char)(MemElem
>> 56);
2530 index
+= (AccessLength
+ 1);
2531 switch (AccessLength
) { /* little-endian memory */
2532 case AccessLength_DOUBLEWORD
:
2533 mem
[--index
] = (unsigned char)(MemElem
>> 56);
2534 case AccessLength_SEPTIBYTE
:
2535 mem
[--index
] = (unsigned char)(MemElem
>> 48);
2536 case AccessLength_SEXTIBYTE
:
2537 mem
[--index
] = (unsigned char)(MemElem
>> 40);
2538 case AccessLength_QUINTIBYTE
:
2539 mem
[--index
] = (unsigned char)(MemElem
>> 32);
2540 case AccessLength_WORD
:
2541 mem
[--index
] = (unsigned char)(MemElem
>> 24);
2542 case AccessLength_TRIPLEBYTE
:
2543 mem
[--index
] = (unsigned char)(MemElem
>> 16);
2544 case AccessLength_HALFWORD
:
2545 mem
[--index
] = (unsigned char)(MemElem
>> 8);
2546 case AccessLength_BYTE
:
2547 mem
[--index
] = (unsigned char)(MemElem
>> 0);
2557 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2558 /* Order loads and stores to synchronise shared memory. Perform the
2559 action necessary to make the effects of groups of synchronizable
2560 loads and stores indicated by stype occur in the same order for all
2563 SyncOperation(stype
)
2567 callback
->printf_filtered(callback
,"SyncOperation(%d) : TODO\n",stype
);
2572 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2573 /* Signal an exception condition. This will result in an exception
2574 that aborts the instruction. The instruction operation pseudocode
2575 will never see a return from this function call. */
2577 SignalException (int exception
,...)
2579 /* Ensure that any active atomic read/modify/write operation will fail: */
2582 switch (exception
) {
2583 /* TODO: For testing purposes I have been ignoring TRAPs. In
2584 reality we should either simulate them, or allow the user to
2585 ignore them at run-time. */
2587 sim_warning("Ignoring instruction TRAP (PC 0x%08X%08X)",WORD64HI(IPC
),WORD64LO(IPC
));
2590 case ReservedInstruction
:
2593 unsigned int instruction
;
2594 va_start(ap
,exception
);
2595 instruction
= va_arg(ap
,unsigned int);
2597 /* Provide simple monitor support using ReservedInstruction
2598 exceptions. The following code simulates the fixed vector
2599 entry points into the IDT monitor by causing a simulator
2600 trap, performing the monitor operation, and returning to
2601 the address held in the $ra register (standard PCS return
2602 address). This means we only need to pre-load the vector
2603 space with suitable instruction values. For systems were
2604 actual trap instructions are used, we would not need to
2605 perform this magic. */
2606 if ((instruction
& ~RSVD_INSTRUCTION_AMASK
) == RSVD_INSTRUCTION
) {
2607 sim_monitor(instruction
& RSVD_INSTRUCTION_AMASK
);
2608 PC
= RA
; /* simulate the return from the vector entry */
2609 /* NOTE: This assumes that a branch-and-link style
2610 instruction was used to enter the vector (which is the
2611 case with the current IDT monitor). */
2612 break; /* out of the switch statement */
2613 } /* else fall through to normal exception processing */
2614 sim_warning("ReservedInstruction 0x%08X at IPC = 0x%08X%08X",instruction
,WORD64HI(IPC
),WORD64LO(IPC
));
2619 if (exception
!= BreakPoint
)
2620 callback
->printf_filtered(callback
,"DBG: SignalException(%d) IPC = 0x%08X%08X\n",exception
,WORD64HI(IPC
),WORD64LO(IPC
));
2622 /* Store exception code into current exception id variable (used
2625 /* TODO: If not simulating exceptions then stop the simulator
2626 execution. At the moment we always stop the simulation. */
2627 state
|= (simSTOP
| simEXCEPTION
);
2629 /* Keep a copy of the current A0 in-case this is the program exit
2631 if (exception
== BreakPoint
) {
2633 unsigned int instruction
;
2634 va_start(ap
,exception
);
2635 instruction
= va_arg(ap
,unsigned int);
2637 /* Check for our special terminating BREAK: */
2638 if ((instruction
& 0x03FFFFC0) == 0x03ff0000) {
2639 rcexit
= (unsigned int)(A0
& 0xFFFFFFFF);
2640 state
&= ~simEXCEPTION
;
2645 /* Store exception code into current exception id variable (used
2647 CAUSE
= (exception
<< 2);
2648 if (state
& simDELAYSLOT
) {
2650 EPC
= (IPC
- 4); /* reference the branch instruction */
2653 /* The following is so that the simulator will continue from the
2654 exception address on breakpoint operations. */
2658 case SimulatorFault
:
2662 va_start(ap
,exception
);
2663 msg
= va_arg(ap
,char *);
2664 fprintf(stderr
,"FATAL: Simulator error \"%s\"\n",msg
);
2673 #if defined(WARN_RESULT)
2674 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2675 /* This function indicates that the result of the operation is
2676 undefined. However, this should not affect the instruction
2677 stream. All that is meant to happen is that the destination
2678 register is set to an undefined result. To keep the simulator
2679 simple, we just don't bother updating the destination register, so
2680 the overall result will be undefined. If desired we can stop the
2681 simulator by raising a pseudo-exception. */
2685 sim_warning("UndefinedResult: IPC = 0x%08X%08X",WORD64HI(IPC
),WORD64LO(IPC
));
2686 #if 0 /* Disabled for the moment, since it actually happens a lot at the moment. */
2691 #endif /* WARN_RESULT */
2694 CacheOp(op
,pAddr
,vAddr
,instruction
)
2698 unsigned int instruction
;
2700 #if 1 /* stop warning message being displayed (we should really just remove the code) */
2701 static int icache_warning
= 1;
2702 static int dcache_warning
= 1;
2704 static int icache_warning
= 0;
2705 static int dcache_warning
= 0;
2708 /* If CP0 is not useable (User or Supervisor mode) and the CP0
2709 enable bit in the Status Register is clear - a coprocessor
2710 unusable exception is taken. */
2712 callback
->printf_filtered(callback
,"TODO: Cache availability checking (PC = 0x%08X%08X)\n",WORD64HI(IPC
),WORD64LO(IPC
));
2716 case 0: /* instruction cache */
2718 case 0: /* Index Invalidate */
2719 case 1: /* Index Load Tag */
2720 case 2: /* Index Store Tag */
2721 case 4: /* Hit Invalidate */
2723 case 6: /* Hit Writeback */
2724 if (!icache_warning
)
2726 sim_warning("Instruction CACHE operation %d to be coded",(op
>> 2));
2732 SignalException(ReservedInstruction
,instruction
);
2737 case 1: /* data cache */
2739 case 0: /* Index Writeback Invalidate */
2740 case 1: /* Index Load Tag */
2741 case 2: /* Index Store Tag */
2742 case 3: /* Create Dirty */
2743 case 4: /* Hit Invalidate */
2744 case 5: /* Hit Writeback Invalidate */
2745 case 6: /* Hit Writeback */
2746 if (!dcache_warning
)
2748 sim_warning("Data CACHE operation %d to be coded",(op
>> 2));
2754 SignalException(ReservedInstruction
,instruction
);
2759 default: /* unrecognised cache ID */
2760 SignalException(ReservedInstruction
,instruction
);
2767 /*-- FPU support routines ---------------------------------------------------*/
2769 #if defined(HASFPU) /* Only needed when building FPU aware simulators */
2772 #define SizeFGR() (GPRLEN)
2774 /* They depend on the CPU being simulated */
2775 #define SizeFGR() ((PROCESSOR_64BIT && ((SR & status_FR) == 1)) ? 64 : 32)
2778 /* Numbers are held in normalized form. The SINGLE and DOUBLE binary
2779 formats conform to ANSI/IEEE Std 754-1985. */
2780 /* SINGLE precision floating:
2781 * seeeeeeeefffffffffffffffffffffff
2783 * e = 8bits = exponent
2784 * f = 23bits = fraction
2786 /* SINGLE precision fixed:
2787 * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
2789 * i = 31bits = integer
2791 /* DOUBLE precision floating:
2792 * seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
2794 * e = 11bits = exponent
2795 * f = 52bits = fraction
2797 /* DOUBLE precision fixed:
2798 * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
2800 * i = 63bits = integer
2803 /* Extract sign-bit: */
2804 #define FP_S_s(v) (((v) & ((unsigned)1 << 31)) ? 1 : 0)
2805 #define FP_D_s(v) (((v) & ((uword64)1 << 63)) ? 1 : 0)
2806 /* Extract biased exponent: */
2807 #define FP_S_be(v) (((v) >> 23) & 0xFF)
2808 #define FP_D_be(v) (((v) >> 52) & 0x7FF)
2809 /* Extract unbiased Exponent: */
2810 #define FP_S_e(v) (FP_S_be(v) - 0x7F)
2811 #define FP_D_e(v) (FP_D_be(v) - 0x3FF)
2812 /* Extract complete fraction field: */
2813 #define FP_S_f(v) ((v) & ~((unsigned)0x1FF << 23))
2814 #define FP_D_f(v) ((v) & ~((uword64)0xFFF << 52))
2815 /* Extract numbered fraction bit: */
2816 #define FP_S_fb(b,v) (((v) & (1 << (23 - (b)))) ? 1 : 0)
2817 #define FP_D_fb(b,v) (((v) & (1 << (52 - (b)))) ? 1 : 0)
2819 /* Explicit QNaN values used when value required: */
2820 #define FPQNaN_SINGLE (0x7FBFFFFF)
2821 #define FPQNaN_WORD (0x7FFFFFFF)
2822 #define FPQNaN_DOUBLE (((uword64)0x7FF7FFFF << 32) | 0xFFFFFFFF)
2823 #define FPQNaN_LONG (((uword64)0x7FFFFFFF << 32) | 0xFFFFFFFF)
2825 /* Explicit Infinity values used when required: */
2826 #define FPINF_SINGLE (0x7F800000)
2827 #define FPINF_DOUBLE (((uword64)0x7FF00000 << 32) | 0x00000000)
2829 #if 1 /* def DEBUG */
2830 #define RMMODE(v) (((v) == FP_RM_NEAREST) ? "Round" : (((v) == FP_RM_TOZERO) ? "Trunc" : (((v) == FP_RM_TOPINF) ? "Ceil" : "Floor")))
2831 #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>" : "<format error>"))))))
2842 /* Treat unused register values, as fixed-point 64bit values: */
2843 if ((fmt
== fmt_uninterpreted
) || (fmt
== fmt_unknown
))
2845 /* If request to read data as "uninterpreted", then use the current
2847 fmt
= fpr_state
[fpr
];
2852 /* For values not yet accessed, set to the desired format: */
2853 if (fpr_state
[fpr
] == fmt_uninterpreted
) {
2854 fpr_state
[fpr
] = fmt
;
2856 printf("DBG: Register %d was fmt_uninterpreted. Now %s\n",fpr
,DOFMT(fmt
));
2859 if (fmt
!= fpr_state
[fpr
]) {
2860 sim_warning("FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%08X%08X)",fpr
,DOFMT(fpr_state
[fpr
]),DOFMT(fmt
),WORD64HI(IPC
),WORD64LO(IPC
));
2861 fpr_state
[fpr
] = fmt_unknown
;
2864 if (fpr_state
[fpr
] == fmt_unknown
) {
2865 /* Set QNaN value: */
2868 value
= FPQNaN_SINGLE
;
2872 value
= FPQNaN_DOUBLE
;
2876 value
= FPQNaN_WORD
;
2880 value
= FPQNaN_LONG
;
2887 } else if (SizeFGR() == 64) {
2891 value
= (FGR
[fpr
] & 0xFFFFFFFF);
2894 case fmt_uninterpreted
:
2904 } else if ((fpr
& 1) == 0) { /* even registers only */
2908 value
= (FGR
[fpr
] & 0xFFFFFFFF);
2911 case fmt_uninterpreted
:
2914 value
= ((((uword64
)FGR
[fpr
+1]) << 32) | (FGR
[fpr
] & 0xFFFFFFFF));
2924 SignalException(SimulatorFault
,"Unrecognised FP format in ValueFPR()");
2927 printf("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%08X%08X : PC = 0x%08X%08X : SizeFGR() = %d\n",fpr
,DOFMT(fmt
),WORD64HI(value
),WORD64LO(value
),WORD64HI(IPC
),WORD64LO(IPC
),SizeFGR());
2934 StoreFPR(fpr
,fmt
,value
)
2942 printf("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%08X%08X : PC = 0x%08X%08X : SizeFGR() = %d\n",fpr
,DOFMT(fmt
),WORD64HI(value
),WORD64LO(value
),WORD64HI(IPC
),WORD64LO(IPC
),SizeFGR());
2945 if (SizeFGR() == 64) {
2949 FGR
[fpr
] = (((uword64
)0xDEADC0DE << 32) | (value
& 0xFFFFFFFF));
2950 fpr_state
[fpr
] = fmt
;
2953 case fmt_uninterpreted
:
2957 fpr_state
[fpr
] = fmt
;
2961 fpr_state
[fpr
] = fmt_unknown
;
2965 } else if ((fpr
& 1) == 0) { /* even register number only */
2969 FGR
[fpr
+1] = 0xDEADC0DE;
2970 FGR
[fpr
] = (value
& 0xFFFFFFFF);
2971 fpr_state
[fpr
+ 1] = fmt
;
2972 fpr_state
[fpr
] = fmt
;
2975 case fmt_uninterpreted
:
2978 FGR
[fpr
+1] = (value
>> 32);
2979 FGR
[fpr
] = (value
& 0xFFFFFFFF);
2980 fpr_state
[fpr
+ 1] = fmt
;
2981 fpr_state
[fpr
] = fmt
;
2985 fpr_state
[fpr
] = fmt_unknown
;
2990 #if defined(WARN_RESULT)
2993 #endif /* WARN_RESULT */
2996 SignalException(SimulatorFault
,"Unrecognised FP format in StoreFPR()");
2999 printf("DBG: StoreFPR: fpr[%d] = 0x%08X%08X (format %s)\n",fpr
,WORD64HI(FGR
[fpr
]),WORD64LO(FGR
[fpr
]),DOFMT(fmt
));
3012 /* Check if (((E - bias) == (E_max + 1)) && (fraction != 0)). We
3013 know that the exponent field is biased... we we cheat and avoid
3014 removing the bias value. */
3017 boolean
= ((FP_S_be(op
) == 0xFF) && (FP_S_f(op
) != 0));
3018 /* We could use "FP_S_fb(1,op)" to ascertain whether we are
3019 dealing with a SNaN or QNaN */
3022 boolean
= ((FP_D_be(op
) == 0x7FF) && (FP_D_f(op
) != 0));
3023 /* We could use "FP_S_fb(1,op)" to ascertain whether we are
3024 dealing with a SNaN or QNaN */
3027 boolean
= (op
== FPQNaN_WORD
);
3030 boolean
= (op
== FPQNaN_LONG
);
3035 printf("DBG: NaN: returning %d for 0x%08X%08X (format = %s)\n",boolean
,WORD64HI(op
),WORD64LO(op
),DOFMT(fmt
));
3049 printf("DBG: Infinity: format %s 0x%08X%08X (PC = 0x%08X%08X)\n",DOFMT(fmt
),WORD64HI(op
),WORD64LO(op
),WORD64HI(IPC
),WORD64LO(IPC
));
3052 /* Check if (((E - bias) == (E_max + 1)) && (fraction == 0)). We
3053 know that the exponent field is biased... we we cheat and avoid
3054 removing the bias value. */
3057 boolean
= ((FP_S_be(op
) == 0xFF) && (FP_S_f(op
) == 0));
3060 boolean
= ((FP_D_be(op
) == 0x7FF) && (FP_D_f(op
) == 0));
3063 printf("DBG: TODO: unrecognised format (%s) for Infinity check\n",DOFMT(fmt
));
3068 printf("DBG: Infinity: returning %d for 0x%08X%08X (format = %s)\n",boolean
,WORD64HI(op
),WORD64LO(op
),DOFMT(fmt
));
3082 /* Argument checking already performed by the FPCOMPARE code */
3085 printf("DBG: Less: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt
),WORD64HI(op1
),WORD64LO(op1
),WORD64HI(op2
),WORD64LO(op2
));
3088 /* The format type should already have been checked: */
3092 unsigned int wop1
= (unsigned int)op1
;
3093 unsigned int wop2
= (unsigned int)op2
;
3094 boolean
= (*(float *)&wop1
< *(float *)&wop2
);
3098 boolean
= (*(double *)&op1
< *(double *)&op2
);
3103 printf("DBG: Less: returning %d (format = %s)\n",boolean
,DOFMT(fmt
));
3117 /* Argument checking already performed by the FPCOMPARE code */
3120 printf("DBG: Equal: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt
),WORD64HI(op1
),WORD64LO(op1
),WORD64HI(op2
),WORD64LO(op2
));
3123 /* The format type should already have been checked: */
3126 boolean
= ((op1
& 0xFFFFFFFF) == (op2
& 0xFFFFFFFF));
3129 boolean
= (op1
== op2
);
3134 printf("DBG: Equal: returning %d (format = %s)\n",boolean
,DOFMT(fmt
));
3141 AbsoluteValue(op
,fmt
)
3148 printf("DBG: AbsoluteValue: %s: op = 0x%08X%08X\n",DOFMT(fmt
),WORD64HI(op
),WORD64LO(op
));
3151 /* The format type should already have been checked: */
3155 unsigned int wop
= (unsigned int)op
;
3156 float tmp
= ((float)fabs((double)*(float *)&wop
));
3157 result
= (uword64
)*(unsigned int *)&tmp
;
3162 double tmp
= (fabs(*(double *)&op
));
3163 result
= *(uword64
*)&tmp
;
3178 printf("DBG: Negate: %s: op = 0x%08X%08X\n",DOFMT(fmt
),WORD64HI(op
),WORD64LO(op
));
3181 /* The format type should already have been checked: */
3185 unsigned int wop
= (unsigned int)op
;
3186 float tmp
= ((float)0.0 - *(float *)&wop
);
3187 result
= (uword64
)*(unsigned int *)&tmp
;
3192 double tmp
= ((double)0.0 - *(double *)&op
);
3193 result
= *(uword64
*)&tmp
;
3210 printf("DBG: Add: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt
),WORD64HI(op1
),WORD64LO(op1
),WORD64HI(op2
),WORD64LO(op2
));
3213 /* The registers must specify FPRs valid for operands of type
3214 "fmt". If they are not valid, the result is undefined. */
3216 /* The format type should already have been checked: */
3220 unsigned int wop1
= (unsigned int)op1
;
3221 unsigned int wop2
= (unsigned int)op2
;
3222 float tmp
= (*(float *)&wop1
+ *(float *)&wop2
);
3223 result
= (uword64
)*(unsigned int *)&tmp
;
3228 double tmp
= (*(double *)&op1
+ *(double *)&op2
);
3229 result
= *(uword64
*)&tmp
;
3235 printf("DBG: Add: returning 0x%08X%08X (format = %s)\n",WORD64HI(result
),WORD64LO(result
),DOFMT(fmt
));
3250 printf("DBG: Sub: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt
),WORD64HI(op1
),WORD64LO(op1
),WORD64HI(op2
),WORD64LO(op2
));
3253 /* The registers must specify FPRs valid for operands of type
3254 "fmt". If they are not valid, the result is undefined. */
3256 /* The format type should already have been checked: */
3260 unsigned int wop1
= (unsigned int)op1
;
3261 unsigned int wop2
= (unsigned int)op2
;
3262 float tmp
= (*(float *)&wop1
- *(float *)&wop2
);
3263 result
= (uword64
)*(unsigned int *)&tmp
;
3268 double tmp
= (*(double *)&op1
- *(double *)&op2
);
3269 result
= *(uword64
*)&tmp
;
3275 printf("DBG: Sub: returning 0x%08X%08X (format = %s)\n",WORD64HI(result
),WORD64LO(result
),DOFMT(fmt
));
3282 Multiply(op1
,op2
,fmt
)
3290 printf("DBG: Multiply: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt
),WORD64HI(op1
),WORD64LO(op1
),WORD64HI(op2
),WORD64LO(op2
));
3293 /* The registers must specify FPRs valid for operands of type
3294 "fmt". If they are not valid, the result is undefined. */
3296 /* The format type should already have been checked: */
3300 unsigned int wop1
= (unsigned int)op1
;
3301 unsigned int wop2
= (unsigned int)op2
;
3302 float tmp
= (*(float *)&wop1
* *(float *)&wop2
);
3303 result
= (uword64
)*(unsigned int *)&tmp
;
3308 double tmp
= (*(double *)&op1
* *(double *)&op2
);
3309 result
= *(uword64
*)&tmp
;
3315 printf("DBG: Multiply: returning 0x%08X%08X (format = %s)\n",WORD64HI(result
),WORD64LO(result
),DOFMT(fmt
));
3330 printf("DBG: Divide: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt
),WORD64HI(op1
),WORD64LO(op1
),WORD64HI(op2
),WORD64LO(op2
));
3333 /* The registers must specify FPRs valid for operands of type
3334 "fmt". If they are not valid, the result is undefined. */
3336 /* The format type should already have been checked: */
3340 unsigned int wop1
= (unsigned int)op1
;
3341 unsigned int wop2
= (unsigned int)op2
;
3342 float tmp
= (*(float *)&wop1
/ *(float *)&wop2
);
3343 result
= (uword64
)*(unsigned int *)&tmp
;
3348 double tmp
= (*(double *)&op1
/ *(double *)&op2
);
3349 result
= *(uword64
*)&tmp
;
3355 printf("DBG: Divide: returning 0x%08X%08X (format = %s)\n",WORD64HI(result
),WORD64LO(result
),DOFMT(fmt
));
3369 printf("DBG: Recip: %s: op = 0x%08X%08X\n",DOFMT(fmt
),WORD64HI(op
),WORD64LO(op
));
3372 /* The registers must specify FPRs valid for operands of type
3373 "fmt". If they are not valid, the result is undefined. */
3375 /* The format type should already have been checked: */
3379 unsigned int wop
= (unsigned int)op
;
3380 float tmp
= ((float)1.0 / *(float *)&wop
);
3381 result
= (uword64
)*(unsigned int *)&tmp
;
3386 double tmp
= ((double)1.0 / *(double *)&op
);
3387 result
= *(uword64
*)&tmp
;
3393 printf("DBG: Recip: returning 0x%08X%08X (format = %s)\n",WORD64HI(result
),WORD64LO(result
),DOFMT(fmt
));
3407 printf("DBG: SquareRoot: %s: op = 0x%08X%08X\n",DOFMT(fmt
),WORD64HI(op
),WORD64LO(op
));
3410 /* The registers must specify FPRs valid for operands of type
3411 "fmt". If they are not valid, the result is undefined. */
3413 /* The format type should already have been checked: */
3417 unsigned int wop
= (unsigned int)op
;
3419 float tmp
= ((float)sqrt((double)*(float *)&wop
));
3420 result
= (uword64
)*(unsigned int *)&tmp
;
3422 /* TODO: Provide square-root */
3423 result
= (uword64
)0;
3430 double tmp
= (sqrt(*(double *)&op
));
3431 result
= *(uword64
*)&tmp
;
3433 /* TODO: Provide square-root */
3434 result
= (uword64
)0;
3441 printf("DBG: SquareRoot: returning 0x%08X%08X (format = %s)\n",WORD64HI(result
),WORD64LO(result
),DOFMT(fmt
));
3448 Convert(rm
,op
,from
,to
)
3457 printf("DBG: Convert: mode %s : op 0x%08X%08X : from %s : to %s : (PC = 0x%08X%08X)\n",RMMODE(rm
),WORD64HI(op
),WORD64LO(op
),DOFMT(from
),DOFMT(to
),WORD64HI(IPC
),WORD64LO(IPC
));
3460 /* The value "op" is converted to the destination format, rounding
3461 using mode "rm". When the destination is a fixed-point format,
3462 then a source value of Infinity, NaN or one which would round to
3463 an integer outside the fixed point range then an IEEE Invalid
3464 Operation condition is raised. */
3471 tmp
= (float)(*(double *)&op
);
3475 tmp
= (float)((int)(op
& 0xFFFFFFFF));
3479 tmp
= (float)((word64
)op
);
3484 /* FIXME: This code is incorrect. The rounding mode does not
3485 round to integral values; it rounds to the nearest
3486 representable value in the format. */
3490 /* Round result to nearest representable value. When two
3491 representable values are equally near, round to the value
3492 that has a least significant bit of zero (i.e. is even). */
3494 tmp
= (float)anint((double)tmp
);
3496 /* TODO: Provide round-to-nearest */
3501 /* Round result to the value closest to, and not greater in
3502 magnitude than, the result. */
3504 tmp
= (float)aint((double)tmp
);
3506 /* TODO: Provide round-to-zero */
3511 /* Round result to the value closest to, and not less than,
3513 tmp
= (float)ceil((double)tmp
);
3517 /* Round result to the value closest to, and not greater than,
3519 tmp
= (float)floor((double)tmp
);
3524 result
= (uword64
)*(unsigned int *)&tmp
;
3536 unsigned int wop
= (unsigned int)op
;
3537 tmp
= (double)(*(float *)&wop
);
3542 xxx
= SIGNEXTEND((op
& 0xFFFFFFFF),32);
3547 tmp
= (double)((word64
)op
);
3552 /* FIXME: This code is incorrect. The rounding mode does not
3553 round to integral values; it rounds to the nearest
3554 representable value in the format. */
3559 tmp
= anint(*(double *)&tmp
);
3561 /* TODO: Provide round-to-nearest */
3567 tmp
= aint(*(double *)&tmp
);
3569 /* TODO: Provide round-to-zero */
3574 tmp
= ceil(*(double *)&tmp
);
3578 tmp
= floor(*(double *)&tmp
);
3583 result
= *(uword64
*)&tmp
;
3589 if (Infinity(op
,from
) || NaN(op
,from
) || (1 == 0/*TODO: check range */)) {
3590 printf("DBG: TODO: update FCSR\n");
3591 SignalException(FPE
);
3593 if (to
== fmt_word
) {
3598 unsigned int wop
= (unsigned int)op
;
3599 tmp
= (int)*((float *)&wop
);
3603 tmp
= (int)*((double *)&op
);
3605 printf("DBG: from double %.30f (0x%08X%08X) to word: 0x%08X\n",*((double *)&op
),WORD64HI(op
),WORD64LO(op
),tmp
);
3609 result
= (uword64
)tmp
;
3610 } else { /* fmt_long */
3615 unsigned int wop
= (unsigned int)op
;
3616 tmp
= (word64
)*((float *)&wop
);
3620 tmp
= (word64
)*((double *)&op
);
3623 result
= (uword64
)tmp
;
3630 printf("DBG: Convert: returning 0x%08X%08X (to format = %s)\n",WORD64HI(result
),WORD64LO(result
),DOFMT(to
));
3637 /*-- co-processor support routines ------------------------------------------*/
3640 CoProcPresent(coproc_number
)
3641 unsigned int coproc_number
;
3643 /* Return TRUE if simulator provides a model for the given co-processor number */
3648 COP_LW(coproc_num
,coproc_reg
,memword
)
3649 int coproc_num
, coproc_reg
;
3650 unsigned int memword
;
3652 switch (coproc_num
) {
3656 printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%08X%08X\n",memword
,WORD64HI(memword
),WORD64LO(memword
));
3658 StoreFPR(coproc_reg
,fmt_uninterpreted
,(uword64
)memword
);
3663 #if 0 /* this should be controlled by a configuration option */
3664 callback
->printf_filtered(callback
,"COP_LW(%d,%d,0x%08X) at IPC = 0x%08X%08X : TODO (architecture specific)\n",coproc_num
,coproc_reg
,memword
,WORD64HI(IPC
),WORD64LO(IPC
));
3673 COP_LD(coproc_num
,coproc_reg
,memword
)
3674 int coproc_num
, coproc_reg
;
3677 switch (coproc_num
) {
3680 StoreFPR(coproc_reg
,fmt_uninterpreted
,memword
);
3685 #if 0 /* this message should be controlled by a configuration option */
3686 callback
->printf_filtered(callback
,"COP_LD(%d,%d,0x%08X%08X) at IPC = 0x%08X%08X : TODO (architecture specific)\n",coproc_num
,coproc_reg
,WORD64HI(memword
),WORD64LO(memword
),WORD64HI(IPC
),WORD64LO(IPC
));
3695 COP_SW(coproc_num
,coproc_reg
)
3696 int coproc_num
, coproc_reg
;
3698 unsigned int value
= 0;
3699 switch (coproc_num
) {
3703 value
= (unsigned int)ValueFPR(coproc_reg
,fmt_uninterpreted
);
3706 value
= (unsigned int)ValueFPR(coproc_reg
,fpr_state
[coproc_reg
]);
3709 printf("DBG: COP_SW: reg in format %s (will be accessing as single)\n",DOFMT(fpr_state
[coproc_reg
]));
3711 value
= (unsigned int)ValueFPR(coproc_reg
,fmt_single
);
3718 #if 0 /* should be controlled by configuration option */
3719 callback
->printf_filtered(callback
,"COP_SW(%d,%d) at IPC = 0x%08X%08X : TODO (architecture specific)\n",coproc_num
,coproc_reg
,WORD64HI(IPC
),WORD64LO(IPC
));
3728 COP_SD(coproc_num
,coproc_reg
)
3729 int coproc_num
, coproc_reg
;
3732 switch (coproc_num
) {
3736 value
= ValueFPR(coproc_reg
,fmt_uninterpreted
);
3739 value
= ValueFPR(coproc_reg
,fpr_state
[coproc_reg
]);
3742 printf("DBG: COP_SD: reg in format %s (will be accessing as double)\n",DOFMT(fpr_state
[coproc_reg
]));
3744 value
= ValueFPR(coproc_reg
,fmt_double
);
3751 #if 0 /* should be controlled by configuration option */
3752 callback
->printf_filtered(callback
,"COP_SD(%d,%d) at IPC = 0x%08X%08X : TODO (architecture specific)\n",coproc_num
,coproc_reg
,WORD64HI(IPC
),WORD64LO(IPC
));
3761 decode_coproc(instruction
)
3762 unsigned int instruction
;
3764 int coprocnum
= ((instruction
>> 26) & 3);
3766 switch (coprocnum
) {
3767 case 0: /* standard CPU control and cache registers */
3770 Standard CP0 registers
3771 0 = Index R4000 VR4100 VR4300
3772 1 = Random R4000 VR4100 VR4300
3773 2 = EntryLo0 R4000 VR4100 VR4300
3774 3 = EntryLo1 R4000 VR4100 VR4300
3775 4 = Context R4000 VR4100 VR4300
3776 5 = PageMask R4000 VR4100 VR4300
3777 6 = Wired R4000 VR4100 VR4300
3778 8 = BadVAddr R4000 VR4100 VR4300
3779 9 = Count R4000 VR4100 VR4300
3780 10 = EntryHi R4000 VR4100 VR4300
3781 11 = Compare R4000 VR4100 VR4300
3782 12 = SR R4000 VR4100 VR4300
3783 13 = Cause R4000 VR4100 VR4300
3784 14 = EPC R4000 VR4100 VR4300
3785 15 = PRId R4000 VR4100 VR4300
3786 16 = Config R4000 VR4100 VR4300
3787 17 = LLAddr R4000 VR4100 VR4300
3788 18 = WatchLo R4000 VR4100 VR4300
3789 19 = WatchHi R4000 VR4100 VR4300
3790 20 = XContext R4000 VR4100 VR4300
3791 26 = PErr or ECC R4000 VR4100 VR4300
3792 27 = CacheErr R4000 VR4100
3793 28 = TagLo R4000 VR4100 VR4300
3794 29 = TagHi R4000 VR4100 VR4300
3795 30 = ErrorEPC R4000 VR4100 VR4300
3797 int code
= ((instruction
>> 21) & 0x1F);
3798 /* R4000 Users Manual (second edition) lists the following CP0
3800 DMFC0 Doubleword Move From CP0 (VR4100 = 01000000001tttttddddd00000000000)
3801 DMTC0 Doubleword Move To CP0 (VR4100 = 01000000101tttttddddd00000000000)
3802 MFC0 word Move From CP0 (VR4100 = 01000000000tttttddddd00000000000)
3803 MTC0 word Move To CP0 (VR4100 = 01000000100tttttddddd00000000000)
3804 TLBR Read Indexed TLB Entry (VR4100 = 01000010000000000000000000000001)
3805 TLBWI Write Indexed TLB Entry (VR4100 = 01000010000000000000000000000010)
3806 TLBWR Write Random TLB Entry (VR4100 = 01000010000000000000000000000110)
3807 TLBP Probe TLB for Matching Entry (VR4100 = 01000010000000000000000000001000)
3808 CACHE Cache operation (VR4100 = 101111bbbbbpppppiiiiiiiiiiiiiiii)
3809 ERET Exception return (VR4100 = 01000010000000000000000000011000)
3811 if (((code
== 0x00) || (code
== 0x04)) && ((instruction
& 0x7FF) == 0)) {
3812 int rt
= ((instruction
>> 16) & 0x1F);
3813 int rd
= ((instruction
>> 11) & 0x1F);
3814 if (code
== 0x00) { /* MF : move from */
3815 #if 0 /* message should be controlled by configuration option */
3816 callback
->printf_filtered(callback
,"Warning: MFC0 %d,%d not handled yet (architecture specific)\n",rt
,rd
);
3818 GPR
[rt
] = 0xDEADC0DE; /* CPR[0,rd] */
3819 } else { /* MT : move to */
3820 /* CPR[0,rd] = GPR[rt]; */
3821 #if 0 /* should be controlled by configuration option */
3822 callback
->printf_filtered(callback
,"Warning: MTC0 %d,%d not handled yet (architecture specific)\n",rt
,rd
);
3826 sim_warning("Unrecognised COP0 instruction 0x%08X at IPC = 0x%08X%08X : No handler present",instruction
,WORD64HI(IPC
),WORD64LO(IPC
));
3827 /* TODO: When executing an ERET or RFE instruction we should
3828 clear LLBIT, to ensure that any out-standing atomic
3829 read/modify/write sequence fails. */
3833 case 2: /* undefined co-processor */
3834 sim_warning("COP2 instruction 0x%08X at IPC = 0x%08X%08X : No handler present",instruction
,WORD64HI(IPC
),WORD64LO(IPC
));
3837 case 1: /* should not occur (FPU co-processor) */
3838 case 3: /* should not occur (FPU co-processor) */
3839 SignalException(ReservedInstruction
,instruction
);
3846 /*-- instruction simulation -------------------------------------------------*/
3851 unsigned int pipeline_count
= 1;
3854 if (membank
== NULL
) {
3855 printf("DBG: simulate() entered with no memory\n");
3860 #if 0 /* Disabled to check that everything works OK */
3861 /* The VR4300 seems to sign-extend the PC on its first
3862 access. However, this may just be because it is currently
3863 configured in 32bit mode. However... */
3864 PC
= SIGNEXTEND(PC
,32);
3867 /* main controlling loop */
3869 /* Fetch the next instruction from the simulator memory: */
3870 uword64 vaddr
= (uword64
)PC
;
3873 unsigned int instruction
;
3874 int dsstate
= (state
& simDELAYSLOT
);
3878 printf("DBG: state = 0x%08X :",state
);
3879 if (state
& simSTOP
) printf(" simSTOP");
3880 if (state
& simSTEP
) printf(" simSTEP");
3881 if (state
& simHALTEX
) printf(" simHALTEX");
3882 if (state
& simHALTIN
) printf(" simHALTIN");
3883 if (state
& simBE
) printf(" simBE");
3889 callback
->printf_filtered(callback
,"DBG: DSPC = 0x%08X%08X\n",WORD64HI(DSPC
),WORD64LO(DSPC
));
3892 if (AddressTranslation(PC
,isINSTRUCTION
,isLOAD
,&paddr
,&cca
,isTARGET
,isREAL
)) {
3893 if ((vaddr
& 1) == 0) {
3894 /* Copy the action of the LW instruction */
3895 unsigned int reverse
= (ReverseEndian
? (LOADDRMASK
>> 2) : 0);
3896 unsigned int bigend
= (BigEndianCPU
? (LOADDRMASK
>> 2) : 0);
3899 paddr
= ((paddr
& ~LOADDRMASK
) | ((paddr
& LOADDRMASK
) ^ (reverse
<< 2)));
3900 value
= LoadMemory(cca
,AccessLength_WORD
,paddr
,vaddr
,isINSTRUCTION
,isREAL
);
3901 byte
= ((vaddr
& LOADDRMASK
) ^ (bigend
<< 2));
3902 instruction
= ((value
>> (8 * byte
)) & 0xFFFFFFFF);
3904 /* Copy the action of the LH instruction */
3905 unsigned int reverse
= (ReverseEndian
? (LOADDRMASK
>> 1) : 0);
3906 unsigned int bigend
= (BigEndianCPU
? (LOADDRMASK
>> 1) : 0);
3909 paddr
= (((paddr
& ~ (uword64
) 1) & ~LOADDRMASK
)
3910 | (((paddr
& ~ (uword64
) 1) & LOADDRMASK
) ^ (reverse
<< 1)));
3911 value
= LoadMemory(cca
, AccessLength_HALFWORD
,
3912 paddr
& ~ (uword64
) 1,
3913 vaddr
, isINSTRUCTION
, isREAL
);
3914 byte
= (((vaddr
&~ (uword64
) 1) & LOADDRMASK
) ^ (bigend
<< 1));
3915 instruction
= ((value
>> (8 * byte
)) & 0xFFFF);
3918 fprintf(stderr
,"Cannot translate address for PC = 0x%08X%08X failed\n",WORD64HI(PC
),WORD64LO(PC
));
3923 callback
->printf_filtered(callback
,"DBG: fetched 0x%08X from PC = 0x%08X%08X\n",instruction
,WORD64HI(PC
),WORD64LO(PC
));
3926 #if !defined(FASTSIM) || defined(PROFILE)
3927 instruction_fetches
++;
3928 /* Since we increment above, the value should only ever be zero if
3929 we have just overflowed: */
3930 if (instruction_fetches
== 0)
3931 instruction_fetch_overflow
++;
3932 #if defined(PROFILE)
3933 if ((state
& simPROFILE
) && ((instruction_fetches
% profile_frequency
) == 0) && profile_hist
) {
3934 unsigned n
= ((unsigned int)(PC
- profile_minpc
) >> (profile_shift
+ 2));
3935 if (n
< profile_nsamples
) {
3936 /* NOTE: The counts for the profiling bins are only 16bits wide */
3937 if (profile_hist
[n
] != USHRT_MAX
)
3938 (profile_hist
[n
])++;
3941 #endif /* PROFILE */
3942 #endif /* !FASTSIM && PROFILE */
3944 IPC
= PC
; /* copy PC for this instruction */
3945 /* This is required by exception processing, to ensure that we can
3946 cope with exceptions in the delay slots of branches that may
3947 already have changed the PC. */
3948 if ((vaddr
& 1) == 0)
3949 PC
+= 4; /* increment ready for the next fetch */
3952 /* NOTE: If we perform a delay slot change to the PC, this
3953 increment is not requuired. However, it would make the
3954 simulator more complicated to try and avoid this small hit. */
3956 /* Currently this code provides a simple model. For more
3957 complicated models we could perform exception status checks at
3958 this point, and set the simSTOP state as required. This could
3959 also include processing any hardware interrupts raised by any
3960 I/O model attached to the simulator context.
3962 Support for "asynchronous" I/O events within the simulated world
3963 could be providing by managing a counter, and calling a I/O
3964 specific handler when a particular threshold is reached. On most
3965 architectures a decrement and check for zero operation is
3966 usually quicker than an increment and compare. However, the
3967 process of managing a known value decrement to zero, is higher
3968 than the cost of using an explicit value UINT_MAX into the
3969 future. Which system is used will depend on how complicated the
3970 I/O model is, and how much it is likely to affect the simulator
3973 If events need to be scheduled further in the future than
3974 UINT_MAX event ticks, then the I/O model should just provide its
3975 own counter, triggered from the event system. */
3977 /* MIPS pipeline ticks. To allow for future support where the
3978 pipeline hit of individual instructions is known, this control
3979 loop manages a "pipeline_count" variable. It is initialised to
3980 1 (one), and will only be changed by the simulator engine when
3981 executing an instruction. If the engine does not have access to
3982 pipeline cycle count information then all instructions will be
3983 treated as using a single cycle. NOTE: A standard system is not
3984 provided by the default simulator because different MIPS
3985 architectures have different cycle counts for the same
3989 /* Set previous flag, depending on current: */
3990 if (state
& simPCOC0
)
3994 /* and update the current value: */
4001 /* NOTE: For multi-context simulation environments the "instruction"
4002 variable should be local to this routine. */
4004 /* Shorthand accesses for engine. Note: If we wanted to use global
4005 variables (and a single-threaded simulator engine), then we can
4006 create the actual variables with these names. */
4008 if (!(state
& simSKIPNEXT
)) {
4009 /* Include the simulator engine */
4011 #if ((GPRLEN == 64) && !PROCESSOR_64BIT) || ((GPRLEN == 32) && PROCESSOR_64BIT)
4012 #error "Mismatch between run-time simulator code and simulation engine"
4015 #if defined(WARN_LOHI)
4016 /* Decrement the HI/LO validity ticks */
4021 #endif /* WARN_LOHI */
4023 #if defined(WARN_ZERO)
4024 /* For certain MIPS architectures, GPR[0] is hardwired to zero. We
4025 should check for it being changed. It is better doing it here,
4026 than within the simulator, since it will help keep the simulator
4029 sim_warning("The ZERO register has been updated with 0x%08X%08X (PC = 0x%08X%08X) (reset back to zero)",WORD64HI(ZERO
),WORD64LO(ZERO
),WORD64HI(IPC
),WORD64LO(IPC
));
4030 ZERO
= 0; /* reset back to zero before next instruction */
4032 #endif /* WARN_ZERO */
4033 } else /* simSKIPNEXT check */
4034 state
&= ~simSKIPNEXT
;
4036 /* If the delay slot was active before the instruction is
4037 executed, then update the PC to its new value: */
4040 printf("DBG: dsstate set before instruction execution - updating PC to 0x%08X%08X\n",WORD64HI(DSPC
),WORD64LO(DSPC
));
4043 state
&= ~simDELAYSLOT
;
4046 if (MIPSISA
< 4) { /* The following is only required on pre MIPS IV processors: */
4047 /* Deal with pending register updates: */
4049 printf("DBG: EMPTY BEFORE pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in
,pending_out
,pending_total
);
4051 if (pending_out
!= pending_in
) {
4053 int index
= pending_out
;
4054 int total
= pending_total
;
4055 if (pending_total
== 0) {
4056 fprintf(stderr
,"FATAL: Mis-match on pending update pointers\n");
4059 for (loop
= 0; (loop
< total
); loop
++) {
4061 printf("DBG: BEFORE index = %d, loop = %d\n",index
,loop
);
4063 if (pending_slot_reg
[index
] != (LAST_EMBED_REGNUM
+ 1)) {
4065 printf("pending_slot_count[%d] = %d\n",index
,pending_slot_count
[index
]);
4067 if (--(pending_slot_count
[index
]) == 0) {
4069 printf("pending_slot_reg[%d] = %d\n",index
,pending_slot_reg
[index
]);
4070 printf("pending_slot_value[%d] = 0x%08X%08X\n",index
,WORD64HI(pending_slot_value
[index
]),WORD64LO(pending_slot_value
[index
]));
4072 if (pending_slot_reg
[index
] == COCIDX
) {
4073 SETFCC(0,((FCR31
& (1 << 23)) ? 1 : 0));
4075 registers
[pending_slot_reg
[index
]] = pending_slot_value
[index
];
4077 /* The only time we have PENDING updates to FPU
4078 registers, is when performing binary transfers. This
4079 means we should update the register type field. */
4080 if ((pending_slot_reg
[index
] >= FGRIDX
) && (pending_slot_reg
[index
] < (FGRIDX
+ 32)))
4081 fpr_state
[pending_slot_reg
[index
]] = fmt_uninterpreted
;
4085 printf("registers[%d] = 0x%08X%08X\n",pending_slot_reg
[index
],WORD64HI(registers
[pending_slot_reg
[index
]]),WORD64LO(registers
[pending_slot_reg
[index
]]));
4087 pending_slot_reg
[index
] = (LAST_EMBED_REGNUM
+ 1);
4089 if (pending_out
== PSLOTS
)
4095 printf("DBG: AFTER index = %d, loop = %d\n",index
,loop
);
4098 if (index
== PSLOTS
)
4103 printf("DBG: EMPTY AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in
,pending_out
,pending_total
);
4107 #if !defined(FASTSIM)
4108 pipeline_ticks
+= pipeline_count
;
4109 #endif /* FASTSIM */
4111 if (state
& simSTEP
)
4113 } while (!(state
& simSTOP
));
4116 if (membank
== NULL
) {
4117 printf("DBG: simulate() LEAVING with no memory\n");
4125 /*---------------------------------------------------------------------------*/
4126 /*> EOF interp.c <*/