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