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