2 /* Simulator for the MIPS architecture.
4 This file is part of the MIPS sim
6 THIS SOFTWARE IS NOT COPYRIGHTED
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.
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.
22 The IDT monitor (found on the VR4300 board), seems to lie about
23 register contents. It seems to treat the registers as sign-extended
24 32-bit values. This cause *REAL* problems when single-stepping 64-bit
29 /* The TRACE manifests enable the provision of extra features. If they
30 are not defined then a simpler (quicker) simulator is constructed
31 without the required run-time checks, etc. */
32 #if 1 /* 0 to allow user build selection, 1 to force inclusion */
38 #include "sim-utils.h"
39 #include "sim-options.h"
40 #include "sim-assert.h"
62 #include "libiberty.h"
64 #include "callback.h" /* GDB simulator callback interface */
65 #include "remote-sim.h" /* GDB simulator interface */
73 char* pr_addr
PARAMS ((SIM_ADDR addr
));
74 char* pr_uword64
PARAMS ((uword64 addr
));
77 /* Get the simulator engine description, without including the code: */
79 #define LOADDRMASK (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3)
86 /* Within interp.c we refer to the sim_state and sim_cpu directly. */
91 /* The following reserved instruction value is used when a simulator
92 trap is required. NOTE: Care must be taken, since this value may be
93 used in later revisions of the MIPS ISA. */
94 #define RSVD_INSTRUCTION (0x00000005)
95 #define RSVD_INSTRUCTION_MASK (0xFC00003F)
97 #define RSVD_INSTRUCTION_ARG_SHIFT 6
98 #define RSVD_INSTRUCTION_ARG_MASK 0xFFFFF
101 /* Bits in the Debug register */
102 #define Debug_DBD 0x80000000 /* Debug Branch Delay */
103 #define Debug_DM 0x40000000 /* Debug Mode */
104 #define Debug_DBp 0x00000002 /* Debug Breakpoint indicator */
110 /*---------------------------------------------------------------------------*/
111 /*-- GDB simulator interface ------------------------------------------------*/
112 /*---------------------------------------------------------------------------*/
114 static void ColdReset
PARAMS((SIM_DESC sd
));
116 /*---------------------------------------------------------------------------*/
120 #define DELAYSLOT() {\
121 if (STATE & simDELAYSLOT)\
122 sim_io_eprintf(sd,"Delay slot already activated (branch in delay slot?)\n");\
123 STATE |= simDELAYSLOT;\
126 #define JALDELAYSLOT() {\
128 STATE |= simJALDELAYSLOT;\
132 STATE &= ~simDELAYSLOT;\
133 STATE |= simSKIPNEXT;\
136 #define CANCELDELAYSLOT() {\
138 STATE &= ~(simDELAYSLOT | simJALDELAYSLOT);\
141 #define INDELAYSLOT() ((STATE & simDELAYSLOT) != 0)
142 #define INJALDELAYSLOT() ((STATE & simJALDELAYSLOT) != 0)
144 #define K0BASE (0x80000000)
145 #define K0SIZE (0x20000000)
146 #define K1BASE (0xA0000000)
147 #define K1SIZE (0x20000000)
148 #define MONITOR_BASE (0xBFC00000)
149 #define MONITOR_SIZE (1 << 11)
150 #define MEM_SIZE (2 << 20)
153 static char *tracefile
= "trace.din"; /* default filename for trace log */
154 FILE *tracefh
= NULL
;
155 static void open_trace
PARAMS((SIM_DESC sd
));
158 #define OPTION_DINERO_TRACE 200
159 #define OPTION_DINERO_FILE 201
162 mips_option_handler (sd
, opt
, arg
)
170 case OPTION_DINERO_TRACE
: /* ??? */
172 /* Eventually the simTRACE flag could be treated as a toggle, to
173 allow external control of the program points being traced
174 (i.e. only from main onwards, excluding the run-time setup,
176 for (cpu_nr
= 0; cpu_nr
< sim_engine_nr_cpus (sd
); cpu_nr
++)
178 sim_cpu
*cpu
= STATE_CPU (sd
, cpu_nr
);
181 else if (strcmp (arg
, "yes") == 0)
183 else if (strcmp (arg
, "no") == 0)
185 else if (strcmp (arg
, "on") == 0)
187 else if (strcmp (arg
, "off") == 0)
191 fprintf (stderr
, "Unreconized dinero-trace option `%s'\n", arg
);
198 Simulator constructed without dinero tracing support (for performance).\n\
199 Re-compile simulator with \"-DTRACE\" to enable this option.\n");
203 case OPTION_DINERO_FILE
:
205 if (optarg
!= NULL
) {
207 tmp
= (char *)malloc(strlen(optarg
) + 1);
210 sim_io_printf(sd
,"Failed to allocate buffer for tracefile name \"%s\"\n",optarg
);
216 sim_io_printf(sd
,"Placing trace information into file \"%s\"\n",tracefile
);
227 static const OPTION mips_options
[] =
229 { {"dinero-trace", optional_argument
, NULL
, OPTION_DINERO_TRACE
},
230 '\0', "on|off", "Enable dinero tracing",
231 mips_option_handler
},
232 { {"dinero-file", required_argument
, NULL
, OPTION_DINERO_FILE
},
233 '\0', "FILE", "Write dinero trace to FILE",
234 mips_option_handler
},
235 { {NULL
, no_argument
, NULL
, 0}, '\0', NULL
, NULL
, NULL
}
239 int interrupt_pending
;
242 interrupt_event (SIM_DESC sd
, void *data
)
244 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
247 interrupt_pending
= 0;
248 SignalExceptionInterrupt ();
250 else if (!interrupt_pending
)
251 sim_events_schedule (sd
, 1, interrupt_event
, data
);
255 /*---------------------------------------------------------------------------*/
256 /*-- Device registration hook -----------------------------------------------*/
257 /*---------------------------------------------------------------------------*/
258 static void device_init(SIM_DESC sd
) {
260 extern void register_devices(SIM_DESC
);
261 register_devices(sd
);
265 /* start-sanitize-sky */
269 int f
[NUM_VU_REGS
- 16];
272 /* end-sanitize-sky */
274 /*---------------------------------------------------------------------------*/
275 /*-- GDB simulator interface ------------------------------------------------*/
276 /*---------------------------------------------------------------------------*/
279 sim_open (kind
, cb
, abfd
, argv
)
285 SIM_DESC sd
= sim_state_alloc (kind
, cb
);
286 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
288 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
290 /* FIXME: watchpoints code shouldn't need this */
291 STATE_WATCHPOINTS (sd
)->pc
= &(PC
);
292 STATE_WATCHPOINTS (sd
)->sizeof_pc
= sizeof (PC
);
293 STATE_WATCHPOINTS (sd
)->interrupt_handler
= interrupt_event
;
297 if (sim_pre_argv_init (sd
, argv
[0]) != SIM_RC_OK
)
299 sim_add_option_table (sd
, mips_options
);
301 /* Allocate core managed memory */
304 sim_do_commandf (sd
, "memory region 0x%lx,0x%lx", MONITOR_BASE
, MONITOR_SIZE
);
305 /* For compatibility with the old code - under this (at level one)
306 are the kernel spaces K0 & K1. Both of these map to a single
307 smaller sub region */
308 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x",
310 MEM_SIZE
, /* actual size */
315 /* getopt will print the error message so we just have to exit if this fails.
316 FIXME: Hmmm... in the case of gdb we need getopt to call
318 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
320 /* Uninstall the modules to avoid memory leaks,
321 file descriptor leaks, etc. */
322 sim_module_uninstall (sd
);
326 /* check for/establish the a reference program image */
327 if (sim_analyze_program (sd
,
328 (STATE_PROG_ARGV (sd
) != NULL
329 ? *STATE_PROG_ARGV (sd
)
333 sim_module_uninstall (sd
);
337 /* Configure/verify the target byte order and other runtime
338 configuration options */
339 if (sim_config (sd
) != SIM_RC_OK
)
341 sim_module_uninstall (sd
);
345 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
347 /* Uninstall the modules to avoid memory leaks,
348 file descriptor leaks, etc. */
349 sim_module_uninstall (sd
);
353 /* verify assumptions the simulator made about the host type system.
354 This macro does not return if there is a problem */
355 SIM_ASSERT (sizeof(int) == (4 * sizeof(char)));
356 SIM_ASSERT (sizeof(word64
) == (8 * sizeof(char)));
358 /* This is NASTY, in that we are assuming the size of specific
362 for (rn
= 0; (rn
< (LAST_EMBED_REGNUM
+ 1)); rn
++)
365 cpu
->register_widths
[rn
] = WITH_TARGET_WORD_BITSIZE
;
366 else if ((rn
>= FGRIDX
) && (rn
< (FGRIDX
+ NR_FGR
)))
367 cpu
->register_widths
[rn
] = WITH_TARGET_FLOATING_POINT_BITSIZE
;
368 else if ((rn
>= 33) && (rn
<= 37))
369 cpu
->register_widths
[rn
] = WITH_TARGET_WORD_BITSIZE
;
370 else if ((rn
== SRIDX
) || (rn
== FCR0IDX
) || (rn
== FCR31IDX
) || ((rn
>= 72) && (rn
<= 89)))
371 cpu
->register_widths
[rn
] = 32;
373 cpu
->register_widths
[rn
] = 0;
375 /* start-sanitize-r5900 */
377 /* set the 5900 "upper" registers to 64 bits */
378 for( rn
= LAST_EMBED_REGNUM
+1; rn
< NUM_REGS
; rn
++)
379 cpu
->register_widths
[rn
] = 64;
380 /* end-sanitize-r5900 */
382 /* start-sanitize-sky */
384 /* Now the VU registers */
385 for( rn
= 0; rn
< 16; rn
++ ) { /* first the integer registers */
386 cpu
->register_widths
[rn
+ NUM_R5900_REGS
] = 16;
387 cpu
->register_widths
[rn
+ NUM_R5900_REGS
+ NUM_VU_REGS
] = 16;
389 /* Hack for now - to test gdb interface */
390 vu_regs
[0].i
[rn
] = rn
+ 0x100;
391 vu_regs
[1].i
[rn
] = rn
+ 0x200;
394 for( rn
= 16; rn
< NUM_VU_REGS
; rn
++ ) { /* then the FP registers */
397 cpu
->register_widths
[rn
+ NUM_R5900_REGS
] = 32;
398 cpu
->register_widths
[rn
+ NUM_R5900_REGS
+ NUM_VU_REGS
] = 32;
400 /* Hack for now - to test gdb interface */
403 vu_regs
[0].f
[rn
-16] = *((unsigned *) &f
);
405 vu_regs
[1].f
[rn
-16] = *((unsigned *) &f
);
408 f
= (rn
- 24)/4 + (rn
- 24)%4 + 1000.0;
409 vu_regs
[0].f
[rn
-16] = *((unsigned *) &f
);
410 f
= (rn
- 24)/4 + (rn
- 24)%4 + 2000.0;
411 vu_regs
[1].f
[rn
-16] = *((unsigned *) &f
);
415 /* end-sanitize-sky */
419 if (STATE
& simTRACE
)
423 /* Write the monitor trap address handlers into the monitor (eeprom)
424 address space. This can only be done once the target endianness
425 has been determined. */
428 /* Entry into the IDT monitor is via fixed address vectors, and
429 not using machine instructions. To avoid clashing with use of
430 the MIPS TRAP system, we place our own (simulator specific)
431 "undefined" instructions into the relevant vector slots. */
432 for (loop
= 0; (loop
< MONITOR_SIZE
); loop
+= 4)
434 address_word vaddr
= (MONITOR_BASE
+ loop
);
435 unsigned32 insn
= (RSVD_INSTRUCTION
| (((loop
>> 2) & RSVD_INSTRUCTION_ARG_MASK
) << RSVD_INSTRUCTION_ARG_SHIFT
));
437 sim_write (sd
, vaddr
, (char *)&insn
, sizeof (insn
));
439 /* The PMON monitor uses the same address space, but rather than
440 branching into it the address of a routine is loaded. We can
441 cheat for the moment, and direct the PMON routine to IDT style
442 instructions within the monitor space. This relies on the IDT
443 monitor not using the locations from 0xBFC00500 onwards as its
445 for (loop
= 0; (loop
< 24); loop
++)
447 address_word vaddr
= (MONITOR_BASE
+ 0x500 + (loop
* 4));
448 unsigned32 value
= ((0x500 - 8) / 8); /* default UNDEFINED reason code */
464 value
= ((0x500 - 16) / 8); /* not an IDT reason code */
466 case 8: /* cliexit */
469 case 11: /* flush_cache */
473 /* FIXME - should monitor_base be SIM_ADDR?? */
474 value
= ((unsigned int)MONITOR_BASE
+ (value
* 8));
476 sim_write (sd
, vaddr
, (char *)&value
, sizeof (value
));
478 /* The LSI MiniRISC PMON has its vectors at 0x200, not 0x500. */
480 sim_write (sd
, vaddr
, (char *)&value
, sizeof (value
));
492 tracefh
= fopen(tracefile
,"wb+");
495 sim_io_eprintf(sd
,"Failed to create file \"%s\", writing trace information to stderr.\n",tracefile
);
502 sim_close (sd
, quitting
)
507 printf("DBG: sim_close: entered (quitting = %d)\n",quitting
);
510 /* "quitting" is non-zero if we cannot hang on errors */
512 /* Ensure that any resources allocated through the callback
513 mechanism are released: */
514 sim_io_shutdown (sd
);
517 if (tracefh
!= NULL
&& tracefh
!= stderr
)
522 /* FIXME - free SD */
529 sim_write (sd
,addr
,buffer
,size
)
532 unsigned char *buffer
;
536 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
538 /* Return the number of bytes written, or zero if error. */
540 sim_io_printf(sd
,"sim_write(0x%s,buffer,%d);\n",pr_addr(addr
),size
);
543 /* We use raw read and write routines, since we do not want to count
544 the GDB memory accesses in our statistics gathering. */
546 for (index
= 0; index
< size
; index
++)
548 address_word vaddr
= (address_word
)addr
+ index
;
551 if (!address_translation (SD
, CPU
, NULL_CIA
, vaddr
, isDATA
, isSTORE
, &paddr
, &cca
, isRAW
))
553 if (sim_core_write_buffer (SD
, CPU
, sim_core_read_map
, buffer
+ index
, paddr
, 1) != 1)
561 sim_read (sd
,addr
,buffer
,size
)
564 unsigned char *buffer
;
568 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
570 /* Return the number of bytes read, or zero if error. */
572 sim_io_printf(sd
,"sim_read(0x%s,buffer,%d);\n",pr_addr(addr
),size
);
575 for (index
= 0; (index
< size
); index
++)
577 address_word vaddr
= (address_word
)addr
+ index
;
580 if (!address_translation (SD
, CPU
, NULL_CIA
, vaddr
, isDATA
, isLOAD
, &paddr
, &cca
, isRAW
))
582 if (sim_core_read_buffer (SD
, CPU
, sim_core_read_map
, buffer
+ index
, paddr
, 1) != 1)
590 sim_store_register (sd
,rn
,memory
)
593 unsigned char *memory
;
595 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
596 /* NOTE: gdb (the client) stores registers in target byte order
597 while the simulator uses host byte order */
599 sim_io_printf(sd
,"sim_store_register(%d,*memory=0x%s);\n",rn
,pr_addr(*((SIM_ADDR
*)memory
)));
602 /* Unfortunately this suffers from the same problem as the register
603 numbering one. We need to know what the width of each logical
604 register number is for the architecture being simulated. */
606 if (cpu
->register_widths
[rn
] == 0)
607 sim_io_eprintf(sd
,"Invalid register width for %d (register store ignored)\n",rn
);
608 /* start-sanitize-sky */
610 else if( rn
> NUM_R5900_REGS
) {
611 rn
= rn
- NUM_R5900_REGS
;
614 vu_regs
[0].i
[rn
] = T2H_2( *(unsigned short *) memory
);
615 else if( rn
< NUM_VU_REGS
)
616 vu_regs
[0].f
[rn
- 16] = T2H_4( *(unsigned int *) memory
);
618 rn
= rn
- NUM_VU_REGS
;
621 vu_regs
[1].i
[rn
] = T2H_2( *(unsigned short *) memory
);
622 else if( rn
< NUM_VU_REGS
)
623 vu_regs
[1].f
[rn
- 16] = T2H_4( *(unsigned int *) memory
);
625 sim_io_eprintf( sd
, "Invalid VU register (register store ignored)\n" );
629 /* end-sanitize-sky */
630 /* start-sanitize-r5900 */
631 else if (rn
== REGISTER_SA
)
632 SA
= T2H_8(*(unsigned64
*)memory
);
633 else if (rn
> LAST_EMBED_REGNUM
)
634 cpu
->registers1
[rn
- LAST_EMBED_REGNUM
- 1] = T2H_8(*(unsigned64
*)memory
);
635 /* end-sanitize-r5900 */
636 else if (rn
>= FGRIDX
&& rn
< FGRIDX
+ NR_FGR
)
638 if (cpu
->register_widths
[rn
] == 32)
639 cpu
->fgr
[rn
- FGRIDX
] = T2H_4 (*(unsigned32
*)memory
);
641 cpu
->fgr
[rn
- FGRIDX
] = T2H_8 (*(unsigned64
*)memory
);
643 else if (cpu
->register_widths
[rn
] == 32)
644 cpu
->registers
[rn
] = T2H_4 (*(unsigned32
*)memory
);
646 cpu
->registers
[rn
] = T2H_8 (*(unsigned64
*)memory
);
652 sim_fetch_register (sd
,rn
,memory
)
655 unsigned char *memory
;
657 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
658 /* NOTE: gdb (the client) stores registers in target byte order
659 while the simulator uses host byte order */
661 sim_io_printf(sd
,"sim_fetch_register(%d=0x%s,mem) : place simulator registers into memory\n",rn
,pr_addr(registers
[rn
]));
664 if (cpu
->register_widths
[rn
] == 0)
665 sim_io_eprintf(sd
,"Invalid register width for %d (register fetch ignored)\n",rn
);
666 /* start-sanitize-sky */
668 else if( rn
> NUM_R5900_REGS
) {
669 rn
= rn
- NUM_R5900_REGS
;
672 *((unsigned short *) memory
) = H2T_2( vu_regs
[0].i
[rn
] );
673 else if( rn
< NUM_VU_REGS
)
674 *((unsigned int *) memory
) = H2T_4( vu_regs
[0].f
[rn
- 16] );
676 rn
= rn
- NUM_VU_REGS
;
679 (*(unsigned short *) memory
) = H2T_2( vu_regs
[1].i
[rn
] );
680 else if( rn
< NUM_VU_REGS
)
681 (*(unsigned int *) memory
) = H2T_4( vu_regs
[1].f
[rn
- 16] );
683 sim_io_eprintf( sd
, "Invalid VU register (register fetch ignored)\n" );
687 /* end-sanitize-sky */
688 /* start-sanitize-r5900 */
689 else if (rn
== REGISTER_SA
)
690 *((unsigned64
*)memory
) = H2T_8(SA
);
691 else if (rn
> LAST_EMBED_REGNUM
)
692 *((unsigned64
*)memory
) = H2T_8(cpu
->registers1
[rn
- LAST_EMBED_REGNUM
- 1]);
693 /* end-sanitize-r5900 */
694 else if (rn
>= FGRIDX
&& rn
< FGRIDX
+ NR_FGR
)
696 if (cpu
->register_widths
[rn
] == 32)
697 *(unsigned32
*)memory
= H2T_4 (cpu
->fgr
[rn
- FGRIDX
]);
699 *(unsigned64
*)memory
= H2T_8 (cpu
->fgr
[rn
- FGRIDX
]);
701 else if (cpu
->register_widths
[rn
] == 32)
702 *(unsigned32
*)memory
= H2T_4 ((unsigned32
)(cpu
->registers
[rn
]));
703 else /* 64bit register */
704 *(unsigned64
*)memory
= H2T_8 ((unsigned64
)(cpu
->registers
[rn
]));
711 sim_info (sd
,verbose
)
715 /* Accessed from the GDB "info files" command: */
716 if (STATE_VERBOSE_P (sd
) || verbose
)
719 sim_io_printf (sd
, "MIPS %d-bit %s endian simulator\n",
720 WITH_TARGET_WORD_BITSIZE
,
721 (CURRENT_TARGET_BYTE_ORDER
== BIG_ENDIAN
? "Big" : "Little"));
723 #if !defined(FASTSIM)
724 /* It would be a useful feature, if when performing multi-cycle
725 simulations (rather than single-stepping) we keep the start and
726 end times of the execution, so that we can give a performance
727 figure for the simulator. */
728 #endif /* !FASTSIM */
729 sim_io_printf (sd
, "Number of execution cycles = %ld\n",
730 (long) sim_events_time (sd
));
732 /* print information pertaining to MIPS ISA and architecture being simulated */
733 /* things that may be interesting */
734 /* instructions executed - if available */
735 /* cycles executed - if available */
736 /* pipeline stalls - if available */
737 /* virtual time taken */
739 /* profiling frequency */
743 profile_print (sd
, STATE_VERBOSE_P (sd
), NULL
, NULL
);
748 sim_create_inferior (sd
, abfd
, argv
,env
)
756 printf("DBG: sim_create_inferior entered: start_address = 0x%s\n",
764 /* override PC value set by ColdReset () */
766 for (cpu_nr
= 0; cpu_nr
< sim_engine_nr_cpus (sd
); cpu_nr
++)
768 sim_cpu
*cpu
= STATE_CPU (sd
, cpu_nr
);
769 CIA_SET (cpu
, (unsigned64
) bfd_get_start_address (abfd
));
773 #if 0 /* def DEBUG */
776 /* We should really place the argv slot values into the argument
777 registers, and onto the stack as required. However, this
778 assumes that we have a stack defined, which is not
779 necessarily true at the moment. */
781 sim_io_printf(sd
,"sim_create_inferior() : passed arguments ignored\n");
782 for (cptr
= argv
; (cptr
&& *cptr
); cptr
++)
783 printf("DBG: arg \"%s\"\n",*cptr
);
791 sim_do_command (sd
,cmd
)
795 if (sim_args_command (sd
, cmd
) != SIM_RC_OK
)
796 sim_io_printf (sd
, "Error: \"%s\" is not a valid MIPS simulator command.\n",
800 /*---------------------------------------------------------------------------*/
801 /*-- Private simulator support interface ------------------------------------*/
802 /*---------------------------------------------------------------------------*/
804 /* Read a null terminated string from memory, return in a buffer */
813 while (sim_read (sd
, addr
+ nr
, &null
, 1) == 1 && null
!= 0)
815 buf
= NZALLOC (char, nr
+ 1);
816 sim_read (sd
, addr
, buf
, nr
);
820 /* Simple monitor interface (currently setup for the IDT and PMON monitors) */
822 sim_monitor (SIM_DESC sd
,
828 printf("DBG: sim_monitor: entered (reason = %d)\n",reason
);
831 /* The IDT monitor actually allows two instructions per vector
832 slot. However, the simulator currently causes a trap on each
833 individual instruction. We cheat, and lose the bottom bit. */
836 /* The following callback functions are available, however the
837 monitor we are simulating does not make use of them: get_errno,
838 isatty, lseek, rename, system, time and unlink */
842 case 6: /* int open(char *path,int flags) */
844 char *path
= fetch_str (sd
, A0
);
845 V0
= sim_io_open (sd
, path
, (int)A1
);
850 case 7: /* int read(int file,char *ptr,int len) */
854 char *buf
= zalloc (nr
);
855 V0
= sim_io_read (sd
, fd
, buf
, nr
);
856 sim_write (sd
, A1
, buf
, nr
);
861 case 8: /* int write(int file,char *ptr,int len) */
865 char *buf
= zalloc (nr
);
866 sim_read (sd
, A1
, buf
, nr
);
867 V0
= sim_io_write (sd
, fd
, buf
, nr
);
872 case 10: /* int close(int file) */
874 V0
= sim_io_close (sd
, (int)A0
);
878 case 2: /* Densan monitor: char inbyte(int waitflag) */
880 if (A0
== 0) /* waitflag == NOWAIT */
881 V0
= (unsigned_word
)-1;
883 /* Drop through to case 11 */
885 case 11: /* char inbyte(void) */
888 if (sim_io_read_stdin (sd
, &tmp
, sizeof(char)) != sizeof(char))
890 sim_io_error(sd
,"Invalid return from character read");
891 V0
= (unsigned_word
)-1;
894 V0
= (unsigned_word
)tmp
;
898 case 3: /* Densan monitor: void co(char chr) */
899 case 12: /* void outbyte(char chr) : write a byte to "stdout" */
901 char tmp
= (char)(A0
& 0xFF);
902 sim_io_write_stdout (sd
, &tmp
, sizeof(char));
906 case 17: /* void _exit() */
908 sim_io_eprintf (sd
, "sim_monitor(17): _exit(int reason) to be coded\n");
909 sim_engine_halt (SD
, CPU
, NULL
, NULL_CIA
, sim_exited
,
910 (unsigned int)(A0
& 0xFFFFFFFF));
914 case 28 : /* PMON flush_cache */
917 case 55: /* void get_mem_info(unsigned int *ptr) */
918 /* in: A0 = pointer to three word memory location */
919 /* out: [A0 + 0] = size */
920 /* [A0 + 4] = instruction cache size */
921 /* [A0 + 8] = data cache size */
923 address_word value
= MEM_SIZE
/* FIXME STATE_MEM_SIZE (sd) */;
925 sim_write (sd
, A0
, (char *)&value
, sizeof (value
));
926 /* sim_io_eprintf (sd, "sim: get_mem_info() depreciated\n"); */
930 case 158 : /* PMON printf */
931 /* in: A0 = pointer to format string */
932 /* A1 = optional argument 1 */
933 /* A2 = optional argument 2 */
934 /* A3 = optional argument 3 */
936 /* The following is based on the PMON printf source */
940 signed_word
*ap
= &A1
; /* 1st argument */
941 /* This isn't the quickest way, since we call the host print
942 routine for every character almost. But it does avoid
943 having to allocate and manage a temporary string buffer. */
944 /* TODO: Include check that we only use three arguments (A1,
946 while (sim_read (sd
, s
++, &c
, 1) && c
!= '\0')
951 enum {FMT_RJUST
, FMT_LJUST
, FMT_RJUST0
, FMT_CENTER
} fmt
= FMT_RJUST
;
952 int width
= 0, trunc
= 0, haddot
= 0, longlong
= 0;
953 while (sim_read (sd
, s
++, &c
, 1) && c
!= '\0')
955 if (strchr ("dobxXulscefg%", s
))
970 else if (c
>= '1' && c
<= '9')
974 while (sim_read (sd
, s
++, &c
, 1) == 1 && isdigit (c
))
977 n
= (unsigned int)strtol(tmp
,NULL
,10);
990 sim_io_printf (sd
, "%%");
995 address_word p
= *ap
++;
997 while (sim_read (sd
, p
++, &ch
, 1) == 1 && ch
!= '\0')
998 sim_io_printf(sd
, "%c", ch
);
1001 sim_io_printf(sd
,"(null)");
1004 sim_io_printf (sd
, "%c", (int)*ap
++);
1009 sim_read (sd
, s
++, &c
, 1);
1013 sim_read (sd
, s
++, &c
, 1);
1016 if (strchr ("dobxXu", c
))
1018 word64 lv
= (word64
) *ap
++;
1020 sim_io_printf(sd
,"<binary not supported>");
1023 sprintf (tmp
, "%%%s%c", longlong
? "ll" : "", c
);
1025 sim_io_printf(sd
, tmp
, lv
);
1027 sim_io_printf(sd
, tmp
, (int)lv
);
1030 else if (strchr ("eEfgG", c
))
1032 double dbl
= *(double*)(ap
++);
1033 sprintf (tmp
, "%%%d.%d%c", width
, trunc
, c
);
1034 sim_io_printf (sd
, tmp
, dbl
);
1040 sim_io_printf(sd
, "%c", c
);
1046 sim_io_error (sd
, "TODO: sim_monitor(%d) : PC = 0x%s\n",
1047 reason
, pr_addr(cia
));
1053 /* Store a word into memory. */
1056 store_word (SIM_DESC sd
,
1065 if ((vaddr
& 3) != 0)
1066 SignalExceptionAddressStore ();
1069 if (AddressTranslation (vaddr
, isDATA
, isSTORE
, &paddr
, &uncached
,
1072 const uword64 mask
= 7;
1076 paddr
= (paddr
& ~mask
) | ((paddr
& mask
) ^ (ReverseEndian
<< 2));
1077 byte
= (vaddr
& mask
) ^ (BigEndianCPU
<< 2);
1078 memval
= ((uword64
) val
) << (8 * byte
);
1079 StoreMemory (uncached
, AccessLength_WORD
, memval
, 0, paddr
, vaddr
,
1085 /* Load a word from memory. */
1088 load_word (SIM_DESC sd
,
1093 if ((vaddr
& 3) != 0)
1094 SignalExceptionAddressLoad ();
1100 if (AddressTranslation (vaddr
, isDATA
, isLOAD
, &paddr
, &uncached
,
1103 const uword64 mask
= 0x7;
1104 const unsigned int reverse
= ReverseEndian
? 1 : 0;
1105 const unsigned int bigend
= BigEndianCPU
? 1 : 0;
1109 paddr
= (paddr
& ~mask
) | ((paddr
& mask
) ^ (reverse
<< 2));
1110 LoadMemory (&memval
,NULL
,uncached
, AccessLength_WORD
, paddr
, vaddr
,
1112 byte
= (vaddr
& mask
) ^ (bigend
<< 2);
1113 return SIGNEXTEND (((memval
>> (8 * byte
)) & 0xffffffff), 32);
1120 /* Simulate the mips16 entry and exit pseudo-instructions. These
1121 would normally be handled by the reserved instruction exception
1122 code, but for ease of simulation we just handle them directly. */
1125 mips16_entry (SIM_DESC sd
,
1130 int aregs
, sregs
, rreg
;
1133 printf("DBG: mips16_entry: entered (insn = 0x%08X)\n",insn
);
1136 aregs
= (insn
& 0x700) >> 8;
1137 sregs
= (insn
& 0x0c0) >> 6;
1138 rreg
= (insn
& 0x020) >> 5;
1140 /* This should be checked by the caller. */
1149 /* This is the entry pseudo-instruction. */
1151 for (i
= 0; i
< aregs
; i
++)
1152 store_word (SD
, CPU
, cia
, (uword64
) (SP
+ 4 * i
), GPR
[i
+ 4]);
1160 store_word (SD
, CPU
, cia
, (uword64
) tsp
, RA
);
1163 for (i
= 0; i
< sregs
; i
++)
1166 store_word (SD
, CPU
, cia
, (uword64
) tsp
, GPR
[16 + i
]);
1174 /* This is the exit pseudo-instruction. */
1181 RA
= load_word (SD
, CPU
, cia
, (uword64
) tsp
);
1184 for (i
= 0; i
< sregs
; i
++)
1187 GPR
[i
+ 16] = load_word (SD
, CPU
, cia
, (uword64
) tsp
);
1192 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
1196 FGR
[0] = WORD64LO (GPR
[4]);
1197 FPR_STATE
[0] = fmt_uninterpreted
;
1199 else if (aregs
== 6)
1201 FGR
[0] = WORD64LO (GPR
[5]);
1202 FGR
[1] = WORD64LO (GPR
[4]);
1203 FPR_STATE
[0] = fmt_uninterpreted
;
1204 FPR_STATE
[1] = fmt_uninterpreted
;
1213 /*-- trace support ----------------------------------------------------------*/
1215 /* The TRACE support is provided (if required) in the memory accessing
1216 routines. Since we are also providing the architecture specific
1217 features, the architecture simulation code can also deal with
1218 notifying the TRACE world of cache flushes, etc. Similarly we do
1219 not need to provide profiling support in the simulator engine,
1220 since we can sample in the instruction fetch control loop. By
1221 defining the TRACE manifest, we add tracing as a run-time
1225 /* Tracing by default produces "din" format (as required by
1226 dineroIII). Each line of such a trace file *MUST* have a din label
1227 and address field. The rest of the line is ignored, so comments can
1228 be included if desired. The first field is the label which must be
1229 one of the following values:
1234 3 escape record (treated as unknown access type)
1235 4 escape record (causes cache flush)
1237 The address field is a 32bit (lower-case) hexadecimal address
1238 value. The address should *NOT* be preceded by "0x".
1240 The size of the memory transfer is not important when dealing with
1241 cache lines (as long as no more than a cache line can be
1242 transferred in a single operation :-), however more information
1243 could be given following the dineroIII requirement to allow more
1244 complete memory and cache simulators to provide better
1245 results. i.e. the University of Pisa has a cache simulator that can
1246 also take bus size and speed as (variable) inputs to calculate
1247 complete system performance (a much more useful ability when trying
1248 to construct an end product, rather than a processor). They
1249 currently have an ARM version of their tool called ChARM. */
1253 dotrace (SIM_DESC sd
,
1261 if (STATE
& simTRACE
) {
1263 fprintf(tracefh
,"%d %s ; width %d ; ",
1267 va_start(ap
,comment
);
1268 vfprintf(tracefh
,comment
,ap
);
1270 fprintf(tracefh
,"\n");
1272 /* NOTE: Since the "din" format will only accept 32bit addresses, and
1273 we may be generating 64bit ones, we should put the hi-32bits of the
1274 address into the comment field. */
1276 /* TODO: Provide a buffer for the trace lines. We can then avoid
1277 performing writes until the buffer is filled, or the file is
1280 /* NOTE: We could consider adding a comment field to the "din" file
1281 produced using type 3 markers (unknown access). This would then
1282 allow information about the program that the "din" is for, and
1283 the MIPs world that was being simulated, to be placed into the
1290 /*---------------------------------------------------------------------------*/
1291 /*-- simulator engine -------------------------------------------------------*/
1292 /*---------------------------------------------------------------------------*/
1295 ColdReset (SIM_DESC sd
)
1298 for (cpu_nr
= 0; cpu_nr
< sim_engine_nr_cpus (sd
); cpu_nr
++)
1300 sim_cpu
*cpu
= STATE_CPU (sd
, cpu_nr
);
1301 /* RESET: Fixed PC address: */
1302 PC
= UNSIGNED64 (0xFFFFFFFFBFC00000);
1303 /* The reset vector address is in the unmapped, uncached memory space. */
1305 SR
&= ~(status_SR
| status_TS
| status_RP
);
1306 SR
|= (status_ERL
| status_BEV
);
1308 /* Cheat and allow access to the complete register set immediately */
1309 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
1310 && WITH_TARGET_WORD_BITSIZE
== 64)
1311 SR
|= status_FR
; /* 64bit registers */
1313 /* Ensure that any instructions with pending register updates are
1315 PENDING_INVALIDATE();
1317 /* Initialise the FPU registers to the unknown state */
1318 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
1321 for (rn
= 0; (rn
< 32); rn
++)
1322 FPR_STATE
[rn
] = fmt_uninterpreted
;
1328 /* Description from page A-22 of the "MIPS IV Instruction Set" manual
1330 /* Translate a virtual address to a physical address and cache
1331 coherence algorithm describing the mechanism used to resolve the
1332 memory reference. Given the virtual address vAddr, and whether the
1333 reference is to Instructions ot Data (IorD), find the corresponding
1334 physical address (pAddr) and the cache coherence algorithm (CCA)
1335 used to resolve the reference. If the virtual address is in one of
1336 the unmapped address spaces the physical address and the CCA are
1337 determined directly by the virtual address. If the virtual address
1338 is in one of the mapped address spaces then the TLB is used to
1339 determine the physical address and access type; if the required
1340 translation is not present in the TLB or the desired access is not
1341 permitted the function fails and an exception is taken.
1343 NOTE: Normally (RAW == 0), when address translation fails, this
1344 function raises an exception and does not return. */
1347 address_translation (SIM_DESC sd
,
1353 address_word
*pAddr
,
1357 int res
= -1; /* TRUE : Assume good return */
1360 sim_io_printf(sd
,"AddressTranslation(0x%s,%s,%s,...);\n",pr_addr(vAddr
),(IorD
? "isDATA" : "isINSTRUCTION"),(LorS
? "iSTORE" : "isLOAD"));
1363 /* Check that the address is valid for this memory model */
1365 /* For a simple (flat) memory model, we simply pass virtual
1366 addressess through (mostly) unchanged. */
1367 vAddr
&= 0xFFFFFFFF;
1369 *pAddr
= vAddr
; /* default for isTARGET */
1370 *CCA
= Uncached
; /* not used for isHOST */
1375 /* Description from page A-23 of the "MIPS IV Instruction Set" manual
1377 /* Prefetch data from memory. Prefetch is an advisory instruction for
1378 which an implementation specific action is taken. The action taken
1379 may increase performance, but must not change the meaning of the
1380 program, or alter architecturally-visible state. */
1383 prefetch (SIM_DESC sd
,
1393 sim_io_printf(sd
,"Prefetch(%d,0x%s,0x%s,%d,%d);\n",CCA
,pr_addr(pAddr
),pr_addr(vAddr
),DATA
,hint
);
1396 /* For our simple memory model we do nothing */
1400 /* Description from page A-22 of the "MIPS IV Instruction Set" manual
1402 /* Load a value from memory. Use the cache and main memory as
1403 specified in the Cache Coherence Algorithm (CCA) and the sort of
1404 access (IorD) to find the contents of AccessLength memory bytes
1405 starting at physical location pAddr. The data is returned in the
1406 fixed width naturally-aligned memory element (MemElem). The
1407 low-order two (or three) bits of the address and the AccessLength
1408 indicate which of the bytes within MemElem needs to be given to the
1409 processor. If the memory access type of the reference is uncached
1410 then only the referenced bytes are read from memory and valid
1411 within the memory element. If the access type is cached, and the
1412 data is not present in cache, an implementation specific size and
1413 alignment block of memory is read and loaded into the cache to
1414 satisfy a load reference. At a minimum, the block is the entire
1417 load_memory (SIM_DESC sd
,
1432 sim_io_printf(sd
,"DBG: LoadMemory(%p,%p,%d,%d,0x%s,0x%s,%s)\n",memvalp
,memval1p
,CCA
,AccessLength
,pr_addr(pAddr
),pr_addr(vAddr
),(IorD
? "isDATA" : "isINSTRUCTION"));
1435 #if defined(WARN_MEM)
1436 if (CCA
!= uncached
)
1437 sim_io_eprintf(sd
,"LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA
);
1438 #endif /* WARN_MEM */
1440 /* If instruction fetch then we need to check that the two lo-order
1441 bits are zero, otherwise raise a InstructionFetch exception: */
1442 if ((IorD
== isINSTRUCTION
)
1443 && ((pAddr
& 0x3) != 0)
1444 && (((pAddr
& 0x1) != 0) || ((vAddr
& 0x1) == 0)))
1445 SignalExceptionInstructionFetch ();
1447 if (((pAddr
& LOADDRMASK
) + AccessLength
) > LOADDRMASK
)
1449 /* In reality this should be a Bus Error */
1450 sim_io_error (sd
, "AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%s\n",
1452 (LOADDRMASK
+ 1) << 2,
1457 dotrace (SD
, CPU
, tracefh
,((IorD
== isDATA
) ? 0 : 2),(unsigned int)(pAddr
&0xFFFFFFFF),(AccessLength
+ 1),"load%s",((IorD
== isDATA
) ? "" : " instruction"));
1460 /* Read the specified number of bytes from memory. Adjust for
1461 host/target byte ordering/ Align the least significant byte
1464 switch (AccessLength
)
1466 case AccessLength_QUADWORD
:
1468 unsigned_16 val
= sim_core_read_aligned_16 (cpu
, NULL_CIA
,
1469 sim_core_read_map
, pAddr
);
1470 value1
= VH8_16 (val
);
1471 value
= VL8_16 (val
);
1474 case AccessLength_DOUBLEWORD
:
1475 value
= sim_core_read_aligned_8 (cpu
, NULL_CIA
,
1476 sim_core_read_map
, pAddr
);
1478 case AccessLength_SEPTIBYTE
:
1479 value
= sim_core_read_misaligned_7 (cpu
, NULL_CIA
,
1480 sim_core_read_map
, pAddr
);
1481 case AccessLength_SEXTIBYTE
:
1482 value
= sim_core_read_misaligned_6 (cpu
, NULL_CIA
,
1483 sim_core_read_map
, pAddr
);
1484 case AccessLength_QUINTIBYTE
:
1485 value
= sim_core_read_misaligned_5 (cpu
, NULL_CIA
,
1486 sim_core_read_map
, pAddr
);
1487 case AccessLength_WORD
:
1488 value
= sim_core_read_aligned_4 (cpu
, NULL_CIA
,
1489 sim_core_read_map
, pAddr
);
1491 case AccessLength_TRIPLEBYTE
:
1492 value
= sim_core_read_misaligned_3 (cpu
, NULL_CIA
,
1493 sim_core_read_map
, pAddr
);
1494 case AccessLength_HALFWORD
:
1495 value
= sim_core_read_aligned_2 (cpu
, NULL_CIA
,
1496 sim_core_read_map
, pAddr
);
1498 case AccessLength_BYTE
:
1499 value
= sim_core_read_aligned_1 (cpu
, NULL_CIA
,
1500 sim_core_read_map
, pAddr
);
1507 printf("DBG: LoadMemory() : (offset %d) : value = 0x%s%s\n",
1508 (int)(pAddr
& LOADDRMASK
),pr_uword64(value1
),pr_uword64(value
));
1511 /* See also store_memory. */
1512 if (AccessLength
<= AccessLength_DOUBLEWORD
)
1515 /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
1516 shifted to the most significant byte position. */
1517 value
<<= (((7 - (pAddr
& LOADDRMASK
)) - AccessLength
) * 8);
1519 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
1520 is already in the correct postition. */
1521 value
<<= ((pAddr
& LOADDRMASK
) * 8);
1525 printf("DBG: LoadMemory() : shifted value = 0x%s%s\n",
1526 pr_uword64(value1
),pr_uword64(value
));
1530 if (memval1p
) *memval1p
= value1
;
1534 /* Description from page A-23 of the "MIPS IV Instruction Set" manual
1536 /* Store a value to memory. The specified data is stored into the
1537 physical location pAddr using the memory hierarchy (data caches and
1538 main memory) as specified by the Cache Coherence Algorithm
1539 (CCA). The MemElem contains the data for an aligned, fixed-width
1540 memory element (word for 32-bit processors, doubleword for 64-bit
1541 processors), though only the bytes that will actually be stored to
1542 memory need to be valid. The low-order two (or three) bits of pAddr
1543 and the AccessLength field indicates which of the bytes within the
1544 MemElem data should actually be stored; only these bytes in memory
1548 store_memory (SIM_DESC sd
,
1554 uword64 MemElem1
, /* High order 64 bits */
1559 sim_io_printf(sd
,"DBG: StoreMemory(%d,%d,0x%s,0x%s,0x%s,0x%s)\n",CCA
,AccessLength
,pr_uword64(MemElem
),pr_uword64(MemElem1
),pr_addr(pAddr
),pr_addr(vAddr
));
1562 #if defined(WARN_MEM)
1563 if (CCA
!= uncached
)
1564 sim_io_eprintf(sd
,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA
);
1565 #endif /* WARN_MEM */
1567 if (((pAddr
& LOADDRMASK
) + AccessLength
) > LOADDRMASK
)
1568 sim_io_error(sd
,"AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%s\n",AccessLength
,(LOADDRMASK
+ 1)<<2,pr_addr(pAddr
));
1571 dotrace (SD
, CPU
, tracefh
,1,(unsigned int)(pAddr
&0xFFFFFFFF),(AccessLength
+ 1),"store");
1575 printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr
& LOADDRMASK
),pr_uword64(MemElem1
),pr_uword64(MemElem
));
1578 /* See also load_memory */
1579 if (AccessLength
<= AccessLength_DOUBLEWORD
)
1582 /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
1583 shifted to the most significant byte position. */
1584 MemElem
>>= (((7 - (pAddr
& LOADDRMASK
)) - AccessLength
) * 8);
1586 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
1587 is already in the correct postition. */
1588 MemElem
>>= ((pAddr
& LOADDRMASK
) * 8);
1592 printf("DBG: StoreMemory: shift = %d MemElem = 0x%s%s\n",shift
,pr_uword64(MemElem1
),pr_uword64(MemElem
));
1595 switch (AccessLength
)
1597 case AccessLength_QUADWORD
:
1599 unsigned_16 val
= U16_8 (MemElem1
, MemElem
);
1600 sim_core_write_aligned_16 (cpu
, NULL_CIA
,
1601 sim_core_write_map
, pAddr
, val
);
1604 case AccessLength_DOUBLEWORD
:
1605 sim_core_write_aligned_8 (cpu
, NULL_CIA
,
1606 sim_core_write_map
, pAddr
, MemElem
);
1608 case AccessLength_SEPTIBYTE
:
1609 sim_core_write_misaligned_7 (cpu
, NULL_CIA
,
1610 sim_core_write_map
, pAddr
, MemElem
);
1612 case AccessLength_SEXTIBYTE
:
1613 sim_core_write_misaligned_6 (cpu
, NULL_CIA
,
1614 sim_core_write_map
, pAddr
, MemElem
);
1616 case AccessLength_QUINTIBYTE
:
1617 sim_core_write_misaligned_5 (cpu
, NULL_CIA
,
1618 sim_core_write_map
, pAddr
, MemElem
);
1620 case AccessLength_WORD
:
1621 sim_core_write_aligned_4 (cpu
, NULL_CIA
,
1622 sim_core_write_map
, pAddr
, MemElem
);
1624 case AccessLength_TRIPLEBYTE
:
1625 sim_core_write_misaligned_3 (cpu
, NULL_CIA
,
1626 sim_core_write_map
, pAddr
, MemElem
);
1628 case AccessLength_HALFWORD
:
1629 sim_core_write_aligned_2 (cpu
, NULL_CIA
,
1630 sim_core_write_map
, pAddr
, MemElem
);
1632 case AccessLength_BYTE
:
1633 sim_core_write_aligned_1 (cpu
, NULL_CIA
,
1634 sim_core_write_map
, pAddr
, MemElem
);
1645 ifetch32 (SIM_DESC sd
,
1650 /* Copy the action of the LW instruction */
1651 address_word reverse
= (ReverseEndian
? (LOADDRMASK
>> 2) : 0);
1652 address_word bigend
= (BigEndianCPU
? (LOADDRMASK
>> 2) : 0);
1655 unsigned32 instruction
;
1658 AddressTranslation (vaddr
, isINSTRUCTION
, isLOAD
, &paddr
, &cca
, isTARGET
, isREAL
);
1659 paddr
= ((paddr
& ~LOADDRMASK
) | ((paddr
& LOADDRMASK
) ^ (reverse
<< 2)));
1660 LoadMemory (&value
, NULL
, cca
, AccessLength_WORD
, paddr
, vaddr
, isINSTRUCTION
, isREAL
);
1661 byte
= ((vaddr
& LOADDRMASK
) ^ (bigend
<< 2));
1662 instruction
= ((value
>> (8 * byte
)) & 0xFFFFFFFF);
1668 ifetch16 (SIM_DESC sd
,
1673 /* Copy the action of the LW instruction */
1674 address_word reverse
= (ReverseEndian
? (LOADDRMASK
>> 2) : 0);
1675 address_word bigend
= (BigEndianCPU
? (LOADDRMASK
>> 2) : 0);
1678 unsigned16 instruction
;
1681 AddressTranslation (vaddr
, isINSTRUCTION
, isLOAD
, &paddr
, &cca
, isTARGET
, isREAL
);
1682 paddr
= ((paddr
& ~LOADDRMASK
) | ((paddr
& LOADDRMASK
) ^ (reverse
<< 2)));
1683 LoadMemory (&value
, NULL
, cca
, AccessLength_WORD
, paddr
, vaddr
, isINSTRUCTION
, isREAL
);
1684 byte
= ((vaddr
& LOADDRMASK
) ^ (bigend
<< 2));
1685 instruction
= ((value
>> (8 * byte
)) & 0xFFFFFFFF);
1690 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
1691 /* Order loads and stores to synchronise shared memory. Perform the
1692 action necessary to make the effects of groups of synchronizable
1693 loads and stores indicated by stype occur in the same order for all
1696 sync_operation (SIM_DESC sd
,
1702 sim_io_printf(sd
,"SyncOperation(%d) : TODO\n",stype
);
1707 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
1708 /* Signal an exception condition. This will result in an exception
1709 that aborts the instruction. The instruction operation pseudocode
1710 will never see a return from this function call. */
1713 signal_exception (SIM_DESC sd
,
1721 sim_io_printf(sd
,"DBG: SignalException(%d) PC = 0x%s\n",exception
,pr_addr(cia
));
1724 /* Ensure that any active atomic read/modify/write operation will fail: */
1727 switch (exception
) {
1728 /* TODO: For testing purposes I have been ignoring TRAPs. In
1729 reality we should either simulate them, or allow the user to
1730 ignore them at run-time.
1733 sim_io_eprintf(sd
,"Ignoring instruction TRAP (PC 0x%s)\n",pr_addr(cia
));
1739 unsigned int instruction
;
1742 va_start(ap
,exception
);
1743 instruction
= va_arg(ap
,unsigned int);
1746 code
= (instruction
>> 6) & 0xFFFFF;
1748 sim_io_eprintf(sd
,"Ignoring instruction `syscall %d' (PC 0x%s)\n",
1749 code
, pr_addr(cia
));
1753 case DebugBreakPoint
:
1754 if (! (Debug
& Debug_DM
))
1760 Debug
|= Debug_DBD
; /* signaled from within in delay slot */
1761 DEPC
= cia
- 4; /* reference the branch instruction */
1765 Debug
&= ~Debug_DBD
; /* not signaled from within a delay slot */
1769 Debug
|= Debug_DM
; /* in debugging mode */
1770 Debug
|= Debug_DBp
; /* raising a DBp exception */
1772 sim_engine_restart (SD
, CPU
, NULL
, NULL_CIA
);
1776 case ReservedInstruction
:
1779 unsigned int instruction
;
1780 va_start(ap
,exception
);
1781 instruction
= va_arg(ap
,unsigned int);
1783 /* Provide simple monitor support using ReservedInstruction
1784 exceptions. The following code simulates the fixed vector
1785 entry points into the IDT monitor by causing a simulator
1786 trap, performing the monitor operation, and returning to
1787 the address held in the $ra register (standard PCS return
1788 address). This means we only need to pre-load the vector
1789 space with suitable instruction values. For systems were
1790 actual trap instructions are used, we would not need to
1791 perform this magic. */
1792 if ((instruction
& RSVD_INSTRUCTION_MASK
) == RSVD_INSTRUCTION
)
1794 sim_monitor (SD
, CPU
, cia
, ((instruction
>> RSVD_INSTRUCTION_ARG_SHIFT
) & RSVD_INSTRUCTION_ARG_MASK
) );
1795 /* NOTE: This assumes that a branch-and-link style
1796 instruction was used to enter the vector (which is the
1797 case with the current IDT monitor). */
1798 sim_engine_restart (SD
, CPU
, NULL
, RA
);
1800 /* Look for the mips16 entry and exit instructions, and
1801 simulate a handler for them. */
1802 else if ((cia
& 1) != 0
1803 && (instruction
& 0xf81f) == 0xe809
1804 && (instruction
& 0x0c0) != 0x0c0)
1806 mips16_entry (SD
, CPU
, cia
, instruction
);
1807 sim_engine_restart (sd
, NULL
, NULL
, NULL_CIA
);
1809 /* else fall through to normal exception processing */
1810 sim_io_eprintf(sd
,"ReservedInstruction 0x%08X at PC = 0x%s\n",instruction
,pr_addr(cia
));
1815 sim_io_printf(sd
,"DBG: SignalException(%d) PC = 0x%s\n",exception
,pr_addr(cia
));
1817 /* Keep a copy of the current A0 in-case this is the program exit
1821 unsigned int instruction
;
1822 va_start(ap
,exception
);
1823 instruction
= va_arg(ap
,unsigned int);
1825 /* Check for our special terminating BREAK: */
1826 if ((instruction
& 0x03FFFFC0) == 0x03ff0000) {
1827 sim_engine_halt (SD
, CPU
, NULL
, cia
,
1828 sim_exited
, (unsigned int)(A0
& 0xFFFFFFFF));
1831 if (STATE
& simDELAYSLOT
)
1832 PC
= cia
- 4; /* reference the branch instruction */
1835 sim_engine_halt (SD
, CPU
, NULL
, cia
,
1836 sim_stopped
, SIM_SIGTRAP
);
1839 /* Store exception code into current exception id variable (used
1842 /* TODO: If not simulating exceptions then stop the simulator
1843 execution. At the moment we always stop the simulation. */
1845 /* See figure 5-17 for an outline of the code below */
1846 if (! (SR
& status_EXL
))
1848 CAUSE
= (exception
<< 2);
1849 if (STATE
& simDELAYSLOT
)
1851 STATE
&= ~simDELAYSLOT
;
1853 EPC
= (cia
- 4); /* reference the branch instruction */
1857 /* FIXME: TLB et.al. */
1862 CAUSE
= (exception
<< 2);
1866 /* Store exception code into current exception id variable (used
1868 if (SR
& status_BEV
)
1869 PC
= (signed)0xBFC00200 + 0x180;
1871 PC
= (signed)0x80000000 + 0x180;
1873 switch ((CAUSE
>> 2) & 0x1F)
1876 /* Interrupts arrive during event processing, no need to
1880 case TLBModification
:
1885 case InstructionFetch
:
1887 /* The following is so that the simulator will continue from the
1888 exception address on breakpoint operations. */
1890 sim_engine_halt (SD
, CPU
, NULL
, NULL_CIA
,
1891 sim_stopped
, SIM_SIGBUS
);
1893 case ReservedInstruction
:
1894 case CoProcessorUnusable
:
1896 sim_engine_halt (SD
, CPU
, NULL
, NULL_CIA
,
1897 sim_stopped
, SIM_SIGILL
);
1899 case IntegerOverflow
:
1901 sim_engine_halt (SD
, CPU
, NULL
, NULL_CIA
,
1902 sim_stopped
, SIM_SIGFPE
);
1908 sim_engine_halt (SD
, CPU
, NULL
, NULL_CIA
,
1909 sim_stopped
, SIM_SIGTRAP
);
1913 sim_engine_abort (SD
, CPU
, NULL_CIA
,
1914 "FATAL: Should not encounter a breakpoint\n");
1916 default : /* Unknown internal exception */
1918 sim_engine_halt (SD
, CPU
, NULL
, NULL_CIA
,
1919 sim_stopped
, SIM_SIGABRT
);
1923 case SimulatorFault
:
1927 va_start(ap
,exception
);
1928 msg
= va_arg(ap
,char *);
1930 sim_engine_abort (SD
, CPU
, NULL_CIA
,
1931 "FATAL: Simulator error \"%s\"\n",msg
);
1938 #if defined(WARN_RESULT)
1939 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
1940 /* This function indicates that the result of the operation is
1941 undefined. However, this should not affect the instruction
1942 stream. All that is meant to happen is that the destination
1943 register is set to an undefined result. To keep the simulator
1944 simple, we just don't bother updating the destination register, so
1945 the overall result will be undefined. If desired we can stop the
1946 simulator by raising a pseudo-exception. */
1947 #define UndefinedResult() undefined_result (sd,cia)
1949 undefined_result(sd
,cia
)
1953 sim_io_eprintf(sd
,"UndefinedResult: PC = 0x%s\n",pr_addr(cia
));
1954 #if 0 /* Disabled for the moment, since it actually happens a lot at the moment. */
1959 #endif /* WARN_RESULT */
1962 cache_op (SIM_DESC sd
,
1968 unsigned int instruction
)
1970 #if 1 /* stop warning message being displayed (we should really just remove the code) */
1971 static int icache_warning
= 1;
1972 static int dcache_warning
= 1;
1974 static int icache_warning
= 0;
1975 static int dcache_warning
= 0;
1978 /* If CP0 is not useable (User or Supervisor mode) and the CP0
1979 enable bit in the Status Register is clear - a coprocessor
1980 unusable exception is taken. */
1982 sim_io_printf(sd
,"TODO: Cache availability checking (PC = 0x%s)\n",pr_addr(cia
));
1986 case 0: /* instruction cache */
1988 case 0: /* Index Invalidate */
1989 case 1: /* Index Load Tag */
1990 case 2: /* Index Store Tag */
1991 case 4: /* Hit Invalidate */
1993 case 6: /* Hit Writeback */
1994 if (!icache_warning
)
1996 sim_io_eprintf(sd
,"Instruction CACHE operation %d to be coded\n",(op
>> 2));
2002 SignalException(ReservedInstruction
,instruction
);
2007 case 1: /* data cache */
2009 case 0: /* Index Writeback Invalidate */
2010 case 1: /* Index Load Tag */
2011 case 2: /* Index Store Tag */
2012 case 3: /* Create Dirty */
2013 case 4: /* Hit Invalidate */
2014 case 5: /* Hit Writeback Invalidate */
2015 case 6: /* Hit Writeback */
2016 if (!dcache_warning
)
2018 sim_io_eprintf(sd
,"Data CACHE operation %d to be coded\n",(op
>> 2));
2024 SignalException(ReservedInstruction
,instruction
);
2029 default: /* unrecognised cache ID */
2030 SignalException(ReservedInstruction
,instruction
);
2037 /*-- FPU support routines ---------------------------------------------------*/
2039 /* Numbers are held in normalized form. The SINGLE and DOUBLE binary
2040 formats conform to ANSI/IEEE Std 754-1985. */
2041 /* SINGLE precision floating:
2042 * seeeeeeeefffffffffffffffffffffff
2044 * e = 8bits = exponent
2045 * f = 23bits = fraction
2047 /* SINGLE precision fixed:
2048 * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
2050 * i = 31bits = integer
2052 /* DOUBLE precision floating:
2053 * seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
2055 * e = 11bits = exponent
2056 * f = 52bits = fraction
2058 /* DOUBLE precision fixed:
2059 * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
2061 * i = 63bits = integer
2064 /* Extract sign-bit: */
2065 #define FP_S_s(v) (((v) & ((unsigned)1 << 31)) ? 1 : 0)
2066 #define FP_D_s(v) (((v) & ((uword64)1 << 63)) ? 1 : 0)
2067 /* Extract biased exponent: */
2068 #define FP_S_be(v) (((v) >> 23) & 0xFF)
2069 #define FP_D_be(v) (((v) >> 52) & 0x7FF)
2070 /* Extract unbiased Exponent: */
2071 #define FP_S_e(v) (FP_S_be(v) - 0x7F)
2072 #define FP_D_e(v) (FP_D_be(v) - 0x3FF)
2073 /* Extract complete fraction field: */
2074 #define FP_S_f(v) ((v) & ~((unsigned)0x1FF << 23))
2075 #define FP_D_f(v) ((v) & ~((uword64)0xFFF << 52))
2076 /* Extract numbered fraction bit: */
2077 #define FP_S_fb(b,v) (((v) & (1 << (23 - (b)))) ? 1 : 0)
2078 #define FP_D_fb(b,v) (((v) & (1 << (52 - (b)))) ? 1 : 0)
2080 /* Explicit QNaN values used when value required: */
2081 #define FPQNaN_SINGLE (0x7FBFFFFF)
2082 #define FPQNaN_WORD (0x7FFFFFFF)
2083 #define FPQNaN_DOUBLE (((uword64)0x7FF7FFFF << 32) | 0xFFFFFFFF)
2084 #define FPQNaN_LONG (((uword64)0x7FFFFFFF << 32) | 0xFFFFFFFF)
2086 /* Explicit Infinity values used when required: */
2087 #define FPINF_SINGLE (0x7F800000)
2088 #define FPINF_DOUBLE (((uword64)0x7FF00000 << 32) | 0x00000000)
2090 #if 1 /* def DEBUG */
2091 #define RMMODE(v) (((v) == FP_RM_NEAREST) ? "Round" : (((v) == FP_RM_TOZERO) ? "Trunc" : (((v) == FP_RM_TOPINF) ? "Ceil" : "Floor")))
2092 #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>"))))))
2096 value_fpr (SIM_DESC sd
,
2105 /* Treat unused register values, as fixed-point 64bit values: */
2106 if ((fmt
== fmt_uninterpreted
) || (fmt
== fmt_unknown
))
2108 /* If request to read data as "uninterpreted", then use the current
2110 fmt
= FPR_STATE
[fpr
];
2115 /* For values not yet accessed, set to the desired format: */
2116 if (FPR_STATE
[fpr
] == fmt_uninterpreted
) {
2117 FPR_STATE
[fpr
] = fmt
;
2119 printf("DBG: Register %d was fmt_uninterpreted. Now %s\n",fpr
,DOFMT(fmt
));
2122 if (fmt
!= FPR_STATE
[fpr
]) {
2123 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
));
2124 FPR_STATE
[fpr
] = fmt_unknown
;
2127 if (FPR_STATE
[fpr
] == fmt_unknown
) {
2128 /* Set QNaN value: */
2131 value
= FPQNaN_SINGLE
;
2135 value
= FPQNaN_DOUBLE
;
2139 value
= FPQNaN_WORD
;
2143 value
= FPQNaN_LONG
;
2150 } else if (SizeFGR() == 64) {
2154 value
= (FGR
[fpr
] & 0xFFFFFFFF);
2157 case fmt_uninterpreted
:
2171 value
= (FGR
[fpr
] & 0xFFFFFFFF);
2174 case fmt_uninterpreted
:
2177 if ((fpr
& 1) == 0) { /* even registers only */
2178 value
= ((((uword64
)FGR
[fpr
+1]) << 32) | (FGR
[fpr
] & 0xFFFFFFFF));
2180 SignalException(ReservedInstruction
,0);
2191 SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR()");
2194 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());
2201 store_fpr (SIM_DESC sd
,
2211 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());
2214 if (SizeFGR() == 64) {
2216 case fmt_uninterpreted_32
:
2217 fmt
= fmt_uninterpreted
;
2220 FGR
[fpr
] = (((uword64
)0xDEADC0DE << 32) | (value
& 0xFFFFFFFF));
2221 FPR_STATE
[fpr
] = fmt
;
2224 case fmt_uninterpreted_64
:
2225 fmt
= fmt_uninterpreted
;
2226 case fmt_uninterpreted
:
2230 FPR_STATE
[fpr
] = fmt
;
2234 FPR_STATE
[fpr
] = fmt_unknown
;
2240 case fmt_uninterpreted_32
:
2241 fmt
= fmt_uninterpreted
;
2244 FGR
[fpr
] = (value
& 0xFFFFFFFF);
2245 FPR_STATE
[fpr
] = fmt
;
2248 case fmt_uninterpreted_64
:
2249 fmt
= fmt_uninterpreted
;
2250 case fmt_uninterpreted
:
2253 if ((fpr
& 1) == 0) { /* even register number only */
2254 FGR
[fpr
+1] = (value
>> 32);
2255 FGR
[fpr
] = (value
& 0xFFFFFFFF);
2256 FPR_STATE
[fpr
+ 1] = fmt
;
2257 FPR_STATE
[fpr
] = fmt
;
2259 FPR_STATE
[fpr
] = fmt_unknown
;
2260 FPR_STATE
[fpr
+ 1] = fmt_unknown
;
2261 SignalException(ReservedInstruction
,0);
2266 FPR_STATE
[fpr
] = fmt_unknown
;
2271 #if defined(WARN_RESULT)
2274 #endif /* WARN_RESULT */
2277 SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR()");
2280 printf("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",fpr
,pr_addr(FGR
[fpr
]),DOFMT(fmt
));
2297 sim_fpu_32to (&wop
, op
);
2298 boolean
= sim_fpu_is_nan (&wop
);
2305 sim_fpu_64to (&wop
, op
);
2306 boolean
= sim_fpu_is_nan (&wop
);
2310 fprintf (stderr
, "Bad switch\n");
2315 printf("DBG: NaN: returning %d for 0x%s (format = %s)\n",boolean
,pr_addr(op
),DOFMT(fmt
));
2329 printf("DBG: Infinity: format %s 0x%s\n",DOFMT(fmt
),pr_addr(op
));
2336 sim_fpu_32to (&wop
, op
);
2337 boolean
= sim_fpu_is_infinity (&wop
);
2343 sim_fpu_64to (&wop
, op
);
2344 boolean
= sim_fpu_is_infinity (&wop
);
2348 printf("DBG: TODO: unrecognised format (%s) for Infinity check\n",DOFMT(fmt
));
2353 printf("DBG: Infinity: returning %d for 0x%s (format = %s)\n",boolean
,pr_addr(op
),DOFMT(fmt
));
2367 /* Argument checking already performed by the FPCOMPARE code */
2370 printf("DBG: Less: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2373 /* The format type should already have been checked: */
2379 sim_fpu_32to (&wop1
, op1
);
2380 sim_fpu_32to (&wop2
, op2
);
2381 boolean
= sim_fpu_is_lt (&wop1
, &wop2
);
2388 sim_fpu_64to (&wop1
, op1
);
2389 sim_fpu_64to (&wop2
, op2
);
2390 boolean
= sim_fpu_is_lt (&wop1
, &wop2
);
2394 fprintf (stderr
, "Bad switch\n");
2399 printf("DBG: Less: returning %d (format = %s)\n",boolean
,DOFMT(fmt
));
2413 /* Argument checking already performed by the FPCOMPARE code */
2416 printf("DBG: Equal: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2419 /* The format type should already have been checked: */
2425 sim_fpu_32to (&wop1
, op1
);
2426 sim_fpu_32to (&wop2
, op2
);
2427 boolean
= sim_fpu_is_eq (&wop1
, &wop2
);
2434 sim_fpu_64to (&wop1
, op1
);
2435 sim_fpu_64to (&wop2
, op2
);
2436 boolean
= sim_fpu_is_eq (&wop1
, &wop2
);
2440 fprintf (stderr
, "Bad switch\n");
2445 printf("DBG: Equal: returning %d (format = %s)\n",boolean
,DOFMT(fmt
));
2452 AbsoluteValue(op
,fmt
)
2459 printf("DBG: AbsoluteValue: %s: op = 0x%s\n",DOFMT(fmt
),pr_addr(op
));
2462 /* The format type should already have been checked: */
2468 sim_fpu_32to (&wop
, op
);
2469 sim_fpu_abs (&wop
, &wop
);
2470 sim_fpu_to32 (&ans
, &wop
);
2478 sim_fpu_64to (&wop
, op
);
2479 sim_fpu_abs (&wop
, &wop
);
2480 sim_fpu_to64 (&ans
, &wop
);
2485 fprintf (stderr
, "Bad switch\n");
2500 printf("DBG: Negate: %s: op = 0x%s\n",DOFMT(fmt
),pr_addr(op
));
2503 /* The format type should already have been checked: */
2509 sim_fpu_32to (&wop
, op
);
2510 sim_fpu_neg (&wop
, &wop
);
2511 sim_fpu_to32 (&ans
, &wop
);
2519 sim_fpu_64to (&wop
, op
);
2520 sim_fpu_neg (&wop
, &wop
);
2521 sim_fpu_to64 (&ans
, &wop
);
2526 fprintf (stderr
, "Bad switch\n");
2542 printf("DBG: Add: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2545 /* The registers must specify FPRs valid for operands of type
2546 "fmt". If they are not valid, the result is undefined. */
2548 /* The format type should already have been checked: */
2556 sim_fpu_32to (&wop1
, op1
);
2557 sim_fpu_32to (&wop2
, op2
);
2558 sim_fpu_add (&ans
, &wop1
, &wop2
);
2559 sim_fpu_to32 (&res
, &ans
);
2569 sim_fpu_64to (&wop1
, op1
);
2570 sim_fpu_64to (&wop2
, op2
);
2571 sim_fpu_add (&ans
, &wop1
, &wop2
);
2572 sim_fpu_to64 (&res
, &ans
);
2577 fprintf (stderr
, "Bad switch\n");
2582 printf("DBG: Add: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2597 printf("DBG: Sub: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2600 /* The registers must specify FPRs valid for operands of type
2601 "fmt". If they are not valid, the result is undefined. */
2603 /* The format type should already have been checked: */
2611 sim_fpu_32to (&wop1
, op1
);
2612 sim_fpu_32to (&wop2
, op2
);
2613 sim_fpu_sub (&ans
, &wop1
, &wop2
);
2614 sim_fpu_to32 (&res
, &ans
);
2624 sim_fpu_64to (&wop1
, op1
);
2625 sim_fpu_64to (&wop2
, op2
);
2626 sim_fpu_sub (&ans
, &wop1
, &wop2
);
2627 sim_fpu_to64 (&res
, &ans
);
2632 fprintf (stderr
, "Bad switch\n");
2637 printf("DBG: Sub: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2644 Multiply(op1
,op2
,fmt
)
2652 printf("DBG: Multiply: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2655 /* The registers must specify FPRs valid for operands of type
2656 "fmt". If they are not valid, the result is undefined. */
2658 /* The format type should already have been checked: */
2666 sim_fpu_32to (&wop1
, op1
);
2667 sim_fpu_32to (&wop2
, op2
);
2668 sim_fpu_mul (&ans
, &wop1
, &wop2
);
2669 sim_fpu_to32 (&res
, &ans
);
2679 sim_fpu_64to (&wop1
, op1
);
2680 sim_fpu_64to (&wop2
, op2
);
2681 sim_fpu_mul (&ans
, &wop1
, &wop2
);
2682 sim_fpu_to64 (&res
, &ans
);
2687 fprintf (stderr
, "Bad switch\n");
2692 printf("DBG: Multiply: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2707 printf("DBG: Divide: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2710 /* The registers must specify FPRs valid for operands of type
2711 "fmt". If they are not valid, the result is undefined. */
2713 /* The format type should already have been checked: */
2721 sim_fpu_32to (&wop1
, op1
);
2722 sim_fpu_32to (&wop2
, op2
);
2723 sim_fpu_div (&ans
, &wop1
, &wop2
);
2724 sim_fpu_to32 (&res
, &ans
);
2734 sim_fpu_64to (&wop1
, op1
);
2735 sim_fpu_64to (&wop2
, op2
);
2736 sim_fpu_div (&ans
, &wop1
, &wop2
);
2737 sim_fpu_to64 (&res
, &ans
);
2742 fprintf (stderr
, "Bad switch\n");
2747 printf("DBG: Divide: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2761 printf("DBG: Recip: %s: op = 0x%s\n",DOFMT(fmt
),pr_addr(op
));
2764 /* The registers must specify FPRs valid for operands of type
2765 "fmt". If they are not valid, the result is undefined. */
2767 /* The format type should already have been checked: */
2774 sim_fpu_32to (&wop
, op
);
2775 sim_fpu_inv (&ans
, &wop
);
2776 sim_fpu_to32 (&res
, &ans
);
2785 sim_fpu_64to (&wop
, op
);
2786 sim_fpu_inv (&ans
, &wop
);
2787 sim_fpu_to64 (&res
, &ans
);
2792 fprintf (stderr
, "Bad switch\n");
2797 printf("DBG: Recip: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2811 printf("DBG: SquareRoot: %s: op = 0x%s\n",DOFMT(fmt
),pr_addr(op
));
2814 /* The registers must specify FPRs valid for operands of type
2815 "fmt". If they are not valid, the result is undefined. */
2817 /* The format type should already have been checked: */
2824 sim_fpu_32to (&wop
, op
);
2825 sim_fpu_sqrt (&ans
, &wop
);
2826 sim_fpu_to32 (&res
, &ans
);
2835 sim_fpu_64to (&wop
, op
);
2836 sim_fpu_sqrt (&ans
, &wop
);
2837 sim_fpu_to64 (&res
, &ans
);
2842 fprintf (stderr
, "Bad switch\n");
2847 printf("DBG: SquareRoot: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2854 convert (SIM_DESC sd
,
2863 sim_fpu_round round
;
2864 unsigned32 result32
;
2865 unsigned64 result64
;
2868 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
));
2874 /* Round result to nearest representable value. When two
2875 representable values are equally near, round to the value
2876 that has a least significant bit of zero (i.e. is even). */
2877 round
= sim_fpu_round_near
;
2880 /* Round result to the value closest to, and not greater in
2881 magnitude than, the result. */
2882 round
= sim_fpu_round_zero
;
2885 /* Round result to the value closest to, and not less than,
2887 round
= sim_fpu_round_up
;
2891 /* Round result to the value closest to, and not greater than,
2893 round
= sim_fpu_round_down
;
2897 fprintf (stderr
, "Bad switch\n");
2901 /* Convert the input to sim_fpu internal format */
2905 sim_fpu_64to (&wop
, op
);
2908 sim_fpu_32to (&wop
, op
);
2911 sim_fpu_i32to (&wop
, op
, round
);
2914 sim_fpu_i64to (&wop
, op
, round
);
2917 fprintf (stderr
, "Bad switch\n");
2921 /* Convert sim_fpu format into the output */
2922 /* The value WOP is converted to the destination format, rounding
2923 using mode RM. When the destination is a fixed-point format, then
2924 a source value of Infinity, NaN or one which would round to an
2925 integer outside the fixed point range then an IEEE Invalid
2926 Operation condition is raised. */
2930 sim_fpu_round_32 (&wop
, round
, 0);
2931 sim_fpu_to32 (&result32
, &wop
);
2932 result64
= result32
;
2935 sim_fpu_round_64 (&wop
, round
, 0);
2936 sim_fpu_to64 (&result64
, &wop
);
2939 sim_fpu_to32i (&result32
, &wop
, round
);
2940 result64
= result32
;
2943 sim_fpu_to64i (&result64
, &wop
, round
);
2947 fprintf (stderr
, "Bad switch\n");
2952 printf("DBG: Convert: returning 0x%s (to format = %s)\n",pr_addr(result64
),DOFMT(to
));
2959 /*-- co-processor support routines ------------------------------------------*/
2962 CoProcPresent(coproc_number
)
2963 unsigned int coproc_number
;
2965 /* Return TRUE if simulator provides a model for the given co-processor number */
2970 cop_lw (SIM_DESC sd
,
2975 unsigned int memword
)
2980 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
2983 printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%s\n",memword
,pr_addr(memword
));
2985 StoreFPR(coproc_reg
,fmt_word
,(uword64
)memword
);
2986 FPR_STATE
[coproc_reg
] = fmt_uninterpreted
;
2991 #if 0 /* this should be controlled by a configuration option */
2992 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
));
3001 cop_ld (SIM_DESC sd
,
3008 switch (coproc_num
) {
3010 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
3012 StoreFPR(coproc_reg
,fmt_uninterpreted
,memword
);
3017 #if 0 /* this message should be controlled by a configuration option */
3018 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
));
3027 cop_sw (SIM_DESC sd
,
3033 unsigned int value
= 0;
3038 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
3041 hold
= FPR_STATE
[coproc_reg
];
3042 FPR_STATE
[coproc_reg
] = fmt_word
;
3043 value
= (unsigned int)ValueFPR(coproc_reg
,fmt_uninterpreted
);
3044 FPR_STATE
[coproc_reg
] = hold
;
3049 #if 0 /* should be controlled by configuration option */
3050 sim_io_printf(sd
,"COP_SW(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num
,coproc_reg
,pr_addr(cia
));
3059 cop_sd (SIM_DESC sd
,
3069 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
3071 value
= ValueFPR(coproc_reg
,fmt_uninterpreted
);
3076 #if 0 /* should be controlled by configuration option */
3077 sim_io_printf(sd
,"COP_SD(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num
,coproc_reg
,pr_addr(cia
));
3086 decode_coproc (SIM_DESC sd
,
3089 unsigned int instruction
)
3091 int coprocnum
= ((instruction
>> 26) & 3);
3095 case 0: /* standard CPU control and cache registers */
3097 int code
= ((instruction
>> 21) & 0x1F);
3098 /* R4000 Users Manual (second edition) lists the following CP0
3100 DMFC0 Doubleword Move From CP0 (VR4100 = 01000000001tttttddddd00000000000)
3101 DMTC0 Doubleword Move To CP0 (VR4100 = 01000000101tttttddddd00000000000)
3102 MFC0 word Move From CP0 (VR4100 = 01000000000tttttddddd00000000000)
3103 MTC0 word Move To CP0 (VR4100 = 01000000100tttttddddd00000000000)
3104 TLBR Read Indexed TLB Entry (VR4100 = 01000010000000000000000000000001)
3105 TLBWI Write Indexed TLB Entry (VR4100 = 01000010000000000000000000000010)
3106 TLBWR Write Random TLB Entry (VR4100 = 01000010000000000000000000000110)
3107 TLBP Probe TLB for Matching Entry (VR4100 = 01000010000000000000000000001000)
3108 CACHE Cache operation (VR4100 = 101111bbbbbpppppiiiiiiiiiiiiiiii)
3109 ERET Exception return (VR4100 = 01000010000000000000000000011000)
3111 if (((code
== 0x00) || (code
== 0x04)) && ((instruction
& 0x7FF) == 0))
3113 int rt
= ((instruction
>> 16) & 0x1F);
3114 int rd
= ((instruction
>> 11) & 0x1F);
3116 switch (rd
) /* NOTEs: Standard CP0 registers */
3118 /* 0 = Index R4000 VR4100 VR4300 */
3119 /* 1 = Random R4000 VR4100 VR4300 */
3120 /* 2 = EntryLo0 R4000 VR4100 VR4300 */
3121 /* 3 = EntryLo1 R4000 VR4100 VR4300 */
3122 /* 4 = Context R4000 VR4100 VR4300 */
3123 /* 5 = PageMask R4000 VR4100 VR4300 */
3124 /* 6 = Wired R4000 VR4100 VR4300 */
3125 /* 8 = BadVAddr R4000 VR4100 VR4300 */
3126 /* 9 = Count R4000 VR4100 VR4300 */
3127 /* 10 = EntryHi R4000 VR4100 VR4300 */
3128 /* 11 = Compare R4000 VR4100 VR4300 */
3129 /* 12 = SR R4000 VR4100 VR4300 */
3136 /* 13 = Cause R4000 VR4100 VR4300 */
3143 /* 14 = EPC R4000 VR4100 VR4300 */
3144 /* 15 = PRId R4000 VR4100 VR4300 */
3145 #ifdef SUBTARGET_R3900
3154 /* 16 = Config R4000 VR4100 VR4300 */
3157 GPR
[rt
] = C0_CONFIG
;
3159 C0_CONFIG
= GPR
[rt
];
3162 #ifdef SUBTARGET_R3900
3171 /* 17 = LLAddr R4000 VR4100 VR4300 */
3173 /* 18 = WatchLo R4000 VR4100 VR4300 */
3174 /* 19 = WatchHi R4000 VR4100 VR4300 */
3175 /* 20 = XContext R4000 VR4100 VR4300 */
3176 /* 26 = PErr or ECC R4000 VR4100 VR4300 */
3177 /* 27 = CacheErr R4000 VR4100 */
3178 /* 28 = TagLo R4000 VR4100 VR4300 */
3179 /* 29 = TagHi R4000 VR4100 VR4300 */
3180 /* 30 = ErrorEPC R4000 VR4100 VR4300 */
3181 GPR
[rt
] = 0xDEADC0DE; /* CPR[0,rd] */
3182 /* CPR[0,rd] = GPR[rt]; */
3185 sim_io_printf(sd
,"Warning: MFC0 %d,%d ignored (architecture specific)\n",rt
,rd
);
3187 sim_io_printf(sd
,"Warning: MTC0 %d,%d ignored (architecture specific)\n",rt
,rd
);
3190 else if (code
== 0x10 && (instruction
& 0x3f) == 0x18)
3193 if (SR
& status_ERL
)
3195 /* Oops, not yet available */
3196 sim_io_printf(sd
,"Warning: ERET when SR[ERL] set not handled yet");
3206 else if (code
== 0x10 && (instruction
& 0x3f) == 0x10)
3210 else if (code
== 0x10 && (instruction
& 0x3f) == 0x1F)
3218 sim_io_eprintf(sd
,"Unrecognised COP0 instruction 0x%08X at PC = 0x%s : No handler present\n",instruction
,pr_addr(cia
));
3219 /* TODO: When executing an ERET or RFE instruction we should
3220 clear LLBIT, to ensure that any out-standing atomic
3221 read/modify/write sequence fails. */
3225 case 2: /* undefined co-processor */
3226 sim_io_eprintf(sd
,"COP2 instruction 0x%08X at PC = 0x%s : No handler present\n",instruction
,pr_addr(cia
));
3229 case 1: /* should not occur (FPU co-processor) */
3230 case 3: /* should not occur (FPU co-processor) */
3231 SignalException(ReservedInstruction
,instruction
);
3238 /*-- instruction simulation -------------------------------------------------*/
3240 /* When the IGEN simulator is being built, the function below is be
3241 replaced by a generated version. However, WITH_IGEN == 2 indicates
3242 that the fubction below should be compiled but under a different
3243 name (to allow backward compatibility) */
3245 #if (WITH_IGEN != 1)
3247 void old_engine_run
PARAMS ((SIM_DESC sd
, int next_cpu_nr
, int siggnal
));
3249 old_engine_run (sd
, next_cpu_nr
, nr_cpus
, siggnal
)
3252 sim_engine_run (sd
, next_cpu_nr
, nr_cpus
, siggnal
)
3255 int next_cpu_nr
; /* ignore */
3256 int nr_cpus
; /* ignore */
3257 int siggnal
; /* ignore */
3259 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* hardwire to cpu 0 */
3260 #if !defined(FASTSIM)
3261 unsigned int pipeline_count
= 1;
3265 if (STATE_MEMORY (sd
) == NULL
) {
3266 printf("DBG: simulate() entered with no memory\n");
3271 #if 0 /* Disabled to check that everything works OK */
3272 /* The VR4300 seems to sign-extend the PC on its first
3273 access. However, this may just be because it is currently
3274 configured in 32bit mode. However... */
3275 PC
= SIGNEXTEND(PC
,32);
3278 /* main controlling loop */
3280 /* vaddr is slowly being replaced with cia - current instruction
3282 address_word cia
= (uword64
)PC
;
3283 address_word vaddr
= cia
;
3286 unsigned int instruction
; /* uword64? what's this used for? FIXME! */
3290 printf("DBG: state = 0x%08X :",state
);
3291 if (state
& simHALTEX
) printf(" simHALTEX");
3292 if (state
& simHALTIN
) printf(" simHALTIN");
3297 DSSTATE
= (STATE
& simDELAYSLOT
);
3300 sim_io_printf(sd
,"DBG: DSPC = 0x%s\n",pr_addr(DSPC
));
3303 /* Fetch the next instruction from the simulator memory: */
3304 if (AddressTranslation(cia
,isINSTRUCTION
,isLOAD
,&paddr
,&cca
,isTARGET
,isREAL
)) {
3305 if ((vaddr
& 1) == 0) {
3306 /* Copy the action of the LW instruction */
3307 unsigned int reverse
= (ReverseEndian
? (LOADDRMASK
>> 2) : 0);
3308 unsigned int bigend
= (BigEndianCPU
? (LOADDRMASK
>> 2) : 0);
3311 paddr
= ((paddr
& ~LOADDRMASK
) | ((paddr
& LOADDRMASK
) ^ (reverse
<< 2)));
3312 LoadMemory(&value
,NULL
,cca
,AccessLength_WORD
,paddr
,vaddr
,isINSTRUCTION
,isREAL
);
3313 byte
= ((vaddr
& LOADDRMASK
) ^ (bigend
<< 2));
3314 instruction
= ((value
>> (8 * byte
)) & 0xFFFFFFFF);
3316 /* Copy the action of the LH instruction */
3317 unsigned int reverse
= (ReverseEndian
? (LOADDRMASK
>> 1) : 0);
3318 unsigned int bigend
= (BigEndianCPU
? (LOADDRMASK
>> 1) : 0);
3321 paddr
= (((paddr
& ~ (uword64
) 1) & ~LOADDRMASK
)
3322 | (((paddr
& ~ (uword64
) 1) & LOADDRMASK
) ^ (reverse
<< 1)));
3323 LoadMemory(&value
,NULL
,cca
, AccessLength_HALFWORD
,
3324 paddr
& ~ (uword64
) 1,
3325 vaddr
, isINSTRUCTION
, isREAL
);
3326 byte
= (((vaddr
&~ (uword64
) 1) & LOADDRMASK
) ^ (bigend
<< 1));
3327 instruction
= ((value
>> (8 * byte
)) & 0xFFFF);
3330 fprintf(stderr
,"Cannot translate address for PC = 0x%s failed\n",pr_addr(PC
));
3335 sim_io_printf(sd
,"DBG: fetched 0x%08X from PC = 0x%s\n",instruction
,pr_addr(PC
));
3338 /* This is required by exception processing, to ensure that we can
3339 cope with exceptions in the delay slots of branches that may
3340 already have changed the PC. */
3341 if ((vaddr
& 1) == 0)
3342 PC
+= 4; /* increment ready for the next fetch */
3345 /* NOTE: If we perform a delay slot change to the PC, this
3346 increment is not requuired. However, it would make the
3347 simulator more complicated to try and avoid this small hit. */
3349 /* Currently this code provides a simple model. For more
3350 complicated models we could perform exception status checks at
3351 this point, and set the simSTOP state as required. This could
3352 also include processing any hardware interrupts raised by any
3353 I/O model attached to the simulator context.
3355 Support for "asynchronous" I/O events within the simulated world
3356 could be providing by managing a counter, and calling a I/O
3357 specific handler when a particular threshold is reached. On most
3358 architectures a decrement and check for zero operation is
3359 usually quicker than an increment and compare. However, the
3360 process of managing a known value decrement to zero, is higher
3361 than the cost of using an explicit value UINT_MAX into the
3362 future. Which system is used will depend on how complicated the
3363 I/O model is, and how much it is likely to affect the simulator
3366 If events need to be scheduled further in the future than
3367 UINT_MAX event ticks, then the I/O model should just provide its
3368 own counter, triggered from the event system. */
3370 /* MIPS pipeline ticks. To allow for future support where the
3371 pipeline hit of individual instructions is known, this control
3372 loop manages a "pipeline_count" variable. It is initialised to
3373 1 (one), and will only be changed by the simulator engine when
3374 executing an instruction. If the engine does not have access to
3375 pipeline cycle count information then all instructions will be
3376 treated as using a single cycle. NOTE: A standard system is not
3377 provided by the default simulator because different MIPS
3378 architectures have different cycle counts for the same
3381 [NOTE: pipeline_count has been replaced the event queue] */
3383 /* shuffle the floating point status pipeline state */
3384 ENGINE_ISSUE_PREFIX_HOOK();
3386 /* NOTE: For multi-context simulation environments the "instruction"
3387 variable should be local to this routine. */
3389 /* Shorthand accesses for engine. Note: If we wanted to use global
3390 variables (and a single-threaded simulator engine), then we can
3391 create the actual variables with these names. */
3393 if (!(STATE
& simSKIPNEXT
)) {
3394 /* Include the simulator engine */
3395 #include "oengine.c"
3396 #if ((GPRLEN == 64) && !PROCESSOR_64BIT) || ((GPRLEN == 32) && PROCESSOR_64BIT)
3397 #error "Mismatch between run-time simulator code and simulation engine"
3399 #if (WITH_TARGET_WORD_BITSIZE != GPRLEN)
3400 #error "Mismatch between configure WITH_TARGET_WORD_BITSIZE and gencode GPRLEN"
3402 #if ((WITH_FLOATING_POINT == HARD_FLOATING_POINT) != defined (HASFPU))
3403 #error "Mismatch between configure WITH_FLOATING_POINT and gencode HASFPU"
3406 #if defined(WARN_LOHI)
3407 /* Decrement the HI/LO validity ticks */
3412 /* start-sanitize-r5900 */
3417 /* end-sanitize-r5900 */
3418 #endif /* WARN_LOHI */
3420 /* For certain MIPS architectures, GPR[0] is hardwired to zero. We
3421 should check for it being changed. It is better doing it here,
3422 than within the simulator, since it will help keep the simulator
3425 #if defined(WARN_ZERO)
3426 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
));
3427 #endif /* WARN_ZERO */
3428 ZERO
= 0; /* reset back to zero before next instruction */
3430 } else /* simSKIPNEXT check */
3431 STATE
&= ~simSKIPNEXT
;
3433 /* If the delay slot was active before the instruction is
3434 executed, then update the PC to its new value: */
3437 printf("DBG: dsstate set before instruction execution - updating PC to 0x%s\n",pr_addr(DSPC
));
3446 #if !defined(FASTSIM)
3447 if (sim_events_tickn (sd
, pipeline_count
))
3449 /* cpu->cia = cia; */
3450 sim_events_process (sd
);
3453 if (sim_events_tick (sd
))
3455 /* cpu->cia = cia; */
3456 sim_events_process (sd
);
3458 #endif /* FASTSIM */
3464 /* This code copied from gdb's utils.c. Would like to share this code,
3465 but don't know of a common place where both could get to it. */
3467 /* Temporary storage using circular buffer */
3473 static char buf
[NUMCELLS
][CELLSIZE
];
3475 if (++cell
>=NUMCELLS
) cell
=0;
3479 /* Print routines to handle variable size regs, etc */
3481 /* Eliminate warning from compiler on 32-bit systems */
3482 static int thirty_two
= 32;
3488 char *paddr_str
=get_cell();
3489 switch (sizeof(addr
))
3492 sprintf(paddr_str
,"%08lx%08lx",
3493 (unsigned long)(addr
>>thirty_two
),(unsigned long)(addr
&0xffffffff));
3496 sprintf(paddr_str
,"%08lx",(unsigned long)addr
);
3499 sprintf(paddr_str
,"%04x",(unsigned short)(addr
&0xffff));
3502 sprintf(paddr_str
,"%x",addr
);
3511 char *paddr_str
=get_cell();
3512 sprintf(paddr_str
,"%08lx%08lx",
3513 (unsigned long)(addr
>>thirty_two
),(unsigned long)(addr
&0xffffffff));
3519 pending_tick (SIM_DESC sd
,
3524 sim_io_printf (sd
, "PENDING_DRAIN - pending_in = %d, pending_out = %d, pending_total = %d\n", PENDING_IN
, PENDING_OUT
, PENDING_TOTAL
);
3525 if (PENDING_OUT
!= PENDING_IN
)
3528 int index
= PENDING_OUT
;
3529 int total
= PENDING_TOTAL
;
3530 if (PENDING_TOTAL
== 0)
3531 sim_engine_abort (SD
, CPU
, cia
, "PENDING_DRAIN - Mis-match on pending update pointers\n");
3532 for (loop
= 0; (loop
< total
); loop
++)
3534 if (PENDING_SLOT_DEST
[index
] != NULL
)
3536 PENDING_SLOT_DELAY
[index
] -= 1;
3537 if (PENDING_SLOT_DELAY
[index
] == 0)
3539 if (PENDING_SLOT_BIT
[index
] >= 0)
3540 switch (PENDING_SLOT_SIZE
[index
])
3543 if (PENDING_SLOT_VALUE
[index
])
3544 *(unsigned32
*)PENDING_SLOT_DEST
[index
] |=
3545 BIT32 (PENDING_SLOT_BIT
[index
]);
3547 *(unsigned32
*)PENDING_SLOT_DEST
[index
] &=
3548 BIT32 (PENDING_SLOT_BIT
[index
]);
3551 if (PENDING_SLOT_VALUE
[index
])
3552 *(unsigned64
*)PENDING_SLOT_DEST
[index
] |=
3553 BIT64 (PENDING_SLOT_BIT
[index
]);
3555 *(unsigned64
*)PENDING_SLOT_DEST
[index
] &=
3556 BIT64 (PENDING_SLOT_BIT
[index
]);
3561 switch (PENDING_SLOT_SIZE
[index
])
3564 *(unsigned32
*)PENDING_SLOT_DEST
[index
] =
3565 PENDING_SLOT_VALUE
[index
];
3568 *(unsigned64
*)PENDING_SLOT_DEST
[index
] =
3569 PENDING_SLOT_VALUE
[index
];
3573 if (PENDING_OUT
== index
)
3575 PENDING_SLOT_DEST
[index
] = NULL
;
3576 PENDING_OUT
= (PENDING_OUT
+ 1) % PSLOTS
;
3581 index
= (index
+ 1) % PSLOTS
;
3585 /*---------------------------------------------------------------------------*/
3586 /*> EOF interp.c <*/