#include "sky-vpe.h"
#include "sky-libvpe.h"
#include "sky-pke.h"
+#include "sky-gpuif.h"
#include "idecode.h"
+#include "support.h"
+#undef SD
#endif
/* end-sanitize-sky */
#endif
/* Within interp.c we refer to the sim_state and sim_cpu directly. */
-#define SD sd
#define CPU cpu
+#define SD sd
/* The following reserved instruction value is used when a simulator
trap is required. NOTE: Care must be taken, since this value may be
used in later revisions of the MIPS ISA. */
+
#define RSVD_INSTRUCTION (0x00000005)
#define RSVD_INSTRUCTION_MASK (0xFC00003F)
#define RSVD_INSTRUCTION_ARG_MASK 0xFFFFF
+/* The following reserved instruction value is used when a simulator
+ halt is required. NOTE: Care must be taken, since this value may
+ be used in later revisions of the MIPS ISA. */
+#define HALT_INSTRUCTION (0x03ff000d)
+#define HALT_INSTRUCTION_MASK (0x03FFFFC0)
+
+
/* Bits in the Debug register */
#define Debug_DBD 0x80000000 /* Debug Branch Delay */
#define Debug_DM 0x40000000 /* Debug Mode */
OPTION_DINERO_TRACE = OPTION_START,
OPTION_DINERO_FILE
/* start-sanitize-sky */
+#ifdef TARGET_SKY
+#ifdef SKY_FUNIT
,OPTION_FLOAT_TYPE
+#endif
+ ,OPTION_GS_ENABLE
+ ,OPTION_GS_REFRESH1
+ ,OPTION_GS_REFRESH2
+#endif
/* end-sanitize-sky */
};
return SIM_RC_OK;
/* start-sanitize-sky */
+#ifdef TARGET_SKY
+#ifdef SKY_FUNIT
case OPTION_FLOAT_TYPE:
/* Use host (fast) or target (accurate) floating point implementation. */
if (arg && strcmp (arg, "host") == 0)
fprintf (stderr, "Unrecognized float-type option `%s'\n", arg);
return SIM_RC_FAIL;
}
+ /*printf ("float-type=0x%08x\n", STATE_FP_TYPE_OPT (sd));*/
return SIM_RC_OK;
+#endif
+
+ case OPTION_GS_ENABLE:
+ /* Enable GS libraries. */
+ if ( arg && strcmp (arg, "on") == 0 )
+ gif_options (&gif_full,GIF_OPT_GS_ENABLE,1,0,0);
+ else if ( arg && strcmp (arg, "off") == 0 )
+ gif_options (&gif_full,GIF_OPT_GS_ENABLE,0,0,0);
+ else
+ {
+ fprintf (stderr, "Unrecognized enable-gs option `%s'\n", arg);
+ return SIM_RC_FAIL;
+ }
+ return SIM_RC_OK;
+
+ case OPTION_GS_REFRESH1:
+ case OPTION_GS_REFRESH2:
+ {
+ /* The GS has defineable register and register values. */
+ unsigned_4 address[2];
+ long long value[2];
+ char c[3];
+
+ if ( arg && strlen (arg) == 59 && arg[10] == '=' &&
+ arg[29] == ':' && arg[40] == '=' &&
+ ( sscanf (arg,"%lx%c%Lx%c%lx%c%Lx", &address[0],&c[0],&value[0],
+ &c[1],&address[1],&c[2],&value[1]) == 7 ))
+ {
+ gif_options (&gif_full, ( opt == OPTION_GS_REFRESH1 ) ?
+ GIF_OPT_GS_REFRESH1:GIF_OPT_GS_REFRESH2,
+ 0,&address[0],&value[0]);
+ }
+ else
+ {
+ fprintf (stderr, "Unrecognized gs-refresh option `%s'\n", arg);
+ return SIM_RC_FAIL;
+ }
+ }
+ return SIM_RC_OK;
+
+#endif
/* end-sanitize-sky */
}
'\0', "FILE", "Write dinero trace to FILE",
mips_option_handler },
/* start-sanitize-sky */
+#ifdef TARGET_SKY
+#ifdef SKY_FUNIT
{ {"float-type", required_argument, NULL, OPTION_FLOAT_TYPE},
'\0', "host|target", "Use host (fast) or target (accurate) floating point",
mips_option_handler },
+#endif
+ { {"enable-gs", required_argument, NULL, OPTION_GS_ENABLE},
+ '\0', "on|off", "Enable GS library routines",
+ mips_option_handler },
+ { {"gs-refresh1", required_argument, NULL, OPTION_GS_REFRESH1},
+ '\0', "0xaddress0=0xvalue0:0xaddress1=0xvalue1", "GS refresh buffer 1 addresses and values",
+ mips_option_handler },
+ { {"gs-refresh2", required_argument, NULL, OPTION_GS_REFRESH2},
+ '\0', "0xaddress0=0xvalue0:0xaddress1=0xvalue1", "GS refresh buffer 2 addresses and values",
+ mips_option_handler },
+#endif
/* end-sanitize-sky */
{ {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
};
sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
+/* start-sanitize-sky */
+
+#if defined(TARGET_SKY) && defined(SKY_FUNIT)
+ /* Set "--float-type host" as the default. */
+ STATE_FP_TYPE_OPT (sd) &= ~STATE_FP_TYPE_OPT_TARGET;
+#endif
+/* end-sanitize-sky */
/* FIXME: watchpoints code shouldn't need this */
STATE_WATCHPOINTS (sd)->pc = &(PC);
/* Finally the VIF registers */
for( rn = 2*NUM_VU_REGS; rn < 2*NUM_VU_REGS + 2*NUM_VIF_REGS; rn++ )
cpu->register_widths[rn + NUM_R5900_REGS] = 32;
+
+ cpu->cur_device = 0;
#endif
/* end-sanitize-sky */
}
open_trace(sd);
#endif /* TRACE */
+ /* Write an abort sequence into the TRAP (common) exception vector
+ addresses. This is to catch code executing a TRAP (et.al.)
+ instruction without installing a trap handler. */
+ {
+ unsigned32 halt[2] = { 0x2404002f /* addiu r4, r0, 47 */,
+ HALT_INSTRUCTION /* BREAK */ };
+ H2T (halt[0]);
+ H2T (halt[1]);
+ sim_write (sd, 0x80000180, (char *) halt, sizeof (halt));
+ sim_write (sd, 0xBFC00380, (char *) halt, sizeof (halt));
+ }
+
+
/* Write the monitor trap address handlers into the monitor (eeprom)
address space. This can only be done once the target endianness
has been determined. */
}
}
-unsigned16
-ifetch16 (SIM_DESC sd,
- sim_cpu *cpu,
- address_word cia,
- address_word vaddr)
-{
- /* Copy the action of the LW instruction */
- address_word reverse = (ReverseEndian ? (LOADDRMASK >> 2) : 0);
- address_word bigend = (BigEndianCPU ? (LOADDRMASK >> 2) : 0);
- unsigned64 value;
- address_word paddr;
- unsigned16 instruction;
- unsigned byte;
- int cca;
- AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &cca, isTARGET, isREAL);
- paddr = ((paddr & ~LOADDRMASK) | ((paddr & LOADDRMASK) ^ (reverse << 2)));
- LoadMemory (&value, NULL, cca, AccessLength_WORD, paddr, vaddr, isINSTRUCTION, isREAL);
- byte = ((vaddr & LOADDRMASK) ^ (bigend << 2));
- instruction = ((value >> (8 * byte)) & 0xFFFFFFFF);
- return instruction;
-}
-
-
/* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
/* Signal an exception condition. This will result in an exception
that aborts the instruction. The instruction operation pseudocode
LLBIT = 0;
switch (exception) {
- /* TODO: For testing purposes I have been ignoring TRAPs. In
- reality we should either simulate them, or allow the user to
- ignore them at run-time.
- Same for SYSCALL */
- case Trap :
- sim_io_eprintf(sd,"Ignoring instruction TRAP (PC 0x%s)\n",pr_addr(cia));
- break;
case SystemCall :
{
sim_engine_restart (sd, NULL, NULL, NULL_CIA);
}
/* else fall through to normal exception processing */
- sim_io_eprintf(sd,"ReservedInstruction 0x%08X at PC = 0x%s\n",instruction,pr_addr(cia));
+ sim_io_eprintf(sd,"ReservedInstruction at PC = 0x%s\n", pr_addr (cia));
}
case BreakPoint:
{
va_list ap;
unsigned int instruction;
- va_start(ap,exception);
+ va_start(ap, exception);
instruction = va_arg(ap,unsigned int);
va_end(ap);
/* Check for our special terminating BREAK: */
- if ((instruction & 0x03FFFFC0) == 0x03ff0000) {
- sim_engine_halt (SD, CPU, NULL, cia,
- sim_exited, (unsigned int)(A0 & 0xFFFFFFFF));
- }
+ if ((instruction & HALT_INSTRUCTION_MASK)
+ == (HALT_INSTRUCTION & HALT_INSTRUCTION_MASK))
+ {
+ sim_engine_halt (SD, CPU, NULL, cia,
+ sim_exited, (unsigned int)(A0 & 0xFFFFFFFF));
+ }
}
if (STATE & simDELAYSLOT)
PC = cia - 4; /* reference the branch instruction */
sim_stopped, SIM_SIGFPE);
case Trap:
+ sim_engine_restart (SD, CPU, NULL, PC);
+ break;
+
case Watch:
case SystemCall:
PC = EPC;
{
case 2:
{
- unsigned_16 xyzw;
+ int i;
while(vu0_busy())
vu0_issue(sd);
- memcpy(& xyzw, & memword, sizeof(xyzw));
- xyzw = H2T_16(xyzw);
/* one word at a time, argh! */
- write_vu_vec_reg(&(vu0_device.regs), coproc_reg, 0, A4_16(& xyzw, 3));
- write_vu_vec_reg(&(vu0_device.regs), coproc_reg, 1, A4_16(& xyzw, 2));
- write_vu_vec_reg(&(vu0_device.regs), coproc_reg, 2, A4_16(& xyzw, 1));
- write_vu_vec_reg(&(vu0_device.regs), coproc_reg, 3, A4_16(& xyzw, 0));
+ for(i=0; i<4; i++)
+ {
+ unsigned_4 value;
+ value = H2T_4(*A4_16(& memword, 3-i));
+ write_vu_vec_reg(&(vu0_device.regs), coproc_reg, i, & value);
+ }
}
break;
case 2:
{
unsigned_16 xyzw;
+ int i;
while(vu0_busy())
vu0_issue(sd);
/* one word at a time, argh! */
- read_vu_vec_reg(&(vu0_device.regs), coproc_reg, 0, A4_16(& xyzw, 3));
- read_vu_vec_reg(&(vu0_device.regs), coproc_reg, 1, A4_16(& xyzw, 2));
- read_vu_vec_reg(&(vu0_device.regs), coproc_reg, 2, A4_16(& xyzw, 1));
- read_vu_vec_reg(&(vu0_device.regs), coproc_reg, 3, A4_16(& xyzw, 0));
- xyzw = T2H_16(xyzw);
+ for(i=0; i<4; i++)
+ {
+ unsigned_4 value;
+ read_vu_vec_reg(&(vu0_device.regs), coproc_reg, i, & value);
+ *A4_16(& xyzw, 3-i) = T2H_4(value);
+ }
return xyzw;
}
break;
CAUSE = GPR[rt];
break;
/* 14 = EPC R4000 VR4100 VR4300 */
+ case 14:
+ if (code == 0x00)
+ GPR[rt] = (signed_word) (signed_address) EPC;
+ else
+ EPC = GPR[rt];
+ break;
/* 15 = PRId R4000 VR4100 VR4300 */
#ifdef SUBTARGET_R3900
/* 16 = Debug */
typedef unsigned_4 instruction_word;
int CIA = cia;
int NIA = cia + 4;
- sim_cpu* CPU_ = cpu;
handle = 1;
/* NOTREACHED */
}
+#define MY_INDEX itable_COPz_NORMAL
+#define MY_PREFIX COPz_NORMAL
+#define MY_NAME "COPz_NORMAL"
+
/* classify & execute basic COP2 instructions */
if(i_25_21 == 0x08 && i_20_16 == 0x00) /* BC2F */
{
read_vu_vec_reg(&(vu0_device.regs), id, 1, A4_16(& xyzw, 2));
read_vu_vec_reg(&(vu0_device.regs), id, 2, A4_16(& xyzw, 1));
read_vu_vec_reg(&(vu0_device.regs), id, 3, A4_16(& xyzw, 0));
- xyzw = T2H_16(xyzw);
- memcpy(& GPR[rt], & xyzw, sizeof(xyzw));
+ GPR[rt] = T2H_8(* A8_16(& xyzw, 1));
+ GPR1[rt] = T2H_8(* A8_16(& xyzw, 0));
}
else /* CFC2 */
{
int rt = i_20_16;
int id = i_15_11;
- /* interlock checking */
+ /* interlock checking: wait until M or E bits set */
/* POLICY: never busy in macro mode */
- if(vu0_busy() && interlock)
+ while(vu0_busy() && interlock)
{
- while(! vu0_micro_interlock_released())
- vu0_issue(sd);
+ if(vu0_micro_interlock_released())
+ {
+ vu0_micro_interlock_clear();
+ break;
+ }
+
+ vu0_issue(sd);
}
/* perform VU register address */
if(i_25_21 == 0x05) /* QMTC2 */
{
- unsigned_16 xyzw;
- memcpy(& xyzw, & GPR[rt], sizeof(xyzw));
+ unsigned_16 xyzw = U16_8(GPR1[rt], GPR[rt]);
+
xyzw = H2T_16(xyzw);
/* one word at a time, argh! */
write_vu_vec_reg(&(vu0_device.regs), id, 0, A4_16(& xyzw, 3));
vu0_issue(sd);
/* write to reserved CIA register to get VU0 moving */
- write_vu_misc_reg(&(vu0_device.regs), VU_REG_CIA, & data);
+ write_vu_special_reg(& vu0_device, VU_REG_CIA, & data);
+
+ ASSERT(vu0_busy());
}
else if(i_5_0 == 0x39) /* VCALLMSR */
{
while(vu0_busy())
vu0_issue(sd);
- read_vu_misc_reg(&(vu0_device.regs), VU_REG_CMSAR0, & data);
+ read_vu_special_reg(& vu0_device, VU_REG_CMSAR0, & data);
/* write to reserved CIA register to get VU0 moving */
- write_vu_misc_reg(&(vu0_device.regs), VU_REG_CIA, & data);
+ write_vu_special_reg(& vu0_device, VU_REG_CIA, & data);
+
+ ASSERT(vu0_busy());
}
/* handle all remaining UPPER VU instructions in one block */
else if((i_5_0 < 0x30) || /* VADDx .. VMINI */
unsigned_4 vu_upper, vu_lower;
vu_upper = 0x000002ff; /* NOP/NOP */
vu_lower =
- 0x10000000 | /* bits 31 .. 25 */
+ 0x80000000 | /* bits 31 .. 25 */
(instruction & 0x01ffffff); /* bits 24 .. 0 */
/* POLICY: never busy in macro mode */
/* cleanup for semantic.c-like actions above */
PC = NIA;
+#undef MY_INDEX
+#undef MY_PREFIX
+#undef MY_NAME
+
#endif /* TARGET_SKY */
/* end-sanitize-sky */
#error "Mismatch between configure WITH_FLOATING_POINT and gencode HASFPU"
#endif
-#if defined(WARN_LOHI)
- /* Decrement the HI/LO validity ticks */
- if (HIACCESS > 0)
- HIACCESS--;
- if (LOACCESS > 0)
- LOACCESS--;
- /* start-sanitize-r5900 */
- if (HI1ACCESS > 0)
- HI1ACCESS--;
- if (LO1ACCESS > 0)
- LO1ACCESS--;
- /* end-sanitize-r5900 */
-#endif /* WARN_LOHI */
-
/* For certain MIPS architectures, GPR[0] is hardwired to zero. We
should check for it being changed. It is better doing it here,
than within the simulator, since it will help keep the simulator