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