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