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