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