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