summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/cpu/rsp/rspfe.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/cpu/rsp/rspfe.c')
-rw-r--r--trunk/src/emu/cpu/rsp/rspfe.c308
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;
+}