27b774695f0ec7485b53bbc67cfb72f0bea291cf
[deliverable/binutils-gdb.git] / sim / mips / interp.c
1 /*> interp.c <*/
2 /* Simulator for the MIPS architecture.
3
4 This file is part of the MIPS sim
5
6 THIS SOFTWARE IS NOT COPYRIGHTED
7
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.
11
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.
15
16 $Revision$
17 $Author$
18 $Date$
19
20 NOTEs:
21
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
25 the same process.
26
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
30 code on the hardware.
31
32 */
33
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,
37 etc. */
38 #if 1 /* 0 to allow user build selection, 1 to force inclusion */
39 #define TRACE (1)
40 #define PROFILE (1)
41 #endif
42
43 #include "config.h"
44
45 #include <stdio.h>
46 #include <stdarg.h>
47 #include <ansidecl.h>
48 #include <signal.h>
49 #include <ctype.h>
50 #include <limits.h>
51 #include <math.h>
52 #ifdef HAVE_STDLIB_H
53 #include <stdlib.h>
54 #endif
55 #ifdef HAVE_STRING_H
56 #include <string.h>
57 #else
58 #ifdef HAVE_STRINGS_H
59 #include <strings.h>
60 #endif
61 #endif
62
63 #include "getopt.h"
64 #include "libiberty.h"
65
66 #include "callback.h" /* GDB simulator callback interface */
67 #include "remote-sim.h" /* GDB simulator interface */
68
69 #include "support.h" /* internal support manifests */
70
71 #include "sysdep.h"
72
73 #ifndef SIGBUS
74 #define SIGBUS SIGSEGV
75 #endif
76
77 /* Get the simulator engine description, without including the code: */
78 #define SIM_MANIFESTS
79 #include "engine.c"
80 #undef SIM_MANIFESTS
81
82 /* This variable holds the GDB view of the target endianness: */
83 extern int target_byte_order;
84
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)
90
91 /* NOTE: These numbers depend on the processor architecture being
92 simulated: */
93 #define Interrupt (0)
94 #define TLBModification (1)
95 #define TLBLoad (2)
96 #define TLBStore (3)
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) */
106 #define Trap (13)
107 #define FPE (15)
108 #define Watch (23)
109
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)
114
115 /* The following are generic to all versions of the MIPS architecture
116 to date: */
117 /* Memory Access Types (for CCA): */
118 #define Uncached (0)
119 #define CachedNoncoherent (1)
120 #define CachedCoherent (2)
121 #define Cached (3)
122
123 #define isINSTRUCTION (1 == 0) /* FALSE */
124 #define isDATA (1 == 1) /* TRUE */
125
126 #define isLOAD (1 == 0) /* FALSE */
127 #define isSTORE (1 == 1) /* TRUE */
128
129 #define isREAL (1 == 0) /* FALSE */
130 #define isRAW (1 == 1) /* TRUE */
131
132 #define isTARGET (1 == 0) /* FALSE */
133 #define isHOST (1 == 1) /* TRUE */
134
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)
145
146 #if defined(HASFPU)
147 /* FPU registers must be one of the following types. All other values
148 are reserved (and undefined). */
149 typedef enum {
150 fmt_single = 0,
151 fmt_double = 1,
152 fmt_word = 4,
153 fmt_long = 5,
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,
158 } FP_formats;
159 #endif /* HASFPU */
160
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. */
175
176 static host_callback *callback = NULL; /* handle onto the current callback structure */
177
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
183 state. */
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. */
189 #ifndef TM_MIPS_H
190 #define LAST_EMBED_REGNUM (89)
191 #endif
192
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];
198
199 #define GPR (&registers[0])
200 #if defined(HASFPU)
201 #define FGRIDX (38)
202 #define FGR (&registers[FGRIDX])
203 #endif /* HASFPU */
204 #define LO (registers[33])
205 #define HI (registers[34])
206 #define PC (registers[37])
207 #define CAUSE (registers[36])
208 #define SRIDX (32)
209 #define SR (registers[SRIDX]) /* CPU status register */
210 #define FCR0IDX (71)
211 #define FCR0 (registers[FCR0IDX]) /* really a 32bit register */
212 #define FCR31IDX (70)
213 #define FCR31 (registers[FCR31IDX]) /* really a 32bit register */
214 #define FCSR (FCR31)
215 #define COCIDX (LAST_EMBED_REGNUM + 2) /* special case : outside the normal range */
216
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])
226
227 static ut_reg EPC = 0; /* Exception PC */
228
229 #if defined(HASFPU)
230 /* Keep the current format state for each register: */
231 static FP_formats fpr_state[32];
232 #endif /* HASFPU */
233
234 /* VR4300 CP0 configuration register: */
235 static unsigned int CONFIG = 0;
236
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 */
240
241
242 /* TODO : these should be the bitmasks for these bits within the
243 status register. At the moment the following are VR4300
244 bit-positions: */
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)
251
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 */
259
260 #define config_EP_mask (0xF)
261 #define config_EP_shift (27)
262 #define config_EP_D (0x0)
263 #define config_EP_DxxDxx (0x6)
264
265 #define config_BE (1 << 15)
266
267 #define cause_BD ((unsigned)1 << 31) /* Exception in branch delay slot */
268
269 #if defined(HASFPU)
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));\
277 }
278 #define GETFCC(cc) (((((cc) == 0) ? (FCSR & (1 << 23)) : (FCSR & (1 << (24 + (cc))))) != 0) ? 1 : 0)
279
280 /* This should be the COC1 value at the start of the preceding
281 instruction: */
282 #define PREVCOC1() ((state & simPCOC1) ? 1 : 0)
283 #endif /* HASFPU */
284
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 */
292
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)
298 #else
299 #define FP_FLAGS(b) (1 << ((b) + 2))
300 #define FP_ENABLE(b) (1 << ((b) + 7))
301 #define FP_CAUSE(b) (1 << ((b) + 12))
302 #endif
303
304 #define FP_FS (1 << 24) /* MIPS III onwards : Flush to Zero */
305
306 #define FP_MASK_RM (0x3)
307 #define FP_SH_RM (0)
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)
313
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
318 cycle. */
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];
326
327 /*---------------------------------------------------------------------------*/
328 /*-- GDB simulator interface ------------------------------------------------*/
329 /*---------------------------------------------------------------------------*/
330
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));
344
345 /*---------------------------------------------------------------------------*/
346
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));*/\
356 pending_total++;\
357 pending_in++;\
358 if (pending_in == PSLOTS)\
359 pending_in = 0;\
360 /*printf("DBG: FILL AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total);*/\
361 }
362
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
369 instructions. */
370
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;
377
378 /* TODO: The 4300 has interlocks so we should not need to warn of the possible over-write (CHECK THIS) */
379 /* If either of the preceding two instructions have accessed the HI or
380 LO registers, then the values they see should be
381 undefined. However, to keep the simulator world simple, we just let
382 them use the value read and raise a warning to notify the user: */
383 #define CHECKHILO(s) {\
384 if ((HIACCESS != 0) || (LOACCESS != 0))\
385 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));\
386 }
387
388 /* NOTE: We keep the following status flags as bit values (1 for true,
389 0 for false). This allows them to be used in binary boolean
390 operations without worrying about what exactly the non-zero true
391 value is. */
392
393 /* UserMode */
394 #define UserMode ((((SR & status_KSU_mask) >> status_KSU_shift) == ksu_user) ? 1 : 0)
395
396 /* BigEndianMem */
397 /* Hardware configuration. Affects endianness of LoadMemory and
398 StoreMemory and the endianness of Kernel and Supervisor mode
399 execution. The value is 0 for little-endian; 1 for big-endian. */
400 #define BigEndianMem ((CONFIG & config_BE) ? 1 : 0)
401 /* NOTE: Problems will occur if the simulator memory model does not
402 match the host program expectation. i.e. if the host is writing
403 big-endian values to a little-endian memory model. */
404
405 /* ReverseEndian */
406 /* This mode is selected if in User mode with the RE bit being set in
407 SR (Status Register). It reverses the endianness of load and store
408 instructions. */
409 #define ReverseEndian (((SR & status_RE) && UserMode) ? 1 : 0)
410
411 /* BigEndianCPU */
412 /* The endianness for load and store instructions (0=little;1=big). In
413 User mode this endianness may be switched by setting the state_RE
414 bit in the SR register. Thus, BigEndianCPU may be computed as
415 (BigEndienMem EOR ReverseEndian). */
416 #define BigEndianCPU (BigEndianMem ^ ReverseEndian) /* Already bits */
417
418 #if !defined(FASTSIM) || defined(PROFILE)
419 /* At the moment these values will be the same, since we do not have
420 access to the pipeline cycle count information from the simulator
421 engine. */
422 static unsigned int instruction_fetches = 0;
423 static unsigned int instruction_fetch_overflow = 0;
424 static unsigned int pipeline_ticks = 0;
425 #endif
426
427 /* Flags in the "state" variable: */
428 #define simSTOP (1 << 0) /* 0 = execute; 1 = stop simulation */
429 #define simSTEP (1 << 1) /* 0 = run; 1 = single-step */
430 #define simHALTEX (1 << 2) /* 0 = run; 1 = halt on exception */
431 #define simHALTIN (1 << 3) /* 0 = run; 1 = halt on interrupt */
432 #define simTRACE (1 << 8) /* 0 = do nothing; 1 = trace address activity */
433 #define simPROFILE (1 << 9) /* 0 = do nothing; 1 = gather profiling samples */
434 #define simHOSTBE (1 << 10) /* 0 = little-endian; 1 = big-endian (host endianness) */
435 /* Whilst simSTOP is not set, the simulator control loop should just
436 keep simulating instructions. The simSTEP flag is used to force
437 single-step execution. */
438 #define simBE (1 << 16) /* 0 = little-endian; 1 = big-endian (target endianness) */
439 #define simPCOC0 (1 << 17) /* COC[1] from current */
440 #define simPCOC1 (1 << 18) /* COC[1] from previous */
441 #define simDELAYSLOT (1 << 24) /* 0 = do nothing; 1 = delay slot entry exists */
442 #define simSKIPNEXT (1 << 25) /* 0 = do nothing; 1 = skip instruction */
443 #define simEXCEPTION (1 << 26) /* 0 = no exception; 1 = exception has occurred */
444 #define simEXIT (1 << 27) /* 0 = do nothing; 1 = run-time exit() processing */
445
446 static unsigned int state = 0;
447 static unsigned int rcexit = 0; /* _exit() reason code holder */
448
449 #define DELAYSLOT() {\
450 if (state & simDELAYSLOT)\
451 sim_warning("Delay slot already activated (branch in delay slot?)");\
452 state |= simDELAYSLOT;\
453 }
454
455 #define NULLIFY() {\
456 state &= ~simDELAYSLOT;\
457 state |= simSKIPNEXT;\
458 }
459
460 #define K0BASE (0x80000000)
461 #define K0SIZE (0x20000000)
462 #define K1BASE (0xA0000000)
463 #define K1SIZE (0x20000000)
464
465 /* Very simple memory model to start with: */
466 static unsigned char *membank = NULL;
467 static ut_reg membank_base = K1BASE;
468 static unsigned membank_size = (1 << 20); /* (16 << 20); */ /* power-of-2 */
469
470 /* Simple run-time monitor support */
471 static unsigned char *monitor = NULL;
472 static ut_reg monitor_base = 0xBFC00000;
473 static unsigned monitor_size = (1 << 11); /* power-of-2 */
474
475 static char *logfile = NULL; /* logging disabled by default */
476 static FILE *logfh = NULL;
477
478 #if defined(TRACE)
479 static char *tracefile = "trace.din"; /* default filename for trace log */
480 static FILE *tracefh = NULL;
481 #endif /* TRACE */
482
483 #if defined(PROFILE)
484 static unsigned profile_frequency = 256;
485 static unsigned profile_nsamples = (128 << 10);
486 static unsigned short *profile_hist = NULL;
487 static ut_reg profile_minpc;
488 static ut_reg profile_maxpc;
489 static int profile_shift = 0; /* address shift amount */
490 #endif /* PROFILE */
491
492 /* The following are used to provide shortcuts to the required version
493 of host<->target copying. This avoids run-time conditionals, which
494 would slow the simulator throughput. */
495 typedef unsigned int (*fnptr_read_word) PARAMS((unsigned char *memory));
496 typedef unsigned int (*fnptr_swap_word) PARAMS((unsigned int data));
497 typedef uword64 (*fnptr_read_long) PARAMS((unsigned char *memory));
498 typedef uword64 (*fnptr_swap_long) PARAMS((uword64 data));
499
500 static fnptr_read_word host_read_word;
501 static fnptr_read_long host_read_long;
502 static fnptr_swap_word host_swap_word;
503 static fnptr_swap_long host_swap_long;
504
505 /*---------------------------------------------------------------------------*/
506 /*-- GDB simulator interface ------------------------------------------------*/
507 /*---------------------------------------------------------------------------*/
508
509 void
510 sim_open (args)
511 char *args;
512 {
513 if (callback == NULL) {
514 fprintf(stderr,"SIM Error: sim_open() called without callbacks attached\n");
515 return;
516 }
517
518 /* The following ensures that the standard file handles for stdin,
519 stdout and stderr are initialised: */
520 callback->init(callback);
521
522 state = 0;
523 CHECKSIM();
524 if (state & simEXCEPTION) {
525 fprintf(stderr,"This simulator is not suitable for this host configuration\n");
526 exit(1);
527 }
528
529 {
530 int data = 0x12;
531 if (*((char *)&data) != 0x12)
532 state |= simHOSTBE; /* big-endian host */
533 }
534
535 #if defined(HASFPU)
536 /* Check that the host FPU conforms to IEEE 754-1985 for the SINGLE
537 and DOUBLE binary formats. This is a bit nasty, requiring that we
538 trust the explicit manifests held in the source: */
539 {
540 unsigned int s[2];
541 s[state & simHOSTBE ? 0 : 1] = 0x40805A5A;
542 s[state & simHOSTBE ? 1 : 0] = 0x00000000;
543
544 /* TODO: We need to cope with the simulated target and the host
545 not having the same endianness. This will require the high and
546 low words of a (double) to be swapped when converting between
547 the host and the simulated target. */
548
549 if (((float)4.01102924346923828125 != *(float *)(s + ((state & simHOSTBE) ? 0 : 1))) || ((double)523.2939453125 != *(double *)s)) {
550 fprintf(stderr,"The host executing the simulator does not seem to have IEEE 754-1985 std FP\n");
551 fprintf(stderr,"*(float *)s = %.20f (4.01102924346923828125)\n",*(float *)s);
552 fprintf(stderr,"*(double *)s = %.20f (523.2939453125)\n",*(double *)s);
553 exit(1);
554 }
555 }
556 #endif /* HASFPU */
557
558 /* This is NASTY, in that we are assuming the size of specific
559 registers: */
560 {
561 int rn;
562 for (rn = 0; (rn < (LAST_EMBED_REGNUM + 1)); rn++) {
563 if (rn < 32)
564 register_widths[rn] = GPRLEN;
565 else if ((rn >= FGRIDX) && (rn < (FGRIDX + 32)))
566 register_widths[rn] = GPRLEN;
567 else if ((rn >= 33) && (rn <= 37))
568 register_widths[rn] = GPRLEN;
569 else if ((rn == SRIDX) || (rn == FCR0IDX) || (rn == FCR31IDX) || ((rn >= 72) && (rn <= 89)))
570 register_widths[rn] = 32;
571 else
572 register_widths[rn] = 0;
573 }
574 }
575
576 /* It would be good if we could select particular named MIPS
577 architecture simulators. However, having a pre-built, fixed
578 engine would mean including multiple engines. If the simulator is
579 changed to a run-time conditional version, then the ability to
580 select a particular architecture would be straightforward. */
581 if (args != NULL) {
582 int c;
583 char *cline;
584 char **argv;
585 int argc;
586 static struct option cmdline[] = {
587 {"help", 0,0,'h'},
588 {"log", 1,0,'l'},
589 {"name", 1,0,'n'},
590 {"profile", 0,0,'p'},
591 {"size", 1,0,'s'},
592 {"trace", 0,0,'t'},
593 {"tracefile",1,0,'z'},
594 {"frequency",1,0,'y'},
595 {"samples", 1,0,'x'},
596 {0, 0,0,0}
597 };
598
599 /* Unfortunately, getopt_long() is designed to be used with
600 vectors, where the first option is normally program name (and
601 ignored). We cheat by creating a dummy first argument, so that
602 we can use the standard argument processing. */
603 #define DUMMYARG "simulator "
604 cline = (char *)malloc(strlen(args) + strlen(DUMMYARG) + 1);
605 if (cline == NULL) {
606 fprintf(stderr,"Failed to allocate memory for command line buffer\n");
607 exit(1);
608 }
609 sprintf(cline,"%s%s",DUMMYARG,args);
610 argv = buildargv(cline);
611 for (argc = 0; argv[argc]; argc++);
612
613 /* Unfortunately, getopt_long() assumes that it is ignoring the
614 first argument (normally the program name). This means it
615 ignores the first option on our "args" line. */
616 optind = 0; /* Force reset of argument processing */
617 while (1) {
618 int option_index = 0;
619
620 c = getopt_long(argc,argv,"hn:s:tp",cmdline,&option_index);
621 if (c == -1)
622 break;
623
624 switch (c) {
625 case 'h':
626 callback->printf_filtered(callback,"Usage:\n\t\
627 target sim [-h] [--log=<file>] [--name=<model>] [--size=<amount>]");
628 #if defined(TRACE)
629 callback->printf_filtered(callback," [-t [--tracefile=<name>]]");
630 #endif /* TRACE */
631 #if defined(PROFILE)
632 callback->printf_filtered(callback," [-p [--frequency=<count>] [--samples=<count>]]");
633 #endif /* PROFILE */
634 callback->printf_filtered(callback,"\n");
635 break;
636
637 case 'l':
638 if (optarg != NULL) {
639 char *tmp;
640 tmp = (char *)malloc(strlen(optarg) + 1);
641 if (tmp == NULL)
642 callback->printf_filtered(callback,"Failed to allocate buffer for logfile name \"%s\"\n",optarg);
643 else {
644 strcpy(tmp,optarg);
645 logfile = tmp;
646 }
647 }
648 break;
649
650 case 'n':
651 callback->printf_filtered(callback,"Explicit model selection not yet available (Ignoring \"%s\")\n",optarg);
652 break;
653
654 case 's':
655 membank_size = (unsigned)getnum(optarg);
656 break;
657
658 case 't':
659 #if defined(TRACE)
660 /* Eventually the simTRACE flag could be treated as a toggle, to
661 allow external control of the program points being traced
662 (i.e. only from main onwards, excluding the run-time setup,
663 etc.). */
664 state |= simTRACE;
665 #else /* !TRACE */
666 fprintf(stderr,"\
667 Simulator constructed without tracing support (for performance).\n\
668 Re-compile simulator with \"-DTRACE\" to enable this option.\n");
669 #endif /* !TRACE */
670 break;
671
672 case 'z':
673 #if defined(TRACE)
674 if (optarg != NULL) {
675 char *tmp;
676 tmp = (char *)malloc(strlen(optarg) + 1);
677 if (tmp == NULL)
678 callback->printf_filtered(callback,"Failed to allocate buffer for tracefile name \"%s\"\n",optarg);
679 else {
680 strcpy(tmp,optarg);
681 tracefile = tmp;
682 callback->printf_filtered(callback,"Placing trace information into file \"%s\"\n",tracefile);
683 }
684 }
685 #endif /* TRACE */
686 break;
687
688 case 'p':
689 #if defined(PROFILE)
690 state |= simPROFILE;
691 #else /* !PROFILE */
692 fprintf(stderr,"\
693 Simulator constructed without profiling support (for performance).\n\
694 Re-compile simulator with \"-DPROFILE\" to enable this option.\n");
695 #endif /* !PROFILE */
696 break;
697
698 case 'x':
699 #if defined(PROFILE)
700 profile_nsamples = (unsigned)getnum(optarg);
701 #endif /* PROFILE */
702 break;
703
704 case 'y':
705 #if defined(PROFILE)
706 sim_set_profile((int)getnum(optarg));
707 #endif /* PROFILE */
708 break;
709
710 default:
711 callback->printf_filtered(callback,"Warning: Simulator getopt returned unrecognised code 0x%08X\n",c);
712 case '?':
713 break;
714 }
715 }
716
717 #if 0
718 if (optind < argc) {
719 callback->printf_filtered(callback,"Warning: Ignoring spurious non-option arguments ");
720 while (optind < argc)
721 callback->printf_filtered(callback,"\"%s\" ",argv[optind++]);
722 callback->printf_filtered(callback,"\n");
723 }
724 #endif
725
726 freeargv(argv);
727 }
728
729 if (logfile != NULL) {
730 if (strcmp(logfile,"-") == 0)
731 logfh = stdout;
732 else {
733 logfh = fopen(logfile,"wb+");
734 if (logfh == NULL) {
735 callback->printf_filtered(callback,"Failed to create file \"%s\", writing log information to stderr.\n",tracefile);
736 logfh = stderr;
737 }
738 }
739 }
740
741 /* If the host has "mmap" available we could use it to provide a
742 very large virtual address space for the simulator, since memory
743 would only be allocated within the "mmap" space as it is
744 accessed. This can also be linked to the architecture specific
745 support, required to simulate the MMU. */
746 sim_size(membank_size);
747 /* NOTE: The above will also have enabled any profiling state */
748
749 ColdReset();
750 /* If we were providing a more complete I/O, co-processor or memory
751 simulation, we should perform any "device" initialisation at this
752 point. This can include pre-loading memory areas with particular
753 patterns (e.g. simulating ROM monitors). */
754
755 /* We can start writing to the memory, now that the processor has
756 been reset: */
757 monitor = (unsigned char *)calloc(1,monitor_size);
758 if (!monitor) {
759 fprintf(stderr,"Not enough VM for monitor simulation (%d bytes)\n",monitor_size);
760 } else {
761 unsigned loop;
762 /* Entry into the IDT monitor is via fixed address vectors, and
763 not using machine instructions. To avoid clashing with use of
764 the MIPS TRAP system, we place our own (simulator specific)
765 "undefined" instructions into the relevant vector slots. */
766 for (loop = 0; (loop < monitor_size); loop += 4) {
767 uword64 vaddr = (monitor_base + loop);
768 uword64 paddr;
769 int cca;
770 if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW))
771 StoreMemory(cca,AccessLength_WORD,(RSVD_INSTRUCTION | ((loop >> 2) & RSVD_INSTRUCTION_AMASK)),paddr,vaddr,isRAW);
772 }
773 /* The PMON monitor uses the same address space, but rather than
774 branching into it the address of a routine is loaded. We can
775 cheat for the moment, and direct the PMON routine to IDT style
776 instructions within the monitor space. This relies on the IDT
777 monitor not using the locations from 0xBFC00500 onwards as its
778 entry points.*/
779 for (loop = 0; (loop < 24); loop++)
780 {
781 uword64 vaddr = (monitor_base + 0x500 + (loop * 4));
782 uword64 paddr;
783 int cca;
784 unsigned int value = ((0x500 - 8) / 8); /* default UNDEFINED reason code */
785 switch (loop)
786 {
787 case 0: /* read */
788 value = 7;
789 break;
790
791 case 1: /* write */
792 value = 8;
793 break;
794
795 case 2: /* open */
796 value = 6;
797 break;
798
799 case 3: /* close */
800 value = 10;
801 break;
802
803 case 5: /* printf */
804 value = ((0x500 - 16) / 8); /* not an IDT reason code */
805 break;
806
807 case 8: /* cliexit */
808 value = 17;
809 break;
810 }
811 /* FIXME - should monitor_base be SIM_ADDR?? */
812 value = ((unsigned int)monitor_base + (value * 8));
813 if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW))
814 StoreMemory(cca,AccessLength_WORD,value,paddr,vaddr,isRAW);
815 else
816 sim_error("Failed to write to monitor space 0x%08X%08X",WORD64HI(vaddr),WORD64LO(vaddr));
817 }
818 }
819
820 #if defined(TRACE)
821 if (state & simTRACE) {
822 tracefh = fopen(tracefile,"wb+");
823 if (tracefh == NULL) {
824 sim_warning("Failed to create file \"%s\", writing trace information to stderr.",tracefile);
825 tracefh = stderr;
826 }
827 }
828 #endif /* TRACE */
829
830 return;
831 }
832
833 /* For the profile writing, we write the data in the host
834 endianness. This unfortunately means we are assuming that the
835 profile file we create is processed on the same host executing the
836 simulator. The gmon.out file format should either have an explicit
837 endianness, or a method of encoding the endianness in the file
838 header. */
839 static int
840 writeout32(fh,val)
841 FILE *fh;
842 unsigned int val;
843 {
844 char buff[4];
845 int res = 1;
846
847 if (state & simHOSTBE) {
848 buff[3] = ((val >> 0) & 0xFF);
849 buff[2] = ((val >> 8) & 0xFF);
850 buff[1] = ((val >> 16) & 0xFF);
851 buff[0] = ((val >> 24) & 0xFF);
852 } else {
853 buff[0] = ((val >> 0) & 0xFF);
854 buff[1] = ((val >> 8) & 0xFF);
855 buff[2] = ((val >> 16) & 0xFF);
856 buff[3] = ((val >> 24) & 0xFF);
857 }
858 if (fwrite(buff,4,1,fh) != 1) {
859 sim_warning("Failed to write 4bytes to the profile file");
860 res = 0;
861 }
862 return(res);
863 }
864
865 static int
866 writeout16(fh,val)
867 FILE *fh;
868 unsigned short val;
869 {
870 char buff[2];
871 int res = 1;
872 if (state & simHOSTBE) {
873 buff[1] = ((val >> 0) & 0xFF);
874 buff[0] = ((val >> 8) & 0xFF);
875 } else {
876 buff[0] = ((val >> 0) & 0xFF);
877 buff[1] = ((val >> 8) & 0xFF);
878 }
879 if (fwrite(buff,2,1,fh) != 1) {
880 sim_warning("Failed to write 2bytes to the profile file");
881 res = 0;
882 }
883 return(res);
884 }
885
886 void
887 sim_close (quitting)
888 int quitting;
889 {
890 #ifdef DEBUG
891 printf("DBG: sim_close: entered (quitting = %d)\n",quitting);
892 #endif
893
894 /* Cannot assume sim_kill() has been called */
895 /* "quitting" is non-zero if we cannot hang on errors */
896
897 /* Ensure that any resources allocated through the callback
898 mechanism are released: */
899 callback->shutdown(callback);
900
901 #if defined(PROFILE)
902 if ((state & simPROFILE) && (profile_hist != NULL)) {
903 unsigned short *p = profile_hist;
904 FILE *pf = fopen("gmon.out","wb");
905 unsigned loop;
906
907 if (pf == NULL)
908 sim_warning("Failed to open \"gmon.out\" profile file");
909 else {
910 int ok;
911 #ifdef DEBUG
912 printf("DBG: minpc = 0x%08X\n",(unsigned int)profile_minpc);
913 printf("DBG: maxpc = 0x%08X\n",(unsigned int)profile_maxpc);
914 #endif /* DEBUG */
915 ok = writeout32(pf,(unsigned int)profile_minpc);
916 if (ok)
917 ok = writeout32(pf,(unsigned int)profile_maxpc);
918 if (ok)
919 ok = writeout32(pf,(profile_nsamples * 2) + 12); /* size of sample buffer (+ header) */
920 #ifdef DEBUG
921 printf("DBG: nsamples = %d (size = 0x%08X)\n",profile_nsamples,((profile_nsamples * 2) + 12));
922 #endif /* DEBUG */
923 for (loop = 0; (ok && (loop < profile_nsamples)); loop++) {
924 ok = writeout16(pf,profile_hist[loop]);
925 if (!ok)
926 break;
927 }
928
929 fclose(pf);
930 }
931
932 free(profile_hist);
933 profile_hist = NULL;
934 state &= ~simPROFILE;
935 }
936 #endif /* PROFILE */
937
938 #if defined(TRACE)
939 if (tracefh != NULL && tracefh != stderr)
940 fclose(tracefh);
941 tracefh = NULL;
942 state &= ~simTRACE;
943 #endif /* TRACE */
944
945 if (logfh != NULL && logfh != stdout && logfh != stderr)
946 fclose(logfh);
947 logfh = NULL;
948
949 if (membank)
950 free(membank); /* cfree not available on all hosts */
951 membank = NULL;
952
953 return;
954 }
955
956 void
957 sim_resume (step,signal)
958 int step, signal;
959 {
960 #ifdef DEBUG
961 printf("DBG: sim_resume entered: step = %d, signal = %d (membank = 0x%08X)\n",step,signal,membank);
962 #endif /* DEBUG */
963
964 if (step)
965 state |= simSTEP; /* execute only a single instruction */
966 else
967 state &= ~(simSTOP | simSTEP); /* execute until event */
968
969 state |= (simHALTEX | simHALTIN); /* treat interrupt event as exception */
970
971 /* Start executing instructions from the current state (set
972 explicitly by register updates, or by sim_create_inferior): */
973
974 simulate();
975 return;
976 }
977
978 int
979 sim_write (addr,buffer,size)
980 SIM_ADDR addr;
981 unsigned char *buffer;
982 int size;
983 {
984 int index = size;
985 uword64 vaddr = (uword64)addr;
986
987 /* Return the number of bytes written, or zero if error. */
988 #ifdef DEBUG
989 callback->printf_filtered(callback,"sim_write(0x%08X%08X,buffer,%d);\n",WORD64HI(addr),WORD64LO(addr),size);
990 #endif
991
992 /* We provide raw read and write routines, since we do not want to
993 count the GDB memory accesses in our statistics gathering. */
994
995 /* There is a lot of code duplication in the individual blocks
996 below, but the variables are declared locally to a block to give
997 the optimiser the best chance of improving the code. We have to
998 perform slow byte reads from the host memory, to ensure that we
999 get the data into the correct endianness for the (simulated)
1000 target memory world. */
1001
1002 /* Mask count to get odd byte, odd halfword, and odd word out of the
1003 way. We can then perform doubleword transfers to and from the
1004 simulator memory for optimum performance. */
1005 if (index && (index & 1)) {
1006 uword64 paddr;
1007 int cca;
1008 if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) {
1009 uword64 value = ((uword64)(*buffer++));
1010 StoreMemory(cca,AccessLength_BYTE,value,paddr,vaddr,isRAW);
1011 }
1012 vaddr++;
1013 index &= ~1; /* logical operations usually quicker than arithmetic on RISC systems */
1014 }
1015 if (index && (index & 2)) {
1016 uword64 paddr;
1017 int cca;
1018 if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) {
1019 uword64 value;
1020 /* We need to perform the following magic to ensure that that
1021 bytes are written into same byte positions in the target memory
1022 world, regardless of the endianness of the host. */
1023 if (BigEndianMem) {
1024 value = ((uword64)(*buffer++) << 8);
1025 value |= ((uword64)(*buffer++) << 0);
1026 } else {
1027 value = ((uword64)(*buffer++) << 0);
1028 value |= ((uword64)(*buffer++) << 8);
1029 }
1030 StoreMemory(cca,AccessLength_HALFWORD,value,paddr,vaddr,isRAW);
1031 }
1032 vaddr += 2;
1033 index &= ~2;
1034 }
1035 if (index && (index & 4)) {
1036 uword64 paddr;
1037 int cca;
1038 if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) {
1039 uword64 value;
1040 if (BigEndianMem) {
1041 value = ((uword64)(*buffer++) << 24);
1042 value |= ((uword64)(*buffer++) << 16);
1043 value |= ((uword64)(*buffer++) << 8);
1044 value |= ((uword64)(*buffer++) << 0);
1045 } else {
1046 value = ((uword64)(*buffer++) << 0);
1047 value |= ((uword64)(*buffer++) << 8);
1048 value |= ((uword64)(*buffer++) << 16);
1049 value |= ((uword64)(*buffer++) << 24);
1050 }
1051 StoreMemory(cca,AccessLength_WORD,value,paddr,vaddr,isRAW);
1052 }
1053 vaddr += 4;
1054 index &= ~4;
1055 }
1056 for (;index; index -= 8) {
1057 uword64 paddr;
1058 int cca;
1059 if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) {
1060 uword64 value;
1061 if (BigEndianMem) {
1062 value = ((uword64)(*buffer++) << 56);
1063 value |= ((uword64)(*buffer++) << 48);
1064 value |= ((uword64)(*buffer++) << 40);
1065 value |= ((uword64)(*buffer++) << 32);
1066 value |= ((uword64)(*buffer++) << 24);
1067 value |= ((uword64)(*buffer++) << 16);
1068 value |= ((uword64)(*buffer++) << 8);
1069 value |= ((uword64)(*buffer++) << 0);
1070 } else {
1071 value = ((uword64)(*buffer++) << 0);
1072 value |= ((uword64)(*buffer++) << 8);
1073 value |= ((uword64)(*buffer++) << 16);
1074 value |= ((uword64)(*buffer++) << 24);
1075 value |= ((uword64)(*buffer++) << 32);
1076 value |= ((uword64)(*buffer++) << 40);
1077 value |= ((uword64)(*buffer++) << 48);
1078 value |= ((uword64)(*buffer++) << 56);
1079 }
1080 StoreMemory(cca,AccessLength_DOUBLEWORD,value,paddr,vaddr,isRAW);
1081 }
1082 vaddr += 8;
1083 }
1084
1085 return(size);
1086 }
1087
1088 int
1089 sim_read (addr,buffer,size)
1090 SIM_ADDR addr;
1091 unsigned char *buffer;
1092 int size;
1093 {
1094 int index;
1095
1096 /* Return the number of bytes read, or zero if error. */
1097 #ifdef DEBUG
1098 callback->printf_filtered(callback,"sim_read(0x%08X%08X,buffer,%d);\n",WORD64HI(addr),WORD64LO(addr),size);
1099 #endif /* DEBUG */
1100
1101 /* TODO: Perform same optimisation as the sim_write() code
1102 above. NOTE: This will require a bit more work since we will need
1103 to ensure that the source physical address is doubleword aligned
1104 before, and then deal with trailing bytes. */
1105 for (index = 0; (index < size); index++) {
1106 uword64 vaddr,paddr,value;
1107 int cca;
1108 vaddr = (uword64)addr + index;
1109 if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&cca,isTARGET,isRAW)) {
1110 value = LoadMemory(cca,AccessLength_BYTE,paddr,vaddr,isDATA,isRAW);
1111 buffer[index] = (unsigned char)(value&0xFF);
1112 } else
1113 break;
1114 }
1115
1116 return(index);
1117 }
1118
1119 void
1120 sim_store_register (rn,memory)
1121 int rn;
1122 unsigned char *memory;
1123 {
1124 #ifdef DEBUG
1125 callback->printf_filtered(callback,"sim_store_register(%d,*memory=0x%08X%08X);\n",rn,*((unsigned int *)memory),*((unsigned int *)(memory + 4)));
1126 #endif /* DEBUG */
1127
1128 /* Unfortunately this suffers from the same problem as the register
1129 numbering one. We need to know what the width of each logical
1130 register number is for the architecture being simulated. */
1131 if (register_widths[rn] == 0)
1132 sim_warning("Invalid register width for %d (register store ignored)",rn);
1133 else {
1134 if (register_widths[rn] == 32)
1135 registers[rn] = host_read_word(memory);
1136 else
1137 registers[rn] = host_read_long(memory);
1138 }
1139
1140 return;
1141 }
1142
1143 void
1144 sim_fetch_register (rn,memory)
1145 int rn;
1146 unsigned char *memory;
1147 {
1148 #ifdef DEBUG
1149 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]));
1150 #endif /* DEBUG */
1151
1152 if (register_widths[rn] == 0)
1153 sim_warning("Invalid register width for %d (register fetch ignored)",rn);
1154 else {
1155 if (register_widths[rn] == 32)
1156 *((unsigned int *)memory) = host_swap_word((unsigned int)(registers[rn] & 0xFFFFFFFF));
1157 else /* 64bit register */
1158 *((uword64 *)memory) = host_swap_long(registers[rn]);
1159 }
1160 return;
1161 }
1162
1163 void
1164 sim_stop_reason (reason,sigrc)
1165 enum sim_stop *reason;
1166 int *sigrc;
1167 {
1168 /* We can have "*reason = {sim_exited, sim_stopped, sim_signalled}", so
1169 sim_exited *sigrc = argument to exit()
1170 sim_stopped *sigrc = exception number
1171 sim_signalled *sigrc = signal number
1172 */
1173 if (state & simEXCEPTION) {
1174 /* If "sim_signalled" is used, GDB expects normal SIGNAL numbers,
1175 and not the MIPS specific exception codes. */
1176 #if 1
1177 /* For some reason, sending GDB a sim_signalled reason cause it to
1178 terminate out. */
1179 *reason = sim_stopped;
1180 #else
1181 *reason = sim_signalled;
1182 #endif
1183 switch ((CAUSE >> 2) & 0x1F) {
1184 case Interrupt:
1185 *sigrc = SIGINT; /* wrong type of interrupt, but it will do for the moment */
1186 break;
1187
1188 case TLBModification:
1189 case TLBLoad:
1190 case TLBStore:
1191 case AddressLoad:
1192 case AddressStore:
1193 case InstructionFetch:
1194 case DataReference:
1195 *sigrc = SIGBUS;
1196 break;
1197
1198 case ReservedInstruction:
1199 case CoProcessorUnusable:
1200 *sigrc = SIGILL;
1201 break;
1202
1203 case IntegerOverflow:
1204 case FPE:
1205 *sigrc = SIGFPE;
1206 break;
1207
1208 case Trap:
1209 case Watch:
1210 case SystemCall:
1211 case BreakPoint:
1212 *sigrc = SIGTRAP;
1213 break;
1214
1215 default : /* Unknown internal exception */
1216 *sigrc = SIGQUIT;
1217 break;
1218 }
1219 } else if (state & simEXIT) {
1220 #if 0
1221 printf("DBG: simEXIT (%d)\n",rcexit);
1222 #endif
1223 *reason = sim_exited;
1224 *sigrc = rcexit;
1225 } else { /* assume single-stepping */
1226 *reason = sim_stopped;
1227 *sigrc = SIGTRAP;
1228 }
1229 state &= ~(simEXCEPTION | simEXIT);
1230 return;
1231 }
1232
1233 void
1234 sim_info (verbose)
1235 int verbose;
1236 {
1237 /* Accessed from the GDB "info files" command: */
1238
1239 callback->printf_filtered(callback,"MIPS %d-bit simulator\n",(PROCESSOR_64BIT ? 64 : 32));
1240
1241 callback->printf_filtered(callback,"%s endian memory model\n",(BigEndianMem ? "Big" : "Little"));
1242
1243 callback->printf_filtered(callback,"0x%08X bytes of memory at 0x%08X%08X\n",(unsigned int)membank_size,WORD64HI(membank_base),WORD64LO(membank_base));
1244
1245 #if !defined(FASTSIM)
1246 if (instruction_fetch_overflow != 0)
1247 callback->printf_filtered(callback,"Instruction fetches = 0x%08X%08X\n",instruction_fetch_overflow,instruction_fetches);
1248 else
1249 callback->printf_filtered(callback,"Instruction fetches = %d\n",instruction_fetches);
1250 callback->printf_filtered(callback,"Pipeline ticks = %d\n",pipeline_ticks);
1251 /* It would be a useful feature, if when performing multi-cycle
1252 simulations (rather than single-stepping) we keep the start and
1253 end times of the execution, so that we can give a performance
1254 figure for the simulator. */
1255 #endif /* !FASTSIM */
1256
1257 /* print information pertaining to MIPS ISA and architecture being simulated */
1258 /* things that may be interesting */
1259 /* instructions executed - if available */
1260 /* cycles executed - if available */
1261 /* pipeline stalls - if available */
1262 /* virtual time taken */
1263 /* profiling size */
1264 /* profiling frequency */
1265 /* profile minpc */
1266 /* profile maxpc */
1267
1268 return;
1269 }
1270
1271 int
1272 sim_load (prog,from_tty)
1273 char *prog;
1274 int from_tty;
1275 {
1276 /* Return non-zero if the caller should handle the load. Zero if
1277 we have loaded the image. */
1278 return(-1);
1279 }
1280
1281 void
1282 sim_create_inferior (start_address,argv,env)
1283 SIM_ADDR start_address;
1284 char **argv;
1285 char **env;
1286 {
1287 #ifdef DEBUG
1288 printf("DBG: sim_create_inferior entered: start_address = 0x%08X\n",start_address);
1289 #endif /* DEBUG */
1290
1291 /* Prepare to execute the program to be simulated */
1292 /* argv and env are NULL terminated lists of pointers */
1293
1294 #if 1
1295 PC = (uword64)start_address;
1296 #else
1297 /* TODO: Sort this properly. SIM_ADDR may already be a 64bit value: */
1298 PC = SIGNEXTEND(start_address,32);
1299 #endif
1300 /* NOTE: GDB normally sets the PC explicitly. However, this call is
1301 used by other clients of the simulator. */
1302
1303 if (argv || env) {
1304 #if 0 /* def DEBUG */
1305 callback->printf_filtered(callback,"sim_create_inferior() : passed arguments ignored\n");
1306 {
1307 char **cptr;
1308 for (cptr = argv; (cptr && *cptr); cptr++)
1309 printf("DBG: arg \"%s\"\n",*cptr);
1310 }
1311 #endif /* DEBUG */
1312 /* We should really place the argv slot values into the argument
1313 registers, and onto the stack as required. However, this
1314 assumes that we have a stack defined, which is not necessarily
1315 true at the moment. */
1316 }
1317
1318 return;
1319 }
1320
1321 void
1322 sim_kill ()
1323 {
1324 #if 1
1325 /* This routine should be for terminating any existing simulation
1326 thread. Since we are single-threaded only at the moment, this is
1327 not an issue. It should *NOT* be used to terminate the
1328 simulator. */
1329 #else /* do *NOT* call sim_close */
1330 sim_close(1); /* Do not hang on errors */
1331 /* This would also be the point where any memory mapped areas used
1332 by the simulator should be released. */
1333 #endif
1334 return;
1335 }
1336
1337 ut_reg
1338 sim_get_quit_code ()
1339 {
1340 /* The standard MIPS PCS (Procedure Calling Standard) uses V0(r2) as
1341 the function return value. However, it may be more correct for
1342 this to return the argument to the exit() function (if
1343 called). */
1344 return(V0);
1345 }
1346
1347 void
1348 sim_set_callbacks (p)
1349 host_callback *p;
1350 {
1351 callback = p;
1352 return;
1353 }
1354
1355 typedef enum {e_terminate,e_help,e_setmemsize,e_reset} e_cmds;
1356
1357 static struct t_sim_command {
1358 e_cmds id;
1359 const char *name;
1360 const char *help;
1361 } sim_commands[] = {
1362 {e_help, "help", ": Show MIPS simulator private commands"},
1363 {e_setmemsize,"set-memory-size","<n> : Specify amount of memory simulated"},
1364 {e_reset, "reset-system", ": Reset the simulated processor"},
1365 {e_terminate, NULL}
1366 };
1367
1368 void
1369 sim_do_command (cmd)
1370 char *cmd;
1371 {
1372 struct t_sim_command *cptr;
1373
1374 if (callback == NULL) {
1375 fprintf(stderr,"Simulator not enabled: \"target sim\" should be used to activate\n");
1376 return;
1377 }
1378
1379 if (!(cmd && *cmd != '\0'))
1380 cmd = "help";
1381
1382 /* NOTE: Accessed from the GDB "sim" commmand: */
1383 for (cptr = sim_commands; cptr && cptr->name; cptr++)
1384 if (strncmp(cmd,cptr->name,strlen(cptr->name)) == 0) {
1385 cmd += strlen(cptr->name);
1386 switch (cptr->id) {
1387 case e_help: /* no arguments */
1388 { /* no arguments */
1389 struct t_sim_command *lptr;
1390 callback->printf_filtered(callback,"List of MIPS simulator commands:\n");
1391 for (lptr = sim_commands; lptr->name; lptr++)
1392 callback->printf_filtered(callback,"%s %s\n",lptr->name,lptr->help);
1393 }
1394 break;
1395
1396 case e_setmemsize: /* memory size argument */
1397 {
1398 unsigned int newsize = (unsigned int)getnum(cmd);
1399 sim_size(newsize);
1400 }
1401 break;
1402
1403 case e_reset: /* no arguments */
1404 ColdReset();
1405 /* NOTE: See the comments in sim_open() relating to device
1406 initialisation. */
1407 break;
1408
1409 default:
1410 callback->printf_filtered(callback,"FATAL: Matched \"%s\", but failed to match command id %d.\n",cmd,cptr->id);
1411 break;
1412 }
1413 break;
1414 }
1415
1416 if (!(cptr->name))
1417 callback->printf_filtered(callback,"Error: \"%s\" is not a valid MIPS simulator command.\n",cmd);
1418
1419 return;
1420 }
1421
1422 /*---------------------------------------------------------------------------*/
1423 /* NOTE: The following routines do not seem to be used by GDB at the
1424 moment. However, they may be useful to the standalone simulator
1425 world. */
1426
1427
1428 /* The profiling format is described in the "gmon_out.h" header file */
1429 void
1430 sim_set_profile (n)
1431 int n;
1432 {
1433 #if defined(PROFILE)
1434 profile_frequency = n;
1435 state |= simPROFILE;
1436 #endif /* PROFILE */
1437 return;
1438 }
1439
1440 void
1441 sim_set_profile_size (n)
1442 int n;
1443 {
1444 #if defined(PROFILE)
1445 if (state & simPROFILE) {
1446 int bsize;
1447
1448 /* Since we KNOW that the memory banks are a power-of-2 in size: */
1449 profile_nsamples = power2(n);
1450 profile_minpc = membank_base;
1451 profile_maxpc = (membank_base + membank_size);
1452
1453 /* Just in-case we are sampling every address: NOTE: The shift
1454 right of 2 is because we only have word-aligned PC addresses. */
1455 if (profile_nsamples > (membank_size >> 2))
1456 profile_nsamples = (membank_size >> 2);
1457
1458 /* Since we are dealing with power-of-2 values: */
1459 profile_shift = (((membank_size >> 2) / profile_nsamples) - 1);
1460
1461 bsize = (profile_nsamples * sizeof(unsigned short));
1462 if (profile_hist == NULL)
1463 profile_hist = (unsigned short *)calloc(64,(bsize / 64));
1464 else
1465 profile_hist = (unsigned short *)realloc(profile_hist,bsize);
1466 if (profile_hist == NULL) {
1467 sim_warning("Failed to allocate VM for profiling buffer (0x%08X bytes)",bsize);
1468 state &= ~simPROFILE;
1469 }
1470 }
1471 #endif /* PROFILE */
1472
1473 return;
1474 }
1475
1476 void
1477 sim_size(newsize)
1478 unsigned int newsize;
1479 {
1480 char *new;
1481 /* Used by "run", and internally, to set the simulated memory size */
1482 if (newsize == 0) {
1483 callback->printf_filtered(callback,"Zero not valid: Memory size still 0x%08X bytes\n",membank_size);
1484 return;
1485 }
1486 newsize = power2(newsize);
1487 if (membank == NULL)
1488 new = (char *)calloc(64,(membank_size / 64));
1489 else
1490 new = (char *)realloc(membank,newsize);
1491 if (new == NULL) {
1492 if (membank == NULL)
1493 sim_error("Not enough VM for simulation memory of 0x%08X bytes",membank_size);
1494 else
1495 sim_warning("Failed to resize memory (still 0x%08X bytes)",membank_size);
1496 } else {
1497 membank_size = (unsigned)newsize;
1498 membank = new;
1499 #if defined(PROFILE)
1500 /* Ensure that we sample across the new memory range */
1501 sim_set_profile_size(profile_nsamples);
1502 #endif /* PROFILE */
1503 }
1504
1505 return;
1506 }
1507
1508 int
1509 sim_trace()
1510 {
1511 /* This routine is called by the "run" program, when detailed
1512 execution information is required. Rather than executing a single
1513 instruction, and looping around externally... we just start
1514 simulating, returning TRUE when the simulator stops (for whatever
1515 reason). */
1516
1517 #if defined(TRACE)
1518 /* Ensure tracing is enabled, if available */
1519 if (tracefh != NULL)
1520 state |= simTRACE;
1521 #endif /* TRACE */
1522
1523 state &= ~(simSTOP | simSTEP); /* execute until event */
1524 state |= (simHALTEX | simHALTIN); /* treat interrupt event as exception */
1525 /* Start executing instructions from the current state (set
1526 explicitly by register updates, or by sim_create_inferior): */
1527 simulate();
1528
1529 return(1);
1530 }
1531
1532 /*---------------------------------------------------------------------------*/
1533 /*-- Private simulator support interface ------------------------------------*/
1534 /*---------------------------------------------------------------------------*/
1535
1536 /* Simple monitor interface (currently setup for the IDT and PMON monitors) */
1537 static void
1538 sim_monitor(reason)
1539 unsigned int reason;
1540 {
1541 /* The IDT monitor actually allows two instructions per vector
1542 slot. However, the simulator currently causes a trap on each
1543 individual instruction. We cheat, and lose the bottom bit. */
1544 reason >>= 1;
1545
1546 /* The following callback functions are available, however the
1547 monitor we are simulating does not make use of them: get_errno,
1548 isatty, lseek, rename, system, time and unlink */
1549 switch (reason) {
1550 case 6: /* int open(char *path,int flags) */
1551 {
1552 uword64 paddr;
1553 int cca;
1554 if (AddressTranslation(A0,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL))
1555 V0 = callback->open(callback,(char *)((int)paddr),(int)A1);
1556 else
1557 sim_error("Attempt to pass pointer that does not reference simulated memory");
1558 }
1559 break;
1560
1561 case 7: /* int read(int file,char *ptr,int len) */
1562 {
1563 uword64 paddr;
1564 int cca;
1565 if (AddressTranslation(A1,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL))
1566 V0 = callback->read(callback,(int)A0,(char *)((int)paddr),(int)A2);
1567 else
1568 sim_error("Attempt to pass pointer that does not reference simulated memory");
1569 }
1570 break;
1571
1572 case 8: /* int write(int file,char *ptr,int len) */
1573 {
1574 uword64 paddr;
1575 int cca;
1576 if (AddressTranslation(A1,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL))
1577 V0 = callback->write(callback,(int)A0,(const char *)((int)paddr),(int)A2);
1578 else
1579 sim_error("Attempt to pass pointer that does not reference simulated memory");
1580 }
1581 break;
1582
1583 case 10: /* int close(int file) */
1584 V0 = callback->close(callback,(int)A0);
1585 break;
1586
1587 case 11: /* char inbyte(void) */
1588 {
1589 char tmp;
1590 if (callback->read_stdin(callback,&tmp,sizeof(char)) != sizeof(char)) {
1591 sim_error("Invalid return from character read");
1592 V0 = (ut_reg)-1;
1593 }
1594 else
1595 V0 = (ut_reg)tmp;
1596 }
1597 break;
1598
1599 case 12: /* void outbyte(char chr) : write a byte to "stdout" */
1600 {
1601 char tmp = (char)(A0 & 0xFF);
1602 callback->write_stdout(callback,&tmp,sizeof(char));
1603 }
1604 break;
1605
1606 case 17: /* void _exit() */
1607 sim_warning("sim_monitor(17): _exit(int reason) to be coded");
1608 state |= (simSTOP | simEXIT); /* stop executing code */
1609 rcexit = (unsigned int)(A0 & 0xFFFFFFFF);
1610 break;
1611
1612 case 55: /* void get_mem_info(unsigned int *ptr) */
1613 /* in: A0 = pointer to three word memory location */
1614 /* out: [A0 + 0] = size */
1615 /* [A0 + 4] = instruction cache size */
1616 /* [A0 + 8] = data cache size */
1617 {
1618 uword64 vaddr = A0;
1619 uword64 paddr, value;
1620 int cca;
1621 int failed = 0;
1622
1623 /* NOTE: We use RAW memory writes here, but since we are not
1624 gathering statistics for the monitor calls we are simulating,
1625 it is not an issue. */
1626
1627 /* Memory size */
1628 if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isREAL)) {
1629 value = (uword64)membank_size;
1630 StoreMemory(cca,AccessLength_WORD,value,paddr,vaddr,isRAW);
1631 /* We re-do the address translations, in-case the block
1632 overlaps a memory boundary: */
1633 value = 0;
1634 vaddr += (AccessLength_WORD + 1);
1635 if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isREAL)) {
1636 StoreMemory(cca,AccessLength_WORD,value,paddr,vaddr,isRAW);
1637 vaddr += (AccessLength_WORD + 1);
1638 if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isREAL))
1639 StoreMemory(cca,AccessLength_WORD,value,paddr,vaddr,isRAW);
1640 else
1641 failed = -1;
1642 } else
1643 failed = -1;
1644 } else
1645 failed = -1;
1646
1647 if (failed)
1648 sim_error("Invalid pointer passed into monitor call");
1649 }
1650 break;
1651
1652 case 158 : /* PMON printf */
1653 /* in: A0 = pointer to format string */
1654 /* A1 = optional argument 1 */
1655 /* A2 = optional argument 2 */
1656 /* A3 = optional argument 3 */
1657 /* out: void */
1658 /* The following is based on the PMON printf source */
1659 {
1660 uword64 paddr;
1661 int cca;
1662 /* This isn't the quickest way, since we call the host print
1663 routine for every character almost. But it does avoid
1664 having to allocate and manage a temporary string buffer. */
1665 if (AddressTranslation(A0,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL)) {
1666 char *s = (char *)((int)paddr);
1667 ut_reg *ap = &A1; /* 1st argument */
1668 /* TODO: Include check that we only use three arguments (A1, A2 and A3) */
1669 for (; *s;) {
1670 if (*s == '%') {
1671 char tmp[40];
1672 enum {FMT_RJUST, FMT_LJUST, FMT_RJUST0, FMT_CENTER} fmt = FMT_RJUST;
1673 int width = 0, trunc = 0, haddot = 0, longlong = 0;
1674 int base = 10;
1675 s++;
1676 for (; *s; s++) {
1677 if (strchr ("dobxXulscefg%", *s))
1678 break;
1679 else if (*s == '-')
1680 fmt = FMT_LJUST;
1681 else if (*s == '0')
1682 fmt = FMT_RJUST0;
1683 else if (*s == '~')
1684 fmt = FMT_CENTER;
1685 else if (*s == '*') {
1686 if (haddot)
1687 trunc = (int)*ap++;
1688 else
1689 width = (int)*ap++;
1690 } else if (*s >= '1' && *s <= '9') {
1691 char *t;
1692 unsigned int n;
1693 for (t = s; isdigit (*s); s++);
1694 strncpy (tmp, t, s - t);
1695 tmp[s - t] = '\0';
1696 n = (unsigned int)strtol(tmp,NULL,10);
1697 if (haddot)
1698 trunc = n;
1699 else
1700 width = n;
1701 s--;
1702 } else if (*s == '.')
1703 haddot = 1;
1704 }
1705 if (*s == '%') {
1706 callback->printf_filtered(callback,"%%");
1707 } else if (*s == 's') {
1708 if ((int)*ap != 0) {
1709 if (AddressTranslation(*ap++,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL)) {
1710 char *p = (char *)((int)paddr);;
1711 callback->printf_filtered(callback,p);
1712 } else {
1713 ap++;
1714 sim_error("Attempt to pass pointer that does not reference simulated memory");
1715 }
1716 }
1717 else
1718 callback->printf_filtered(callback,"(null)");
1719 } else if (*s == 'c') {
1720 int n = (int)*ap++;
1721 callback->printf_filtered(callback,"%c",n);
1722 } else {
1723 if (*s == 'l') {
1724 if (*++s == 'l') {
1725 longlong = 1;
1726 ++s;
1727 }
1728 }
1729 if (strchr ("dobxXu", *s)) {
1730 word64 lv = (word64) *ap++;
1731 if (*s == 'b')
1732 callback->printf_filtered(callback,"<binary not supported>");
1733 else {
1734 sprintf(tmp,"%%%s%c",longlong ? "ll" : "",*s);
1735 if (longlong)
1736 callback->printf_filtered(callback,tmp,lv);
1737 else
1738 callback->printf_filtered(callback,tmp,(int)lv);
1739 }
1740 } else if (strchr ("eEfgG", *s)) {
1741 #ifdef _MSC_VER /* MSVC version 2.x can't convert from uword64 directly */
1742 double dbl = (double)((word64)*ap++);
1743 #else
1744 double dbl = (double)*ap++;
1745 #endif
1746 sprintf(tmp,"%%%d.%d%c",width,trunc,*s);
1747 callback->printf_filtered(callback,tmp,dbl);
1748 trunc = 0;
1749 }
1750 }
1751 s++;
1752 } else
1753 callback->printf_filtered(callback,"%c",*s++);
1754 }
1755 } else
1756 sim_error("Attempt to pass pointer that does not reference simulated memory");
1757 }
1758 break;
1759
1760 default:
1761 sim_warning("TODO: sim_monitor(%d) : PC = 0x%08X%08X",reason,WORD64HI(IPC),WORD64LO(IPC));
1762 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));
1763 break;
1764 }
1765 return;
1766 }
1767
1768 void
1769 #ifdef _MSC_VER
1770 sim_warning(char *fmt,...)
1771 #else
1772 sim_warning(fmt)
1773 char *fmt;
1774 #endif
1775 {
1776 va_list ap;
1777 va_start(ap,fmt);
1778 if (logfh != NULL) {
1779 #if 1
1780 fprintf(logfh,"SIM Warning: ");
1781 fprintf(logfh,fmt,ap);
1782 fprintf(logfh,"\n");
1783 #else /* we should provide a method of routing log messages to the simulator output stream */
1784 callback->printf_filtered(callback,"SIM Warning: ");
1785 callback->printf_filtered(callback,fmt,ap);
1786 #endif
1787 }
1788 va_end(ap);
1789 SignalException(SimulatorFault,"");
1790 return;
1791 }
1792
1793 void
1794 #ifdef _MSC_VER
1795 sim_error(char *fmt,...)
1796 #else
1797 sim_error(fmt)
1798 char *fmt;
1799 #endif
1800 {
1801 va_list ap;
1802 va_start(ap,fmt);
1803 callback->printf_filtered(callback,"SIM Error: ");
1804 callback->printf_filtered(callback,fmt,ap);
1805 va_end(ap);
1806 SignalException(SimulatorFault,"");
1807 return;
1808 }
1809
1810 static unsigned int
1811 power2(value)
1812 unsigned int value;
1813 {
1814 int loop,tmp;
1815
1816 /* Round *UP* to the nearest power-of-2 if not already one */
1817 if (value != (value & ~(value - 1))) {
1818 for (tmp = value, loop = 0; (tmp != 0); loop++)
1819 tmp >>= 1;
1820 value = (1 << loop);
1821 }
1822
1823 return(value);
1824 }
1825
1826 static long
1827 getnum(value)
1828 char *value;
1829 {
1830 long num;
1831 char *end;
1832
1833 num = strtol(value,&end,10);
1834 if (end == value)
1835 callback->printf_filtered(callback,"Warning: Invalid number \"%s\" ignored, using zero\n",value);
1836 else {
1837 if (*end && ((tolower(*end) == 'k') || (tolower(*end) == 'm'))) {
1838 if (tolower(*end) == 'k')
1839 num *= (1 << 10);
1840 else
1841 num *= (1 << 20);
1842 end++;
1843 }
1844 if (*end)
1845 callback->printf_filtered(callback,"Warning: Spurious characters \"%s\" at end of number ignored\n",end);
1846 }
1847
1848 return(num);
1849 }
1850
1851 /*-- trace support ----------------------------------------------------------*/
1852
1853 /* The TRACE support is provided (if required) in the memory accessing
1854 routines. Since we are also providing the architecture specific
1855 features, the architecture simulation code can also deal with
1856 notifying the TRACE world of cache flushes, etc. Similarly we do
1857 not need to provide profiling support in the simulator engine,
1858 since we can sample in the instruction fetch control loop. By
1859 defining the TRACE manifest, we add tracing as a run-time
1860 option. */
1861
1862 #if defined(TRACE)
1863 /* Tracing by default produces "din" format (as required by
1864 dineroIII). Each line of such a trace file *MUST* have a din label
1865 and address field. The rest of the line is ignored, so comments can
1866 be included if desired. The first field is the label which must be
1867 one of the following values:
1868
1869 0 read data
1870 1 write data
1871 2 instruction fetch
1872 3 escape record (treated as unknown access type)
1873 4 escape record (causes cache flush)
1874
1875 The address field is a 32bit (lower-case) hexadecimal address
1876 value. The address should *NOT* be preceded by "0x".
1877
1878 The size of the memory transfer is not important when dealing with
1879 cache lines (as long as no more than a cache line can be
1880 transferred in a single operation :-), however more information
1881 could be given following the dineroIII requirement to allow more
1882 complete memory and cache simulators to provide better
1883 results. i.e. the University of Pisa has a cache simulator that can
1884 also take bus size and speed as (variable) inputs to calculate
1885 complete system performance (a much more useful ability when trying
1886 to construct an end product, rather than a processor). They
1887 currently have an ARM version of their tool called ChARM. */
1888
1889
1890 static
1891 #ifdef _MSC_VER
1892 void dotrace(FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...)
1893 #else
1894 void dotrace(tracefh,type,address,width,comment)
1895 FILE *tracefh;
1896 int type;
1897 SIM_ADDR address;
1898 int width;
1899 char *comment;
1900 #endif
1901 {
1902 if (state & simTRACE) {
1903 va_list ap;
1904 fprintf(tracefh,"%d %08x%08x ; width %d ; ",
1905 type,(unsigned long)(address>>32),(unsigned long)(address&0xffffffff),width);
1906 va_start(ap,comment);
1907 fprintf(tracefh,comment,ap);
1908 va_end(ap);
1909 fprintf(tracefh,"\n");
1910 }
1911 /* NOTE: Since the "din" format will only accept 32bit addresses, and
1912 we may be generating 64bit ones, we should put the hi-32bits of the
1913 address into the comment field. */
1914
1915 /* TODO: Provide a buffer for the trace lines. We can then avoid
1916 performing writes until the buffer is filled, or the file is
1917 being closed. */
1918
1919 /* NOTE: We could consider adding a comment field to the "din" file
1920 produced using type 3 markers (unknown access). This would then
1921 allow information about the program that the "din" is for, and
1922 the MIPs world that was being simulated, to be placed into the
1923 trace file. */
1924
1925 return;
1926 }
1927 #endif /* TRACE */
1928
1929 /*---------------------------------------------------------------------------*/
1930 /*-- host<->target transfers ------------------------------------------------*/
1931 /*---------------------------------------------------------------------------*/
1932 /* The following routines allow conditionals to be avoided during the
1933 simulation, at the cost of increasing the image and source size. */
1934
1935 static unsigned int
1936 #ifdef _MSC_VER
1937 xfer_direct_word(unsigned char *memory)
1938 #else
1939 xfer_direct_word(memory)
1940 unsigned char *memory;
1941 #endif
1942 {
1943 return *((unsigned int *)memory);
1944 }
1945
1946 static uword64
1947 #ifdef _MSC_VER
1948 xfer_direct_long(unsigned char *memory)
1949 #else
1950 xfer_direct_long(memory)
1951 unsigned char *memory;
1952 #endif
1953 {
1954 return *((uword64 *)memory);
1955 }
1956
1957 static unsigned int
1958 #ifdef _MSC_VER
1959 swap_direct_word(unsigned int data)
1960 #else
1961 swap_direct_word(data)
1962 unsigned int data;
1963 #endif
1964 {
1965 return data;
1966 }
1967
1968 static uword64
1969 #ifdef _MSC_VER
1970 swap_direct_long(uword64 data)
1971 #else
1972 swap_direct_long(data)
1973 uword64 data;
1974 #endif
1975 {
1976 return data;
1977 }
1978
1979 static unsigned int
1980 #ifdef _MSC_VER
1981 xfer_big_word(unsigned char *memory)
1982 #else
1983 xfer_big_word(memory)
1984 unsigned char *memory;
1985 #endif
1986 {
1987 return ((memory[0] << 24) | (memory[1] << 16) | (memory[2] << 8) | memory[3]);
1988 }
1989
1990 static uword64
1991 #ifdef _MSC_VER
1992 xfer_big_long(unsigned char *memory)
1993 #else
1994 xfer_big_long(memory)
1995 unsigned char *memory;
1996 #endif
1997 {
1998 return (((uword64)memory[0] << 56) | ((uword64)memory[1] << 48)
1999 | ((uword64)memory[2] << 40) | ((uword64)memory[3] << 32)
2000 | ((uword64)memory[4] << 24) | ((uword64)memory[5] << 16)
2001 | ((uword64)memory[6] << 8) | ((uword64)memory[7]));
2002 }
2003
2004 static unsigned int
2005 #ifdef _MSC_VER
2006 xfer_little_word(unsigned char *memory)
2007 #else
2008 xfer_little_word(memory)
2009 unsigned char *memory;
2010 #endif
2011 {
2012 return ((memory[3] << 24) | (memory[2] << 16) | (memory[1] << 8) | memory[0]);
2013 }
2014
2015 static uword64
2016 #ifdef _MSC_VER
2017 xfer_little_long(unsigned char *memory)
2018 #else
2019 xfer_little_long(memory)
2020 unsigned char *memory;
2021 #endif
2022 {
2023 return (((uword64)memory[7] << 56) | ((uword64)memory[6] << 48)
2024 | ((uword64)memory[5] << 40) | ((uword64)memory[4] << 32)
2025 | ((uword64)memory[3] << 24) | ((uword64)memory[2] << 16)
2026 | ((uword64)memory[1] << 8) | (uword64)memory[0]);
2027 }
2028
2029 static unsigned int
2030 #ifdef _MSC_VER
2031 swap_word(unsigned int data)
2032 #else
2033 swap_word(data)
2034 unsigned int data;
2035 #endif
2036 {
2037 unsigned int result;
2038 result = data ^ ((data << 16) | (data >> 16));
2039 result &= ~0x00FF0000;
2040 data = (data << 24) | (data >> 8);
2041 return data ^ (result >> 8);
2042 }
2043
2044 static uword64
2045 #ifdef _MSC_VER
2046 swap_long(uword64 data)
2047 #else
2048 swap_long(data)
2049 uword64 data;
2050 #endif
2051 {
2052 unsigned int tmphi = WORD64HI(data);
2053 unsigned int tmplo = WORD64LO(data);
2054 tmphi = swap_word(tmphi);
2055 tmplo = swap_word(tmplo);
2056 /* Now swap the HI and LO parts */
2057 return SET64LO(tmphi) | SET64HI(tmplo);
2058 }
2059
2060 /*---------------------------------------------------------------------------*/
2061 /*-- simulator engine -------------------------------------------------------*/
2062 /*---------------------------------------------------------------------------*/
2063
2064 static void
2065 ColdReset()
2066 {
2067 /* RESET: Fixed PC address: */
2068 PC = (((uword64)0xFFFFFFFF<<32) | 0xBFC00000);
2069 /* The reset vector address is in the unmapped, uncached memory space. */
2070
2071 SR &= ~(status_SR | status_TS | status_RP);
2072 SR |= (status_ERL | status_BEV);
2073 /* VR4300 starts in Big-Endian mode */
2074 CONFIG &= ~(config_EP_mask << config_EP_shift);
2075 CONFIG |= ((config_EP_D << config_EP_shift) | config_BE);
2076 /* TODO: The VR4300 CONFIG register is not modelled fully at the moment */
2077
2078 #if defined(HASFPU) && (GPRLEN == (64))
2079 /* Cheat and allow access to the complete register set immediately: */
2080 SR |= status_FR; /* 64bit registers */
2081 #endif /* HASFPU and 64bit FP registers */
2082
2083 /* Ensure that any instructions with pending register updates are
2084 cleared: */
2085 {
2086 int loop;
2087 for (loop = 0; (loop < PSLOTS); loop++)
2088 pending_slot_reg[loop] = (LAST_EMBED_REGNUM + 1);
2089 pending_in = pending_out = pending_total = 0;
2090 }
2091
2092 #if defined(HASFPU)
2093 /* Initialise the FPU registers to the unknown state */
2094 {
2095 int rn;
2096 for (rn = 0; (rn < 32); rn++)
2097 fpr_state[rn] = fmt_uninterpreted;
2098 }
2099 #endif /* HASFPU */
2100
2101 /* In reality this check should be performed at various points
2102 within the simulation, since it is possible to change the
2103 endianness of user programs. However, we perform the check here
2104 to ensure that the start-of-day values agree: */
2105 state |= (BigEndianCPU ? simBE : 0);
2106 if ((target_byte_order == 1234) != !(state & simBE)) {
2107 fprintf(stderr,"ColdReset: GDB (%s) and simulator (%s) do not agree on target endianness\n",
2108 target_byte_order == 1234 ? "little" : "big",
2109 state & simBE ? "big" : "little");
2110 exit(1);
2111 }
2112
2113 if (!(state & simHOSTBE) == !(state & simBE)) {
2114 host_read_word = xfer_direct_word;
2115 host_read_long = xfer_direct_long;
2116 host_swap_word = swap_direct_word;
2117 host_swap_long = swap_direct_long;
2118 } else if (state & simHOSTBE) {
2119 host_read_word = xfer_little_word;
2120 host_read_long = xfer_little_long;
2121 host_swap_word = swap_word;
2122 host_swap_long = swap_long;
2123 } else { /* HOST little-endian */
2124 host_read_word = xfer_big_word;
2125 host_read_long = xfer_big_long;
2126 host_swap_word = swap_word;
2127 host_swap_long = swap_long;
2128 }
2129
2130 return;
2131 }
2132
2133 /* Description from page A-22 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2134 /* Translate a virtual address to a physical address and cache
2135 coherence algorithm describing the mechanism used to resolve the
2136 memory reference. Given the virtual address vAddr, and whether the
2137 reference is to Instructions ot Data (IorD), find the corresponding
2138 physical address (pAddr) and the cache coherence algorithm (CCA)
2139 used to resolve the reference. If the virtual address is in one of
2140 the unmapped address spaces the physical address and the CCA are
2141 determined directly by the virtual address. If the virtual address
2142 is in one of the mapped address spaces then the TLB is used to
2143 determine the physical address and access type; if the required
2144 translation is not present in the TLB or the desired access is not
2145 permitted the function fails and an exception is taken.
2146
2147 NOTE: This function is extended to return an exception state. This,
2148 along with the exception generation is used to notify whether a
2149 valid address translation occured */
2150
2151 static int
2152 AddressTranslation(vAddr,IorD,LorS,pAddr,CCA,host,raw)
2153 uword64 vAddr;
2154 int IorD;
2155 int LorS;
2156 uword64 *pAddr;
2157 int *CCA;
2158 int host;
2159 int raw;
2160 {
2161 int res = -1; /* TRUE : Assume good return */
2162
2163 #ifdef DEBUG
2164 callback->printf_filtered(callback,"AddressTranslation(0x%08X%08X,%s,%s,...);\n",WORD64HI(vAddr),WORD64LO(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "iSTORE" : "isLOAD"));
2165 #endif
2166
2167 /* Check that the address is valid for this memory model */
2168
2169 /* For a simple (flat) memory model, we simply pass virtual
2170 addressess through (mostly) unchanged. */
2171 vAddr &= 0xFFFFFFFF;
2172
2173 /* Treat the kernel memory spaces identically for the moment: */
2174 if ((membank_base == K1BASE) && (vAddr >= K0BASE) && (vAddr < (K0BASE + K0SIZE)))
2175 vAddr += (K1BASE - K0BASE);
2176
2177 /* Also assume that the K1BASE memory wraps. This is required to
2178 allow the PMON run-time __sizemem() routine to function (without
2179 having to provide exception simulation). NOTE: A kludge to work
2180 around the fact that the monitor memory is currently held in the
2181 K1BASE space. */
2182 if (((vAddr < monitor_base) || (vAddr >= (monitor_base + monitor_size))) && (vAddr >= K1BASE && vAddr < (K1BASE + K1SIZE)))
2183 vAddr = (K1BASE | (vAddr & (membank_size - 1)));
2184
2185 *pAddr = vAddr; /* default for isTARGET */
2186 *CCA = Uncached; /* not used for isHOST */
2187
2188 /* NOTE: This is a duplicate of the code that appears in the
2189 LoadMemory and StoreMemory functions. They should be merged into
2190 a single function (that can be in-lined if required). */
2191 if ((vAddr >= membank_base) && (vAddr < (membank_base + membank_size))) {
2192 if (host)
2193 *pAddr = (int)&membank[((unsigned int)(vAddr - membank_base) & (membank_size - 1))];
2194 } else if ((vAddr >= monitor_base) && (vAddr < (monitor_base + monitor_size))) {
2195 if (host)
2196 *pAddr = (int)&monitor[((unsigned int)(vAddr - monitor_base) & (monitor_size - 1))];
2197 } else {
2198 #if 1 /* def DEBUG */
2199 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));
2200 #endif /* DEBUG */
2201 res = 0; /* AddressTranslation has failed */
2202 *pAddr = (SIM_ADDR)-1;
2203 if (!raw) /* only generate exceptions on real memory transfers */
2204 SignalException((LorS == isSTORE) ? AddressStore : AddressLoad);
2205 else
2206 sim_warning("AddressTranslation for %s %s from 0x%08X%08X failed",(IorD ? "data" : "instruction"),(LorS ? "store" : "load"),WORD64HI(vAddr),WORD64LO(vAddr));
2207 }
2208
2209 return(res);
2210 }
2211
2212 /* Description from page A-23 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2213 /* Prefetch data from memory. Prefetch is an advisory instruction for
2214 which an implementation specific action is taken. The action taken
2215 may increase performance, but must not change the meaning of the
2216 program, or alter architecturally-visible state. */
2217 static void
2218 Prefetch(CCA,pAddr,vAddr,DATA,hint)
2219 int CCA;
2220 uword64 pAddr;
2221 uword64 vAddr;
2222 int DATA;
2223 int hint;
2224 {
2225 #ifdef DEBUG
2226 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);
2227 #endif /* DEBUG */
2228
2229 /* For our simple memory model we do nothing */
2230 return;
2231 }
2232
2233 /* Description from page A-22 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2234 /* Load a value from memory. Use the cache and main memory as
2235 specified in the Cache Coherence Algorithm (CCA) and the sort of
2236 access (IorD) to find the contents of AccessLength memory bytes
2237 starting at physical location pAddr. The data is returned in the
2238 fixed width naturally-aligned memory element (MemElem). The
2239 low-order two (or three) bits of the address and the AccessLength
2240 indicate which of the bytes within MemElem needs to be given to the
2241 processor. If the memory access type of the reference is uncached
2242 then only the referenced bytes are read from memory and valid
2243 within the memory element. If the access type is cached, and the
2244 data is not present in cache, an implementation specific size and
2245 alignment block of memory is read and loaded into the cache to
2246 satisfy a load reference. At a minimum, the block is the entire
2247 memory element. */
2248 static uword64
2249 LoadMemory(CCA,AccessLength,pAddr,vAddr,IorD,raw)
2250 int CCA;
2251 int AccessLength;
2252 uword64 pAddr;
2253 uword64 vAddr;
2254 int IorD;
2255 int raw;
2256 {
2257 uword64 value;
2258
2259 #ifdef DEBUG
2260 if (membank == NULL)
2261 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"));
2262 #endif /* DEBUG */
2263
2264 #if defined(WARN_MEM)
2265 if (CCA != uncached)
2266 sim_warning("LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)",CCA);
2267
2268 if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK) {
2269 /* In reality this should be a Bus Error */
2270 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));
2271 }
2272 #endif /* WARN_MEM */
2273
2274 /* Decide which physical memory locations are being dealt with. At
2275 this point we should be able to split the pAddr bits into the
2276 relevant address map being simulated. If the "raw" variable is
2277 set, the memory read being performed should *NOT* update any I/O
2278 state or affect the CPU state. This also includes avoiding
2279 affecting statistics gathering. */
2280
2281 /* If instruction fetch then we need to check that the two lo-order
2282 bits are zero, otherwise raise a InstructionFetch exception: */
2283 if ((IorD == isINSTRUCTION) && ((pAddr & 0x3) != 0))
2284 SignalException(InstructionFetch);
2285 else {
2286 unsigned int index;
2287 unsigned char *mem = NULL;
2288
2289 #if defined(TRACE)
2290 if (!raw)
2291 dotrace(tracefh,((IorD == isDATA) ? 0 : 2),(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"load%s",((IorD == isDATA) ? "" : " instruction"));
2292 #endif /* TRACE */
2293
2294 /* NOTE: Quicker methods of decoding the address space can be used
2295 when a real memory map is being simulated (i.e. using hi-order
2296 address bits to select device). */
2297 if ((pAddr >= membank_base) && (pAddr < (membank_base + membank_size))) {
2298 index = ((unsigned int)(pAddr - membank_base) & (membank_size - 1));
2299 mem = membank;
2300 } else if ((pAddr >= monitor_base) && (pAddr < (monitor_base + monitor_size))) {
2301 index = ((unsigned int)(pAddr - monitor_base) & (monitor_size - 1));
2302 mem = monitor;
2303 }
2304 if (mem == NULL)
2305 sim_error("Simulator memory not found for physical address 0x%08X%08X\n",WORD64HI(pAddr),WORD64LO(pAddr));
2306 else {
2307 /* If we obtained the endianness of the host, and it is the same
2308 as the target memory system we can optimise the memory
2309 accesses. However, without that information we must perform
2310 slow transfer, and hope that the compiler optimisation will
2311 merge successive loads. */
2312 value = 0; /* no data loaded yet */
2313
2314 /* In reality we should always be loading a doubleword value (or
2315 word value in 32bit memory worlds). The external code then
2316 extracts the required bytes. However, to keep performance
2317 high we only load the required bytes into the relevant
2318 slots. */
2319 if (BigEndianMem)
2320 switch (AccessLength) { /* big-endian memory */
2321 case AccessLength_DOUBLEWORD :
2322 value |= ((uword64)mem[index++] << 56);
2323 case AccessLength_SEPTIBYTE :
2324 value |= ((uword64)mem[index++] << 48);
2325 case AccessLength_SEXTIBYTE :
2326 value |= ((uword64)mem[index++] << 40);
2327 case AccessLength_QUINTIBYTE :
2328 value |= ((uword64)mem[index++] << 32);
2329 case AccessLength_WORD :
2330 value |= ((unsigned int)mem[index++] << 24);
2331 case AccessLength_TRIPLEBYTE :
2332 value |= ((unsigned int)mem[index++] << 16);
2333 case AccessLength_HALFWORD :
2334 value |= ((unsigned int)mem[index++] << 8);
2335 case AccessLength_BYTE :
2336 value |= mem[index];
2337 break;
2338 }
2339 else {
2340 index += (AccessLength + 1);
2341 switch (AccessLength) { /* little-endian memory */
2342 case AccessLength_DOUBLEWORD :
2343 value |= ((uword64)mem[--index] << 56);
2344 case AccessLength_SEPTIBYTE :
2345 value |= ((uword64)mem[--index] << 48);
2346 case AccessLength_SEXTIBYTE :
2347 value |= ((uword64)mem[--index] << 40);
2348 case AccessLength_QUINTIBYTE :
2349 value |= ((uword64)mem[--index] << 32);
2350 case AccessLength_WORD :
2351 value |= ((uword64)mem[--index] << 24);
2352 case AccessLength_TRIPLEBYTE :
2353 value |= ((uword64)mem[--index] << 16);
2354 case AccessLength_HALFWORD :
2355 value |= ((uword64)mem[--index] << 8);
2356 case AccessLength_BYTE :
2357 value |= ((uword64)mem[--index] << 0);
2358 break;
2359 }
2360 }
2361
2362 #ifdef DEBUG
2363 printf("DBG: LoadMemory() : (offset %d) : value = 0x%08X%08X\n",(int)(pAddr & LOADDRMASK),WORD64HI(value),WORD64LO(value));
2364 #endif /* DEBUG */
2365
2366 /* TODO: We could try and avoid the shifts when dealing with raw
2367 memory accesses. This would mean updating the LoadMemory and
2368 StoreMemory routines to avoid shifting the data before
2369 returning or using it. */
2370 if (!raw) { /* do nothing for raw accessess */
2371 if (BigEndianMem)
2372 value <<= (((7 - (pAddr & LOADDRMASK)) - AccessLength) * 8);
2373 else /* little-endian only needs to be shifted up to the correct byte offset */
2374 value <<= ((pAddr & LOADDRMASK) * 8);
2375 }
2376
2377 #ifdef DEBUG
2378 printf("DBG: LoadMemory() : shifted value = 0x%08X%08X\n",WORD64HI(value),WORD64LO(value));
2379 #endif /* DEBUG */
2380 }
2381 }
2382
2383 return(value);
2384 }
2385
2386 /* Description from page A-23 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2387 /* Store a value to memory. The specified data is stored into the
2388 physical location pAddr using the memory hierarchy (data caches and
2389 main memory) as specified by the Cache Coherence Algorithm
2390 (CCA). The MemElem contains the data for an aligned, fixed-width
2391 memory element (word for 32-bit processors, doubleword for 64-bit
2392 processors), though only the bytes that will actually be stored to
2393 memory need to be valid. The low-order two (or three) bits of pAddr
2394 and the AccessLength field indicates which of the bytes within the
2395 MemElem data should actually be stored; only these bytes in memory
2396 will be changed. */
2397 static void
2398 StoreMemory(CCA,AccessLength,MemElem,pAddr,vAddr,raw)
2399 int CCA;
2400 int AccessLength;
2401 uword64 MemElem;
2402 uword64 pAddr;
2403 uword64 vAddr;
2404 int raw;
2405 {
2406 #ifdef DEBUG
2407 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"));
2408 #endif /* DEBUG */
2409
2410 #if defined(WARN_MEM)
2411 if (CCA != uncached)
2412 sim_warning("StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)",CCA);
2413
2414 if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
2415 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));
2416 #endif /* WARN_MEM */
2417
2418 #if defined(TRACE)
2419 if (!raw)
2420 dotrace(tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store");
2421 #endif /* TRACE */
2422
2423 /* See the comments in the LoadMemory routine about optimising
2424 memory accesses. Also if we wanted to make the simulator smaller,
2425 we could merge a lot of this code with the LoadMemory
2426 routine. However, this would slow the simulator down with
2427 run-time conditionals. */
2428 {
2429 unsigned int index;
2430 unsigned char *mem = NULL;
2431
2432 if ((pAddr >= membank_base) && (pAddr < (membank_base + membank_size))) {
2433 index = ((unsigned int)(pAddr - membank_base) & (membank_size - 1));
2434 mem = membank;
2435 } else if ((pAddr >= monitor_base) && (pAddr < (monitor_base + monitor_size))) {
2436 index = ((unsigned int)(pAddr - monitor_base) & (monitor_size - 1));
2437 mem = monitor;
2438 }
2439
2440 if (mem == NULL)
2441 sim_error("Simulator memory not found for physical address 0x%08X%08X\n",WORD64HI(pAddr),WORD64LO(pAddr));
2442 else {
2443 int shift = 0;
2444
2445 #ifdef DEBUG
2446 printf("DBG: StoreMemory: offset = %d MemElem = 0x%08X%08X\n",(unsigned int)(pAddr & LOADDRMASK),WORD64HI(MemElem),WORD64LO(MemElem));
2447 #endif /* DEBUG */
2448
2449 if (BigEndianMem) {
2450 if (raw)
2451 shift = ((7 - AccessLength) * 8);
2452 else /* real memory access */
2453 shift = ((pAddr & LOADDRMASK) * 8);
2454 MemElem <<= shift;
2455 } else {
2456 /* no need to shift raw little-endian data */
2457 if (!raw)
2458 MemElem >>= ((pAddr & LOADDRMASK) * 8);
2459 }
2460
2461 #ifdef DEBUG
2462 printf("DBG: StoreMemory: shift = %d MemElem = 0x%08X%08X\n",shift,WORD64HI(MemElem),WORD64LO(MemElem));
2463 #endif /* DEBUG */
2464
2465 if (BigEndianMem) {
2466 switch (AccessLength) { /* big-endian memory */
2467 case AccessLength_DOUBLEWORD :
2468 mem[index++] = (unsigned char)(MemElem >> 56);
2469 MemElem <<= 8;
2470 case AccessLength_SEPTIBYTE :
2471 mem[index++] = (unsigned char)(MemElem >> 56);
2472 MemElem <<= 8;
2473 case AccessLength_SEXTIBYTE :
2474 mem[index++] = (unsigned char)(MemElem >> 56);
2475 MemElem <<= 8;
2476 case AccessLength_QUINTIBYTE :
2477 mem[index++] = (unsigned char)(MemElem >> 56);
2478 MemElem <<= 8;
2479 case AccessLength_WORD :
2480 mem[index++] = (unsigned char)(MemElem >> 56);
2481 MemElem <<= 8;
2482 case AccessLength_TRIPLEBYTE :
2483 mem[index++] = (unsigned char)(MemElem >> 56);
2484 MemElem <<= 8;
2485 case AccessLength_HALFWORD :
2486 mem[index++] = (unsigned char)(MemElem >> 56);
2487 MemElem <<= 8;
2488 case AccessLength_BYTE :
2489 mem[index++] = (unsigned char)(MemElem >> 56);
2490 break;
2491 }
2492 } else {
2493 index += (AccessLength + 1);
2494 switch (AccessLength) { /* little-endian memory */
2495 case AccessLength_DOUBLEWORD :
2496 mem[--index] = (unsigned char)(MemElem >> 56);
2497 case AccessLength_SEPTIBYTE :
2498 mem[--index] = (unsigned char)(MemElem >> 48);
2499 case AccessLength_SEXTIBYTE :
2500 mem[--index] = (unsigned char)(MemElem >> 40);
2501 case AccessLength_QUINTIBYTE :
2502 mem[--index] = (unsigned char)(MemElem >> 32);
2503 case AccessLength_WORD :
2504 mem[--index] = (unsigned char)(MemElem >> 24);
2505 case AccessLength_TRIPLEBYTE :
2506 mem[--index] = (unsigned char)(MemElem >> 16);
2507 case AccessLength_HALFWORD :
2508 mem[--index] = (unsigned char)(MemElem >> 8);
2509 case AccessLength_BYTE :
2510 mem[--index] = (unsigned char)(MemElem >> 0);
2511 break;
2512 }
2513 }
2514 }
2515 }
2516
2517 return;
2518 }
2519
2520 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2521 /* Order loads and stores to synchronise shared memory. Perform the
2522 action necessary to make the effects of groups of synchronizable
2523 loads and stores indicated by stype occur in the same order for all
2524 processors. */
2525 static void
2526 SyncOperation(stype)
2527 int stype;
2528 {
2529 #ifdef DEBUG
2530 callback->printf_filtered(callback,"SyncOperation(%d) : TODO\n",stype);
2531 #endif /* DEBUG */
2532 return;
2533 }
2534
2535 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2536 /* Signal an exception condition. This will result in an exception
2537 that aborts the instruction. The instruction operation pseudocode
2538 will never see a return from this function call. */
2539 static void
2540 #ifdef _MSC_VER
2541 SignalException (int exception,...)
2542 #else
2543 SignalException(exception)
2544 int exception;
2545 #endif
2546 {
2547 /* Ensure that any active atomic read/modify/write operation will fail: */
2548 LLBIT = 0;
2549
2550 switch (exception) {
2551 /* TODO: For testing purposes I have been ignoring TRAPs. In
2552 reality we should either simulate them, or allow the user to
2553 ignore them at run-time. */
2554 case Trap :
2555 sim_warning("Ignoring instruction TRAP (PC 0x%08X%08X)",WORD64HI(IPC),WORD64LO(IPC));
2556 break;
2557
2558 case ReservedInstruction :
2559 {
2560 va_list ap;
2561 unsigned int instruction;
2562 va_start(ap,exception);
2563 instruction = va_arg(ap,unsigned int);
2564 va_end(ap);
2565 /* Provide simple monitor support using ReservedInstruction
2566 exceptions. The following code simulates the fixed vector
2567 entry points into the IDT monitor by causing a simulator
2568 trap, performing the monitor operation, and returning to
2569 the address held in the $ra register (standard PCS return
2570 address). This means we only need to pre-load the vector
2571 space with suitable instruction values. For systems were
2572 actual trap instructions are used, we would not need to
2573 perform this magic. */
2574 if ((instruction & ~RSVD_INSTRUCTION_AMASK) == RSVD_INSTRUCTION) {
2575 sim_monitor(instruction & RSVD_INSTRUCTION_AMASK);
2576 PC = RA; /* simulate the return from the vector entry */
2577 /* NOTE: This assumes that a branch-and-link style
2578 instruction was used to enter the vector (which is the
2579 case with the current IDT monitor). */
2580 break; /* out of the switch statement */
2581 } /* else fall through to normal exception processing */
2582 sim_warning("ReservedInstruction 0x%08X at IPC = 0x%08X%08X",instruction,WORD64HI(IPC),WORD64LO(IPC));
2583 }
2584
2585 default:
2586 #ifdef DEBUG
2587 if (exception != BreakPoint)
2588 callback->printf_filtered(callback,"DBG: SignalException(%d) IPC = 0x%08X%08X\n",exception,WORD64HI(IPC),WORD64LO(IPC));
2589 #endif /* DEBUG */
2590 /* Store exception code into current exception id variable (used
2591 by exit code): */
2592
2593 /* TODO: If not simulating exceptions then stop the simulator
2594 execution. At the moment we always stop the simulation. */
2595 state |= (simSTOP | simEXCEPTION);
2596
2597 /* Keep a copy of the current A0 in-case this is the program exit
2598 breakpoint: */
2599 if (exception == BreakPoint) {
2600 va_list ap;
2601 unsigned int instruction;
2602 va_start(ap,exception);
2603 instruction = va_arg(ap,unsigned int);
2604 va_end(ap);
2605 /* Check for our special terminating BREAK: */
2606 if ((instruction & 0x03FFFFC0) == 0x03ff0000) {
2607 rcexit = (unsigned int)(A0 & 0xFFFFFFFF);
2608 state &= ~simEXCEPTION;
2609 state |= simEXIT;
2610 }
2611 }
2612
2613 /* Store exception code into current exception id variable (used
2614 by exit code): */
2615 CAUSE = (exception << 2);
2616 if (state & simDELAYSLOT) {
2617 CAUSE |= cause_BD;
2618 EPC = (IPC - 4); /* reference the branch instruction */
2619 } else
2620 EPC = IPC;
2621 /* The following is so that the simulator will continue from the
2622 exception address on breakpoint operations. */
2623 PC = EPC;
2624 break;
2625
2626 case SimulatorFault:
2627 {
2628 va_list ap;
2629 char *msg;
2630 va_start(ap,exception);
2631 msg = va_arg(ap,char *);
2632 fprintf(stderr,"FATAL: Simulator error \"%s\"\n",msg);
2633 va_end(ap);
2634 }
2635 exit(1);
2636 }
2637
2638 return;
2639 }
2640
2641 #if defined(WARN_RESULT)
2642 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2643 /* This function indicates that the result of the operation is
2644 undefined. However, this should not affect the instruction
2645 stream. All that is meant to happen is that the destination
2646 register is set to an undefined result. To keep the simulator
2647 simple, we just don't bother updating the destination register, so
2648 the overall result will be undefined. If desired we can stop the
2649 simulator by raising a pseudo-exception. */
2650 static void
2651 UndefinedResult()
2652 {
2653 sim_warning("UndefinedResult: IPC = 0x%08X%08X",WORD64HI(IPC),WORD64LO(IPC));
2654 #if 0 /* Disabled for the moment, since it actually happens a lot at the moment. */
2655 state |= simSTOP;
2656 #endif
2657 return;
2658 }
2659 #endif /* WARN_RESULT */
2660
2661 static void
2662 CacheOp(op,pAddr,vAddr,instruction)
2663 int op;
2664 uword64 pAddr;
2665 uword64 vAddr;
2666 unsigned int instruction;
2667 {
2668 #if 1 /* stop warning message being displayed (we should really just remove the code) */
2669 static int icache_warning = 1;
2670 static int dcache_warning = 1;
2671 #else
2672 static int icache_warning = 0;
2673 static int dcache_warning = 0;
2674 #endif
2675
2676 /* If CP0 is not useable (User or Supervisor mode) and the CP0
2677 enable bit in the Status Register is clear - a coprocessor
2678 unusable exception is taken. */
2679 #if 0
2680 callback->printf_filtered(callback,"TODO: Cache availability checking (PC = 0x%08X%08X)\n",WORD64HI(IPC),WORD64LO(IPC));
2681 #endif
2682
2683 switch (op & 0x3) {
2684 case 0: /* instruction cache */
2685 switch (op >> 2) {
2686 case 0: /* Index Invalidate */
2687 case 1: /* Index Load Tag */
2688 case 2: /* Index Store Tag */
2689 case 4: /* Hit Invalidate */
2690 case 5: /* Fill */
2691 case 6: /* Hit Writeback */
2692 if (!icache_warning)
2693 {
2694 sim_warning("Instruction CACHE operation %d to be coded",(op >> 2));
2695 icache_warning = 1;
2696 }
2697 break;
2698
2699 default:
2700 SignalException(ReservedInstruction,instruction);
2701 break;
2702 }
2703 break;
2704
2705 case 1: /* data cache */
2706 switch (op >> 2) {
2707 case 0: /* Index Writeback Invalidate */
2708 case 1: /* Index Load Tag */
2709 case 2: /* Index Store Tag */
2710 case 3: /* Create Dirty */
2711 case 4: /* Hit Invalidate */
2712 case 5: /* Hit Writeback Invalidate */
2713 case 6: /* Hit Writeback */
2714 if (!dcache_warning)
2715 {
2716 sim_warning("Data CACHE operation %d to be coded",(op >> 2));
2717 dcache_warning = 1;
2718 }
2719 break;
2720
2721 default:
2722 SignalException(ReservedInstruction,instruction);
2723 break;
2724 }
2725 break;
2726
2727 default: /* unrecognised cache ID */
2728 SignalException(ReservedInstruction,instruction);
2729 break;
2730 }
2731
2732 return;
2733 }
2734
2735 /*-- FPU support routines ---------------------------------------------------*/
2736
2737 #if defined(HASFPU) /* Only needed when building FPU aware simulators */
2738
2739 #if 1
2740 #define SizeFGR() (GPRLEN)
2741 #else
2742 /* They depend on the CPU being simulated */
2743 #define SizeFGR() ((PROCESSOR_64BIT && ((SR & status_FR) == 1)) ? 64 : 32)
2744 #endif
2745
2746 /* Numbers are held in normalized form. The SINGLE and DOUBLE binary
2747 formats conform to ANSI/IEEE Std 754-1985. */
2748 /* SINGLE precision floating:
2749 * seeeeeeeefffffffffffffffffffffff
2750 * s = 1bit = sign
2751 * e = 8bits = exponent
2752 * f = 23bits = fraction
2753 */
2754 /* SINGLE precision fixed:
2755 * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
2756 * s = 1bit = sign
2757 * i = 31bits = integer
2758 */
2759 /* DOUBLE precision floating:
2760 * seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
2761 * s = 1bit = sign
2762 * e = 11bits = exponent
2763 * f = 52bits = fraction
2764 */
2765 /* DOUBLE precision fixed:
2766 * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
2767 * s = 1bit = sign
2768 * i = 63bits = integer
2769 */
2770
2771 /* Extract sign-bit: */
2772 #define FP_S_s(v) (((v) & ((unsigned)1 << 31)) ? 1 : 0)
2773 #define FP_D_s(v) (((v) & ((uword64)1 << 63)) ? 1 : 0)
2774 /* Extract biased exponent: */
2775 #define FP_S_be(v) (((v) >> 23) & 0xFF)
2776 #define FP_D_be(v) (((v) >> 52) & 0x7FF)
2777 /* Extract unbiased Exponent: */
2778 #define FP_S_e(v) (FP_S_be(v) - 0x7F)
2779 #define FP_D_e(v) (FP_D_be(v) - 0x3FF)
2780 /* Extract complete fraction field: */
2781 #define FP_S_f(v) ((v) & ~((unsigned)0x1FF << 23))
2782 #define FP_D_f(v) ((v) & ~((uword64)0xFFF << 52))
2783 /* Extract numbered fraction bit: */
2784 #define FP_S_fb(b,v) (((v) & (1 << (23 - (b)))) ? 1 : 0)
2785 #define FP_D_fb(b,v) (((v) & (1 << (52 - (b)))) ? 1 : 0)
2786
2787 /* Explicit QNaN values used when value required: */
2788 #define FPQNaN_SINGLE (0x7FBFFFFF)
2789 #define FPQNaN_WORD (0x7FFFFFFF)
2790 #define FPQNaN_DOUBLE (((uword64)0x7FF7FFFF << 32) | 0xFFFFFFFF)
2791 #define FPQNaN_LONG (((uword64)0x7FFFFFFF << 32) | 0xFFFFFFFF)
2792
2793 /* Explicit Infinity values used when required: */
2794 #define FPINF_SINGLE (0x7F800000)
2795 #define FPINF_DOUBLE (((uword64)0x7FF00000 << 32) | 0x00000000)
2796
2797 #if 1 /* def DEBUG */
2798 #define RMMODE(v) (((v) == FP_RM_NEAREST) ? "Round" : (((v) == FP_RM_TOZERO) ? "Trunc" : (((v) == FP_RM_TOPINF) ? "Ceil" : "Floor")))
2799 #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>"))))))
2800 #endif /* DEBUG */
2801
2802 static uword64
2803 ValueFPR(fpr,fmt)
2804 int fpr;
2805 FP_formats fmt;
2806 {
2807 uword64 value;
2808 int err = 0;
2809
2810 /* Treat unused register values, as fixed-point 64bit values: */
2811 if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown))
2812 #if 1
2813 /* If request to read data as "uninterpreted", then use the current
2814 encoding: */
2815 fmt = fpr_state[fpr];
2816 #else
2817 fmt = fmt_long;
2818 #endif
2819
2820 /* For values not yet accessed, set to the desired format: */
2821 if (fpr_state[fpr] == fmt_uninterpreted) {
2822 fpr_state[fpr] = fmt;
2823 #ifdef DEBUG
2824 printf("DBG: Register %d was fmt_uninterpreted. Now %s\n",fpr,DOFMT(fmt));
2825 #endif /* DEBUG */
2826 }
2827 if (fmt != fpr_state[fpr]) {
2828 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));
2829 fpr_state[fpr] = fmt_unknown;
2830 }
2831
2832 if (fpr_state[fpr] == fmt_unknown) {
2833 /* Set QNaN value: */
2834 switch (fmt) {
2835 case fmt_single:
2836 value = FPQNaN_SINGLE;
2837 break;
2838
2839 case fmt_double:
2840 value = FPQNaN_DOUBLE;
2841 break;
2842
2843 case fmt_word:
2844 value = FPQNaN_WORD;
2845 break;
2846
2847 case fmt_long:
2848 value = FPQNaN_LONG;
2849 break;
2850
2851 default:
2852 err = -1;
2853 break;
2854 }
2855 } else if (SizeFGR() == 64) {
2856 switch (fmt) {
2857 case fmt_single:
2858 case fmt_word:
2859 value = (FGR[fpr] & 0xFFFFFFFF);
2860 break;
2861
2862 case fmt_uninterpreted:
2863 case fmt_double:
2864 case fmt_long:
2865 value = FGR[fpr];
2866 break;
2867
2868 default :
2869 err = -1;
2870 break;
2871 }
2872 } else if ((fpr & 1) == 0) { /* even registers only */
2873 switch (fmt) {
2874 case fmt_single:
2875 case fmt_word:
2876 value = (FGR[fpr] & 0xFFFFFFFF);
2877 break;
2878
2879 case fmt_uninterpreted:
2880 case fmt_double:
2881 case fmt_long:
2882 value = ((((uword64)FGR[fpr+1]) << 32) | (FGR[fpr] & 0xFFFFFFFF));
2883 break;
2884
2885 default :
2886 err = -1;
2887 break;
2888 }
2889 }
2890
2891 if (err)
2892 SignalException(SimulatorFault,"Unrecognised FP format in ValueFPR()");
2893
2894 #ifdef DEBUG
2895 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());
2896 #endif /* DEBUG */
2897
2898 return(value);
2899 }
2900
2901 static void
2902 StoreFPR(fpr,fmt,value)
2903 int fpr;
2904 FP_formats fmt;
2905 uword64 value;
2906 {
2907 int err = 0;
2908
2909 #ifdef DEBUG
2910 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());
2911 #endif /* DEBUG */
2912
2913 if (SizeFGR() == 64) {
2914 switch (fmt) {
2915 case fmt_single :
2916 case fmt_word :
2917 FGR[fpr] = (((uword64)0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
2918 fpr_state[fpr] = fmt;
2919 break;
2920
2921 case fmt_uninterpreted:
2922 case fmt_double :
2923 case fmt_long :
2924 FGR[fpr] = value;
2925 fpr_state[fpr] = fmt;
2926 break;
2927
2928 default :
2929 fpr_state[fpr] = fmt_unknown;
2930 err = -1;
2931 break;
2932 }
2933 } else if ((fpr & 1) == 0) { /* even register number only */
2934 switch (fmt) {
2935 case fmt_single :
2936 case fmt_word :
2937 FGR[fpr+1] = 0xDEADC0DE;
2938 FGR[fpr] = (value & 0xFFFFFFFF);
2939 fpr_state[fpr + 1] = fmt;
2940 fpr_state[fpr] = fmt;
2941 break;
2942
2943 case fmt_uninterpreted:
2944 case fmt_double :
2945 case fmt_long :
2946 FGR[fpr+1] = (value >> 32);
2947 FGR[fpr] = (value & 0xFFFFFFFF);
2948 fpr_state[fpr + 1] = fmt;
2949 fpr_state[fpr] = fmt;
2950 break;
2951
2952 default :
2953 fpr_state[fpr] = fmt_unknown;
2954 err = -1;
2955 break;
2956 }
2957 }
2958 #if defined(WARN_RESULT)
2959 else
2960 UndefinedResult();
2961 #endif /* WARN_RESULT */
2962
2963 if (err)
2964 SignalException(SimulatorFault,"Unrecognised FP format in StoreFPR()");
2965
2966 #ifdef DEBUG
2967 printf("DBG: StoreFPR: fpr[%d] = 0x%08X%08X (format %s)\n",fpr,WORD64HI(FGR[fpr]),WORD64LO(FGR[fpr]),DOFMT(fmt));
2968 #endif /* DEBUG */
2969
2970 return;
2971 }
2972
2973 static int
2974 NaN(op,fmt)
2975 uword64 op;
2976 FP_formats fmt;
2977 {
2978 int boolean = 0;
2979
2980 /* Check if (((E - bias) == (E_max + 1)) && (fraction != 0)). We
2981 know that the exponent field is biased... we we cheat and avoid
2982 removing the bias value. */
2983 switch (fmt) {
2984 case fmt_single:
2985 boolean = ((FP_S_be(op) == 0xFF) && (FP_S_f(op) != 0));
2986 /* We could use "FP_S_fb(1,op)" to ascertain whether we are
2987 dealing with a SNaN or QNaN */
2988 break;
2989 case fmt_double:
2990 boolean = ((FP_D_be(op) == 0x7FF) && (FP_D_f(op) != 0));
2991 /* We could use "FP_S_fb(1,op)" to ascertain whether we are
2992 dealing with a SNaN or QNaN */
2993 break;
2994 case fmt_word:
2995 boolean = (op == FPQNaN_WORD);
2996 break;
2997 case fmt_long:
2998 boolean = (op == FPQNaN_LONG);
2999 break;
3000 }
3001
3002 #ifdef DEBUG
3003 printf("DBG: NaN: returning %d for 0x%08X%08X (format = %s)\n",boolean,WORD64HI(op),WORD64LO(op),DOFMT(fmt));
3004 #endif /* DEBUG */
3005
3006 return(boolean);
3007 }
3008
3009 static int
3010 Infinity(op,fmt)
3011 uword64 op;
3012 FP_formats fmt;
3013 {
3014 int boolean = 0;
3015
3016 #ifdef DEBUG
3017 printf("DBG: Infinity: format %s 0x%08X%08X (PC = 0x%08X%08X)\n",DOFMT(fmt),WORD64HI(op),WORD64LO(op),WORD64HI(IPC),WORD64LO(IPC));
3018 #endif /* DEBUG */
3019
3020 /* Check if (((E - bias) == (E_max + 1)) && (fraction == 0)). We
3021 know that the exponent field is biased... we we cheat and avoid
3022 removing the bias value. */
3023 switch (fmt) {
3024 case fmt_single:
3025 boolean = ((FP_S_be(op) == 0xFF) && (FP_S_f(op) == 0));
3026 break;
3027 case fmt_double:
3028 boolean = ((FP_D_be(op) == 0x7FF) && (FP_D_f(op) == 0));
3029 break;
3030 default:
3031 printf("DBG: TODO: unrecognised format (%s) for Infinity check\n",DOFMT(fmt));
3032 break;
3033 }
3034
3035 #ifdef DEBUG
3036 printf("DBG: Infinity: returning %d for 0x%08X%08X (format = %s)\n",boolean,WORD64HI(op),WORD64LO(op),DOFMT(fmt));
3037 #endif /* DEBUG */
3038
3039 return(boolean);
3040 }
3041
3042 static int
3043 Less(op1,op2,fmt)
3044 uword64 op1;
3045 uword64 op2;
3046 FP_formats fmt;
3047 {
3048 int boolean = 0;
3049
3050 /* Argument checking already performed by the FPCOMPARE code */
3051
3052 #ifdef DEBUG
3053 printf("DBG: Less: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op1),WORD64LO(op1),WORD64HI(op2),WORD64LO(op2));
3054 #endif /* DEBUG */
3055
3056 /* The format type should already have been checked: */
3057 switch (fmt) {
3058 case fmt_single:
3059 {
3060 unsigned int wop1 = (unsigned int)op1;
3061 unsigned int wop2 = (unsigned int)op2;
3062 boolean = (*(float *)&wop1 < *(float *)&wop2);
3063 }
3064 break;
3065 case fmt_double:
3066 boolean = (*(double *)&op1 < *(double *)&op2);
3067 break;
3068 }
3069
3070 #ifdef DEBUG
3071 printf("DBG: Less: returning %d (format = %s)\n",boolean,DOFMT(fmt));
3072 #endif /* DEBUG */
3073
3074 return(boolean);
3075 }
3076
3077 static int
3078 Equal(op1,op2,fmt)
3079 uword64 op1;
3080 uword64 op2;
3081 FP_formats fmt;
3082 {
3083 int boolean = 0;
3084
3085 /* Argument checking already performed by the FPCOMPARE code */
3086
3087 #ifdef DEBUG
3088 printf("DBG: Equal: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op1),WORD64LO(op1),WORD64HI(op2),WORD64LO(op2));
3089 #endif /* DEBUG */
3090
3091 /* The format type should already have been checked: */
3092 switch (fmt) {
3093 case fmt_single:
3094 boolean = ((op1 & 0xFFFFFFFF) == (op2 & 0xFFFFFFFF));
3095 break;
3096 case fmt_double:
3097 boolean = (op1 == op2);
3098 break;
3099 }
3100
3101 #ifdef DEBUG
3102 printf("DBG: Equal: returning %d (format = %s)\n",boolean,DOFMT(fmt));
3103 #endif /* DEBUG */
3104
3105 return(boolean);
3106 }
3107
3108 static uword64
3109 AbsoluteValue(op,fmt)
3110 uword64 op;
3111 FP_formats fmt;
3112 {
3113 uword64 result;
3114
3115 #ifdef DEBUG
3116 printf("DBG: AbsoluteValue: %s: op = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op),WORD64LO(op));
3117 #endif /* DEBUG */
3118
3119 /* The format type should already have been checked: */
3120 switch (fmt) {
3121 case fmt_single:
3122 {
3123 unsigned int wop = (unsigned int)op;
3124 float tmp = ((float)fabs((double)*(float *)&wop));
3125 result = (uword64)*(unsigned int *)&tmp;
3126 }
3127 break;
3128 case fmt_double:
3129 {
3130 double tmp = (fabs(*(double *)&op));
3131 result = *(uword64 *)&tmp;
3132 }
3133 }
3134
3135 return(result);
3136 }
3137
3138 static uword64
3139 Negate(op,fmt)
3140 uword64 op;
3141 FP_formats fmt;
3142 {
3143 uword64 result;
3144
3145 #ifdef DEBUG
3146 printf("DBG: Negate: %s: op = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op),WORD64LO(op));
3147 #endif /* DEBUG */
3148
3149 /* The format type should already have been checked: */
3150 switch (fmt) {
3151 case fmt_single:
3152 {
3153 unsigned int wop = (unsigned int)op;
3154 float tmp = ((float)0.0 - *(float *)&wop);
3155 result = (uword64)*(unsigned int *)&tmp;
3156 }
3157 break;
3158 case fmt_double:
3159 {
3160 double tmp = ((double)0.0 - *(double *)&op);
3161 result = *(uword64 *)&tmp;
3162 }
3163 break;
3164 }
3165
3166 return(result);
3167 }
3168
3169 static uword64
3170 Add(op1,op2,fmt)
3171 uword64 op1;
3172 uword64 op2;
3173 FP_formats fmt;
3174 {
3175 uword64 result;
3176
3177 #ifdef DEBUG
3178 printf("DBG: Add: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op1),WORD64LO(op1),WORD64HI(op2),WORD64LO(op2));
3179 #endif /* DEBUG */
3180
3181 /* The registers must specify FPRs valid for operands of type
3182 "fmt". If they are not valid, the result is undefined. */
3183
3184 /* The format type should already have been checked: */
3185 switch (fmt) {
3186 case fmt_single:
3187 {
3188 unsigned int wop1 = (unsigned int)op1;
3189 unsigned int wop2 = (unsigned int)op2;
3190 float tmp = (*(float *)&wop1 + *(float *)&wop2);
3191 result = (uword64)*(unsigned int *)&tmp;
3192 }
3193 break;
3194 case fmt_double:
3195 {
3196 double tmp = (*(double *)&op1 + *(double *)&op2);
3197 result = *(uword64 *)&tmp;
3198 }
3199 break;
3200 }
3201
3202 #ifdef DEBUG
3203 printf("DBG: Add: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
3204 #endif /* DEBUG */
3205
3206 return(result);
3207 }
3208
3209 static uword64
3210 Sub(op1,op2,fmt)
3211 uword64 op1;
3212 uword64 op2;
3213 FP_formats fmt;
3214 {
3215 uword64 result;
3216
3217 #ifdef DEBUG
3218 printf("DBG: Sub: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op1),WORD64LO(op1),WORD64HI(op2),WORD64LO(op2));
3219 #endif /* DEBUG */
3220
3221 /* The registers must specify FPRs valid for operands of type
3222 "fmt". If they are not valid, the result is undefined. */
3223
3224 /* The format type should already have been checked: */
3225 switch (fmt) {
3226 case fmt_single:
3227 {
3228 unsigned int wop1 = (unsigned int)op1;
3229 unsigned int wop2 = (unsigned int)op2;
3230 float tmp = (*(float *)&wop1 - *(float *)&wop2);
3231 result = (uword64)*(unsigned int *)&tmp;
3232 }
3233 break;
3234 case fmt_double:
3235 {
3236 double tmp = (*(double *)&op1 - *(double *)&op2);
3237 result = *(uword64 *)&tmp;
3238 }
3239 break;
3240 }
3241
3242 #ifdef DEBUG
3243 printf("DBG: Sub: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
3244 #endif /* DEBUG */
3245
3246 return(result);
3247 }
3248
3249 static uword64
3250 Multiply(op1,op2,fmt)
3251 uword64 op1;
3252 uword64 op2;
3253 FP_formats fmt;
3254 {
3255 uword64 result;
3256
3257 #ifdef DEBUG
3258 printf("DBG: Multiply: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op1),WORD64LO(op1),WORD64HI(op2),WORD64LO(op2));
3259 #endif /* DEBUG */
3260
3261 /* The registers must specify FPRs valid for operands of type
3262 "fmt". If they are not valid, the result is undefined. */
3263
3264 /* The format type should already have been checked: */
3265 switch (fmt) {
3266 case fmt_single:
3267 {
3268 unsigned int wop1 = (unsigned int)op1;
3269 unsigned int wop2 = (unsigned int)op2;
3270 float tmp = (*(float *)&wop1 * *(float *)&wop2);
3271 result = (uword64)*(unsigned int *)&tmp;
3272 }
3273 break;
3274 case fmt_double:
3275 {
3276 double tmp = (*(double *)&op1 * *(double *)&op2);
3277 result = *(uword64 *)&tmp;
3278 }
3279 break;
3280 }
3281
3282 #ifdef DEBUG
3283 printf("DBG: Multiply: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
3284 #endif /* DEBUG */
3285
3286 return(result);
3287 }
3288
3289 static uword64
3290 Divide(op1,op2,fmt)
3291 uword64 op1;
3292 uword64 op2;
3293 FP_formats fmt;
3294 {
3295 uword64 result;
3296
3297 #ifdef DEBUG
3298 printf("DBG: Divide: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op1),WORD64LO(op1),WORD64HI(op2),WORD64LO(op2));
3299 #endif /* DEBUG */
3300
3301 /* The registers must specify FPRs valid for operands of type
3302 "fmt". If they are not valid, the result is undefined. */
3303
3304 /* The format type should already have been checked: */
3305 switch (fmt) {
3306 case fmt_single:
3307 {
3308 unsigned int wop1 = (unsigned int)op1;
3309 unsigned int wop2 = (unsigned int)op2;
3310 float tmp = (*(float *)&wop1 / *(float *)&wop2);
3311 result = (uword64)*(unsigned int *)&tmp;
3312 }
3313 break;
3314 case fmt_double:
3315 {
3316 double tmp = (*(double *)&op1 / *(double *)&op2);
3317 result = *(uword64 *)&tmp;
3318 }
3319 break;
3320 }
3321
3322 #ifdef DEBUG
3323 printf("DBG: Divide: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
3324 #endif /* DEBUG */
3325
3326 return(result);
3327 }
3328
3329 static uword64
3330 Recip(op,fmt)
3331 uword64 op;
3332 FP_formats fmt;
3333 {
3334 uword64 result;
3335
3336 #ifdef DEBUG
3337 printf("DBG: Recip: %s: op = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op),WORD64LO(op));
3338 #endif /* DEBUG */
3339
3340 /* The registers must specify FPRs valid for operands of type
3341 "fmt". If they are not valid, the result is undefined. */
3342
3343 /* The format type should already have been checked: */
3344 switch (fmt) {
3345 case fmt_single:
3346 {
3347 unsigned int wop = (unsigned int)op;
3348 float tmp = ((float)1.0 / *(float *)&wop);
3349 result = (uword64)*(unsigned int *)&tmp;
3350 }
3351 break;
3352 case fmt_double:
3353 {
3354 double tmp = ((double)1.0 / *(double *)&op);
3355 result = *(uword64 *)&tmp;
3356 }
3357 break;
3358 }
3359
3360 #ifdef DEBUG
3361 printf("DBG: Recip: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
3362 #endif /* DEBUG */
3363
3364 return(result);
3365 }
3366
3367 static uword64
3368 SquareRoot(op,fmt)
3369 uword64 op;
3370 FP_formats fmt;
3371 {
3372 uword64 result;
3373
3374 #ifdef DEBUG
3375 printf("DBG: SquareRoot: %s: op = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op),WORD64LO(op));
3376 #endif /* DEBUG */
3377
3378 /* The registers must specify FPRs valid for operands of type
3379 "fmt". If they are not valid, the result is undefined. */
3380
3381 /* The format type should already have been checked: */
3382 switch (fmt) {
3383 case fmt_single:
3384 {
3385 unsigned int wop = (unsigned int)op;
3386 #ifdef HAVE_SQRT
3387 float tmp = ((float)sqrt((double)*(float *)&wop));
3388 result = (uword64)*(unsigned int *)&tmp;
3389 #else
3390 /* TODO: Provide square-root */
3391 result = (uword64)0;
3392 #endif
3393 }
3394 break;
3395 case fmt_double:
3396 {
3397 #ifdef HAVE_SQRT
3398 double tmp = (sqrt(*(double *)&op));
3399 result = *(uword64 *)&tmp;
3400 #else
3401 /* TODO: Provide square-root */
3402 result = (uword64)0;
3403 #endif
3404 }
3405 break;
3406 }
3407
3408 #ifdef DEBUG
3409 printf("DBG: SquareRoot: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
3410 #endif /* DEBUG */
3411
3412 return(result);
3413 }
3414
3415 static uword64
3416 Convert(rm,op,from,to)
3417 int rm;
3418 uword64 op;
3419 FP_formats from;
3420 FP_formats to;
3421 {
3422 uword64 result;
3423
3424 #ifdef DEBUG
3425 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));
3426 #endif /* DEBUG */
3427
3428 /* The value "op" is converted to the destination format, rounding
3429 using mode "rm". When the destination is a fixed-point format,
3430 then a source value of Infinity, NaN or one which would round to
3431 an integer outside the fixed point range then an IEEE Invalid
3432 Operation condition is raised. */
3433 switch (to) {
3434 case fmt_single:
3435 {
3436 float tmp;
3437 switch (from) {
3438 case fmt_double:
3439 tmp = (float)(*(double *)&op);
3440 break;
3441
3442 case fmt_word:
3443 tmp = (float)((int)(op & 0xFFFFFFFF));
3444 break;
3445
3446 case fmt_long:
3447 tmp = (float)((word64)op);
3448 break;
3449 }
3450
3451 #if 0
3452 /* FIXME: This code is incorrect. The rounding mode does not
3453 round to integral values; it rounds to the nearest
3454 representable value in the format. */
3455
3456 switch (rm) {
3457 case FP_RM_NEAREST:
3458 /* Round result to nearest representable value. When two
3459 representable values are equally near, round to the value
3460 that has a least significant bit of zero (i.e. is even). */
3461 #ifdef HAVE_ANINT
3462 tmp = (float)anint((double)tmp);
3463 #else
3464 /* TODO: Provide round-to-nearest */
3465 #endif
3466 break;
3467
3468 case FP_RM_TOZERO:
3469 /* Round result to the value closest to, and not greater in
3470 magnitude than, the result. */
3471 #ifdef HAVE_AINT
3472 tmp = (float)aint((double)tmp);
3473 #else
3474 /* TODO: Provide round-to-zero */
3475 #endif
3476 break;
3477
3478 case FP_RM_TOPINF:
3479 /* Round result to the value closest to, and not less than,
3480 the result. */
3481 tmp = (float)ceil((double)tmp);
3482 break;
3483
3484 case FP_RM_TOMINF:
3485 /* Round result to the value closest to, and not greater than,
3486 the result. */
3487 tmp = (float)floor((double)tmp);
3488 break;
3489 }
3490 #endif /* 0 */
3491
3492 result = (uword64)*(unsigned int *)&tmp;
3493 }
3494 break;
3495
3496 case fmt_double:
3497 {
3498 double tmp;
3499 word64 xxx;
3500
3501 switch (from) {
3502 case fmt_single:
3503 {
3504 unsigned int wop = (unsigned int)op;
3505 tmp = (double)(*(float *)&wop);
3506 }
3507 break;
3508
3509 case fmt_word:
3510 xxx = SIGNEXTEND((op & 0xFFFFFFFF),32);
3511 tmp = (double)xxx;
3512 break;
3513
3514 case fmt_long:
3515 tmp = (double)((word64)op);
3516 break;
3517 }
3518
3519 #if 0
3520 /* FIXME: This code is incorrect. The rounding mode does not
3521 round to integral values; it rounds to the nearest
3522 representable value in the format. */
3523
3524 switch (rm) {
3525 case FP_RM_NEAREST:
3526 #ifdef HAVE_ANINT
3527 tmp = anint(*(double *)&tmp);
3528 #else
3529 /* TODO: Provide round-to-nearest */
3530 #endif
3531 break;
3532
3533 case FP_RM_TOZERO:
3534 #ifdef HAVE_AINT
3535 tmp = aint(*(double *)&tmp);
3536 #else
3537 /* TODO: Provide round-to-zero */
3538 #endif
3539 break;
3540
3541 case FP_RM_TOPINF:
3542 tmp = ceil(*(double *)&tmp);
3543 break;
3544
3545 case FP_RM_TOMINF:
3546 tmp = floor(*(double *)&tmp);
3547 break;
3548 }
3549 #endif /* 0 */
3550
3551 result = *(uword64 *)&tmp;
3552 }
3553 break;
3554
3555 case fmt_word:
3556 case fmt_long:
3557 if (Infinity(op,from) || NaN(op,from) || (1 == 0/*TODO: check range */)) {
3558 printf("DBG: TODO: update FCSR\n");
3559 SignalException(FPE);
3560 } else {
3561 if (to == fmt_word) {
3562 int tmp;
3563 switch (from) {
3564 case fmt_single:
3565 {
3566 unsigned int wop = (unsigned int)op;
3567 tmp = (int)*((float *)&wop);
3568 }
3569 break;
3570 case fmt_double:
3571 tmp = (int)*((double *)&op);
3572 #ifdef DEBUG
3573 printf("DBG: from double %.30f (0x%08X%08X) to word: 0x%08X\n",*((double *)&op),WORD64HI(op),WORD64LO(op),tmp);
3574 #endif /* DEBUG */
3575 break;
3576 }
3577 result = (uword64)tmp;
3578 } else { /* fmt_long */
3579 word64 tmp;
3580 switch (from) {
3581 case fmt_single:
3582 {
3583 unsigned int wop = (unsigned int)op;
3584 tmp = (word64)*((float *)&wop);
3585 }
3586 break;
3587 case fmt_double:
3588 tmp = (word64)*((double *)&op);
3589 break;
3590 }
3591 result = (uword64)tmp;
3592 }
3593 }
3594 break;
3595 }
3596
3597 #ifdef DEBUG
3598 printf("DBG: Convert: returning 0x%08X%08X (to format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(to));
3599 #endif /* DEBUG */
3600
3601 return(result);
3602 }
3603 #endif /* HASFPU */
3604
3605 /*-- co-processor support routines ------------------------------------------*/
3606
3607 static int
3608 CoProcPresent(coproc_number)
3609 unsigned int coproc_number;
3610 {
3611 /* Return TRUE if simulator provides a model for the given co-processor number */
3612 return(0);
3613 }
3614
3615 static void
3616 COP_LW(coproc_num,coproc_reg,memword)
3617 int coproc_num, coproc_reg;
3618 unsigned int memword;
3619 {
3620 switch (coproc_num) {
3621 #if defined(HASFPU)
3622 case 1:
3623 #ifdef DEBUG
3624 printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%08X%08X\n",memword,WORD64HI(memword),WORD64LO(memword));
3625 #endif
3626 StoreFPR(coproc_reg,fmt_uninterpreted,(uword64)memword);
3627 break;
3628 #endif /* HASFPU */
3629
3630 default:
3631 #if 0 /* this should be controlled by a configuration option */
3632 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));
3633 #endif
3634 break;
3635 }
3636
3637 return;
3638 }
3639
3640 static void
3641 COP_LD(coproc_num,coproc_reg,memword)
3642 int coproc_num, coproc_reg;
3643 uword64 memword;
3644 {
3645 switch (coproc_num) {
3646 #if defined(HASFPU)
3647 case 1:
3648 StoreFPR(coproc_reg,fmt_uninterpreted,memword);
3649 break;
3650 #endif /* HASFPU */
3651
3652 default:
3653 #if 0 /* this message should be controlled by a configuration option */
3654 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));
3655 #endif
3656 break;
3657 }
3658
3659 return;
3660 }
3661
3662 static unsigned int
3663 COP_SW(coproc_num,coproc_reg)
3664 int coproc_num, coproc_reg;
3665 {
3666 unsigned int value = 0;
3667 switch (coproc_num) {
3668 #if defined(HASFPU)
3669 case 1:
3670 #if 1
3671 value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted);
3672 #else
3673 #if 1
3674 value = (unsigned int)ValueFPR(coproc_reg,fpr_state[coproc_reg]);
3675 #else
3676 #ifdef DEBUG
3677 printf("DBG: COP_SW: reg in format %s (will be accessing as single)\n",DOFMT(fpr_state[coproc_reg]));
3678 #endif /* DEBUG */
3679 value = (unsigned int)ValueFPR(coproc_reg,fmt_single);
3680 #endif
3681 #endif
3682 break;
3683 #endif /* HASFPU */
3684
3685 default:
3686 #if 0 /* should be controlled by configuration option */
3687 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));
3688 #endif
3689 break;
3690 }
3691
3692 return(value);
3693 }
3694
3695 static uword64
3696 COP_SD(coproc_num,coproc_reg)
3697 int coproc_num, coproc_reg;
3698 {
3699 uword64 value = 0;
3700 switch (coproc_num) {
3701 #if defined(HASFPU)
3702 case 1:
3703 #if 1
3704 value = ValueFPR(coproc_reg,fmt_uninterpreted);
3705 #else
3706 #if 1
3707 value = ValueFPR(coproc_reg,fpr_state[coproc_reg]);
3708 #else
3709 #ifdef DEBUG
3710 printf("DBG: COP_SD: reg in format %s (will be accessing as double)\n",DOFMT(fpr_state[coproc_reg]));
3711 #endif /* DEBUG */
3712 value = ValueFPR(coproc_reg,fmt_double);
3713 #endif
3714 #endif
3715 break;
3716 #endif /* HASFPU */
3717
3718 default:
3719 #if 0 /* should be controlled by configuration option */
3720 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));
3721 #endif
3722 break;
3723 }
3724
3725 return(value);
3726 }
3727
3728 static void
3729 decode_coproc(instruction)
3730 unsigned int instruction;
3731 {
3732 int coprocnum = ((instruction >> 26) & 3);
3733
3734 switch (coprocnum) {
3735 case 0: /* standard CPU control and cache registers */
3736 {
3737 /* NOTEs:
3738 Standard CP0 registers
3739 0 = Index R4000 VR4100 VR4300
3740 1 = Random R4000 VR4100 VR4300
3741 2 = EntryLo0 R4000 VR4100 VR4300
3742 3 = EntryLo1 R4000 VR4100 VR4300
3743 4 = Context R4000 VR4100 VR4300
3744 5 = PageMask R4000 VR4100 VR4300
3745 6 = Wired R4000 VR4100 VR4300
3746 8 = BadVAddr R4000 VR4100 VR4300
3747 9 = Count R4000 VR4100 VR4300
3748 10 = EntryHi R4000 VR4100 VR4300
3749 11 = Compare R4000 VR4100 VR4300
3750 12 = SR R4000 VR4100 VR4300
3751 13 = Cause R4000 VR4100 VR4300
3752 14 = EPC R4000 VR4100 VR4300
3753 15 = PRId R4000 VR4100 VR4300
3754 16 = Config R4000 VR4100 VR4300
3755 17 = LLAddr R4000 VR4100 VR4300
3756 18 = WatchLo R4000 VR4100 VR4300
3757 19 = WatchHi R4000 VR4100 VR4300
3758 20 = XContext R4000 VR4100 VR4300
3759 26 = PErr or ECC R4000 VR4100 VR4300
3760 27 = CacheErr R4000 VR4100
3761 28 = TagLo R4000 VR4100 VR4300
3762 29 = TagHi R4000 VR4100 VR4300
3763 30 = ErrorEPC R4000 VR4100 VR4300
3764 */
3765 int code = ((instruction >> 21) & 0x1F);
3766 /* R4000 Users Manual (second edition) lists the following CP0
3767 instructions:
3768 DMFC0 Doubleword Move From CP0 (VR4100 = 01000000001tttttddddd00000000000)
3769 DMTC0 Doubleword Move To CP0 (VR4100 = 01000000101tttttddddd00000000000)
3770 MFC0 word Move From CP0 (VR4100 = 01000000000tttttddddd00000000000)
3771 MTC0 word Move To CP0 (VR4100 = 01000000100tttttddddd00000000000)
3772 TLBR Read Indexed TLB Entry (VR4100 = 01000010000000000000000000000001)
3773 TLBWI Write Indexed TLB Entry (VR4100 = 01000010000000000000000000000010)
3774 TLBWR Write Random TLB Entry (VR4100 = 01000010000000000000000000000110)
3775 TLBP Probe TLB for Matching Entry (VR4100 = 01000010000000000000000000001000)
3776 CACHE Cache operation (VR4100 = 101111bbbbbpppppiiiiiiiiiiiiiiii)
3777 ERET Exception return (VR4100 = 01000010000000000000000000011000)
3778 */
3779 if (((code == 0x00) || (code == 0x04)) && ((instruction & 0x7FF) == 0)) {
3780 int rt = ((instruction >> 16) & 0x1F);
3781 int rd = ((instruction >> 11) & 0x1F);
3782 if (code == 0x00) { /* MF : move from */
3783 #if 0 /* message should be controlled by configuration option */
3784 callback->printf_filtered(callback,"Warning: MFC0 %d,%d not handled yet (architecture specific)\n",rt,rd);
3785 #endif
3786 GPR[rt] = 0xDEADC0DE; /* CPR[0,rd] */
3787 } else { /* MT : move to */
3788 /* CPR[0,rd] = GPR[rt]; */
3789 #if 0 /* should be controlled by configuration option */
3790 callback->printf_filtered(callback,"Warning: MTC0 %d,%d not handled yet (architecture specific)\n",rt,rd);
3791 #endif
3792 }
3793 } else
3794 sim_warning("Unrecognised COP0 instruction 0x%08X at IPC = 0x%08X%08X : No handler present",instruction,WORD64HI(IPC),WORD64LO(IPC));
3795 /* TODO: When executing an ERET or RFE instruction we should
3796 clear LLBIT, to ensure that any out-standing atomic
3797 read/modify/write sequence fails. */
3798 }
3799 break;
3800
3801 case 2: /* undefined co-processor */
3802 sim_warning("COP2 instruction 0x%08X at IPC = 0x%08X%08X : No handler present",instruction,WORD64HI(IPC),WORD64LO(IPC));
3803 break;
3804
3805 case 1: /* should not occur (FPU co-processor) */
3806 case 3: /* should not occur (FPU co-processor) */
3807 SignalException(ReservedInstruction,instruction);
3808 break;
3809 }
3810
3811 return;
3812 }
3813
3814 /*-- instruction simulation -------------------------------------------------*/
3815
3816 static void
3817 simulate ()
3818 {
3819 unsigned int pipeline_count = 1;
3820
3821 #ifdef DEBUG
3822 if (membank == NULL) {
3823 printf("DBG: simulate() entered with no memory\n");
3824 exit(1);
3825 }
3826 #endif /* DEBUG */
3827
3828 #if 0 /* Disabled to check that everything works OK */
3829 /* The VR4300 seems to sign-extend the PC on its first
3830 access. However, this may just be because it is currently
3831 configured in 32bit mode. However... */
3832 PC = SIGNEXTEND(PC,32);
3833 #endif
3834
3835 /* main controlling loop */
3836 do {
3837 /* Fetch the next instruction from the simulator memory: */
3838 uword64 vaddr = (uword64)PC;
3839 uword64 paddr;
3840 int cca;
3841 unsigned int instruction;
3842 int dsstate = (state & simDELAYSLOT);
3843
3844 #ifdef DEBUG
3845 {
3846 printf("DBG: state = 0x%08X :",state);
3847 if (state & simSTOP) printf(" simSTOP");
3848 if (state & simSTEP) printf(" simSTEP");
3849 if (state & simHALTEX) printf(" simHALTEX");
3850 if (state & simHALTIN) printf(" simHALTIN");
3851 if (state & simBE) printf(" simBE");
3852 }
3853 #endif /* DEBUG */
3854
3855 #ifdef DEBUG
3856 if (dsstate)
3857 callback->printf_filtered(callback,"DBG: DSPC = 0x%08X%08X\n",WORD64HI(DSPC),WORD64LO(DSPC));
3858 #endif /* DEBUG */
3859
3860 if (AddressTranslation(PC,isINSTRUCTION,isLOAD,&paddr,&cca,isTARGET,isREAL)) { /* Copy the action of the LW instruction */
3861 unsigned int reverse = (ReverseEndian ? (LOADDRMASK >> 2) : 0);
3862 unsigned int bigend = (BigEndianCPU ? (LOADDRMASK >> 2) : 0);
3863 uword64 value;
3864 unsigned int byte;
3865 paddr = ((paddr & ~LOADDRMASK) | ((paddr & LOADDRMASK) ^ (reverse << 2)));
3866 value = LoadMemory(cca,AccessLength_WORD,paddr,vaddr,isINSTRUCTION,isREAL);
3867 byte = ((vaddr & LOADDRMASK) ^ (bigend << 2));
3868 instruction = ((value >> (8 * byte)) & 0xFFFFFFFF);
3869 } else {
3870 fprintf(stderr,"Cannot translate address for PC = 0x%08X%08X failed\n",WORD64HI(PC),WORD64LO(PC));
3871 exit(1);
3872 }
3873
3874 #ifdef DEBUG
3875 callback->printf_filtered(callback,"DBG: fetched 0x%08X from PC = 0x%08X%08X\n",instruction,WORD64HI(PC),WORD64LO(PC));
3876 #endif /* DEBUG */
3877
3878 #if !defined(FASTSIM) || defined(PROFILE)
3879 instruction_fetches++;
3880 /* Since we increment above, the value should only ever be zero if
3881 we have just overflowed: */
3882 if (instruction_fetches == 0)
3883 instruction_fetch_overflow++;
3884 #if defined(PROFILE)
3885 if ((state & simPROFILE) && ((instruction_fetches % profile_frequency) == 0) && profile_hist) {
3886 unsigned n = ((unsigned int)(PC - profile_minpc) >> (profile_shift + 2));
3887 if (n < profile_nsamples) {
3888 /* NOTE: The counts for the profiling bins are only 16bits wide */
3889 if (profile_hist[n] != USHRT_MAX)
3890 (profile_hist[n])++;
3891 }
3892 }
3893 #endif /* PROFILE */
3894 #endif /* !FASTSIM && PROFILE */
3895
3896 IPC = PC; /* copy PC for this instruction */
3897 /* This is required by exception processing, to ensure that we can
3898 cope with exceptions in the delay slots of branches that may
3899 already have changed the PC. */
3900 PC += 4; /* increment ready for the next fetch */
3901 /* NOTE: If we perform a delay slot change to the PC, this
3902 increment is not requuired. However, it would make the
3903 simulator more complicated to try and avoid this small hit. */
3904
3905 /* Currently this code provides a simple model. For more
3906 complicated models we could perform exception status checks at
3907 this point, and set the simSTOP state as required. This could
3908 also include processing any hardware interrupts raised by any
3909 I/O model attached to the simulator context.
3910
3911 Support for "asynchronous" I/O events within the simulated world
3912 could be providing by managing a counter, and calling a I/O
3913 specific handler when a particular threshold is reached. On most
3914 architectures a decrement and check for zero operation is
3915 usually quicker than an increment and compare. However, the
3916 process of managing a known value decrement to zero, is higher
3917 than the cost of using an explicit value UINT_MAX into the
3918 future. Which system is used will depend on how complicated the
3919 I/O model is, and how much it is likely to affect the simulator
3920 bandwidth.
3921
3922 If events need to be scheduled further in the future than
3923 UINT_MAX event ticks, then the I/O model should just provide its
3924 own counter, triggered from the event system. */
3925
3926 /* MIPS pipeline ticks. To allow for future support where the
3927 pipeline hit of individual instructions is known, this control
3928 loop manages a "pipeline_count" variable. It is initialised to
3929 1 (one), and will only be changed by the simulator engine when
3930 executing an instruction. If the engine does not have access to
3931 pipeline cycle count information then all instructions will be
3932 treated as using a single cycle. NOTE: A standard system is not
3933 provided by the default simulator because different MIPS
3934 architectures have different cycle counts for the same
3935 instructions. */
3936
3937 #if defined(HASFPU)
3938 /* Set previous flag, depending on current: */
3939 if (state & simPCOC0)
3940 state |= simPCOC1;
3941 else
3942 state &= ~simPCOC1;
3943 /* and update the current value: */
3944 if (GETFCC(0))
3945 state |= simPCOC0;
3946 else
3947 state &= ~simPCOC0;
3948 #endif /* HASFPU */
3949
3950 /* NOTE: For multi-context simulation environments the "instruction"
3951 variable should be local to this routine. */
3952
3953 /* Shorthand accesses for engine. Note: If we wanted to use global
3954 variables (and a single-threaded simulator engine), then we can
3955 create the actual variables with these names. */
3956
3957 if (!(state & simSKIPNEXT)) {
3958 /* Include the simulator engine */
3959 #include "engine.c"
3960 #if ((GPRLEN == 64) && !PROCESSOR_64BIT) || ((GPRLEN == 32) && PROCESSOR_64BIT)
3961 #error "Mismatch between run-time simulator code and simulation engine"
3962 #endif
3963
3964 #if defined(WARN_LOHI)
3965 /* Decrement the HI/LO validity ticks */
3966 if (HIACCESS > 0)
3967 HIACCESS--;
3968 if (LOACCESS > 0)
3969 LOACCESS--;
3970 #endif /* WARN_LOHI */
3971
3972 #if defined(WARN_ZERO)
3973 /* For certain MIPS architectures, GPR[0] is hardwired to zero. We
3974 should check for it being changed. It is better doing it here,
3975 than within the simulator, since it will help keep the simulator
3976 small. */
3977 if (ZERO != 0) {
3978 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));
3979 ZERO = 0; /* reset back to zero before next instruction */
3980 }
3981 #endif /* WARN_ZERO */
3982 } else /* simSKIPNEXT check */
3983 state &= ~simSKIPNEXT;
3984
3985 /* If the delay slot was active before the instruction is
3986 executed, then update the PC to its new value: */
3987 if (dsstate) {
3988 #ifdef DEBUG
3989 printf("DBG: dsstate set before instruction execution - updating PC to 0x%08X%08X\n",WORD64HI(DSPC),WORD64LO(DSPC));
3990 #endif /* DEBUG */
3991 PC = DSPC;
3992 state &= ~simDELAYSLOT;
3993 }
3994
3995 if (MIPSISA < 4) { /* The following is only required on pre MIPS IV processors: */
3996 /* Deal with pending register updates: */
3997 #ifdef DEBUG
3998 printf("DBG: EMPTY BEFORE pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total);
3999 #endif /* DEBUG */
4000 if (pending_out != pending_in) {
4001 int loop;
4002 int index = pending_out;
4003 int total = pending_total;
4004 if (pending_total == 0) {
4005 fprintf(stderr,"FATAL: Mis-match on pending update pointers\n");
4006 exit(1);
4007 }
4008 for (loop = 0; (loop < total); loop++) {
4009 #ifdef DEBUG
4010 printf("DBG: BEFORE index = %d, loop = %d\n",index,loop);
4011 #endif /* DEBUG */
4012 if (pending_slot_reg[index] != (LAST_EMBED_REGNUM + 1)) {
4013 #ifdef DEBUG
4014 printf("pending_slot_count[%d] = %d\n",index,pending_slot_count[index]);
4015 #endif /* DEBUG */
4016 if (--(pending_slot_count[index]) == 0) {
4017 #ifdef DEBUG
4018 printf("pending_slot_reg[%d] = %d\n",index,pending_slot_reg[index]);
4019 printf("pending_slot_value[%d] = 0x%08X%08X\n",index,WORD64HI(pending_slot_value[index]),WORD64LO(pending_slot_value[index]));
4020 #endif /* DEBUG */
4021 if (pending_slot_reg[index] == COCIDX) {
4022 SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0));
4023 } else {
4024 registers[pending_slot_reg[index]] = pending_slot_value[index];
4025 #if defined(HASFPU)
4026 /* The only time we have PENDING updates to FPU
4027 registers, is when performing binary transfers. This
4028 means we should update the register type field. */
4029 if ((pending_slot_reg[index] >= FGRIDX) && (pending_slot_reg[index] < (FGRIDX + 32)))
4030 fpr_state[pending_slot_reg[index]] = fmt_uninterpreted;
4031 #endif /* HASFPU */
4032 }
4033 #ifdef DEBUG
4034 printf("registers[%d] = 0x%08X%08X\n",pending_slot_reg[index],WORD64HI(registers[pending_slot_reg[index]]),WORD64LO(registers[pending_slot_reg[index]]));
4035 #endif /* DEBUG */
4036 pending_slot_reg[index] = (LAST_EMBED_REGNUM + 1);
4037 pending_out++;
4038 if (pending_out == PSLOTS)
4039 pending_out = 0;
4040 pending_total--;
4041 }
4042 }
4043 #ifdef DEBUG
4044 printf("DBG: AFTER index = %d, loop = %d\n",index,loop);
4045 #endif /* DEBUG */
4046 index++;
4047 if (index == PSLOTS)
4048 index = 0;
4049 }
4050 }
4051 #ifdef DEBUG
4052 printf("DBG: EMPTY AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total);
4053 #endif /* DEBUG */
4054 }
4055
4056 #if !defined(FASTSIM)
4057 pipeline_ticks += pipeline_count;
4058 #endif /* FASTSIM */
4059
4060 if (state & simSTEP)
4061 state |= simSTOP;
4062 } while (!(state & simSTOP));
4063
4064 #ifdef DEBUG
4065 if (membank == NULL) {
4066 printf("DBG: simulate() LEAVING with no memory\n");
4067 exit(1);
4068 }
4069 #endif /* DEBUG */
4070
4071 return;
4072 }
4073
4074 /*---------------------------------------------------------------------------*/
4075 /*> EOF interp.c <*/
This page took 0.136325 seconds and 4 git commands to generate.