This commit is contained in:
twinaphex 2015-12-09 15:09:57 +01:00
parent cd6774fa01
commit ae955d5844
5 changed files with 2067 additions and 2130 deletions

View File

@ -1,41 +1,10 @@
/******************************************************************************\
* Authors: Iconoclast *
* Release: 2013.12.04 *
* License: CC0 Public Domain Dedication *
* *
* To the extent possible under law, the author(s) have dedicated all copyright *
* and related and neighboring rights to this software to the public domain *
* worldwide. This software is distributed without any warranty. *
* *
* You should have received a copy of the CC0 Public Domain Dedication along *
* with this software. *
* If not, see <http://creativecommons.org/publicdomain/zero/1.0/>. *
\******************************************************************************/
#ifndef _CXD4_CONFIG_H
#define _CXD4_CONFIG_H
#include <stdint.h>
extern unsigned char conf[32];
#define MINIMUM_MESSAGE_PRIORITY 1
#define EXTERN_COMMAND_LIST_GBI
#define EXTERN_COMMAND_LIST_ABI
#define SEMAPHORE_LOCK_CORRECTIONS
#define WAIT_FOR_CPU_HOST
#define EMULATE_STATIC_PC
#ifdef EMULATE_STATIC_PC
#define CONTINUE {continue;}
#define JUMP {goto BRANCH;}
#else
#define CONTINUE {break;}
#define JUMP {break;}
#endif
#if (0)
#define SP_EXECUTE_LOG
#define VU_EMULATE_SCALAR_ACCUMULATOR_READ
#endif
/*
* The config file used to be a 32-byte EEPROM with binary settings storage.
* It was found necessary for user and contributor convenience to replace.
@ -47,33 +16,5 @@ extern unsigned char conf[32];
#define CFG_HLE_AUD (conf[0x01])
#define CFG_HLE_VID (conf[0x02]) /* reserved/unused */
#define CFG_HLE_JPG (conf[0x03]) /* unused */
/*
* Most of the point behind this config system is to let users use HLE video
* or audio plug-ins. The other task types are used less than 1% of the time
* and only in a few games. They require simulation from within the RSP
* internally, which I have no intention to ever support. Some good research
* on a few of these special task types was done by Hacktarux in the MUPEN64
* HLE RSP plug-in, so consider using that instead for complete HLE.
*/
/*
* Schedule binary dump exports to the DllConfig schedule delay queue.
*/
#define CFG_QUEUE_E_DRAM (*(int *)(conf + 0x04))
#define CFG_QUEUE_E_DMEM (*(int *)(conf + 0x08))
#define CFG_QUEUE_E_IMEM (*(int *)(conf + 0x0C))
/*
* Note: This never actually made it into the configuration system.
* Instead, DMEM and IMEM are always exported on every call to DllConfig().
*/
/*
* Special switches.
* (generally for correcting RSP clock behavior on Project64 2.x)
* Also includes RSP register states debugger.
*/
#define CFG_WAIT_FOR_CPU_HOST (*(int *)(conf + 0x10))
#define CFG_MEND_SEMAPHORE_LOCK (*(int *)(conf + 0x14))
#define CFG_TRACE_RSP_REGISTERS (*(int *)(conf + 0x18))
#endif

View File

@ -1,452 +0,0 @@
/******************************************************************************\
* Authors: Iconoclast *
* Release: 2013.12.11 *
* License: CC0 Public Domain Dedication *
* *
* To the extent possible under law, the author(s) have dedicated all copyright *
* and related and neighboring rights to this software to the public domain *
* worldwide. This software is distributed without any warranty. *
* *
* You should have received a copy of the CC0 Public Domain Dedication along *
* with this software. *
* If not, see <http://creativecommons.org/publicdomain/zero/1.0/>. *
\******************************************************************************/
#include "Rsp_#1.1.h"
#include "rsp.h"
#include "su.h"
#include "vu/vu.h"
#include "matrix.h"
#define FIT_IMEM(PC) (PC & 0xFFF & 0xFFC)
NOINLINE void run_task(void)
{
register uint32_t PC;
register unsigned int i;
#ifdef WAIT_FOR_CPU_HOST
for (i = 0; i < 32; i++)
MFC0_count[i] = 0;
#endif
PC = FIT_IMEM(*RSP.SP_PC_REG);
while ((*RSP.SP_STATUS_REG & 0x00000001) == 0x00000000)
{
register uint32_t inst;
register int rd, rs, rt;
register int base;
inst = *(uint32_t *)(RSP.IMEM + FIT_IMEM(PC));
#ifdef EMULATE_STATIC_PC
PC = (PC + 0x004);
EX:
#endif
#ifdef SP_EXECUTE_LOG
step_SP_commands(inst);
#endif
if (inst >> 25 == 0x25) /* is a VU instruction */
{
const int opcode = inst % 64; /* inst.R.func */
const int vd = (inst & 0x000007FF) >> 6; /* inst.R.sa */
const int vs = (unsigned short)(inst) >> 11; /* inst.R.rd */
const int vt = (inst >> 16) & 31; /* inst.R.rt */
const int e = (inst >> 21) & 0xF; /* rs & 0xF */
COP2_C2[opcode](vd, vs, vt, e);
}
else
{
const int op = inst >> 26;
const int element = (inst & 0x000007FF) >> 7;
switch (op)
{
int16_t offset;
register uint32_t addr;
case 000: /* SPECIAL */
#if (1u >> 1 == 0)
rd = (inst & 0x0000FFFFu) >> 11;
/* rs = inst >> 21; // Primary op is 0, so we don't need &= 31. */
#else
rd = (inst >> 11) % 32;
/* rs = (inst >> 21) % 32; */
#endif
rt = (inst >> 16) % (1 << 5);
switch (inst % 64)
{
case 000: /* SLL */
SR[rd] = SR[rt] << MASK_SA(inst >> 6);
SR[0] = 0x00000000;
CONTINUE
case 002: /* SRL */
SR[rd] = (unsigned)(SR[rt]) >> MASK_SA(inst >> 6);
SR[0] = 0x00000000;
CONTINUE
case 003: /* SRA */
SR[rd] = (signed)(SR[rt]) >> MASK_SA(inst >> 6);
SR[0] = 0x00000000;
CONTINUE
case 004: /* SLLV */
SR[rd] = SR[rt] << MASK_SA(SR[rs = inst >> 21]);
SR[0] = 0x00000000;
CONTINUE
case 006: /* SRLV */
SR[rd] = (unsigned)(SR[rt]) >> MASK_SA(SR[rs = inst >> 21]);
SR[0] = 0x00000000;
CONTINUE
case 007: /* SRAV */
SR[rd] = (signed)(SR[rt]) >> MASK_SA(SR[rs = inst >> 21]);
SR[0] = 0x00000000;
CONTINUE
case 011: /* JALR */
SR[rd] = (PC + LINK_OFF) & 0x00000FFC;
SR[0] = 0x00000000;
case 010: /* JR */
set_PC(SR[rs = inst >> 21]);
JUMP
case 015: /* BREAK */
*RSP.SP_STATUS_REG |= 0x00000003; /* BROKE | HALT */
if (*RSP.SP_STATUS_REG & 0x00000040)
{ /* SP_STATUS_INTR_BREAK */
*RSP.MI_INTR_REG |= 0x00000001;
RSP.CheckInterrupts();
}
CONTINUE
case 040: /* ADD */
case 041: /* ADDU */
rs = inst >> 21;
SR[rd] = SR[rs] + SR[rt];
SR[0] = 0x00000000; /* needed for Rareware ucodes */
CONTINUE
case 042: /* SUB */
case 043: /* SUBU */
rs = inst >> 21;
SR[rd] = SR[rs] - SR[rt];
SR[0] = 0x00000000;
CONTINUE
case 044: /* AND */
rs = inst >> 21;
SR[rd] = SR[rs] & SR[rt];
SR[0] = 0x00000000; /* needed for Rareware ucodes */
CONTINUE
case 045: /* OR */
rs = inst >> 21;
SR[rd] = SR[rs] | SR[rt];
SR[0] = 0x00000000;
CONTINUE
case 046: /* XOR */
rs = inst >> 21;
SR[rd] = SR[rs] ^ SR[rt];
SR[0] = 0x00000000;
CONTINUE
case 047: /* NOR */
rs = inst >> 21;
SR[rd] = ~(SR[rs] | SR[rt]);
SR[0] = 0x00000000;
CONTINUE
case 052: /* SLT */
rs = inst >> 21;
SR[rd] = ((signed)(SR[rs]) < (signed)(SR[rt]));
SR[0] = 0x00000000;
CONTINUE
case 053: /* SLTU */
rs = inst >> 21;
SR[rd] = ((unsigned)(SR[rs]) < (unsigned)(SR[rt]));
SR[0] = 0x00000000;
CONTINUE
default:
res_S();
CONTINUE
}
CONTINUE
case 001: /* REGIMM */
rs = (inst >> 21) & 31;
rt = (inst >> 16) & 31;
switch (rt)
{
case 020: /* BLTZAL */
SR[31] = (PC + LINK_OFF) & 0x00000FFC;
case 000: /* BLTZ */
if (!(SR[rs] < 0))
CONTINUE
set_PC(PC + 4*inst + SLOT_OFF);
JUMP
case 021: /* BGEZAL */
SR[31] = (PC + LINK_OFF) & 0x00000FFC;
case 001: /* BGEZ */
if (!(SR[rs] >= 0))
CONTINUE
set_PC(PC + 4*inst + SLOT_OFF);
JUMP
default:
res_S();
CONTINUE
}
CONTINUE
case 003: /* JAL */
SR[31] = (PC + LINK_OFF) & 0x00000FFC;
case 002: /* J */
set_PC(4*inst);
JUMP
case 004: /* BEQ */
rs = (inst >> 21) & 31;
rt = (inst >> 16) & 31;
if (!(SR[rs] == SR[rt]))
CONTINUE
set_PC(PC + 4*inst + SLOT_OFF);
JUMP
case 005: /* BNE */
rs = (inst >> 21) & 31;
rt = (inst >> 16) & 31;
if (!(SR[rs] != SR[rt]))
CONTINUE
set_PC(PC + 4*inst + SLOT_OFF);
JUMP
case 006: /* BLEZ */
if (!((signed)SR[rs = (inst >> 21) & 31] <= 0x00000000))
CONTINUE
set_PC(PC + 4*inst + SLOT_OFF);
JUMP
case 007: /* BGTZ */
if (!((signed)SR[rs = (inst >> 21) & 31] > 0x00000000))
CONTINUE
set_PC(PC + 4*inst + SLOT_OFF);
JUMP
case 010: /* ADDI */
case 011: /* ADDIU */
rs = (inst >> 21) & 31;
rt = (inst >> 16) & 31;
SR[rt] = SR[rs] + (signed short)(inst);
SR[0] = 0x00000000;
CONTINUE
case 012: /* SLTI */
rs = (inst >> 21) & 31;
rt = (inst >> 16) & 31;
SR[rt] = ((signed)(SR[rs]) < (signed short)(inst));
SR[0] = 0x00000000;
CONTINUE
case 013: /* SLTIU */
rs = (inst >> 21) & 31;
rt = (inst >> 16) & 31;
SR[rt] = ((unsigned)(SR[rs]) < (unsigned short)(inst));
SR[0] = 0x00000000;
CONTINUE
case 014: /* ANDI */
rs = (inst >> 21) & 31;
rt = (inst >> 16) & 31;
SR[rt] = SR[rs] & (unsigned short)(inst);
SR[0] = 0x00000000;
CONTINUE
case 015: /* ORI */
rs = (inst >> 21) & 31;
rt = (inst >> 16) & 31;
SR[rt] = SR[rs] | (unsigned short)(inst);
SR[0] = 0x00000000;
CONTINUE
case 016: /* XORI */
rs = (inst >> 21) & 31;
rt = (inst >> 16) & 31;
SR[rt] = SR[rs] ^ (unsigned short)(inst);
SR[0] = 0x00000000;
CONTINUE
case 017: /* LUI */
SR[rt = (inst >> 16) & 31] = inst << 16;
SR[0] = 0x00000000;
CONTINUE
case 020: /* COP0 */
rd = (inst & 0x0000F800u) >> 11;
rs = (inst >> 21) & 31;
rt = (inst >> 16) & 31;
switch (rs)
{
case 000: /* MFC0 */
MFC0(rt, rd & 0xF);
CONTINUE
case 004: /* MTC0 */
MTC0[rd & 0xF](rt);
CONTINUE
default:
res_S();
CONTINUE
}
CONTINUE
case 022: /* COP2 */
rd = (inst & 0x0000F800u) >> 11;
rs = (inst >> 21) & 31;
rt = (inst >> 16) & 31;
switch (rs)
{
case 000: /* MFC2 */
MFC2(rt, rd, element);
CONTINUE
case 002: /* CFC2 */
CFC2(rt, rd);
CONTINUE
case 004: /* MTC2 */
MTC2(rt, rd, element);
CONTINUE
case 006: /* CTC2 */
CTC2(rt, rd);
CONTINUE
default:
res_S();
CONTINUE
}
CONTINUE
case 040: /* LB */
rt = (inst >> 16) % (1 << 5);
offset = (signed short)(inst);
addr = (SR[base = (inst >> 21) & 31] + offset) & 0x00000FFF;
SR[rt] = RSP.DMEM[BES(addr)];
SR[rt] = (signed char)(SR[rt]);
SR[0] = 0x00000000;
CONTINUE
case 041: /* LH */
rt = (inst >> 16) % (1 << 5);
offset = (signed short)(inst);
addr = (SR[base = (inst >> 21) & 31] + offset) & 0x00000FFF;
if (addr%0x004 == 0x003)
{
SR_B(rt, 2) = RSP.DMEM[addr - BES(0x000)];
addr = (addr + 0x00000001) & 0x00000FFF;
SR_B(rt, 3) = RSP.DMEM[addr + BES(0x000)];
SR[rt] = (signed short)(SR[rt]);
}
else
{
addr -= HES(0x000)*(addr%0x004 - 1);
SR[rt] = *(signed short *)(RSP.DMEM + addr);
}
SR[0] = 0x00000000;
CONTINUE
case 043: /* LW */
rt = (inst >> 16) % (1 << 5);
offset = (signed short)(inst);
addr = (SR[base = (inst >> 21) & 31] + offset) & 0x00000FFF;
if (addr%0x004 != 0x000)
ULW(rt, addr);
else
SR[rt] = *(int32_t *)(RSP.DMEM + addr);
SR[0] = 0x00000000;
CONTINUE
case 044: /* LBU */
rt = (inst >> 16) % (1 << 5);
offset = (signed short)(inst);
addr = (SR[base = (inst >> 21) & 31] + offset) & 0x00000FFF;
SR[rt] = RSP.DMEM[BES(addr)];
SR[rt] = (unsigned char)(SR[rt]);
SR[0] = 0x00000000;
CONTINUE
case 045: /* LHU */
rt = (inst >> 16) % (1 << 5);
offset = (signed short)(inst);
addr = (SR[base = (inst >> 21) & 31] + offset) & 0x00000FFF;
if (addr%0x004 == 0x003)
{
SR_B(rt, 2) = RSP.DMEM[addr - BES(0x000)];
addr = (addr + 0x00000001) & 0x00000FFF;
SR_B(rt, 3) = RSP.DMEM[addr + BES(0x000)];
SR[rt] = (unsigned short)(SR[rt]);
}
else
{
addr -= HES(0x000)*(addr%0x004 - 1);
SR[rt] = *(unsigned short *)(RSP.DMEM + addr);
}
SR[0] = 0x00000000;
CONTINUE
case 050: /* SB */
rt = (inst >> 16) % (1 << 5);
offset = (signed short)(inst);
addr = (SR[base = (inst >> 21) & 31] + offset) & 0x00000FFF;
RSP.DMEM[BES(addr)] = (unsigned char)(SR[rt]);
CONTINUE
case 051: /* SH */
rt = (inst >> 16) % (1 << 5);
offset = (signed short)(inst);
addr = (SR[base = (inst >> 21) & 31] + offset) & 0x00000FFF;
if (addr%0x004 == 0x003)
{
RSP.DMEM[addr - BES(0x000)] = SR_B(rt, 2);
addr = (addr + 0x00000001) & 0x00000FFF;
RSP.DMEM[addr + BES(0x000)] = SR_B(rt, 3);
CONTINUE
}
addr -= HES(0x000)*(addr%0x004 - 1);
*(short *)(RSP.DMEM + addr) = (short)(SR[rt]);
CONTINUE
case 053: /* SW */
rt = (inst >> 16) % (1 << 5);
offset = (signed short)(inst);
addr = (SR[base = (inst >> 21) & 31] + offset) & 0x00000FFF;
if (addr%0x004 != 0x000)
USW(rt, addr);
else
*(int32_t *)(RSP.DMEM + addr) = SR[rt];
CONTINUE
case 062: /* LWC2 */
rt = (inst >> 16) % (1 << 5);
offset = (signed short)(inst & 0x0000FFFFu);
#if defined(ARCH_MIN_SSE2)
offset <<= 5 + 4; /* safe on x86, skips 5-bit rd, 4-bit element */
offset >>= 5 + 4;
#else
offset = SE(offset, 6);
#endif
base = (inst >> 21) & 31;
LWC2_op[rd = (inst & 0xF800u) >> 11](rt, element, offset, base);
CONTINUE
case 072: /* SWC2 */
rt = (inst >> 16) % (1 << 5);
offset = (signed short)(inst & 0x0000FFFFu);
#if defined(ARCH_MIN_SSE2)
offset <<= 5 + 4; /* safe on x86, skips 5-bit rd, 4-bit element */
offset >>= 5 + 4;
#else
offset = SE(offset, 6);
#endif
base = (inst >> 21) & 31;
SWC2_op[rd = (inst & 0xF800u) >> 11](rt, element, offset, base);
CONTINUE
default:
res_S();
CONTINUE
}
}
#ifndef EMULATE_STATIC_PC
if (stage == 2) /* branch phase of scheduler */
{
stage = 0*stage;
PC = temp_PC & 0x00000FFC;
*RSP.SP_PC_REG = temp_PC;
}
else
{
stage = 2*stage; /* next IW in branch delay slot? */
PC = (PC + 0x004) & 0xFFC;
*RSP.SP_PC_REG = 0x04001000 + PC;
}
continue;
#else
continue;
BRANCH:
inst = *(uint32_t *)(RSP.IMEM + FIT_IMEM(PC));
PC = temp_PC & 0x00000FFC;
goto EX;
#endif
}
*RSP.SP_PC_REG = 0x04001000 | FIT_IMEM(PC);
if (*RSP.SP_STATUS_REG & 0x00000002) /* normal exit, from executing BREAK */
return;
else if (*RSP.MI_INTR_REG & 0x00000001) /* interrupt set by MTC0 to break */
RSP.CheckInterrupts();
else if (*RSP.SP_SEMAPHORE_REG != 0x00000000) /* semaphore lock fixes */
{}
#ifndef WAIT_FOR_CPU_HOST
else /* ??? unknown, possibly external intervention from CPU memory map */
return; /* SP_SET_HALT */
#endif
*RSP.SP_STATUS_REG &= ~0x00000001; /* CPU restarts with the correct SIGs. */
}

File diff suppressed because it is too large Load Diff

View File

@ -14,8 +14,6 @@
#ifndef _RSP_H_
#define _RSP_H_
#include <stdint.h>
#include "Rsp_#1.1.h"
RSP_INFO RSP;
#ifdef _MSC_VER
@ -73,11 +71,4 @@ static short MFC0_count[32];
/* Keep one C0 MF status read count for each scalar register. */
#endif
#include "su.h"
#include "vu/vu.h"
/* Allocate the RSP CPU loop to its own functional space. */
NOINLINE extern void run_task(void);
#include "execute.h"
#endif

File diff suppressed because it is too large Load Diff