[RSP] Preliminary RSP recompiler, with all vector ops stubbed out to C functions for now. [Harmony]

This commit is contained in:
Ryan Holtz 2009-12-16 23:26:58 +00:00
parent 6a6b1eb094
commit f9045e7268
10 changed files with 5746 additions and 453 deletions

3
.gitattributes vendored
View File

@ -332,6 +332,9 @@ src/emu/cpu/powerpc/ppcfe.h svneol=native#text/plain
src/emu/cpu/rsp/rsp.c svneol=native#text/plain
src/emu/cpu/rsp/rsp.h svneol=native#text/plain
src/emu/cpu/rsp/rsp_dasm.c svneol=native#text/plain
src/emu/cpu/rsp/rspdrc.c svneol=native#text/plain
src/emu/cpu/rsp/rspfe.c svneol=native#text/plain
src/emu/cpu/rsp/rspfe.h svneol=native#text/plain
src/emu/cpu/s2650/2650dasm.c svneol=native#text/plain
src/emu/cpu/s2650/s2650.c svneol=native#text/plain
src/emu/cpu/s2650/s2650.h svneol=native#text/plain

View File

@ -805,23 +805,23 @@ DASMOBJS += $(CPUOBJ)/mips/psxdasm.o
endif
$(CPUOBJ)/mips/r3000.o: $(CPUSRC)/mips/r3000.c \
$(CPUSRC)/mips/r3000.h
$(CPUSRC)/mips/r3000.h
$(CPUOBJ)/mips/mips3com.o: $(CPUSRC)/mips/mips3.h \
$(CPUSRC)/mips/mips3com.h
$(CPUSRC)/mips/mips3com.h
$(CPUOBJ)/mips/mips3fe.o: $(CPUSRC)/mips/mips3.h \
$(CPUSRC)/mips/mips3com.h \
$(CPUSRC)/mips/mips3fe.h
$(CPUSRC)/mips/mips3com.h \
$(CPUSRC)/mips/mips3fe.h
$(CPUOBJ)/mips/mips3drc.o: $(CPUSRC)/mips/mips3drc.c \
$(CPUSRC)/mips/mips3.h \
$(CPUSRC)/mips/mips3com.h \
$(CPUSRC)/mips/mips3fe.h \
$(DRCDEPS)
$(CPUOBJ)/mips/mips3drc.o: $(CPUSRC)/mips/mips3drc.c \
$(CPUSRC)/mips/mips3.h \
$(CPUSRC)/mips/mips3com.h \
$(CPUSRC)/mips/mips3fe.h \
$(DRCDEPS)
$(CPUOBJ)/mips/psx.o: $(CPUSRC)/mips/psx.c \
$(CPUSRC)/mips/psx.h
$(CPUSRC)/mips/psx.h
@ -1191,13 +1191,17 @@ $(CPUOBJ)/minx/minx.o: $(CPUSRC)/minx/minx.c \
ifneq ($(filter RSP,$(CPUS)),)
OBJDIRS += $(CPUOBJ)/rsp
CPUOBJS += $(CPUOBJ)/rsp/rsp.o
CPUOBJS += $(CPUOBJ)/rsp/rspdrc.o $(CPUOBJ)/rsp/rspfe.o $(DRCOBJ)
DASMOBJS += $(CPUOBJ)/rsp/rsp_dasm.o
endif
$(CPUOBJ)/rsp/rsp.o: $(CPUSRC)/rsp/rsp.c \
$(CPUSRC)/rsp/rsp.h
$(CPUOBJ)/rsp/rspdrc.o: $(CPUSRC)/rsp/rspdrc.c \
$(CPUSRC)/rsp/rsp.h \
$(CPUSRC)/rsp/rspfe.h \
$(DRCDEPS)
$(CPUOBJ)/rsp/rspfe.o: $(CPUSRC)/rsp/rspfe.c \
$(CPUSRC)/rsp/rspfe.h
#-------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,27 @@
/***************************************************************************
mips3.h
Interface file for the universal machine language-based
Reality Signal Processor (RSP) emulator.
Copyright the MESS etam
Released for general non-commercial use under the MAME license
Visit http://mamedev.org for licensing and usage restrictions.
***************************************************************************/
#pragma once
#ifndef __RSP_H__
#define __RSP_H__
typedef void (*rsp_set_status_func)(const device_config *device, UINT32 status);
#include "cpuintrf.h"
typedef struct _rsp_config rsp_config;
struct _rsp_config
{
read32_space_func dp_reg_r;
write32_space_func dp_reg_w;
read32_space_func sp_reg_r;
write32_space_func sp_reg_w;
rsp_set_status_func sp_set_status;
};
/***************************************************************************
REGISTER ENUMERATION
***************************************************************************/
enum
{
@ -55,6 +63,65 @@ enum
RSP_STEPCNT,
};
/***************************************************************************
STRUCTURES
***************************************************************************/
typedef void (*rsp_set_status_func)(const device_config *device, UINT32 status);
typedef struct _rsp_config rsp_config;
struct _rsp_config
{
read32_space_func dp_reg_r;
write32_space_func dp_reg_w;
read32_space_func sp_reg_r;
write32_space_func sp_reg_w;
rsp_set_status_func sp_set_status;
};
/***************************************************************************
PUBLIC FUNCTIONS
***************************************************************************/
void rspdrc_flush_drc_cache(const device_config *device);
void rspdrc_set_options(const device_config *device, UINT32 options);
void rspdrc_add_imem(const device_config *device, void *base);
void rspdrc_add_dmem(const device_config *device, void *base);
/***************************************************************************
HELPER MACROS
***************************************************************************/
#define REG_LO 32
#define REG_HI 33
#define RSREG ((op >> 21) & 31)
#define RTREG ((op >> 16) & 31)
#define RDREG ((op >> 11) & 31)
#define SHIFT ((op >> 6) & 31)
#define RSVAL (rsp->r[RSREG])
#define RTVAL (rsp->r[RTREG])
#define RDVAL (rsp->r[RDREG])
#define FRREG ((op >> 21) & 31)
#define FTREG ((op >> 16) & 31)
#define FSREG ((op >> 11) & 31)
#define FDREG ((op >> 6) & 31)
#define IS_SINGLE(o) (((o) & (1 << 21)) == 0)
#define IS_DOUBLE(o) (((o) & (1 << 21)) != 0)
#define IS_FLOAT(o) (((o) & (1 << 23)) == 0)
#define IS_INTEGRAL(o) (((o) & (1 << 23)) != 0)
#define SIMMVAL ((INT16)op)
#define UIMMVAL ((UINT16)op)
#define LIMMVAL (op & 0x03ffffff)
#define RSP_STATUS_HALT 0x0001
#define RSP_STATUS_BROKE 0x0002
#define RSP_STATUS_DMABUSY 0x0004
@ -71,6 +138,75 @@ enum
#define RSP_STATUS_SIGNAL6 0x2000
#define RSP_STATUS_SIGNAL7 0x4000
#define RSPDRC_STRICT_VERIFY 0x0001 /* verify all instructions */
typedef struct
{
union
{
UINT8 b[16];
UINT16 s[8];
UINT32 l[4];
UINT64 d[2];
};
} VECTOR_REG;
typedef struct
{
union
{
INT64 l;
#ifdef LSB_FIRST
struct
{
INT16 z;
INT16 low;
INT16 mid;
INT16 high;
} h;
#else
struct
{
INT16 high;
INT16 mid;
INT16 low;
INT16 z;
} h;
#endif
};
} ACCUMULATOR;
typedef struct _rspimp_state rspimp_state;
typedef struct _rsp_state rsp_state;
struct _rsp_state
{
const rsp_config *config;
FILE *exec_output;
UINT32 pc;
UINT32 r[35];
VECTOR_REG v[32];
UINT16 flag[4];
UINT32 sr;
UINT32 step_count;
ACCUMULATOR accum[8];
INT32 square_root_res;
INT32 square_root_high;
INT32 reciprocal_res;
INT32 reciprocal_high;
UINT32 ppc;
UINT32 nextpc;
cpu_irq_callback irq_callback;
const device_config *device;
const address_space *program;
int icount;
rspimp_state* impstate;
};
CPU_GET_INFO( rsp );
#define CPU_RSP CPU_GET_INFO_NAME( rsp )

View File

@ -348,6 +348,7 @@ offs_t rsp_dasm_one(char *buffer, offs_t pc, UINT32 op)
CPU_DISASSEMBLE( rsp )
{
UINT32 op = LITTLE_ENDIANIZE_INT32(*(UINT32 *)opram);
UINT32 op = *(UINT32 *)opram;
op = BIG_ENDIANIZE_INT32(op);
return rsp_dasm_one(buffer, pc, op);
}

4850
src/emu/cpu/rsp/rspdrc.c Normal file

File diff suppressed because it is too large Load Diff

308
src/emu/cpu/rsp/rspfe.c Normal file
View File

@ -0,0 +1,308 @@
/***************************************************************************
rspfe.c
Front-end for RSP recompiler
Copyright the MESS team
Released for general non-commercial use under the MAME license
Visit http://mamedev.org for licensing and usage restrictions.
***************************************************************************/
#include <stddef.h>
#include "cpuintrf.h"
#include "rspfe.h"
#include "rsp.h"
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
static int describe_instruction_special(rsp_state *rsp, UINT32 op, opcode_desc *desc);
static int describe_instruction_regimm(rsp_state *rsp, UINT32 op, opcode_desc *desc);
static int describe_instruction_cop0(rsp_state *rsp, UINT32 op, opcode_desc *desc);
static int describe_instruction_cop2(rsp_state *rsp, UINT32 op, opcode_desc *desc);
/***************************************************************************
INSTRUCTION PARSERS
***************************************************************************/
/*-------------------------------------------------
describe_instruction - build a description
of a single instruction
-------------------------------------------------*/
int rspfe_describe(void *param, opcode_desc *desc, const opcode_desc *prev)
{
rsp_state *rsp = (rsp_state *)param;
UINT32 op, opswitch;
/* fetch the opcode */
op = desc->opptr.l[0] = memory_decrypted_read_dword(rsp->program, desc->physpc | 0x1000);
/* all instructions are 4 bytes and default to a single cycle each */
desc->length = 4;
desc->cycles = 1;
/* parse the instruction */
opswitch = op >> 26;
switch (opswitch)
{
case 0x00: /* SPECIAL */
return describe_instruction_special(rsp, op, desc);
case 0x01: /* REGIMM */
return describe_instruction_regimm(rsp, op, desc);
case 0x10: /* COP0 */
return describe_instruction_cop0(rsp, op, desc);
case 0x12: /* COP2 */
return describe_instruction_cop2(rsp, op, desc);
case 0x02: /* J */
desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
desc->targetpc = LIMMVAL << 2;
desc->delayslots = 1;
return TRUE;
case 0x03: /* JAL */
desc->regout[0] |= REGFLAG_R(31);
desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
desc->targetpc = LIMMVAL << 2;
desc->delayslots = 1;
return TRUE;
case 0x04: /* BEQ */
case 0x05: /* BNE */
if ((opswitch == 0x04 || opswitch == 0x14) && RSREG == RTREG)
desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
else
{
desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
}
desc->targetpc = (desc->pc + 4 + (SIMMVAL << 2)) | 0x04001000;
desc->delayslots = 1;
desc->skipslots = (opswitch & 0x10) ? 1 : 0;
return TRUE;
case 0x06: /* BLEZ */
case 0x07: /* BGTZ */
if ((opswitch == 0x06 || opswitch == 0x16) && RSREG == 0)
desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
else
{
desc->regin[0] |= REGFLAG_R(RSREG);
desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
}
desc->targetpc = (desc->pc + 4 + (SIMMVAL << 2)) | 0x04001000;
desc->delayslots = 1;
desc->skipslots = (opswitch & 0x10) ? 1 : 0;
return TRUE;
case 0x08: /* ADDI */
desc->regin[0] |= REGFLAG_R(RSREG);
desc->regout[0] |= REGFLAG_R(RTREG);
return TRUE;
case 0x09: /* ADDIU */
case 0x0a: /* SLTI */
case 0x0b: /* SLTIU */
case 0x0c: /* ANDI */
case 0x0d: /* ORI */
case 0x0e: /* XORI */
desc->regin[0] |= REGFLAG_R(RSREG);
desc->regout[0] |= REGFLAG_R(RTREG);
return TRUE;
case 0x0f: /* LUI */
desc->regout[0] |= REGFLAG_R(RTREG);
return TRUE;
case 0x20: /* LB */
case 0x21: /* LH */
case 0x23: /* LW */
case 0x24: /* LBU */
case 0x25: /* LHU */
case 0x27: /* LWU */
desc->regin[0] |= REGFLAG_R(RSREG);
desc->regout[0] |= REGFLAG_R(RTREG);
desc->flags |= OPFLAG_READS_MEMORY;
return TRUE;
case 0x28: /* SB */
case 0x29: /* SH */
case 0x2b: /* SW */
desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
desc->flags |= OPFLAG_WRITES_MEMORY;
return TRUE;
case 0x32: /* LWC2 */
desc->regin[0] |= REGFLAG_R(RSREG);
desc->flags |= OPFLAG_READS_MEMORY;
return TRUE;
case 0x3a: /* SWC2 */
desc->regin[0] |= REGFLAG_R(RSREG);
desc->flags |= OPFLAG_WRITES_MEMORY;
return TRUE;
}
return FALSE;
}
/*-------------------------------------------------
describe_instruction_special - build a
description of a single instruction in the
'special' group
-------------------------------------------------*/
static int describe_instruction_special(rsp_state *rsp, UINT32 op, opcode_desc *desc)
{
switch (op & 63)
{
case 0x00: /* SLL */
case 0x02: /* SRL */
case 0x03: /* SRA */
desc->regin[0] |= REGFLAG_R(RTREG);
desc->regout[0] |= REGFLAG_R(RDREG);
return TRUE;
case 0x04: /* SLLV */
case 0x06: /* SRLV */
case 0x07: /* SRAV */
case 0x21: /* ADDU */
case 0x23: /* SUBU */
case 0x24: /* AND */
case 0x25: /* OR */
case 0x26: /* XOR */
case 0x27: /* NOR */
case 0x2a: /* SLT */
case 0x2b: /* SLTU */
desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
desc->regout[0] |= REGFLAG_R(RDREG);
return TRUE;
case 0x20: /* ADD */
case 0x22: /* SUB */
desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
desc->regout[0] |= REGFLAG_R(RDREG);
return TRUE;
case 0x08: /* JR */
desc->regin[0] |= REGFLAG_R(RSREG);
desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
desc->targetpc = BRANCH_TARGET_DYNAMIC;
desc->delayslots = 1;
return TRUE;
case 0x09: /* JALR */
desc->regin[0] |= REGFLAG_R(RSREG);
desc->regout[0] |= REGFLAG_R(RDREG);
desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
desc->targetpc = BRANCH_TARGET_DYNAMIC;
desc->delayslots = 1;
return TRUE;
case 0x0d: /* BREAK */
desc->flags |= OPFLAG_END_SEQUENCE;
desc->targetpc = BRANCH_TARGET_DYNAMIC;
return TRUE;
}
return FALSE;
}
/*-------------------------------------------------
describe_instruction_regimm - build a
description of a single instruction in the
'regimm' group
-------------------------------------------------*/
static int describe_instruction_regimm(rsp_state *rsp, UINT32 op, opcode_desc *desc)
{
switch (RTREG)
{
case 0x00: /* BLTZ */
case 0x01: /* BGEZ */
if (RTREG == 0x01 && RSREG == 0)
desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
else
{
desc->regin[0] |= REGFLAG_R(RSREG);
desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
}
desc->targetpc = (desc->pc + 4 + (SIMMVAL << 2)) | 0x04001000;
desc->delayslots = 1;
desc->skipslots = (RTREG & 0x02) ? 1 : 0;
return TRUE;
case 0x10: /* BLTZAL */
case 0x11: /* BGEZAL */
if (RTREG == 0x11 && RSREG == 0)
desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
else
{
desc->regin[0] |= REGFLAG_R(RSREG);
desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
}
desc->regout[0] |= REGFLAG_R(31);
desc->targetpc = (desc->pc + 4 + (SIMMVAL << 2)) | 0x04001000;
desc->delayslots = 1;
desc->skipslots = (RTREG & 0x02) ? 1 : 0;
return TRUE;
}
return FALSE;
}
/*-------------------------------------------------
describe_instruction_cop0 - build a
description of a single instruction in the
COP0 group
-------------------------------------------------*/
static int describe_instruction_cop0(rsp_state *rsp, UINT32 op, opcode_desc *desc)
{
switch (RSREG)
{
case 0x00: /* MFCz */
desc->regout[0] |= REGFLAG_R(RTREG);
return TRUE;
case 0x04: /* MTCz */
desc->regin[0] |= REGFLAG_R(RTREG);
return TRUE;
}
return FALSE;
}
/*-------------------------------------------------
describe_instruction_cop2 - build a
description of a single instruction in the
COP2 group
-------------------------------------------------*/
static int describe_instruction_cop2(rsp_state *rsp, UINT32 op, opcode_desc *desc)
{
switch (RSREG)
{
case 0x00: /* MFCz */
case 0x02: /* CFCz */
desc->regout[0] |= REGFLAG_R(RTREG);
return TRUE;
case 0x04: /* MTCz */
case 0x06: /* CTCz */
desc->regin[0] |= REGFLAG_R(RTREG);
return TRUE;
}
return FALSE;
}

34
src/emu/cpu/rsp/rspfe.h Normal file
View File

@ -0,0 +1,34 @@
/***************************************************************************
rspfe.h
Front-end for RSP recompiler
Copyright the MESS team
Released for general non-commercial use under the MAME license
Visit http://mamedev.org for licensing and usage restrictions.
***************************************************************************/
#pragma once
#ifndef __RSPFE_H__
#define __RSPFE_H__
#include "cpu/drcfe.h"
/***************************************************************************
CONSTANTS
***************************************************************************/
/* register flags 0 */
#define REGFLAG_R(n) (((n) == 0) ? 0 : (1 << (n)))
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
int rspfe_describe(void *param, opcode_desc *desc, const opcode_desc *prev);
#endif /* __RSPFE_H__ */

View File

@ -698,11 +698,11 @@ WRITE32_HANDLER( n64_sp_reg_w )
//printf( "Setting PC to: %08x\n", 0x04001000 | (data & 0xfff ) );
if( cpu_get_reg(cputag_get_cpu(space->machine, "rsp"), RSP_NEXTPC) != 0xffffffff )
{
cpu_set_reg(cputag_get_cpu(space->machine, "rsp"), RSP_NEXTPC, 0x04001000 | (data & 0xfff));
cpu_set_reg(cputag_get_cpu(space->machine, "rsp"), RSP_NEXTPC, 0x1000 | (data & 0xfff));
}
else
{
cpu_set_reg(cputag_get_cpu(space->machine, "rsp"), RSP_PC, 0x04001000 | (data & 0xfff));
cpu_set_reg(cputag_get_cpu(space->machine, "rsp"), RSP_PC, 0x1000 | (data & 0xfff));
}
break;
@ -1994,8 +1994,13 @@ MACHINE_START( n64 )
{
mips3drc_set_options(cputag_get_cpu(machine, "maincpu"), MIPS3DRC_FASTEST_OPTIONS + MIPS3DRC_STRICT_VERIFY);
/* configure fast RAM regions for DRC */
/* configure fast RAM regions for DRC */
mips3drc_add_fastram(cputag_get_cpu(machine, "maincpu"), 0x00000000, 0x007fffff, FALSE, rdram);
rspdrc_set_options(cputag_get_cpu(machine, "rsp"), 0);
rspdrc_add_imem(cputag_get_cpu(machine, "rsp"), rsp_imem);
rspdrc_add_dmem(cputag_get_cpu(machine, "rsp"), rsp_dmem);
rspdrc_flush_drc_cache(cputag_get_cpu(machine, "rsp"));
}
MACHINE_RESET( n64 )

View File

@ -346,7 +346,7 @@ INLINE void MASK(INT32* S, INT32* T, INT32 cycle)
}
}
INLINE void SHIFT(INT32* S, INT32* T, INT32* maxs, INT32* maxt, UINT32 num)
INLINE void texshift(INT32* S, INT32* T, INT32* maxs, INT32* maxt, UINT32 num)
{
*S = SIGN16(*S);
*T = SIGN16(*T);
@ -1824,7 +1824,7 @@ INLINE void TEXTURE_PIPELINE(COLOR* TEX, INT32 SSS, INT32 SST, UINT32 NOBILINEAR
sss1 = SSS;
sst1 = SST;
SHIFT(&sss1, &sst1, &maxs, &maxt, tilenum);
texshift(&sss1, &sst1, &maxs, &maxt, tilenum);
sss2 = sss1 + 32; sst2 = sst1 + 32;
maxs2 = ((sss2 >> 3) >= tile[tilenum].sh);
@ -1912,7 +1912,7 @@ INLINE void TEXTURE_PIPELINE(COLOR* TEX, INT32 SSS, INT32 SST, UINT32 NOBILINEAR
sss1 = SSS;
sst1 = SST;
SHIFT(&sss1, &sst1, &maxs, &maxt, tilenum);
texshift(&sss1, &sst1, &maxs, &maxt, tilenum);
sss1 = RELATIVE(sss1, tile[tilenum].sl);
sst1 = RELATIVE(sst1, tile[tilenum].tl);
@ -2646,13 +2646,19 @@ INLINE void video_max(UINT32* Pixels, UINT8* max, UINT32* enb)
*enb = 0;
for(i = 0; i < 7; i++)
{
if (Pixels[i] >= Pixels[pos])
pos = i;
}
for(i = 0; i < 7; i++)
{
if (Pixels[i] != Pixels[pos])
if (Pixels[i] > Pixels[pos])
{
*enb += (1 << i);
pos = i;
}
else if (Pixels[i] < Pixels[pos])
{
*enb += (1 << i);
}
else
{
pos = i;
}
}
*max = Pixels[pos];
}