summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/sh/sh4fe.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/sh/sh4fe.cpp')
-rw-r--r--src/devices/cpu/sh/sh4fe.cpp317
1 files changed, 317 insertions, 0 deletions
diff --git a/src/devices/cpu/sh/sh4fe.cpp b/src/devices/cpu/sh/sh4fe.cpp
new file mode 100644
index 00000000000..e97d22a5369
--- /dev/null
+++ b/src/devices/cpu/sh/sh4fe.cpp
@@ -0,0 +1,317 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont, David Haywood
+/***************************************************************************
+
+ sh4fe.c
+
+ Front end for SH-4 recompiler
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sh4.h"
+#include "sh4comn.h"
+#include "cpu/drcfe.h"
+
+
+/***************************************************************************
+ INSTRUCTION PARSERS
+***************************************************************************/
+
+sh4_frontend::sh4_frontend(sh_common_execution *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence)
+ : sh_frontend(device, window_start, window_end, max_sequence)
+{
+}
+
+inline uint16_t sh4_frontend::read_word(opcode_desc &desc)
+{
+ if (desc.physpc >= 0xe0000000)
+ return m_sh->m_direct->read_word(desc.physpc, SH34LE_CODE_XOR(0));
+
+ return m_sh->m_direct->read_word(desc.physpc & SH34_AM, SH34LE_CODE_XOR(0));
+}
+
+inline uint16_t sh4be_frontend::read_word(opcode_desc &desc)
+{
+ if (desc.physpc >= 0xe0000000)
+ return m_sh->m_direct->read_word(desc.physpc, SH34BE_CODE_XOR(0));
+
+ return m_sh->m_direct->read_word(desc.physpc & SH34_AM, SH34BE_CODE_XOR(0));
+}
+
+
+bool sh4_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode)
+{
+ switch (opcode & 0xff)
+ {
+ default:
+ // fall through to SH2 handlers
+ return sh_frontend::describe_group_0(desc, prev, opcode);
+
+ case 0x52:
+ case 0x62:
+ case 0x43:
+ case 0x63:
+ case 0xe3:
+ case 0x68:
+ case 0xe8:
+ case 0x4a:
+ case 0xca:
+ return true; // ILLEGAL(); break; // illegal on sh4
+
+ case 0x93:
+ case 0xa3:
+ case 0xb3:
+ return true; // TODO(opcode); break;
+
+ case 0x82:
+ case 0x92:
+ case 0xa2:
+ case 0xb2:
+ case 0xc2:
+ case 0xd2:
+ case 0xe2:
+ case 0xf2:
+ return true; // STC RBANK(opcode); break; // sh3/4 only
+
+ case 0x32: return true; // STCSSR(opcode); break; // sh3/4 only
+ case 0x42: return true; // STCSPC(opcode); break; // sh3/4 only
+ case 0x83: return true; // PREFM(opcode); break; // sh3/4 only
+ case 0xc3: return true; // MOVCAL(opcode); break; // sh4 only
+
+ case 0x38:
+ case 0xb8:
+ return true; // LDTLB(opcode); break; // sh3/4 only
+
+ case 0x48:
+ case 0xc8:
+ return true; // CLRS(opcode); break; // sh3/4 only
+
+ case 0x58:
+ case 0xd8:
+ return true; // SETS(opcode); break; // sh3/4 only
+
+ case 0x3a:
+ case 0xba:
+ return true; // STCSGR(opcode); break; // sh4 only
+
+ case 0x5a:
+ case 0xda:
+ return true; // STSFPUL(opcode); break; // sh4 only
+
+ case 0x6a:
+ case 0xea:
+ return true; // STSFPSCR(opcode); break; // sh4 only
+
+ case 0x7a:
+ case 0xfa:
+ return true; // STCDBR(opcode); break; // sh4 only
+ }
+
+ return false;
+}
+
+
+bool sh4_frontend::describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode)
+{
+ switch (opcode & 0xff)
+ {
+
+ default: // LDCMSR (0x0e) has sh2/4 flag difference
+ // fall through to SH2 handlers
+ return sh_frontend::describe_group_4(desc, prev, opcode);
+
+ case 0x42:
+ case 0x46:
+ case 0x4a:
+ case 0x53:
+ case 0x57:
+ case 0x5e:
+ case 0x63:
+ case 0x67:
+ case 0x6e:
+ case 0x82:
+ case 0x86:
+ case 0x8a:
+ case 0x92:
+ case 0x96:
+ case 0x9a:
+ case 0xa2:
+ case 0xa6:
+ case 0xaa:
+ case 0xc2:
+ case 0xc6:
+ case 0xca:
+ case 0xd2:
+ case 0xd6:
+ case 0xda:
+ case 0xe2:
+ case 0xe6:
+ case 0xea:
+ return true; // ILLEGAL(); break; // defined as illegal on SH4
+
+ case 0x0c:
+ case 0x1c:
+ case 0x2c:
+ case 0x3c:
+ case 0x4c:
+ case 0x5c:
+ case 0x6c:
+ case 0x7c:
+ case 0x8c:
+ case 0x9c:
+ case 0xac:
+ case 0xbc:
+ case 0xcc:
+ case 0xdc:
+ case 0xec:
+ case 0xfc:
+ return true; // SHAD(opcode); break; // sh3/4 only needed
+
+ case 0x0d:
+ case 0x1d:
+ case 0x2d:
+ case 0x3d:
+ case 0x4d:
+ case 0x5d:
+ case 0x6d:
+ case 0x7d:
+ case 0x8d:
+ case 0x9d:
+ case 0xad:
+ case 0xbd:
+ case 0xcd:
+ case 0xdd:
+ case 0xed:
+ case 0xfd:
+ return true; // SHLD(opcode); break; // sh3/4 only needed
+
+ case 0x8e:
+ case 0x9e:
+ case 0xae:
+ case 0xbe:
+ case 0xce:
+ case 0xde:
+ case 0xee:
+ case 0xfe:
+ return true; // LDCRBANK(opcode); break; // sh3/4 only
+
+ case 0x83:
+ case 0x93:
+ case 0xa3:
+ case 0xb3:
+ case 0xc3:
+ case 0xd3:
+ case 0xe3:
+ case 0xf3:
+ return true; // STCMRBANK(opcode); break; // sh3/4 only
+
+ case 0x87:
+ case 0x97:
+ case 0xa7:
+ case 0xb7:
+ case 0xc7:
+ case 0xd7:
+ case 0xe7:
+ case 0xf7:
+ return true; // LDCMRBANK(opcode); break; // sh3/4 only
+
+ case 0x32: return true; // STCMSGR(opcode); break; // sh4 only
+ case 0x33: return true; // STCMSSR(opcode); break; // sh4 only
+ case 0x37: return true; // LDCMSSR(opcode); break; // sh3/4 only
+ case 0x3e: return true; // LDCSSR(opcode); break; // sh3/4 only
+ case 0x43: return true; // STCMSPC(opcode); break; // sh3/4 only
+ case 0x47: return true; // LDCMSPC(opcode); break; // sh3/4 only
+ case 0x4e: return true; // LDCSPC(opcode); break; // sh3/4 only
+ case 0x52: return true; // STSMFPUL(opcode); break; // sh4 only
+ case 0x56: return true; // LDSMFPUL(opcode); break; // sh4 only
+ case 0x5a: return true; // LDSFPUL(opcode); break; // sh4 only
+ case 0x62: return true; // STSMFPSCR(opcode); break; // sh4 only
+ case 0x66: return true; // LDSMFPSCR(opcode); break; // sh4 only
+ case 0x6a: return true; // LDSFPSCR(opcode); break; // sh4 only
+ case 0xf2: return true; // STCMDBR(opcode); break; // sh4 only
+ case 0xf6: return true; // LDCMDBR(opcode); break; // sh4 only
+ case 0xfa: return true; // LDCDBR(opcode); break; // sh4 only
+ }
+
+ return false;
+}
+
+// SH4 only (FPU ops)
+bool sh4_frontend::describe_group_15(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode)
+{
+ switch (opcode & 0x0f)
+ {
+ case 0x00: return true; // FADD(opcode); break;
+ case 0x01: return true; // FSUB(opcode); break;
+ case 0x02: return true; // FMUL(opcode); break;
+ case 0x03: return true; // FDIV(opcode); break;
+ case 0x04: return true; // FCMP_EQ(opcode); break;
+ case 0x05: return true; // FCMP_GT(opcode); break;
+ case 0x06: return true; // FMOVS0FR(opcode); break;
+ case 0x07: return true; // FMOVFRS0(opcode); break;
+ case 0x08: return true; // FMOVMRFR(opcode); break;
+ case 0x09: return true; // FMOVMRIFR(opcode); break;
+ case 0x0a: return true; // FMOVFRMR(opcode); break;
+ case 0x0b: return true; // FMOVFRMDR(opcode); break;
+ case 0x0c: return true; // FMOVFR(opcode); break;
+ case 0x0d: return describe_op1111_0x13(desc, prev, opcode); // break;
+ case 0x0e: return true; // FMAC(opcode); break;
+ case 0x0f:
+ return true;
+ //if (opcode == 0xffff) return true; // atomiswave uses ffff as NOP?
+ //return false; // dbreak(opcode); break;
+ }
+ return false;
+}
+
+bool sh4_frontend::describe_op1111_0x13(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode)
+{
+ switch ((opcode >> 4) & 0x0f)
+ {
+ case 0x00: return true; // FSTS(opcode); break;
+ case 0x01: return true; // FLDS(opcode); break;
+ case 0x02: return true; // FLOAT(opcode); break;
+ case 0x03: return true; // FTRC(opcode); break;
+ case 0x04: return true; // FNEG(opcode); break;
+ case 0x05: return true; // FABS(opcode); break;
+ case 0x06: return true; // FSQRT(opcode); break;
+ case 0x07: return true; // FSRRA(opcode); break;
+ case 0x08: return true; // FLDI0(opcode); break;
+ case 0x09: return true; // FLDI1(opcode); break;
+ case 0x0a: return true; // FCNVSD(opcode); break;
+ case 0x0b: return true; // FCNVDS(opcode); break;
+ case 0x0c: return false; // dbreak(opcode); break;
+ case 0x0d: return false; // dbreak(opcode); break;
+ case 0x0e: return true; // FIPR(opcode); break;
+ case 0x0f: return describe_op1111_0xf13(desc, prev, opcode); // break;
+ }
+ return false;
+}
+
+bool sh4_frontend::describe_op1111_0xf13(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode)
+{
+ if (opcode & 0x100) {
+ if (opcode & 0x200) {
+ switch (opcode & 0xC00)
+ {
+ case 0x000:
+ return true; //FSCHG();
+ break;
+ case 0x800:
+ return true; //FRCHG();
+ break;
+ default:
+ return false; //machine().debug_break();
+ break;
+ }
+ }
+ else {
+ return true; // FTRV(opcode);
+ }
+ }
+ else {
+ return true; // FSSCA(opcode);
+ }
+ return false;
+}