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