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