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