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