MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
$Revision$
- $Author$
- $Date$
+ $Date$
NOTEs:
#include "sim-options.h"
#include "sim-assert.h"
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
+#include "sky-vu.h"
+#include "sky-vpe.h"
+#include "sky-libvpe.h"
+#endif
+/* end-sanitize-sky */
+
#include "config.h"
#include <stdio.h>
#include "sysdep.h"
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
+#include "sky-vu.h"
+#endif
+/* end-sanitize-sky */
+
#ifndef PARAMS
#define PARAMS(x)
#endif
#define MONITOR_SIZE (1 << 11)
#define MEM_SIZE (2 << 20)
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
+#undef MEM_SIZE
+#define MEM_SIZE (16 << 20) /* 16 MB */
+#endif
+/* end-sanitize-sky */
+
#if defined(TRACE)
static char *tracefile = "trace.din"; /* default filename for trace log */
FILE *tracefh = NULL;
static void open_trace PARAMS((SIM_DESC sd));
#endif /* TRACE */
+static DECLARE_OPTION_HANDLER (mips_option_handler);
+
#define OPTION_DINERO_TRACE 200
#define OPTION_DINERO_FILE 201
static SIM_RC
-mips_option_handler (sd, opt, arg)
+mips_option_handler (sd, cpu, opt, arg, is_command)
SIM_DESC sd;
+ sim_cpu *cpu;
int opt;
char *arg;
+ int is_command;
{
int cpu_nr;
switch (opt)
allow external control of the program points being traced
(i.e. only from main onwards, excluding the run-time setup,
etc.). */
- for (cpu_nr = 0; cpu_nr < sim_engine_nr_cpus (sd); cpu_nr++)
+ for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
{
sim_cpu *cpu = STATE_CPU (sd, cpu_nr);
if (arg == NULL)
/* start-sanitize-sky */
#ifdef TARGET_SKY
static struct {
- short i[16];
- int f[NUM_VU_REGS - 16];
+ short i[NUM_VU_INTEGER_REGS];
+ int f[NUM_VU_REGS - NUM_VU_INTEGER_REGS];
} vu_regs[2];
#endif
/* end-sanitize-sky */
if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
return 0;
- sim_add_option_table (sd, mips_options);
+ sim_add_option_table (sd, NULL, mips_options);
/* Allocate core managed memory */
/* For compatibility with the old code - under this (at level one)
are the kernel spaces K0 & K1. Both of these map to a single
smaller sub region */
+ sim_do_command(sd," memory region 0x7fff8000,0x8000") ; /* MTZ- 32 k stack */
+/* start-sanitize-sky */
+#ifndef TARGET_SKY
+/* end-sanitize-sky */
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x",
K1BASE, K0SIZE,
MEM_SIZE, /* actual size */
K0BASE);
+/* start-sanitize-sky */
+#else
+ sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x,0x%0x",
+ K1BASE, K0SIZE,
+ MEM_SIZE, /* actual size */
+ K0BASE,
+ 0); /* add alias at 0x0000 */
+#endif
+/* end-sanitize-sky */
device_init(sd);
cpu->register_widths[rn] = WITH_TARGET_FLOATING_POINT_BITSIZE;
else if ((rn >= 33) && (rn <= 37))
cpu->register_widths[rn] = WITH_TARGET_WORD_BITSIZE;
- else if ((rn == SRIDX) || (rn == FCR0IDX) || (rn == FCR31IDX) || ((rn >= 72) && (rn <= 89)))
+ else if ((rn == SRIDX)
+ || (rn == FCR0IDX)
+ || (rn == FCR31IDX)
+ || ((rn >= 72) && (rn <= 89)))
cpu->register_widths[rn] = 32;
else
cpu->register_widths[rn] = 0;
/* start-sanitize-sky */
#ifdef TARGET_SKY
/* Now the VU registers */
- for( rn = 0; rn < 16; rn++ ) { /* first the integer registers */
+ for( rn = 0; rn < NUM_VU_INTEGER_REGS; rn++ ) {
cpu->register_widths[rn + NUM_R5900_REGS] = 16;
cpu->register_widths[rn + NUM_R5900_REGS + NUM_VU_REGS] = 16;
vu_regs[1].i[rn] = rn + 0x200;
}
- for( rn = 16; rn < NUM_VU_REGS; rn++ ) { /* then the FP registers */
+ for( rn = NUM_VU_INTEGER_REGS; rn < NUM_VU_REGS; rn++ ) {
float f;
+ int first_vec_reg = NUM_VU_INTEGER_REGS + 8;
cpu->register_widths[rn + NUM_R5900_REGS] = 32;
cpu->register_widths[rn + NUM_R5900_REGS + NUM_VU_REGS] = 32;
/* Hack for now - to test gdb interface */
- if( rn < 24 ) {
- f = rn - 16 + 100.0;
- vu_regs[0].f[rn-16] = *((unsigned *) &f);
- f = rn - 16 + 200.0;
- vu_regs[1].f[rn-16] = *((unsigned *) &f);
+ if( rn < first_vec_reg ) {
+ f = rn - NUM_VU_INTEGER_REGS + 100.0;
+ vu_regs[0].f[rn-NUM_VU_INTEGER_REGS] = *((unsigned *) &f);
+ f = rn - NUM_VU_INTEGER_REGS + 200.0;
+ vu_regs[1].f[rn-NUM_VU_INTEGER_REGS] = *((unsigned *) &f);
}
else {
- f = (rn - 24)/4 + (rn - 24)%4 + 1000.0;
- vu_regs[0].f[rn-16] = *((unsigned *) &f);
- f = (rn - 24)/4 + (rn - 24)%4 + 2000.0;
- vu_regs[1].f[rn-16] = *((unsigned *) &f);
+ f = (rn - first_vec_reg)/4 + (rn - first_vec_reg)%4 + 1000.0;
+ vu_regs[0].f[rn-NUM_VU_INTEGER_REGS] = *((unsigned *) &f);
+ f = (rn - first_vec_reg)/4 + (rn - first_vec_reg)%4 + 2000.0;
+ vu_regs[1].f[rn-NUM_VU_INTEGER_REGS] = *((unsigned *) &f);
}
}
#endif
int cca;
if (!address_translation (SD, CPU, NULL_CIA, vaddr, isDATA, isSTORE, &paddr, &cca, isRAW))
break;
- if (sim_core_write_buffer (SD, CPU, sim_core_read_map, buffer + index, paddr, 1) != 1)
+ if (sim_core_write_buffer (SD, CPU, read_map, buffer + index, paddr, 1) != 1)
break;
}
int cca;
if (!address_translation (SD, CPU, NULL_CIA, vaddr, isDATA, isLOAD, &paddr, &cca, isRAW))
break;
- if (sim_core_read_buffer (SD, CPU, sim_core_read_map, buffer + index, paddr, 1) != 1)
+ if (sim_core_read_buffer (SD, CPU, read_map, buffer + index, paddr, 1) != 1)
break;
}
return(index);
}
-void
-sim_store_register (sd,rn,memory)
+int
+sim_store_register (sd,rn,memory,length)
SIM_DESC sd;
int rn;
unsigned char *memory;
+ int length;
{
sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
/* NOTE: gdb (the client) stores registers in target byte order
register number is for the architecture being simulated. */
if (cpu->register_widths[rn] == 0)
- sim_io_eprintf(sd,"Invalid register width for %d (register store ignored)\n",rn);
+ {
+ sim_io_eprintf(sd,"Invalid register width for %d (register store ignored)\n",rn);
+ return 0;
+ }
+
+ /* start-sanitize-r5900 */
+ if (rn >= 90 && rn < 90 + 32)
+ {
+ GPR1[rn - 90] = T2H_8 (*(unsigned64*)memory);
+ return 8;
+ }
+ switch (rn)
+ {
+ case REGISTER_SA:
+ SA = T2H_8(*(unsigned64*)memory);
+ return 8;
+ case 122: /* FIXME */
+ LO1 = T2H_8(*(unsigned64*)memory);
+ return 8;
+ case 123: /* FIXME */
+ HI1 = T2H_8(*(unsigned64*)memory);
+ return 8;
+ }
+ /* end-sanitize-r5900 */
+
/* start-sanitize-sky */
#ifdef TARGET_SKY
- else if( rn > NUM_R5900_REGS ) {
- rn = rn - NUM_R5900_REGS;
-
- if( rn < 16 )
- vu_regs[0].i[rn] = T2H_2( *(unsigned short *) memory );
- else if( rn < NUM_VU_REGS )
- vu_regs[0].f[rn - 16] = T2H_4( *(unsigned int *) memory );
- else {
- rn = rn - NUM_VU_REGS;
-
- if( rn < 16 )
- vu_regs[1].i[rn] = T2H_2( *(unsigned short *) memory );
+ if (rn >= NUM_R5900_REGS)
+ {
+ int size = 4; /* Default register size */
+
+ rn = rn - NUM_R5900_REGS;
+
+ if (rn < NUM_VU_INTEGER_REGS)
+ size = write_vu_int_reg (& vu0_device.state->regs, rn, memory);
else if( rn < NUM_VU_REGS )
- vu_regs[1].f[rn - 16] = T2H_4( *(unsigned int *) memory );
- else
- sim_io_eprintf( sd, "Invalid VU register (register store ignored)\n" );
+ vu_regs[0].f[rn - NUM_VU_INTEGER_REGS]
+ = T2H_4( *(unsigned int *) memory );
+ else {
+ rn = rn - NUM_VU_REGS;
+
+ if( rn < NUM_VU_INTEGER_REGS )
+ size = write_vu_int_reg (& vu1_device.state->regs, rn, memory);
+ else if( rn < NUM_VU_REGS )
+ vu_regs[1].f[rn - NUM_VU_INTEGER_REGS]
+ = T2H_4( *(unsigned int *) memory );
+ else
+ sim_io_eprintf( sd, "Invalid VU register (register store ignored)\n" );
+ }
+
+ return size;
}
- }
#endif
/* end-sanitize-sky */
- /* start-sanitize-r5900 */
- else if (rn == REGISTER_SA)
- SA = T2H_8(*(unsigned64*)memory);
- else if (rn > LAST_EMBED_REGNUM)
- cpu->registers1[rn - LAST_EMBED_REGNUM - 1] = T2H_8(*(unsigned64*)memory);
- /* end-sanitize-r5900 */
- else if (rn >= FGRIDX && rn < FGRIDX + NR_FGR)
+
+ if (rn >= FGRIDX && rn < FGRIDX + NR_FGR)
{
if (cpu->register_widths[rn] == 32)
- cpu->fgr[rn - FGRIDX] = T2H_4 (*(unsigned32*)memory);
+ {
+ cpu->fgr[rn - FGRIDX] = T2H_4 (*(unsigned32*)memory);
+ return 4;
+ }
else
- cpu->fgr[rn - FGRIDX] = T2H_8 (*(unsigned64*)memory);
+ {
+ cpu->fgr[rn - FGRIDX] = T2H_8 (*(unsigned64*)memory);
+ return 8;
+ }
}
- else if (cpu->register_widths[rn] == 32)
- cpu->registers[rn] = T2H_4 (*(unsigned32*)memory);
- else
- cpu->registers[rn] = T2H_8 (*(unsigned64*)memory);
- return;
+ if (cpu->register_widths[rn] == 32)
+ {
+ cpu->registers[rn] = T2H_4 (*(unsigned32*)memory);
+ return 4;
+ }
+ else
+ {
+ cpu->registers[rn] = T2H_8 (*(unsigned64*)memory);
+ return 8;
+ }
}
-void
-sim_fetch_register (sd,rn,memory)
+int
+sim_fetch_register (sd,rn,memory,length)
SIM_DESC sd;
int rn;
unsigned char *memory;
+ int length;
{
sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
/* NOTE: gdb (the client) stores registers in target byte order
#endif /* DEBUG */
if (cpu->register_widths[rn] == 0)
- sim_io_eprintf(sd,"Invalid register width for %d (register fetch ignored)\n",rn);
+ {
+ sim_io_eprintf (sd, "Invalid register width for %d (register fetch ignored)\n",rn);
+ return 0;
+ }
+
+ /* start-sanitize-r5900 */
+ if (rn >= 90 && rn < 90 + 32)
+ {
+ *(unsigned64*)memory = GPR1[rn - 90];
+ return 8;
+ }
+ switch (rn)
+ {
+ case REGISTER_SA:
+ *((unsigned64*)memory) = H2T_8(SA);
+ return 8;
+ case 122: /* FIXME */
+ *((unsigned64*)memory) = H2T_8(LO1);
+ return 8;
+ case 123: /* FIXME */
+ *((unsigned64*)memory) = H2T_8(HI1);
+ return 8;
+ }
+ /* end-sanitize-r5900 */
+
/* start-sanitize-sky */
#ifdef TARGET_SKY
- else if( rn > NUM_R5900_REGS ) {
- rn = rn - NUM_R5900_REGS;
-
- if( rn < 16 )
- *((unsigned short *) memory) = H2T_2( vu_regs[0].i[rn] );
- else if( rn < NUM_VU_REGS )
- *((unsigned int *) memory) = H2T_4( vu_regs[0].f[rn - 16] );
- else {
- rn = rn - NUM_VU_REGS;
-
- if( rn < 16 )
- (*(unsigned short *) memory) = H2T_2( vu_regs[1].i[rn] );
- else if( rn < NUM_VU_REGS )
- (*(unsigned int *) memory) = H2T_4( vu_regs[1].f[rn - 16] );
- else
- sim_io_eprintf( sd, "Invalid VU register (register fetch ignored)\n" );
+ if (rn >= NUM_R5900_REGS)
+ {
+ int size = 4; /* default register width */
+
+ rn = rn - NUM_R5900_REGS;
+
+ if (rn < NUM_VU_INTEGER_REGS)
+ size = read_vu_int_reg (& vu0_device.state->regs, rn, memory);
+ else if (rn < NUM_VU_REGS)
+ *((unsigned int *) memory)
+ = H2T_4( vu_regs[0].f[rn - NUM_VU_INTEGER_REGS] );
+ else
+ {
+ rn = rn - NUM_VU_REGS;
+
+ if (rn < NUM_VU_INTEGER_REGS)
+ size = read_vu_int_reg (& vu1_device.state->regs, rn, memory);
+ else if (rn < NUM_VU_REGS)
+ (*(unsigned int *) memory)
+ = H2T_4( vu_regs[1].f[rn - NUM_VU_INTEGER_REGS] );
+ else
+ sim_io_eprintf( sd, "Invalid VU register (register fetch ignored)\n" );
+ }
+
+ return size;
}
- }
#endif
/* end-sanitize-sky */
- /* start-sanitize-r5900 */
- else if (rn == REGISTER_SA)
- *((unsigned64*)memory) = H2T_8(SA);
- else if (rn > LAST_EMBED_REGNUM)
- *((unsigned64*)memory) = H2T_8(cpu->registers1[rn - LAST_EMBED_REGNUM - 1]);
- /* end-sanitize-r5900 */
- else if (rn >= FGRIDX && rn < FGRIDX + NR_FGR)
+
+ /* Any floating point register */
+ if (rn >= FGRIDX && rn < FGRIDX + NR_FGR)
{
if (cpu->register_widths[rn] == 32)
- *(unsigned32*)memory = H2T_4 (cpu->fgr[rn - FGRIDX]);
+ {
+ *(unsigned32*)memory = H2T_4 (cpu->fgr[rn - FGRIDX]);
+ return 4;
+ }
else
- *(unsigned64*)memory = H2T_8 (cpu->fgr[rn - FGRIDX]);
+ {
+ *(unsigned64*)memory = H2T_8 (cpu->fgr[rn - FGRIDX]);
+ return 8;
+ }
}
- else if (cpu->register_widths[rn] == 32)
- *(unsigned32*)memory = H2T_4 ((unsigned32)(cpu->registers[rn]));
- else /* 64bit register */
- *(unsigned64*)memory = H2T_8 ((unsigned64)(cpu->registers[rn]));
-
- return;
-}
-
-void
-sim_info (sd,verbose)
- SIM_DESC sd;
- int verbose;
-{
- /* Accessed from the GDB "info files" command: */
- if (STATE_VERBOSE_P (sd) || verbose)
+ if (cpu->register_widths[rn] == 32)
{
-
- sim_io_printf (sd, "MIPS %d-bit %s endian simulator\n",
- WITH_TARGET_WORD_BITSIZE,
- (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN ? "Big" : "Little"));
-
-#if !defined(FASTSIM)
- /* It would be a useful feature, if when performing multi-cycle
- simulations (rather than single-stepping) we keep the start and
- end times of the execution, so that we can give a performance
- figure for the simulator. */
-#endif /* !FASTSIM */
- sim_io_printf (sd, "Number of execution cycles = %ld\n",
- (long) sim_events_time (sd));
-
- /* print information pertaining to MIPS ISA and architecture being simulated */
- /* things that may be interesting */
- /* instructions executed - if available */
- /* cycles executed - if available */
- /* pipeline stalls - if available */
- /* virtual time taken */
- /* profiling size */
- /* profiling frequency */
- /* profile minpc */
- /* profile maxpc */
- }
- profile_print (sd, STATE_VERBOSE_P (sd), NULL, NULL);
+ *(unsigned32*)memory = H2T_4 ((unsigned32)(cpu->registers[rn]));
+ return 4;
+ }
+ else
+ {
+ *(unsigned64*)memory = H2T_8 ((unsigned64)(cpu->registers[rn]));
+ return 8;
+ }
}
{
case AccessLength_QUADWORD :
{
- unsigned_16 val = sim_core_read_aligned_16 (cpu, NULL_CIA,
- sim_core_read_map, pAddr);
+ unsigned_16 val = sim_core_read_aligned_16 (cpu, NULL_CIA, read_map, pAddr);
value1 = VH8_16 (val);
value = VL8_16 (val);
break;
}
case AccessLength_DOUBLEWORD :
value = sim_core_read_aligned_8 (cpu, NULL_CIA,
- sim_core_read_map, pAddr);
+ read_map, pAddr);
break;
case AccessLength_SEPTIBYTE :
value = sim_core_read_misaligned_7 (cpu, NULL_CIA,
- sim_core_read_map, pAddr);
+ read_map, pAddr);
+ break;
case AccessLength_SEXTIBYTE :
value = sim_core_read_misaligned_6 (cpu, NULL_CIA,
- sim_core_read_map, pAddr);
+ read_map, pAddr);
+ break;
case AccessLength_QUINTIBYTE :
value = sim_core_read_misaligned_5 (cpu, NULL_CIA,
- sim_core_read_map, pAddr);
+ read_map, pAddr);
+ break;
case AccessLength_WORD :
value = sim_core_read_aligned_4 (cpu, NULL_CIA,
- sim_core_read_map, pAddr);
+ read_map, pAddr);
break;
case AccessLength_TRIPLEBYTE :
value = sim_core_read_misaligned_3 (cpu, NULL_CIA,
- sim_core_read_map, pAddr);
+ read_map, pAddr);
+ break;
case AccessLength_HALFWORD :
value = sim_core_read_aligned_2 (cpu, NULL_CIA,
- sim_core_read_map, pAddr);
+ read_map, pAddr);
break;
case AccessLength_BYTE :
value = sim_core_read_aligned_1 (cpu, NULL_CIA,
- sim_core_read_map, pAddr);
+ read_map, pAddr);
break;
default:
abort ();
case AccessLength_QUADWORD :
{
unsigned_16 val = U16_8 (MemElem1, MemElem);
- sim_core_write_aligned_16 (cpu, NULL_CIA,
- sim_core_write_map, pAddr, val);
+ sim_core_write_aligned_16 (cpu, NULL_CIA, write_map, pAddr, val);
break;
}
case AccessLength_DOUBLEWORD :
sim_core_write_aligned_8 (cpu, NULL_CIA,
- sim_core_write_map, pAddr, MemElem);
+ write_map, pAddr, MemElem);
break;
case AccessLength_SEPTIBYTE :
sim_core_write_misaligned_7 (cpu, NULL_CIA,
- sim_core_write_map, pAddr, MemElem);
+ write_map, pAddr, MemElem);
break;
case AccessLength_SEXTIBYTE :
sim_core_write_misaligned_6 (cpu, NULL_CIA,
- sim_core_write_map, pAddr, MemElem);
+ write_map, pAddr, MemElem);
break;
case AccessLength_QUINTIBYTE :
sim_core_write_misaligned_5 (cpu, NULL_CIA,
- sim_core_write_map, pAddr, MemElem);
+ write_map, pAddr, MemElem);
break;
case AccessLength_WORD :
sim_core_write_aligned_4 (cpu, NULL_CIA,
- sim_core_write_map, pAddr, MemElem);
+ write_map, pAddr, MemElem);
break;
case AccessLength_TRIPLEBYTE :
sim_core_write_misaligned_3 (cpu, NULL_CIA,
- sim_core_write_map, pAddr, MemElem);
+ write_map, pAddr, MemElem);
break;
case AccessLength_HALFWORD :
sim_core_write_aligned_2 (cpu, NULL_CIA,
- sim_core_write_map, pAddr, MemElem);
+ write_map, pAddr, MemElem);
break;
case AccessLength_BYTE :
sim_core_write_aligned_1 (cpu, NULL_CIA,
- sim_core_write_map, pAddr, MemElem);
+ write_map, pAddr, MemElem);
break;
default:
abort ();
return(result);
}
+#if 0
+uword64
+Max (uword64 op1,
+ uword64 op2,
+ FP_formats fmt)
+{
+ int cmp;
+ unsigned64 result;
+
+#ifdef DEBUG
+ printf("DBG: Max: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
+#endif /* DEBUG */
+
+ /* The registers must specify FPRs valid for operands of type
+ "fmt". If they are not valid, the result is undefined. */
+
+ /* The format type should already have been checked: */
+ switch (fmt)
+ {
+ case fmt_single:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ cmp = sim_fpu_cmp (&wop1, &wop2);
+ break;
+ }
+ case fmt_double:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ cmp = sim_fpu_cmp (&wop1, &wop2);
+ break;
+ }
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+ switch (cmp)
+ {
+ case SIM_FPU_IS_SNAN:
+ case SIM_FPU_IS_QNAN:
+ result = op1;
+ case SIM_FPU_IS_NINF:
+ case SIM_FPU_IS_NNUMBER:
+ case SIM_FPU_IS_NDENORM:
+ case SIM_FPU_IS_NZERO:
+ result = op2; /* op1 - op2 < 0 */
+ case SIM_FPU_IS_PINF:
+ case SIM_FPU_IS_PNUMBER:
+ case SIM_FPU_IS_PDENORM:
+ case SIM_FPU_IS_PZERO:
+ result = op1; /* op1 - op2 > 0 */
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+#ifdef DEBUG
+ printf("DBG: Max: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
+#endif /* DEBUG */
+
+ return(result);
+}
+#endif
+
+#if 0
+uword64
+Min (uword64 op1,
+ uword64 op2,
+ FP_formats fmt)
+{
+ int cmp;
+ unsigned64 result;
+
+#ifdef DEBUG
+ printf("DBG: Min: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
+#endif /* DEBUG */
+
+ /* The registers must specify FPRs valid for operands of type
+ "fmt". If they are not valid, the result is undefined. */
+
+ /* The format type should already have been checked: */
+ switch (fmt)
+ {
+ case fmt_single:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ cmp = sim_fpu_cmp (&wop1, &wop2);
+ break;
+ }
+ case fmt_double:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ cmp = sim_fpu_cmp (&wop1, &wop2);
+ break;
+ }
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+ switch (cmp)
+ {
+ case SIM_FPU_IS_SNAN:
+ case SIM_FPU_IS_QNAN:
+ result = op1;
+ case SIM_FPU_IS_NINF:
+ case SIM_FPU_IS_NNUMBER:
+ case SIM_FPU_IS_NDENORM:
+ case SIM_FPU_IS_NZERO:
+ result = op1; /* op1 - op2 < 0 */
+ case SIM_FPU_IS_PINF:
+ case SIM_FPU_IS_PNUMBER:
+ case SIM_FPU_IS_PDENORM:
+ case SIM_FPU_IS_PZERO:
+ result = op2; /* op1 - op2 > 0 */
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+#ifdef DEBUG
+ printf("DBG: Min: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
+#endif /* DEBUG */
+
+ return(result);
+}
+#endif
+
uword64
convert (SIM_DESC sd,
sim_cpu *cpu,
return;
}
+
+void
+cop_lq (SIM_DESC sd,
+ sim_cpu *cpu,
+ address_word cia,
+ int coproc_num,
+ int coproc_reg,
+ unsigned128 memword)
+{
+ switch (coproc_num)
+ {
+ /* start-sanitize-sky */
+ case 2:
+ /* XXX COP2 */
+ break;
+ /* end-sanitize-sky */
+
+ default:
+ sim_io_printf(sd,"COP_LQ(%d,%d,??) at PC = 0x%s : TODO (architecture specific)\n",
+ coproc_num,coproc_reg,pr_addr(cia));
+ break;
+ }
+
+ return;
+}
+
+
unsigned int
cop_sw (SIM_DESC sd,
sim_cpu *cpu,
return(value);
}
+
+unsigned128
+cop_sq (SIM_DESC sd,
+ sim_cpu *cpu,
+ address_word cia,
+ int coproc_num,
+ int coproc_reg)
+{
+ unsigned128 value = {0, 0};
+ switch (coproc_num)
+ {
+ /* start-sanitize-sky */
+ case 2:
+ /* XXX COP2 */
+ break;
+ /* end-sanitize-sky */
+
+ default:
+ sim_io_printf(sd,"COP_SQ(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",
+ coproc_num,coproc_reg,pr_addr(cia));
+ break;
+ }
+
+ return(value);
+}
+
+
void
decode_coproc (SIM_DESC sd,
sim_cpu *cpu,
break;
case 2: /* undefined co-processor */
- sim_io_eprintf(sd,"COP2 instruction 0x%08X at PC = 0x%s : No handler present\n",instruction,pr_addr(cia));
- break;
-
+ {
+ int handle = 0;
+
+ /* start-sanitize-sky */
+ /* On the R5900, this refers to a "VU" vector co-processor. */
+
+ int i_25_21 = (instruction >> 21) & 0x1f;
+ int i_20_16 = (instruction >> 16) & 0x1f;
+ int i_15_11 = (instruction >> 11) & 0x1f;
+ int i_15_0 = instruction & 0xffff;
+ int i_10_1 = (instruction >> 1) & 0x3ff;
+ int interlock = instruction & 0x01;
+ unsigned_4 vpe_status = sim_core_read_aligned_4 (cpu, cia, read_map, VPE0_STAT);
+ int vpe_busy = (vpe_status & 0x00000001);
+ /* setup for semantic.c-like actions below */
+ typedef unsigned_4 instruction_word;
+ int CIA = cia;
+ int NIA = cia + 4;
+ sim_cpu* CPU_ = cpu;
+
+ handle = 1;
+
+ /* test COP2 usability */
+ if(! (SR & status_CU2))
+ {
+ SignalException(CoProcessorUnusable,instruction);
+ /* NOTREACHED */
+ }
+
+ /* classify & execute basic COP2 instructions */
+ if(i_25_21 == 0x08 && i_20_16 == 0x00) /* BC2F */
+ {
+ address_word offset = EXTEND16(i_15_0) << 2;
+ if(! vpe_busy) DELAY_SLOT(cia + 4 + offset);
+ }
+ else if(i_25_21 == 0x08 && i_20_16==0x02) /* BC2FL */
+ {
+ address_word offset = EXTEND16(i_15_0) << 2;
+ if(! vpe_busy) DELAY_SLOT(cia + 4 + offset);
+ else NULLIFY_NEXT_INSTRUCTION();
+ }
+ else if(i_25_21 == 0x08 && i_20_16 == 0x01) /* BC2T */
+ {
+ address_word offset = EXTEND16(i_15_0) << 2;
+ if(vpe_busy) DELAY_SLOT(cia + 4 + offset);
+ }
+ else if(i_25_21 == 0x08 && i_20_16 == 0x03) /* BC2TL */
+ {
+ address_word offset = EXTEND16(i_15_0) << 2;
+ if(vpe_busy) DELAY_SLOT(cia + 4 + offset);
+ else NULLIFY_NEXT_INSTRUCTION();
+ }
+ else if((i_25_21 == 0x02 && i_10_1 == 0x000) || /* CFC2 */
+ (i_25_21 == 0x06 && i_10_1 == 0x000)) /* CTC2 */
+ {
+ int rt = i_20_16;
+ int id = i_15_11;
+ int to_vu = (i_25_21 == 0x06); /* transfer direction */
+ address_word vu_cr_addr; /* VU control register address */
+
+ if(interlock)
+ while(vpe_busy)
+ {
+ vu0_issue(sd); /* advance one clock cycle */
+ vpe_status = sim_core_read_aligned_4 (cpu, cia, read_map, VPE0_STAT);
+ vpe_busy = vpe_status & 0x00000001;
+ }
+
+ /* compute VU register address */
+ vu_cr_addr = VU0_MST + (id * 16);
+
+ /* read or write word */
+ if(to_vu) /* CTC2 */
+ {
+ unsigned_4 data = GPR[rt];
+ sim_core_write_aligned_4(cpu, cia, write_map, vu_cr_addr, data);
+ }
+ else /* CFC2 */
+ {
+ unsigned_4 data = sim_core_read_aligned_4(cpu, cia, read_map, vu_cr_addr);
+ GPR[rt] = EXTEND64(data);
+ }
+ }
+ else if((i_25_21 == 0x01) || /* QMFC2 */
+ (i_25_21 == 0x05)) /* QMTC2 */
+ {
+ int rt = i_20_16;
+ int id = i_15_11;
+ int to_vu = (i_25_21 == 0x05); /* transfer direction */
+ address_word vu_cr_addr; /* VU control register address */
+
+ if(interlock)
+ while(vpe_busy)
+ {
+ vu0_issue(sd); /* advance one clock cycle */
+ vpe_status = sim_core_read_aligned_4 (cpu, cia, read_map, VPE0_STAT);
+ vpe_busy = vpe_status & 0x00000001;
+ }
+
+ /* compute VU register address */
+ vu_cr_addr = VU0_VF00 + (id * 16);
+
+ /* read or write word */
+ if(to_vu) /* CTC2 */
+ {
+ unsigned_4 data = GPR[rt];
+ sim_core_write_aligned_4(cpu, cia, write_map, vu_cr_addr, data);
+ }
+ else /* CFC2 */
+ {
+ unsigned_4 data = sim_core_read_aligned_4(cpu, cia, read_map, vu_cr_addr);
+ GPR[rt] = EXTEND64(data);
+ }
+ }
+ /* other COP2 instructions */
+ else
+ {
+ SignalException(ReservedInstruction,instruction);
+ /* NOTREACHED */
+ }
+
+ /* cleanup for semantic.c-like actions above */
+ PC = NIA;
+
+ /* end-sanitize-sky */
+
+ if(! handle)
+ {
+ sim_io_eprintf(sd,"COP2 instruction 0x%08X at PC = 0x%s : No handler present\n",
+ instruction,pr_addr(cia));
+ }
+ }
+ break;
+
case 1: /* should not occur (FPU co-processor) */
case 3: /* should not occur (FPU co-processor) */
SignalException(ReservedInstruction,instruction);
return;
}
+
/*-- instruction simulation -------------------------------------------------*/
/* When the IGEN simulator is being built, the function below is be