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