diff options
Diffstat (limited to 'src/devices/cpu/sh/sh4fe.cpp')
-rw-r--r-- | src/devices/cpu/sh/sh4fe.cpp | 317 |
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; +} |