summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/sh
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2026-03-02 09:25:23 +1100
committer Vas Crabb <vas@vastheman.com>2026-03-02 09:25:23 +1100
commit366b485b037b404a4a71f1caa77a4cacb83e17ef (patch)
tree5a952cf72bc53d6c1032738f21725e8ae55f152e /src/devices/cpu/sh
parentac492c02708b92ce76400214204a4fa9713d0a1a (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.cpp159
-rw-r--r--src/devices/cpu/sh/sh.h47
-rw-r--r--src/devices/cpu/sh/sh2.cpp9
-rw-r--r--src/devices/cpu/sh/sh2.h19
-rw-r--r--src/devices/cpu/sh/sh2fe.cpp9
-rw-r--r--src/devices/cpu/sh/sh2fe.h28
-rw-r--r--src/devices/cpu/sh/sh4.cpp101
-rw-r--r--src/devices/cpu/sh/sh4.h40
-rw-r--r--src/devices/cpu/sh/sh4comn.h2
-rw-r--r--src/devices/cpu/sh/sh4fe.cpp26
-rw-r--r--src/devices/cpu/sh/sh4fe.h36
-rw-r--r--src/devices/cpu/sh/sh_fe.cpp577
-rw-r--r--src/devices/cpu/sh/sh_fe.h120
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> &reglist, 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> &reglist, 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