* support.h: Make definitions of SIGTRAP and SIGQUIT consistent
[deliverable/binutils-gdb.git] / sim / mips / interp.c
CommitLineData
8bae0a0c
JSC
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$
e3d12c65 18 $Date$
8bae0a0c
JSC
19
20NOTEs:
21
22We only need to take account of the target endianness when moving data
23between the simulator and the host. We do not need to worry about the
24endianness of the host, since this sim code and GDB are executing in
25the same process.
26
27The IDT monitor (found on the VR4300 board), seems to lie about
28register contents. It seems to treat the registers as sign-extended
2932-bit values. This cause *REAL* problems when single-stepping 64-bit
30code 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
4fa134be
ILT
43#include "config.h"
44
8bae0a0c
JSC
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>
4fa134be
ILT
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
8bae0a0c
JSC
62
63#include "getopt.h"
64#include "libiberty.h"
65
8bae0a0c 66#include "callback.h" /* GDB simulator callback interface */
e3d12c65 67#include "remote-sim.h" /* GDB simulator interface */
8bae0a0c
JSC
68
69#include "support.h" /* internal support manifests */
70
f24b7b69
JSC
71#include "sysdep.h"
72
73#ifndef SIGBUS
74#define SIGBUS SIGSEGV
75#endif
76
8bae0a0c
JSC
77/* Get the simulator engine description, without including the code: */
78#define SIM_MANIFESTS
79#include "engine.c"
80#undef SIM_MANIFESTS
81
f7481d45
JSC
82/* This variable holds the GDB view of the target endianness: */
83extern int target_byte_order;
84
8bae0a0c
JSC
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). */
149typedef 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
176static host_callback *callback = NULL; /* handle onto the current callback structure */
177
8bae0a0c
JSC
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. */
e3d12c65 189#ifndef TM_MIPS_H
8bae0a0c 190#define LAST_EMBED_REGNUM (89)
e3d12c65 191#endif
8bae0a0c
JSC
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. */
4fa134be
ILT
196static ut_reg registers[LAST_EMBED_REGNUM + 1];
197static int register_widths[LAST_EMBED_REGNUM + 1];
8bae0a0c
JSC
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
4fa134be 227static ut_reg EPC = 0; /* Exception PC */
8bae0a0c
JSC
228
229#if defined(HASFPU)
230/* Keep the current format state for each register: */
4fa134be 231static FP_formats fpr_state[32];
8bae0a0c
JSC
232#endif /* HASFPU */
233
8bae0a0c 234/* The following are internal simulator state variables: */
4fa134be
ILT
235static ut_reg IPC = 0; /* internal Instruction PC */
236static ut_reg DSPC = 0; /* delay-slot PC */
8bae0a0c
JSC
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
8bae0a0c
JSC
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 */
4fa134be
ILT
310static int pending_in;
311static int pending_out;
312static int pending_total;
313static int pending_slot_count[PSLOTS];
314static int pending_slot_reg[PSLOTS];
315static ut_reg pending_slot_value[PSLOTS];
8bae0a0c 316
e3d12c65
DE
317/*---------------------------------------------------------------------------*/
318/*-- GDB simulator interface ------------------------------------------------*/
319/*---------------------------------------------------------------------------*/
320
321static void dotrace PARAMS((FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...));
322static void sim_warning PARAMS((char *fmt,...));
323extern void sim_error PARAMS((char *fmt,...));
aaff8437 324static void set_endianness PARAMS((void));
e3d12c65
DE
325static void ColdReset PARAMS((void));
326static int AddressTranslation PARAMS((uword64 vAddr,int IorD,int LorS,uword64 *pAddr,int *CCA,int host,int raw));
327static void StoreMemory PARAMS((int CCA,int AccessLength,uword64 MemElem,uword64 pAddr,uword64 vAddr,int raw));
328static uword64 LoadMemory PARAMS((int CCA,int AccessLength,uword64 pAddr,uword64 vAddr,int IorD,int raw));
329static void SignalException PARAMS((int exception,...));
330static void simulate PARAMS((void));
331static long getnum PARAMS((char *value));
332extern void sim_size PARAMS((unsigned int newsize));
333extern void sim_set_profile PARAMS((int frequency));
334static unsigned int power2 PARAMS((unsigned int value));
335
336/*---------------------------------------------------------------------------*/
337
8bae0a0c
JSC
338/* The following are not used for MIPS IV onwards: */
339#define PENDING_FILL(r,v) {\
f24b7b69 340/* printf("DBG: FILL BEFORE pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total); */\
8bae0a0c 341 if (pending_slot_reg[pending_in] != (LAST_EMBED_REGNUM + 1))\
f24b7b69 342 sim_warning("Attempt to over-write pending value");\
8bae0a0c
JSC
343 pending_slot_count[pending_in] = 2;\
344 pending_slot_reg[pending_in] = (r);\
e871dd18 345 pending_slot_value[pending_in] = (uword64)(v);\
f24b7b69 346/*printf("DBG: FILL reg %d value = 0x%08X%08X\n",(r),WORD64HI(v),WORD64LO(v));*/\
8bae0a0c
JSC
347 pending_total++;\
348 pending_in++;\
349 if (pending_in == PSLOTS)\
350 pending_in = 0;\
f24b7b69 351/*printf("DBG: FILL AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total);*/\
8bae0a0c
JSC
352 }
353
4fa134be 354static int LLBIT = 0;
8bae0a0c
JSC
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
4fa134be
ILT
362static int HIACCESS = 0;
363static int LOACCESS = 0;
8bae0a0c
JSC
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. */
f24b7b69 367static ut_reg HLPC = 0;
8bae0a0c 368
6429b296
JW
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
8bae0a0c
JSC
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))\
f24b7b69 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));\
8bae0a0c 382 }
6429b296 383#endif
8bae0a0c
JSC
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
aaff8437
ILT
393/* ByteSwapMem */
394/* This is true if the host and target have different endianness. */
395#define ByteSwapMem (!(state & simHOSTBE) != !(state & simBE))
8bae0a0c
JSC
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
aaff8437
ILT
407 (!ByteSwapMem EOR ReverseEndian). */
408#define BigEndianCPU (!ByteSwapMem ^ ReverseEndian) /* Already bits */
8bae0a0c
JSC
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. */
4fa134be
ILT
414static unsigned int instruction_fetches = 0;
415static unsigned int instruction_fetch_overflow = 0;
416static unsigned int pipeline_ticks = 0;
8bae0a0c
JSC
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 */
6429b296 437#define simSIGINT (1 << 28) /* 0 = do nothing; 1 = SIGINT has occured */
aaff8437 438#define simJALDELAYSLOT (1 << 29) /* 1 = in jal delay slot */
8bae0a0c 439
4fa134be
ILT
440static unsigned int state = 0;
441static unsigned int rcexit = 0; /* _exit() reason code holder */
8bae0a0c
JSC
442
443#define DELAYSLOT() {\
f24b7b69
JSC
444 if (state & simDELAYSLOT)\
445 sim_warning("Delay slot already activated (branch in delay slot?)");\
8bae0a0c
JSC
446 state |= simDELAYSLOT;\
447 }
448
aaff8437
ILT
449#define JALDELAYSLOT() {\
450 DELAYSLOT ();\
451 state |= simJALDELAYSLOT;\
452 }
453
8bae0a0c
JSC
454#define NULLIFY() {\
455 state &= ~simDELAYSLOT;\
456 state |= simSKIPNEXT;\
457 }
458
aaff8437
ILT
459#define INDELAYSLOT() ((state & simDELAYSLOT) != 0)
460#define INJALDELAYSLOT() ((state & simJALDELAYSLOT) != 0)
461
a9f7253f
JSC
462#define K0BASE (0x80000000)
463#define K0SIZE (0x20000000)
464#define K1BASE (0xA0000000)
465#define K1SIZE (0x20000000)
466
8bae0a0c 467/* Very simple memory model to start with: */
4fa134be
ILT
468static unsigned char *membank = NULL;
469static ut_reg membank_base = K1BASE;
6429b296
JW
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. */
474static unsigned membank_size = (2 << 20);
8bae0a0c
JSC
475
476/* Simple run-time monitor support */
4fa134be
ILT
477static unsigned char *monitor = NULL;
478static ut_reg monitor_base = 0xBFC00000;
479static unsigned monitor_size = (1 << 11); /* power-of-2 */
8bae0a0c 480
f24b7b69
JSC
481static char *logfile = NULL; /* logging disabled by default */
482static FILE *logfh = NULL;
483
8bae0a0c 484#if defined(TRACE)
4fa134be
ILT
485static char *tracefile = "trace.din"; /* default filename for trace log */
486static FILE *tracefh = NULL;
6429b296 487static void open_trace PARAMS((void));
8bae0a0c
JSC
488#endif /* TRACE */
489
490#if defined(PROFILE)
4fa134be
ILT
491static unsigned profile_frequency = 256;
492static unsigned profile_nsamples = (128 << 10);
493static unsigned short *profile_hist = NULL;
494static ut_reg profile_minpc;
495static ut_reg profile_maxpc;
496static int profile_shift = 0; /* address shift amount */
8bae0a0c
JSC
497#endif /* PROFILE */
498
f7481d45
JSC
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. */
502typedef unsigned int (*fnptr_read_word) PARAMS((unsigned char *memory));
503typedef unsigned int (*fnptr_swap_word) PARAMS((unsigned int data));
504typedef uword64 (*fnptr_read_long) PARAMS((unsigned char *memory));
505typedef uword64 (*fnptr_swap_long) PARAMS((uword64 data));
506
4fa134be
ILT
507static fnptr_read_word host_read_word;
508static fnptr_read_long host_read_long;
509static fnptr_swap_word host_swap_word;
510static fnptr_swap_long host_swap_long;
f7481d45 511
8bae0a0c
JSC
512/*---------------------------------------------------------------------------*/
513/*-- GDB simulator interface ------------------------------------------------*/
514/*---------------------------------------------------------------------------*/
515
8bae0a0c
JSC
516void
517sim_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
aaff8437
ILT
542 set_endianness ();
543
8bae0a0c
JSC
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];
a9f7253f
JSC
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)) {
8bae0a0c 559 fprintf(stderr,"The host executing the simulator does not seem to have IEEE 754-1985 std FP\n");
a9f7253f
JSC
560 fprintf(stderr,"*(float *)s = %.20f (4.01102924346923828125)\n",*(float *)s);
561 fprintf(stderr,"*(double *)s = %.20f (523.2939453125)\n",*(double *)s);
8bae0a0c
JSC
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'},
f24b7b69 597 {"log", 1,0,'l'},
8bae0a0c
JSC
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\
f24b7b69 636target sim [-h] [--log=<file>] [--name=<model>] [--size=<amount>]");
8bae0a0c
JSC
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
f24b7b69
JSC
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
8bae0a0c
JSC
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,"\
676Simulator constructed without tracing support (for performance).\n\
677Re-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,"\
702Simulator constructed without profiling support (for performance).\n\
703Re-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
f24b7b69 726#if 0
8bae0a0c
JSC
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 }
f24b7b69 733#endif
8bae0a0c
JSC
734
735 freeargv(argv);
736 }
737
f24b7b69
JSC
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
8bae0a0c
JSC
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 {
e3d12c65 770 unsigned loop;
8bae0a0c
JSC
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) {
e871dd18
JSC
776 uword64 vaddr = (monitor_base + loop);
777 uword64 paddr;
8bae0a0c
JSC
778 int cca;
779 if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW))
e871dd18 780 StoreMemory(cca,AccessLength_WORD,(RSVD_INSTRUCTION | ((loop >> 2) & RSVD_INSTRUCTION_AMASK)),paddr,vaddr,isRAW);
8bae0a0c 781 }
a9f7253f
JSC
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;
280f90e1
AMT
819
820 case 11: /* flush_cache */
821 value = 28;
822 break;
a9f7253f 823 }
e3d12c65
DE
824 /* FIXME - should monitor_base be SIM_ADDR?? */
825 value = ((unsigned int)monitor_base + (value * 8));
a9f7253f
JSC
826 if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW))
827 StoreMemory(cca,AccessLength_WORD,value,paddr,vaddr,isRAW);
828 else
f24b7b69 829 sim_error("Failed to write to monitor space 0x%08X%08X",WORD64HI(vaddr),WORD64LO(vaddr));
a9f7253f 830 }
8bae0a0c
JSC
831 }
832
833#if defined(TRACE)
6429b296
JW
834 if (state & simTRACE)
835 open_trace();
8bae0a0c
JSC
836#endif /* TRACE */
837
838 return;
839}
840
6429b296
JW
841#if defined(TRACE)
842static void
843open_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
8bae0a0c
JSC
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. */
860static int
861writeout32(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) {
f24b7b69 880 sim_warning("Failed to write 4bytes to the profile file");
8bae0a0c
JSC
881 res = 0;
882 }
883 return(res);
884}
885
886static int
887writeout16(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) {
f24b7b69 901 sim_warning("Failed to write 2bytes to the profile file");
8bae0a0c
JSC
902 res = 0;
903 }
904 return(res);
905}
906
907void
908sim_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");
e3d12c65 926 unsigned loop;
8bae0a0c
JSC
927
928 if (pf == NULL)
f24b7b69 929 sim_warning("Failed to open \"gmon.out\" profile file");
8bae0a0c
JSC
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)
e3d12c65 960 if (tracefh != NULL && tracefh != stderr)
8bae0a0c 961 fclose(tracefh);
e3d12c65 962 tracefh = NULL;
8bae0a0c
JSC
963 state &= ~simTRACE;
964#endif /* TRACE */
965
f24b7b69
JSC
966 if (logfh != NULL && logfh != stdout && logfh != stderr)
967 fclose(logfh);
968 logfh = NULL;
969
8bae0a0c 970 if (membank)
d0757082 971 free(membank); /* cfree not available on all hosts */
8bae0a0c
JSC
972 membank = NULL;
973
974 return;
975}
976
977void
6429b296
JW
978control_c (sig, code, scp, addr)
979 int sig;
980 int code;
981 char *scp;
982 char *addr;
8bae0a0c 983{
6429b296
JW
984 state |= (simSTOP | simSIGINT);
985}
986
987void
988sim_resume (step,signal_number)
989 int step, signal_number;
990{
991 void (*prev) ();
992
8bae0a0c 993#ifdef DEBUG
6429b296 994 printf("DBG: sim_resume entered: step = %d, signal = %d (membank = 0x%08X)\n",step,signal_number,membank);
8bae0a0c
JSC
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
6429b296
JW
1007 prev = signal (SIGINT, control_c);
1008
8bae0a0c 1009 simulate();
6429b296
JW
1010
1011 signal (SIGINT, prev);
1012
8bae0a0c
JSC
1013 return;
1014}
1015
1016int
1017sim_write (addr,buffer,size)
1018 SIM_ADDR addr;
1019 unsigned char *buffer;
1020 int size;
1021{
1022 int index = size;
e871dd18 1023 uword64 vaddr = (uword64)addr;
8bae0a0c
JSC
1024
1025 /* Return the number of bytes written, or zero if error. */
1026#ifdef DEBUG
e871dd18 1027 callback->printf_filtered(callback,"sim_write(0x%08X%08X,buffer,%d);\n",WORD64HI(addr),WORD64LO(addr),size);
8bae0a0c
JSC
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)) {
e871dd18 1044 uword64 paddr;
8bae0a0c
JSC
1045 int cca;
1046 if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) {
e871dd18 1047 uword64 value = ((uword64)(*buffer++));
8bae0a0c
JSC
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)) {
e871dd18 1054 uword64 paddr;
8bae0a0c
JSC
1055 int cca;
1056 if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) {
e871dd18 1057 uword64 value;
8bae0a0c
JSC
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. */
aaff8437 1061 if (!ByteSwapMem) {
e871dd18
JSC
1062 value = ((uword64)(*buffer++) << 8);
1063 value |= ((uword64)(*buffer++) << 0);
8bae0a0c 1064 } else {
e871dd18
JSC
1065 value = ((uword64)(*buffer++) << 0);
1066 value |= ((uword64)(*buffer++) << 8);
8bae0a0c
JSC
1067 }
1068 StoreMemory(cca,AccessLength_HALFWORD,value,paddr,vaddr,isRAW);
1069 }
1070 vaddr += 2;
1071 index &= ~2;
1072 }
1073 if (index && (index & 4)) {
e871dd18 1074 uword64 paddr;
8bae0a0c
JSC
1075 int cca;
1076 if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) {
e871dd18 1077 uword64 value;
aaff8437 1078 if (!ByteSwapMem) {
e871dd18
JSC
1079 value = ((uword64)(*buffer++) << 24);
1080 value |= ((uword64)(*buffer++) << 16);
1081 value |= ((uword64)(*buffer++) << 8);
1082 value |= ((uword64)(*buffer++) << 0);
8bae0a0c 1083 } else {
e871dd18
JSC
1084 value = ((uword64)(*buffer++) << 0);
1085 value |= ((uword64)(*buffer++) << 8);
1086 value |= ((uword64)(*buffer++) << 16);
1087 value |= ((uword64)(*buffer++) << 24);
8bae0a0c
JSC
1088 }
1089 StoreMemory(cca,AccessLength_WORD,value,paddr,vaddr,isRAW);
1090 }
1091 vaddr += 4;
1092 index &= ~4;
1093 }
1094 for (;index; index -= 8) {
e871dd18 1095 uword64 paddr;
8bae0a0c
JSC
1096 int cca;
1097 if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) {
e871dd18 1098 uword64 value;
aaff8437 1099 if (!ByteSwapMem) {
e871dd18
JSC
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);
8bae0a0c 1108 } else {
e871dd18
JSC
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);
8bae0a0c
JSC
1117 }
1118 StoreMemory(cca,AccessLength_DOUBLEWORD,value,paddr,vaddr,isRAW);
1119 }
1120 vaddr += 8;
1121 }
1122
1123 return(size);
1124}
1125
1126int
1127sim_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
e871dd18 1136 callback->printf_filtered(callback,"sim_read(0x%08X%08X,buffer,%d);\n",WORD64HI(addr),WORD64LO(addr),size);
8bae0a0c
JSC
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++) {
e871dd18 1144 uword64 vaddr,paddr,value;
8bae0a0c 1145 int cca;
e871dd18 1146 vaddr = (uword64)addr + index;
8bae0a0c
JSC
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
1157void
1158sim_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)
f24b7b69 1170 sim_warning("Invalid register width for %d (register store ignored)",rn);
8bae0a0c
JSC
1171 else {
1172 if (register_widths[rn] == 32)
f7481d45 1173 registers[rn] = host_read_word(memory);
8bae0a0c 1174 else
f7481d45 1175 registers[rn] = host_read_long(memory);
8bae0a0c
JSC
1176 }
1177
1178 return;
1179}
1180
1181void
1182sim_fetch_register (rn,memory)
1183 int rn;
1184 unsigned char *memory;
1185{
1186#ifdef DEBUG
e871dd18 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]));
8bae0a0c
JSC
1188#endif /* DEBUG */
1189
1190 if (register_widths[rn] == 0)
f24b7b69 1191 sim_warning("Invalid register width for %d (register fetch ignored)",rn);
8bae0a0c
JSC
1192 else {
1193 if (register_widths[rn] == 32)
e3d12c65 1194 *((unsigned int *)memory) = host_swap_word((unsigned int)(registers[rn] & 0xFFFFFFFF));
8bae0a0c 1195 else /* 64bit register */
f7481d45 1196 *((uword64 *)memory) = host_swap_long(registers[rn]);
8bae0a0c
JSC
1197 }
1198 return;
1199}
1200
1201void
1202sim_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) {
f24b7b69 1258#if 0
8bae0a0c 1259 printf("DBG: simEXIT (%d)\n",rcexit);
f24b7b69 1260#endif
8bae0a0c
JSC
1261 *reason = sim_exited;
1262 *sigrc = rcexit;
6429b296
JW
1263 } else if (state & simSIGINT) {
1264 *reason = sim_stopped;
1265 *sigrc = SIGINT;
8bae0a0c
JSC
1266 } else { /* assume single-stepping */
1267 *reason = sim_stopped;
1268 *sigrc = SIGTRAP;
1269 }
6429b296 1270 state &= ~(simEXCEPTION | simEXIT | simSIGINT);
8bae0a0c
JSC
1271 return;
1272}
1273
1274void
1275sim_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
aaff8437 1282 callback->printf_filtered(callback,"%s endian memory model\n",(state & simBE ? "Big" : "Little"));
8bae0a0c 1283
e871dd18 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));
8bae0a0c
JSC
1285
1286#if !defined(FASTSIM)
a9f7253f
JSC
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);
8bae0a0c
JSC
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
1312int
1313sim_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
1322void
1323sim_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
e871dd18 1336 PC = (uword64)start_address;
8bae0a0c
JSC
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) {
f24b7b69 1345#if 0 /* def DEBUG */
8bae0a0c 1346 callback->printf_filtered(callback,"sim_create_inferior() : passed arguments ignored\n");
8bae0a0c
JSC
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
1362void
1363sim_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
e3d12c65 1378ut_reg
8bae0a0c
JSC
1379sim_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
1388void
1389sim_set_callbacks (p)
1390 host_callback *p;
1391{
1392 callback = p;
1393 return;
1394}
1395
1396typedef enum {e_terminate,e_help,e_setmemsize,e_reset} e_cmds;
1397
1398static 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
1409void
1410sim_do_command (cmd)
1411 char *cmd;
1412{
1413 struct t_sim_command *cptr;
1414
8b554809
JSC
1415 if (callback == NULL) {
1416 fprintf(stderr,"Simulator not enabled: \"target sim\" should be used to activate\n");
1417 return;
1418 }
1419
8bae0a0c
JSC
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 */
1470void
1471sim_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
1481void
1482sim_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) {
f24b7b69 1508 sim_warning("Failed to allocate VM for profiling buffer (0x%08X bytes)",bsize);
8bae0a0c
JSC
1509 state &= ~simPROFILE;
1510 }
1511 }
1512#endif /* PROFILE */
1513
1514 return;
1515}
1516
1517void
1518sim_size(newsize)
1519 unsigned int newsize;
1520{
1521 char *new;
1522 /* Used by "run", and internally, to set the simulated memory size */
f24b7b69
JSC
1523 if (newsize == 0) {
1524 callback->printf_filtered(callback,"Zero not valid: Memory size still 0x%08X bytes\n",membank_size);
1525 return;
1526 }
8bae0a0c
JSC
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)
f24b7b69 1534 sim_error("Not enough VM for simulation memory of 0x%08X bytes",membank_size);
8bae0a0c 1535 else
f24b7b69 1536 sim_warning("Failed to resize memory (still 0x%08X bytes)",membank_size);
8bae0a0c
JSC
1537 } else {
1538 membank_size = (unsigned)newsize;
1539 membank = new;
8bae0a0c
JSC
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
1549int
1550sim_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 */
6429b296
JW
1560 if (tracefh == NULL)
1561 {
1562 open_trace();
1563 state |= simTRACE;
1564 }
8bae0a0c
JSC
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
a9f7253f 1580/* Simple monitor interface (currently setup for the IDT and PMON monitors) */
8bae0a0c
JSC
1581static void
1582sim_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 {
e871dd18 1596 uword64 paddr;
8bae0a0c
JSC
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
f24b7b69 1601 sim_error("Attempt to pass pointer that does not reference simulated memory");
8bae0a0c
JSC
1602 }
1603 break;
1604
1605 case 7: /* int read(int file,char *ptr,int len) */
1606 {
e871dd18 1607 uword64 paddr;
8bae0a0c
JSC
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
f24b7b69 1612 sim_error("Attempt to pass pointer that does not reference simulated memory");
8bae0a0c
JSC
1613 }
1614 break;
1615
1616 case 8: /* int write(int file,char *ptr,int len) */
1617 {
e871dd18 1618 uword64 paddr;
8bae0a0c
JSC
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
f24b7b69 1623 sim_error("Attempt to pass pointer that does not reference simulated memory");
8bae0a0c
JSC
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)) {
f24b7b69 1635 sim_error("Invalid return from character read");
e3d12c65 1636 V0 = (ut_reg)-1;
8bae0a0c
JSC
1637 }
1638 else
e3d12c65 1639 V0 = (ut_reg)tmp;
8bae0a0c
JSC
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() */
f24b7b69 1651 sim_warning("sim_monitor(17): _exit(int reason) to be coded");
8bae0a0c
JSC
1652 state |= (simSTOP | simEXIT); /* stop executing code */
1653 rcexit = (unsigned int)(A0 & 0xFFFFFFFF);
1654 break;
1655
280f90e1
AMT
1656 case 28 : /* PMON flush_cache */
1657 break;
1658
8bae0a0c
JSC
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 {
e871dd18
JSC
1665 uword64 vaddr = A0;
1666 uword64 paddr, value;
8bae0a0c
JSC
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)) {
e871dd18 1676 value = (uword64)membank_size;
8bae0a0c
JSC
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)
f24b7b69 1695 sim_error("Invalid pointer passed into monitor call");
8bae0a0c
JSC
1696 }
1697 break;
1698
a9f7253f
JSC
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 */
f24b7b69 1705 /* The following is based on the PMON printf source */
a9f7253f
JSC
1706 {
1707 uword64 paddr;
1708 int cca;
f24b7b69
JSC
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)) {
e3d12c65 1777 word64 lv = (word64) *ap++;
f24b7b69
JSC
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)) {
e3d12c65
DE
1788#ifdef _MSC_VER /* MSVC version 2.x can't convert from uword64 directly */
1789 double dbl = (double)((word64)*ap++);
1790#else
f24b7b69 1791 double dbl = (double)*ap++;
e3d12c65 1792#endif
f24b7b69
JSC
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");
a9f7253f
JSC
1804 }
1805 break;
1806
8bae0a0c 1807 default:
f24b7b69
JSC
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));
8bae0a0c
JSC
1810 break;
1811 }
1812 return;
1813}
1814
f24b7b69 1815void
e3d12c65 1816sim_warning(char *fmt,...)
f24b7b69 1817{
6429b296 1818 char buf[256];
f24b7b69 1819 va_list ap;
6429b296
JW
1820
1821 va_start (ap,fmt);
1822 vsprintf (buf, fmt, ap);
1823 va_end (ap);
1824
f24b7b69 1825 if (logfh != NULL) {
6429b296
JW
1826 fprintf(logfh,"SIM Warning: %s\n", buf);
1827 } else {
1828 callback->printf_filtered(callback,"SIM Warning: %s\n", buf);
f24b7b69 1829 }
6429b296
JW
1830 /* This used to call SignalException with a SimulatorFault, but that causes
1831 the simulator to exit, and that is inappropriate for a warning. */
f24b7b69
JSC
1832 return;
1833}
1834
8bae0a0c 1835void
e3d12c65 1836sim_error(char *fmt,...)
8bae0a0c 1837{
6429b296 1838 char buf[256];
8bae0a0c 1839 va_list ap;
6429b296
JW
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);
8bae0a0c
JSC
1847 return;
1848}
1849
1850static unsigned int
1851power2(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
1866static long
1867getnum(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
e3d12c65 1929
8bae0a0c 1930static
e3d12c65 1931void dotrace(FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...)
8bae0a0c
JSC
1932{
1933 if (state & simTRACE) {
1934 va_list ap;
e3d12c65 1935 fprintf(tracefh,"%d %08x%08x ; width %d ; ",
6429b296
JW
1936 type,
1937 sizeof (address) > 4 ? (unsigned long)(address>>32) : 0,
1938 (unsigned long)(address&0xffffffff),width);
8bae0a0c 1939 va_start(ap,comment);
6429b296 1940 vfprintf(tracefh,comment,ap);
8bae0a0c
JSC
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
f7481d45
JSC
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
1968static unsigned int
e3d12c65 1969xfer_direct_word(unsigned char *memory)
f7481d45
JSC
1970{
1971 return *((unsigned int *)memory);
1972}
1973
1974static uword64
e3d12c65 1975xfer_direct_long(unsigned char *memory)
f7481d45
JSC
1976{
1977 return *((uword64 *)memory);
1978}
1979
1980static unsigned int
e3d12c65 1981swap_direct_word(unsigned int data)
f7481d45
JSC
1982{
1983 return data;
1984}
1985
1986static uword64
e3d12c65 1987swap_direct_long(uword64 data)
f7481d45
JSC
1988{
1989 return data;
1990}
1991
1992static unsigned int
e3d12c65 1993xfer_big_word(unsigned char *memory)
f7481d45
JSC
1994{
1995 return ((memory[0] << 24) | (memory[1] << 16) | (memory[2] << 8) | memory[3]);
1996}
1997
1998static uword64
e3d12c65 1999xfer_big_long(unsigned char *memory)
f7481d45
JSC
2000{
2001 return (((uword64)memory[0] << 56) | ((uword64)memory[1] << 48)
2002 | ((uword64)memory[2] << 40) | ((uword64)memory[3] << 32)
e3d12c65
DE
2003 | ((uword64)memory[4] << 24) | ((uword64)memory[5] << 16)
2004 | ((uword64)memory[6] << 8) | ((uword64)memory[7]));
f7481d45
JSC
2005}
2006
2007static unsigned int
e3d12c65 2008xfer_little_word(unsigned char *memory)
f7481d45
JSC
2009{
2010 return ((memory[3] << 24) | (memory[2] << 16) | (memory[1] << 8) | memory[0]);
2011}
2012
2013static uword64
e3d12c65 2014xfer_little_long(unsigned char *memory)
f7481d45
JSC
2015{
2016 return (((uword64)memory[7] << 56) | ((uword64)memory[6] << 48)
2017 | ((uword64)memory[5] << 40) | ((uword64)memory[4] << 32)
e3d12c65
DE
2018 | ((uword64)memory[3] << 24) | ((uword64)memory[2] << 16)
2019 | ((uword64)memory[1] << 8) | (uword64)memory[0]);
f7481d45
JSC
2020}
2021
2022static unsigned int
e3d12c65 2023swap_word(unsigned int data)
f7481d45
JSC
2024{
2025 unsigned int result;
aaff8437
ILT
2026 result = (((data & 0xff) << 24) | ((data & 0xff00) << 8)
2027 | ((data >> 8) & 0xff00) | ((data >> 24) & 0xff));
2028 return result;
f7481d45
JSC
2029}
2030
2031static uword64
e3d12c65 2032swap_long(uword64 data)
f7481d45
JSC
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
8bae0a0c
JSC
2042/*---------------------------------------------------------------------------*/
2043/*-- simulator engine -------------------------------------------------------*/
2044/*---------------------------------------------------------------------------*/
2045
aaff8437
ILT
2046static void
2047set_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
8bae0a0c
JSC
2076static void
2077ColdReset()
2078{
2079 /* RESET: Fixed PC address: */
e871dd18 2080 PC = (((uword64)0xFFFFFFFF<<32) | 0xBFC00000);
8bae0a0c
JSC
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);
8bae0a0c
JSC
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
2130static int
2131AddressTranslation(vAddr,IorD,LorS,pAddr,CCA,host,raw)
e871dd18 2132 uword64 vAddr;
8bae0a0c
JSC
2133 int IorD;
2134 int LorS;
e871dd18 2135 uword64 *pAddr;
8bae0a0c
JSC
2136 int *CCA;
2137 int host;
2138 int raw;
2139{
2140 int res = -1; /* TRUE : Assume good return */
2141
2142#ifdef DEBUG
e871dd18 2143 callback->printf_filtered(callback,"AddressTranslation(0x%08X%08X,%s,%s,...);\n",WORD64HI(vAddr),WORD64LO(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "iSTORE" : "isLOAD"));
8bae0a0c
JSC
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;
a9f7253f
JSC
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
8bae0a0c
JSC
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 {
6429b296 2177#ifdef DEBUG
f24b7b69 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));
8bae0a0c
JSC
2179#endif /* DEBUG */
2180 res = 0; /* AddressTranslation has failed */
e3d12c65 2181 *pAddr = (SIM_ADDR)-1;
8bae0a0c
JSC
2182 if (!raw) /* only generate exceptions on real memory transfers */
2183 SignalException((LorS == isSTORE) ? AddressStore : AddressLoad);
6429b296 2184#ifdef DEBUG
8bae0a0c 2185 else
6429b296
JW
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. */
f24b7b69 2190 sim_warning("AddressTranslation for %s %s from 0x%08X%08X failed",(IorD ? "data" : "instruction"),(LorS ? "store" : "load"),WORD64HI(vAddr),WORD64LO(vAddr));
6429b296 2191#endif
8bae0a0c
JSC
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. */
2202static void
2203Prefetch(CCA,pAddr,vAddr,DATA,hint)
2204 int CCA;
e871dd18
JSC
2205 uword64 pAddr;
2206 uword64 vAddr;
8bae0a0c
JSC
2207 int DATA;
2208 int hint;
2209{
2210#ifdef DEBUG
e871dd18 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);
8bae0a0c
JSC
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. */
e871dd18 2233static uword64
8bae0a0c
JSC
2234LoadMemory(CCA,AccessLength,pAddr,vAddr,IorD,raw)
2235 int CCA;
2236 int AccessLength;
e871dd18
JSC
2237 uword64 pAddr;
2238 uword64 vAddr;
8bae0a0c
JSC
2239 int IorD;
2240 int raw;
2241{
e871dd18 2242 uword64 value;
8bae0a0c
JSC
2243
2244#ifdef DEBUG
2245 if (membank == NULL)
e871dd18 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"));
8bae0a0c
JSC
2247#endif /* DEBUG */
2248
2249#if defined(WARN_MEM)
2250 if (CCA != uncached)
f24b7b69 2251 sim_warning("LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)",CCA);
8bae0a0c
JSC
2252
2253 if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK) {
2254 /* In reality this should be a Bus Error */
f24b7b69 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));
8bae0a0c
JSC
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: */
6429b296
JW
2268 if ((IorD == isINSTRUCTION)
2269 && ((pAddr & 0x3) != 0)
2270 && (((pAddr & 0x1) != 0) || ((vAddr & 0x1) == 0)))
8bae0a0c
JSC
2271 SignalException(InstructionFetch);
2272 else {
2273 unsigned int index;
2274 unsigned char *mem = NULL;
2275
8bae0a0c
JSC
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)
e871dd18 2292 sim_error("Simulator memory not found for physical address 0x%08X%08X\n",WORD64HI(pAddr),WORD64LO(pAddr));
8bae0a0c
JSC
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. */
aaff8437 2306 if (!ByteSwapMem)
8bae0a0c
JSC
2307 switch (AccessLength) { /* big-endian memory */
2308 case AccessLength_DOUBLEWORD :
e871dd18 2309 value |= ((uword64)mem[index++] << 56);
8bae0a0c 2310 case AccessLength_SEPTIBYTE :
e871dd18 2311 value |= ((uword64)mem[index++] << 48);
8bae0a0c 2312 case AccessLength_SEXTIBYTE :
e871dd18 2313 value |= ((uword64)mem[index++] << 40);
8bae0a0c 2314 case AccessLength_QUINTIBYTE :
e871dd18 2315 value |= ((uword64)mem[index++] << 32);
8bae0a0c
JSC
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 :
e871dd18 2330 value |= ((uword64)mem[--index] << 56);
8bae0a0c 2331 case AccessLength_SEPTIBYTE :
e871dd18 2332 value |= ((uword64)mem[--index] << 48);
8bae0a0c 2333 case AccessLength_SEXTIBYTE :
e871dd18 2334 value |= ((uword64)mem[--index] << 40);
8bae0a0c 2335 case AccessLength_QUINTIBYTE :
e871dd18 2336 value |= ((uword64)mem[--index] << 32);
8bae0a0c 2337 case AccessLength_WORD :
e871dd18 2338 value |= ((uword64)mem[--index] << 24);
8bae0a0c 2339 case AccessLength_TRIPLEBYTE :
e871dd18 2340 value |= ((uword64)mem[--index] << 16);
8bae0a0c 2341 case AccessLength_HALFWORD :
e871dd18 2342 value |= ((uword64)mem[--index] << 8);
8bae0a0c 2343 case AccessLength_BYTE :
e871dd18 2344 value |= ((uword64)mem[--index] << 0);
8bae0a0c
JSC
2345 break;
2346 }
2347 }
2348
2349#ifdef DEBUG
e871dd18 2350 printf("DBG: LoadMemory() : (offset %d) : value = 0x%08X%08X\n",(int)(pAddr & LOADDRMASK),WORD64HI(value),WORD64LO(value));
8bae0a0c
JSC
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 */
aaff8437 2358 if (!ByteSwapMem)
8bae0a0c
JSC
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
e871dd18
JSC
2365 printf("DBG: LoadMemory() : shifted value = 0x%08X%08X\n",WORD64HI(value),WORD64LO(value));
2366#endif /* DEBUG */
8bae0a0c
JSC
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. */
2384static void
2385StoreMemory(CCA,AccessLength,MemElem,pAddr,vAddr,raw)
2386 int CCA;
2387 int AccessLength;
e871dd18
JSC
2388 uword64 MemElem;
2389 uword64 pAddr;
2390 uword64 vAddr;
8bae0a0c
JSC
2391 int raw;
2392{
2393#ifdef DEBUG
e871dd18 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"));
8bae0a0c
JSC
2395#endif /* DEBUG */
2396
2397#if defined(WARN_MEM)
2398 if (CCA != uncached)
f24b7b69 2399 sim_warning("StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)",CCA);
8bae0a0c
JSC
2400
2401 if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
f24b7b69 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));
8bae0a0c
JSC
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)
e871dd18 2428 sim_error("Simulator memory not found for physical address 0x%08X%08X\n",WORD64HI(pAddr),WORD64LO(pAddr));
8bae0a0c
JSC
2429 else {
2430 int shift = 0;
2431
2432#ifdef DEBUG
e871dd18 2433 printf("DBG: StoreMemory: offset = %d MemElem = 0x%08X%08X\n",(unsigned int)(pAddr & LOADDRMASK),WORD64HI(MemElem),WORD64LO(MemElem));
8bae0a0c
JSC
2434#endif /* DEBUG */
2435
aaff8437 2436 if (!ByteSwapMem) {
8bae0a0c
JSC
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
e871dd18 2449 printf("DBG: StoreMemory: shift = %d MemElem = 0x%08X%08X\n",shift,WORD64HI(MemElem),WORD64LO(MemElem));
8bae0a0c
JSC
2450#endif /* DEBUG */
2451
aaff8437 2452 if (!ByteSwapMem) {
8bae0a0c
JSC
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. */
2512static void
2513SyncOperation(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. */
2526static void
e3d12c65 2527SignalException (int exception,...)
8bae0a0c
JSC
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 :
f24b7b69 2537 sim_warning("Ignoring instruction TRAP (PC 0x%08X%08X)",WORD64HI(IPC),WORD64LO(IPC));
8bae0a0c
JSC
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 */
f24b7b69 2564 sim_warning("ReservedInstruction 0x%08X at IPC = 0x%08X%08X",instruction,WORD64HI(IPC),WORD64LO(IPC));
8bae0a0c
JSC
2565 }
2566
2567 default:
e3d12c65 2568#ifdef DEBUG
f24b7b69
JSC
2569 if (exception != BreakPoint)
2570 callback->printf_filtered(callback,"DBG: SignalException(%d) IPC = 0x%08X%08X\n",exception,WORD64HI(IPC),WORD64LO(IPC));
8bae0a0c
JSC
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);
e3d12c65
DE
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): */
8bae0a0c
JSC
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. */
2632static void
2633UndefinedResult()
2634{
f24b7b69 2635 sim_warning("UndefinedResult: IPC = 0x%08X%08X",WORD64HI(IPC),WORD64LO(IPC));
8bae0a0c
JSC
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
2643static void
2644CacheOp(op,pAddr,vAddr,instruction)
2645 int op;
e871dd18
JSC
2646 uword64 pAddr;
2647 uword64 vAddr;
8bae0a0c
JSC
2648 unsigned int instruction;
2649{
f24b7b69
JSC
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
a9f7253f
JSC
2654 static int icache_warning = 0;
2655 static int dcache_warning = 0;
f24b7b69 2656#endif
a9f7253f 2657
8bae0a0c
JSC
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. */
a9f7253f 2661#if 0
e871dd18 2662 callback->printf_filtered(callback,"TODO: Cache availability checking (PC = 0x%08X%08X)\n",WORD64HI(IPC),WORD64LO(IPC));
a9f7253f 2663#endif
8bae0a0c
JSC
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 */
a9f7253f
JSC
2674 if (!icache_warning)
2675 {
f24b7b69 2676 sim_warning("Instruction CACHE operation %d to be coded",(op >> 2));
a9f7253f
JSC
2677 icache_warning = 1;
2678 }
8bae0a0c
JSC
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 */
a9f7253f
JSC
2696 if (!dcache_warning)
2697 {
f24b7b69 2698 sim_warning("Data CACHE operation %d to be coded",(op >> 2));
a9f7253f
JSC
2699 dcache_warning = 1;
2700 }
8bae0a0c
JSC
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)
e871dd18 2755#define FP_D_s(v) (((v) & ((uword64)1 << 63)) ? 1 : 0)
8bae0a0c
JSC
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))
e871dd18 2764#define FP_D_f(v) ((v) & ~((uword64)0xFFF << 52))
8bae0a0c
JSC
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)
e871dd18
JSC
2772#define FPQNaN_DOUBLE (((uword64)0x7FF7FFFF << 32) | 0xFFFFFFFF)
2773#define FPQNaN_LONG (((uword64)0x7FFFFFFF << 32) | 0xFFFFFFFF)
8bae0a0c
JSC
2774
2775/* Explicit Infinity values used when required: */
2776#define FPINF_SINGLE (0x7F800000)
e871dd18 2777#define FPINF_DOUBLE (((uword64)0x7FF00000 << 32) | 0x00000000)
8bae0a0c
JSC
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
e871dd18 2784static uword64
8bae0a0c
JSC
2785ValueFPR(fpr,fmt)
2786 int fpr;
2787 FP_formats fmt;
2788{
e871dd18 2789 uword64 value;
8bae0a0c
JSC
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]) {
f24b7b69 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));
8bae0a0c
JSC
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:
f24b7b69 2864 value = ((((uword64)FGR[fpr+1]) << 32) | (FGR[fpr] & 0xFFFFFFFF));
8bae0a0c
JSC
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
e871dd18 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());
8bae0a0c
JSC
2878#endif /* DEBUG */
2879
2880 return(value);
2881}
2882
2883static void
2884StoreFPR(fpr,fmt,value)
2885 int fpr;
2886 FP_formats fmt;
e871dd18 2887 uword64 value;
8bae0a0c
JSC
2888{
2889 int err = 0;
2890
2891#ifdef DEBUG
e871dd18 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());
8bae0a0c
JSC
2893#endif /* DEBUG */
2894
2895 if (SizeFGR() == 64) {
2896 switch (fmt) {
2897 case fmt_single :
2898 case fmt_word :
e871dd18 2899 FGR[fpr] = (((uword64)0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
8bae0a0c
JSC
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 }
e871dd18
JSC
2939 }
2940#if defined(WARN_RESULT)
2941 else
2942 UndefinedResult();
2943#endif /* WARN_RESULT */
8bae0a0c
JSC
2944
2945 if (err)
2946 SignalException(SimulatorFault,"Unrecognised FP format in StoreFPR()");
2947
2948#ifdef DEBUG
e871dd18 2949 printf("DBG: StoreFPR: fpr[%d] = 0x%08X%08X (format %s)\n",fpr,WORD64HI(FGR[fpr]),WORD64LO(FGR[fpr]),DOFMT(fmt));
8bae0a0c
JSC
2950#endif /* DEBUG */
2951
2952 return;
2953}
2954
2955static int
2956NaN(op,fmt)
e871dd18 2957 uword64 op;
8bae0a0c
JSC
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
e871dd18 2985printf("DBG: NaN: returning %d for 0x%08X%08X (format = %s)\n",boolean,WORD64HI(op),WORD64LO(op),DOFMT(fmt));
8bae0a0c
JSC
2986#endif /* DEBUG */
2987
2988 return(boolean);
2989}
2990
2991static int
2992Infinity(op,fmt)
e871dd18 2993 uword64 op;
8bae0a0c
JSC
2994 FP_formats fmt;
2995{
2996 int boolean = 0;
2997
2998#ifdef DEBUG
e871dd18 2999 printf("DBG: Infinity: format %s 0x%08X%08X (PC = 0x%08X%08X)\n",DOFMT(fmt),WORD64HI(op),WORD64LO(op),WORD64HI(IPC),WORD64LO(IPC));
8bae0a0c
JSC
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
e871dd18 3018 printf("DBG: Infinity: returning %d for 0x%08X%08X (format = %s)\n",boolean,WORD64HI(op),WORD64LO(op),DOFMT(fmt));
8bae0a0c
JSC
3019#endif /* DEBUG */
3020
3021 return(boolean);
3022}
3023
3024static int
3025Less(op1,op2,fmt)
e871dd18
JSC
3026 uword64 op1;
3027 uword64 op2;
8bae0a0c
JSC
3028 FP_formats fmt;
3029{
3030 int boolean = 0;
3031
e871dd18
JSC
3032 /* Argument checking already performed by the FPCOMPARE code */
3033
8bae0a0c 3034#ifdef DEBUG
e871dd18 3035 printf("DBG: Less: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op1),WORD64LO(op1),WORD64HI(op2),WORD64LO(op2));
8bae0a0c
JSC
3036#endif /* DEBUG */
3037
8bae0a0c
JSC
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
3059static int
3060Equal(op1,op2,fmt)
e871dd18
JSC
3061 uword64 op1;
3062 uword64 op2;
8bae0a0c
JSC
3063 FP_formats fmt;
3064{
3065 int boolean = 0;
3066
e871dd18
JSC
3067 /* Argument checking already performed by the FPCOMPARE code */
3068
8bae0a0c 3069#ifdef DEBUG
e871dd18 3070 printf("DBG: Equal: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op1),WORD64LO(op1),WORD64HI(op2),WORD64LO(op2));
8bae0a0c
JSC
3071#endif /* DEBUG */
3072
8bae0a0c
JSC
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
a9f7253f
JSC
3090static uword64
3091AbsoluteValue(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
e871dd18 3120static uword64
8bae0a0c 3121Negate(op,fmt)
e871dd18 3122 uword64 op;
8bae0a0c
JSC
3123 FP_formats fmt;
3124{
e871dd18 3125 uword64 result;
8bae0a0c
JSC
3126
3127#ifdef DEBUG
e871dd18 3128 printf("DBG: Negate: %s: op = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op),WORD64LO(op));
8bae0a0c
JSC
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);
e871dd18 3137 result = (uword64)*(unsigned int *)&tmp;
8bae0a0c
JSC
3138 }
3139 break;
3140 case fmt_double:
3141 {
3142 double tmp = ((double)0.0 - *(double *)&op);
e871dd18 3143 result = *(uword64 *)&tmp;
8bae0a0c
JSC
3144 }
3145 break;
3146 }
3147
3148 return(result);
3149}
3150
e871dd18 3151static uword64
8bae0a0c 3152Add(op1,op2,fmt)
e871dd18
JSC
3153 uword64 op1;
3154 uword64 op2;
8bae0a0c
JSC
3155 FP_formats fmt;
3156{
e871dd18 3157 uword64 result;
8bae0a0c
JSC
3158
3159#ifdef DEBUG
e871dd18 3160 printf("DBG: Add: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op1),WORD64LO(op1),WORD64HI(op2),WORD64LO(op2));
8bae0a0c
JSC
3161#endif /* DEBUG */
3162
e871dd18
JSC
3163 /* The registers must specify FPRs valid for operands of type
3164 "fmt". If they are not valid, the result is undefined. */
8bae0a0c
JSC
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);
e871dd18 3173 result = (uword64)*(unsigned int *)&tmp;
8bae0a0c
JSC
3174 }
3175 break;
3176 case fmt_double:
3177 {
3178 double tmp = (*(double *)&op1 + *(double *)&op2);
e871dd18 3179 result = *(uword64 *)&tmp;
8bae0a0c
JSC
3180 }
3181 break;
3182 }
3183
3184#ifdef DEBUG
e871dd18 3185 printf("DBG: Add: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
8bae0a0c
JSC
3186#endif /* DEBUG */
3187
3188 return(result);
3189}
3190
e871dd18 3191static uword64
8bae0a0c 3192Sub(op1,op2,fmt)
e871dd18
JSC
3193 uword64 op1;
3194 uword64 op2;
8bae0a0c
JSC
3195 FP_formats fmt;
3196{
e871dd18 3197 uword64 result;
8bae0a0c
JSC
3198
3199#ifdef DEBUG
a9f7253f 3200 printf("DBG: Sub: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op1),WORD64LO(op1),WORD64HI(op2),WORD64LO(op2));
8bae0a0c
JSC
3201#endif /* DEBUG */
3202
e871dd18
JSC
3203 /* The registers must specify FPRs valid for operands of type
3204 "fmt". If they are not valid, the result is undefined. */
8bae0a0c
JSC
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);
e871dd18 3213 result = (uword64)*(unsigned int *)&tmp;
8bae0a0c
JSC
3214 }
3215 break;
3216 case fmt_double:
3217 {
3218 double tmp = (*(double *)&op1 - *(double *)&op2);
e871dd18 3219 result = *(uword64 *)&tmp;
8bae0a0c
JSC
3220 }
3221 break;
3222 }
3223
3224#ifdef DEBUG
e871dd18 3225 printf("DBG: Sub: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
8bae0a0c
JSC
3226#endif /* DEBUG */
3227
3228 return(result);
3229}
3230
e871dd18 3231static uword64
8bae0a0c 3232Multiply(op1,op2,fmt)
e871dd18
JSC
3233 uword64 op1;
3234 uword64 op2;
8bae0a0c
JSC
3235 FP_formats fmt;
3236{
e871dd18 3237 uword64 result;
8bae0a0c
JSC
3238
3239#ifdef DEBUG
e871dd18 3240 printf("DBG: Multiply: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op1),WORD64LO(op1),WORD64HI(op2),WORD64LO(op2));
8bae0a0c
JSC
3241#endif /* DEBUG */
3242
e871dd18
JSC
3243 /* The registers must specify FPRs valid for operands of type
3244 "fmt". If they are not valid, the result is undefined. */
8bae0a0c
JSC
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);
e871dd18 3253 result = (uword64)*(unsigned int *)&tmp;
8bae0a0c
JSC
3254 }
3255 break;
3256 case fmt_double:
3257 {
3258 double tmp = (*(double *)&op1 * *(double *)&op2);
e871dd18 3259 result = *(uword64 *)&tmp;
8bae0a0c
JSC
3260 }
3261 break;
3262 }
3263
3264#ifdef DEBUG
e871dd18 3265 printf("DBG: Multiply: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
8bae0a0c
JSC
3266#endif /* DEBUG */
3267
3268 return(result);
3269}
3270
e871dd18 3271static uword64
8bae0a0c 3272Divide(op1,op2,fmt)
e871dd18
JSC
3273 uword64 op1;
3274 uword64 op2;
8bae0a0c
JSC
3275 FP_formats fmt;
3276{
e871dd18 3277 uword64 result;
8bae0a0c
JSC
3278
3279#ifdef DEBUG
e871dd18 3280 printf("DBG: Divide: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op1),WORD64LO(op1),WORD64HI(op2),WORD64LO(op2));
8bae0a0c
JSC
3281#endif /* DEBUG */
3282
e871dd18
JSC
3283 /* The registers must specify FPRs valid for operands of type
3284 "fmt". If they are not valid, the result is undefined. */
8bae0a0c
JSC
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);
e871dd18 3293 result = (uword64)*(unsigned int *)&tmp;
8bae0a0c
JSC
3294 }
3295 break;
3296 case fmt_double:
3297 {
3298 double tmp = (*(double *)&op1 / *(double *)&op2);
e871dd18 3299 result = *(uword64 *)&tmp;
8bae0a0c
JSC
3300 }
3301 break;
3302 }
3303
3304#ifdef DEBUG
e871dd18 3305 printf("DBG: Divide: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
8bae0a0c
JSC
3306#endif /* DEBUG */
3307
3308 return(result);
3309}
3310
e871dd18 3311static uword64
8bae0a0c 3312Recip(op,fmt)
e871dd18 3313 uword64 op;
8bae0a0c
JSC
3314 FP_formats fmt;
3315{
e871dd18 3316 uword64 result;
8bae0a0c
JSC
3317
3318#ifdef DEBUG
e871dd18 3319 printf("DBG: Recip: %s: op = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op),WORD64LO(op));
8bae0a0c
JSC
3320#endif /* DEBUG */
3321
e871dd18
JSC
3322 /* The registers must specify FPRs valid for operands of type
3323 "fmt". If they are not valid, the result is undefined. */
8bae0a0c
JSC
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);
e871dd18 3331 result = (uword64)*(unsigned int *)&tmp;
8bae0a0c
JSC
3332 }
3333 break;
3334 case fmt_double:
3335 {
3336 double tmp = ((double)1.0 / *(double *)&op);
e871dd18 3337 result = *(uword64 *)&tmp;
8bae0a0c
JSC
3338 }
3339 break;
3340 }
3341
3342#ifdef DEBUG
e871dd18 3343 printf("DBG: Recip: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
8bae0a0c
JSC
3344#endif /* DEBUG */
3345
3346 return(result);
3347}
3348
e871dd18 3349static uword64
8bae0a0c 3350SquareRoot(op,fmt)
e871dd18 3351 uword64 op;
8bae0a0c
JSC
3352 FP_formats fmt;
3353{
e871dd18 3354 uword64 result;
8bae0a0c
JSC
3355
3356#ifdef DEBUG
e871dd18 3357 printf("DBG: SquareRoot: %s: op = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op),WORD64LO(op));
8bae0a0c
JSC
3358#endif /* DEBUG */
3359
e871dd18
JSC
3360 /* The registers must specify FPRs valid for operands of type
3361 "fmt". If they are not valid, the result is undefined. */
8bae0a0c
JSC
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;
e3d12c65 3368#ifdef HAVE_SQRT
8bae0a0c 3369 float tmp = ((float)sqrt((double)*(float *)&wop));
e871dd18 3370 result = (uword64)*(unsigned int *)&tmp;
e3d12c65
DE
3371#else
3372 /* TODO: Provide square-root */
3373 result = (uword64)0;
3374#endif
8bae0a0c
JSC
3375 }
3376 break;
3377 case fmt_double:
3378 {
e3d12c65 3379#ifdef HAVE_SQRT
8bae0a0c 3380 double tmp = (sqrt(*(double *)&op));
e871dd18 3381 result = *(uword64 *)&tmp;
e3d12c65
DE
3382#else
3383 /* TODO: Provide square-root */
3384 result = (uword64)0;
3385#endif
8bae0a0c
JSC
3386 }
3387 break;
3388 }
3389
3390#ifdef DEBUG
e871dd18 3391 printf("DBG: SquareRoot: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
8bae0a0c
JSC
3392#endif /* DEBUG */
3393
3394 return(result);
3395}
3396
e871dd18 3397static uword64
8bae0a0c
JSC
3398Convert(rm,op,from,to)
3399 int rm;
e871dd18 3400 uword64 op;
8bae0a0c
JSC
3401 FP_formats from;
3402 FP_formats to;
3403{
e871dd18 3404 uword64 result;
8bae0a0c
JSC
3405
3406#ifdef DEBUG
e871dd18 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));
8bae0a0c
JSC
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:
e3d12c65 3429 tmp = (float)((word64)op);
8bae0a0c
JSC
3430 break;
3431 }
3432
458e1f58
ILT
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
8bae0a0c
JSC
3438 switch (rm) {
3439 case FP_RM_NEAREST:
e871dd18
JSC
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). */
4fa134be 3443#ifdef HAVE_ANINT
e871dd18 3444 tmp = (float)anint((double)tmp);
d0757082
JSC
3445#else
3446 /* TODO: Provide round-to-nearest */
3447#endif
8bae0a0c
JSC
3448 break;
3449
3450 case FP_RM_TOZERO:
e871dd18
JSC
3451 /* Round result to the value closest to, and not greater in
3452 magnitude than, the result. */
4fa134be 3453#ifdef HAVE_AINT
e871dd18 3454 tmp = (float)aint((double)tmp);
d0757082
JSC
3455#else
3456 /* TODO: Provide round-to-zero */
3457#endif
8bae0a0c
JSC
3458 break;
3459
3460 case FP_RM_TOPINF:
e871dd18
JSC
3461 /* Round result to the value closest to, and not less than,
3462 the result. */
3463 tmp = (float)ceil((double)tmp);
8bae0a0c
JSC
3464 break;
3465
3466 case FP_RM_TOMINF:
e871dd18
JSC
3467 /* Round result to the value closest to, and not greater than,
3468 the result. */
3469 tmp = (float)floor((double)tmp);
8bae0a0c
JSC
3470 break;
3471 }
458e1f58
ILT
3472#endif /* 0 */
3473
e871dd18 3474 result = (uword64)*(unsigned int *)&tmp;
8bae0a0c
JSC
3475 }
3476 break;
3477
3478 case fmt_double:
3479 {
3480 double tmp;
f24b7b69 3481 word64 xxx;
8bae0a0c
JSC
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:
f24b7b69 3492 xxx = SIGNEXTEND((op & 0xFFFFFFFF),32);
e3d12c65 3493 tmp = (double)xxx;
8bae0a0c
JSC
3494 break;
3495
3496 case fmt_long:
e871dd18 3497 tmp = (double)((word64)op);
8bae0a0c
JSC
3498 break;
3499 }
e871dd18 3500
458e1f58
ILT
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
8bae0a0c
JSC
3506 switch (rm) {
3507 case FP_RM_NEAREST:
4fa134be 3508#ifdef HAVE_ANINT
e871dd18 3509 tmp = anint(*(double *)&tmp);
d0757082
JSC
3510#else
3511 /* TODO: Provide round-to-nearest */
3512#endif
8bae0a0c
JSC
3513 break;
3514
3515 case FP_RM_TOZERO:
4fa134be 3516#ifdef HAVE_AINT
e871dd18 3517 tmp = aint(*(double *)&tmp);
d0757082
JSC
3518#else
3519 /* TODO: Provide round-to-zero */
3520#endif
8bae0a0c
JSC
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 }
458e1f58
ILT
3531#endif /* 0 */
3532
e871dd18 3533 result = *(uword64 *)&tmp;
8bae0a0c
JSC
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) {
e3d12c65 3544 int tmp;
8bae0a0c
JSC
3545 switch (from) {
3546 case fmt_single:
3547 {
3548 unsigned int wop = (unsigned int)op;
e3d12c65 3549 tmp = (int)*((float *)&wop);
8bae0a0c
JSC
3550 }
3551 break;
3552 case fmt_double:
e3d12c65 3553 tmp = (int)*((double *)&op);
8bae0a0c 3554#ifdef DEBUG
e871dd18 3555 printf("DBG: from double %.30f (0x%08X%08X) to word: 0x%08X\n",*((double *)&op),WORD64HI(op),WORD64LO(op),tmp);
8bae0a0c
JSC
3556#endif /* DEBUG */
3557 break;
3558 }
e871dd18 3559 result = (uword64)tmp;
8bae0a0c 3560 } else { /* fmt_long */
e3d12c65 3561 word64 tmp;
8bae0a0c
JSC
3562 switch (from) {
3563 case fmt_single:
3564 {
3565 unsigned int wop = (unsigned int)op;
e3d12c65 3566 tmp = (word64)*((float *)&wop);
8bae0a0c
JSC
3567 }
3568 break;
3569 case fmt_double:
e3d12c65 3570 tmp = (word64)*((double *)&op);
8bae0a0c
JSC
3571 break;
3572 }
e3d12c65 3573 result = (uword64)tmp;
8bae0a0c
JSC
3574 }
3575 }
3576 break;
3577 }
3578
3579#ifdef DEBUG
e871dd18 3580 printf("DBG: Convert: returning 0x%08X%08X (to format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(to));
8bae0a0c
JSC
3581#endif /* DEBUG */
3582
3583 return(result);
3584}
3585#endif /* HASFPU */
3586
3587/*-- co-processor support routines ------------------------------------------*/
3588
3589static int
3590CoProcPresent(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
3597static void
3598COP_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
e871dd18 3606 printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%08X%08X\n",memword,WORD64HI(memword),WORD64LO(memword));
8bae0a0c 3607#endif
e871dd18 3608 StoreFPR(coproc_reg,fmt_uninterpreted,(uword64)memword);
8bae0a0c
JSC
3609 break;
3610#endif /* HASFPU */
3611
3612 default:
f24b7b69 3613#if 0 /* this should be controlled by a configuration option */
e871dd18 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));
f24b7b69 3615#endif
8bae0a0c
JSC
3616 break;
3617 }
3618
3619 return;
3620}
3621
3622static void
3623COP_LD(coproc_num,coproc_reg,memword)
3624 int coproc_num, coproc_reg;
e871dd18 3625 uword64 memword;
8bae0a0c
JSC
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:
f24b7b69 3635#if 0 /* this message should be controlled by a configuration option */
e871dd18 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));
f24b7b69 3637#endif
8bae0a0c
JSC
3638 break;
3639 }
3640
3641 return;
3642}
3643
3644static unsigned int
3645COP_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:
f24b7b69 3668#if 0 /* should be controlled by configuration option */
e871dd18 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));
f24b7b69 3670#endif
8bae0a0c
JSC
3671 break;
3672 }
3673
3674 return(value);
3675}
3676
e871dd18 3677static uword64
8bae0a0c
JSC
3678COP_SD(coproc_num,coproc_reg)
3679 int coproc_num, coproc_reg;
3680{
e871dd18 3681 uword64 value = 0;
8bae0a0c
JSC
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:
f24b7b69 3701#if 0 /* should be controlled by configuration option */
e871dd18 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));
f24b7b69 3703#endif
8bae0a0c
JSC
3704 break;
3705 }
3706
3707 return(value);
3708}
3709
3710static void
3711decode_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 */
f24b7b69 3765#if 0 /* message should be controlled by configuration option */
8bae0a0c 3766 callback->printf_filtered(callback,"Warning: MFC0 %d,%d not handled yet (architecture specific)\n",rt,rd);
f24b7b69 3767#endif
8bae0a0c
JSC
3768 GPR[rt] = 0xDEADC0DE; /* CPR[0,rd] */
3769 } else { /* MT : move to */
3770 /* CPR[0,rd] = GPR[rt]; */
f24b7b69 3771#if 0 /* should be controlled by configuration option */
8bae0a0c 3772 callback->printf_filtered(callback,"Warning: MTC0 %d,%d not handled yet (architecture specific)\n",rt,rd);
f24b7b69 3773#endif
8bae0a0c
JSC
3774 }
3775 } else
f24b7b69 3776 sim_warning("Unrecognised COP0 instruction 0x%08X at IPC = 0x%08X%08X : No handler present",instruction,WORD64HI(IPC),WORD64LO(IPC));
e871dd18 3777 /* TODO: When executing an ERET or RFE instruction we should
8bae0a0c
JSC
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 */
f24b7b69 3784 sim_warning("COP2 instruction 0x%08X at IPC = 0x%08X%08X : No handler present",instruction,WORD64HI(IPC),WORD64LO(IPC));
8bae0a0c
JSC
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
3798static void
3799simulate ()
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: */
e871dd18
JSC
3820 uword64 vaddr = (uword64)PC;
3821 uword64 paddr;
8bae0a0c
JSC
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)
e871dd18 3839 callback->printf_filtered(callback,"DBG: DSPC = 0x%08X%08X\n",WORD64HI(DSPC),WORD64LO(DSPC));
8bae0a0c
JSC
3840#endif /* DEBUG */
3841
6429b296
JW
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 }
8bae0a0c 3867 } else {
e871dd18 3868 fprintf(stderr,"Cannot translate address for PC = 0x%08X%08X failed\n",WORD64HI(PC),WORD64LO(PC));
8bae0a0c
JSC
3869 exit(1);
3870 }
3871
3872#ifdef DEBUG
e871dd18 3873 callback->printf_filtered(callback,"DBG: fetched 0x%08X from PC = 0x%08X%08X\n",instruction,WORD64HI(PC),WORD64LO(PC));
8bae0a0c
JSC
3874#endif /* DEBUG */
3875
3876#if !defined(FASTSIM) || defined(PROFILE)
3877 instruction_fetches++;
a9f7253f
JSC
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++;
8bae0a0c
JSC
3882#if defined(PROFILE)
3883 if ((state & simPROFILE) && ((instruction_fetches % profile_frequency) == 0) && profile_hist) {
e3d12c65 3884 unsigned n = ((unsigned int)(PC - profile_minpc) >> (profile_shift + 2));
8bae0a0c
JSC
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. */
6429b296
JW
3898 if ((vaddr & 1) == 0)
3899 PC += 4; /* increment ready for the next fetch */
3900 else
3901 PC += 2;
8bae0a0c
JSC
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"
f24b7b69 3961#if ((GPRLEN == 64) && !PROCESSOR_64BIT) || ((GPRLEN == 32) && PROCESSOR_64BIT)
8bae0a0c
JSC
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) {
f24b7b69 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));
8bae0a0c
JSC
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
e871dd18 3990 printf("DBG: dsstate set before instruction execution - updating PC to 0x%08X%08X\n",WORD64HI(DSPC),WORD64LO(DSPC));
8bae0a0c
JSC
3991#endif /* DEBUG */
3992 PC = DSPC;
aaff8437 3993 state &= ~(simDELAYSLOT | simJALDELAYSLOT);
8bae0a0c
JSC
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]);
e871dd18 4020 printf("pending_slot_value[%d] = 0x%08X%08X\n",index,WORD64HI(pending_slot_value[index]),WORD64LO(pending_slot_value[index]));
8bae0a0c
JSC
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
e871dd18 4035 printf("registers[%d] = 0x%08X%08X\n",pending_slot_reg[index],WORD64HI(registers[pending_slot_reg[index]]),WORD64LO(registers[pending_slot_reg[index]]));
8bae0a0c
JSC
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.32844 seconds and 4 git commands to generate.