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