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.
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
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 */
37 #include "sim-utils.h"
38 #include "sim-options.h"
39 #include "sim-assert.h"
41 /* start-sanitize-sky */
45 #include "sky-libvpe.h"
49 /* end-sanitize-sky */
71 #include "libiberty.h"
73 #include "callback.h" /* GDB simulator callback interface */
74 #include "remote-sim.h" /* GDB simulator interface */
82 char* pr_addr
PARAMS ((SIM_ADDR addr
));
83 char* pr_uword64
PARAMS ((uword64 addr
));
86 /* Get the simulator engine description, without including the code: */
93 /* Within interp.c we refer to the sim_state and sim_cpu directly. */
98 /* The following reserved instruction value is used when a simulator
99 trap is required. NOTE: Care must be taken, since this value may be
100 used in later revisions of the MIPS ISA. */
101 #define RSVD_INSTRUCTION (0x00000005)
102 #define RSVD_INSTRUCTION_MASK (0xFC00003F)
104 #define RSVD_INSTRUCTION_ARG_SHIFT 6
105 #define RSVD_INSTRUCTION_ARG_MASK 0xFFFFF
108 /* Bits in the Debug register */
109 #define Debug_DBD 0x80000000 /* Debug Branch Delay */
110 #define Debug_DM 0x40000000 /* Debug Mode */
111 #define Debug_DBp 0x00000002 /* Debug Breakpoint indicator */
117 /*---------------------------------------------------------------------------*/
118 /*-- GDB simulator interface ------------------------------------------------*/
119 /*---------------------------------------------------------------------------*/
121 static void ColdReset
PARAMS((SIM_DESC sd
));
123 /*---------------------------------------------------------------------------*/
127 #define DELAYSLOT() {\
128 if (STATE & simDELAYSLOT)\
129 sim_io_eprintf(sd,"Delay slot already activated (branch in delay slot?)\n");\
130 STATE |= simDELAYSLOT;\
133 #define JALDELAYSLOT() {\
135 STATE |= simJALDELAYSLOT;\
139 STATE &= ~simDELAYSLOT;\
140 STATE |= simSKIPNEXT;\
143 #define CANCELDELAYSLOT() {\
145 STATE &= ~(simDELAYSLOT | simJALDELAYSLOT);\
148 #define INDELAYSLOT() ((STATE & simDELAYSLOT) != 0)
149 #define INJALDELAYSLOT() ((STATE & simJALDELAYSLOT) != 0)
151 #define K0BASE (0x80000000)
152 #define K0SIZE (0x20000000)
153 #define K1BASE (0xA0000000)
154 #define K1SIZE (0x20000000)
155 #define MONITOR_BASE (0xBFC00000)
156 #define MONITOR_SIZE (1 << 11)
157 #define MEM_SIZE (2 << 20)
159 /* start-sanitize-sky */
162 #define MEM_SIZE (16 << 20) /* 16 MB */
164 /* end-sanitize-sky */
167 static char *tracefile
= "trace.din"; /* default filename for trace log */
168 FILE *tracefh
= NULL
;
169 static void open_trace
PARAMS((SIM_DESC sd
));
172 static DECLARE_OPTION_HANDLER (mips_option_handler
);
175 OPTION_DINERO_TRACE
= OPTION_START
,
177 /* start-sanitize-sky */
179 /* end-sanitize-sky */
183 mips_option_handler (sd
, cpu
, opt
, arg
, is_command
)
193 case OPTION_DINERO_TRACE
: /* ??? */
195 /* Eventually the simTRACE flag could be treated as a toggle, to
196 allow external control of the program points being traced
197 (i.e. only from main onwards, excluding the run-time setup,
199 for (cpu_nr
= 0; cpu_nr
< MAX_NR_PROCESSORS
; cpu_nr
++)
201 sim_cpu
*cpu
= STATE_CPU (sd
, cpu_nr
);
204 else if (strcmp (arg
, "yes") == 0)
206 else if (strcmp (arg
, "no") == 0)
208 else if (strcmp (arg
, "on") == 0)
210 else if (strcmp (arg
, "off") == 0)
214 fprintf (stderr
, "Unrecognized dinero-trace option `%s'\n", arg
);
221 Simulator constructed without dinero tracing support (for performance).\n\
222 Re-compile simulator with \"-DTRACE\" to enable this option.\n");
226 case OPTION_DINERO_FILE
:
228 if (optarg
!= NULL
) {
230 tmp
= (char *)malloc(strlen(optarg
) + 1);
233 sim_io_printf(sd
,"Failed to allocate buffer for tracefile name \"%s\"\n",optarg
);
239 sim_io_printf(sd
,"Placing trace information into file \"%s\"\n",tracefile
);
245 /* start-sanitize-sky */
246 case OPTION_FLOAT_TYPE
:
247 /* Use host (fast) or target (accurate) floating point implementation. */
248 if (arg
&& strcmp (arg
, "host") == 0)
249 STATE_FP_TYPE_OPT (sd
) &= ~STATE_FP_TYPE_OPT_TARGET
;
250 else if (arg
&& strcmp (arg
, "target") == 0)
251 STATE_FP_TYPE_OPT (sd
) |= STATE_FP_TYPE_OPT_TARGET
;
254 fprintf (stderr
, "Unrecognized float-type option `%s'\n", arg
);
258 /* end-sanitize-sky */
264 static const OPTION mips_options
[] =
266 { {"dinero-trace", optional_argument
, NULL
, OPTION_DINERO_TRACE
},
267 '\0', "on|off", "Enable dinero tracing",
268 mips_option_handler
},
269 { {"dinero-file", required_argument
, NULL
, OPTION_DINERO_FILE
},
270 '\0', "FILE", "Write dinero trace to FILE",
271 mips_option_handler
},
272 /* start-sanitize-sky */
273 { {"float-type", required_argument
, NULL
, OPTION_FLOAT_TYPE
},
274 '\0', "host|target", "Use host (fast) or target (accurate) floating point",
275 mips_option_handler
},
276 /* end-sanitize-sky */
277 { {NULL
, no_argument
, NULL
, 0}, '\0', NULL
, NULL
, NULL
}
281 int interrupt_pending
;
284 interrupt_event (SIM_DESC sd
, void *data
)
286 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
289 interrupt_pending
= 0;
290 SignalExceptionInterrupt ();
292 else if (!interrupt_pending
)
293 sim_events_schedule (sd
, 1, interrupt_event
, data
);
297 /*---------------------------------------------------------------------------*/
298 /*-- Device registration hook -----------------------------------------------*/
299 /*---------------------------------------------------------------------------*/
300 static void device_init(SIM_DESC sd
) {
302 extern void register_devices(SIM_DESC
);
303 register_devices(sd
);
307 /*---------------------------------------------------------------------------*/
308 /*-- GDB simulator interface ------------------------------------------------*/
309 /*---------------------------------------------------------------------------*/
312 sim_open (kind
, cb
, abfd
, argv
)
318 SIM_DESC sd
= sim_state_alloc (kind
, cb
);
319 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
321 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
323 /* FIXME: watchpoints code shouldn't need this */
324 STATE_WATCHPOINTS (sd
)->pc
= &(PC
);
325 STATE_WATCHPOINTS (sd
)->sizeof_pc
= sizeof (PC
);
326 STATE_WATCHPOINTS (sd
)->interrupt_handler
= interrupt_event
;
330 if (sim_pre_argv_init (sd
, argv
[0]) != SIM_RC_OK
)
332 sim_add_option_table (sd
, NULL
, mips_options
);
334 /* Allocate core managed memory */
337 sim_do_commandf (sd
, "memory region 0x%lx,0x%lx", MONITOR_BASE
, MONITOR_SIZE
);
338 /* For compatibility with the old code - under this (at level one)
339 are the kernel spaces K0 & K1. Both of these map to a single
340 smaller sub region */
341 sim_do_command(sd
," memory region 0x7fff8000,0x8000") ; /* MTZ- 32 k stack */
342 /* start-sanitize-sky */
344 /* end-sanitize-sky */
345 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x",
347 MEM_SIZE
, /* actual size */
349 /* start-sanitize-sky */
351 sim_do_commandf (sd
, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x,0x%0x",
353 MEM_SIZE
, /* actual size */
355 0); /* add alias at 0x0000 */
357 /* end-sanitize-sky */
361 /* getopt will print the error message so we just have to exit if this fails.
362 FIXME: Hmmm... in the case of gdb we need getopt to call
364 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
366 /* Uninstall the modules to avoid memory leaks,
367 file descriptor leaks, etc. */
368 sim_module_uninstall (sd
);
372 /* check for/establish the a reference program image */
373 if (sim_analyze_program (sd
,
374 (STATE_PROG_ARGV (sd
) != NULL
375 ? *STATE_PROG_ARGV (sd
)
379 sim_module_uninstall (sd
);
383 /* Configure/verify the target byte order and other runtime
384 configuration options */
385 if (sim_config (sd
) != SIM_RC_OK
)
387 sim_module_uninstall (sd
);
391 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
393 /* Uninstall the modules to avoid memory leaks,
394 file descriptor leaks, etc. */
395 sim_module_uninstall (sd
);
399 /* verify assumptions the simulator made about the host type system.
400 This macro does not return if there is a problem */
401 SIM_ASSERT (sizeof(int) == (4 * sizeof(char)));
402 SIM_ASSERT (sizeof(word64
) == (8 * sizeof(char)));
404 /* This is NASTY, in that we are assuming the size of specific
408 for (rn
= 0; (rn
< (LAST_EMBED_REGNUM
+ 1)); rn
++)
411 cpu
->register_widths
[rn
] = WITH_TARGET_WORD_BITSIZE
;
412 else if ((rn
>= FGRIDX
) && (rn
< (FGRIDX
+ NR_FGR
)))
413 cpu
->register_widths
[rn
] = WITH_TARGET_FLOATING_POINT_BITSIZE
;
414 else if ((rn
>= 33) && (rn
<= 37))
415 cpu
->register_widths
[rn
] = WITH_TARGET_WORD_BITSIZE
;
416 else if ((rn
== SRIDX
)
419 || ((rn
>= 72) && (rn
<= 89)))
420 cpu
->register_widths
[rn
] = 32;
422 cpu
->register_widths
[rn
] = 0;
424 /* start-sanitize-r5900 */
426 /* set the 5900 "upper" registers to 64 bits */
427 for( rn
= LAST_EMBED_REGNUM
+1; rn
< NUM_REGS
; rn
++)
428 cpu
->register_widths
[rn
] = 64;
429 /* end-sanitize-r5900 */
431 /* start-sanitize-sky */
433 /* Now the VU registers */
434 for( rn
= 0; rn
< NUM_VU_INTEGER_REGS
; rn
++ ) {
435 cpu
->register_widths
[rn
+ NUM_R5900_REGS
] = 16;
436 cpu
->register_widths
[rn
+ NUM_R5900_REGS
+ NUM_VU_REGS
] = 16;
439 for( rn
= NUM_VU_INTEGER_REGS
; rn
< NUM_VU_REGS
; rn
++ ) {
440 cpu
->register_widths
[rn
+ NUM_R5900_REGS
] = 32;
441 cpu
->register_widths
[rn
+ NUM_R5900_REGS
+ NUM_VU_REGS
] = 32;
444 /* Finally the VIF registers */
445 for( rn
= 2*NUM_VU_REGS
; rn
< 2*NUM_VU_REGS
+ 2*NUM_VIF_REGS
; rn
++ )
446 cpu
->register_widths
[rn
+ NUM_R5900_REGS
] = 32;
448 /* end-sanitize-sky */
452 if (STATE
& simTRACE
)
456 /* Write the monitor trap address handlers into the monitor (eeprom)
457 address space. This can only be done once the target endianness
458 has been determined. */
461 /* Entry into the IDT monitor is via fixed address vectors, and
462 not using machine instructions. To avoid clashing with use of
463 the MIPS TRAP system, we place our own (simulator specific)
464 "undefined" instructions into the relevant vector slots. */
465 for (loop
= 0; (loop
< MONITOR_SIZE
); loop
+= 4)
467 address_word vaddr
= (MONITOR_BASE
+ loop
);
468 unsigned32 insn
= (RSVD_INSTRUCTION
| (((loop
>> 2) & RSVD_INSTRUCTION_ARG_MASK
) << RSVD_INSTRUCTION_ARG_SHIFT
));
470 sim_write (sd
, vaddr
, (char *)&insn
, sizeof (insn
));
472 /* The PMON monitor uses the same address space, but rather than
473 branching into it the address of a routine is loaded. We can
474 cheat for the moment, and direct the PMON routine to IDT style
475 instructions within the monitor space. This relies on the IDT
476 monitor not using the locations from 0xBFC00500 onwards as its
478 for (loop
= 0; (loop
< 24); loop
++)
480 address_word vaddr
= (MONITOR_BASE
+ 0x500 + (loop
* 4));
481 unsigned32 value
= ((0x500 - 8) / 8); /* default UNDEFINED reason code */
497 value
= ((0x500 - 16) / 8); /* not an IDT reason code */
499 case 8: /* cliexit */
502 case 11: /* flush_cache */
506 /* FIXME - should monitor_base be SIM_ADDR?? */
507 value
= ((unsigned int)MONITOR_BASE
+ (value
* 8));
509 sim_write (sd
, vaddr
, (char *)&value
, sizeof (value
));
511 /* The LSI MiniRISC PMON has its vectors at 0x200, not 0x500. */
513 sim_write (sd
, vaddr
, (char *)&value
, sizeof (value
));
525 tracefh
= fopen(tracefile
,"wb+");
528 sim_io_eprintf(sd
,"Failed to create file \"%s\", writing trace information to stderr.\n",tracefile
);
535 sim_close (sd
, quitting
)
540 printf("DBG: sim_close: entered (quitting = %d)\n",quitting
);
543 /* "quitting" is non-zero if we cannot hang on errors */
545 /* Ensure that any resources allocated through the callback
546 mechanism are released: */
547 sim_io_shutdown (sd
);
550 if (tracefh
!= NULL
&& tracefh
!= stderr
)
555 /* FIXME - free SD */
562 sim_write (sd
,addr
,buffer
,size
)
565 unsigned char *buffer
;
569 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
571 /* Return the number of bytes written, or zero if error. */
573 sim_io_printf(sd
,"sim_write(0x%s,buffer,%d);\n",pr_addr(addr
),size
);
576 /* We use raw read and write routines, since we do not want to count
577 the GDB memory accesses in our statistics gathering. */
579 for (index
= 0; index
< size
; index
++)
581 address_word vaddr
= (address_word
)addr
+ index
;
584 if (!address_translation (SD
, CPU
, NULL_CIA
, vaddr
, isDATA
, isSTORE
, &paddr
, &cca
, isRAW
))
586 if (sim_core_write_buffer (SD
, CPU
, read_map
, buffer
+ index
, paddr
, 1) != 1)
594 sim_read (sd
,addr
,buffer
,size
)
597 unsigned char *buffer
;
601 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
603 /* Return the number of bytes read, or zero if error. */
605 sim_io_printf(sd
,"sim_read(0x%s,buffer,%d);\n",pr_addr(addr
),size
);
608 for (index
= 0; (index
< size
); index
++)
610 address_word vaddr
= (address_word
)addr
+ index
;
613 if (!address_translation (SD
, CPU
, NULL_CIA
, vaddr
, isDATA
, isLOAD
, &paddr
, &cca
, isRAW
))
615 if (sim_core_read_buffer (SD
, CPU
, read_map
, buffer
+ index
, paddr
, 1) != 1)
623 sim_store_register (sd
,rn
,memory
,length
)
626 unsigned char *memory
;
629 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
630 /* NOTE: gdb (the client) stores registers in target byte order
631 while the simulator uses host byte order */
633 sim_io_printf(sd
,"sim_store_register(%d,*memory=0x%s);\n",rn
,pr_addr(*((SIM_ADDR
*)memory
)));
636 /* Unfortunately this suffers from the same problem as the register
637 numbering one. We need to know what the width of each logical
638 register number is for the architecture being simulated. */
640 if (cpu
->register_widths
[rn
] == 0)
642 sim_io_eprintf(sd
,"Invalid register width for %d (register store ignored)\n",rn
);
646 /* start-sanitize-r5900 */
647 if (rn
>= 90 && rn
< 90 + 32)
649 GPR1
[rn
- 90] = T2H_8 (*(unsigned64
*)memory
);
655 SA
= T2H_8(*(unsigned64
*)memory
);
657 case 122: /* FIXME */
658 LO1
= T2H_8(*(unsigned64
*)memory
);
660 case 123: /* FIXME */
661 HI1
= T2H_8(*(unsigned64
*)memory
);
664 /* end-sanitize-r5900 */
666 /* start-sanitize-sky */
668 if (rn
>= NUM_R5900_REGS
)
670 rn
= rn
- NUM_R5900_REGS
;
672 if( rn
< NUM_VU_REGS
)
674 if (rn
< NUM_VU_INTEGER_REGS
)
675 return write_vu_int_reg (&(vu0_device
.regs
), rn
, memory
);
676 else if (rn
>= FIRST_VEC_REG
)
679 return write_vu_vec_reg (&(vu0_device
.regs
), rn
>>2, rn
&3,
682 else switch (rn
- NUM_VU_INTEGER_REGS
)
685 return write_vu_special_reg (&vu0_device
, VU_REG_CIA
,
688 return write_vu_misc_reg (&(vu0_device
.regs
), VU_REG_MR
,
690 case 2: /* VU0 has no P register */
693 return write_vu_misc_reg (&(vu0_device
.regs
), VU_REG_MI
,
696 return write_vu_misc_reg (&(vu0_device
.regs
), VU_REG_MQ
,
699 return write_vu_acc_reg (&(vu0_device
.regs
),
700 rn
- (NUM_VU_INTEGER_REGS
+ 5),
705 rn
= rn
- NUM_VU_REGS
;
707 if (rn
< NUM_VU_REGS
)
709 if (rn
< NUM_VU_INTEGER_REGS
)
710 return write_vu_int_reg (&(vu1_device
.regs
), rn
, memory
);
711 else if (rn
>= FIRST_VEC_REG
)
714 return write_vu_vec_reg (&(vu1_device
.regs
),
715 rn
>> 2, rn
& 3, memory
);
717 else switch (rn
- NUM_VU_INTEGER_REGS
)
720 return write_vu_special_reg (&vu1_device
, VU_REG_CIA
,
723 return write_vu_misc_reg (&(vu1_device
.regs
), VU_REG_MR
,
726 return write_vu_misc_reg (&(vu1_device
.regs
), VU_REG_MP
,
729 return write_vu_misc_reg (&(vu1_device
.regs
), VU_REG_MI
,
732 return write_vu_misc_reg (&(vu1_device
.regs
), VU_REG_MQ
,
735 return write_vu_acc_reg (&(vu1_device
.regs
),
736 rn
- (NUM_VU_INTEGER_REGS
+ 5),
741 rn
-= NUM_VU_REGS
; /* VIF0 registers are next */
743 if (rn
< NUM_VIF_REGS
)
745 if (rn
< NUM_VIF_REGS
-1)
746 return write_pke_reg (&pke0_device
, rn
, memory
);
749 sim_io_eprintf( sd
, "Can't write vif0_pc (store ignored)\n" );
754 rn
-= NUM_VIF_REGS
; /* VIF1 registers are last */
756 if (rn
< NUM_VIF_REGS
)
758 if (rn
< NUM_VIF_REGS
-1)
759 return write_pke_reg (&pke1_device
, rn
, memory
);
762 sim_io_eprintf( sd
, "Can't write vif1_pc (store ignored)\n" );
767 sim_io_eprintf( sd
, "Invalid VU register (register store ignored)\n" );
771 /* end-sanitize-sky */
773 if (rn
>= FGRIDX
&& rn
< FGRIDX
+ NR_FGR
)
775 if (cpu
->register_widths
[rn
] == 32)
777 cpu
->fgr
[rn
- FGRIDX
] = T2H_4 (*(unsigned32
*)memory
);
782 cpu
->fgr
[rn
- FGRIDX
] = T2H_8 (*(unsigned64
*)memory
);
787 if (cpu
->register_widths
[rn
] == 32)
789 cpu
->registers
[rn
] = T2H_4 (*(unsigned32
*)memory
);
794 cpu
->registers
[rn
] = T2H_8 (*(unsigned64
*)memory
);
802 sim_fetch_register (sd
,rn
,memory
,length
)
805 unsigned char *memory
;
808 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* FIXME */
809 /* NOTE: gdb (the client) stores registers in target byte order
810 while the simulator uses host byte order */
812 sim_io_printf(sd
,"sim_fetch_register(%d=0x%s,mem) : place simulator registers into memory\n",rn
,pr_addr(registers
[rn
]));
815 if (cpu
->register_widths
[rn
] == 0)
817 sim_io_eprintf (sd
, "Invalid register width for %d (register fetch ignored)\n",rn
);
821 /* start-sanitize-r5900 */
822 if (rn
>= 90 && rn
< 90 + 32)
824 *(unsigned64
*)memory
= GPR1
[rn
- 90];
830 *((unsigned64
*)memory
) = H2T_8(SA
);
832 case 122: /* FIXME */
833 *((unsigned64
*)memory
) = H2T_8(LO1
);
835 case 123: /* FIXME */
836 *((unsigned64
*)memory
) = H2T_8(HI1
);
839 /* end-sanitize-r5900 */
841 /* start-sanitize-sky */
843 if (rn
>= NUM_R5900_REGS
)
845 rn
= rn
- NUM_R5900_REGS
;
847 if (rn
< NUM_VU_REGS
)
849 if (rn
< NUM_VU_INTEGER_REGS
)
850 return read_vu_int_reg (&(vu0_device
.regs
), rn
, memory
);
851 else if (rn
>= FIRST_VEC_REG
)
854 return read_vu_vec_reg (&(vu0_device
.regs
), rn
>>2, rn
& 3,
857 else switch (rn
- NUM_VU_INTEGER_REGS
)
860 return read_vu_special_reg(&vu0_device
, VU_REG_CIA
, memory
);
862 return read_vu_misc_reg (&(vu0_device
.regs
), VU_REG_MR
,
864 case 2: /* VU0 has no P register */
865 *((int *) memory
) = 0;
868 return read_vu_misc_reg (&(vu0_device
.regs
), VU_REG_MI
,
871 return read_vu_misc_reg (&(vu0_device
.regs
), VU_REG_MQ
,
874 return read_vu_acc_reg (&(vu0_device
.regs
),
875 rn
- (NUM_VU_INTEGER_REGS
+ 5),
880 rn
-= NUM_VU_REGS
; /* VU1 registers are next */
882 if (rn
< NUM_VU_REGS
)
884 if (rn
< NUM_VU_INTEGER_REGS
)
885 return read_vu_int_reg (&(vu1_device
.regs
), rn
, memory
);
886 else if (rn
>= FIRST_VEC_REG
)
889 return read_vu_vec_reg (&(vu1_device
.regs
),
890 rn
>> 2, rn
& 3, memory
);
892 else switch (rn
- NUM_VU_INTEGER_REGS
)
895 return read_vu_special_reg(&vu1_device
, VU_REG_CIA
, memory
);
897 return read_vu_misc_reg (&(vu1_device
.regs
),
900 return read_vu_misc_reg (&(vu1_device
.regs
),
903 return read_vu_misc_reg (&(vu1_device
.regs
),
906 return read_vu_misc_reg (&(vu1_device
.regs
),
909 return read_vu_acc_reg (&(vu1_device
.regs
),
910 rn
- (NUM_VU_INTEGER_REGS
+ 5),
915 rn
-= NUM_VU_REGS
; /* VIF0 registers are next */
917 if (rn
< NUM_VIF_REGS
)
919 if (rn
< NUM_VIF_REGS
-1)
920 return read_pke_reg (&pke0_device
, rn
, memory
);
922 return read_pke_pc (&pke0_device
, memory
);
925 rn
-= NUM_VIF_REGS
; /* VIF1 registers are last */
927 if (rn
< NUM_VIF_REGS
)
929 if (rn
< NUM_VIF_REGS
-1)
930 return read_pke_reg (&pke1_device
, rn
, memory
);
932 return read_pke_pc (&pke1_device
, memory
);
935 sim_io_eprintf( sd
, "Invalid VU register (register fetch ignored)\n" );
938 /* end-sanitize-sky */
940 /* Any floating point register */
941 if (rn
>= FGRIDX
&& rn
< FGRIDX
+ NR_FGR
)
943 if (cpu
->register_widths
[rn
] == 32)
945 *(unsigned32
*)memory
= H2T_4 (cpu
->fgr
[rn
- FGRIDX
]);
950 *(unsigned64
*)memory
= H2T_8 (cpu
->fgr
[rn
- FGRIDX
]);
955 if (cpu
->register_widths
[rn
] == 32)
957 *(unsigned32
*)memory
= H2T_4 ((unsigned32
)(cpu
->registers
[rn
]));
962 *(unsigned64
*)memory
= H2T_8 ((unsigned64
)(cpu
->registers
[rn
]));
971 sim_create_inferior (sd
, abfd
, argv
,env
)
979 printf("DBG: sim_create_inferior entered: start_address = 0x%s\n",
987 /* override PC value set by ColdReset () */
989 for (cpu_nr
= 0; cpu_nr
< sim_engine_nr_cpus (sd
); cpu_nr
++)
991 sim_cpu
*cpu
= STATE_CPU (sd
, cpu_nr
);
992 CIA_SET (cpu
, (unsigned64
) bfd_get_start_address (abfd
));
996 #if 0 /* def DEBUG */
999 /* We should really place the argv slot values into the argument
1000 registers, and onto the stack as required. However, this
1001 assumes that we have a stack defined, which is not
1002 necessarily true at the moment. */
1004 sim_io_printf(sd
,"sim_create_inferior() : passed arguments ignored\n");
1005 for (cptr
= argv
; (cptr
&& *cptr
); cptr
++)
1006 printf("DBG: arg \"%s\"\n",*cptr
);
1014 sim_do_command (sd
,cmd
)
1018 if (sim_args_command (sd
, cmd
) != SIM_RC_OK
)
1019 sim_io_printf (sd
, "Error: \"%s\" is not a valid MIPS simulator command.\n",
1023 /*---------------------------------------------------------------------------*/
1024 /*-- Private simulator support interface ------------------------------------*/
1025 /*---------------------------------------------------------------------------*/
1027 /* Read a null terminated string from memory, return in a buffer */
1029 fetch_str (sd
, addr
)
1036 while (sim_read (sd
, addr
+ nr
, &null
, 1) == 1 && null
!= 0)
1038 buf
= NZALLOC (char, nr
+ 1);
1039 sim_read (sd
, addr
, buf
, nr
);
1043 /* Simple monitor interface (currently setup for the IDT and PMON monitors) */
1045 sim_monitor (SIM_DESC sd
,
1048 unsigned int reason
)
1051 printf("DBG: sim_monitor: entered (reason = %d)\n",reason
);
1054 /* The IDT monitor actually allows two instructions per vector
1055 slot. However, the simulator currently causes a trap on each
1056 individual instruction. We cheat, and lose the bottom bit. */
1059 /* The following callback functions are available, however the
1060 monitor we are simulating does not make use of them: get_errno,
1061 isatty, lseek, rename, system, time and unlink */
1065 case 6: /* int open(char *path,int flags) */
1067 char *path
= fetch_str (sd
, A0
);
1068 V0
= sim_io_open (sd
, path
, (int)A1
);
1073 case 7: /* int read(int file,char *ptr,int len) */
1077 char *buf
= zalloc (nr
);
1078 V0
= sim_io_read (sd
, fd
, buf
, nr
);
1079 sim_write (sd
, A1
, buf
, nr
);
1084 case 8: /* int write(int file,char *ptr,int len) */
1088 char *buf
= zalloc (nr
);
1089 sim_read (sd
, A1
, buf
, nr
);
1090 V0
= sim_io_write (sd
, fd
, buf
, nr
);
1095 case 10: /* int close(int file) */
1097 V0
= sim_io_close (sd
, (int)A0
);
1101 case 2: /* Densan monitor: char inbyte(int waitflag) */
1103 if (A0
== 0) /* waitflag == NOWAIT */
1104 V0
= (unsigned_word
)-1;
1106 /* Drop through to case 11 */
1108 case 11: /* char inbyte(void) */
1111 if (sim_io_read_stdin (sd
, &tmp
, sizeof(char)) != sizeof(char))
1113 sim_io_error(sd
,"Invalid return from character read");
1114 V0
= (unsigned_word
)-1;
1117 V0
= (unsigned_word
)tmp
;
1121 case 3: /* Densan monitor: void co(char chr) */
1122 case 12: /* void outbyte(char chr) : write a byte to "stdout" */
1124 char tmp
= (char)(A0
& 0xFF);
1125 sim_io_write_stdout (sd
, &tmp
, sizeof(char));
1129 case 17: /* void _exit() */
1131 sim_io_eprintf (sd
, "sim_monitor(17): _exit(int reason) to be coded\n");
1132 sim_engine_halt (SD
, CPU
, NULL
, NULL_CIA
, sim_exited
,
1133 (unsigned int)(A0
& 0xFFFFFFFF));
1137 case 28 : /* PMON flush_cache */
1140 case 55: /* void get_mem_info(unsigned int *ptr) */
1141 /* in: A0 = pointer to three word memory location */
1142 /* out: [A0 + 0] = size */
1143 /* [A0 + 4] = instruction cache size */
1144 /* [A0 + 8] = data cache size */
1146 unsigned_4 value
= MEM_SIZE
/* FIXME STATE_MEM_SIZE (sd) */;
1147 unsigned_4 zero
= 0;
1149 sim_write (sd
, A0
+ 0, (char *)&value
, 4);
1150 sim_write (sd
, A0
+ 4, (char *)&zero
, 4);
1151 sim_write (sd
, A0
+ 8, (char *)&zero
, 4);
1152 /* sim_io_eprintf (sd, "sim: get_mem_info() depreciated\n"); */
1156 case 158 : /* PMON printf */
1157 /* in: A0 = pointer to format string */
1158 /* A1 = optional argument 1 */
1159 /* A2 = optional argument 2 */
1160 /* A3 = optional argument 3 */
1162 /* The following is based on the PMON printf source */
1164 address_word s
= A0
;
1166 signed_word
*ap
= &A1
; /* 1st argument */
1167 /* This isn't the quickest way, since we call the host print
1168 routine for every character almost. But it does avoid
1169 having to allocate and manage a temporary string buffer. */
1170 /* TODO: Include check that we only use three arguments (A1,
1172 while (sim_read (sd
, s
++, &c
, 1) && c
!= '\0')
1177 enum {FMT_RJUST
, FMT_LJUST
, FMT_RJUST0
, FMT_CENTER
} fmt
= FMT_RJUST
;
1178 int width
= 0, trunc
= 0, haddot
= 0, longlong
= 0;
1179 while (sim_read (sd
, s
++, &c
, 1) && c
!= '\0')
1181 if (strchr ("dobxXulscefg%", s
))
1196 else if (c
>= '1' && c
<= '9')
1200 while (sim_read (sd
, s
++, &c
, 1) == 1 && isdigit (c
))
1203 n
= (unsigned int)strtol(tmp
,NULL
,10);
1216 sim_io_printf (sd
, "%%");
1221 address_word p
= *ap
++;
1223 while (sim_read (sd
, p
++, &ch
, 1) == 1 && ch
!= '\0')
1224 sim_io_printf(sd
, "%c", ch
);
1227 sim_io_printf(sd
,"(null)");
1230 sim_io_printf (sd
, "%c", (int)*ap
++);
1235 sim_read (sd
, s
++, &c
, 1);
1239 sim_read (sd
, s
++, &c
, 1);
1242 if (strchr ("dobxXu", c
))
1244 word64 lv
= (word64
) *ap
++;
1246 sim_io_printf(sd
,"<binary not supported>");
1249 sprintf (tmp
, "%%%s%c", longlong
? "ll" : "", c
);
1251 sim_io_printf(sd
, tmp
, lv
);
1253 sim_io_printf(sd
, tmp
, (int)lv
);
1256 else if (strchr ("eEfgG", c
))
1258 double dbl
= *(double*)(ap
++);
1259 sprintf (tmp
, "%%%d.%d%c", width
, trunc
, c
);
1260 sim_io_printf (sd
, tmp
, dbl
);
1266 sim_io_printf(sd
, "%c", c
);
1272 sim_io_error (sd
, "TODO: sim_monitor(%d) : PC = 0x%s\n",
1273 reason
, pr_addr(cia
));
1279 /* Store a word into memory. */
1282 store_word (SIM_DESC sd
,
1291 if ((vaddr
& 3) != 0)
1292 SignalExceptionAddressStore ();
1295 if (AddressTranslation (vaddr
, isDATA
, isSTORE
, &paddr
, &uncached
,
1298 const uword64 mask
= 7;
1302 paddr
= (paddr
& ~mask
) | ((paddr
& mask
) ^ (ReverseEndian
<< 2));
1303 byte
= (vaddr
& mask
) ^ (BigEndianCPU
<< 2);
1304 memval
= ((uword64
) val
) << (8 * byte
);
1305 StoreMemory (uncached
, AccessLength_WORD
, memval
, 0, paddr
, vaddr
,
1311 /* Load a word from memory. */
1314 load_word (SIM_DESC sd
,
1319 if ((vaddr
& 3) != 0)
1320 SignalExceptionAddressLoad ();
1326 if (AddressTranslation (vaddr
, isDATA
, isLOAD
, &paddr
, &uncached
,
1329 const uword64 mask
= 0x7;
1330 const unsigned int reverse
= ReverseEndian
? 1 : 0;
1331 const unsigned int bigend
= BigEndianCPU
? 1 : 0;
1335 paddr
= (paddr
& ~mask
) | ((paddr
& mask
) ^ (reverse
<< 2));
1336 LoadMemory (&memval
,NULL
,uncached
, AccessLength_WORD
, paddr
, vaddr
,
1338 byte
= (vaddr
& mask
) ^ (bigend
<< 2);
1339 return SIGNEXTEND (((memval
>> (8 * byte
)) & 0xffffffff), 32);
1346 /* Simulate the mips16 entry and exit pseudo-instructions. These
1347 would normally be handled by the reserved instruction exception
1348 code, but for ease of simulation we just handle them directly. */
1351 mips16_entry (SIM_DESC sd
,
1356 int aregs
, sregs
, rreg
;
1359 printf("DBG: mips16_entry: entered (insn = 0x%08X)\n",insn
);
1362 aregs
= (insn
& 0x700) >> 8;
1363 sregs
= (insn
& 0x0c0) >> 6;
1364 rreg
= (insn
& 0x020) >> 5;
1366 /* This should be checked by the caller. */
1375 /* This is the entry pseudo-instruction. */
1377 for (i
= 0; i
< aregs
; i
++)
1378 store_word (SD
, CPU
, cia
, (uword64
) (SP
+ 4 * i
), GPR
[i
+ 4]);
1386 store_word (SD
, CPU
, cia
, (uword64
) tsp
, RA
);
1389 for (i
= 0; i
< sregs
; i
++)
1392 store_word (SD
, CPU
, cia
, (uword64
) tsp
, GPR
[16 + i
]);
1400 /* This is the exit pseudo-instruction. */
1407 RA
= load_word (SD
, CPU
, cia
, (uword64
) tsp
);
1410 for (i
= 0; i
< sregs
; i
++)
1413 GPR
[i
+ 16] = load_word (SD
, CPU
, cia
, (uword64
) tsp
);
1418 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
1422 FGR
[0] = WORD64LO (GPR
[4]);
1423 FPR_STATE
[0] = fmt_uninterpreted
;
1425 else if (aregs
== 6)
1427 FGR
[0] = WORD64LO (GPR
[5]);
1428 FGR
[1] = WORD64LO (GPR
[4]);
1429 FPR_STATE
[0] = fmt_uninterpreted
;
1430 FPR_STATE
[1] = fmt_uninterpreted
;
1439 /*-- trace support ----------------------------------------------------------*/
1441 /* The TRACE support is provided (if required) in the memory accessing
1442 routines. Since we are also providing the architecture specific
1443 features, the architecture simulation code can also deal with
1444 notifying the TRACE world of cache flushes, etc. Similarly we do
1445 not need to provide profiling support in the simulator engine,
1446 since we can sample in the instruction fetch control loop. By
1447 defining the TRACE manifest, we add tracing as a run-time
1451 /* Tracing by default produces "din" format (as required by
1452 dineroIII). Each line of such a trace file *MUST* have a din label
1453 and address field. The rest of the line is ignored, so comments can
1454 be included if desired. The first field is the label which must be
1455 one of the following values:
1460 3 escape record (treated as unknown access type)
1461 4 escape record (causes cache flush)
1463 The address field is a 32bit (lower-case) hexadecimal address
1464 value. The address should *NOT* be preceded by "0x".
1466 The size of the memory transfer is not important when dealing with
1467 cache lines (as long as no more than a cache line can be
1468 transferred in a single operation :-), however more information
1469 could be given following the dineroIII requirement to allow more
1470 complete memory and cache simulators to provide better
1471 results. i.e. the University of Pisa has a cache simulator that can
1472 also take bus size and speed as (variable) inputs to calculate
1473 complete system performance (a much more useful ability when trying
1474 to construct an end product, rather than a processor). They
1475 currently have an ARM version of their tool called ChARM. */
1479 dotrace (SIM_DESC sd
,
1487 if (STATE
& simTRACE
) {
1489 fprintf(tracefh
,"%d %s ; width %d ; ",
1493 va_start(ap
,comment
);
1494 vfprintf(tracefh
,comment
,ap
);
1496 fprintf(tracefh
,"\n");
1498 /* NOTE: Since the "din" format will only accept 32bit addresses, and
1499 we may be generating 64bit ones, we should put the hi-32bits of the
1500 address into the comment field. */
1502 /* TODO: Provide a buffer for the trace lines. We can then avoid
1503 performing writes until the buffer is filled, or the file is
1506 /* NOTE: We could consider adding a comment field to the "din" file
1507 produced using type 3 markers (unknown access). This would then
1508 allow information about the program that the "din" is for, and
1509 the MIPs world that was being simulated, to be placed into the
1516 /*---------------------------------------------------------------------------*/
1517 /*-- simulator engine -------------------------------------------------------*/
1518 /*---------------------------------------------------------------------------*/
1521 ColdReset (SIM_DESC sd
)
1524 for (cpu_nr
= 0; cpu_nr
< sim_engine_nr_cpus (sd
); cpu_nr
++)
1526 sim_cpu
*cpu
= STATE_CPU (sd
, cpu_nr
);
1527 /* RESET: Fixed PC address: */
1528 PC
= UNSIGNED64 (0xFFFFFFFFBFC00000);
1529 /* The reset vector address is in the unmapped, uncached memory space. */
1531 SR
&= ~(status_SR
| status_TS
| status_RP
);
1532 SR
|= (status_ERL
| status_BEV
);
1534 /* Cheat and allow access to the complete register set immediately */
1535 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
1536 && WITH_TARGET_WORD_BITSIZE
== 64)
1537 SR
|= status_FR
; /* 64bit registers */
1539 /* Ensure that any instructions with pending register updates are
1541 PENDING_INVALIDATE();
1543 /* Initialise the FPU registers to the unknown state */
1544 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
1547 for (rn
= 0; (rn
< 32); rn
++)
1548 FPR_STATE
[rn
] = fmt_uninterpreted
;
1555 ifetch16 (SIM_DESC sd
,
1560 /* Copy the action of the LW instruction */
1561 address_word reverse
= (ReverseEndian
? (LOADDRMASK
>> 2) : 0);
1562 address_word bigend
= (BigEndianCPU
? (LOADDRMASK
>> 2) : 0);
1565 unsigned16 instruction
;
1568 AddressTranslation (vaddr
, isINSTRUCTION
, isLOAD
, &paddr
, &cca
, isTARGET
, isREAL
);
1569 paddr
= ((paddr
& ~LOADDRMASK
) | ((paddr
& LOADDRMASK
) ^ (reverse
<< 2)));
1570 LoadMemory (&value
, NULL
, cca
, AccessLength_WORD
, paddr
, vaddr
, isINSTRUCTION
, isREAL
);
1571 byte
= ((vaddr
& LOADDRMASK
) ^ (bigend
<< 2));
1572 instruction
= ((value
>> (8 * byte
)) & 0xFFFFFFFF);
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. */
1583 signal_exception (SIM_DESC sd
,
1591 sim_io_printf(sd
,"DBG: SignalException(%d) PC = 0x%s\n",exception
,pr_addr(cia
));
1594 /* Ensure that any active atomic read/modify/write operation will fail: */
1597 switch (exception
) {
1598 /* TODO: For testing purposes I have been ignoring TRAPs. In
1599 reality we should either simulate them, or allow the user to
1600 ignore them at run-time.
1603 sim_io_eprintf(sd
,"Ignoring instruction TRAP (PC 0x%s)\n",pr_addr(cia
));
1609 unsigned int instruction
;
1612 va_start(ap
,exception
);
1613 instruction
= va_arg(ap
,unsigned int);
1616 code
= (instruction
>> 6) & 0xFFFFF;
1618 sim_io_eprintf(sd
,"Ignoring instruction `syscall %d' (PC 0x%s)\n",
1619 code
, pr_addr(cia
));
1623 case DebugBreakPoint
:
1624 if (! (Debug
& Debug_DM
))
1630 Debug
|= Debug_DBD
; /* signaled from within in delay slot */
1631 DEPC
= cia
- 4; /* reference the branch instruction */
1635 Debug
&= ~Debug_DBD
; /* not signaled from within a delay slot */
1639 Debug
|= Debug_DM
; /* in debugging mode */
1640 Debug
|= Debug_DBp
; /* raising a DBp exception */
1642 sim_engine_restart (SD
, CPU
, NULL
, NULL_CIA
);
1646 case ReservedInstruction
:
1649 unsigned int instruction
;
1650 va_start(ap
,exception
);
1651 instruction
= va_arg(ap
,unsigned int);
1653 /* Provide simple monitor support using ReservedInstruction
1654 exceptions. The following code simulates the fixed vector
1655 entry points into the IDT monitor by causing a simulator
1656 trap, performing the monitor operation, and returning to
1657 the address held in the $ra register (standard PCS return
1658 address). This means we only need to pre-load the vector
1659 space with suitable instruction values. For systems were
1660 actual trap instructions are used, we would not need to
1661 perform this magic. */
1662 if ((instruction
& RSVD_INSTRUCTION_MASK
) == RSVD_INSTRUCTION
)
1664 sim_monitor (SD
, CPU
, cia
, ((instruction
>> RSVD_INSTRUCTION_ARG_SHIFT
) & RSVD_INSTRUCTION_ARG_MASK
) );
1665 /* NOTE: This assumes that a branch-and-link style
1666 instruction was used to enter the vector (which is the
1667 case with the current IDT monitor). */
1668 sim_engine_restart (SD
, CPU
, NULL
, RA
);
1670 /* Look for the mips16 entry and exit instructions, and
1671 simulate a handler for them. */
1672 else if ((cia
& 1) != 0
1673 && (instruction
& 0xf81f) == 0xe809
1674 && (instruction
& 0x0c0) != 0x0c0)
1676 mips16_entry (SD
, CPU
, cia
, instruction
);
1677 sim_engine_restart (sd
, NULL
, NULL
, NULL_CIA
);
1679 /* else fall through to normal exception processing */
1680 sim_io_eprintf(sd
,"ReservedInstruction 0x%08X at PC = 0x%s\n",instruction
,pr_addr(cia
));
1685 sim_io_printf(sd
,"DBG: SignalException(%d) PC = 0x%s\n",exception
,pr_addr(cia
));
1687 /* Keep a copy of the current A0 in-case this is the program exit
1691 unsigned int instruction
;
1692 va_start(ap
,exception
);
1693 instruction
= va_arg(ap
,unsigned int);
1695 /* Check for our special terminating BREAK: */
1696 if ((instruction
& 0x03FFFFC0) == 0x03ff0000) {
1697 sim_engine_halt (SD
, CPU
, NULL
, cia
,
1698 sim_exited
, (unsigned int)(A0
& 0xFFFFFFFF));
1701 if (STATE
& simDELAYSLOT
)
1702 PC
= cia
- 4; /* reference the branch instruction */
1705 sim_engine_halt (SD
, CPU
, NULL
, cia
,
1706 sim_stopped
, SIM_SIGTRAP
);
1709 /* Store exception code into current exception id variable (used
1712 /* TODO: If not simulating exceptions then stop the simulator
1713 execution. At the moment we always stop the simulation. */
1715 /* See figure 5-17 for an outline of the code below */
1716 if (! (SR
& status_EXL
))
1718 CAUSE
= (exception
<< 2);
1719 if (STATE
& simDELAYSLOT
)
1721 STATE
&= ~simDELAYSLOT
;
1723 EPC
= (cia
- 4); /* reference the branch instruction */
1727 /* FIXME: TLB et.al. */
1732 CAUSE
= (exception
<< 2);
1736 /* Store exception code into current exception id variable (used
1738 if (SR
& status_BEV
)
1739 PC
= (signed)0xBFC00200 + 0x180;
1741 PC
= (signed)0x80000000 + 0x180;
1743 switch ((CAUSE
>> 2) & 0x1F)
1746 /* Interrupts arrive during event processing, no need to
1750 case TLBModification
:
1755 case InstructionFetch
:
1757 /* The following is so that the simulator will continue from the
1758 exception address on breakpoint operations. */
1760 sim_engine_halt (SD
, CPU
, NULL
, NULL_CIA
,
1761 sim_stopped
, SIM_SIGBUS
);
1763 case ReservedInstruction
:
1764 case CoProcessorUnusable
:
1766 sim_engine_halt (SD
, CPU
, NULL
, NULL_CIA
,
1767 sim_stopped
, SIM_SIGILL
);
1769 case IntegerOverflow
:
1771 sim_engine_halt (SD
, CPU
, NULL
, NULL_CIA
,
1772 sim_stopped
, SIM_SIGFPE
);
1778 sim_engine_halt (SD
, CPU
, NULL
, NULL_CIA
,
1779 sim_stopped
, SIM_SIGTRAP
);
1783 sim_engine_abort (SD
, CPU
, NULL_CIA
,
1784 "FATAL: Should not encounter a breakpoint\n");
1786 default : /* Unknown internal exception */
1788 sim_engine_halt (SD
, CPU
, NULL
, NULL_CIA
,
1789 sim_stopped
, SIM_SIGABRT
);
1793 case SimulatorFault
:
1797 va_start(ap
,exception
);
1798 msg
= va_arg(ap
,char *);
1800 sim_engine_abort (SD
, CPU
, NULL_CIA
,
1801 "FATAL: Simulator error \"%s\"\n",msg
);
1808 #if defined(WARN_RESULT)
1809 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
1810 /* This function indicates that the result of the operation is
1811 undefined. However, this should not affect the instruction
1812 stream. All that is meant to happen is that the destination
1813 register is set to an undefined result. To keep the simulator
1814 simple, we just don't bother updating the destination register, so
1815 the overall result will be undefined. If desired we can stop the
1816 simulator by raising a pseudo-exception. */
1817 #define UndefinedResult() undefined_result (sd,cia)
1819 undefined_result(sd
,cia
)
1823 sim_io_eprintf(sd
,"UndefinedResult: PC = 0x%s\n",pr_addr(cia
));
1824 #if 0 /* Disabled for the moment, since it actually happens a lot at the moment. */
1829 #endif /* WARN_RESULT */
1831 /*-- FPU support routines ---------------------------------------------------*/
1833 /* Numbers are held in normalized form. The SINGLE and DOUBLE binary
1834 formats conform to ANSI/IEEE Std 754-1985. */
1835 /* SINGLE precision floating:
1836 * seeeeeeeefffffffffffffffffffffff
1838 * e = 8bits = exponent
1839 * f = 23bits = fraction
1841 /* SINGLE precision fixed:
1842 * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
1844 * i = 31bits = integer
1846 /* DOUBLE precision floating:
1847 * seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
1849 * e = 11bits = exponent
1850 * f = 52bits = fraction
1852 /* DOUBLE precision fixed:
1853 * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
1855 * i = 63bits = integer
1858 /* Extract sign-bit: */
1859 #define FP_S_s(v) (((v) & ((unsigned)1 << 31)) ? 1 : 0)
1860 #define FP_D_s(v) (((v) & ((uword64)1 << 63)) ? 1 : 0)
1861 /* Extract biased exponent: */
1862 #define FP_S_be(v) (((v) >> 23) & 0xFF)
1863 #define FP_D_be(v) (((v) >> 52) & 0x7FF)
1864 /* Extract unbiased Exponent: */
1865 #define FP_S_e(v) (FP_S_be(v) - 0x7F)
1866 #define FP_D_e(v) (FP_D_be(v) - 0x3FF)
1867 /* Extract complete fraction field: */
1868 #define FP_S_f(v) ((v) & ~((unsigned)0x1FF << 23))
1869 #define FP_D_f(v) ((v) & ~((uword64)0xFFF << 52))
1870 /* Extract numbered fraction bit: */
1871 #define FP_S_fb(b,v) (((v) & (1 << (23 - (b)))) ? 1 : 0)
1872 #define FP_D_fb(b,v) (((v) & (1 << (52 - (b)))) ? 1 : 0)
1874 /* Explicit QNaN values used when value required: */
1875 #define FPQNaN_SINGLE (0x7FBFFFFF)
1876 #define FPQNaN_WORD (0x7FFFFFFF)
1877 #define FPQNaN_DOUBLE (((uword64)0x7FF7FFFF << 32) | 0xFFFFFFFF)
1878 #define FPQNaN_LONG (((uword64)0x7FFFFFFF << 32) | 0xFFFFFFFF)
1880 /* Explicit Infinity values used when required: */
1881 #define FPINF_SINGLE (0x7F800000)
1882 #define FPINF_DOUBLE (((uword64)0x7FF00000 << 32) | 0x00000000)
1884 #if 1 /* def DEBUG */
1885 #define RMMODE(v) (((v) == FP_RM_NEAREST) ? "Round" : (((v) == FP_RM_TOZERO) ? "Trunc" : (((v) == FP_RM_TOPINF) ? "Ceil" : "Floor")))
1886 #define DOFMT(v) (((v) == fmt_single) ? "single" : (((v) == fmt_double) ? "double" : (((v) == fmt_word) ? "word" : (((v) == fmt_long) ? "long" : (((v) == fmt_unknown) ? "<unknown>" : (((v) == fmt_uninterpreted) ? "<uninterpreted>" : "<format error>"))))))
1890 value_fpr (SIM_DESC sd
,
1899 /* Treat unused register values, as fixed-point 64bit values: */
1900 if ((fmt
== fmt_uninterpreted
) || (fmt
== fmt_unknown
))
1902 /* If request to read data as "uninterpreted", then use the current
1904 fmt
= FPR_STATE
[fpr
];
1909 /* For values not yet accessed, set to the desired format: */
1910 if (FPR_STATE
[fpr
] == fmt_uninterpreted
) {
1911 FPR_STATE
[fpr
] = fmt
;
1913 printf("DBG: Register %d was fmt_uninterpreted. Now %s\n",fpr
,DOFMT(fmt
));
1916 if (fmt
!= FPR_STATE
[fpr
]) {
1917 sim_io_eprintf(sd
,"FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",fpr
,DOFMT(FPR_STATE
[fpr
]),DOFMT(fmt
),pr_addr(cia
));
1918 FPR_STATE
[fpr
] = fmt_unknown
;
1921 if (FPR_STATE
[fpr
] == fmt_unknown
) {
1922 /* Set QNaN value: */
1925 value
= FPQNaN_SINGLE
;
1929 value
= FPQNaN_DOUBLE
;
1933 value
= FPQNaN_WORD
;
1937 value
= FPQNaN_LONG
;
1944 } else if (SizeFGR() == 64) {
1948 value
= (FGR
[fpr
] & 0xFFFFFFFF);
1951 case fmt_uninterpreted
:
1965 value
= (FGR
[fpr
] & 0xFFFFFFFF);
1968 case fmt_uninterpreted
:
1971 if ((fpr
& 1) == 0) { /* even registers only */
1972 value
= ((((uword64
)FGR
[fpr
+1]) << 32) | (FGR
[fpr
] & 0xFFFFFFFF));
1974 SignalException(ReservedInstruction
,0);
1985 SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR()");
1988 printf("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d\n",fpr
,DOFMT(fmt
),pr_addr(value
),pr_addr(cia
),SizeFGR());
1995 store_fpr (SIM_DESC sd
,
2005 printf("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d\n",fpr
,DOFMT(fmt
),pr_addr(value
),pr_addr(cia
),SizeFGR());
2008 if (SizeFGR() == 64) {
2010 case fmt_uninterpreted_32
:
2011 fmt
= fmt_uninterpreted
;
2014 FGR
[fpr
] = (((uword64
)0xDEADC0DE << 32) | (value
& 0xFFFFFFFF));
2015 FPR_STATE
[fpr
] = fmt
;
2018 case fmt_uninterpreted_64
:
2019 fmt
= fmt_uninterpreted
;
2020 case fmt_uninterpreted
:
2024 FPR_STATE
[fpr
] = fmt
;
2028 FPR_STATE
[fpr
] = fmt_unknown
;
2034 case fmt_uninterpreted_32
:
2035 fmt
= fmt_uninterpreted
;
2038 FGR
[fpr
] = (value
& 0xFFFFFFFF);
2039 FPR_STATE
[fpr
] = fmt
;
2042 case fmt_uninterpreted_64
:
2043 fmt
= fmt_uninterpreted
;
2044 case fmt_uninterpreted
:
2047 if ((fpr
& 1) == 0) { /* even register number only */
2048 FGR
[fpr
+1] = (value
>> 32);
2049 FGR
[fpr
] = (value
& 0xFFFFFFFF);
2050 FPR_STATE
[fpr
+ 1] = fmt
;
2051 FPR_STATE
[fpr
] = fmt
;
2053 FPR_STATE
[fpr
] = fmt_unknown
;
2054 FPR_STATE
[fpr
+ 1] = fmt_unknown
;
2055 SignalException(ReservedInstruction
,0);
2060 FPR_STATE
[fpr
] = fmt_unknown
;
2065 #if defined(WARN_RESULT)
2068 #endif /* WARN_RESULT */
2071 SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR()");
2074 printf("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",fpr
,pr_addr(FGR
[fpr
]),DOFMT(fmt
));
2091 sim_fpu_32to (&wop
, op
);
2092 boolean
= sim_fpu_is_nan (&wop
);
2099 sim_fpu_64to (&wop
, op
);
2100 boolean
= sim_fpu_is_nan (&wop
);
2104 fprintf (stderr
, "Bad switch\n");
2109 printf("DBG: NaN: returning %d for 0x%s (format = %s)\n",boolean
,pr_addr(op
),DOFMT(fmt
));
2123 printf("DBG: Infinity: format %s 0x%s\n",DOFMT(fmt
),pr_addr(op
));
2130 sim_fpu_32to (&wop
, op
);
2131 boolean
= sim_fpu_is_infinity (&wop
);
2137 sim_fpu_64to (&wop
, op
);
2138 boolean
= sim_fpu_is_infinity (&wop
);
2142 printf("DBG: TODO: unrecognised format (%s) for Infinity check\n",DOFMT(fmt
));
2147 printf("DBG: Infinity: returning %d for 0x%s (format = %s)\n",boolean
,pr_addr(op
),DOFMT(fmt
));
2161 /* Argument checking already performed by the FPCOMPARE code */
2164 printf("DBG: Less: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2167 /* The format type should already have been checked: */
2173 sim_fpu_32to (&wop1
, op1
);
2174 sim_fpu_32to (&wop2
, op2
);
2175 boolean
= sim_fpu_is_lt (&wop1
, &wop2
);
2182 sim_fpu_64to (&wop1
, op1
);
2183 sim_fpu_64to (&wop2
, op2
);
2184 boolean
= sim_fpu_is_lt (&wop1
, &wop2
);
2188 fprintf (stderr
, "Bad switch\n");
2193 printf("DBG: Less: returning %d (format = %s)\n",boolean
,DOFMT(fmt
));
2207 /* Argument checking already performed by the FPCOMPARE code */
2210 printf("DBG: Equal: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2213 /* The format type should already have been checked: */
2219 sim_fpu_32to (&wop1
, op1
);
2220 sim_fpu_32to (&wop2
, op2
);
2221 boolean
= sim_fpu_is_eq (&wop1
, &wop2
);
2228 sim_fpu_64to (&wop1
, op1
);
2229 sim_fpu_64to (&wop2
, op2
);
2230 boolean
= sim_fpu_is_eq (&wop1
, &wop2
);
2234 fprintf (stderr
, "Bad switch\n");
2239 printf("DBG: Equal: returning %d (format = %s)\n",boolean
,DOFMT(fmt
));
2246 AbsoluteValue(op
,fmt
)
2253 printf("DBG: AbsoluteValue: %s: op = 0x%s\n",DOFMT(fmt
),pr_addr(op
));
2256 /* The format type should already have been checked: */
2262 sim_fpu_32to (&wop
, op
);
2263 sim_fpu_abs (&wop
, &wop
);
2264 sim_fpu_to32 (&ans
, &wop
);
2272 sim_fpu_64to (&wop
, op
);
2273 sim_fpu_abs (&wop
, &wop
);
2274 sim_fpu_to64 (&ans
, &wop
);
2279 fprintf (stderr
, "Bad switch\n");
2294 printf("DBG: Negate: %s: op = 0x%s\n",DOFMT(fmt
),pr_addr(op
));
2297 /* The format type should already have been checked: */
2303 sim_fpu_32to (&wop
, op
);
2304 sim_fpu_neg (&wop
, &wop
);
2305 sim_fpu_to32 (&ans
, &wop
);
2313 sim_fpu_64to (&wop
, op
);
2314 sim_fpu_neg (&wop
, &wop
);
2315 sim_fpu_to64 (&ans
, &wop
);
2320 fprintf (stderr
, "Bad switch\n");
2336 printf("DBG: Add: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2339 /* The registers must specify FPRs valid for operands of type
2340 "fmt". If they are not valid, the result is undefined. */
2342 /* The format type should already have been checked: */
2350 sim_fpu_32to (&wop1
, op1
);
2351 sim_fpu_32to (&wop2
, op2
);
2352 sim_fpu_add (&ans
, &wop1
, &wop2
);
2353 sim_fpu_to32 (&res
, &ans
);
2363 sim_fpu_64to (&wop1
, op1
);
2364 sim_fpu_64to (&wop2
, op2
);
2365 sim_fpu_add (&ans
, &wop1
, &wop2
);
2366 sim_fpu_to64 (&res
, &ans
);
2371 fprintf (stderr
, "Bad switch\n");
2376 printf("DBG: Add: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2391 printf("DBG: Sub: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2394 /* The registers must specify FPRs valid for operands of type
2395 "fmt". If they are not valid, the result is undefined. */
2397 /* The format type should already have been checked: */
2405 sim_fpu_32to (&wop1
, op1
);
2406 sim_fpu_32to (&wop2
, op2
);
2407 sim_fpu_sub (&ans
, &wop1
, &wop2
);
2408 sim_fpu_to32 (&res
, &ans
);
2418 sim_fpu_64to (&wop1
, op1
);
2419 sim_fpu_64to (&wop2
, op2
);
2420 sim_fpu_sub (&ans
, &wop1
, &wop2
);
2421 sim_fpu_to64 (&res
, &ans
);
2426 fprintf (stderr
, "Bad switch\n");
2431 printf("DBG: Sub: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2438 Multiply(op1
,op2
,fmt
)
2446 printf("DBG: Multiply: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2449 /* The registers must specify FPRs valid for operands of type
2450 "fmt". If they are not valid, the result is undefined. */
2452 /* The format type should already have been checked: */
2460 sim_fpu_32to (&wop1
, op1
);
2461 sim_fpu_32to (&wop2
, op2
);
2462 sim_fpu_mul (&ans
, &wop1
, &wop2
);
2463 sim_fpu_to32 (&res
, &ans
);
2473 sim_fpu_64to (&wop1
, op1
);
2474 sim_fpu_64to (&wop2
, op2
);
2475 sim_fpu_mul (&ans
, &wop1
, &wop2
);
2476 sim_fpu_to64 (&res
, &ans
);
2481 fprintf (stderr
, "Bad switch\n");
2486 printf("DBG: Multiply: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2501 printf("DBG: Divide: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2504 /* The registers must specify FPRs valid for operands of type
2505 "fmt". If they are not valid, the result is undefined. */
2507 /* The format type should already have been checked: */
2515 sim_fpu_32to (&wop1
, op1
);
2516 sim_fpu_32to (&wop2
, op2
);
2517 sim_fpu_div (&ans
, &wop1
, &wop2
);
2518 sim_fpu_to32 (&res
, &ans
);
2528 sim_fpu_64to (&wop1
, op1
);
2529 sim_fpu_64to (&wop2
, op2
);
2530 sim_fpu_div (&ans
, &wop1
, &wop2
);
2531 sim_fpu_to64 (&res
, &ans
);
2536 fprintf (stderr
, "Bad switch\n");
2541 printf("DBG: Divide: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2555 printf("DBG: Recip: %s: op = 0x%s\n",DOFMT(fmt
),pr_addr(op
));
2558 /* The registers must specify FPRs valid for operands of type
2559 "fmt". If they are not valid, the result is undefined. */
2561 /* The format type should already have been checked: */
2568 sim_fpu_32to (&wop
, op
);
2569 sim_fpu_inv (&ans
, &wop
);
2570 sim_fpu_to32 (&res
, &ans
);
2579 sim_fpu_64to (&wop
, op
);
2580 sim_fpu_inv (&ans
, &wop
);
2581 sim_fpu_to64 (&res
, &ans
);
2586 fprintf (stderr
, "Bad switch\n");
2591 printf("DBG: Recip: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2605 printf("DBG: SquareRoot: %s: op = 0x%s\n",DOFMT(fmt
),pr_addr(op
));
2608 /* The registers must specify FPRs valid for operands of type
2609 "fmt". If they are not valid, the result is undefined. */
2611 /* The format type should already have been checked: */
2618 sim_fpu_32to (&wop
, op
);
2619 sim_fpu_sqrt (&ans
, &wop
);
2620 sim_fpu_to32 (&res
, &ans
);
2629 sim_fpu_64to (&wop
, op
);
2630 sim_fpu_sqrt (&ans
, &wop
);
2631 sim_fpu_to64 (&res
, &ans
);
2636 fprintf (stderr
, "Bad switch\n");
2641 printf("DBG: SquareRoot: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2657 printf("DBG: Max: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2660 /* The registers must specify FPRs valid for operands of type
2661 "fmt". If they are not valid, the result is undefined. */
2663 /* The format type should already have been checked: */
2670 sim_fpu_32to (&wop1
, op1
);
2671 sim_fpu_32to (&wop2
, op2
);
2672 cmp
= sim_fpu_cmp (&wop1
, &wop2
);
2679 sim_fpu_64to (&wop1
, op1
);
2680 sim_fpu_64to (&wop2
, op2
);
2681 cmp
= sim_fpu_cmp (&wop1
, &wop2
);
2685 fprintf (stderr
, "Bad switch\n");
2691 case SIM_FPU_IS_SNAN
:
2692 case SIM_FPU_IS_QNAN
:
2694 case SIM_FPU_IS_NINF
:
2695 case SIM_FPU_IS_NNUMBER
:
2696 case SIM_FPU_IS_NDENORM
:
2697 case SIM_FPU_IS_NZERO
:
2698 result
= op2
; /* op1 - op2 < 0 */
2699 case SIM_FPU_IS_PINF
:
2700 case SIM_FPU_IS_PNUMBER
:
2701 case SIM_FPU_IS_PDENORM
:
2702 case SIM_FPU_IS_PZERO
:
2703 result
= op1
; /* op1 - op2 > 0 */
2705 fprintf (stderr
, "Bad switch\n");
2710 printf("DBG: Max: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2727 printf("DBG: Min: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt
),pr_addr(op1
),pr_addr(op2
));
2730 /* The registers must specify FPRs valid for operands of type
2731 "fmt". If they are not valid, the result is undefined. */
2733 /* The format type should already have been checked: */
2740 sim_fpu_32to (&wop1
, op1
);
2741 sim_fpu_32to (&wop2
, op2
);
2742 cmp
= sim_fpu_cmp (&wop1
, &wop2
);
2749 sim_fpu_64to (&wop1
, op1
);
2750 sim_fpu_64to (&wop2
, op2
);
2751 cmp
= sim_fpu_cmp (&wop1
, &wop2
);
2755 fprintf (stderr
, "Bad switch\n");
2761 case SIM_FPU_IS_SNAN
:
2762 case SIM_FPU_IS_QNAN
:
2764 case SIM_FPU_IS_NINF
:
2765 case SIM_FPU_IS_NNUMBER
:
2766 case SIM_FPU_IS_NDENORM
:
2767 case SIM_FPU_IS_NZERO
:
2768 result
= op1
; /* op1 - op2 < 0 */
2769 case SIM_FPU_IS_PINF
:
2770 case SIM_FPU_IS_PNUMBER
:
2771 case SIM_FPU_IS_PDENORM
:
2772 case SIM_FPU_IS_PZERO
:
2773 result
= op2
; /* op1 - op2 > 0 */
2775 fprintf (stderr
, "Bad switch\n");
2780 printf("DBG: Min: returning 0x%s (format = %s)\n",pr_addr(result
),DOFMT(fmt
));
2788 convert (SIM_DESC sd
,
2797 sim_fpu_round round
;
2798 unsigned32 result32
;
2799 unsigned64 result64
;
2802 printf("DBG: Convert: mode %s : op 0x%s : from %s : to %s : (PC = 0x%s)\n",RMMODE(rm
),pr_addr(op
),DOFMT(from
),DOFMT(to
),pr_addr(IPC
));
2808 /* Round result to nearest representable value. When two
2809 representable values are equally near, round to the value
2810 that has a least significant bit of zero (i.e. is even). */
2811 round
= sim_fpu_round_near
;
2814 /* Round result to the value closest to, and not greater in
2815 magnitude than, the result. */
2816 round
= sim_fpu_round_zero
;
2819 /* Round result to the value closest to, and not less than,
2821 round
= sim_fpu_round_up
;
2825 /* Round result to the value closest to, and not greater than,
2827 round
= sim_fpu_round_down
;
2831 fprintf (stderr
, "Bad switch\n");
2835 /* Convert the input to sim_fpu internal format */
2839 sim_fpu_64to (&wop
, op
);
2842 sim_fpu_32to (&wop
, op
);
2845 sim_fpu_i32to (&wop
, op
, round
);
2848 sim_fpu_i64to (&wop
, op
, round
);
2851 fprintf (stderr
, "Bad switch\n");
2855 /* Convert sim_fpu format into the output */
2856 /* The value WOP is converted to the destination format, rounding
2857 using mode RM. When the destination is a fixed-point format, then
2858 a source value of Infinity, NaN or one which would round to an
2859 integer outside the fixed point range then an IEEE Invalid
2860 Operation condition is raised. */
2864 sim_fpu_round_32 (&wop
, round
, 0);
2865 sim_fpu_to32 (&result32
, &wop
);
2866 result64
= result32
;
2869 sim_fpu_round_64 (&wop
, round
, 0);
2870 sim_fpu_to64 (&result64
, &wop
);
2873 sim_fpu_to32i (&result32
, &wop
, round
);
2874 result64
= result32
;
2877 sim_fpu_to64i (&result64
, &wop
, round
);
2881 fprintf (stderr
, "Bad switch\n");
2886 printf("DBG: Convert: returning 0x%s (to format = %s)\n",pr_addr(result64
),DOFMT(to
));
2893 /*-- co-processor support routines ------------------------------------------*/
2896 CoProcPresent(coproc_number
)
2897 unsigned int coproc_number
;
2899 /* Return TRUE if simulator provides a model for the given co-processor number */
2904 cop_lw (SIM_DESC sd
,
2909 unsigned int memword
)
2914 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
2917 printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%s\n",memword
,pr_addr(memword
));
2919 StoreFPR(coproc_reg
,fmt_word
,(uword64
)memword
);
2920 FPR_STATE
[coproc_reg
] = fmt_uninterpreted
;
2925 #if 0 /* this should be controlled by a configuration option */
2926 sim_io_printf(sd
,"COP_LW(%d,%d,0x%08X) at PC = 0x%s : TODO (architecture specific)\n",coproc_num
,coproc_reg
,memword
,pr_addr(cia
));
2935 cop_ld (SIM_DESC sd
,
2942 switch (coproc_num
) {
2944 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
2946 StoreFPR(coproc_reg
,fmt_uninterpreted
,memword
);
2951 #if 0 /* this message should be controlled by a configuration option */
2952 sim_io_printf(sd
,"COP_LD(%d,%d,0x%s) at PC = 0x%s : TODO (architecture specific)\n",coproc_num
,coproc_reg
,pr_addr(memword
),pr_addr(cia
));
2961 /* start-sanitize-sky */
2964 cop_lq (SIM_DESC sd
,
2969 unsigned128 memword
)
2980 memcpy(& xyzw
, & memword
, sizeof(xyzw
));
2981 xyzw
= H2T_16(xyzw
);
2982 /* one word at a time, argh! */
2983 write_vu_vec_reg(&(vu0_device
.regs
), coproc_reg
, 0, A4_16(& xyzw
, 3));
2984 write_vu_vec_reg(&(vu0_device
.regs
), coproc_reg
, 1, A4_16(& xyzw
, 2));
2985 write_vu_vec_reg(&(vu0_device
.regs
), coproc_reg
, 2, A4_16(& xyzw
, 1));
2986 write_vu_vec_reg(&(vu0_device
.regs
), coproc_reg
, 3, A4_16(& xyzw
, 0));
2991 sim_io_printf(sd
,"COP_LQ(%d,%d,??) at PC = 0x%s : TODO (architecture specific)\n",
2992 coproc_num
,coproc_reg
,pr_addr(cia
));
2998 #endif /* TARGET_SKY */
2999 /* end-sanitize-sky */
3003 cop_sw (SIM_DESC sd
,
3009 unsigned int value
= 0;
3014 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
3017 hold
= FPR_STATE
[coproc_reg
];
3018 FPR_STATE
[coproc_reg
] = fmt_word
;
3019 value
= (unsigned int)ValueFPR(coproc_reg
,fmt_uninterpreted
);
3020 FPR_STATE
[coproc_reg
] = hold
;
3025 #if 0 /* should be controlled by configuration option */
3026 sim_io_printf(sd
,"COP_SW(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num
,coproc_reg
,pr_addr(cia
));
3035 cop_sd (SIM_DESC sd
,
3045 if (CURRENT_FLOATING_POINT
== HARD_FLOATING_POINT
)
3047 value
= ValueFPR(coproc_reg
,fmt_uninterpreted
);
3052 #if 0 /* should be controlled by configuration option */
3053 sim_io_printf(sd
,"COP_SD(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num
,coproc_reg
,pr_addr(cia
));
3062 /* start-sanitize-sky */
3065 cop_sq (SIM_DESC sd
,
3071 unsigned128 value
= U16_8(0, 0);
3081 /* one word at a time, argh! */
3082 read_vu_vec_reg(&(vu0_device
.regs
), coproc_reg
, 0, A4_16(& xyzw
, 3));
3083 read_vu_vec_reg(&(vu0_device
.regs
), coproc_reg
, 1, A4_16(& xyzw
, 2));
3084 read_vu_vec_reg(&(vu0_device
.regs
), coproc_reg
, 2, A4_16(& xyzw
, 1));
3085 read_vu_vec_reg(&(vu0_device
.regs
), coproc_reg
, 3, A4_16(& xyzw
, 0));
3086 xyzw
= T2H_16(xyzw
);
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
));
3099 #endif /* TARGET_SKY */
3100 /* end-sanitize-sky */
3104 decode_coproc (SIM_DESC sd
,
3107 unsigned int instruction
)
3109 int coprocnum
= ((instruction
>> 26) & 3);
3113 case 0: /* standard CPU control and cache registers */
3115 int code
= ((instruction
>> 21) & 0x1F);
3116 /* R4000 Users Manual (second edition) lists the following CP0
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)
3129 if (((code
== 0x00) || (code
== 0x04)) && ((instruction
& 0x7FF) == 0))
3131 int rt
= ((instruction
>> 16) & 0x1F);
3132 int rd
= ((instruction
>> 11) & 0x1F);
3134 switch (rd
) /* NOTEs: Standard CP0 registers */
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 */
3154 /* 13 = Cause R4000 VR4100 VR4300 */
3161 /* 14 = EPC R4000 VR4100 VR4300 */
3162 /* 15 = PRId R4000 VR4100 VR4300 */
3163 #ifdef SUBTARGET_R3900
3172 /* 16 = Config R4000 VR4100 VR4300 */
3175 GPR
[rt
] = C0_CONFIG
;
3177 C0_CONFIG
= GPR
[rt
];
3180 #ifdef SUBTARGET_R3900
3189 /* 17 = LLAddr R4000 VR4100 VR4300 */
3191 /* 18 = WatchLo R4000 VR4100 VR4300 */
3192 /* 19 = WatchHi R4000 VR4100 VR4300 */
3193 /* 20 = XContext R4000 VR4100 VR4300 */
3194 /* 26 = PErr or ECC R4000 VR4100 VR4300 */
3195 /* 27 = CacheErr R4000 VR4100 */
3196 /* 28 = TagLo R4000 VR4100 VR4300 */
3197 /* 29 = TagHi R4000 VR4100 VR4300 */
3198 /* 30 = ErrorEPC R4000 VR4100 VR4300 */
3199 GPR
[rt
] = 0xDEADC0DE; /* CPR[0,rd] */
3200 /* CPR[0,rd] = GPR[rt]; */
3203 sim_io_printf(sd
,"Warning: MFC0 %d,%d ignored (architecture specific)\n",rt
,rd
);
3205 sim_io_printf(sd
,"Warning: MTC0 %d,%d ignored (architecture specific)\n",rt
,rd
);
3208 else if (code
== 0x10 && (instruction
& 0x3f) == 0x18)
3211 if (SR
& status_ERL
)
3213 /* Oops, not yet available */
3214 sim_io_printf(sd
,"Warning: ERET when SR[ERL] set not handled yet");
3224 else if (code
== 0x10 && (instruction
& 0x3f) == 0x10)
3228 else if (code
== 0x10 && (instruction
& 0x3f) == 0x1F)
3236 sim_io_eprintf(sd
,"Unrecognised COP0 instruction 0x%08X at PC = 0x%s : No handler present\n",instruction
,pr_addr(cia
));
3237 /* TODO: When executing an ERET or RFE instruction we should
3238 clear LLBIT, to ensure that any out-standing atomic
3239 read/modify/write sequence fails. */
3243 case 2: /* co-processor 2 */
3247 /* start-sanitize-sky */
3249 /* On the R5900, this refers to a "VU" vector co-processor. */
3251 int i_25_21
= (instruction
>> 21) & 0x1f;
3252 int i_20_16
= (instruction
>> 16) & 0x1f;
3253 int i_20_6
= (instruction
>> 6) & 0x7fff;
3254 int i_15_11
= (instruction
>> 11) & 0x1f;
3255 int i_15_0
= instruction
& 0xffff;
3256 int i_10_1
= (instruction
>> 1) & 0x3ff;
3257 int i_10_0
= instruction
& 0x7ff;
3258 int i_10_6
= (instruction
>> 6) & 0x1f;
3259 int i_5_0
= instruction
& 0x03f;
3260 int interlock
= instruction
& 0x01;
3261 /* setup for semantic.c-like actions below */
3262 typedef unsigned_4 instruction_word
;
3265 sim_cpu
* CPU_
= cpu
;
3269 /* test COP2 usability */
3270 if(! (SR
& status_CU2
))
3272 SignalException(CoProcessorUnusable
,instruction
);
3276 /* classify & execute basic COP2 instructions */
3277 if(i_25_21
== 0x08 && i_20_16
== 0x00) /* BC2F */
3279 address_word offset
= EXTEND16(i_15_0
) << 2;
3280 if(! vu0_busy()) DELAY_SLOT(cia
+ 4 + offset
);
3282 else if(i_25_21
== 0x08 && i_20_16
==0x02) /* BC2FL */
3284 address_word offset
= EXTEND16(i_15_0
) << 2;
3285 if(! vu0_busy()) DELAY_SLOT(cia
+ 4 + offset
);
3286 else NULLIFY_NEXT_INSTRUCTION();
3288 else if(i_25_21
== 0x08 && i_20_16
== 0x01) /* BC2T */
3290 address_word offset
= EXTEND16(i_15_0
) << 2;
3291 if(vu0_busy()) DELAY_SLOT(cia
+ 4 + offset
);
3293 else if(i_25_21
== 0x08 && i_20_16
== 0x03) /* BC2TL */
3295 address_word offset
= EXTEND16(i_15_0
) << 2;
3296 if(vu0_busy()) DELAY_SLOT(cia
+ 4 + offset
);
3297 else NULLIFY_NEXT_INSTRUCTION();
3299 else if((i_25_21
== 0x02 && i_10_1
== 0x000) || /* CFC2 */
3300 (i_25_21
== 0x01)) /* QMFC2 */
3305 /* interlock checking */
3306 /* POLICY: never busy in macro mode */
3307 while(vu0_busy() && interlock
)
3310 /* perform VU register address */
3311 if(i_25_21
== 0x01) /* QMFC2 */
3314 /* one word at a time, argh! */
3315 read_vu_vec_reg(&(vu0_device
.regs
), id
, 0, A4_16(& xyzw
, 3));
3316 read_vu_vec_reg(&(vu0_device
.regs
), id
, 1, A4_16(& xyzw
, 2));
3317 read_vu_vec_reg(&(vu0_device
.regs
), id
, 2, A4_16(& xyzw
, 1));
3318 read_vu_vec_reg(&(vu0_device
.regs
), id
, 3, A4_16(& xyzw
, 0));
3319 xyzw
= T2H_16(xyzw
);
3320 memcpy(& GPR
[rt
], & xyzw
, sizeof(xyzw
));
3325 /* enum + int calculation, argh! */
3326 id
= VU_REG_MST
+ 16 * id
;
3327 read_vu_misc_reg(&(vu0_device
.regs
), id
, & data
);
3328 GPR
[rt
] = EXTEND32(T2H_4(data
));
3331 else if((i_25_21
== 0x06 && i_10_1
== 0x000) || /* CTC2 */
3332 (i_25_21
== 0x05)) /* QMTC2 */
3337 /* interlock checking */
3338 /* POLICY: never busy in macro mode */
3339 if(vu0_busy() && interlock
)
3341 while(! vu0_micro_interlock_released())
3345 /* perform VU register address */
3346 if(i_25_21
== 0x05) /* QMTC2 */
3349 memcpy(& xyzw
, & GPR
[rt
], sizeof(xyzw
));
3350 xyzw
= H2T_16(xyzw
);
3351 /* one word at a time, argh! */
3352 write_vu_vec_reg(&(vu0_device
.regs
), id
, 0, A4_16(& xyzw
, 3));
3353 write_vu_vec_reg(&(vu0_device
.regs
), id
, 1, A4_16(& xyzw
, 2));
3354 write_vu_vec_reg(&(vu0_device
.regs
), id
, 2, A4_16(& xyzw
, 1));
3355 write_vu_vec_reg(&(vu0_device
.regs
), id
, 3, A4_16(& xyzw
, 0));
3359 unsigned_4 data
= H2T_4(GPR
[rt
]);
3360 /* enum + int calculation, argh! */
3361 id
= VU_REG_MST
+ 16 * id
;
3362 write_vu_misc_reg(&(vu0_device
.regs
), id
, & data
);
3365 else if(i_10_0
== 0x3bf) /* VWAITQ */
3370 else if(i_5_0
== 0x38) /* VCALLMS */
3372 unsigned_4 data
= H2T_2(i_20_6
);
3377 /* write to reserved CIA register to get VU0 moving */
3378 write_vu_special_reg(& vu0_device
, VU_REG_CIA
, & data
);
3382 else if(i_5_0
== 0x39) /* VCALLMSR */
3389 read_vu_special_reg(& vu0_device
, VU_REG_CMSAR0
, & data
);
3390 /* write to reserved CIA register to get VU0 moving */
3391 write_vu_special_reg(& vu0_device
, VU_REG_CIA
, & data
);
3395 /* handle all remaining UPPER VU instructions in one block */
3396 else if((i_5_0
< 0x30) || /* VADDx .. VMINI */
3397 (i_5_0
>= 0x3c && i_10_6
< 0x0c)) /* VADDAx .. VNOP */
3399 unsigned_4 vu_upper
, vu_lower
;
3401 0x00000000 | /* bits 31 .. 25 */
3402 (instruction
& 0x01ffffff); /* bits 24 .. 0 */
3403 vu_lower
= 0x8000033c; /* NOP */
3405 /* POLICY: never busy in macro mode */
3409 vu0_macro_issue(vu_upper
, vu_lower
);
3411 /* POLICY: wait for completion of macro-instruction */
3415 /* handle all remaining LOWER VU instructions in one block */
3416 else if((i_5_0
>= 0x30 && i_5_0
<= 0x35) || /* VIADD .. VIOR */
3417 (i_5_0
>= 0x3c && i_10_6
>= 0x0c)) /* VMOVE .. VRXOR */
3418 { /* N.B.: VWAITQ already covered by prior case */
3419 unsigned_4 vu_upper
, vu_lower
;
3420 vu_upper
= 0x000002ff; /* NOP/NOP */
3422 0x10000000 | /* bits 31 .. 25 */
3423 (instruction
& 0x01ffffff); /* bits 24 .. 0 */
3425 /* POLICY: never busy in macro mode */
3429 vu0_macro_issue(vu_upper
, vu_lower
);
3431 /* POLICY: wait for completion of macro-instruction */
3435 /* ... no other COP2 instructions ... */
3438 SignalException(ReservedInstruction
, instruction
);
3442 /* cleanup for semantic.c-like actions above */
3445 #endif /* TARGET_SKY */
3446 /* end-sanitize-sky */
3450 sim_io_eprintf(sd
, "COP2 instruction 0x%08X at PC = 0x%s : No handler present\n",
3451 instruction
,pr_addr(cia
));
3456 case 1: /* should not occur (FPU co-processor) */
3457 case 3: /* should not occur (FPU co-processor) */
3458 SignalException(ReservedInstruction
,instruction
);
3466 /*-- instruction simulation -------------------------------------------------*/
3468 /* When the IGEN simulator is being built, the function below is be
3469 replaced by a generated version. However, WITH_IGEN == 2 indicates
3470 that the fubction below should be compiled but under a different
3471 name (to allow backward compatibility) */
3473 #if (WITH_IGEN != 1)
3475 void old_engine_run
PARAMS ((SIM_DESC sd
, int next_cpu_nr
, int siggnal
));
3477 old_engine_run (sd
, next_cpu_nr
, nr_cpus
, siggnal
)
3480 sim_engine_run (sd
, next_cpu_nr
, nr_cpus
, siggnal
)
3483 int next_cpu_nr
; /* ignore */
3484 int nr_cpus
; /* ignore */
3485 int siggnal
; /* ignore */
3487 sim_cpu
*cpu
= STATE_CPU (sd
, 0); /* hardwire to cpu 0 */
3488 #if !defined(FASTSIM)
3489 unsigned int pipeline_count
= 1;
3493 if (STATE_MEMORY (sd
) == NULL
) {
3494 printf("DBG: simulate() entered with no memory\n");
3499 #if 0 /* Disabled to check that everything works OK */
3500 /* The VR4300 seems to sign-extend the PC on its first
3501 access. However, this may just be because it is currently
3502 configured in 32bit mode. However... */
3503 PC
= SIGNEXTEND(PC
,32);
3506 /* main controlling loop */
3508 /* vaddr is slowly being replaced with cia - current instruction
3510 address_word cia
= (uword64
)PC
;
3511 address_word vaddr
= cia
;
3514 unsigned int instruction
; /* uword64? what's this used for? FIXME! */
3518 printf("DBG: state = 0x%08X :",state
);
3519 if (state
& simHALTEX
) printf(" simHALTEX");
3520 if (state
& simHALTIN
) printf(" simHALTIN");
3525 DSSTATE
= (STATE
& simDELAYSLOT
);
3528 sim_io_printf(sd
,"DBG: DSPC = 0x%s\n",pr_addr(DSPC
));
3531 /* Fetch the next instruction from the simulator memory: */
3532 if (AddressTranslation(cia
,isINSTRUCTION
,isLOAD
,&paddr
,&cca
,isTARGET
,isREAL
)) {
3533 if ((vaddr
& 1) == 0) {
3534 /* Copy the action of the LW instruction */
3535 unsigned int reverse
= (ReverseEndian
? (LOADDRMASK
>> 2) : 0);
3536 unsigned int bigend
= (BigEndianCPU
? (LOADDRMASK
>> 2) : 0);
3539 paddr
= ((paddr
& ~LOADDRMASK
) | ((paddr
& LOADDRMASK
) ^ (reverse
<< 2)));
3540 LoadMemory(&value
,NULL
,cca
,AccessLength_WORD
,paddr
,vaddr
,isINSTRUCTION
,isREAL
);
3541 byte
= ((vaddr
& LOADDRMASK
) ^ (bigend
<< 2));
3542 instruction
= ((value
>> (8 * byte
)) & 0xFFFFFFFF);
3544 /* Copy the action of the LH instruction */
3545 unsigned int reverse
= (ReverseEndian
? (LOADDRMASK
>> 1) : 0);
3546 unsigned int bigend
= (BigEndianCPU
? (LOADDRMASK
>> 1) : 0);
3549 paddr
= (((paddr
& ~ (uword64
) 1) & ~LOADDRMASK
)
3550 | (((paddr
& ~ (uword64
) 1) & LOADDRMASK
) ^ (reverse
<< 1)));
3551 LoadMemory(&value
,NULL
,cca
, AccessLength_HALFWORD
,
3552 paddr
& ~ (uword64
) 1,
3553 vaddr
, isINSTRUCTION
, isREAL
);
3554 byte
= (((vaddr
&~ (uword64
) 1) & LOADDRMASK
) ^ (bigend
<< 1));
3555 instruction
= ((value
>> (8 * byte
)) & 0xFFFF);
3558 fprintf(stderr
,"Cannot translate address for PC = 0x%s failed\n",pr_addr(PC
));
3563 sim_io_printf(sd
,"DBG: fetched 0x%08X from PC = 0x%s\n",instruction
,pr_addr(PC
));
3566 /* This is required by exception processing, to ensure that we can
3567 cope with exceptions in the delay slots of branches that may
3568 already have changed the PC. */
3569 if ((vaddr
& 1) == 0)
3570 PC
+= 4; /* increment ready for the next fetch */
3573 /* NOTE: If we perform a delay slot change to the PC, this
3574 increment is not requuired. However, it would make the
3575 simulator more complicated to try and avoid this small hit. */
3577 /* Currently this code provides a simple model. For more
3578 complicated models we could perform exception status checks at
3579 this point, and set the simSTOP state as required. This could
3580 also include processing any hardware interrupts raised by any
3581 I/O model attached to the simulator context.
3583 Support for "asynchronous" I/O events within the simulated world
3584 could be providing by managing a counter, and calling a I/O
3585 specific handler when a particular threshold is reached. On most
3586 architectures a decrement and check for zero operation is
3587 usually quicker than an increment and compare. However, the
3588 process of managing a known value decrement to zero, is higher
3589 than the cost of using an explicit value UINT_MAX into the
3590 future. Which system is used will depend on how complicated the
3591 I/O model is, and how much it is likely to affect the simulator
3594 If events need to be scheduled further in the future than
3595 UINT_MAX event ticks, then the I/O model should just provide its
3596 own counter, triggered from the event system. */
3598 /* MIPS pipeline ticks. To allow for future support where the
3599 pipeline hit of individual instructions is known, this control
3600 loop manages a "pipeline_count" variable. It is initialised to
3601 1 (one), and will only be changed by the simulator engine when
3602 executing an instruction. If the engine does not have access to
3603 pipeline cycle count information then all instructions will be
3604 treated as using a single cycle. NOTE: A standard system is not
3605 provided by the default simulator because different MIPS
3606 architectures have different cycle counts for the same
3609 [NOTE: pipeline_count has been replaced the event queue] */
3611 /* shuffle the floating point status pipeline state */
3612 ENGINE_ISSUE_PREFIX_HOOK();
3614 /* NOTE: For multi-context simulation environments the "instruction"
3615 variable should be local to this routine. */
3617 /* Shorthand accesses for engine. Note: If we wanted to use global
3618 variables (and a single-threaded simulator engine), then we can
3619 create the actual variables with these names. */
3621 if (!(STATE
& simSKIPNEXT
)) {
3622 /* Include the simulator engine */
3623 #include "oengine.c"
3624 #if ((GPRLEN == 64) && !PROCESSOR_64BIT) || ((GPRLEN == 32) && PROCESSOR_64BIT)
3625 #error "Mismatch between run-time simulator code and simulation engine"
3627 #if (WITH_TARGET_WORD_BITSIZE != GPRLEN)
3628 #error "Mismatch between configure WITH_TARGET_WORD_BITSIZE and gencode GPRLEN"
3630 #if ((WITH_FLOATING_POINT == HARD_FLOATING_POINT) != defined (HASFPU))
3631 #error "Mismatch between configure WITH_FLOATING_POINT and gencode HASFPU"
3634 #if defined(WARN_LOHI)
3635 /* Decrement the HI/LO validity ticks */
3640 /* start-sanitize-r5900 */
3645 /* end-sanitize-r5900 */
3646 #endif /* WARN_LOHI */
3648 /* For certain MIPS architectures, GPR[0] is hardwired to zero. We
3649 should check for it being changed. It is better doing it here,
3650 than within the simulator, since it will help keep the simulator
3653 #if defined(WARN_ZERO)
3654 sim_io_eprintf(sd
,"The ZERO register has been updated with 0x%s (PC = 0x%s) (reset back to zero)\n",pr_addr(ZERO
),pr_addr(cia
));
3655 #endif /* WARN_ZERO */
3656 ZERO
= 0; /* reset back to zero before next instruction */
3658 } else /* simSKIPNEXT check */
3659 STATE
&= ~simSKIPNEXT
;
3661 /* If the delay slot was active before the instruction is
3662 executed, then update the PC to its new value: */
3665 printf("DBG: dsstate set before instruction execution - updating PC to 0x%s\n",pr_addr(DSPC
));
3674 #if !defined(FASTSIM)
3675 if (sim_events_tickn (sd
, pipeline_count
))
3677 /* cpu->cia = cia; */
3678 sim_events_process (sd
);
3681 if (sim_events_tick (sd
))
3683 /* cpu->cia = cia; */
3684 sim_events_process (sd
);
3686 #endif /* FASTSIM */
3692 /* This code copied from gdb's utils.c. Would like to share this code,
3693 but don't know of a common place where both could get to it. */
3695 /* Temporary storage using circular buffer */
3701 static char buf
[NUMCELLS
][CELLSIZE
];
3703 if (++cell
>=NUMCELLS
) cell
=0;
3707 /* Print routines to handle variable size regs, etc */
3709 /* Eliminate warning from compiler on 32-bit systems */
3710 static int thirty_two
= 32;
3716 char *paddr_str
=get_cell();
3717 switch (sizeof(addr
))
3720 sprintf(paddr_str
,"%08lx%08lx",
3721 (unsigned long)(addr
>>thirty_two
),(unsigned long)(addr
&0xffffffff));
3724 sprintf(paddr_str
,"%08lx",(unsigned long)addr
);
3727 sprintf(paddr_str
,"%04x",(unsigned short)(addr
&0xffff));
3730 sprintf(paddr_str
,"%x",addr
);
3739 char *paddr_str
=get_cell();
3740 sprintf(paddr_str
,"%08lx%08lx",
3741 (unsigned long)(addr
>>thirty_two
),(unsigned long)(addr
&0xffffffff));
3747 /*---------------------------------------------------------------------------*/
3748 /*> EOF interp.c <*/