2014-02-15 06:37:59 -03:00
|
|
|
/******************************************************************************\
|
|
|
|
* 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.h"
|
|
|
|
|
|
|
|
#include "su.h"
|
|
|
|
#include "vu/vu.h"
|
|
|
|
|
|
|
|
#define FIT_IMEM(PC) (PC & 0xFFF & 0xFFC)
|
|
|
|
|
|
|
|
NOINLINE void run_task(usf_state_t * state)
|
|
|
|
{
|
|
|
|
register int PC;
|
2014-02-20 22:07:57 -03:00
|
|
|
int wrap_count = 0;
|
2014-04-07 21:42:09 -03:00
|
|
|
#ifdef SP_EXECUTE_LOG
|
|
|
|
int last_PC;
|
|
|
|
#endif
|
2014-02-15 06:37:59 -03:00
|
|
|
|
|
|
|
if (CFG_WAIT_FOR_CPU_HOST != 0)
|
|
|
|
{
|
|
|
|
register int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 32; i++)
|
|
|
|
state->MFC0_count[i] = 0;
|
|
|
|
}
|
2018-07-11 22:01:38 -04:00
|
|
|
PC = FIT_IMEM(SP_PC_REG);
|
|
|
|
while ((SP_STATUS_REG & 0x00000001) == 0x00000000)
|
2014-02-15 06:37:59 -03:00
|
|
|
{
|
|
|
|
register uint32_t inst;
|
|
|
|
|
|
|
|
inst = *(uint32_t *)(state->IMEM + FIT_IMEM(PC));
|
2014-04-07 21:42:09 -03:00
|
|
|
#ifdef SP_EXECUTE_LOG
|
|
|
|
last_PC = PC;
|
|
|
|
#endif
|
2014-02-15 06:37:59 -03:00
|
|
|
#ifdef EMULATE_STATIC_PC
|
|
|
|
PC = (PC + 0x004);
|
2014-02-20 22:07:57 -03:00
|
|
|
if ( FIT_IMEM(PC) == 0 && ++wrap_count == 32 )
|
|
|
|
{
|
|
|
|
message( state, "RSP execution presumably caught in an infinite loop", 3 );
|
|
|
|
break;
|
|
|
|
}
|
2014-02-15 06:37:59 -03:00
|
|
|
EX:
|
|
|
|
#endif
|
|
|
|
#ifdef SP_EXECUTE_LOG
|
2014-04-07 21:42:09 -03:00
|
|
|
step_SP_commands(state, last_PC, inst);
|
2014-02-15 06:37:59 -03:00
|
|
|
#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](state, vd, vs, vt, e);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const int op = inst >> 26;
|
|
|
|
const int rs = inst >> 21; /* &= 31 */
|
|
|
|
const int rt = (inst >> 16) & 31;
|
|
|
|
const int rd = (unsigned short)(inst) >> 11;
|
|
|
|
const int element = (inst & 0x000007FF) >> 7;
|
|
|
|
const int base = (inst >> 21) & 31;
|
|
|
|
|
|
|
|
#if (0)
|
|
|
|
state->SR[0] = 0x00000000; /* already handled on per-instruction basis */
|
|
|
|
#endif
|
|
|
|
switch (op)
|
|
|
|
{
|
|
|
|
signed int offset;
|
|
|
|
register uint32_t addr;
|
|
|
|
|
|
|
|
case 000: /* SPECIAL */
|
|
|
|
switch (inst % 64)
|
|
|
|
{
|
|
|
|
case 000: /* SLL */
|
|
|
|
state->SR[rd] = state->SR[rt] << MASK_SA(inst >> 6);
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 002: /* SRL */
|
|
|
|
state->SR[rd] = (unsigned)(state->SR[rt]) >> MASK_SA(inst >> 6);
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 003: /* SRA */
|
|
|
|
state->SR[rd] = (signed)(state->SR[rt]) >> MASK_SA(inst >> 6);
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 004: /* SLLV */
|
|
|
|
state->SR[rd] = state->SR[rt] << MASK_SA(state->SR[rs]);
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 006: /* SRLV */
|
|
|
|
state->SR[rd] = (unsigned)(state->SR[rt]) >> MASK_SA(state->SR[rs]);
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 007: /* SRAV */
|
|
|
|
state->SR[rd] = (signed)(state->SR[rt]) >> MASK_SA(state->SR[rs]);
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 011: /* JALR */
|
|
|
|
state->SR[rd] = (PC + LINK_OFF) & 0x00000FFC;
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
case 010: /* JR */
|
|
|
|
set_PC(state, state->SR[rs]);
|
|
|
|
JUMP
|
|
|
|
case 015: /* BREAK */
|
2018-07-11 22:01:38 -04:00
|
|
|
SP_STATUS_REG |= 0x00000003; /* BROKE | HALT */
|
|
|
|
if (SP_STATUS_REG & 0x00000040)
|
2014-02-15 06:37:59 -03:00
|
|
|
{ /* SP_STATUS_INTR_BREAK */
|
2018-07-11 22:01:38 -04:00
|
|
|
MI_INTR_REG |= 0x00000001;
|
|
|
|
CheckInterrupts(state);
|
2014-02-15 06:37:59 -03:00
|
|
|
}
|
|
|
|
CONTINUE
|
|
|
|
case 040: /* ADD */
|
|
|
|
case 041: /* ADDU */
|
|
|
|
state->SR[rd] = state->SR[rs] + state->SR[rt];
|
|
|
|
state->SR[0] = 0x00000000; /* needed for Rareware ucodes */
|
|
|
|
CONTINUE
|
|
|
|
case 042: /* SUB */
|
|
|
|
case 043: /* SUBU */
|
|
|
|
state->SR[rd] = state->SR[rs] - state->SR[rt];
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 044: /* AND */
|
|
|
|
state->SR[rd] = state->SR[rs] & state->SR[rt];
|
|
|
|
state->SR[0] = 0x00000000; /* needed for Rareware ucodes */
|
|
|
|
CONTINUE
|
|
|
|
case 045: /* OR */
|
|
|
|
state->SR[rd] = state->SR[rs] | state->SR[rt];
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 046: /* XOR */
|
|
|
|
state->SR[rd] = state->SR[rs] ^ state->SR[rt];
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 047: /* NOR */
|
|
|
|
state->SR[rd] = ~(state->SR[rs] | state->SR[rt]);
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 052: /* SLT */
|
|
|
|
state->SR[rd] = ((signed)(state->SR[rs]) < (signed)(state->SR[rt]));
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 053: /* SLTU */
|
|
|
|
state->SR[rd] = ((unsigned)(state->SR[rs]) < (unsigned)(state->SR[rt]));
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
default:
|
|
|
|
res_S(state);
|
|
|
|
CONTINUE
|
|
|
|
}
|
|
|
|
CONTINUE
|
|
|
|
case 001: /* REGIMM */
|
|
|
|
switch (rt)
|
|
|
|
{
|
|
|
|
case 020: /* BLTZAL */
|
|
|
|
state->SR[31] = (PC + LINK_OFF) & 0x00000FFC;
|
|
|
|
case 000: /* BLTZ */
|
|
|
|
if (!(state->SR[base] < 0))
|
|
|
|
CONTINUE
|
|
|
|
set_PC(state, PC + 4*inst + SLOT_OFF);
|
|
|
|
JUMP
|
|
|
|
case 021: /* BGEZAL */
|
|
|
|
state->SR[31] = (PC + LINK_OFF) & 0x00000FFC;
|
|
|
|
case 001: /* BGEZ */
|
|
|
|
if (!(state->SR[base] >= 0))
|
|
|
|
CONTINUE
|
|
|
|
set_PC(state, PC + 4*inst + SLOT_OFF);
|
|
|
|
JUMP
|
|
|
|
default:
|
|
|
|
res_S(state);
|
|
|
|
CONTINUE
|
|
|
|
}
|
|
|
|
CONTINUE
|
|
|
|
case 003: /* JAL */
|
|
|
|
state->SR[31] = (PC + LINK_OFF) & 0x00000FFC;
|
|
|
|
case 002: /* J */
|
|
|
|
set_PC(state, 4*inst);
|
|
|
|
JUMP
|
|
|
|
case 004: /* BEQ */
|
|
|
|
if (!(state->SR[base] == state->SR[rt]))
|
|
|
|
CONTINUE
|
|
|
|
set_PC(state, PC + 4*inst + SLOT_OFF);
|
|
|
|
JUMP
|
|
|
|
case 005: /* BNE */
|
|
|
|
if (!(state->SR[base] != state->SR[rt]))
|
|
|
|
CONTINUE
|
|
|
|
set_PC(state, PC + 4*inst + SLOT_OFF);
|
|
|
|
JUMP
|
|
|
|
case 006: /* BLEZ */
|
|
|
|
if (!((signed)state->SR[base] <= 0x00000000))
|
|
|
|
CONTINUE
|
|
|
|
set_PC(state, PC + 4*inst + SLOT_OFF);
|
|
|
|
JUMP
|
|
|
|
case 007: /* BGTZ */
|
|
|
|
if (!((signed)state->SR[base] > 0x00000000))
|
|
|
|
CONTINUE
|
|
|
|
set_PC(state, PC + 4*inst + SLOT_OFF);
|
|
|
|
JUMP
|
|
|
|
case 010: /* ADDI */
|
|
|
|
case 011: /* ADDIU */
|
|
|
|
state->SR[rt] = state->SR[base] + (signed short)(inst);
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 012: /* SLTI */
|
|
|
|
state->SR[rt] = ((signed)(state->SR[base]) < (signed short)(inst));
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 013: /* SLTIU */
|
|
|
|
state->SR[rt] = ((unsigned)(state->SR[base]) < (unsigned short)(inst));
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 014: /* ANDI */
|
|
|
|
state->SR[rt] = state->SR[base] & (unsigned short)(inst);
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 015: /* ORI */
|
|
|
|
state->SR[rt] = state->SR[base] | (unsigned short)(inst);
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 016: /* XORI */
|
|
|
|
state->SR[rt] = state->SR[base] ^ (unsigned short)(inst);
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 017: /* LUI */
|
|
|
|
state->SR[rt] = inst << 16;
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 020: /* COP0 */
|
|
|
|
switch (base)
|
|
|
|
{
|
|
|
|
case 000: /* MFC0 */
|
|
|
|
MFC0(state, rt, rd & 0xF);
|
|
|
|
CONTINUE
|
|
|
|
case 004: /* MTC0 */
|
|
|
|
MTC0[rd & 0xF](state, rt);
|
|
|
|
CONTINUE
|
|
|
|
default:
|
|
|
|
res_S(state);
|
|
|
|
CONTINUE
|
|
|
|
}
|
|
|
|
CONTINUE
|
|
|
|
case 022: /* COP2 */
|
|
|
|
switch (base)
|
|
|
|
{
|
|
|
|
case 000: /* MFC2 */
|
|
|
|
MFC2(state, rt, rd, element);
|
|
|
|
CONTINUE
|
|
|
|
case 002: /* CFC2 */
|
|
|
|
CFC2(state, rt, rd);
|
|
|
|
CONTINUE
|
|
|
|
case 004: /* MTC2 */
|
|
|
|
MTC2(state, rt, rd, element);
|
|
|
|
CONTINUE
|
|
|
|
case 006: /* CTC2 */
|
|
|
|
CTC2(state, rt, rd);
|
|
|
|
CONTINUE
|
|
|
|
default:
|
|
|
|
res_S(state);
|
|
|
|
CONTINUE
|
|
|
|
}
|
|
|
|
CONTINUE
|
|
|
|
case 040: /* LB */
|
|
|
|
offset = (signed short)(inst);
|
|
|
|
addr = (state->SR[base] + offset) & 0x00000FFF;
|
|
|
|
state->SR[rt] = state->DMEM[BES(addr)];
|
|
|
|
state->SR[rt] = (signed char)(state->SR[rt]);
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 041: /* LH */
|
|
|
|
offset = (signed short)(inst);
|
|
|
|
addr = (state->SR[base] + offset) & 0x00000FFF;
|
|
|
|
if (addr%0x004 == 0x003)
|
|
|
|
{
|
|
|
|
SR_B(rt, 2) = state->DMEM[addr - BES(0x000)];
|
|
|
|
addr = (addr + 0x00000001) & 0x00000FFF;
|
|
|
|
SR_B(rt, 3) = state->DMEM[addr + BES(0x000)];
|
|
|
|
state->SR[rt] = (signed short)(state->SR[rt]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
addr -= HES(0x000)*(addr%0x004 - 1);
|
|
|
|
state->SR[rt] = *(signed short *)(state->DMEM + addr);
|
|
|
|
}
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 043: /* LW */
|
|
|
|
offset = (signed short)(inst);
|
|
|
|
addr = (state->SR[base] + offset) & 0x00000FFF;
|
|
|
|
if (addr%0x004 != 0x000)
|
|
|
|
ULW(state, rt, addr);
|
|
|
|
else
|
|
|
|
state->SR[rt] = *(int32_t *)(state->DMEM + addr);
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 044: /* LBU */
|
|
|
|
offset = (signed short)(inst);
|
|
|
|
addr = (state->SR[base] + offset) & 0x00000FFF;
|
|
|
|
state->SR[rt] = state->DMEM[BES(addr)];
|
|
|
|
state->SR[rt] = (unsigned char)(state->SR[rt]);
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 045: /* LHU */
|
|
|
|
offset = (signed short)(inst);
|
|
|
|
addr = (state->SR[base] + offset) & 0x00000FFF;
|
|
|
|
if (addr%0x004 == 0x003)
|
|
|
|
{
|
|
|
|
SR_B(rt, 2) = state->DMEM[addr - BES(0x000)];
|
|
|
|
addr = (addr + 0x00000001) & 0x00000FFF;
|
|
|
|
SR_B(rt, 3) = state->DMEM[addr + BES(0x000)];
|
|
|
|
state->SR[rt] = (unsigned short)(state->SR[rt]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
addr -= HES(0x000)*(addr%0x004 - 1);
|
|
|
|
state->SR[rt] = *(unsigned short *)(state->DMEM + addr);
|
|
|
|
}
|
|
|
|
state->SR[0] = 0x00000000;
|
|
|
|
CONTINUE
|
|
|
|
case 050: /* SB */
|
|
|
|
offset = (signed short)(inst);
|
|
|
|
addr = (state->SR[base] + offset) & 0x00000FFF;
|
|
|
|
state->DMEM[BES(addr)] = (unsigned char)(state->SR[rt]);
|
|
|
|
CONTINUE
|
|
|
|
case 051: /* SH */
|
|
|
|
offset = (signed short)(inst);
|
|
|
|
addr = (state->SR[base] + offset) & 0x00000FFF;
|
|
|
|
if (addr%0x004 == 0x003)
|
|
|
|
{
|
|
|
|
state->DMEM[addr - BES(0x000)] = SR_B(rt, 2);
|
|
|
|
addr = (addr + 0x00000001) & 0x00000FFF;
|
|
|
|
state->DMEM[addr + BES(0x000)] = SR_B(rt, 3);
|
|
|
|
CONTINUE
|
|
|
|
}
|
|
|
|
addr -= HES(0x000)*(addr%0x004 - 1);
|
|
|
|
*(short *)(state->DMEM + addr) = (short)(state->SR[rt]);
|
|
|
|
CONTINUE
|
|
|
|
case 053: /* SW */
|
|
|
|
offset = (signed short)(inst);
|
|
|
|
addr = (state->SR[base] + offset) & 0x00000FFF;
|
|
|
|
if (addr%0x004 != 0x000)
|
|
|
|
USW(state, rt, addr);
|
|
|
|
else
|
|
|
|
*(int32_t *)(state->DMEM + addr) = state->SR[rt];
|
|
|
|
CONTINUE
|
|
|
|
case 062: /* LWC2 */
|
|
|
|
offset = SE(inst, 6);
|
|
|
|
switch (rd)
|
|
|
|
{
|
|
|
|
case 000: /* LBV */
|
|
|
|
LBV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 001: /* LSV */
|
|
|
|
LSV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 002: /* LLV */
|
|
|
|
LLV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 003: /* LDV */
|
|
|
|
LDV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 004: /* LQV */
|
|
|
|
LQV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 005: /* LRV */
|
|
|
|
LRV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 006: /* LPV */
|
|
|
|
LPV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 007: /* LUV */
|
|
|
|
LUV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 010: /* LHV */
|
|
|
|
LHV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 011: /* LFV */
|
|
|
|
LFV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 013: /* LTV */
|
|
|
|
LTV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
default:
|
|
|
|
res_S(state);
|
|
|
|
CONTINUE
|
|
|
|
}
|
|
|
|
CONTINUE
|
|
|
|
case 072: /* SWC2 */
|
|
|
|
offset = SE(inst, 6);
|
|
|
|
switch (rd)
|
|
|
|
{
|
|
|
|
case 000: /* SBV */
|
|
|
|
SBV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 001: /* SSV */
|
|
|
|
SSV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 002: /* SLV */
|
|
|
|
SLV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 003: /* SDV */
|
|
|
|
SDV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 004: /* SQV */
|
|
|
|
SQV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 005: /* SRV */
|
|
|
|
SRV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 006: /* SPV */
|
|
|
|
SPV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 007: /* SUV */
|
|
|
|
SUV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 010: /* SHV */
|
|
|
|
SHV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 011: /* SFV */
|
|
|
|
SFV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 012: /* SWV */
|
|
|
|
SWV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
case 013: /* STV */
|
|
|
|
STV(state, rt, element, offset, base);
|
|
|
|
CONTINUE
|
|
|
|
default:
|
|
|
|
res_S(state);
|
|
|
|
CONTINUE
|
|
|
|
}
|
|
|
|
CONTINUE
|
|
|
|
default:
|
|
|
|
res_S(state);
|
|
|
|
CONTINUE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#ifndef EMULATE_STATIC_PC
|
|
|
|
if (state->stage == 2) /* branch phase of scheduler */
|
|
|
|
{
|
|
|
|
state->stage = 0*stage;
|
|
|
|
PC = state->temp_PC & 0x00000FFC;
|
2018-07-11 22:01:38 -04:00
|
|
|
SP_PC_REG = state->temp_PC;
|
2014-02-15 06:37:59 -03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
state->stage = 2*state->stage; /* next IW in branch delay slot? */
|
|
|
|
PC = (PC + 0x004) & 0xFFC;
|
2014-02-20 22:07:57 -03:00
|
|
|
if ( FIT_IMEM(PC) == 0 && ++wrap_count == 32 )
|
|
|
|
{
|
|
|
|
message( state, "RSP execution presumably caught in an infinite loop", 3 );
|
|
|
|
break;
|
|
|
|
}
|
2018-07-11 22:01:38 -04:00
|
|
|
SP_PC_REG = 0x04001000 + PC;
|
2014-02-15 06:37:59 -03:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
#else
|
|
|
|
continue;
|
|
|
|
BRANCH:
|
|
|
|
inst = *(uint32_t *)(state->IMEM + FIT_IMEM(PC));
|
2014-04-07 21:42:09 -03:00
|
|
|
#ifdef SP_EXECUTE_LOG
|
|
|
|
last_PC = PC;
|
|
|
|
#endif
|
2014-02-15 06:37:59 -03:00
|
|
|
PC = state->temp_PC & 0x00000FFC;
|
|
|
|
goto EX;
|
|
|
|
#endif
|
|
|
|
}
|
2018-07-11 22:01:38 -04:00
|
|
|
SP_PC_REG = 0x04001000 | FIT_IMEM(PC);
|
|
|
|
if (SP_STATUS_REG & 0x00000002) /* normal exit, from executing BREAK */
|
2014-02-15 06:37:59 -03:00
|
|
|
return;
|
2018-07-11 22:01:38 -04:00
|
|
|
else if (MI_INTR_REG & 0x00000001) /* interrupt set by MTC0 to break */
|
|
|
|
CheckInterrupts(state);
|
2014-02-15 06:37:59 -03:00
|
|
|
else if (CFG_WAIT_FOR_CPU_HOST != 0) /* plugin system hack to re-sync */
|
|
|
|
{}
|
2018-07-11 22:01:38 -04:00
|
|
|
else if (SP_SEMAPHORE_REG != 0x00000000) /* semaphore lock fixes */
|
2014-02-15 06:37:59 -03:00
|
|
|
{}
|
|
|
|
else /* ??? unknown, possibly external intervention from CPU memory map */
|
|
|
|
{
|
2014-02-20 22:07:57 -03:00
|
|
|
message(state, "SP_SET_HALT", 3);
|
2014-02-15 06:37:59 -03:00
|
|
|
return;
|
|
|
|
}
|
2018-07-11 22:01:38 -04:00
|
|
|
SP_STATUS_REG &= ~0x00000001; /* CPU restarts with the correct SIGs. */
|
2014-02-15 06:37:59 -03:00
|
|
|
return;
|
|
|
|
}
|