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