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