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