diff options
Diffstat (limited to 'trunk/src/emu/cpu/rsp/rspfe.c')
-rw-r--r-- | trunk/src/emu/cpu/rsp/rspfe.c | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/rsp/rspfe.c b/trunk/src/emu/cpu/rsp/rspfe.c new file mode 100644 index 00000000000..ce2e062910f --- /dev/null +++ b/trunk/src/emu/cpu/rsp/rspfe.c @@ -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 "emu.h" +#include "rspfe.h" +#include "rsp.h" + +//************************************************************************** +// RSP FRONTEND +//************************************************************************** + +//------------------------------------------------- +// rsp_frontend - constructor +//------------------------------------------------- + +rsp_frontend::rsp_frontend(rsp_state &state, UINT32 window_start, UINT32 window_end, UINT32 max_sequence) + : drc_frontend(*state.device, window_start, window_end, max_sequence), + m_context(state) +{ +} + + +//------------------------------------------------- +// describe - build a description of a single +// instruction +//------------------------------------------------- + +bool rsp_frontend::describe(opcode_desc &desc, const opcode_desc *prev) +{ + UINT32 op, opswitch; + + // fetch the opcode + op = desc.opptr.l[0] = m_context.direct->read_decrypted_dword(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_special(op, desc); + + case 0x01: // REGIMM + return describe_regimm(op, desc); + + case 0x10: // COP0 + return describe_cop0(op, desc); + + case 0x12: // COP2 + return describe_cop2(op, desc); + + case 0x02: // J + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = ((LIMMVAL << 2) & 0x00000fff) | 0x1000; + 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) & 0x00000fff) | 0x1000; + 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)) & 0x00000fff) | 0x1000; + 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)) & 0x00000fff) | 0x1000; + 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_special - build a description of a +// single instruction in the 'special' group +//------------------------------------------------- + +bool rsp_frontend::describe_special(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_regimm - build a description of a +// single instruction in the 'regimm' group +//------------------------------------------------- + +bool rsp_frontend::describe_regimm(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)) & 0x00000fff) | 0x1000; + 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)) & 0x00000fff) | 0x1000; + desc.delayslots = 1; + desc.skipslots = (RTREG & 0x02) ? 1 : 0; + return true; + } + + return false; +} + + +//------------------------------------------------- +// describe_cop0 - build a description of a +// single instruction in the COP0 group +//------------------------------------------------- + +bool rsp_frontend::describe_cop0(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); + if(RDREG == 2) // SP_RD_LEN, initiating DMA + { + desc.flags |= OPFLAG_END_SEQUENCE; + } + return true; + } + + return false; +} + +//------------------------------------------------- +// describe_cop2 - build a description of a +// single instruction in the COP2 group +//------------------------------------------------- + +bool rsp_frontend::describe_cop2(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; +} |