* compile.c (sim_open): New SIM_DESC result. Argument is now in
[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))
da0bce9c
ILT
1627 {
1628 if (A0 == 1)
1629 V0 = callback->write_stdout(callback,(const char *)((int)paddr),
1630 (int)A2);
1631 else
1632 V0 = callback->write(callback,(int)A0,(const char *)((int)paddr),
1633 (int)A2);
1634 }
8bae0a0c 1635 else
f24b7b69 1636 sim_error("Attempt to pass pointer that does not reference simulated memory");
8bae0a0c
JSC
1637 }
1638 break;
1639
1640 case 10: /* int close(int file) */
1641 V0 = callback->close(callback,(int)A0);
1642 break;
1643
1644 case 11: /* char inbyte(void) */
1645 {
1646 char tmp;
1647 if (callback->read_stdin(callback,&tmp,sizeof(char)) != sizeof(char)) {
f24b7b69 1648 sim_error("Invalid return from character read");
e3d12c65 1649 V0 = (ut_reg)-1;
8bae0a0c
JSC
1650 }
1651 else
e3d12c65 1652 V0 = (ut_reg)tmp;
8bae0a0c
JSC
1653 }
1654 break;
1655
1656 case 12: /* void outbyte(char chr) : write a byte to "stdout" */
1657 {
1658 char tmp = (char)(A0 & 0xFF);
1659 callback->write_stdout(callback,&tmp,sizeof(char));
1660 }
1661 break;
1662
1663 case 17: /* void _exit() */
f24b7b69 1664 sim_warning("sim_monitor(17): _exit(int reason) to be coded");
8bae0a0c
JSC
1665 state |= (simSTOP | simEXIT); /* stop executing code */
1666 rcexit = (unsigned int)(A0 & 0xFFFFFFFF);
1667 break;
1668
280f90e1
AMT
1669 case 28 : /* PMON flush_cache */
1670 break;
1671
8bae0a0c
JSC
1672 case 55: /* void get_mem_info(unsigned int *ptr) */
1673 /* in: A0 = pointer to three word memory location */
1674 /* out: [A0 + 0] = size */
1675 /* [A0 + 4] = instruction cache size */
1676 /* [A0 + 8] = data cache size */
1677 {
e871dd18
JSC
1678 uword64 vaddr = A0;
1679 uword64 paddr, value;
8bae0a0c
JSC
1680 int cca;
1681 int failed = 0;
1682
1683 /* NOTE: We use RAW memory writes here, but since we are not
1684 gathering statistics for the monitor calls we are simulating,
1685 it is not an issue. */
1686
1687 /* Memory size */
1688 if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isREAL)) {
e871dd18 1689 value = (uword64)membank_size;
8bae0a0c
JSC
1690 StoreMemory(cca,AccessLength_WORD,value,paddr,vaddr,isRAW);
1691 /* We re-do the address translations, in-case the block
1692 overlaps a memory boundary: */
1693 value = 0;
1694 vaddr += (AccessLength_WORD + 1);
1695 if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isREAL)) {
1696 StoreMemory(cca,AccessLength_WORD,value,paddr,vaddr,isRAW);
1697 vaddr += (AccessLength_WORD + 1);
1698 if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isREAL))
1699 StoreMemory(cca,AccessLength_WORD,value,paddr,vaddr,isRAW);
1700 else
1701 failed = -1;
1702 } else
1703 failed = -1;
1704 } else
1705 failed = -1;
1706
1707 if (failed)
f24b7b69 1708 sim_error("Invalid pointer passed into monitor call");
8bae0a0c
JSC
1709 }
1710 break;
1711
a9f7253f
JSC
1712 case 158 : /* PMON printf */
1713 /* in: A0 = pointer to format string */
1714 /* A1 = optional argument 1 */
1715 /* A2 = optional argument 2 */
1716 /* A3 = optional argument 3 */
1717 /* out: void */
f24b7b69 1718 /* The following is based on the PMON printf source */
a9f7253f
JSC
1719 {
1720 uword64 paddr;
1721 int cca;
f24b7b69
JSC
1722 /* This isn't the quickest way, since we call the host print
1723 routine for every character almost. But it does avoid
1724 having to allocate and manage a temporary string buffer. */
1725 if (AddressTranslation(A0,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL)) {
1726 char *s = (char *)((int)paddr);
1727 ut_reg *ap = &A1; /* 1st argument */
1728 /* TODO: Include check that we only use three arguments (A1, A2 and A3) */
1729 for (; *s;) {
1730 if (*s == '%') {
1731 char tmp[40];
1732 enum {FMT_RJUST, FMT_LJUST, FMT_RJUST0, FMT_CENTER} fmt = FMT_RJUST;
1733 int width = 0, trunc = 0, haddot = 0, longlong = 0;
1734 int base = 10;
1735 s++;
1736 for (; *s; s++) {
1737 if (strchr ("dobxXulscefg%", *s))
1738 break;
1739 else if (*s == '-')
1740 fmt = FMT_LJUST;
1741 else if (*s == '0')
1742 fmt = FMT_RJUST0;
1743 else if (*s == '~')
1744 fmt = FMT_CENTER;
1745 else if (*s == '*') {
1746 if (haddot)
1747 trunc = (int)*ap++;
1748 else
1749 width = (int)*ap++;
1750 } else if (*s >= '1' && *s <= '9') {
1751 char *t;
1752 unsigned int n;
1753 for (t = s; isdigit (*s); s++);
1754 strncpy (tmp, t, s - t);
1755 tmp[s - t] = '\0';
1756 n = (unsigned int)strtol(tmp,NULL,10);
1757 if (haddot)
1758 trunc = n;
1759 else
1760 width = n;
1761 s--;
1762 } else if (*s == '.')
1763 haddot = 1;
1764 }
1765 if (*s == '%') {
1766 callback->printf_filtered(callback,"%%");
1767 } else if (*s == 's') {
1768 if ((int)*ap != 0) {
1769 if (AddressTranslation(*ap++,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL)) {
1770 char *p = (char *)((int)paddr);;
1771 callback->printf_filtered(callback,p);
1772 } else {
1773 ap++;
1774 sim_error("Attempt to pass pointer that does not reference simulated memory");
1775 }
1776 }
1777 else
1778 callback->printf_filtered(callback,"(null)");
1779 } else if (*s == 'c') {
1780 int n = (int)*ap++;
1781 callback->printf_filtered(callback,"%c",n);
1782 } else {
1783 if (*s == 'l') {
1784 if (*++s == 'l') {
1785 longlong = 1;
1786 ++s;
1787 }
1788 }
1789 if (strchr ("dobxXu", *s)) {
e3d12c65 1790 word64 lv = (word64) *ap++;
f24b7b69
JSC
1791 if (*s == 'b')
1792 callback->printf_filtered(callback,"<binary not supported>");
1793 else {
1794 sprintf(tmp,"%%%s%c",longlong ? "ll" : "",*s);
1795 if (longlong)
1796 callback->printf_filtered(callback,tmp,lv);
1797 else
1798 callback->printf_filtered(callback,tmp,(int)lv);
1799 }
1800 } else if (strchr ("eEfgG", *s)) {
e3d12c65
DE
1801#ifdef _MSC_VER /* MSVC version 2.x can't convert from uword64 directly */
1802 double dbl = (double)((word64)*ap++);
1803#else
f24b7b69 1804 double dbl = (double)*ap++;
e3d12c65 1805#endif
f24b7b69
JSC
1806 sprintf(tmp,"%%%d.%d%c",width,trunc,*s);
1807 callback->printf_filtered(callback,tmp,dbl);
1808 trunc = 0;
1809 }
1810 }
1811 s++;
1812 } else
1813 callback->printf_filtered(callback,"%c",*s++);
1814 }
1815 } else
1816 sim_error("Attempt to pass pointer that does not reference simulated memory");
a9f7253f
JSC
1817 }
1818 break;
1819
8bae0a0c 1820 default:
f24b7b69
JSC
1821 sim_warning("TODO: sim_monitor(%d) : PC = 0x%08X%08X",reason,WORD64HI(IPC),WORD64LO(IPC));
1822 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
1823 break;
1824 }
1825 return;
1826}
1827
7e6c297e
ILT
1828/* Store a word into memory. */
1829
1830static void
1831store_word (vaddr, val)
1832 uword64 vaddr;
1833 t_reg val;
1834{
1835 uword64 paddr;
1836 int uncached;
1837
1838 if ((vaddr & 3) != 0)
1839 SignalException (AddressStore);
1840 else
1841 {
1842 if (AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached,
1843 isTARGET, isREAL))
1844 {
1845 const uword64 mask = 7;
1846 uword64 memval;
1847 unsigned int byte;
1848
1849 paddr = (paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2));
1850 byte = (vaddr & mask) ^ (BigEndianCPU << 2);
1851 memval = ((uword64) val) << (8 * byte);
1852 StoreMemory (uncached, AccessLength_WORD, memval, paddr, vaddr,
1853 isREAL);
1854 }
1855 }
1856}
1857
1858/* Load a word from memory. */
1859
1860static t_reg
1861load_word (vaddr)
1862 uword64 vaddr;
1863{
1864 if ((vaddr & 3) != 0)
1865 SignalException (AddressLoad);
1866 else
1867 {
1868 uword64 paddr;
1869 int uncached;
1870
1871 if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached,
1872 isTARGET, isREAL))
1873 {
1874 const uword64 mask = 0x7;
1875 const unsigned int reverse = ReverseEndian ? 1 : 0;
1876 const unsigned int bigend = BigEndianCPU ? 1 : 0;
1877 uword64 memval;
1878 unsigned int byte;
1879
1880 paddr = (paddr & ~mask) | ((paddr & mask) ^ (reverse << 2));
1881 memval = LoadMemory (uncached, AccessLength_WORD, paddr, vaddr,
1882 isDATA, isREAL);
1883 byte = (vaddr & mask) ^ (bigend << 2);
1884 return SIGNEXTEND (((memval >> (8 * byte)) & 0xffffffff), 32);
1885 }
1886 }
1887
1888 return 0;
1889}
1890
1891/* Simulate the mips16 entry and exit pseudo-instructions. These
1892 would normally be handled by the reserved instruction exception
1893 code, but for ease of simulation we just handle them directly. */
1894
1895static void
1896mips16_entry (insn)
1897 unsigned int insn;
1898{
1899 int aregs, sregs, rreg;
1900
1901 aregs = (insn & 0x700) >> 8;
1902 sregs = (insn & 0x0c0) >> 6;
1903 rreg = (insn & 0x020) >> 5;
1904
da0bce9c
ILT
1905 /* This should be checked by the caller. */
1906 if (sregs == 3)
7e6c297e
ILT
1907 abort ();
1908
da0bce9c 1909 if (aregs < 5)
7e6c297e
ILT
1910 {
1911 int i;
1912 t_reg tsp;
1913
1914 /* This is the entry pseudo-instruction. */
1915
1916 for (i = 0; i < aregs; i++)
1917 store_word ((uword64) (SP + 4 * i), registers[i + 4]);
1918
1919 tsp = SP;
1920 SP -= 32;
1921
1922 if (rreg)
1923 {
1924 tsp -= 4;
1925 store_word ((uword64) tsp, RA);
1926 }
1927
1928 for (i = 0; i < sregs; i++)
1929 {
1930 tsp -= 4;
1931 store_word ((uword64) tsp, registers[16 + i]);
1932 }
1933 }
1934 else
1935 {
1936 int i;
1937 t_reg tsp;
1938
1939 /* This is the exit pseudo-instruction. */
1940
1941 tsp = SP + 32;
1942
1943 if (rreg)
1944 {
1945 tsp -= 4;
1946 RA = load_word ((uword64) tsp);
1947 }
1948
1949 for (i = 0; i < sregs; i++)
1950 {
1951 tsp -= 4;
1952 registers[i + 16] = load_word ((uword64) tsp);
1953 }
1954
1955 SP += 32;
1956
da0bce9c
ILT
1957 if (aregs == 5)
1958 {
1959 FGR[0] = WORD64LO (GPR[4]);
1960 fpr_state[0] = fmt_uninterpreted;
1961 }
1962 else if (aregs == 6)
1963 {
1964 FGR[0] = WORD64LO (GPR[5]);
1965 FGR[1] = WORD64LO (GPR[4]);
1966 fpr_state[0] = fmt_uninterpreted;
1967 fpr_state[1] = fmt_uninterpreted;
1968 }
1969
7e6c297e
ILT
1970 PC = RA;
1971 }
1972}
1973
f24b7b69 1974void
e3d12c65 1975sim_warning(char *fmt,...)
f24b7b69 1976{
6429b296 1977 char buf[256];
f24b7b69 1978 va_list ap;
6429b296
JW
1979
1980 va_start (ap,fmt);
1981 vsprintf (buf, fmt, ap);
1982 va_end (ap);
1983
f24b7b69 1984 if (logfh != NULL) {
6429b296
JW
1985 fprintf(logfh,"SIM Warning: %s\n", buf);
1986 } else {
1987 callback->printf_filtered(callback,"SIM Warning: %s\n", buf);
f24b7b69 1988 }
6429b296
JW
1989 /* This used to call SignalException with a SimulatorFault, but that causes
1990 the simulator to exit, and that is inappropriate for a warning. */
f24b7b69
JSC
1991 return;
1992}
1993
8bae0a0c 1994void
e3d12c65 1995sim_error(char *fmt,...)
8bae0a0c 1996{
6429b296 1997 char buf[256];
8bae0a0c 1998 va_list ap;
6429b296
JW
1999
2000 va_start (ap,fmt);
2001 vsprintf (buf, fmt, ap);
2002 va_end (ap);
2003
2004 callback->printf_filtered(callback,"SIM Error: %s", buf);
2005 SignalException (SimulatorFault, buf);
8bae0a0c
JSC
2006 return;
2007}
2008
2009static unsigned int
2010power2(value)
2011 unsigned int value;
2012{
2013 int loop,tmp;
2014
2015 /* Round *UP* to the nearest power-of-2 if not already one */
2016 if (value != (value & ~(value - 1))) {
2017 for (tmp = value, loop = 0; (tmp != 0); loop++)
2018 tmp >>= 1;
2019 value = (1 << loop);
2020 }
2021
2022 return(value);
2023}
2024
2025static long
2026getnum(value)
2027 char *value;
2028{
2029 long num;
2030 char *end;
2031
2032 num = strtol(value,&end,10);
2033 if (end == value)
2034 callback->printf_filtered(callback,"Warning: Invalid number \"%s\" ignored, using zero\n",value);
2035 else {
2036 if (*end && ((tolower(*end) == 'k') || (tolower(*end) == 'm'))) {
2037 if (tolower(*end) == 'k')
2038 num *= (1 << 10);
2039 else
2040 num *= (1 << 20);
2041 end++;
2042 }
2043 if (*end)
2044 callback->printf_filtered(callback,"Warning: Spurious characters \"%s\" at end of number ignored\n",end);
2045 }
2046
2047 return(num);
2048}
2049
2050/*-- trace support ----------------------------------------------------------*/
2051
2052/* The TRACE support is provided (if required) in the memory accessing
2053 routines. Since we are also providing the architecture specific
2054 features, the architecture simulation code can also deal with
2055 notifying the TRACE world of cache flushes, etc. Similarly we do
2056 not need to provide profiling support in the simulator engine,
2057 since we can sample in the instruction fetch control loop. By
2058 defining the TRACE manifest, we add tracing as a run-time
2059 option. */
2060
2061#if defined(TRACE)
2062/* Tracing by default produces "din" format (as required by
2063 dineroIII). Each line of such a trace file *MUST* have a din label
2064 and address field. The rest of the line is ignored, so comments can
2065 be included if desired. The first field is the label which must be
2066 one of the following values:
2067
2068 0 read data
2069 1 write data
2070 2 instruction fetch
2071 3 escape record (treated as unknown access type)
2072 4 escape record (causes cache flush)
2073
2074 The address field is a 32bit (lower-case) hexadecimal address
2075 value. The address should *NOT* be preceded by "0x".
2076
2077 The size of the memory transfer is not important when dealing with
2078 cache lines (as long as no more than a cache line can be
2079 transferred in a single operation :-), however more information
2080 could be given following the dineroIII requirement to allow more
2081 complete memory and cache simulators to provide better
2082 results. i.e. the University of Pisa has a cache simulator that can
2083 also take bus size and speed as (variable) inputs to calculate
2084 complete system performance (a much more useful ability when trying
2085 to construct an end product, rather than a processor). They
2086 currently have an ARM version of their tool called ChARM. */
2087
e3d12c65 2088
8bae0a0c 2089static
e3d12c65 2090void dotrace(FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...)
8bae0a0c
JSC
2091{
2092 if (state & simTRACE) {
2093 va_list ap;
e3d12c65 2094 fprintf(tracefh,"%d %08x%08x ; width %d ; ",
6429b296
JW
2095 type,
2096 sizeof (address) > 4 ? (unsigned long)(address>>32) : 0,
2097 (unsigned long)(address&0xffffffff),width);
8bae0a0c 2098 va_start(ap,comment);
6429b296 2099 vfprintf(tracefh,comment,ap);
8bae0a0c
JSC
2100 va_end(ap);
2101 fprintf(tracefh,"\n");
2102 }
2103 /* NOTE: Since the "din" format will only accept 32bit addresses, and
2104 we may be generating 64bit ones, we should put the hi-32bits of the
2105 address into the comment field. */
2106
2107 /* TODO: Provide a buffer for the trace lines. We can then avoid
2108 performing writes until the buffer is filled, or the file is
2109 being closed. */
2110
2111 /* NOTE: We could consider adding a comment field to the "din" file
2112 produced using type 3 markers (unknown access). This would then
2113 allow information about the program that the "din" is for, and
2114 the MIPs world that was being simulated, to be placed into the
2115 trace file. */
2116
2117 return;
2118}
2119#endif /* TRACE */
2120
f7481d45
JSC
2121/*---------------------------------------------------------------------------*/
2122/*-- host<->target transfers ------------------------------------------------*/
2123/*---------------------------------------------------------------------------*/
2124/* The following routines allow conditionals to be avoided during the
2125 simulation, at the cost of increasing the image and source size. */
2126
2127static unsigned int
e3d12c65 2128xfer_direct_word(unsigned char *memory)
f7481d45
JSC
2129{
2130 return *((unsigned int *)memory);
2131}
2132
2133static uword64
e3d12c65 2134xfer_direct_long(unsigned char *memory)
f7481d45
JSC
2135{
2136 return *((uword64 *)memory);
2137}
2138
2139static unsigned int
e3d12c65 2140swap_direct_word(unsigned int data)
f7481d45
JSC
2141{
2142 return data;
2143}
2144
2145static uword64
e3d12c65 2146swap_direct_long(uword64 data)
f7481d45
JSC
2147{
2148 return data;
2149}
2150
2151static unsigned int
e3d12c65 2152xfer_big_word(unsigned char *memory)
f7481d45
JSC
2153{
2154 return ((memory[0] << 24) | (memory[1] << 16) | (memory[2] << 8) | memory[3]);
2155}
2156
2157static uword64
e3d12c65 2158xfer_big_long(unsigned char *memory)
f7481d45
JSC
2159{
2160 return (((uword64)memory[0] << 56) | ((uword64)memory[1] << 48)
2161 | ((uword64)memory[2] << 40) | ((uword64)memory[3] << 32)
e3d12c65
DE
2162 | ((uword64)memory[4] << 24) | ((uword64)memory[5] << 16)
2163 | ((uword64)memory[6] << 8) | ((uword64)memory[7]));
f7481d45
JSC
2164}
2165
2166static unsigned int
e3d12c65 2167xfer_little_word(unsigned char *memory)
f7481d45
JSC
2168{
2169 return ((memory[3] << 24) | (memory[2] << 16) | (memory[1] << 8) | memory[0]);
2170}
2171
2172static uword64
e3d12c65 2173xfer_little_long(unsigned char *memory)
f7481d45
JSC
2174{
2175 return (((uword64)memory[7] << 56) | ((uword64)memory[6] << 48)
2176 | ((uword64)memory[5] << 40) | ((uword64)memory[4] << 32)
e3d12c65
DE
2177 | ((uword64)memory[3] << 24) | ((uword64)memory[2] << 16)
2178 | ((uword64)memory[1] << 8) | (uword64)memory[0]);
f7481d45
JSC
2179}
2180
2181static unsigned int
e3d12c65 2182swap_word(unsigned int data)
f7481d45
JSC
2183{
2184 unsigned int result;
aaff8437
ILT
2185 result = (((data & 0xff) << 24) | ((data & 0xff00) << 8)
2186 | ((data >> 8) & 0xff00) | ((data >> 24) & 0xff));
2187 return result;
f7481d45
JSC
2188}
2189
2190static uword64
e3d12c65 2191swap_long(uword64 data)
f7481d45
JSC
2192{
2193 unsigned int tmphi = WORD64HI(data);
2194 unsigned int tmplo = WORD64LO(data);
2195 tmphi = swap_word(tmphi);
2196 tmplo = swap_word(tmplo);
2197 /* Now swap the HI and LO parts */
2198 return SET64LO(tmphi) | SET64HI(tmplo);
2199}
2200
8bae0a0c
JSC
2201/*---------------------------------------------------------------------------*/
2202/*-- simulator engine -------------------------------------------------------*/
2203/*---------------------------------------------------------------------------*/
2204
aaff8437
ILT
2205static void
2206set_endianness ()
2207{
2208 /* In reality this check should be performed at various points
2209 within the simulation, since it is possible to change the
2210 endianness of user programs. However, we perform the check here
2211 to ensure that the start-of-day values agree. */
2212 if (target_byte_order == 4321)
2213 state |= simBE;
2214
2215 /* ??? This is a lot more code than is necessary to solve the problem.
2216 It would be simpler to handle this like the SH simulator. */
2217 if (!ByteSwapMem) {
2218 host_read_word = xfer_direct_word;
2219 host_read_long = xfer_direct_long;
2220 host_swap_word = swap_direct_word;
2221 host_swap_long = swap_direct_long;
2222 } else if (state & simHOSTBE) {
2223 host_read_word = xfer_little_word;
2224 host_read_long = xfer_little_long;
2225 host_swap_word = swap_word;
2226 host_swap_long = swap_long;
2227 } else { /* HOST little-endian */
2228 host_read_word = xfer_big_word;
2229 host_read_long = xfer_big_long;
2230 host_swap_word = swap_word;
2231 host_swap_long = swap_long;
2232 }
2233}
2234
8bae0a0c
JSC
2235static void
2236ColdReset()
2237{
2238 /* RESET: Fixed PC address: */
e871dd18 2239 PC = (((uword64)0xFFFFFFFF<<32) | 0xBFC00000);
8bae0a0c
JSC
2240 /* The reset vector address is in the unmapped, uncached memory space. */
2241
2242 SR &= ~(status_SR | status_TS | status_RP);
2243 SR |= (status_ERL | status_BEV);
8bae0a0c
JSC
2244
2245#if defined(HASFPU) && (GPRLEN == (64))
2246 /* Cheat and allow access to the complete register set immediately: */
2247 SR |= status_FR; /* 64bit registers */
2248#endif /* HASFPU and 64bit FP registers */
2249
2250 /* Ensure that any instructions with pending register updates are
2251 cleared: */
2252 {
2253 int loop;
2254 for (loop = 0; (loop < PSLOTS); loop++)
2255 pending_slot_reg[loop] = (LAST_EMBED_REGNUM + 1);
2256 pending_in = pending_out = pending_total = 0;
2257 }
2258
2259#if defined(HASFPU)
2260 /* Initialise the FPU registers to the unknown state */
2261 {
2262 int rn;
2263 for (rn = 0; (rn < 32); rn++)
2264 fpr_state[rn] = fmt_uninterpreted;
2265 }
2266#endif /* HASFPU */
2267
2268 return;
2269}
2270
2271/* Description from page A-22 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2272/* Translate a virtual address to a physical address and cache
2273 coherence algorithm describing the mechanism used to resolve the
2274 memory reference. Given the virtual address vAddr, and whether the
2275 reference is to Instructions ot Data (IorD), find the corresponding
2276 physical address (pAddr) and the cache coherence algorithm (CCA)
2277 used to resolve the reference. If the virtual address is in one of
2278 the unmapped address spaces the physical address and the CCA are
2279 determined directly by the virtual address. If the virtual address
2280 is in one of the mapped address spaces then the TLB is used to
2281 determine the physical address and access type; if the required
2282 translation is not present in the TLB or the desired access is not
2283 permitted the function fails and an exception is taken.
2284
2285 NOTE: This function is extended to return an exception state. This,
2286 along with the exception generation is used to notify whether a
2287 valid address translation occured */
2288
2289static int
2290AddressTranslation(vAddr,IorD,LorS,pAddr,CCA,host,raw)
e871dd18 2291 uword64 vAddr;
8bae0a0c
JSC
2292 int IorD;
2293 int LorS;
e871dd18 2294 uword64 *pAddr;
8bae0a0c
JSC
2295 int *CCA;
2296 int host;
2297 int raw;
2298{
2299 int res = -1; /* TRUE : Assume good return */
2300
2301#ifdef DEBUG
e871dd18 2302 callback->printf_filtered(callback,"AddressTranslation(0x%08X%08X,%s,%s,...);\n",WORD64HI(vAddr),WORD64LO(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "iSTORE" : "isLOAD"));
8bae0a0c
JSC
2303#endif
2304
2305 /* Check that the address is valid for this memory model */
2306
2307 /* For a simple (flat) memory model, we simply pass virtual
2308 addressess through (mostly) unchanged. */
2309 vAddr &= 0xFFFFFFFF;
a9f7253f
JSC
2310
2311 /* Treat the kernel memory spaces identically for the moment: */
2312 if ((membank_base == K1BASE) && (vAddr >= K0BASE) && (vAddr < (K0BASE + K0SIZE)))
2313 vAddr += (K1BASE - K0BASE);
2314
2315 /* Also assume that the K1BASE memory wraps. This is required to
2316 allow the PMON run-time __sizemem() routine to function (without
2317 having to provide exception simulation). NOTE: A kludge to work
2318 around the fact that the monitor memory is currently held in the
2319 K1BASE space. */
2320 if (((vAddr < monitor_base) || (vAddr >= (monitor_base + monitor_size))) && (vAddr >= K1BASE && vAddr < (K1BASE + K1SIZE)))
2321 vAddr = (K1BASE | (vAddr & (membank_size - 1)));
2322
8bae0a0c
JSC
2323 *pAddr = vAddr; /* default for isTARGET */
2324 *CCA = Uncached; /* not used for isHOST */
2325
2326 /* NOTE: This is a duplicate of the code that appears in the
2327 LoadMemory and StoreMemory functions. They should be merged into
2328 a single function (that can be in-lined if required). */
2329 if ((vAddr >= membank_base) && (vAddr < (membank_base + membank_size))) {
2330 if (host)
2331 *pAddr = (int)&membank[((unsigned int)(vAddr - membank_base) & (membank_size - 1))];
2332 } else if ((vAddr >= monitor_base) && (vAddr < (monitor_base + monitor_size))) {
2333 if (host)
2334 *pAddr = (int)&monitor[((unsigned int)(vAddr - monitor_base) & (monitor_size - 1))];
2335 } else {
6429b296 2336#ifdef DEBUG
f24b7b69 2337 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
2338#endif /* DEBUG */
2339 res = 0; /* AddressTranslation has failed */
e3d12c65 2340 *pAddr = (SIM_ADDR)-1;
8bae0a0c
JSC
2341 if (!raw) /* only generate exceptions on real memory transfers */
2342 SignalException((LorS == isSTORE) ? AddressStore : AddressLoad);
6429b296 2343#ifdef DEBUG
8bae0a0c 2344 else
6429b296
JW
2345 /* This is a normal occurance during gdb operation, for instance trying
2346 to print parameters at function start before they have been setup,
2347 and hence we should not print a warning except when debugging the
2348 simulator. */
f24b7b69 2349 sim_warning("AddressTranslation for %s %s from 0x%08X%08X failed",(IorD ? "data" : "instruction"),(LorS ? "store" : "load"),WORD64HI(vAddr),WORD64LO(vAddr));
6429b296 2350#endif
8bae0a0c
JSC
2351 }
2352
2353 return(res);
2354}
2355
2356/* Description from page A-23 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2357/* Prefetch data from memory. Prefetch is an advisory instruction for
2358 which an implementation specific action is taken. The action taken
2359 may increase performance, but must not change the meaning of the
2360 program, or alter architecturally-visible state. */
2361static void
2362Prefetch(CCA,pAddr,vAddr,DATA,hint)
2363 int CCA;
e871dd18
JSC
2364 uword64 pAddr;
2365 uword64 vAddr;
8bae0a0c
JSC
2366 int DATA;
2367 int hint;
2368{
2369#ifdef DEBUG
e871dd18 2370 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
2371#endif /* DEBUG */
2372
2373 /* For our simple memory model we do nothing */
2374 return;
2375}
2376
2377/* Description from page A-22 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2378/* Load a value from memory. Use the cache and main memory as
2379 specified in the Cache Coherence Algorithm (CCA) and the sort of
2380 access (IorD) to find the contents of AccessLength memory bytes
2381 starting at physical location pAddr. The data is returned in the
2382 fixed width naturally-aligned memory element (MemElem). The
2383 low-order two (or three) bits of the address and the AccessLength
2384 indicate which of the bytes within MemElem needs to be given to the
2385 processor. If the memory access type of the reference is uncached
2386 then only the referenced bytes are read from memory and valid
2387 within the memory element. If the access type is cached, and the
2388 data is not present in cache, an implementation specific size and
2389 alignment block of memory is read and loaded into the cache to
2390 satisfy a load reference. At a minimum, the block is the entire
2391 memory element. */
e871dd18 2392static uword64
8bae0a0c
JSC
2393LoadMemory(CCA,AccessLength,pAddr,vAddr,IorD,raw)
2394 int CCA;
2395 int AccessLength;
e871dd18
JSC
2396 uword64 pAddr;
2397 uword64 vAddr;
8bae0a0c
JSC
2398 int IorD;
2399 int raw;
2400{
e871dd18 2401 uword64 value;
8bae0a0c
JSC
2402
2403#ifdef DEBUG
2404 if (membank == NULL)
e871dd18 2405 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
2406#endif /* DEBUG */
2407
2408#if defined(WARN_MEM)
2409 if (CCA != uncached)
f24b7b69 2410 sim_warning("LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)",CCA);
8bae0a0c
JSC
2411
2412 if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK) {
2413 /* In reality this should be a Bus Error */
f24b7b69 2414 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
2415 }
2416#endif /* WARN_MEM */
2417
2418 /* Decide which physical memory locations are being dealt with. At
2419 this point we should be able to split the pAddr bits into the
2420 relevant address map being simulated. If the "raw" variable is
2421 set, the memory read being performed should *NOT* update any I/O
2422 state or affect the CPU state. This also includes avoiding
2423 affecting statistics gathering. */
2424
2425 /* If instruction fetch then we need to check that the two lo-order
2426 bits are zero, otherwise raise a InstructionFetch exception: */
6429b296
JW
2427 if ((IorD == isINSTRUCTION)
2428 && ((pAddr & 0x3) != 0)
2429 && (((pAddr & 0x1) != 0) || ((vAddr & 0x1) == 0)))
8bae0a0c
JSC
2430 SignalException(InstructionFetch);
2431 else {
2432 unsigned int index;
2433 unsigned char *mem = NULL;
2434
8bae0a0c
JSC
2435#if defined(TRACE)
2436 if (!raw)
2437 dotrace(tracefh,((IorD == isDATA) ? 0 : 2),(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"load%s",((IorD == isDATA) ? "" : " instruction"));
2438#endif /* TRACE */
2439
2440 /* NOTE: Quicker methods of decoding the address space can be used
2441 when a real memory map is being simulated (i.e. using hi-order
2442 address bits to select device). */
2443 if ((pAddr >= membank_base) && (pAddr < (membank_base + membank_size))) {
2444 index = ((unsigned int)(pAddr - membank_base) & (membank_size - 1));
2445 mem = membank;
2446 } else if ((pAddr >= monitor_base) && (pAddr < (monitor_base + monitor_size))) {
2447 index = ((unsigned int)(pAddr - monitor_base) & (monitor_size - 1));
2448 mem = monitor;
2449 }
2450 if (mem == NULL)
e871dd18 2451 sim_error("Simulator memory not found for physical address 0x%08X%08X\n",WORD64HI(pAddr),WORD64LO(pAddr));
8bae0a0c
JSC
2452 else {
2453 /* If we obtained the endianness of the host, and it is the same
2454 as the target memory system we can optimise the memory
2455 accesses. However, without that information we must perform
2456 slow transfer, and hope that the compiler optimisation will
2457 merge successive loads. */
2458 value = 0; /* no data loaded yet */
2459
2460 /* In reality we should always be loading a doubleword value (or
2461 word value in 32bit memory worlds). The external code then
2462 extracts the required bytes. However, to keep performance
2463 high we only load the required bytes into the relevant
2464 slots. */
0049ba7a 2465 if (BigEndianMem)
8bae0a0c
JSC
2466 switch (AccessLength) { /* big-endian memory */
2467 case AccessLength_DOUBLEWORD :
e871dd18 2468 value |= ((uword64)mem[index++] << 56);
8bae0a0c 2469 case AccessLength_SEPTIBYTE :
e871dd18 2470 value |= ((uword64)mem[index++] << 48);
8bae0a0c 2471 case AccessLength_SEXTIBYTE :
e871dd18 2472 value |= ((uword64)mem[index++] << 40);
8bae0a0c 2473 case AccessLength_QUINTIBYTE :
e871dd18 2474 value |= ((uword64)mem[index++] << 32);
8bae0a0c
JSC
2475 case AccessLength_WORD :
2476 value |= ((unsigned int)mem[index++] << 24);
2477 case AccessLength_TRIPLEBYTE :
2478 value |= ((unsigned int)mem[index++] << 16);
2479 case AccessLength_HALFWORD :
2480 value |= ((unsigned int)mem[index++] << 8);
2481 case AccessLength_BYTE :
2482 value |= mem[index];
2483 break;
2484 }
2485 else {
2486 index += (AccessLength + 1);
2487 switch (AccessLength) { /* little-endian memory */
2488 case AccessLength_DOUBLEWORD :
e871dd18 2489 value |= ((uword64)mem[--index] << 56);
8bae0a0c 2490 case AccessLength_SEPTIBYTE :
e871dd18 2491 value |= ((uword64)mem[--index] << 48);
8bae0a0c 2492 case AccessLength_SEXTIBYTE :
e871dd18 2493 value |= ((uword64)mem[--index] << 40);
8bae0a0c 2494 case AccessLength_QUINTIBYTE :
e871dd18 2495 value |= ((uword64)mem[--index] << 32);
8bae0a0c 2496 case AccessLength_WORD :
e871dd18 2497 value |= ((uword64)mem[--index] << 24);
8bae0a0c 2498 case AccessLength_TRIPLEBYTE :
e871dd18 2499 value |= ((uword64)mem[--index] << 16);
8bae0a0c 2500 case AccessLength_HALFWORD :
e871dd18 2501 value |= ((uword64)mem[--index] << 8);
8bae0a0c 2502 case AccessLength_BYTE :
e871dd18 2503 value |= ((uword64)mem[--index] << 0);
8bae0a0c
JSC
2504 break;
2505 }
2506 }
2507
2508#ifdef DEBUG
e871dd18 2509 printf("DBG: LoadMemory() : (offset %d) : value = 0x%08X%08X\n",(int)(pAddr & LOADDRMASK),WORD64HI(value),WORD64LO(value));
8bae0a0c
JSC
2510#endif /* DEBUG */
2511
2512 /* TODO: We could try and avoid the shifts when dealing with raw
2513 memory accesses. This would mean updating the LoadMemory and
2514 StoreMemory routines to avoid shifting the data before
2515 returning or using it. */
2516 if (!raw) { /* do nothing for raw accessess */
0049ba7a 2517 if (BigEndianMem)
8bae0a0c
JSC
2518 value <<= (((7 - (pAddr & LOADDRMASK)) - AccessLength) * 8);
2519 else /* little-endian only needs to be shifted up to the correct byte offset */
2520 value <<= ((pAddr & LOADDRMASK) * 8);
2521 }
2522
2523#ifdef DEBUG
e871dd18
JSC
2524 printf("DBG: LoadMemory() : shifted value = 0x%08X%08X\n",WORD64HI(value),WORD64LO(value));
2525#endif /* DEBUG */
8bae0a0c
JSC
2526 }
2527 }
2528
2529 return(value);
2530}
2531
2532/* Description from page A-23 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2533/* Store a value to memory. The specified data is stored into the
2534 physical location pAddr using the memory hierarchy (data caches and
2535 main memory) as specified by the Cache Coherence Algorithm
2536 (CCA). The MemElem contains the data for an aligned, fixed-width
2537 memory element (word for 32-bit processors, doubleword for 64-bit
2538 processors), though only the bytes that will actually be stored to
2539 memory need to be valid. The low-order two (or three) bits of pAddr
2540 and the AccessLength field indicates which of the bytes within the
2541 MemElem data should actually be stored; only these bytes in memory
2542 will be changed. */
2543static void
2544StoreMemory(CCA,AccessLength,MemElem,pAddr,vAddr,raw)
2545 int CCA;
2546 int AccessLength;
e871dd18
JSC
2547 uword64 MemElem;
2548 uword64 pAddr;
2549 uword64 vAddr;
8bae0a0c
JSC
2550 int raw;
2551{
2552#ifdef DEBUG
e871dd18 2553 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
2554#endif /* DEBUG */
2555
2556#if defined(WARN_MEM)
2557 if (CCA != uncached)
f24b7b69 2558 sim_warning("StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)",CCA);
8bae0a0c
JSC
2559
2560 if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
f24b7b69 2561 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
2562#endif /* WARN_MEM */
2563
2564#if defined(TRACE)
2565 if (!raw)
2566 dotrace(tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store");
2567#endif /* TRACE */
2568
2569 /* See the comments in the LoadMemory routine about optimising
2570 memory accesses. Also if we wanted to make the simulator smaller,
2571 we could merge a lot of this code with the LoadMemory
2572 routine. However, this would slow the simulator down with
2573 run-time conditionals. */
2574 {
2575 unsigned int index;
2576 unsigned char *mem = NULL;
2577
2578 if ((pAddr >= membank_base) && (pAddr < (membank_base + membank_size))) {
2579 index = ((unsigned int)(pAddr - membank_base) & (membank_size - 1));
2580 mem = membank;
2581 } else if ((pAddr >= monitor_base) && (pAddr < (monitor_base + monitor_size))) {
2582 index = ((unsigned int)(pAddr - monitor_base) & (monitor_size - 1));
2583 mem = monitor;
2584 }
2585
2586 if (mem == NULL)
e871dd18 2587 sim_error("Simulator memory not found for physical address 0x%08X%08X\n",WORD64HI(pAddr),WORD64LO(pAddr));
8bae0a0c
JSC
2588 else {
2589 int shift = 0;
2590
2591#ifdef DEBUG
e871dd18 2592 printf("DBG: StoreMemory: offset = %d MemElem = 0x%08X%08X\n",(unsigned int)(pAddr & LOADDRMASK),WORD64HI(MemElem),WORD64LO(MemElem));
8bae0a0c
JSC
2593#endif /* DEBUG */
2594
0049ba7a 2595 if (BigEndianMem) {
8bae0a0c
JSC
2596 if (raw)
2597 shift = ((7 - AccessLength) * 8);
2598 else /* real memory access */
2599 shift = ((pAddr & LOADDRMASK) * 8);
2600 MemElem <<= shift;
2601 } else {
2602 /* no need to shift raw little-endian data */
2603 if (!raw)
2604 MemElem >>= ((pAddr & LOADDRMASK) * 8);
2605 }
2606
2607#ifdef DEBUG
e871dd18 2608 printf("DBG: StoreMemory: shift = %d MemElem = 0x%08X%08X\n",shift,WORD64HI(MemElem),WORD64LO(MemElem));
8bae0a0c
JSC
2609#endif /* DEBUG */
2610
0049ba7a 2611 if (BigEndianMem) {
8bae0a0c
JSC
2612 switch (AccessLength) { /* big-endian memory */
2613 case AccessLength_DOUBLEWORD :
2614 mem[index++] = (unsigned char)(MemElem >> 56);
2615 MemElem <<= 8;
2616 case AccessLength_SEPTIBYTE :
2617 mem[index++] = (unsigned char)(MemElem >> 56);
2618 MemElem <<= 8;
2619 case AccessLength_SEXTIBYTE :
2620 mem[index++] = (unsigned char)(MemElem >> 56);
2621 MemElem <<= 8;
2622 case AccessLength_QUINTIBYTE :
2623 mem[index++] = (unsigned char)(MemElem >> 56);
2624 MemElem <<= 8;
2625 case AccessLength_WORD :
2626 mem[index++] = (unsigned char)(MemElem >> 56);
2627 MemElem <<= 8;
2628 case AccessLength_TRIPLEBYTE :
2629 mem[index++] = (unsigned char)(MemElem >> 56);
2630 MemElem <<= 8;
2631 case AccessLength_HALFWORD :
2632 mem[index++] = (unsigned char)(MemElem >> 56);
2633 MemElem <<= 8;
2634 case AccessLength_BYTE :
2635 mem[index++] = (unsigned char)(MemElem >> 56);
2636 break;
2637 }
2638 } else {
2639 index += (AccessLength + 1);
2640 switch (AccessLength) { /* little-endian memory */
2641 case AccessLength_DOUBLEWORD :
2642 mem[--index] = (unsigned char)(MemElem >> 56);
2643 case AccessLength_SEPTIBYTE :
2644 mem[--index] = (unsigned char)(MemElem >> 48);
2645 case AccessLength_SEXTIBYTE :
2646 mem[--index] = (unsigned char)(MemElem >> 40);
2647 case AccessLength_QUINTIBYTE :
2648 mem[--index] = (unsigned char)(MemElem >> 32);
2649 case AccessLength_WORD :
2650 mem[--index] = (unsigned char)(MemElem >> 24);
2651 case AccessLength_TRIPLEBYTE :
2652 mem[--index] = (unsigned char)(MemElem >> 16);
2653 case AccessLength_HALFWORD :
2654 mem[--index] = (unsigned char)(MemElem >> 8);
2655 case AccessLength_BYTE :
2656 mem[--index] = (unsigned char)(MemElem >> 0);
2657 break;
2658 }
2659 }
2660 }
2661 }
2662
2663 return;
2664}
2665
2666/* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2667/* Order loads and stores to synchronise shared memory. Perform the
2668 action necessary to make the effects of groups of synchronizable
2669 loads and stores indicated by stype occur in the same order for all
2670 processors. */
2671static void
2672SyncOperation(stype)
2673 int stype;
2674{
2675#ifdef DEBUG
2676 callback->printf_filtered(callback,"SyncOperation(%d) : TODO\n",stype);
2677#endif /* DEBUG */
2678 return;
2679}
2680
2681/* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2682/* Signal an exception condition. This will result in an exception
2683 that aborts the instruction. The instruction operation pseudocode
2684 will never see a return from this function call. */
2685static void
e3d12c65 2686SignalException (int exception,...)
8bae0a0c
JSC
2687{
2688 /* Ensure that any active atomic read/modify/write operation will fail: */
2689 LLBIT = 0;
2690
2691 switch (exception) {
2692 /* TODO: For testing purposes I have been ignoring TRAPs. In
2693 reality we should either simulate them, or allow the user to
2694 ignore them at run-time. */
2695 case Trap :
f24b7b69 2696 sim_warning("Ignoring instruction TRAP (PC 0x%08X%08X)",WORD64HI(IPC),WORD64LO(IPC));
8bae0a0c
JSC
2697 break;
2698
2699 case ReservedInstruction :
2700 {
2701 va_list ap;
2702 unsigned int instruction;
2703 va_start(ap,exception);
2704 instruction = va_arg(ap,unsigned int);
2705 va_end(ap);
2706 /* Provide simple monitor support using ReservedInstruction
2707 exceptions. The following code simulates the fixed vector
2708 entry points into the IDT monitor by causing a simulator
2709 trap, performing the monitor operation, and returning to
2710 the address held in the $ra register (standard PCS return
2711 address). This means we only need to pre-load the vector
2712 space with suitable instruction values. For systems were
2713 actual trap instructions are used, we would not need to
2714 perform this magic. */
2715 if ((instruction & ~RSVD_INSTRUCTION_AMASK) == RSVD_INSTRUCTION) {
2716 sim_monitor(instruction & RSVD_INSTRUCTION_AMASK);
2717 PC = RA; /* simulate the return from the vector entry */
2718 /* NOTE: This assumes that a branch-and-link style
2719 instruction was used to enter the vector (which is the
2720 case with the current IDT monitor). */
2721 break; /* out of the switch statement */
7e6c297e
ILT
2722 }
2723 /* Look for the mips16 entry and exit instructions, and
2724 simulate a handler for them. */
2725 else if ((IPC & 1) != 0
2726 && (instruction & 0xf81f) == 0xe809
7e6c297e
ILT
2727 && (instruction & 0x0c0) != 0x0c0) {
2728 mips16_entry (instruction);
2729 break;
8bae0a0c 2730 } /* else fall through to normal exception processing */
f24b7b69 2731 sim_warning("ReservedInstruction 0x%08X at IPC = 0x%08X%08X",instruction,WORD64HI(IPC),WORD64LO(IPC));
8bae0a0c
JSC
2732 }
2733
2734 default:
e3d12c65 2735#ifdef DEBUG
f24b7b69
JSC
2736 if (exception != BreakPoint)
2737 callback->printf_filtered(callback,"DBG: SignalException(%d) IPC = 0x%08X%08X\n",exception,WORD64HI(IPC),WORD64LO(IPC));
8bae0a0c
JSC
2738#endif /* DEBUG */
2739 /* Store exception code into current exception id variable (used
2740 by exit code): */
2741
2742 /* TODO: If not simulating exceptions then stop the simulator
2743 execution. At the moment we always stop the simulation. */
2744 state |= (simSTOP | simEXCEPTION);
e3d12c65
DE
2745
2746 /* Keep a copy of the current A0 in-case this is the program exit
2747 breakpoint: */
2748 if (exception == BreakPoint) {
2749 va_list ap;
2750 unsigned int instruction;
2751 va_start(ap,exception);
2752 instruction = va_arg(ap,unsigned int);
2753 va_end(ap);
2754 /* Check for our special terminating BREAK: */
2755 if ((instruction & 0x03FFFFC0) == 0x03ff0000) {
2756 rcexit = (unsigned int)(A0 & 0xFFFFFFFF);
2757 state &= ~simEXCEPTION;
2758 state |= simEXIT;
2759 }
2760 }
2761
2762 /* Store exception code into current exception id variable (used
2763 by exit code): */
8bae0a0c
JSC
2764 CAUSE = (exception << 2);
2765 if (state & simDELAYSLOT) {
2766 CAUSE |= cause_BD;
2767 EPC = (IPC - 4); /* reference the branch instruction */
2768 } else
2769 EPC = IPC;
2770 /* The following is so that the simulator will continue from the
2771 exception address on breakpoint operations. */
2772 PC = EPC;
2773 break;
2774
2775 case SimulatorFault:
2776 {
2777 va_list ap;
2778 char *msg;
2779 va_start(ap,exception);
2780 msg = va_arg(ap,char *);
2781 fprintf(stderr,"FATAL: Simulator error \"%s\"\n",msg);
2782 va_end(ap);
2783 }
2784 exit(1);
2785 }
2786
2787 return;
2788}
2789
2790#if defined(WARN_RESULT)
2791/* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2792/* This function indicates that the result of the operation is
2793 undefined. However, this should not affect the instruction
2794 stream. All that is meant to happen is that the destination
2795 register is set to an undefined result. To keep the simulator
2796 simple, we just don't bother updating the destination register, so
2797 the overall result will be undefined. If desired we can stop the
2798 simulator by raising a pseudo-exception. */
2799static void
2800UndefinedResult()
2801{
f24b7b69 2802 sim_warning("UndefinedResult: IPC = 0x%08X%08X",WORD64HI(IPC),WORD64LO(IPC));
8bae0a0c
JSC
2803#if 0 /* Disabled for the moment, since it actually happens a lot at the moment. */
2804 state |= simSTOP;
2805#endif
2806 return;
2807}
2808#endif /* WARN_RESULT */
2809
2810static void
2811CacheOp(op,pAddr,vAddr,instruction)
2812 int op;
e871dd18
JSC
2813 uword64 pAddr;
2814 uword64 vAddr;
8bae0a0c
JSC
2815 unsigned int instruction;
2816{
f24b7b69
JSC
2817#if 1 /* stop warning message being displayed (we should really just remove the code) */
2818 static int icache_warning = 1;
2819 static int dcache_warning = 1;
2820#else
a9f7253f
JSC
2821 static int icache_warning = 0;
2822 static int dcache_warning = 0;
f24b7b69 2823#endif
a9f7253f 2824
8bae0a0c
JSC
2825 /* If CP0 is not useable (User or Supervisor mode) and the CP0
2826 enable bit in the Status Register is clear - a coprocessor
2827 unusable exception is taken. */
a9f7253f 2828#if 0
e871dd18 2829 callback->printf_filtered(callback,"TODO: Cache availability checking (PC = 0x%08X%08X)\n",WORD64HI(IPC),WORD64LO(IPC));
a9f7253f 2830#endif
8bae0a0c
JSC
2831
2832 switch (op & 0x3) {
2833 case 0: /* instruction cache */
2834 switch (op >> 2) {
2835 case 0: /* Index Invalidate */
2836 case 1: /* Index Load Tag */
2837 case 2: /* Index Store Tag */
2838 case 4: /* Hit Invalidate */
2839 case 5: /* Fill */
2840 case 6: /* Hit Writeback */
a9f7253f
JSC
2841 if (!icache_warning)
2842 {
f24b7b69 2843 sim_warning("Instruction CACHE operation %d to be coded",(op >> 2));
a9f7253f
JSC
2844 icache_warning = 1;
2845 }
8bae0a0c
JSC
2846 break;
2847
2848 default:
2849 SignalException(ReservedInstruction,instruction);
2850 break;
2851 }
2852 break;
2853
2854 case 1: /* data cache */
2855 switch (op >> 2) {
2856 case 0: /* Index Writeback Invalidate */
2857 case 1: /* Index Load Tag */
2858 case 2: /* Index Store Tag */
2859 case 3: /* Create Dirty */
2860 case 4: /* Hit Invalidate */
2861 case 5: /* Hit Writeback Invalidate */
2862 case 6: /* Hit Writeback */
a9f7253f
JSC
2863 if (!dcache_warning)
2864 {
f24b7b69 2865 sim_warning("Data CACHE operation %d to be coded",(op >> 2));
a9f7253f
JSC
2866 dcache_warning = 1;
2867 }
8bae0a0c
JSC
2868 break;
2869
2870 default:
2871 SignalException(ReservedInstruction,instruction);
2872 break;
2873 }
2874 break;
2875
2876 default: /* unrecognised cache ID */
2877 SignalException(ReservedInstruction,instruction);
2878 break;
2879 }
2880
2881 return;
2882}
2883
2884/*-- FPU support routines ---------------------------------------------------*/
2885
2886#if defined(HASFPU) /* Only needed when building FPU aware simulators */
2887
2888#if 1
2889#define SizeFGR() (GPRLEN)
2890#else
2891/* They depend on the CPU being simulated */
2892#define SizeFGR() ((PROCESSOR_64BIT && ((SR & status_FR) == 1)) ? 64 : 32)
2893#endif
2894
2895/* Numbers are held in normalized form. The SINGLE and DOUBLE binary
2896 formats conform to ANSI/IEEE Std 754-1985. */
2897/* SINGLE precision floating:
2898 * seeeeeeeefffffffffffffffffffffff
2899 * s = 1bit = sign
2900 * e = 8bits = exponent
2901 * f = 23bits = fraction
2902 */
2903/* SINGLE precision fixed:
2904 * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
2905 * s = 1bit = sign
2906 * i = 31bits = integer
2907 */
2908/* DOUBLE precision floating:
2909 * seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
2910 * s = 1bit = sign
2911 * e = 11bits = exponent
2912 * f = 52bits = fraction
2913 */
2914/* DOUBLE precision fixed:
2915 * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
2916 * s = 1bit = sign
2917 * i = 63bits = integer
2918 */
2919
2920/* Extract sign-bit: */
2921#define FP_S_s(v) (((v) & ((unsigned)1 << 31)) ? 1 : 0)
e871dd18 2922#define FP_D_s(v) (((v) & ((uword64)1 << 63)) ? 1 : 0)
8bae0a0c
JSC
2923/* Extract biased exponent: */
2924#define FP_S_be(v) (((v) >> 23) & 0xFF)
2925#define FP_D_be(v) (((v) >> 52) & 0x7FF)
2926/* Extract unbiased Exponent: */
2927#define FP_S_e(v) (FP_S_be(v) - 0x7F)
2928#define FP_D_e(v) (FP_D_be(v) - 0x3FF)
2929/* Extract complete fraction field: */
2930#define FP_S_f(v) ((v) & ~((unsigned)0x1FF << 23))
e871dd18 2931#define FP_D_f(v) ((v) & ~((uword64)0xFFF << 52))
8bae0a0c
JSC
2932/* Extract numbered fraction bit: */
2933#define FP_S_fb(b,v) (((v) & (1 << (23 - (b)))) ? 1 : 0)
2934#define FP_D_fb(b,v) (((v) & (1 << (52 - (b)))) ? 1 : 0)
2935
2936/* Explicit QNaN values used when value required: */
2937#define FPQNaN_SINGLE (0x7FBFFFFF)
2938#define FPQNaN_WORD (0x7FFFFFFF)
e871dd18
JSC
2939#define FPQNaN_DOUBLE (((uword64)0x7FF7FFFF << 32) | 0xFFFFFFFF)
2940#define FPQNaN_LONG (((uword64)0x7FFFFFFF << 32) | 0xFFFFFFFF)
8bae0a0c
JSC
2941
2942/* Explicit Infinity values used when required: */
2943#define FPINF_SINGLE (0x7F800000)
e871dd18 2944#define FPINF_DOUBLE (((uword64)0x7FF00000 << 32) | 0x00000000)
8bae0a0c
JSC
2945
2946#if 1 /* def DEBUG */
2947#define RMMODE(v) (((v) == FP_RM_NEAREST) ? "Round" : (((v) == FP_RM_TOZERO) ? "Trunc" : (((v) == FP_RM_TOPINF) ? "Ceil" : "Floor")))
2948#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>"))))))
2949#endif /* DEBUG */
2950
e871dd18 2951static uword64
8bae0a0c
JSC
2952ValueFPR(fpr,fmt)
2953 int fpr;
2954 FP_formats fmt;
2955{
e871dd18 2956 uword64 value;
8bae0a0c
JSC
2957 int err = 0;
2958
2959 /* Treat unused register values, as fixed-point 64bit values: */
2960 if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown))
2961#if 1
2962 /* If request to read data as "uninterpreted", then use the current
2963 encoding: */
2964 fmt = fpr_state[fpr];
2965#else
2966 fmt = fmt_long;
2967#endif
2968
2969 /* For values not yet accessed, set to the desired format: */
2970 if (fpr_state[fpr] == fmt_uninterpreted) {
2971 fpr_state[fpr] = fmt;
2972#ifdef DEBUG
2973 printf("DBG: Register %d was fmt_uninterpreted. Now %s\n",fpr,DOFMT(fmt));
2974#endif /* DEBUG */
2975 }
2976 if (fmt != fpr_state[fpr]) {
f24b7b69 2977 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
2978 fpr_state[fpr] = fmt_unknown;
2979 }
2980
2981 if (fpr_state[fpr] == fmt_unknown) {
2982 /* Set QNaN value: */
2983 switch (fmt) {
2984 case fmt_single:
2985 value = FPQNaN_SINGLE;
2986 break;
2987
2988 case fmt_double:
2989 value = FPQNaN_DOUBLE;
2990 break;
2991
2992 case fmt_word:
2993 value = FPQNaN_WORD;
2994 break;
2995
2996 case fmt_long:
2997 value = FPQNaN_LONG;
2998 break;
2999
3000 default:
3001 err = -1;
3002 break;
3003 }
3004 } else if (SizeFGR() == 64) {
3005 switch (fmt) {
3006 case fmt_single:
3007 case fmt_word:
3008 value = (FGR[fpr] & 0xFFFFFFFF);
3009 break;
3010
3011 case fmt_uninterpreted:
3012 case fmt_double:
3013 case fmt_long:
3014 value = FGR[fpr];
3015 break;
3016
3017 default :
3018 err = -1;
3019 break;
3020 }
da0bce9c 3021 } else {
8bae0a0c
JSC
3022 switch (fmt) {
3023 case fmt_single:
3024 case fmt_word:
3025 value = (FGR[fpr] & 0xFFFFFFFF);
3026 break;
3027
3028 case fmt_uninterpreted:
3029 case fmt_double:
3030 case fmt_long:
da0bce9c
ILT
3031 if ((fpr & 1) == 0) { /* even registers only */
3032 value = ((((uword64)FGR[fpr+1]) << 32) | (FGR[fpr] & 0xFFFFFFFF));
3033 } else {
3034 SignalException (ReservedInstruction, 0);
3035 }
8bae0a0c
JSC
3036 break;
3037
3038 default :
3039 err = -1;
3040 break;
3041 }
3042 }
3043
3044 if (err)
3045 SignalException(SimulatorFault,"Unrecognised FP format in ValueFPR()");
3046
3047#ifdef DEBUG
e871dd18 3048 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
3049#endif /* DEBUG */
3050
3051 return(value);
3052}
3053
3054static void
3055StoreFPR(fpr,fmt,value)
3056 int fpr;
3057 FP_formats fmt;
e871dd18 3058 uword64 value;
8bae0a0c
JSC
3059{
3060 int err = 0;
3061
3062#ifdef DEBUG
e871dd18 3063 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
3064#endif /* DEBUG */
3065
3066 if (SizeFGR() == 64) {
3067 switch (fmt) {
3068 case fmt_single :
3069 case fmt_word :
e871dd18 3070 FGR[fpr] = (((uword64)0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
8bae0a0c
JSC
3071 fpr_state[fpr] = fmt;
3072 break;
3073
3074 case fmt_uninterpreted:
3075 case fmt_double :
3076 case fmt_long :
3077 FGR[fpr] = value;
3078 fpr_state[fpr] = fmt;
3079 break;
3080
3081 default :
3082 fpr_state[fpr] = fmt_unknown;
3083 err = -1;
3084 break;
3085 }
da0bce9c 3086 } else {
8bae0a0c
JSC
3087 switch (fmt) {
3088 case fmt_single :
3089 case fmt_word :
8bae0a0c 3090 FGR[fpr] = (value & 0xFFFFFFFF);
8bae0a0c
JSC
3091 fpr_state[fpr] = fmt;
3092 break;
3093
3094 case fmt_uninterpreted:
3095 case fmt_double :
3096 case fmt_long :
da0bce9c
ILT
3097 if ((fpr & 1) == 0) { /* even register number only */
3098 FGR[fpr+1] = (value >> 32);
3099 FGR[fpr] = (value & 0xFFFFFFFF);
3100 fpr_state[fpr + 1] = fmt;
3101 fpr_state[fpr] = fmt;
3102 } else {
3103 fpr_state[fpr] = fmt_unknown;
3104 fpr_state[fpr + 1] = fmt_unknown;
3105 SignalException (ReservedInstruction, 0);
3106 }
8bae0a0c
JSC
3107 break;
3108
3109 default :
3110 fpr_state[fpr] = fmt_unknown;
3111 err = -1;
3112 break;
3113 }
e871dd18
JSC
3114 }
3115#if defined(WARN_RESULT)
3116 else
3117 UndefinedResult();
3118#endif /* WARN_RESULT */
8bae0a0c
JSC
3119
3120 if (err)
3121 SignalException(SimulatorFault,"Unrecognised FP format in StoreFPR()");
3122
3123#ifdef DEBUG
e871dd18 3124 printf("DBG: StoreFPR: fpr[%d] = 0x%08X%08X (format %s)\n",fpr,WORD64HI(FGR[fpr]),WORD64LO(FGR[fpr]),DOFMT(fmt));
8bae0a0c
JSC
3125#endif /* DEBUG */
3126
3127 return;
3128}
3129
3130static int
3131NaN(op,fmt)
e871dd18 3132 uword64 op;
8bae0a0c
JSC
3133 FP_formats fmt;
3134{
3135 int boolean = 0;
3136
3137 /* Check if (((E - bias) == (E_max + 1)) && (fraction != 0)). We
3138 know that the exponent field is biased... we we cheat and avoid
3139 removing the bias value. */
3140 switch (fmt) {
3141 case fmt_single:
3142 boolean = ((FP_S_be(op) == 0xFF) && (FP_S_f(op) != 0));
3143 /* We could use "FP_S_fb(1,op)" to ascertain whether we are
3144 dealing with a SNaN or QNaN */
3145 break;
3146 case fmt_double:
3147 boolean = ((FP_D_be(op) == 0x7FF) && (FP_D_f(op) != 0));
3148 /* We could use "FP_S_fb(1,op)" to ascertain whether we are
3149 dealing with a SNaN or QNaN */
3150 break;
3151 case fmt_word:
3152 boolean = (op == FPQNaN_WORD);
3153 break;
3154 case fmt_long:
3155 boolean = (op == FPQNaN_LONG);
3156 break;
3157 }
3158
3159#ifdef DEBUG
e871dd18 3160printf("DBG: NaN: returning %d for 0x%08X%08X (format = %s)\n",boolean,WORD64HI(op),WORD64LO(op),DOFMT(fmt));
8bae0a0c
JSC
3161#endif /* DEBUG */
3162
3163 return(boolean);
3164}
3165
3166static int
3167Infinity(op,fmt)
e871dd18 3168 uword64 op;
8bae0a0c
JSC
3169 FP_formats fmt;
3170{
3171 int boolean = 0;
3172
3173#ifdef DEBUG
e871dd18 3174 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
3175#endif /* DEBUG */
3176
3177 /* Check if (((E - bias) == (E_max + 1)) && (fraction == 0)). We
3178 know that the exponent field is biased... we we cheat and avoid
3179 removing the bias value. */
3180 switch (fmt) {
3181 case fmt_single:
3182 boolean = ((FP_S_be(op) == 0xFF) && (FP_S_f(op) == 0));
3183 break;
3184 case fmt_double:
3185 boolean = ((FP_D_be(op) == 0x7FF) && (FP_D_f(op) == 0));
3186 break;
3187 default:
3188 printf("DBG: TODO: unrecognised format (%s) for Infinity check\n",DOFMT(fmt));
3189 break;
3190 }
3191
3192#ifdef DEBUG
e871dd18 3193 printf("DBG: Infinity: returning %d for 0x%08X%08X (format = %s)\n",boolean,WORD64HI(op),WORD64LO(op),DOFMT(fmt));
8bae0a0c
JSC
3194#endif /* DEBUG */
3195
3196 return(boolean);
3197}
3198
3199static int
3200Less(op1,op2,fmt)
e871dd18
JSC
3201 uword64 op1;
3202 uword64 op2;
8bae0a0c
JSC
3203 FP_formats fmt;
3204{
3205 int boolean = 0;
3206
e871dd18
JSC
3207 /* Argument checking already performed by the FPCOMPARE code */
3208
8bae0a0c 3209#ifdef DEBUG
e871dd18 3210 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
3211#endif /* DEBUG */
3212
8bae0a0c
JSC
3213 /* The format type should already have been checked: */
3214 switch (fmt) {
3215 case fmt_single:
3216 {
3217 unsigned int wop1 = (unsigned int)op1;
3218 unsigned int wop2 = (unsigned int)op2;
3219 boolean = (*(float *)&wop1 < *(float *)&wop2);
3220 }
3221 break;
3222 case fmt_double:
3223 boolean = (*(double *)&op1 < *(double *)&op2);
3224 break;
3225 }
3226
3227#ifdef DEBUG
3228 printf("DBG: Less: returning %d (format = %s)\n",boolean,DOFMT(fmt));
3229#endif /* DEBUG */
3230
3231 return(boolean);
3232}
3233
3234static int
3235Equal(op1,op2,fmt)
e871dd18
JSC
3236 uword64 op1;
3237 uword64 op2;
8bae0a0c
JSC
3238 FP_formats fmt;
3239{
3240 int boolean = 0;
3241
e871dd18
JSC
3242 /* Argument checking already performed by the FPCOMPARE code */
3243
8bae0a0c 3244#ifdef DEBUG
e871dd18 3245 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
3246#endif /* DEBUG */
3247
8bae0a0c
JSC
3248 /* The format type should already have been checked: */
3249 switch (fmt) {
3250 case fmt_single:
3251 boolean = ((op1 & 0xFFFFFFFF) == (op2 & 0xFFFFFFFF));
3252 break;
3253 case fmt_double:
3254 boolean = (op1 == op2);
3255 break;
3256 }
3257
3258#ifdef DEBUG
3259 printf("DBG: Equal: returning %d (format = %s)\n",boolean,DOFMT(fmt));
3260#endif /* DEBUG */
3261
3262 return(boolean);
3263}
3264
a9f7253f
JSC
3265static uword64
3266AbsoluteValue(op,fmt)
3267 uword64 op;
3268 FP_formats fmt;
3269{
3270 uword64 result;
3271
3272#ifdef DEBUG
3273 printf("DBG: AbsoluteValue: %s: op = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op),WORD64LO(op));
3274#endif /* DEBUG */
3275
3276 /* The format type should already have been checked: */
3277 switch (fmt) {
3278 case fmt_single:
3279 {
3280 unsigned int wop = (unsigned int)op;
3281 float tmp = ((float)fabs((double)*(float *)&wop));
3282 result = (uword64)*(unsigned int *)&tmp;
3283 }
3284 break;
3285 case fmt_double:
3286 {
3287 double tmp = (fabs(*(double *)&op));
3288 result = *(uword64 *)&tmp;
3289 }
3290 }
3291
3292 return(result);
3293}
3294
e871dd18 3295static uword64
8bae0a0c 3296Negate(op,fmt)
e871dd18 3297 uword64 op;
8bae0a0c
JSC
3298 FP_formats fmt;
3299{
e871dd18 3300 uword64 result;
8bae0a0c
JSC
3301
3302#ifdef DEBUG
e871dd18 3303 printf("DBG: Negate: %s: op = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op),WORD64LO(op));
8bae0a0c
JSC
3304#endif /* DEBUG */
3305
3306 /* The format type should already have been checked: */
3307 switch (fmt) {
3308 case fmt_single:
3309 {
3310 unsigned int wop = (unsigned int)op;
3311 float tmp = ((float)0.0 - *(float *)&wop);
e871dd18 3312 result = (uword64)*(unsigned int *)&tmp;
8bae0a0c
JSC
3313 }
3314 break;
3315 case fmt_double:
3316 {
3317 double tmp = ((double)0.0 - *(double *)&op);
e871dd18 3318 result = *(uword64 *)&tmp;
8bae0a0c
JSC
3319 }
3320 break;
3321 }
3322
3323 return(result);
3324}
3325
e871dd18 3326static uword64
8bae0a0c 3327Add(op1,op2,fmt)
e871dd18
JSC
3328 uword64 op1;
3329 uword64 op2;
8bae0a0c
JSC
3330 FP_formats fmt;
3331{
e871dd18 3332 uword64 result;
8bae0a0c
JSC
3333
3334#ifdef DEBUG
e871dd18 3335 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
3336#endif /* DEBUG */
3337
e871dd18
JSC
3338 /* The registers must specify FPRs valid for operands of type
3339 "fmt". If they are not valid, the result is undefined. */
8bae0a0c
JSC
3340
3341 /* The format type should already have been checked: */
3342 switch (fmt) {
3343 case fmt_single:
3344 {
3345 unsigned int wop1 = (unsigned int)op1;
3346 unsigned int wop2 = (unsigned int)op2;
3347 float tmp = (*(float *)&wop1 + *(float *)&wop2);
e871dd18 3348 result = (uword64)*(unsigned int *)&tmp;
8bae0a0c
JSC
3349 }
3350 break;
3351 case fmt_double:
3352 {
3353 double tmp = (*(double *)&op1 + *(double *)&op2);
e871dd18 3354 result = *(uword64 *)&tmp;
8bae0a0c
JSC
3355 }
3356 break;
3357 }
3358
3359#ifdef DEBUG
e871dd18 3360 printf("DBG: Add: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
8bae0a0c
JSC
3361#endif /* DEBUG */
3362
3363 return(result);
3364}
3365
e871dd18 3366static uword64
8bae0a0c 3367Sub(op1,op2,fmt)
e871dd18
JSC
3368 uword64 op1;
3369 uword64 op2;
8bae0a0c
JSC
3370 FP_formats fmt;
3371{
e871dd18 3372 uword64 result;
8bae0a0c
JSC
3373
3374#ifdef DEBUG
a9f7253f 3375 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
3376#endif /* DEBUG */
3377
e871dd18
JSC
3378 /* The registers must specify FPRs valid for operands of type
3379 "fmt". If they are not valid, the result is undefined. */
8bae0a0c
JSC
3380
3381 /* The format type should already have been checked: */
3382 switch (fmt) {
3383 case fmt_single:
3384 {
3385 unsigned int wop1 = (unsigned int)op1;
3386 unsigned int wop2 = (unsigned int)op2;
3387 float tmp = (*(float *)&wop1 - *(float *)&wop2);
e871dd18 3388 result = (uword64)*(unsigned int *)&tmp;
8bae0a0c
JSC
3389 }
3390 break;
3391 case fmt_double:
3392 {
3393 double tmp = (*(double *)&op1 - *(double *)&op2);
e871dd18 3394 result = *(uword64 *)&tmp;
8bae0a0c
JSC
3395 }
3396 break;
3397 }
3398
3399#ifdef DEBUG
e871dd18 3400 printf("DBG: Sub: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
8bae0a0c
JSC
3401#endif /* DEBUG */
3402
3403 return(result);
3404}
3405
e871dd18 3406static uword64
8bae0a0c 3407Multiply(op1,op2,fmt)
e871dd18
JSC
3408 uword64 op1;
3409 uword64 op2;
8bae0a0c
JSC
3410 FP_formats fmt;
3411{
e871dd18 3412 uword64 result;
8bae0a0c
JSC
3413
3414#ifdef DEBUG
e871dd18 3415 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
3416#endif /* DEBUG */
3417
e871dd18
JSC
3418 /* The registers must specify FPRs valid for operands of type
3419 "fmt". If they are not valid, the result is undefined. */
8bae0a0c
JSC
3420
3421 /* The format type should already have been checked: */
3422 switch (fmt) {
3423 case fmt_single:
3424 {
3425 unsigned int wop1 = (unsigned int)op1;
3426 unsigned int wop2 = (unsigned int)op2;
3427 float tmp = (*(float *)&wop1 * *(float *)&wop2);
e871dd18 3428 result = (uword64)*(unsigned int *)&tmp;
8bae0a0c
JSC
3429 }
3430 break;
3431 case fmt_double:
3432 {
3433 double tmp = (*(double *)&op1 * *(double *)&op2);
e871dd18 3434 result = *(uword64 *)&tmp;
8bae0a0c
JSC
3435 }
3436 break;
3437 }
3438
3439#ifdef DEBUG
e871dd18 3440 printf("DBG: Multiply: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
8bae0a0c
JSC
3441#endif /* DEBUG */
3442
3443 return(result);
3444}
3445
e871dd18 3446static uword64
8bae0a0c 3447Divide(op1,op2,fmt)
e871dd18
JSC
3448 uword64 op1;
3449 uword64 op2;
8bae0a0c
JSC
3450 FP_formats fmt;
3451{
e871dd18 3452 uword64 result;
8bae0a0c
JSC
3453
3454#ifdef DEBUG
e871dd18 3455 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
3456#endif /* DEBUG */
3457
e871dd18
JSC
3458 /* The registers must specify FPRs valid for operands of type
3459 "fmt". If they are not valid, the result is undefined. */
8bae0a0c
JSC
3460
3461 /* The format type should already have been checked: */
3462 switch (fmt) {
3463 case fmt_single:
3464 {
3465 unsigned int wop1 = (unsigned int)op1;
3466 unsigned int wop2 = (unsigned int)op2;
3467 float tmp = (*(float *)&wop1 / *(float *)&wop2);
e871dd18 3468 result = (uword64)*(unsigned int *)&tmp;
8bae0a0c
JSC
3469 }
3470 break;
3471 case fmt_double:
3472 {
3473 double tmp = (*(double *)&op1 / *(double *)&op2);
e871dd18 3474 result = *(uword64 *)&tmp;
8bae0a0c
JSC
3475 }
3476 break;
3477 }
3478
3479#ifdef DEBUG
e871dd18 3480 printf("DBG: Divide: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
8bae0a0c
JSC
3481#endif /* DEBUG */
3482
3483 return(result);
3484}
3485
e871dd18 3486static uword64
8bae0a0c 3487Recip(op,fmt)
e871dd18 3488 uword64 op;
8bae0a0c
JSC
3489 FP_formats fmt;
3490{
e871dd18 3491 uword64 result;
8bae0a0c
JSC
3492
3493#ifdef DEBUG
e871dd18 3494 printf("DBG: Recip: %s: op = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op),WORD64LO(op));
8bae0a0c
JSC
3495#endif /* DEBUG */
3496
e871dd18
JSC
3497 /* The registers must specify FPRs valid for operands of type
3498 "fmt". If they are not valid, the result is undefined. */
8bae0a0c
JSC
3499
3500 /* The format type should already have been checked: */
3501 switch (fmt) {
3502 case fmt_single:
3503 {
3504 unsigned int wop = (unsigned int)op;
3505 float tmp = ((float)1.0 / *(float *)&wop);
e871dd18 3506 result = (uword64)*(unsigned int *)&tmp;
8bae0a0c
JSC
3507 }
3508 break;
3509 case fmt_double:
3510 {
3511 double tmp = ((double)1.0 / *(double *)&op);
e871dd18 3512 result = *(uword64 *)&tmp;
8bae0a0c
JSC
3513 }
3514 break;
3515 }
3516
3517#ifdef DEBUG
e871dd18 3518 printf("DBG: Recip: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
8bae0a0c
JSC
3519#endif /* DEBUG */
3520
3521 return(result);
3522}
3523
e871dd18 3524static uword64
8bae0a0c 3525SquareRoot(op,fmt)
e871dd18 3526 uword64 op;
8bae0a0c
JSC
3527 FP_formats fmt;
3528{
e871dd18 3529 uword64 result;
8bae0a0c
JSC
3530
3531#ifdef DEBUG
e871dd18 3532 printf("DBG: SquareRoot: %s: op = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op),WORD64LO(op));
8bae0a0c
JSC
3533#endif /* DEBUG */
3534
e871dd18
JSC
3535 /* The registers must specify FPRs valid for operands of type
3536 "fmt". If they are not valid, the result is undefined. */
8bae0a0c
JSC
3537
3538 /* The format type should already have been checked: */
3539 switch (fmt) {
3540 case fmt_single:
3541 {
3542 unsigned int wop = (unsigned int)op;
e3d12c65 3543#ifdef HAVE_SQRT
8bae0a0c 3544 float tmp = ((float)sqrt((double)*(float *)&wop));
e871dd18 3545 result = (uword64)*(unsigned int *)&tmp;
e3d12c65
DE
3546#else
3547 /* TODO: Provide square-root */
3548 result = (uword64)0;
3549#endif
8bae0a0c
JSC
3550 }
3551 break;
3552 case fmt_double:
3553 {
e3d12c65 3554#ifdef HAVE_SQRT
8bae0a0c 3555 double tmp = (sqrt(*(double *)&op));
e871dd18 3556 result = *(uword64 *)&tmp;
e3d12c65
DE
3557#else
3558 /* TODO: Provide square-root */
3559 result = (uword64)0;
3560#endif
8bae0a0c
JSC
3561 }
3562 break;
3563 }
3564
3565#ifdef DEBUG
e871dd18 3566 printf("DBG: SquareRoot: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
8bae0a0c
JSC
3567#endif /* DEBUG */
3568
3569 return(result);
3570}
3571
e871dd18 3572static uword64
8bae0a0c
JSC
3573Convert(rm,op,from,to)
3574 int rm;
e871dd18 3575 uword64 op;
8bae0a0c
JSC
3576 FP_formats from;
3577 FP_formats to;
3578{
e871dd18 3579 uword64 result;
8bae0a0c
JSC
3580
3581#ifdef DEBUG
e871dd18 3582 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
3583#endif /* DEBUG */
3584
3585 /* The value "op" is converted to the destination format, rounding
3586 using mode "rm". When the destination is a fixed-point format,
3587 then a source value of Infinity, NaN or one which would round to
3588 an integer outside the fixed point range then an IEEE Invalid
3589 Operation condition is raised. */
3590 switch (to) {
3591 case fmt_single:
3592 {
3593 float tmp;
3594 switch (from) {
3595 case fmt_double:
3596 tmp = (float)(*(double *)&op);
3597 break;
3598
3599 case fmt_word:
3600 tmp = (float)((int)(op & 0xFFFFFFFF));
3601 break;
3602
3603 case fmt_long:
e3d12c65 3604 tmp = (float)((word64)op);
8bae0a0c
JSC
3605 break;
3606 }
3607
458e1f58
ILT
3608#if 0
3609 /* FIXME: This code is incorrect. The rounding mode does not
3610 round to integral values; it rounds to the nearest
3611 representable value in the format. */
3612
8bae0a0c
JSC
3613 switch (rm) {
3614 case FP_RM_NEAREST:
e871dd18
JSC
3615 /* Round result to nearest representable value. When two
3616 representable values are equally near, round to the value
3617 that has a least significant bit of zero (i.e. is even). */
4fa134be 3618#ifdef HAVE_ANINT
e871dd18 3619 tmp = (float)anint((double)tmp);
d0757082
JSC
3620#else
3621 /* TODO: Provide round-to-nearest */
3622#endif
8bae0a0c
JSC
3623 break;
3624
3625 case FP_RM_TOZERO:
e871dd18
JSC
3626 /* Round result to the value closest to, and not greater in
3627 magnitude than, the result. */
4fa134be 3628#ifdef HAVE_AINT
e871dd18 3629 tmp = (float)aint((double)tmp);
d0757082
JSC
3630#else
3631 /* TODO: Provide round-to-zero */
3632#endif
8bae0a0c
JSC
3633 break;
3634
3635 case FP_RM_TOPINF:
e871dd18
JSC
3636 /* Round result to the value closest to, and not less than,
3637 the result. */
3638 tmp = (float)ceil((double)tmp);
8bae0a0c
JSC
3639 break;
3640
3641 case FP_RM_TOMINF:
e871dd18
JSC
3642 /* Round result to the value closest to, and not greater than,
3643 the result. */
3644 tmp = (float)floor((double)tmp);
8bae0a0c
JSC
3645 break;
3646 }
458e1f58
ILT
3647#endif /* 0 */
3648
e871dd18 3649 result = (uword64)*(unsigned int *)&tmp;
8bae0a0c
JSC
3650 }
3651 break;
3652
3653 case fmt_double:
3654 {
3655 double tmp;
f24b7b69 3656 word64 xxx;
8bae0a0c
JSC
3657
3658 switch (from) {
3659 case fmt_single:
3660 {
3661 unsigned int wop = (unsigned int)op;
3662 tmp = (double)(*(float *)&wop);
3663 }
3664 break;
3665
3666 case fmt_word:
f24b7b69 3667 xxx = SIGNEXTEND((op & 0xFFFFFFFF),32);
e3d12c65 3668 tmp = (double)xxx;
8bae0a0c
JSC
3669 break;
3670
3671 case fmt_long:
e871dd18 3672 tmp = (double)((word64)op);
8bae0a0c
JSC
3673 break;
3674 }
e871dd18 3675
458e1f58
ILT
3676#if 0
3677 /* FIXME: This code is incorrect. The rounding mode does not
3678 round to integral values; it rounds to the nearest
3679 representable value in the format. */
3680
8bae0a0c
JSC
3681 switch (rm) {
3682 case FP_RM_NEAREST:
4fa134be 3683#ifdef HAVE_ANINT
e871dd18 3684 tmp = anint(*(double *)&tmp);
d0757082
JSC
3685#else
3686 /* TODO: Provide round-to-nearest */
3687#endif
8bae0a0c
JSC
3688 break;
3689
3690 case FP_RM_TOZERO:
4fa134be 3691#ifdef HAVE_AINT
e871dd18 3692 tmp = aint(*(double *)&tmp);
d0757082
JSC
3693#else
3694 /* TODO: Provide round-to-zero */
3695#endif
8bae0a0c
JSC
3696 break;
3697
3698 case FP_RM_TOPINF:
3699 tmp = ceil(*(double *)&tmp);
3700 break;
3701
3702 case FP_RM_TOMINF:
3703 tmp = floor(*(double *)&tmp);
3704 break;
3705 }
458e1f58
ILT
3706#endif /* 0 */
3707
e871dd18 3708 result = *(uword64 *)&tmp;
8bae0a0c
JSC
3709 }
3710 break;
3711
3712 case fmt_word:
3713 case fmt_long:
3714 if (Infinity(op,from) || NaN(op,from) || (1 == 0/*TODO: check range */)) {
3715 printf("DBG: TODO: update FCSR\n");
3716 SignalException(FPE);
3717 } else {
3718 if (to == fmt_word) {
e3d12c65 3719 int tmp;
8bae0a0c
JSC
3720 switch (from) {
3721 case fmt_single:
3722 {
3723 unsigned int wop = (unsigned int)op;
e3d12c65 3724 tmp = (int)*((float *)&wop);
8bae0a0c
JSC
3725 }
3726 break;
3727 case fmt_double:
e3d12c65 3728 tmp = (int)*((double *)&op);
8bae0a0c 3729#ifdef DEBUG
e871dd18 3730 printf("DBG: from double %.30f (0x%08X%08X) to word: 0x%08X\n",*((double *)&op),WORD64HI(op),WORD64LO(op),tmp);
8bae0a0c
JSC
3731#endif /* DEBUG */
3732 break;
3733 }
e871dd18 3734 result = (uword64)tmp;
8bae0a0c 3735 } else { /* fmt_long */
e3d12c65 3736 word64 tmp;
8bae0a0c
JSC
3737 switch (from) {
3738 case fmt_single:
3739 {
3740 unsigned int wop = (unsigned int)op;
e3d12c65 3741 tmp = (word64)*((float *)&wop);
8bae0a0c
JSC
3742 }
3743 break;
3744 case fmt_double:
e3d12c65 3745 tmp = (word64)*((double *)&op);
8bae0a0c
JSC
3746 break;
3747 }
e3d12c65 3748 result = (uword64)tmp;
8bae0a0c
JSC
3749 }
3750 }
3751 break;
3752 }
3753
3754#ifdef DEBUG
e871dd18 3755 printf("DBG: Convert: returning 0x%08X%08X (to format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(to));
8bae0a0c
JSC
3756#endif /* DEBUG */
3757
3758 return(result);
3759}
3760#endif /* HASFPU */
3761
3762/*-- co-processor support routines ------------------------------------------*/
3763
3764static int
3765CoProcPresent(coproc_number)
3766 unsigned int coproc_number;
3767{
3768 /* Return TRUE if simulator provides a model for the given co-processor number */
3769 return(0);
3770}
3771
3772static void
3773COP_LW(coproc_num,coproc_reg,memword)
3774 int coproc_num, coproc_reg;
3775 unsigned int memword;
3776{
3777 switch (coproc_num) {
3778#if defined(HASFPU)
3779 case 1:
3780#ifdef DEBUG
e871dd18 3781 printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%08X%08X\n",memword,WORD64HI(memword),WORD64LO(memword));
8bae0a0c 3782#endif
da0bce9c
ILT
3783 StoreFPR(coproc_reg,fmt_word,(uword64)memword);
3784 fpr_state[coproc_reg] = fmt_uninterpreted;
8bae0a0c
JSC
3785 break;
3786#endif /* HASFPU */
3787
3788 default:
f24b7b69 3789#if 0 /* this should be controlled by a configuration option */
e871dd18 3790 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 3791#endif
8bae0a0c
JSC
3792 break;
3793 }
3794
3795 return;
3796}
3797
3798static void
3799COP_LD(coproc_num,coproc_reg,memword)
3800 int coproc_num, coproc_reg;
e871dd18 3801 uword64 memword;
8bae0a0c
JSC
3802{
3803 switch (coproc_num) {
3804#if defined(HASFPU)
3805 case 1:
3806 StoreFPR(coproc_reg,fmt_uninterpreted,memword);
3807 break;
3808#endif /* HASFPU */
3809
3810 default:
f24b7b69 3811#if 0 /* this message should be controlled by a configuration option */
e871dd18 3812 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 3813#endif
8bae0a0c
JSC
3814 break;
3815 }
3816
3817 return;
3818}
3819
3820static unsigned int
3821COP_SW(coproc_num,coproc_reg)
3822 int coproc_num, coproc_reg;
3823{
3824 unsigned int value = 0;
da0bce9c
ILT
3825 FP_formats hold;
3826
8bae0a0c
JSC
3827 switch (coproc_num) {
3828#if defined(HASFPU)
3829 case 1:
3830#if 1
da0bce9c
ILT
3831 hold = fpr_state[coproc_reg];
3832 fpr_state[coproc_reg] = fmt_word;
8bae0a0c 3833 value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted);
da0bce9c 3834 fpr_state[coproc_reg] = hold;
8bae0a0c
JSC
3835#else
3836#if 1
3837 value = (unsigned int)ValueFPR(coproc_reg,fpr_state[coproc_reg]);
3838#else
3839#ifdef DEBUG
3840 printf("DBG: COP_SW: reg in format %s (will be accessing as single)\n",DOFMT(fpr_state[coproc_reg]));
3841#endif /* DEBUG */
3842 value = (unsigned int)ValueFPR(coproc_reg,fmt_single);
3843#endif
3844#endif
3845 break;
3846#endif /* HASFPU */
3847
3848 default:
f24b7b69 3849#if 0 /* should be controlled by configuration option */
e871dd18 3850 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 3851#endif
8bae0a0c
JSC
3852 break;
3853 }
3854
3855 return(value);
3856}
3857
e871dd18 3858static uword64
8bae0a0c
JSC
3859COP_SD(coproc_num,coproc_reg)
3860 int coproc_num, coproc_reg;
3861{
e871dd18 3862 uword64 value = 0;
8bae0a0c
JSC
3863 switch (coproc_num) {
3864#if defined(HASFPU)
3865 case 1:
3866#if 1
3867 value = ValueFPR(coproc_reg,fmt_uninterpreted);
3868#else
3869#if 1
3870 value = ValueFPR(coproc_reg,fpr_state[coproc_reg]);
3871#else
3872#ifdef DEBUG
3873 printf("DBG: COP_SD: reg in format %s (will be accessing as double)\n",DOFMT(fpr_state[coproc_reg]));
3874#endif /* DEBUG */
3875 value = ValueFPR(coproc_reg,fmt_double);
3876#endif
3877#endif
3878 break;
3879#endif /* HASFPU */
3880
3881 default:
f24b7b69 3882#if 0 /* should be controlled by configuration option */
e871dd18 3883 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 3884#endif
8bae0a0c
JSC
3885 break;
3886 }
3887
3888 return(value);
3889}
3890
3891static void
3892decode_coproc(instruction)
3893 unsigned int instruction;
3894{
3895 int coprocnum = ((instruction >> 26) & 3);
3896
3897 switch (coprocnum) {
3898 case 0: /* standard CPU control and cache registers */
3899 {
3900 /* NOTEs:
3901 Standard CP0 registers
3902 0 = Index R4000 VR4100 VR4300
3903 1 = Random R4000 VR4100 VR4300
3904 2 = EntryLo0 R4000 VR4100 VR4300
3905 3 = EntryLo1 R4000 VR4100 VR4300
3906 4 = Context R4000 VR4100 VR4300
3907 5 = PageMask R4000 VR4100 VR4300
3908 6 = Wired R4000 VR4100 VR4300
3909 8 = BadVAddr R4000 VR4100 VR4300
3910 9 = Count R4000 VR4100 VR4300
3911 10 = EntryHi R4000 VR4100 VR4300
3912 11 = Compare R4000 VR4100 VR4300
3913 12 = SR R4000 VR4100 VR4300
3914 13 = Cause R4000 VR4100 VR4300
3915 14 = EPC R4000 VR4100 VR4300
3916 15 = PRId R4000 VR4100 VR4300
3917 16 = Config R4000 VR4100 VR4300
3918 17 = LLAddr R4000 VR4100 VR4300
3919 18 = WatchLo R4000 VR4100 VR4300
3920 19 = WatchHi R4000 VR4100 VR4300
3921 20 = XContext R4000 VR4100 VR4300
3922 26 = PErr or ECC R4000 VR4100 VR4300
3923 27 = CacheErr R4000 VR4100
3924 28 = TagLo R4000 VR4100 VR4300
3925 29 = TagHi R4000 VR4100 VR4300
3926 30 = ErrorEPC R4000 VR4100 VR4300
3927 */
3928 int code = ((instruction >> 21) & 0x1F);
3929 /* R4000 Users Manual (second edition) lists the following CP0
3930 instructions:
3931 DMFC0 Doubleword Move From CP0 (VR4100 = 01000000001tttttddddd00000000000)
3932 DMTC0 Doubleword Move To CP0 (VR4100 = 01000000101tttttddddd00000000000)
3933 MFC0 word Move From CP0 (VR4100 = 01000000000tttttddddd00000000000)
3934 MTC0 word Move To CP0 (VR4100 = 01000000100tttttddddd00000000000)
3935 TLBR Read Indexed TLB Entry (VR4100 = 01000010000000000000000000000001)
3936 TLBWI Write Indexed TLB Entry (VR4100 = 01000010000000000000000000000010)
3937 TLBWR Write Random TLB Entry (VR4100 = 01000010000000000000000000000110)
3938 TLBP Probe TLB for Matching Entry (VR4100 = 01000010000000000000000000001000)
3939 CACHE Cache operation (VR4100 = 101111bbbbbpppppiiiiiiiiiiiiiiii)
3940 ERET Exception return (VR4100 = 01000010000000000000000000011000)
3941 */
3942 if (((code == 0x00) || (code == 0x04)) && ((instruction & 0x7FF) == 0)) {
3943 int rt = ((instruction >> 16) & 0x1F);
3944 int rd = ((instruction >> 11) & 0x1F);
3945 if (code == 0x00) { /* MF : move from */
f24b7b69 3946#if 0 /* message should be controlled by configuration option */
8bae0a0c 3947 callback->printf_filtered(callback,"Warning: MFC0 %d,%d not handled yet (architecture specific)\n",rt,rd);
f24b7b69 3948#endif
8bae0a0c
JSC
3949 GPR[rt] = 0xDEADC0DE; /* CPR[0,rd] */
3950 } else { /* MT : move to */
3951 /* CPR[0,rd] = GPR[rt]; */
f24b7b69 3952#if 0 /* should be controlled by configuration option */
8bae0a0c 3953 callback->printf_filtered(callback,"Warning: MTC0 %d,%d not handled yet (architecture specific)\n",rt,rd);
f24b7b69 3954#endif
8bae0a0c
JSC
3955 }
3956 } else
f24b7b69 3957 sim_warning("Unrecognised COP0 instruction 0x%08X at IPC = 0x%08X%08X : No handler present",instruction,WORD64HI(IPC),WORD64LO(IPC));
e871dd18 3958 /* TODO: When executing an ERET or RFE instruction we should
8bae0a0c
JSC
3959 clear LLBIT, to ensure that any out-standing atomic
3960 read/modify/write sequence fails. */
3961 }
3962 break;
3963
3964 case 2: /* undefined co-processor */
f24b7b69 3965 sim_warning("COP2 instruction 0x%08X at IPC = 0x%08X%08X : No handler present",instruction,WORD64HI(IPC),WORD64LO(IPC));
8bae0a0c
JSC
3966 break;
3967
3968 case 1: /* should not occur (FPU co-processor) */
3969 case 3: /* should not occur (FPU co-processor) */
3970 SignalException(ReservedInstruction,instruction);
3971 break;
3972 }
3973
3974 return;
3975}
3976
3977/*-- instruction simulation -------------------------------------------------*/
3978
3979static void
3980simulate ()
3981{
3982 unsigned int pipeline_count = 1;
3983
3984#ifdef DEBUG
3985 if (membank == NULL) {
3986 printf("DBG: simulate() entered with no memory\n");
3987 exit(1);
3988 }
3989#endif /* DEBUG */
3990
3991#if 0 /* Disabled to check that everything works OK */
3992 /* The VR4300 seems to sign-extend the PC on its first
3993 access. However, this may just be because it is currently
3994 configured in 32bit mode. However... */
3995 PC = SIGNEXTEND(PC,32);
3996#endif
3997
3998 /* main controlling loop */
3999 do {
4000 /* Fetch the next instruction from the simulator memory: */
e871dd18
JSC
4001 uword64 vaddr = (uword64)PC;
4002 uword64 paddr;
8bae0a0c
JSC
4003 int cca;
4004 unsigned int instruction;
4005 int dsstate = (state & simDELAYSLOT);
4006
4007#ifdef DEBUG
4008 {
4009 printf("DBG: state = 0x%08X :",state);
4010 if (state & simSTOP) printf(" simSTOP");
4011 if (state & simSTEP) printf(" simSTEP");
4012 if (state & simHALTEX) printf(" simHALTEX");
4013 if (state & simHALTIN) printf(" simHALTIN");
4014 if (state & simBE) printf(" simBE");
4015 }
4016#endif /* DEBUG */
4017
4018#ifdef DEBUG
4019 if (dsstate)
e871dd18 4020 callback->printf_filtered(callback,"DBG: DSPC = 0x%08X%08X\n",WORD64HI(DSPC),WORD64LO(DSPC));
8bae0a0c
JSC
4021#endif /* DEBUG */
4022
6429b296
JW
4023 if (AddressTranslation(PC,isINSTRUCTION,isLOAD,&paddr,&cca,isTARGET,isREAL)) {
4024 if ((vaddr & 1) == 0) {
4025 /* Copy the action of the LW instruction */
4026 unsigned int reverse = (ReverseEndian ? (LOADDRMASK >> 2) : 0);
4027 unsigned int bigend = (BigEndianCPU ? (LOADDRMASK >> 2) : 0);
4028 uword64 value;
4029 unsigned int byte;
4030 paddr = ((paddr & ~LOADDRMASK) | ((paddr & LOADDRMASK) ^ (reverse << 2)));
4031 value = LoadMemory(cca,AccessLength_WORD,paddr,vaddr,isINSTRUCTION,isREAL);
4032 byte = ((vaddr & LOADDRMASK) ^ (bigend << 2));
4033 instruction = ((value >> (8 * byte)) & 0xFFFFFFFF);
4034 } else {
4035 /* Copy the action of the LH instruction */
4036 unsigned int reverse = (ReverseEndian ? (LOADDRMASK >> 1) : 0);
4037 unsigned int bigend = (BigEndianCPU ? (LOADDRMASK >> 1) : 0);
4038 uword64 value;
4039 unsigned int byte;
4040 paddr = (((paddr & ~ (uword64) 1) & ~LOADDRMASK)
4041 | (((paddr & ~ (uword64) 1) & LOADDRMASK) ^ (reverse << 1)));
4042 value = LoadMemory(cca, AccessLength_HALFWORD,
4043 paddr & ~ (uword64) 1,
4044 vaddr, isINSTRUCTION, isREAL);
4045 byte = (((vaddr &~ (uword64) 1) & LOADDRMASK) ^ (bigend << 1));
4046 instruction = ((value >> (8 * byte)) & 0xFFFF);
4047 }
8bae0a0c 4048 } else {
e871dd18 4049 fprintf(stderr,"Cannot translate address for PC = 0x%08X%08X failed\n",WORD64HI(PC),WORD64LO(PC));
8bae0a0c
JSC
4050 exit(1);
4051 }
4052
4053#ifdef DEBUG
e871dd18 4054 callback->printf_filtered(callback,"DBG: fetched 0x%08X from PC = 0x%08X%08X\n",instruction,WORD64HI(PC),WORD64LO(PC));
8bae0a0c
JSC
4055#endif /* DEBUG */
4056
4057#if !defined(FASTSIM) || defined(PROFILE)
4058 instruction_fetches++;
a9f7253f
JSC
4059 /* Since we increment above, the value should only ever be zero if
4060 we have just overflowed: */
4061 if (instruction_fetches == 0)
4062 instruction_fetch_overflow++;
8bae0a0c
JSC
4063#if defined(PROFILE)
4064 if ((state & simPROFILE) && ((instruction_fetches % profile_frequency) == 0) && profile_hist) {
e3d12c65 4065 unsigned n = ((unsigned int)(PC - profile_minpc) >> (profile_shift + 2));
8bae0a0c
JSC
4066 if (n < profile_nsamples) {
4067 /* NOTE: The counts for the profiling bins are only 16bits wide */
4068 if (profile_hist[n] != USHRT_MAX)
4069 (profile_hist[n])++;
4070 }
4071 }
4072#endif /* PROFILE */
4073#endif /* !FASTSIM && PROFILE */
4074
4075 IPC = PC; /* copy PC for this instruction */
4076 /* This is required by exception processing, to ensure that we can
4077 cope with exceptions in the delay slots of branches that may
4078 already have changed the PC. */
6429b296
JW
4079 if ((vaddr & 1) == 0)
4080 PC += 4; /* increment ready for the next fetch */
4081 else
4082 PC += 2;
8bae0a0c
JSC
4083 /* NOTE: If we perform a delay slot change to the PC, this
4084 increment is not requuired. However, it would make the
4085 simulator more complicated to try and avoid this small hit. */
4086
4087 /* Currently this code provides a simple model. For more
4088 complicated models we could perform exception status checks at
4089 this point, and set the simSTOP state as required. This could
4090 also include processing any hardware interrupts raised by any
4091 I/O model attached to the simulator context.
4092
4093 Support for "asynchronous" I/O events within the simulated world
4094 could be providing by managing a counter, and calling a I/O
4095 specific handler when a particular threshold is reached. On most
4096 architectures a decrement and check for zero operation is
4097 usually quicker than an increment and compare. However, the
4098 process of managing a known value decrement to zero, is higher
4099 than the cost of using an explicit value UINT_MAX into the
4100 future. Which system is used will depend on how complicated the
4101 I/O model is, and how much it is likely to affect the simulator
4102 bandwidth.
4103
4104 If events need to be scheduled further in the future than
4105 UINT_MAX event ticks, then the I/O model should just provide its
4106 own counter, triggered from the event system. */
4107
4108 /* MIPS pipeline ticks. To allow for future support where the
4109 pipeline hit of individual instructions is known, this control
4110 loop manages a "pipeline_count" variable. It is initialised to
4111 1 (one), and will only be changed by the simulator engine when
4112 executing an instruction. If the engine does not have access to
4113 pipeline cycle count information then all instructions will be
4114 treated as using a single cycle. NOTE: A standard system is not
4115 provided by the default simulator because different MIPS
4116 architectures have different cycle counts for the same
4117 instructions. */
4118
4119#if defined(HASFPU)
4120 /* Set previous flag, depending on current: */
4121 if (state & simPCOC0)
4122 state |= simPCOC1;
4123 else
4124 state &= ~simPCOC1;
4125 /* and update the current value: */
4126 if (GETFCC(0))
4127 state |= simPCOC0;
4128 else
4129 state &= ~simPCOC0;
4130#endif /* HASFPU */
4131
4132/* NOTE: For multi-context simulation environments the "instruction"
4133 variable should be local to this routine. */
4134
4135/* Shorthand accesses for engine. Note: If we wanted to use global
4136 variables (and a single-threaded simulator engine), then we can
4137 create the actual variables with these names. */
4138
4139 if (!(state & simSKIPNEXT)) {
4140 /* Include the simulator engine */
4141#include "engine.c"
f24b7b69 4142#if ((GPRLEN == 64) && !PROCESSOR_64BIT) || ((GPRLEN == 32) && PROCESSOR_64BIT)
8bae0a0c
JSC
4143#error "Mismatch between run-time simulator code and simulation engine"
4144#endif
4145
4146#if defined(WARN_LOHI)
4147 /* Decrement the HI/LO validity ticks */
4148 if (HIACCESS > 0)
4149 HIACCESS--;
4150 if (LOACCESS > 0)
4151 LOACCESS--;
4152#endif /* WARN_LOHI */
4153
4154#if defined(WARN_ZERO)
4155 /* For certain MIPS architectures, GPR[0] is hardwired to zero. We
4156 should check for it being changed. It is better doing it here,
4157 than within the simulator, since it will help keep the simulator
4158 small. */
4159 if (ZERO != 0) {
f24b7b69 4160 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
4161 ZERO = 0; /* reset back to zero before next instruction */
4162 }
4163#endif /* WARN_ZERO */
4164 } else /* simSKIPNEXT check */
4165 state &= ~simSKIPNEXT;
4166
4167 /* If the delay slot was active before the instruction is
4168 executed, then update the PC to its new value: */
4169 if (dsstate) {
4170#ifdef DEBUG
e871dd18 4171 printf("DBG: dsstate set before instruction execution - updating PC to 0x%08X%08X\n",WORD64HI(DSPC),WORD64LO(DSPC));
8bae0a0c
JSC
4172#endif /* DEBUG */
4173 PC = DSPC;
aaff8437 4174 state &= ~(simDELAYSLOT | simJALDELAYSLOT);
8bae0a0c
JSC
4175 }
4176
4177 if (MIPSISA < 4) { /* The following is only required on pre MIPS IV processors: */
4178 /* Deal with pending register updates: */
4179#ifdef DEBUG
4180 printf("DBG: EMPTY BEFORE pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total);
4181#endif /* DEBUG */
4182 if (pending_out != pending_in) {
4183 int loop;
4184 int index = pending_out;
4185 int total = pending_total;
4186 if (pending_total == 0) {
4187 fprintf(stderr,"FATAL: Mis-match on pending update pointers\n");
4188 exit(1);
4189 }
4190 for (loop = 0; (loop < total); loop++) {
4191#ifdef DEBUG
4192 printf("DBG: BEFORE index = %d, loop = %d\n",index,loop);
4193#endif /* DEBUG */
4194 if (pending_slot_reg[index] != (LAST_EMBED_REGNUM + 1)) {
4195#ifdef DEBUG
4196 printf("pending_slot_count[%d] = %d\n",index,pending_slot_count[index]);
4197#endif /* DEBUG */
4198 if (--(pending_slot_count[index]) == 0) {
4199#ifdef DEBUG
4200 printf("pending_slot_reg[%d] = %d\n",index,pending_slot_reg[index]);
e871dd18 4201 printf("pending_slot_value[%d] = 0x%08X%08X\n",index,WORD64HI(pending_slot_value[index]),WORD64LO(pending_slot_value[index]));
8bae0a0c
JSC
4202#endif /* DEBUG */
4203 if (pending_slot_reg[index] == COCIDX) {
4204 SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0));
4205 } else {
4206 registers[pending_slot_reg[index]] = pending_slot_value[index];
4207#if defined(HASFPU)
4208 /* The only time we have PENDING updates to FPU
4209 registers, is when performing binary transfers. This
4210 means we should update the register type field. */
4211 if ((pending_slot_reg[index] >= FGRIDX) && (pending_slot_reg[index] < (FGRIDX + 32)))
7e6c297e 4212 fpr_state[pending_slot_reg[index] - FGRIDX] = fmt_uninterpreted;
8bae0a0c
JSC
4213#endif /* HASFPU */
4214 }
4215#ifdef DEBUG
e871dd18 4216 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
4217#endif /* DEBUG */
4218 pending_slot_reg[index] = (LAST_EMBED_REGNUM + 1);
4219 pending_out++;
4220 if (pending_out == PSLOTS)
4221 pending_out = 0;
4222 pending_total--;
4223 }
4224 }
4225#ifdef DEBUG
4226 printf("DBG: AFTER index = %d, loop = %d\n",index,loop);
4227#endif /* DEBUG */
4228 index++;
4229 if (index == PSLOTS)
4230 index = 0;
4231 }
4232 }
4233#ifdef DEBUG
4234 printf("DBG: EMPTY AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total);
4235#endif /* DEBUG */
4236 }
4237
4238#if !defined(FASTSIM)
4239 pipeline_ticks += pipeline_count;
4240#endif /* FASTSIM */
4241
4242 if (state & simSTEP)
4243 state |= simSTOP;
4244 } while (!(state & simSTOP));
4245
4246#ifdef DEBUG
4247 if (membank == NULL) {
4248 printf("DBG: simulate() LEAVING with no memory\n");
4249 exit(1);
4250 }
4251#endif /* DEBUG */
4252
4253 return;
4254}
4255
4256/*---------------------------------------------------------------------------*/
4257/*> EOF interp.c <*/
This page took 0.243854 seconds and 4 git commands to generate.