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