diff options
| author | 2026-03-02 09:25:23 +1100 | |
|---|---|---|
| committer | 2026-03-02 09:25:23 +1100 | |
| commit | 366b485b037b404a4a71f1caa77a4cacb83e17ef (patch) | |
| tree | 5a952cf72bc53d6c1032738f21725e8ae55f152e /src/devices/cpu/sh | |
| parent | ac492c02708b92ce76400214204a4fa9713d0a1a (diff) | |
Allow recompiling CPU cores to define their own opcode descriptions.
The base opcode description now only has the parts that are used by the
base recompiler front-end. CPU cores are free to define their own
extensions as they see fit without being limited to pre-defined fields.
The base recompiler front-end is now a template, eliminating the virtual
member functions. It no longer has any dependencies on libemu, which
paves the way to decoupling the recompiler front-ends and allowing the
instruction analysis to be tested without the rest of the emulator.
Also added a compile-time option to disable ASTAT flag update elision in
the SHARC recompiler, and fixed some recompiler front-end bugs.
Diffstat (limited to 'src/devices/cpu/sh')
| -rw-r--r-- | src/devices/cpu/sh/sh.cpp | 159 | ||||
| -rw-r--r-- | src/devices/cpu/sh/sh.h | 47 | ||||
| -rw-r--r-- | src/devices/cpu/sh/sh2.cpp | 9 | ||||
| -rw-r--r-- | src/devices/cpu/sh/sh2.h | 19 | ||||
| -rw-r--r-- | src/devices/cpu/sh/sh2fe.cpp | 9 | ||||
| -rw-r--r-- | src/devices/cpu/sh/sh2fe.h | 28 | ||||
| -rw-r--r-- | src/devices/cpu/sh/sh4.cpp | 101 | ||||
| -rw-r--r-- | src/devices/cpu/sh/sh4.h | 40 | ||||
| -rw-r--r-- | src/devices/cpu/sh/sh4comn.h | 2 | ||||
| -rw-r--r-- | src/devices/cpu/sh/sh4fe.cpp | 26 | ||||
| -rw-r--r-- | src/devices/cpu/sh/sh4fe.h | 36 | ||||
| -rw-r--r-- | src/devices/cpu/sh/sh_fe.cpp | 577 | ||||
| -rw-r--r-- | src/devices/cpu/sh/sh_fe.h | 120 |
13 files changed, 673 insertions, 500 deletions
diff --git a/src/devices/cpu/sh/sh.cpp b/src/devices/cpu/sh/sh.cpp index 4c1d987f639..c507410d759 100644 --- a/src/devices/cpu/sh/sh.cpp +++ b/src/devices/cpu/sh/sh.cpp @@ -5,6 +5,7 @@ #include "sh.h" #include "sh_dasm.h" +#include "sh_fe.h" #include "cpu/drcumlsh.h" @@ -1983,16 +1984,6 @@ void sh_common_execution::sh2drc_add_fastram(offs_t start, offs_t end, uint8_t r ***************************************************************************/ /*------------------------------------------------- - epc - compute the exception PC from a - descriptor --------------------------------------------------*/ - -uint32_t sh_common_execution::epc(const opcode_desc *desc) -{ - return (desc->flags & OPFLAG_IN_DELAY_SLOT) ? (desc->pc - 1) : desc->pc; -} - -/*------------------------------------------------- alloc_handle - allocate a handle if not already allocated -------------------------------------------------*/ @@ -2043,52 +2034,49 @@ void sh_common_execution::save_fast_iregs(drcuml_block &block) flags -------------------------------------------------*/ -const char *sh_common_execution::log_desc_flags_to_string(uint32_t flags) +const char *sh_common_execution::log_desc_flags_to_string(const opcode_desc &desc) { static char tempbuf[30]; char *dest = tempbuf; /* branches */ - if (flags & OPFLAG_IS_UNCONDITIONAL_BRANCH) + if (desc.is_unconditional_branch()) *dest++ = 'U'; - else if (flags & OPFLAG_IS_CONDITIONAL_BRANCH) + else if (desc.is_conditional_branch()) *dest++ = 'C'; else *dest++ = '.'; /* intrablock branches */ - *dest++ = (flags & OPFLAG_INTRABLOCK_BRANCH) ? 'i' : '.'; + *dest++ = desc.intrablock_branch() ? 'i' : '.'; /* branch targets */ - *dest++ = (flags & OPFLAG_IS_BRANCH_TARGET) ? 'B' : '.'; + *dest++ = desc.is_branch_target() ? 'B' : '.'; /* delay slots */ - *dest++ = (flags & OPFLAG_IN_DELAY_SLOT) ? 'D' : '.'; + *dest++ = desc.in_delay_slot() ? 'D' : '.'; /* exceptions */ - if (flags & OPFLAG_WILL_CAUSE_EXCEPTION) + if (desc.will_cause_exception()) *dest++ = 'E'; - else if (flags & OPFLAG_CAN_CAUSE_EXCEPTION) + else if (desc.can_cause_exception()) *dest++ = 'e'; else *dest++ = '.'; /* read/write */ - if (flags & OPFLAG_READS_MEMORY) + if (desc.reads_memory()) *dest++ = 'R'; - else if (flags & OPFLAG_WRITES_MEMORY) + else if (desc.writes_memory()) *dest++ = 'W'; else *dest++ = '.'; /* TLB validation */ - *dest++ = (flags & OPFLAG_VALIDATE_TLB) ? 'V' : '.'; - - /* TLB modification */ - *dest++ = (flags & OPFLAG_MODIFIES_TRANSLATION) ? 'T' : '.'; + *dest++ = desc.validate_tlb() ? 'V' : '.'; /* redispatch */ - *dest++ = (flags & OPFLAG_REDISPATCH) ? 'R' : '.'; + *dest++ = desc.redispatch() ? 'R' : '.'; return tempbuf; } @@ -2097,66 +2085,65 @@ const char *sh_common_execution::log_desc_flags_to_string(uint32_t flags) log_register_list - log a list of GPR registers -------------------------------------------------*/ -void sh_common_execution::log_register_list(const char *string, const uint32_t *reglist, const uint32_t *regnostarlist) +void sh_common_execution::log_register_list(const char *string, const std::bitset<32> ®list, const std::bitset<32> *regnostarlist) { int count = 0; - int regnum; /* skip if nothing */ - if (reglist[0] == 0 && reglist[1] == 0 && reglist[2] == 0) + if (reglist.none()) return; m_drcuml->log_printf("[%s:", string); - for (regnum = 0; regnum < 16; regnum++) + for (int regnum = 0; regnum < 16; regnum++) { - if (reglist[0] & REGFLAG_R(regnum)) + if (reglist[opcode_desc::REG_R0 + regnum]) { m_drcuml->log_printf("%sr%d", (count++ == 0) ? "" : ",", regnum); - if (regnostarlist != nullptr && !(regnostarlist[0] & REGFLAG_R(regnum))) + if (regnostarlist && !(*regnostarlist)[opcode_desc::REG_R0 + regnum]) m_drcuml->log_printf("*"); } } - if (reglist[1] & REGFLAG_PR) + if (reglist[opcode_desc::REG_PR]) { m_drcuml->log_printf("%spr", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_PR)) + if (regnostarlist && !(*regnostarlist)[opcode_desc::REG_PR]) m_drcuml->log_printf("*"); } - if (reglist[1] & REGFLAG_SR) + if (reglist[opcode_desc::REG_SR]) { m_drcuml->log_printf("%ssr", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_SR)) + if (regnostarlist && !(*regnostarlist)[opcode_desc::REG_SR]) m_drcuml->log_printf("*"); } - if (reglist[1] & REGFLAG_MACL) + if (reglist[opcode_desc::REG_MACL]) { m_drcuml->log_printf("%smacl", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_MACL)) + if (regnostarlist && !(*regnostarlist)[opcode_desc::REG_MACL]) m_drcuml->log_printf("*"); } - if (reglist[1] & REGFLAG_MACH) + if (reglist[opcode_desc::REG_MACH]) { m_drcuml->log_printf("%smach", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_MACH)) + if (regnostarlist && !(*regnostarlist)[opcode_desc::REG_MACH]) m_drcuml->log_printf("*"); } - if (reglist[1] & REGFLAG_GBR) + if (reglist[opcode_desc::REG_GBR]) { m_drcuml->log_printf("%sgbr", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_GBR)) + if (regnostarlist && !(*regnostarlist)[opcode_desc::REG_GBR]) m_drcuml->log_printf("*"); } - if (reglist[1] & REGFLAG_VBR) + if (reglist[opcode_desc::REG_VBR]) { m_drcuml->log_printf("%svbr", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_VBR)) + if (regnostarlist && !(*regnostarlist)[opcode_desc::REG_VBR]) m_drcuml->log_printf("*"); } @@ -2181,21 +2168,21 @@ void sh_common_execution::log_opcode_desc(const opcode_desc *desclist, int inden /* disassemle the current instruction and output it to the log */ if (m_drcuml->logging() || m_drcuml->logging_native()) { - if (desclist->flags & OPFLAG_VIRTUAL_NOOP) + if (desclist->virtual_noop()) stream << "<virtual nop>"; else { sh_disassembler sh2d(false); - sh2d.dasm_one(stream, desclist->pc, desclist->opptr.w[0]); + sh2d.dasm_one(stream, desclist->pc, desclist->opptr); } } else stream << "???"; - m_drcuml->log_printf("%08X [%08X] t:%08X f:%s: %-30s", desclist->pc, desclist->physpc, desclist->targetpc, log_desc_flags_to_string(desclist->flags), stream.str().c_str()); + m_drcuml->log_printf("%08X [%08X] t:%08X f:%s: %-30s", desclist->pc, desclist->physpc, desclist->targetpc, log_desc_flags_to_string(*desclist), stream.str()); /* output register states */ log_register_list("use", desclist->regin, nullptr); - log_register_list("mod", desclist->regout, desclist->regreq); + log_register_list("mod", desclist->regout, &desclist->regreq); m_drcuml->log_printf("\n"); /* if we have a delay slot, output it recursively */ @@ -2203,7 +2190,7 @@ void sh_common_execution::log_opcode_desc(const opcode_desc *desclist, int inden log_opcode_desc(desclist->delay.first(), indent + 1); /* at the end of a sequence add a dividing line */ - if (desclist->flags & OPFLAG_END_SEQUENCE) + if (desclist->end_sequence()) m_drcuml->log_printf("-----\n"); } } @@ -2330,7 +2317,7 @@ void sh_common_execution::code_compile_block(uint8_t mode, offs_t pc) /* determine the last instruction in this sequence */ for (seqlast = seqhead; seqlast != nullptr; seqlast = seqlast->next()) - if (seqlast->flags & OPFLAG_END_SEQUENCE) + if (seqlast->end_sequence()) break; assert(seqlast != nullptr); @@ -2360,7 +2347,7 @@ void sh_common_execution::code_compile_block(uint8_t mode, offs_t pc) generate_checksum_block(block, compiler, seqhead, seqlast); /* label this instruction, if it may be jumped to locally */ - if (seqhead->flags & OPFLAG_IS_BRANCH_TARGET) + if (seqhead->is_branch_target()) { UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc | 0x80000000 } @@ -2371,14 +2358,14 @@ void sh_common_execution::code_compile_block(uint8_t mode, offs_t pc) generate_sequence_instruction(block, compiler, curdesc, 0xffffffff); } - /* if we need to return to the start, do it */ - if (seqlast->flags & OPFLAG_RETURN_TO_START) + if (seqlast->return_to_start()) { + // if we need to return to the start, do it nextpc = pc; } - /* otherwise we just go to the next instruction */ else { + // otherwise we just go to the next instruction nextpc = seqlast->pc + (seqlast->skipslots + 1) * 2; } @@ -2459,38 +2446,39 @@ void sh_common_execution::generate_checksum_block(drcuml_block &block, compiler_ if (m_drcuml->logging()) block.append_comment("[Validation for %08X]", seqhead->pc); // comment - /* loose verify or single instruction: just compare and fail */ if (!(m_drcoptions & SH2DRC_STRICT_VERIFY) || seqhead->next() == nullptr) { - if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP)) + // loose verify or single instruction: just compare and fail + if (!seqhead->virtual_noop()) { const void *base = m_prptr(seqhead->physpc); UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x2); // load i0,base,word - UML_CMP(block, I0, seqhead->opptr.w[0]); // cmp i0,*opptr - UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc + UML_CMP(block, I0, seqhead->opptr); // cmp i0,*opptr + UML_EXHc(block, COND_NE, *m_nocode, seqhead->epc()); // exne nocode,seqhead->pc } } - - /* full verification; sum up everything */ else { + // full verification; sum up everything uint32_t sum = 0; const void *base = m_prptr(seqhead->physpc); UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x4); // load i0,base,word - sum += seqhead->opptr.w[0]; + sum += seqhead->opptr; for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next()) - if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP)) + { + if (!curdesc->virtual_noop()) { base = m_prptr(curdesc->physpc); UML_LOAD(block, I1, base, 0, SIZE_WORD, SCALE_x2); // load i1,*opptr,word UML_ADD(block, I0, I0, I1); // add i0,i0,i1 - sum += curdesc->opptr.w[0]; + sum += curdesc->opptr; } + } UML_CMP(block, I0, sum); // cmp i0,sum - UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc + UML_EXHc(block, COND_NE, *m_nocode, seqhead->epc()); // exne nocode,seqhead->pc } } @@ -2503,14 +2491,12 @@ void sh_common_execution::generate_checksum_block(drcuml_block &block, compiler_ void sh_common_execution::generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t ovrpc) { - offs_t expc; - /* add an entry for the log */ - if (m_drcuml->logging() && !(desc->flags & OPFLAG_VIRTUAL_NOOP)) - log_add_disasm_comment(block, desc->pc, desc->opptr.w[0]); + if (m_drcuml->logging() && !desc->virtual_noop()) + log_add_disasm_comment(block, desc->pc, desc->opptr); /* set the PC map variable */ - expc = (desc->flags & OPFLAG_IN_DELAY_SLOT) ? desc->pc - 1 : desc->pc; + const offs_t expc = desc->epc(); UML_MAPVAR(block, MAPVAR_PC, expc); // mapvar PC,expc /* accumulate total cycles */ @@ -2554,29 +2540,20 @@ void sh_common_execution::generate_sequence_instruction(drcuml_block &block, com } - /* if we hit an unmapped address, fatal error */ - if (desc->flags & OPFLAG_COMPILER_UNMAPPED) - { - UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc - save_fast_iregs(block); - UML_EXIT(block, EXECUTE_UNMAPPED_CODE); // exit EXECUTE_UNMAPPED_CODE - } - - /* if this is an invalid opcode, die */ - if (desc->flags & OPFLAG_INVALID_OPCODE) + if (desc->invalid_opcode()) { + // if this is an invalid opcode, die fatalerror("SH2DRC: invalid opcode!\n"); } - - /* otherwise, unless this is a virtual no-op, it's a regular instruction */ - else if (!(desc->flags & OPFLAG_VIRTUAL_NOOP)) + else if (!desc->virtual_noop()) { - /* compile the instruction */ + // otherwise, unless this is a virtual no-op, it's a regular instruction + // compile the instruction if (!generate_opcode(block, compiler, desc, ovrpc)) { // handle an illegal op UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); // mov [arg0],opcode + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); // mov [arg0],opcode UML_CALLC(block, cfunc_unimplemented, this); // callc cfunc_unimplemented } } @@ -2716,9 +2693,9 @@ bool sh_common_execution::generate_opcode(drcuml_block &block, compiler_state &c { uint32_t scratch, scratch2; int32_t disp; - uint16_t opcode = desc->opptr.w[0]; - uint8_t opswitch = opcode >> 12; - int in_delay_slot = ((desc->flags & OPFLAG_IN_DELAY_SLOT) != 0); + const uint16_t opcode = desc->opptr; + const uint8_t opswitch = opcode >> 12; + const int in_delay_slot = desc->in_delay_slot(); //printf("generating %04x\n", opcode); @@ -3073,7 +3050,7 @@ bool sh_common_execution::generate_group_3(drcuml_block &block, compiler_state & case 4: // DIV1(Rm, Rn); save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_DIV1, this); load_fast_iregs(block); return true; @@ -3111,7 +3088,7 @@ bool sh_common_execution::generate_group_3(drcuml_block &block, compiler_state & case 11: // SUBV(Rm, Rn); save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_SUBV, this); load_fast_iregs(block); return true; @@ -3125,7 +3102,7 @@ bool sh_common_execution::generate_group_3(drcuml_block &block, compiler_state & case 15: // ADDV(Rm, Rn); save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_ADDV, this); load_fast_iregs(block); return true; @@ -3755,7 +3732,7 @@ bool sh_common_execution::generate_group_0(drcuml_block &block, compiler_state & if (m_cpu_type > CPU_TYPE_SH1) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_MAC_L, this); load_fast_iregs(block); return true; @@ -3968,7 +3945,7 @@ bool sh_common_execution::generate_group_4(drcuml_block &block, compiler_state & case 0x2f: // MAC_W(Rm, Rn); case 0x3f: // MAC_W(Rm, Rn); save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_MAC_W, this); load_fast_iregs(block); return true; diff --git a/src/devices/cpu/sh/sh.h b/src/devices/cpu/sh/sh.h index 44023ac096e..3d726db11bd 100644 --- a/src/devices/cpu/sh/sh.h +++ b/src/devices/cpu/sh/sh.h @@ -6,9 +6,11 @@ #pragma once -#include "cpu/drcfe.h" #include "cpu/drcuml.h" +#include <bitset> + + /*************************************************************************** DEBUGGING **************************************************************************/ @@ -70,16 +72,6 @@ #define Q_SHIFT 8 #define M_SHIFT 9 -#define REGFLAG_R(n) (1 << (n)) - -/* register flags 1 */ -#define REGFLAG_PR (1 << 0) -#define REGFLAG_MACL (1 << 1) -#define REGFLAG_MACH (1 << 2) -#define REGFLAG_GBR (1 << 3) -#define REGFLAG_VBR (1 << 4) -#define REGFLAG_SR (1 << 5) - /*************************************************************************** MACROS ***************************************************************************/ @@ -186,6 +178,9 @@ protected: EXECUTE_RESET_CACHE = 3 }; + class frontend; + class opcode_desc; + sh_common_execution(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness, address_map_constructor internal); void ADD(uint32_t m, uint32_t n); @@ -448,8 +443,8 @@ public: void alloc_handle(uml::code_handle *&handleptr, const char *name); void load_fast_iregs(drcuml_block &block); void save_fast_iregs(drcuml_block &block); - const char *log_desc_flags_to_string(uint32_t flags); - void log_register_list(const char *string, const uint32_t *reglist, const uint32_t *regnostarlist); + const char *log_desc_flags_to_string(const opcode_desc &flags); + void log_register_list(const char *string, const std::bitset<32> ®list, const std::bitset<32> *regnostarlist); void log_opcode_desc(const opcode_desc *desclist, int indent); void log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32_t op); void generate_delay_slot(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t ovrpc); @@ -463,32 +458,8 @@ public: protected: - // device-level overrides + // device_t implementation virtual void device_start() override ATTR_COLD; }; -class sh_frontend : public drc_frontend -{ -public: - sh_frontend(sh_common_execution *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); - -protected: - virtual uint16_t read_word(opcode_desc &desc); - virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override; - -private: - bool describe_group_2(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_3(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_6(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_8(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_12(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - -protected: - virtual bool describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - virtual bool describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - virtual bool describe_group_15(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) = 0; - - sh_common_execution *m_sh; -}; - #endif // MAME_CPU_SH_SH_H diff --git a/src/devices/cpu/sh/sh2.cpp b/src/devices/cpu/sh/sh2.cpp index ae8acd76ee4..fd4df324c72 100644 --- a/src/devices/cpu/sh/sh2.cpp +++ b/src/devices/cpu/sh/sh2.cpp @@ -15,7 +15,10 @@ #include "emu.h" #include "sh2.h" + +#include "sh2fe.h" #include "sh_dasm.h" + #include "cpu/drcumlsh.h" //#define VERBOSE 1 @@ -34,6 +37,10 @@ sh2_device::sh2_device(const machine_config &mconfig, device_type type, const ch m_isdrc = allow_drc(); } +sh2_device::~sh2_device() +{ +} + void sh2_device::device_start() { sh_common_execution::device_start(); @@ -492,7 +499,7 @@ void sh2_device::sh2_exception_internal(const char *message, int irqline, int ve ///////// // DRC -const opcode_desc* sh2_device::get_desclist(offs_t pc) +const sh2_device::opcode_desc* sh2_device::get_desclist(offs_t pc) { return m_drcfe->describe_code(pc); } diff --git a/src/devices/cpu/sh/sh2.h b/src/devices/cpu/sh/sh2.h index 7e7af7c7d1e..3aceb1ae522 100644 --- a/src/devices/cpu/sh/sh2.h +++ b/src/devices/cpu/sh/sh2.h @@ -19,19 +19,18 @@ #include "sh.h" -class sh2_frontend; - class sh2_device : public sh_common_execution { - friend class sh2_frontend; - public: void set_frt_input(int state) override {} // not every CPU needs this, let the ones that do override it void func_fastirq(); // required for DRC, needs to be public to be accessible through non-classed static trampoline function protected: + class sh2_frontend; + sh2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int cpu_type, address_map_constructor internal_map, int addrlines, uint32_t address_mask); + virtual ~sh2_device(); void check_pending_irq(const char *message); @@ -99,16 +98,4 @@ private: int8_t m_irq_line_state[17]; }; - -class sh2_frontend : public sh_frontend -{ -public: - sh2_frontend(sh_common_execution *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); - -protected: - -private: - virtual bool describe_group_15(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) override; -}; - #endif // MAME_CPU_SH_SH2_H diff --git a/src/devices/cpu/sh/sh2fe.cpp b/src/devices/cpu/sh/sh2fe.cpp index b21ea334ba0..000ecbc8977 100644 --- a/src/devices/cpu/sh/sh2fe.cpp +++ b/src/devices/cpu/sh/sh2fe.cpp @@ -9,22 +9,21 @@ ***************************************************************************/ #include "emu.h" -#include "sh2.h" -#include "cpu/drcfe.h" +#include "sh2fe.h" /*************************************************************************** INSTRUCTION PARSERS ***************************************************************************/ -sh2_frontend::sh2_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) +sh2_device::sh2_frontend::sh2_frontend(sh_common_execution *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) + : frontend(device, window_start, window_end, max_sequence) { } -bool sh2_frontend::describe_group_15(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +bool sh2_device::sh2_frontend::describe_group_15(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) { return true; } diff --git a/src/devices/cpu/sh/sh2fe.h b/src/devices/cpu/sh/sh2fe.h new file mode 100644 index 00000000000..b58fa79e705 --- /dev/null +++ b/src/devices/cpu/sh/sh2fe.h @@ -0,0 +1,28 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/*************************************************************************** + + sh2fe.cpp + + Front end for SH-2 recompiler + +***************************************************************************/ +#ifndef MAME_CPU_SH_SH2FE_H +#define MAME_CPU_SH_SH2FE_H + +#pragma once + +#include "sh2.h" +#include "sh_fe.h" + + +class sh2_device::sh2_frontend : public sh_common_execution::frontend +{ +public: + sh2_frontend(sh_common_execution *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); + +private: + virtual bool describe_group_15(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) override; +}; + +#endif // MAME_CPU_SH_SH2FE_H diff --git a/src/devices/cpu/sh/sh4.cpp b/src/devices/cpu/sh/sh4.cpp index 6e73b69a531..a47754ba4e0 100644 --- a/src/devices/cpu/sh/sh4.cpp +++ b/src/devices/cpu/sh/sh4.cpp @@ -26,11 +26,14 @@ #include "emu.h" #include "sh4.h" -#include "sh4regs.h" -#include "sh4comn.h" + #include "sh3comn.h" +#include "sh4fe.h" +#include "sh4comn.h" +#include "sh4regs.h" #include "sh4tmu.h" #include "sh_dasm.h" + #include "cpu/drcumlsh.h" @@ -937,6 +940,10 @@ sh3_base_device::sh3_base_device(const machine_config &mconfig, device_type type m_am = SH34_AM; } +sh3_base_device::~sh3_base_device() +{ +} + sh4_base_device::sh4_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness) : sh34_base_device(mconfig, type, tag, owner, clock, endianness, address_map_constructor(FUNC(sh4_base_device::sh4_internal_map), this)) @@ -945,6 +952,10 @@ sh4_base_device::sh4_base_device(const machine_config &mconfig, device_type type m_am = SH34_AM; } +sh4_base_device::~sh4_base_device() +{ +} + sh3_device::sh3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness) : sh3_base_device(mconfig, SH3, tag, owner, clock, endianness) @@ -4231,7 +4242,7 @@ void sh34_base_device::sh4_set_ftcsr_callback(sh4_ftcsr_callback callback) */ -const opcode_desc* sh4_base_device::get_desclist(offs_t pc) +const sh4_base_device::opcode_desc* sh4_base_device::get_desclist(offs_t pc) { return m_drcfe->describe_code(pc); } @@ -4241,7 +4252,7 @@ void sh4_base_device::init_drc_frontend() m_drcfe = std::make_unique<sh4_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE); } -const opcode_desc* sh3_base_device::get_desclist(offs_t pc) +const sh3_base_device::opcode_desc* sh3_base_device::get_desclist(offs_t pc) { return m_drcfe->describe_code(pc); } @@ -4548,7 +4559,7 @@ static void cfunc_STCRBANK(void *param) { ((sh34_base_device *)param)->func_STCR bool sh34_base_device::generate_group_0_STCRBANK(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_STCRBANK, this); load_fast_iregs(block); return true; @@ -4572,7 +4583,7 @@ static void cfunc_PREFM(void *param) { ((sh34_base_device *)param)->func_PREFM() bool sh34_base_device::generate_group_0_PREFM(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_PREFM, this); load_fast_iregs(block); return true; @@ -4593,7 +4604,7 @@ static void cfunc_LDTLB(void *param) { ((sh34_base_device *)param)->func_LDTLB() bool sh34_base_device::generate_group_0_LDTLB(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_LDTLB, this); load_fast_iregs(block); return true; @@ -4605,7 +4616,7 @@ static void cfunc_CLRS(void *param) { ((sh34_base_device *)param)->func_CLRS(); bool sh34_base_device::generate_group_0_CLRS(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_CLRS, this); load_fast_iregs(block); return true; @@ -4617,7 +4628,7 @@ static void cfunc_SETS(void *param) { ((sh34_base_device *)param)->func_SETS(); bool sh34_base_device::generate_group_0_SETS(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_SETS, this); load_fast_iregs(block); return true; @@ -4673,7 +4684,7 @@ static void cfunc_TRAPA(void *param) { ((sh34_base_device *)param)->func_TRAPA() bool sh34_base_device::generate_group_12_TRAPA(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_MOV(block, mem(&m_sh2_state->pc), desc->pc + 2); // copy the PC because we need to use it UML_CALLC(block, cfunc_TRAPA, this); load_fast_iregs(block); @@ -4687,7 +4698,7 @@ static void cfunc_LDCSR(void *param) { ((sh34_base_device *)param)->func_LDCSR() bool sh34_base_device::generate_group_4_LDCSR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_LDCSR, this); load_fast_iregs(block); @@ -4702,7 +4713,7 @@ static void cfunc_LDCMSR(void *param) { ((sh34_base_device *)param)->func_LDCMSR bool sh34_base_device::generate_group_4_LDCMSR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_LDCMSR, this); load_fast_iregs(block); @@ -4719,7 +4730,7 @@ static void cfunc_SHAD(void *param) { ((sh34_base_device *)param)->func_SHAD(); bool sh34_base_device::generate_group_4_SHAD(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_SHAD, this); load_fast_iregs(block); return true; @@ -4731,7 +4742,7 @@ static void cfunc_SHLD(void *param) { ((sh34_base_device *)param)->func_SHLD(); bool sh34_base_device::generate_group_4_SHLD(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_SHLD, this); load_fast_iregs(block); return true; @@ -4867,7 +4878,7 @@ static void cfunc_LDCRBANK(void *param) { ((sh34_base_device *)param)->func_LDCR bool sh34_base_device::generate_group_4_LDCRBANK(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_LDCRBANK, this); load_fast_iregs(block); return true; @@ -4879,7 +4890,7 @@ static void cfunc_STCMRBANK(void *param) { ((sh34_base_device *)param)->func_STC bool sh34_base_device::generate_group_4_STCMRBANK(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_STCMRBANK, this); load_fast_iregs(block); return true; @@ -4891,7 +4902,7 @@ static void cfunc_LDCMRBANK(void *param) { ((sh34_base_device *)param)->func_LDC bool sh34_base_device::generate_group_4_LDCMRBANK(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_LDCMRBANK, this); load_fast_iregs(block); return true; @@ -4903,7 +4914,7 @@ static void cfunc_STCMSGR(void *param) { ((sh34_base_device *)param)->func_STCMS bool sh34_base_device::generate_group_4_STCMSGR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_STCMSGR, this); load_fast_iregs(block); return true; @@ -4915,7 +4926,7 @@ static void cfunc_STCMSSR(void *param) { ((sh34_base_device *)param)->func_STCMS bool sh34_base_device::generate_group_4_STCMSSR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_STCMSSR, this); load_fast_iregs(block); return true; @@ -4927,7 +4938,7 @@ static void cfunc_LDCMSSR(void *param) { ((sh34_base_device *)param)->func_LDCMS bool sh34_base_device::generate_group_4_LDCMSSR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_LDCMSSR, this); load_fast_iregs(block); return true; @@ -4945,7 +4956,7 @@ static void cfunc_STCMSPC(void *param) { ((sh34_base_device *)param)->func_STCMS bool sh34_base_device::generate_group_4_STCMSPC(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_STCMSPC, this); load_fast_iregs(block); return true; @@ -4957,7 +4968,7 @@ static void cfunc_LDCMSPC(void *param) { ((sh34_base_device *)param)->func_LDCMS bool sh34_base_device::generate_group_4_LDCMSPC(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_LDCMSPC, this); load_fast_iregs(block); return true; @@ -4975,7 +4986,7 @@ static void cfunc_STSMFPUL(void *param) { ((sh34_base_device *)param)->func_STSM bool sh34_base_device::generate_group_4_STSMFPUL(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_STSMFPUL, this); load_fast_iregs(block); return true; @@ -4987,7 +4998,7 @@ static void cfunc_LDSMFPUL(void *param) { ((sh34_base_device *)param)->func_LDSM bool sh34_base_device::generate_group_4_LDSMFPUL(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_LDSMFPUL, this); load_fast_iregs(block); return true; @@ -5005,7 +5016,7 @@ static void cfunc_STSMFPSCR(void *param) { ((sh34_base_device *)param)->func_STS bool sh34_base_device::generate_group_4_STSMFPSCR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_STSMFPSCR, this); load_fast_iregs(block); return true; @@ -5018,7 +5029,7 @@ static void cfunc_LDSMFPSCR(void *param) { ((sh34_base_device *)param)->func_LDS bool sh34_base_device::generate_group_4_LDSMFPSCR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_LDSMFPSCR, this); load_fast_iregs(block); return true; @@ -5031,7 +5042,7 @@ static void cfunc_LDSFPSCR(void *param) { ((sh34_base_device *)param)->func_LDSF bool sh34_base_device::generate_group_4_LDSFPSCR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_LDSFPSCR, this); load_fast_iregs(block); return true; @@ -5043,7 +5054,7 @@ static void cfunc_STCMDBR(void *param) { ((sh34_base_device *)param)->func_STCMD bool sh34_base_device::generate_group_4_STCMDBR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_STCMDBR, this); load_fast_iregs(block); return true; @@ -5055,7 +5066,7 @@ static void cfunc_LDCMDBR(void *param) { ((sh34_base_device *)param)->func_LDCMD bool sh34_base_device::generate_group_4_LDCMDBR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_LDCMDBR, this); load_fast_iregs(block); return true; @@ -5067,7 +5078,7 @@ static void cfunc_LDCDBR(void *param) { ((sh34_base_device *)param)->func_LDCDBR bool sh34_base_device::generate_group_4_LDCDBR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_LDCDBR, this); load_fast_iregs(block); return true; @@ -5211,7 +5222,7 @@ static void cfunc_FMOVS0FR(void *param) { ((sh34_base_device *)param)->func_FMOV bool sh34_base_device::generate_group_15_FMOVS0FR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_FMOVS0FR, this); load_fast_iregs(block); return true; @@ -5223,7 +5234,7 @@ static void cfunc_FMOVFRS0(void *param) { ((sh34_base_device *)param)->func_FMOV bool sh34_base_device::generate_group_15_FMOVFRS0(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_FMOVFRS0, this); load_fast_iregs(block); return true; @@ -5235,7 +5246,7 @@ static void cfunc_FMOVMRFR(void *param) { ((sh34_base_device *)param)->func_FMOV bool sh34_base_device::generate_group_15_FMOVMRFR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_FMOVMRFR, this); load_fast_iregs(block); return true; @@ -5247,7 +5258,7 @@ static void cfunc_FMOVMRIFR(void *param) { ((sh34_base_device *)param)->func_FMO bool sh34_base_device::generate_group_15_FMOVMRIFR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_FMOVMRIFR, this); load_fast_iregs(block); return true; @@ -5259,7 +5270,7 @@ static void cfunc_FMOVFRMR(void *param) { ((sh34_base_device *)param)->func_FMOV bool sh34_base_device::generate_group_15_FMOVFRMR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_FMOVFRMR, this); load_fast_iregs(block); return true; @@ -5271,7 +5282,7 @@ static void cfunc_FMOVFRMDR(void *param) { ((sh34_base_device *)param)->func_FMO bool sh34_base_device::generate_group_15_FMOVFRMDR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_FMOVFRMDR, this); load_fast_iregs(block); return true; @@ -5283,7 +5294,7 @@ static void cfunc_FMOVFR(void *param) { ((sh34_base_device *)param)->func_FMOVFR bool sh34_base_device::generate_group_15_FMOVFR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_FMOVFR, this); load_fast_iregs(block); return true; @@ -5342,7 +5353,7 @@ static void cfunc_FLDS(void *param) { ((sh34_base_device *)param)->func_FLDS(); bool sh34_base_device::generate_group_15_op1111_0x13_FLDS(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_FLDS, this); load_fast_iregs(block); return true; @@ -5429,7 +5440,7 @@ static void cfunc_FSQRT(void *param) { ((sh34_base_device *)param)->func_FSQRT() bool sh34_base_device::generate_group_15_op1111_0x13_FSQRT(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_FSQRT, this); load_fast_iregs(block); return true; @@ -5441,7 +5452,7 @@ static void cfunc_FSRRA(void *param) { ((sh34_base_device *)param)->func_FSRRA() bool sh34_base_device::generate_group_15_op1111_0x13_FSRRA(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_FSRRA, this); load_fast_iregs(block); return true; @@ -5477,7 +5488,7 @@ static void cfunc_FCNVSD(void *param) { ((sh34_base_device *)param)->func_FCNVSD bool sh34_base_device::generate_group_15_op1111_0x13_FCNVSD(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_FCNVSD, this); load_fast_iregs(block); return true; @@ -5489,7 +5500,7 @@ static void cfunc_FCNVDS(void *param) { ((sh34_base_device *)param)->func_FCNVDS bool sh34_base_device::generate_group_15_op1111_0x13_FCNVDS(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_FCNVDS, this); load_fast_iregs(block); return true; @@ -5501,7 +5512,7 @@ static void cfunc_FIPR(void *param) { ((sh34_base_device *)param)->func_FIPR(); bool sh34_base_device::generate_group_15_op1111_0x13_FIPR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_FIPR, this); load_fast_iregs(block); return true; @@ -5572,7 +5583,7 @@ static void cfunc_FTRV(void *param) { ((sh34_base_device *)param)->func_FTRV(); bool sh34_base_device::generate_group_15_op1111_0x13_op1111_0xf13_FTRV(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_FTRV, this); load_fast_iregs(block); return true; @@ -5584,7 +5595,7 @@ static void cfunc_FSSCA(void *param) { ((sh34_base_device *)param)->func_FSSCA() bool sh34_base_device::generate_group_15_op1111_0x13_op1111_0xf13_FSSCA(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) { save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr); UML_CALLC(block, cfunc_FSSCA, this); load_fast_iregs(block); return true; diff --git a/src/devices/cpu/sh/sh4.h b/src/devices/cpu/sh/sh4.h index c4fc1c0cd1c..d92e374bc5e 100644 --- a/src/devices/cpu/sh/sh4.h +++ b/src/devices/cpu/sh/sh4.h @@ -155,8 +155,6 @@ struct sh4_utlb typedef void (*sh4_ftcsr_callback)(uint32_t); -class sh4_frontend; - class sh34_base_device : public sh_common_execution { public: @@ -250,6 +248,8 @@ public: void func_STCSPC(); protected: + class sh4_frontend; + // construction/destruction sh34_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness, address_map_constructor internal); @@ -684,7 +684,8 @@ private: class sh3_base_device : public sh34_base_device { - friend class sh4_frontend; +public: + virtual ~sh3_base_device(); protected: // construction/destruction @@ -1234,9 +1235,10 @@ protected: class sh4_base_device : public sh34_base_device { -protected: - friend class sh4_frontend; +public: + virtual ~sh4_base_device(); +protected: // construction/destruction sh4_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness); @@ -1972,32 +1974,18 @@ protected: virtual void sh4_register_map(address_map& map) override ATTR_COLD; }; -class sh4_frontend : public sh_frontend -{ -public: - sh4_frontend(sh_common_execution *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); - -protected: - virtual uint16_t read_word(opcode_desc &desc) override; -private: - virtual bool describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) override; - virtual bool describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) override; - virtual bool describe_group_15(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) override; - bool describe_op1111_0x13(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_op1111_0xf13(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); -}; - -DECLARE_DEVICE_TYPE(SH3, sh3_device) +DECLARE_DEVICE_TYPE(SH3, sh3_device) DECLARE_DEVICE_TYPE(SH7708S, sh7708s_device) -DECLARE_DEVICE_TYPE(SH7709, sh7709_device) +DECLARE_DEVICE_TYPE(SH7709, sh7709_device) DECLARE_DEVICE_TYPE(SH7709S, sh7709s_device) -DECLARE_DEVICE_TYPE(SH4, sh4_device) -DECLARE_DEVICE_TYPE(SH7091, sh7091_device) -DECLARE_DEVICE_TYPE(SH7750, sh7750_device) + +DECLARE_DEVICE_TYPE(SH4, sh4_device) +DECLARE_DEVICE_TYPE(SH7091, sh7091_device) +DECLARE_DEVICE_TYPE(SH7750, sh7750_device) DECLARE_DEVICE_TYPE(SH7750R, sh7750r_device) DECLARE_DEVICE_TYPE(SH7750S, sh7750s_device) -DECLARE_DEVICE_TYPE(SH7751, sh7751_device) +DECLARE_DEVICE_TYPE(SH7751, sh7751_device) DECLARE_DEVICE_TYPE(SH7751R, sh7751r_device) #endif // MAME_CPU_SH_SH4_H diff --git a/src/devices/cpu/sh/sh4comn.h b/src/devices/cpu/sh/sh4comn.h index bac004d36b4..00eab9bf51c 100644 --- a/src/devices/cpu/sh/sh4comn.h +++ b/src/devices/cpu/sh/sh4comn.h @@ -63,8 +63,6 @@ enum #define SZ 0x00100000 #define FR 0x00200000 -#define REGFLAG_R(n) (1 << (n)) - /* additional register flags 1 */ #define REGFLAG_SGR (1 << 6) #define REGFLAG_FPUL (1 << 7) diff --git a/src/devices/cpu/sh/sh4fe.cpp b/src/devices/cpu/sh/sh4fe.cpp index 8474cb48171..d05bd07751f 100644 --- a/src/devices/cpu/sh/sh4fe.cpp +++ b/src/devices/cpu/sh/sh4fe.cpp @@ -9,21 +9,23 @@ ***************************************************************************/ #include "emu.h" -#include "sh4.h" +#include "sh4fe.h" + #include "sh4comn.h" -#include "cpu/drcfe.h" + +// FIXME: if the code generation is to be improved, this needs to actually describe the instructions /*************************************************************************** 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) +sh34_base_device::sh4_frontend::sh4_frontend(sh_common_execution *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) + : frontend(device, window_start, window_end, max_sequence) { } -uint16_t sh4_frontend::read_word(opcode_desc &desc) +uint16_t sh34_base_device::sh4_frontend::read_word(opcode_desc &desc) { if (desc.physpc >= 0xe0000000) return m_sh->m_pr16(desc.physpc); @@ -33,13 +35,13 @@ uint16_t sh4_frontend::read_word(opcode_desc &desc) } -bool sh4_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +bool sh34_base_device::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); + return frontend::describe_group_0(desc, prev, opcode); case 0x52: case 0x62: @@ -105,14 +107,14 @@ bool sh4_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, } -bool sh4_frontend::describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +bool sh34_base_device::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); + return frontend::describe_group_4(desc, prev, opcode); case 0x42: case 0x46: @@ -231,7 +233,7 @@ bool sh4_frontend::describe_group_4(opcode_desc &desc, const opcode_desc *prev, } // SH4 only (FPU ops) -bool sh4_frontend::describe_group_15(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +bool sh34_base_device::sh4_frontend::describe_group_15(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) { switch (opcode & 0x0f) { @@ -258,7 +260,7 @@ bool sh4_frontend::describe_group_15(opcode_desc &desc, const opcode_desc *prev, return false; } -bool sh4_frontend::describe_op1111_0x13(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +bool sh34_base_device::sh4_frontend::describe_op1111_0x13(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) { switch ((opcode >> 4) & 0x0f) { @@ -282,7 +284,7 @@ bool sh4_frontend::describe_op1111_0x13(opcode_desc &desc, const opcode_desc *pr return false; } -bool sh4_frontend::describe_op1111_0xf13(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +bool sh34_base_device::sh4_frontend::describe_op1111_0xf13(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) { if (opcode & 0x100) { diff --git a/src/devices/cpu/sh/sh4fe.h b/src/devices/cpu/sh/sh4fe.h new file mode 100644 index 00000000000..f3ce57bf74a --- /dev/null +++ b/src/devices/cpu/sh/sh4fe.h @@ -0,0 +1,36 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/*************************************************************************** + + sh4fe.h + + Front end for SH-4 recompiler + +***************************************************************************/ +#ifndef MAME_CPU_SH_SH4FE_H +#define MAME_CPU_SH_SH4FE_H + +#pragma once + +#include "sh4.h" +#include "sh_fe.h" + + +class sh34_base_device::sh4_frontend : public sh_common_execution::frontend +{ +public: + sh4_frontend(sh_common_execution *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); + +protected: + virtual uint16_t read_word(opcode_desc &desc) override; + + virtual bool describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) override; + virtual bool describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) override; + virtual bool describe_group_15(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) override; + +private: + bool describe_op1111_0x13(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_op1111_0xf13(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); +}; + +#endif // MAME_CPU_SH_SH4FE_H diff --git a/src/devices/cpu/sh/sh_fe.cpp b/src/devices/cpu/sh/sh_fe.cpp index 5e803b8ee00..f62ecf110fb 100644 --- a/src/devices/cpu/sh/sh_fe.cpp +++ b/src/devices/cpu/sh/sh_fe.cpp @@ -4,41 +4,52 @@ sh_fe.cpp - Front end for SH recompiler + Front end for SuperH recompiler ***************************************************************************/ #include "emu.h" -#include "sh2.h" -#include "cpu/drcfe.h" +#include "sh_fe.h" + +#include "cpu/drcfe.ipp" /*************************************************************************** INSTRUCTION PARSERS ***************************************************************************/ -sh_frontend::sh_frontend(sh_common_execution *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) - : drc_frontend(*device, window_start, window_end, max_sequence) +sh_common_execution::frontend::frontend(sh_common_execution *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) + : drc_frontend_base(device->space_config(AS_PROGRAM)->page_shift(), window_start, window_end, max_sequence) , m_sh(device) { } -/*------------------------------------------------- - describe_instruction - build a description - of a single instruction --------------------------------------------------*/ +sh_common_execution::frontend::~frontend() +{ +} -inline uint16_t sh_frontend::read_word(opcode_desc &desc) +sh_common_execution::opcode_desc const *sh_common_execution::frontend::describe_code(offs_t startpc) { - return m_sh->m_pr16(desc.physpc); + return do_describe_code( + [this] (opcode_desc &desc, opcode_desc const *prev) { return describe(desc, prev); }, + startpc); } -bool sh_frontend::describe(opcode_desc &desc, const opcode_desc *prev) + +inline uint16_t sh_common_execution::frontend::read_word(opcode_desc &desc) { - uint16_t opcode; + return m_sh->m_pr16(desc.physpc); +} + +/*------------------------------------------------- + describe_instruction - build a description + of a single instruction +-------------------------------------------------*/ +bool sh_common_execution::frontend::describe(opcode_desc &desc, const opcode_desc *prev) +{ /* fetch the opcode */ - opcode = desc.opptr.w[0] = read_word(desc); + const uint16_t opcode = desc.opptr = read_word(desc); /* all instructions are 2 bytes and most are a single cycle */ desc.length = 2; @@ -46,88 +57,91 @@ bool sh_frontend::describe(opcode_desc &desc, const opcode_desc *prev) switch (opcode>>12) { - case 0: - return describe_group_0(desc, prev, opcode); + case 0: + return describe_group_0(desc, prev, opcode); - case 1: // MOVLS4 - desc.regin[0] |= REGFLAG_R(REG_N) | REGFLAG_R(REG_M); - desc.flags |= OPFLAG_WRITES_MEMORY; - return true; + case 1: // MOVLS4 + desc.set_r_used(REG_M); + desc.set_r_used(REG_N); + desc.set_writes_memory(); + return true; - case 2: - return describe_group_2(desc, prev, opcode); + case 2: + return describe_group_2(desc, prev, opcode); - case 3: - return describe_group_3(desc, prev, opcode); + case 3: + return describe_group_3(desc, prev, opcode); - case 4: - return describe_group_4(desc, prev, opcode); + case 4: + return describe_group_4(desc, prev, opcode); - case 5: // MOVLL4 - desc.regin[0] |= REGFLAG_R(REG_M); - desc.regout[0] |= REGFLAG_R(REG_N); - desc.flags |= OPFLAG_READS_MEMORY; - return true; + case 5: // MOVLL4 + desc.set_r_used(REG_M); + desc.set_r_modified(REG_N); + desc.set_reads_memory(); + return true; - case 6: - return describe_group_6(desc, prev, opcode); + case 6: + return describe_group_6(desc, prev, opcode); - case 7: // ADDI - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regout[0] |= REGFLAG_R(REG_N); - return true; + case 7: // ADDI + desc.set_r_used(REG_N); + desc.set_r_modified(REG_N); + return true; - case 8: - return describe_group_8(desc, prev, opcode); + case 8: + return describe_group_8(desc, prev, opcode); - case 9: // MOVWI - desc.regout[0] |= REGFLAG_R(REG_N); - desc.flags |= OPFLAG_READS_MEMORY; - return true; + case 9: // MOVWI + desc.set_r_modified(REG_N); + desc.set_reads_memory(); + return true; - case 11: // BSR - desc.regout[1] |= REGFLAG_PR; - [[fallthrough]]; // BSR is BRA with the addition of PR = the return address - case 10: // BRA - { - int32_t disp = util::sext(opcode, 12); - - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - desc.targetpc = (desc.pc + 2) + disp * 2 + 2; - desc.delayslots = 1; - desc.cycles = 2; - return true; - } - - case 12: - return describe_group_12(desc, prev, opcode); - - case 13: // MOVLI - desc.regout[0] |= REGFLAG_R(REG_N); - desc.flags |= OPFLAG_READS_MEMORY; - return true; + case 11: // BSR + desc.set_pr_modified(); + [[fallthrough]]; // BSR is BRA with the addition of PR = the return address + case 10: // BRA + { + int32_t disp = util::sext(opcode, 12); - case 14: // MOVI - desc.regout[0] |= REGFLAG_R(REG_N); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + desc.targetpc = (desc.pc + 2) + disp * 2 + 2; + desc.delayslots = 1; + desc.cycles = 2; return true; + } + + case 12: + return describe_group_12(desc, prev, opcode); + + case 13: // MOVLI + desc.set_r_modified(REG_N); + desc.set_reads_memory(); + return true; + + case 14: // MOVI + desc.set_r_modified(REG_N); + return true; - case 15: // NOP - return describe_group_15(desc, prev, opcode); + case 15: // NOP + return describe_group_15(desc, prev, opcode); } return false; } -bool sh_frontend::describe_group_2(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +bool sh_common_execution::frontend::describe_group_2(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) { switch (opcode & 15) { case 0: // MOVBS(Rm, Rn); case 1: // MOVWS(Rm, Rn); case 2: // MOVLS(Rm, Rn); - desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_r_used(REG_M); + desc.set_r_used(REG_N); + desc.set_writes_memory(); return true; case 3: // NOP(); @@ -137,29 +151,33 @@ bool sh_frontend::describe_group_2(opcode_desc &desc, const opcode_desc *prev, u case 5: // MOVWM(Rm, Rn); case 6: // MOVLM(Rm, Rn); case 13: // XTRCT(Rm, Rn); - desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N); - desc.regout[0] |= REGFLAG_R(REG_N); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_r_used(REG_M); + desc.set_r_used(REG_N); + desc.set_r_modified(REG_N); + desc.set_writes_memory(); return true; case 7: // DIV0S(Rm, Rn); case 8: // TST(Rm, Rn); case 12: // CMPSTR(Rm, Rn); - desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_SR; + desc.set_r_used(REG_M); + desc.set_r_used(REG_N); + desc.set_sr_modified(); return true; case 9: // AND(Rm, Rn); case 10: // XOR(Rm, Rn); case 11: // OR(Rm, Rn); - desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N); - desc.regout[0] |= REGFLAG_R(REG_N); + desc.set_r_used(REG_M); + desc.set_r_used(REG_N); + desc.set_r_modified(REG_N); return true; case 14: // MULU(Rm, Rn); case 15: // MULS(Rm, Rn); - desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; + desc.set_r_used(REG_M); + desc.set_r_used(REG_N); + desc.set_mac_modified(); desc.cycles = 2; return true; } @@ -167,7 +185,7 @@ bool sh_frontend::describe_group_2(opcode_desc &desc, const opcode_desc *prev, u return false; } -bool sh_frontend::describe_group_3(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +bool sh_common_execution::frontend::describe_group_3(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) { switch (opcode & 15) { @@ -176,8 +194,9 @@ bool sh_frontend::describe_group_3(opcode_desc &desc, const opcode_desc *prev, u case 3: // CMPGE(Rm, Rn); case 6: // CMPHI(Rm, Rn); case 7: // CMPGT(Rm, Rn); - desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_SR; + desc.set_r_used(REG_M); + desc.set_r_used(REG_N); + desc.set_sr_modified(); return true; case 1: // NOP(); @@ -185,39 +204,43 @@ bool sh_frontend::describe_group_3(opcode_desc &desc, const opcode_desc *prev, u return true; case 4: // DIV1(Rm, Rn); - desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N); - desc.regout[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_SR; + desc.set_r_used(REG_M); + desc.set_r_used(REG_N); + desc.set_r_modified(REG_N); + desc.set_sr_modified(); return true; case 5: // DMULU(Rm, Rn); case 13: // DMULS(Rm, Rn); - desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; + desc.set_r_used(REG_M); + desc.set_r_used(REG_N); + desc.set_mac_modified(); desc.cycles = 2; return true; case 8: // SUB(Rm, Rn); case 12: // ADD(Rm, Rn); - desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N); - desc.regout[0] |= REGFLAG_R(REG_N); + desc.set_r_used(REG_M); + desc.set_r_used(REG_N); + desc.set_r_modified(REG_N); return true; case 10: // SUBC(Rm, Rn); case 11: // SUBV(Rm, Rn); case 14: // ADDC(Rm, Rn); case 15: // ADDV(Rm, Rn); - desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N); - desc.regin[1] |= REGFLAG_SR; - desc.regout[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_SR; + desc.set_r_used(REG_M); + desc.set_r_used(REG_N); + desc.set_sr_used(); + desc.set_r_modified(REG_N); + desc.set_sr_modified(); return true; } return false; } -bool sh_frontend::describe_group_6(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +bool sh_common_execution::frontend::describe_group_6(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) { switch (opcode & 15) { @@ -232,33 +255,35 @@ bool sh_frontend::describe_group_6(opcode_desc &desc, const opcode_desc *prev, u case 13: // EXTUW(Rm, Rn); case 14: // EXTSB(Rm, Rn); case 15: // EXTSW(Rm, Rn); - desc.regin[0] |= REGFLAG_R(REG_M); - desc.regout[0] |= REGFLAG_R(REG_N); + desc.set_r_used(REG_M); + desc.set_r_modified(REG_N); return true; case 4: // MOVBP(Rm, Rn); case 5: // MOVWP(Rm, Rn); case 6: // MOVLP(Rm, Rn); - desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N); - desc.regout[0] |= REGFLAG_R(REG_N); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_r_used(REG_M); + desc.set_r_used(REG_N); + desc.set_r_modified(REG_N); + desc.set_reads_memory(); return true; case 8: // SWAPB(Rm, Rn); - desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N); - desc.regout[0] |= REGFLAG_R(REG_N); + desc.set_r_used(REG_M); + desc.set_r_used(REG_N); + desc.set_r_modified(REG_N); return true; case 10: // NEGC(Rm, Rn); - desc.regin[0] |= REGFLAG_R(REG_M); - desc.regout[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_SR; + desc.set_r_used(REG_M); + desc.set_r_modified(REG_N); + desc.set_sr_modified(); return true; } return false; } -bool sh_frontend::describe_group_8(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +bool sh_common_execution::frontend::describe_group_8(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) { int32_t disp; @@ -266,8 +291,9 @@ bool sh_frontend::describe_group_8(opcode_desc &desc, const opcode_desc *prev, u { case 0 << 8: // MOVBS4(opcode & 0x0f, Rm); case 1 << 8: // MOVWS4(opcode & 0x0f, Rm); - desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(0); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_r_used(REG_M); + desc.set_r_used(0); + desc.set_writes_memory(); return true; case 2 << 8: // NOP(); @@ -281,20 +307,20 @@ bool sh_frontend::describe_group_8(opcode_desc &desc, const opcode_desc *prev, u case 4 << 8: // MOVBL4(Rm, opcode & 0x0f); case 5 << 8: // MOVWL4(Rm, opcode & 0x0f); - desc.regin[0] |= REGFLAG_R(REG_M); - desc.regout[0] |= REGFLAG_R(0); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_r_used(REG_M); + desc.set_r_modified(0); + desc.set_reads_memory(); return true; case 8 << 8: // CMPIM(opcode & 0xff); - desc.regin[0] |= REGFLAG_R(REG_M); - desc.regin[1] |= REGFLAG_SR; - desc.regout[1] |= REGFLAG_SR; + desc.set_r_used(REG_M); + desc.set_sr_used(); + desc.set_sr_modified(); return true; case 9 << 8: // BT(opcode & 0xff); case 11 << 8: // BF(opcode & 0xff); - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.set_is_conditional_branch(); desc.cycles = 3; disp = util::sext(opcode, 8); desc.targetpc = (desc.pc + 2) + disp * 2 + 2; @@ -302,7 +328,7 @@ bool sh_frontend::describe_group_8(opcode_desc &desc, const opcode_desc *prev, u case 13 << 8: // BTS(opcode & 0xff); case 15 << 8: // BFS(opcode & 0xff); - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.set_is_conditional_branch(); desc.cycles = 2; disp = util::sext(opcode, 8); desc.targetpc = (desc.pc + 2) + disp * 2 + 2; @@ -313,55 +339,58 @@ bool sh_frontend::describe_group_8(opcode_desc &desc, const opcode_desc *prev, u return false; } -bool sh_frontend::describe_group_12(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +bool sh_common_execution::frontend::describe_group_12(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) { switch (opcode & (15<<8)) { case 0 << 8: // MOVBSG(opcode & 0xff); case 1 << 8: // MOVWSG(opcode & 0xff); case 2 << 8: // MOVLSG(opcode & 0xff); - desc.regin[0] |= REGFLAG_R(0); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_r_used(0); + desc.set_writes_memory(); return true; case 3 << 8: // TRAPA(opcode & 0xff); - desc.regin[0] |= REGFLAG_R(15); - desc.regin[1] |= REGFLAG_VBR; - desc.regout[0] |= REGFLAG_R(15); + desc.set_r_used(15); + desc.set_vbr_used(); + desc.set_r_modified(15); desc.cycles = 8; desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + desc.set_reads_memory(); return true; case 4 << 8: // MOVBLG(opcode & 0xff); case 5 << 8: // MOVWLG(opcode & 0xff); case 6 << 8: // MOVLLG(opcode & 0xff); case 7 << 8: // MOVA(opcode & 0xff); - desc.regout[0] |= REGFLAG_R(0); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_r_modified(0); + desc.set_reads_memory(); return true; case 8 << 8: // TSTI(opcode & 0xff); - desc.regin[0] |= REGFLAG_R(0); - desc.regin[1] |= REGFLAG_SR; - desc.regout[1] |= REGFLAG_SR; + desc.set_r_used(0); + desc.set_sr_used(); + desc.set_sr_modified(); return true; case 9 << 8: // ANDI(opcode & 0xff); case 10 << 8: // XORI(opcode & 0xff); case 11 << 8: // ORI(opcode & 0xff); - desc.regin[0] |= REGFLAG_R(0); - desc.regout[0] |= REGFLAG_R(0); + desc.set_r_used(0); + desc.set_r_modified(0); return true; case 12 << 8: // TSTM(opcode & 0xff); case 13 << 8: // ANDM(opcode & 0xff); case 14 << 8: // XORM(opcode & 0xff); case 15 << 8: // ORM(opcode & 0xff); - desc.regin[0] |= REGFLAG_R(0); - desc.regin[1] |= REGFLAG_SR | REGFLAG_GBR; - desc.regout[1] |= REGFLAG_SR; - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_r_used(0); + desc.set_sr_used(); + desc.set_gbr_used(); + desc.set_sr_modified(); + desc.set_reads_memory(); return true; } @@ -370,9 +399,9 @@ bool sh_frontend::describe_group_12(opcode_desc &desc, const opcode_desc *prev, -bool sh_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +bool sh_common_execution::frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) { - switch (opcode & 0x3F) + switch (opcode & 0x3f) { case 0x00: // NOP(); case 0x01: // NOP(); @@ -393,13 +422,14 @@ bool sh_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, u return true; case 0x02: // STCSR(Rn); - desc.regout[0] |= REGFLAG_R(REG_N); + desc.set_r_modified(REG_N); return true; case 0x03: // BSRF(Rn); - desc.regout[1] |= REGFLAG_PR; + desc.set_pr_modified(); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); desc.targetpc = BRANCH_TARGET_DYNAMIC; desc.delayslots = 1; @@ -417,32 +447,36 @@ bool sh_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, u case 0x34: // MOVBS0(Rm, Rn); case 0x35: // MOVWS0(Rm, Rn); case 0x36: // MOVLS0(Rm, Rn); - desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N) | REGFLAG_R(0); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_r_used(REG_M); + desc.set_r_used(REG_N); + desc.set_r_used(0); + desc.set_writes_memory(); return true; case 0x07: // MULL(Rm, Rn); case 0x17: // MULL(Rm, Rn); case 0x27: // MULL(Rm, Rn); case 0x37: // MULL(Rm, Rn); - desc.regin[0] |= REGFLAG_R(REG_N) | REGFLAG_R(REG_M); - desc.regout[1] |= REGFLAG_MACL; + desc.set_r_used(REG_M); + desc.set_r_used(REG_N); + desc.set_macl_modified(); desc.cycles = 2; return true; case 0x08: // CLRT(); - desc.regout[1] |= REGFLAG_SR; + desc.set_sr_modified(); return true; case 0x0a: // STSMACH(Rn); - desc.regout[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_MACH; + desc.set_r_modified(REG_N); + desc.set_mach_modified(); return true; case 0x0b: // RTS(); - desc.regin[1] |= REGFLAG_PR; + desc.set_pr_used(); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); desc.targetpc = BRANCH_TARGET_DYNAMIC; desc.delayslots = 1; desc.cycles = 2; @@ -461,36 +495,38 @@ bool sh_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, u case 0x3c: // MOVBL0(Rm, Rn); case 0x3d: // MOVWL0(Rm, Rn); case 0x3e: // MOVLL0(Rm, Rn); - desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(0); - desc.regout[0] |= REGFLAG_R(REG_N); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_r_used(REG_M); + desc.set_r_used(0); + desc.set_r_modified(REG_N); + desc.set_reads_memory(); return true; case 0x0f: // MAC_L(Rm, Rn); case 0x1f: // MAC_L(Rm, Rn); case 0x2f: // MAC_L(Rm, Rn); case 0x3f: // MAC_L(Rm, Rn); - desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; + desc.set_r_used(REG_M); + desc.set_r_used(REG_N); + desc.set_mac_modified(); desc.cycles = 3; return true; case 0x12: // STCGBR(Rn); - desc.regout[0] |= REGFLAG_R(REG_N); - desc.regin[1] |= REGFLAG_GBR; + desc.set_r_modified(REG_N); + desc.set_gbr_used(); return true; case 0x18: // SETT(); - desc.regout[1] |= REGFLAG_SR; + desc.set_sr_modified(); return true; case 0x19: // DIV0U(); - desc.regout[1] |= REGFLAG_SR; + desc.set_sr_modified(); return true; case 0x1a: // STSMACL(Rn); - desc.regin[1] |= REGFLAG_MACL; - desc.regout[0] |= REGFLAG_R(REG_N); + desc.set_macl_used(); + desc.set_r_modified(REG_N); return true; case 0x1b: // SLEEP(); @@ -498,37 +534,40 @@ bool sh_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, u return true; case 0x22: // STCVBR(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_VBR; + desc.set_r_used(REG_N); + desc.set_vbr_modified(); return true; case 0x23: // BRAF(Rn); - desc.regin[0] |= REGFLAG_R(REG_M); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_r_used(REG_M); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); desc.targetpc = BRANCH_TARGET_DYNAMIC; desc.delayslots = 1; desc.cycles = 2; return true; case 0x28: // CLRMAC(); - desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; + desc.set_mac_modified(); return true; case 0x29: // MOVT(Rn); - desc.regin[1] |= REGFLAG_SR; - desc.regout[0] |= REGFLAG_R(REG_N); + desc.set_sr_used(); + desc.set_r_modified(REG_N); return true; case 0x2a: // STSPR(Rn); - desc.regin[1] |= REGFLAG_PR; - desc.regout[0] |= REGFLAG_R(REG_N); + desc.set_pr_used(); + desc.set_r_modified(REG_N); return true; case 0x2b: // RTE(); - desc.regin[0] |= REGFLAG_R(15); - desc.regout[0] |= REGFLAG_R(15); + desc.set_r_used(15); + desc.set_r_modified(15); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_EXPOSE_EXTERNAL_INT; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + desc.set_can_expose_external_int(); desc.targetpc = BRANCH_TARGET_DYNAMIC; desc.delayslots = 1; desc.cycles = 4; @@ -540,7 +579,7 @@ bool sh_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, u } -bool sh_frontend::describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +bool sh_common_execution::frontend::describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) { switch (opcode & 0x3F) { @@ -548,38 +587,40 @@ bool sh_frontend::describe_group_4(opcode_desc &desc, const opcode_desc *prev, u case 0x01: // SHLR(Rn); case 0x04: // ROTL(Rn); case 0x05: // ROTR(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regout[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_SR; + desc.set_r_used(REG_N); + desc.set_r_modified(REG_N); + desc.set_sr_modified(); return true; case 0x02: // STSMMACH(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regin[1] |= REGFLAG_MACH; - desc.regout[0] |= REGFLAG_R(REG_N); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_r_used(REG_N); + desc.set_mach_used(); + desc.set_r_modified(REG_N); + desc.set_writes_memory(); return true; case 0x03: // STCMSR(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regout[0] |= REGFLAG_R(REG_N); + desc.set_r_used(REG_N); + desc.set_r_modified(REG_N); desc.cycles = 2; - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); return true; case 0x06: // LDSMMACH(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regout[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_MACH; - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_r_used(REG_N); + desc.set_r_modified(REG_N); + desc.set_mach_modified(); + desc.set_reads_memory(); return true; case 0x07: // LDCMSR(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regout[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_SR; + desc.set_r_used(REG_N); + desc.set_r_modified(REG_N); + desc.set_sr_modified(); desc.cycles = 3; - desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_END_SEQUENCE; + desc.set_end_sequence(); + desc.set_reads_memory(); + desc.set_can_expose_external_int(); return true; case 0x08: // SHLL2(Rn); @@ -588,158 +629,166 @@ bool sh_frontend::describe_group_4(opcode_desc &desc, const opcode_desc *prev, u case 0x19: // SHLR8(Rn); case 0x28: // SHLL16(Rn); case 0x29: // SHLR16(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regout[0] |= REGFLAG_R(REG_N); + desc.set_r_used(REG_N); + desc.set_r_modified(REG_N); return true; case 0x0a: // LDSMACH(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_MACH; + desc.set_r_used(REG_N); + desc.set_mach_modified(); return true; case 0x0b: // JSR(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_PR; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_r_used(REG_N); + desc.set_pr_modified(); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); desc.targetpc = BRANCH_TARGET_DYNAMIC; desc.delayslots = 1; return true; case 0x0e: // LDCSR(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_SR; - desc.flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_END_SEQUENCE; + desc.set_r_used(REG_N); + desc.set_sr_modified(); + desc.set_end_sequence(); + desc.set_can_expose_external_int(); return true; case 0x0f: // MAC_W(Rm, Rn); case 0x1f: // MAC_W(Rm, Rn); case 0x2f: // MAC_W(Rm, Rn); case 0x3f: // MAC_W(Rm, Rn); - desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N); - desc.regin[1] |= REGFLAG_MACL | REGFLAG_MACH; - desc.regout[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; + desc.set_r_used(REG_M); + desc.set_r_used(REG_N); + desc.set_mac_used(); + desc.set_r_modified(REG_M); + desc.set_r_modified(REG_N); + desc.set_mac_modified(); desc.cycles = 3; return true; case 0x10: // DT(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regin[1] |= REGFLAG_SR; - desc.regout[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_SR; + desc.set_r_used(REG_N); + desc.set_sr_used(); + desc.set_r_modified(REG_N); + desc.set_sr_modified(); return true; case 0x11: // CMPPZ(Rn); case 0x15: // CMPPL(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regin[1] |= REGFLAG_SR; - desc.regout[1] |= REGFLAG_SR; + desc.set_r_used(REG_N); + desc.set_sr_used(); + desc.set_sr_modified(); return true; case 0x12: // STSMMACL(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regin[1] |= REGFLAG_MACL; - desc.regout[0] |= REGFLAG_R(REG_N); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_r_used(REG_N); + desc.set_macl_used(); + desc.set_r_modified(REG_N); + desc.set_writes_memory(); return true; case 0x13: // STCMGBR(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regin[1] |= REGFLAG_GBR; - desc.regout[0] |= REGFLAG_R(REG_N); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_r_used(REG_N); + desc.set_gbr_used(); + desc.set_r_modified(REG_N); + desc.set_writes_memory(); return true; case 0x16: // LDSMMACL(Rn); - desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N); - desc.regout[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_MACL; - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_r_used(REG_M); + desc.set_r_used(REG_N); + desc.set_r_modified(REG_M); + desc.set_r_modified(REG_N); + desc.set_macl_modified(); + desc.set_reads_memory(); return true; case 0x17: // LDCMGBR(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regout[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_GBR; - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_r_used(REG_N); + desc.set_r_modified(REG_N); + desc.set_gbr_modified(); + desc.set_reads_memory(); return true; case 0x1a: // LDSMACL(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_MACL; + desc.set_r_used(REG_N); + desc.set_macl_modified(); return true; case 0x1b: // TAS(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regin[1] |= REGFLAG_SR; - desc.regout[1] |= REGFLAG_SR; + desc.set_r_used(REG_N); + desc.set_sr_used(); + desc.set_sr_modified(); desc.cycles = 4; - desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_WRITES_MEMORY; + desc.set_reads_memory(); + desc.set_writes_memory(); return true; case 0x1e: // LDCGBR(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_GBR; + desc.set_r_used(REG_N); + desc.set_gbr_modified(); return true; case 0x20: // SHAL(Rn); case 0x21: // SHAR(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regout[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_SR; + desc.set_r_used(REG_N); + desc.set_r_modified(REG_N); + desc.set_sr_modified(); return true; case 0x22: // STSMPR(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regin[1] |= REGFLAG_PR; - desc.regout[0] |= REGFLAG_R(REG_N); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_r_used(REG_N); + desc.set_pr_used(); + desc.set_r_modified(REG_N); + desc.set_writes_memory(); return true; case 0x23: // STCMVBR(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regin[1] |= REGFLAG_VBR; - desc.regout[0] |= REGFLAG_R(REG_N); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_r_used(REG_N); + desc.set_vbr_used(); + desc.set_r_modified(REG_N); + desc.set_writes_memory(); return true; case 0x24: // ROTCL(Rn); case 0x25: // ROTCR(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regin[1] |= REGFLAG_SR; - desc.regout[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_SR; + desc.set_r_used(REG_N); + desc.set_sr_used(); + desc.set_r_modified(REG_N); + desc.set_sr_modified(); return true; case 0x26: // LDSMPR(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regout[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_PR; - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_r_used(REG_N); + desc.set_r_modified(REG_N); + desc.set_pr_modified(); + desc.set_reads_memory(); return true; case 0x27: // LDCMVBR(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regout[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_VBR; - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_r_used(REG_N); + desc.set_r_modified(REG_N); + desc.set_vbr_modified(); + desc.set_reads_memory(); return true; case 0x2a: // LDSPR(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_PR; + desc.set_r_used(REG_N); + desc.set_pr_modified(); return true; case 0x2b: // JMP(Rm); - desc.regin[0] |= REGFLAG_R(REG_M); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_r_used(REG_M); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); desc.targetpc = BRANCH_TARGET_DYNAMIC; desc.delayslots = 1; return true; case 0x2e: // LDCVBR(Rn); - desc.regin[0] |= REGFLAG_R(REG_N); - desc.regout[1] |= REGFLAG_VBR; + desc.set_r_used(REG_N); + desc.set_vbr_modified(); return true; case 0x0c: // NOP(); diff --git a/src/devices/cpu/sh/sh_fe.h b/src/devices/cpu/sh/sh_fe.h new file mode 100644 index 00000000000..26439f8af8d --- /dev/null +++ b/src/devices/cpu/sh/sh_fe.h @@ -0,0 +1,120 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood, R. Belmont +/*************************************************************************** + + shfe.h + + Front end for SuperH recompiler + +***************************************************************************/ +#ifndef MAME_CPU_SH_SH_FE_H +#define MAME_CPU_SH_SH_FE_H + +#pragma once + +#include "sh.h" + +#include "cpu/drcfe.h" + + +class sh_common_execution::opcode_desc : public opcode_desc_base<opcode_desc, 32> +{ +public: + enum + { + REG_R0 = 0, + + REG_PR = REG_R0 + 16, + REG_SR, + REG_MACL, + REG_MACH, + REG_GBR, + REG_VBR, + + REG_COUNT + }; + + offs_t physpc; // physical PC of this opcode + + uint16_t opptr; // copy of opcode + + uint32_t cycles; // number of cycles needed to execute + + void set_r_used(unsigned n) { regin.set(REG_R0 + n); } + void set_pr_used() { regin.set(REG_PR); } + void set_sr_used() { regin.set(REG_SR); } + void set_macl_used() { regin.set(REG_MACL); } + void set_mach_used() { regin.set(REG_MACH); } + void set_mac_used() { set_macl_used(); set_mach_used(); } + void set_gbr_used() { regin.set(REG_GBR); } + void set_vbr_used() { regin.set(REG_VBR); } + + void set_r_modified(unsigned n) { regout.set(REG_R0 + n); } + void set_pr_modified() { regout.set(REG_PR); } + void set_sr_modified() { regout.set(REG_SR); } + void set_macl_modified() { regout.set(REG_MACL); } + void set_mach_modified() { regout.set(REG_MACH); } + void set_mac_modified() { set_macl_modified(); set_mach_modified(); } + void set_gbr_modified() { regout.set(REG_GBR); } + void set_vbr_modified() { regout.set(REG_VBR); } + + void set_reads_memory() { m_reads_memory = true; } + void set_writes_memory() { m_writes_memory = true; } + void set_can_expose_external_int() { m_can_expose_external_int = true; } + + bool reads_memory() const { return m_reads_memory; } + bool writes_memory() const { return m_writes_memory; } + bool can_expose_external_int() const { return m_can_expose_external_int; } + + // compute the exception PC + uint32_t epc() const { return in_delay_slot() ? (pc - 1) : pc; } + + void reset(offs_t curpc, bool in_delay_slot) + { + static_assert(REG_COUNT <= 32); + + opcode_desc_base::reset(curpc, in_delay_slot); + + physpc = curpc; + opptr = 0; + cycles = 0; + m_reads_memory = false; + m_writes_memory = false; + m_can_expose_external_int = false; + } + +private: + bool m_reads_memory; + bool m_writes_memory; + bool m_can_expose_external_int; +}; + + +class sh_common_execution::frontend : public drc_frontend_base<opcode_desc> +{ +public: + frontend(sh_common_execution *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); + virtual ~frontend(); + + opcode_desc const *describe_code(offs_t startpc); + +protected: + virtual uint16_t read_word(opcode_desc &desc); + + virtual bool describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + virtual bool describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + virtual bool describe_group_15(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) = 0; + + sh_common_execution *m_sh; + +private: + bool describe(opcode_desc &desc, const opcode_desc *prev); + + bool describe_group_2(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_3(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_6(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_8(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_12(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); +}; + +#endif // MAME_CPU_SH_SH_FE_H |
