diff options
| author | 2026-03-02 09:25:23 +1100 | |
|---|---|---|
| committer | 2026-03-02 09:25:23 +1100 | |
| commit | 366b485b037b404a4a71f1caa77a4cacb83e17ef (patch) | |
| tree | 5a952cf72bc53d6c1032738f21725e8ae55f152e | |
| 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.
56 files changed, 4234 insertions, 3220 deletions
diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 121ec87a8a6..9bf32fcaf66 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -32,8 +32,8 @@ if CPU_INCLUDE_DRC then MAME_DIR .. "src/devices/cpu/drcbeut.h", MAME_DIR .. "src/devices/cpu/drccache.cpp", MAME_DIR .. "src/devices/cpu/drccache.h", - MAME_DIR .. "src/devices/cpu/drcfe.cpp", MAME_DIR .. "src/devices/cpu/drcfe.h", + MAME_DIR .. "src/devices/cpu/drcfe.ipp", MAME_DIR .. "src/devices/cpu/drcuml.cpp", MAME_DIR .. "src/devices/cpu/drcuml.h", MAME_DIR .. "src/devices/cpu/uml.cpp", @@ -879,11 +879,13 @@ end if CPUS["SH"] then files { MAME_DIR .. "src/devices/cpu/sh/sh_fe.cpp", + MAME_DIR .. "src/devices/cpu/sh/sh_fe.h", MAME_DIR .. "src/devices/cpu/sh/sh.cpp", MAME_DIR .. "src/devices/cpu/sh/sh.h", MAME_DIR .. "src/devices/cpu/sh/sh2.cpp", MAME_DIR .. "src/devices/cpu/sh/sh2.h", MAME_DIR .. "src/devices/cpu/sh/sh2fe.cpp", + MAME_DIR .. "src/devices/cpu/sh/sh2fe.h", MAME_DIR .. "src/devices/cpu/sh/sh3comn.cpp", MAME_DIR .. "src/devices/cpu/sh/sh3comn.h", MAME_DIR .. "src/devices/cpu/sh/sh4.cpp", @@ -893,6 +895,7 @@ if CPUS["SH"] then MAME_DIR .. "src/devices/cpu/sh/sh4dmac.cpp", MAME_DIR .. "src/devices/cpu/sh/sh4dmac.h", MAME_DIR .. "src/devices/cpu/sh/sh4fe.cpp", + MAME_DIR .. "src/devices/cpu/sh/sh4fe.h", MAME_DIR .. "src/devices/cpu/sh/sh4regs.h", MAME_DIR .. "src/devices/cpu/sh/sh4tmu.cpp", MAME_DIR .. "src/devices/cpu/sh/sh4tmu.h", diff --git a/src/devices/cpu/drcfe.h b/src/devices/cpu/drcfe.h index 8e2455c85d2..6822028428c 100644 --- a/src/devices/cpu/drcfe.h +++ b/src/devices/cpu/drcfe.h @@ -33,6 +33,9 @@ #pragma once +#include <bitset> +#include <vector> + //************************************************************************** // CONSTANTS @@ -42,125 +45,161 @@ constexpr offs_t BRANCH_TARGET_DYNAMIC = ~offs_t(0); -// opcode branch flags -constexpr u32 OPFLAG_IS_UNCONDITIONAL_BRANCH = 0x00000001; // instruction is unconditional branch -constexpr u32 OPFLAG_IS_CONDITIONAL_BRANCH = 0x00000002; // instruction is conditional branch -constexpr u32 OPFLAG_IS_BRANCH = (OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_IS_CONDITIONAL_BRANCH); -constexpr u32 OPFLAG_IS_BRANCH_TARGET = 0x00000004; // instruction is the target of a branch -constexpr u32 OPFLAG_IN_DELAY_SLOT = 0x00000008; // instruction is in the delay slot of a branch -constexpr u32 OPFLAG_INTRABLOCK_BRANCH = 0x00000010; // instruction branches within the block - -// opcode exception flags -constexpr u32 OPFLAG_CAN_TRIGGER_SW_INT = 0x00000020; // instruction can trigger a software interrupt -constexpr u32 OPFLAG_CAN_EXPOSE_EXTERNAL_INT = 0x00000040; // instruction can expose an external interrupt -constexpr u32 OPFLAG_CAN_CAUSE_EXCEPTION = 0x00000080; // instruction may generate exception -constexpr u32 OPFLAG_WILL_CAUSE_EXCEPTION = 0x00000100; // instruction will generate exception -constexpr u32 OPFLAG_PRIVILEGED = 0x00000200; // instruction is privileged - -// opcode virtual->physical translation flags -constexpr u32 OPFLAG_VALIDATE_TLB = 0x00000400; // instruction must validate TLB before execution -constexpr u32 OPFLAG_MODIFIES_TRANSLATION = 0x00000800; // instruction modifies the TLB -constexpr u32 OPFLAG_COMPILER_PAGE_FAULT = 0x00001000; // compiler hit a page fault when parsing -constexpr u32 OPFLAG_COMPILER_UNMAPPED = 0x00002000; // compiler hit unmapped memory when parsing - -// opcode flags -constexpr u32 OPFLAG_INVALID_OPCODE = 0x00004000; // instruction is invalid -constexpr u32 OPFLAG_VIRTUAL_NOOP = 0x00008000; // instruction is a virtual no-op - -// opcode sequence flow flags -constexpr u32 OPFLAG_REDISPATCH = 0x00010000; // instruction must redispatch after completion -constexpr u32 OPFLAG_RETURN_TO_START = 0x00020000; // instruction must jump back to the beginning after completion -constexpr u32 OPFLAG_END_SEQUENCE = 0x00040000; // this is the last instruction in a sequence -constexpr u32 OPFLAG_CAN_CHANGE_MODES = 0x00080000; // instruction can change modes - -// execution semantics -constexpr u32 OPFLAG_READS_MEMORY = 0x00100000; // instruction reads memory -constexpr u32 OPFLAG_WRITES_MEMORY = 0x00200000; // instruction writes memory - - //************************************************************************** // TYPE DEFINITIONS //************************************************************************** // description of a given opcode -struct opcode_desc +template <typename Impl, size_t N> +class opcode_desc_base { - opcode_desc *next() const { return m_next; } +public: + using regmask = std::bitset<N>; + + Impl *next() const { return m_next; } + + void set_is_unconditional_branch() { m_flags.set(IS_UNCONDITIONAL_BRANCH); } + void set_is_conditional_branch() { m_flags.set(IS_CONDITIONAL_BRANCH); } + void set_is_branch_target() { m_flags.set(IS_BRANCH_TARGET); } + void set_in_delay_slot() { m_flags.set(IN_DELAY_SLOT); } + void set_intrablock_branch() { m_flags.set(INTRABLOCK_BRANCH); } + void set_can_cause_exception() { m_flags.set(CAN_CAUSE_EXCEPTION); } + void set_will_cause_exception() { m_flags.set(WILL_CAUSE_EXCEPTION); } + void set_validate_tlb() { m_flags.set(VALIDATE_TLB); } + void set_compiler_page_fault() { m_flags.set(COMPILER_PAGE_FAULT); } + void set_invalid_opcode() { m_flags.set(INVALID_OPCODE); } + void set_virtual_noop() { m_flags.set(VIRTUAL_NOOP); } + void set_redispatch() { m_flags.set(REDISPATCH); } + void set_return_to_start() { m_flags.set(RETURN_TO_START); } + void set_end_sequence() { m_flags.set(END_SEQUENCE); } + + bool is_unconditional_branch() const { return m_flags[IS_UNCONDITIONAL_BRANCH]; } + bool is_conditional_branch() const { return m_flags[IS_CONDITIONAL_BRANCH]; } + bool is_branch() const { return is_unconditional_branch() || is_conditional_branch(); } + bool is_branch_target() const { return m_flags[IS_BRANCH_TARGET]; } + bool in_delay_slot() const { return m_flags[IN_DELAY_SLOT]; } + bool intrablock_branch() const { return m_flags[INTRABLOCK_BRANCH]; } + bool can_cause_exception() const { return m_flags[CAN_CAUSE_EXCEPTION]; } + bool will_cause_exception() const { return m_flags[WILL_CAUSE_EXCEPTION]; } + bool validate_tlb() const { return m_flags[VALIDATE_TLB]; } + bool compiler_page_fault() const { return m_flags[COMPILER_PAGE_FAULT]; } + bool invalid_opcode() const { return m_flags[INVALID_OPCODE]; } + bool virtual_noop() const { return m_flags[VIRTUAL_NOOP]; } + bool redispatch() const { return m_flags[REDISPATCH]; } + bool return_to_start() const { return m_flags[RETURN_TO_START]; } + bool end_sequence() const { return m_flags[END_SEQUENCE]; } // links to other descriptions - opcode_desc * m_next; // pointer to next description - opcode_desc * branch; // pointer back to branch description for delay slots - simple_list<opcode_desc> delay; // pointer to delay slot description + Impl * m_next; // pointer to next description + Impl * branch; // pointer back to branch description for delay slots + simple_list<Impl> delay; // pointer to delay slot description // information about the current PC offs_t pc; // PC of this opcode - offs_t physpc; // physical PC of this opcode offs_t targetpc; // target PC if we are a branch, or BRANCH_TARGET_DYNAMIC - // copy of up to 16 bytes of opcode - union - { - u8 b[16]; - u16 w[8]; - u32 l[4]; - u64 q[2]; - } opptr; // pointer to opcode memory - // information about this instruction's execution u8 length; // length in bytes of this opcode u8 delayslots; // number of delay slots (for branches) u8 skipslots; // number of skip slots (for branches) - u32 flags; // OPFLAG_* opcode flags - u32 userflags; // core specific flags - u32 userdata0; // core specific data - u32 cycles; // number of cycles needed to execute // register usage information - u32 regin[4]; // input registers - u32 regout[4]; // output registers - u32 regreq[4]; // required output registers + regmask regin; // input registers + regmask regout; // output registers + regmask regreq; // required output registers + +protected: + enum + { + // opcode branch flags + IS_UNCONDITIONAL_BRANCH = 0, // instruction is unconditional branch + IS_CONDITIONAL_BRANCH, // instruction is conditional branch + IS_BRANCH_TARGET, // instruction is the target of a branch + IN_DELAY_SLOT, // instruction is in the delay slot of a branch + INTRABLOCK_BRANCH, // instruction branches within the block + + // opcode exception flags + CAN_CAUSE_EXCEPTION, // instruction may generate exception + WILL_CAUSE_EXCEPTION, // instruction will generate exception + + // opcode virtual->physical translation flags + VALIDATE_TLB, // instruction must validate TLB before execution + COMPILER_PAGE_FAULT, // compiler hit a page fault when parsing + + // opcode flags + INVALID_OPCODE, // instruction is invalid + VIRTUAL_NOOP, // instruction is a virtual no-op + + // opcode sequence flow flags + REDISPATCH, // instruction must redispatch after completion + RETURN_TO_START, // instruction must jump back to the beginning after completion + END_SEQUENCE, // this is the last instruction in a sequence + + FLAG_COUNT + }; + + void reset(offs_t curpc, bool in_delay_slot) + { + m_next = nullptr; + branch = nullptr; + delay.reset(); + pc = curpc; + targetpc = BRANCH_TARGET_DYNAMIC; + length = 0; + delayslots = 0; + skipslots = 0; + regin.reset(); + regout.reset(); + regreq.reset(); + m_flags.reset(); + + // set the delay slot flag + if (in_delay_slot) + set_in_delay_slot(); + } + + std::bitset<FLAG_COUNT> m_flags; }; // DRC frontend state -class drc_frontend +template <typename Desc> +class drc_frontend_base { public: // construction/destruction - drc_frontend(device_t &cpu, u32 window_start, u32 window_end, u32 max_sequence); - virtual ~drc_frontend(); + drc_frontend_base(offs_t pageshift, u32 window_start, u32 window_end, u32 max_sequence); + ~drc_frontend_base(); - // describe a block - opcode_desc const *describe_code(offs_t startpc); // get last opcode of block - opcode_desc const *get_last() { return m_desc_live_list.last(); } + Desc const *get_last() { return m_desc_live_list.last(); } protected: - // required overrides - virtual bool describe(opcode_desc &desc, opcode_desc const *prev) = 0; + // describe a block + template <typename T> + Desc const *do_describe_code(T && describe, offs_t startpc); private: // internal helpers - opcode_desc *describe_one(offs_t curpc, opcode_desc const *prevdesc, bool in_delay_slot = false); - void build_sequence(int start, int end, u32 endflag); - void accumulate_required_backwards(opcode_desc &desc, u32 *reqmask); + template <typename T> + Desc *describe_one(T &&describe, offs_t curpc, Desc const *prevdesc, bool in_delay_slot = false); + void build_sequence(int start, int end, bool redispatch); + void accumulate_required_backwards(Desc &desc, typename Desc::regmask &reqmask); void release_descriptions(); // configuration parameters - u32 m_window_start; // code window start offset = startpc - window_start - u32 m_window_end; // code window end offset = startpc + window_end - u32 m_max_sequence; // maximum instructions to include in a sequence + u32 const m_window_start; // code window start offset = startpc - window_start + u32 const m_window_end; // code window end offset = startpc + window_end + u32 const m_max_sequence; // maximum instructions to include in a sequence // CPU parameters - cpu_device & m_cpudevice; // CPU device object - address_space & m_program; // program address space for this CPU - offs_t m_pageshift; // shift to convert address to a page index + offs_t const m_pageshift; // shift to convert address to a page index // opcode descriptor arrays - simple_list<opcode_desc> m_desc_live_list; // list of live descriptions - fixed_allocator<opcode_desc> m_desc_allocator; // fixed allocator for descriptions - std::vector<opcode_desc *> m_desc_array; // array of descriptions in PC order + simple_list<Desc> m_desc_live_list; // list of live descriptions + fixed_allocator<Desc> m_desc_allocator; // fixed allocator for descriptions + std::vector<Desc *> m_desc_array; // array of descriptions in PC order }; #endif // MAME_CPU_DRCFE_H diff --git a/src/devices/cpu/drcfe.cpp b/src/devices/cpu/drcfe.ipp index a13f23f39f4..681cb85c50a 100644 --- a/src/devices/cpu/drcfe.cpp +++ b/src/devices/cpu/drcfe.ipp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles /*************************************************************************** - drcfe.c + drcfe.ipp Generic dynamic recompiler frontend structures and utilities. @@ -14,34 +14,14 @@ intrablock branches ***************************************************************************/ +#ifndef MAME_CPU_DRCFE_IPP +#define MAME_CPU_DRCFE_IPP -#include "emu.h" -#include "drcfe.h" - - -namespace { - -//************************************************************************** -// CONSTANTS -//************************************************************************** - -constexpr u32 MAX_STACK_DEPTH = 100; - - +#pragma once -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -// an entry that maps branches for our code walking -struct pc_stack_entry -{ - offs_t targetpc; - offs_t srcpc; -}; - -} // anonymous namespace +#include "drcfe.h" +#include <algorithm> //************************************************************************** @@ -49,26 +29,26 @@ struct pc_stack_entry //************************************************************************** //------------------------------------------------- -// drc_frontend - constructor +// drc_frontend_base - constructor //------------------------------------------------- -drc_frontend::drc_frontend(device_t &cpu, u32 window_start, u32 window_end, u32 max_sequence) +template <typename Desc> +drc_frontend_base<Desc>::drc_frontend_base(offs_t pageshift, u32 window_start, u32 window_end, u32 max_sequence) : m_window_start(window_start) , m_window_end(window_end) , m_max_sequence(max_sequence) - , m_cpudevice(downcast<cpu_device &>(cpu)) - , m_program(m_cpudevice.space(AS_PROGRAM)) - , m_pageshift(m_cpudevice.space_config(AS_PROGRAM)->page_shift()) + , m_pageshift(pageshift) , m_desc_array(window_end + window_start + 2, nullptr) { } //------------------------------------------------- -// ~drc_frontend - destructor +// ~drc_frontend_base - destructor //------------------------------------------------- -drc_frontend::~drc_frontend() +template <typename Desc> +drc_frontend_base<Desc>::~drc_frontend_base() { // release any descriptions we've accumulated release_descriptions(); @@ -81,8 +61,19 @@ drc_frontend::~drc_frontend() // relative to the specified startpc //------------------------------------------------- -const opcode_desc *drc_frontend::describe_code(offs_t startpc) +template <typename Desc> +template <typename T> +const Desc *drc_frontend_base<Desc>::do_describe_code(T &&describe, offs_t startpc) { + constexpr u32 MAX_STACK_DEPTH = 100; + + // an entry that maps branches for our code walking + struct pc_stack_entry + { + offs_t targetpc; + offs_t srcpc; + }; + // release any descriptions we've accumulated release_descriptions(); @@ -100,14 +91,17 @@ const opcode_desc *drc_frontend::describe_code(offs_t startpc) { // if we've already hit this PC, just mark it a branch target and continue pc_stack_entry *const curstack = --pcstackptr; - opcode_desc *curdesc = m_desc_array[curstack->targetpc - minpc]; + Desc *curdesc = m_desc_array[curstack->targetpc - minpc]; if (curdesc != nullptr) { - curdesc->flags |= OPFLAG_IS_BRANCH_TARGET; + curdesc->set_is_branch_target(); // if the branch crosses a page boundary, mark the target as needing to revalidate if (m_pageshift != 0 && ((curstack->srcpc ^ curdesc->pc) >> m_pageshift) != 0) - curdesc->flags |= OPFLAG_VALIDATE_TLB | OPFLAG_CAN_CAUSE_EXCEPTION; + { + curdesc->set_validate_tlb(); + curdesc->set_can_cause_exception(); + } // continue processing continue; @@ -117,39 +111,42 @@ const opcode_desc *drc_frontend::describe_code(offs_t startpc) for (offs_t curpc = curstack->targetpc; curpc >= minpc && curpc < maxpc && m_desc_array[curpc - minpc] == nullptr; curpc += m_desc_array[curpc - minpc]->length) { // allocate a new description and describe this instruction - m_desc_array[curpc - minpc] = curdesc = describe_one(curpc, curdesc); + m_desc_array[curpc - minpc] = curdesc = describe_one(describe, curpc, curdesc); // first instruction in a sequence is always a branch target if (curpc == curstack->targetpc) - curdesc->flags |= OPFLAG_IS_BRANCH_TARGET; + curdesc->set_is_branch_target(); // stop if we hit a page fault - if (curdesc->flags & OPFLAG_COMPILER_PAGE_FAULT) + if (curdesc->compiler_page_fault()) break; // if we are the first instruction in the whole window, we must validate the TLB if (curpc == startpc && m_pageshift != 0) - curdesc->flags |= OPFLAG_VALIDATE_TLB | OPFLAG_CAN_CAUSE_EXCEPTION; + { + curdesc->set_validate_tlb(); + curdesc->set_can_cause_exception(); + } // if we are a branch within the block range, add the branch target to our stack - if ((curdesc->flags & OPFLAG_IS_BRANCH) && curdesc->targetpc >= minpc && curdesc->targetpc < maxpc && pcstackptr < &pcstack[MAX_STACK_DEPTH]) + if (curdesc->is_branch() && (curdesc->targetpc >= minpc) && (curdesc->targetpc < maxpc) && (pcstackptr < &pcstack[MAX_STACK_DEPTH])) { - curdesc->flags |= OPFLAG_INTRABLOCK_BRANCH; + curdesc->set_intrablock_branch(); pcstackptr->srcpc = curdesc->pc; pcstackptr->targetpc = curdesc->targetpc; pcstackptr++; } // if we're done, we're done - if (curdesc->flags & OPFLAG_END_SEQUENCE) + if (curdesc->end_sequence()) break; } } // now build the list of descriptions in order // first from startpc -> maxpc, then from minpc -> startpc - build_sequence(startpc - minpc, maxpc - minpc, OPFLAG_REDISPATCH); - build_sequence(minpc - minpc, startpc - minpc, OPFLAG_RETURN_TO_START); + build_sequence(startpc - minpc, maxpc - minpc, true); + build_sequence(minpc - minpc, startpc - minpc, false); return m_desc_live_list.first(); } @@ -160,62 +157,55 @@ const opcode_desc *drc_frontend::describe_code(offs_t startpc) // slots of branches as well //------------------------------------------------- -opcode_desc *drc_frontend::describe_one(offs_t curpc, opcode_desc const *prevdesc, bool in_delay_slot) +template <typename Desc> +template <typename T> +Desc *drc_frontend_base<Desc>::describe_one(T &&describe, offs_t curpc, Desc const *prevdesc, bool in_delay_slot) { // initialize the description - opcode_desc *const desc = m_desc_allocator.alloc(); - desc->m_next = nullptr; - desc->branch = nullptr; - desc->delay.reset(); - desc->pc = curpc; - desc->physpc = curpc; - desc->targetpc = BRANCH_TARGET_DYNAMIC; - memset(&desc->opptr, 0x00, sizeof(desc->opptr)); - desc->length = 0; - desc->delayslots = 0; - desc->skipslots = 0; - // set the delay slot flag - desc->flags = in_delay_slot ? OPFLAG_IN_DELAY_SLOT : 0; - desc->userflags = 0; - desc->userdata0 = 0; - desc->cycles = 0; - memset(desc->regin, 0x00, sizeof(desc->regin)); - memset(desc->regout, 0x00, sizeof(desc->regout)); - memset(desc->regreq, 0x00, sizeof(desc->regreq)); + Desc *const desc = m_desc_allocator.alloc(); + desc->reset(curpc, in_delay_slot); // call the callback to describe an instruction if (!describe(*desc, prevdesc)) { - desc->flags |= OPFLAG_WILL_CAUSE_EXCEPTION | OPFLAG_INVALID_OPCODE; + desc->set_will_cause_exception(); + desc->set_invalid_opcode(); return desc; } // validate the TLB if we are exactly at the start of a page, or if we cross a page boundary if (m_pageshift != 0 && (((curpc - 1) ^ (curpc + desc->length - 1)) >> m_pageshift) != 0) - desc->flags |= OPFLAG_VALIDATE_TLB | OPFLAG_CAN_CAUSE_EXCEPTION; + { + desc->set_validate_tlb(); + desc->set_can_cause_exception(); + } // validate stuff - assert(desc->length > 0 || (desc->flags & OPFLAG_VIRTUAL_NOOP) != 0); + assert((desc->length > 0) || desc->virtual_noop()); // if we are a branch with delay slots, recursively walk those - if (desc->flags & OPFLAG_IS_BRANCH) + if (desc->is_branch()) { // iterate over slots and describe them offs_t delaypc = curpc + desc->length; // If this is a delay slot it is the true branch fork and the pc should be the previous branch target - if (desc->flags & OPFLAG_IN_DELAY_SLOT) { - if (prevdesc->targetpc != BRANCH_TARGET_DYNAMIC) { + if (desc->in_delay_slot()) + { + if (prevdesc->targetpc != BRANCH_TARGET_DYNAMIC) + { delaypc = prevdesc->targetpc; - //printf("drc_frontend::describe_one Branch in delay slot. curpc=%08X delaypc=%08X\n", curpc, delaypc); - } else { - //printf("drc_frontend::describe_one Warning! Branch in delay slot of dynamic target. curpc=%08X\n", curpc); + //printf("drc_frontend_base::describe_one Branch in delay slot. curpc=%08X delaypc=%08X\n", curpc, delaypc); + } + else + { + //printf("drc_frontend_base::describe_one Warning! Branch in delay slot of dynamic target. curpc=%08X\n", curpc); } } - opcode_desc *prev = desc; + Desc *prev = desc; for (u8 slotnum = 0; slotnum < desc->delayslots; slotnum++) { // recursively describe the next instruction - opcode_desc *delaydesc = describe_one(delaypc, prev, true); + Desc *delaydesc = describe_one(describe, delaypc, prev, true); if (delaydesc == nullptr) break; desc->delay.append(*delaydesc); @@ -225,7 +215,7 @@ opcode_desc *drc_frontend::describe_one(offs_t curpc, opcode_desc const *prevdes delaydesc->branch = desc; // stop if we hit a page fault - if (delaydesc->flags & OPFLAG_COMPILER_PAGE_FAULT) + if (delaydesc->compiler_page_fault()) break; // otherwise, advance @@ -241,19 +231,21 @@ opcode_desc *drc_frontend::describe_one(offs_t curpc, opcode_desc const *prevdes // of instructions //------------------------------------------------- -void drc_frontend::build_sequence(int start, int end, u32 endflag) +template <typename Desc> +void drc_frontend_base<Desc>::build_sequence(int start, int end, bool redispatch) { // iterate in order from start to end, picking up all non-NULL instructions int consecutive = 0; int seqstart = -1; int skipsleft = 0; for (int descnum = start; descnum < end; descnum++) + { if (m_desc_array[descnum] != nullptr) { // determine the next instruction, taking skips into account - opcode_desc *curdesc = m_desc_array[descnum]; + Desc *curdesc = m_desc_array[descnum]; int nextdescnum = descnum + curdesc->length; - opcode_desc *nextdesc = (nextdescnum < end) ? m_desc_array[nextdescnum] : nullptr; + Desc *nextdesc = (nextdescnum < end) ? m_desc_array[nextdescnum] : nullptr; for (u8 skipnum = 0; skipnum < curdesc->skipslots && nextdesc != nullptr; skipnum++) { nextdescnum = nextdescnum + nextdesc->length; @@ -264,16 +256,19 @@ void drc_frontend::build_sequence(int start, int end, u32 endflag) if (seqstart == -1 && skipsleft == 0) { // tag all start-of-sequence instructions as needing TLB verification - curdesc->flags |= OPFLAG_VALIDATE_TLB | OPFLAG_CAN_CAUSE_EXCEPTION; + curdesc->set_validate_tlb(); + curdesc->set_can_cause_exception(); seqstart = descnum; } // if we are the last instruction, indicate end-of-sequence and redispatch if (nextdesc == nullptr) { - curdesc->flags |= OPFLAG_END_SEQUENCE; - if (endflag != OPFLAG_RETURN_TO_START || nextdescnum == end) - curdesc->flags |= endflag; + curdesc->set_end_sequence(); + if (redispatch) + curdesc->set_redispatch(); + else if (nextdescnum == end) + curdesc->set_return_to_start(); } // otherwise, do some analysis based on the next instruction @@ -281,7 +276,7 @@ void drc_frontend::build_sequence(int start, int end, u32 endflag) { // if there are instructions between us and the next instruction, we must end our sequence here int scandescnum; - opcode_desc *scandesc = nullptr; + Desc *scandesc = nullptr; for (scandescnum = descnum + 1; scandescnum < end; scandescnum++) { scandesc = m_desc_array[scandescnum]; @@ -289,28 +284,33 @@ void drc_frontend::build_sequence(int start, int end, u32 endflag) break; } if (scandesc != nextdesc) - curdesc->flags |= OPFLAG_END_SEQUENCE; + curdesc->set_end_sequence(); // if the next instruction is a branch target, mark this instruction as end of sequence - if (nextdesc->flags & OPFLAG_IS_BRANCH_TARGET) - curdesc->flags |= OPFLAG_END_SEQUENCE; + if (nextdesc->is_branch_target()) + curdesc->set_end_sequence(); } // if we exceed the maximum consecutive count, cut off the sequence if (++consecutive >= m_max_sequence) - curdesc->flags |= OPFLAG_END_SEQUENCE; - if (curdesc->flags & OPFLAG_END_SEQUENCE) + curdesc->set_end_sequence(); + if (curdesc->end_sequence()) consecutive = 0; // if this is the end of a sequence, work backwards - if (curdesc->flags & OPFLAG_END_SEQUENCE) + if (curdesc->end_sequence()) { // figure out which registers we *must* generate, assuming at the end all must be - u32 reqmask[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }; + typename Desc::regmask reqmask; + reqmask.set(); if (seqstart != -1) + { for (int backdesc = descnum; backdesc != seqstart - 1; backdesc--) + { if (m_desc_array[backdesc] != nullptr) accumulate_required_backwards(*m_desc_array[backdesc], reqmask); + } + } // reset the register states seqstart = -1; @@ -318,7 +318,7 @@ void drc_frontend::build_sequence(int start, int end, u32 endflag) // if we have instructions remaining to be skipped, and this instruction is a branch target // belay the skip order - if (skipsleft > 0 && (curdesc->flags & OPFLAG_IS_BRANCH_TARGET)) + if ((skipsleft > 0) && curdesc->is_branch_target()) skipsleft = 0; // if we're not getting skipped, add us to the end of the list and clear our array slot @@ -334,9 +334,10 @@ void drc_frontend::build_sequence(int start, int end, u32 endflag) else if (skipsleft > 0) skipsleft--; } + } // zap the array - memset(&m_desc_array[start], 0, (end - start) * sizeof(m_desc_array[0])); + std::fill_n(&m_desc_array[start], end - start, nullptr); } @@ -346,33 +347,25 @@ void drc_frontend::build_sequence(int start, int end, u32 endflag) // walking in a backwards direction //------------------------------------------------- -void drc_frontend::accumulate_required_backwards(opcode_desc &desc, u32 *reqmask) +template <typename Desc> +void drc_frontend_base<Desc>::accumulate_required_backwards(Desc &desc, typename Desc::regmask &reqmask) { // recursively handle delay slots if (desc.delay.first() != nullptr) accumulate_required_backwards(*desc.delay.first(), reqmask); // if this is a branch, we have to reset our requests - if (desc.flags & OPFLAG_IS_BRANCH) - reqmask[0] = reqmask[1] = reqmask[2] = reqmask[3] = 0xffffffff; + if (desc.is_branch()) + reqmask = reqmask = reqmask = reqmask.set(); // determine the required registers - desc.regreq[0] = desc.regout[0] & reqmask[0]; - desc.regreq[1] = desc.regout[1] & reqmask[1]; - desc.regreq[2] = desc.regout[2] & reqmask[2]; - desc.regreq[3] = desc.regout[3] & reqmask[3]; + desc.regreq = desc.regout & reqmask; // any registers modified by this instruction aren't required upstream until referenced - reqmask[0] &= ~desc.regout[0]; - reqmask[1] &= ~desc.regout[1]; - reqmask[2] &= ~desc.regout[2]; - reqmask[3] &= ~desc.regout[3]; + reqmask &= ~desc.regout; // any registers required by this instruction now get marked required - reqmask[0] |= desc.regin[0]; - reqmask[1] |= desc.regin[1]; - reqmask[2] |= desc.regin[2]; - reqmask[3] |= desc.regin[3]; + reqmask |= desc.regin; } @@ -382,12 +375,15 @@ void drc_frontend::accumulate_required_backwards(opcode_desc &desc, u32 *reqmask // free list //------------------------------------------------ -void drc_frontend::release_descriptions() +template <typename Desc> +void drc_frontend_base<Desc>::release_descriptions() { // release all delay slots first - for (opcode_desc *curdesc = m_desc_live_list.first(); curdesc != nullptr; curdesc = curdesc->next()) + for (Desc *curdesc = m_desc_live_list.first(); curdesc != nullptr; curdesc = curdesc->next()) m_desc_allocator.reclaim_all(curdesc->delay); // reclaim all the descriptors m_desc_allocator.reclaim_all(m_desc_live_list); } + +#endif // MAME_CPU_DRCFE_IPP diff --git a/src/devices/cpu/dsp16/dsp16.h b/src/devices/cpu/dsp16/dsp16.h index f969f14e851..3e4b6f941fc 100644 --- a/src/devices/cpu/dsp16/dsp16.h +++ b/src/devices/cpu/dsp16/dsp16.h @@ -17,6 +17,7 @@ #include <memory> #include <utility> + class dsp16_device_base : public cpu_device, protected dsp16_disassembler::cpu { public: @@ -173,6 +174,7 @@ private: // recompiler helpers class core_state; + class opcode_desc; class frontend; class recompiler; struct core_destructer { void operator()(core_state *obj) const noexcept; }; diff --git a/src/devices/cpu/dsp16/dsp16fe.cpp b/src/devices/cpu/dsp16/dsp16fe.cpp index 406cf205433..4c10ed14a49 100644 --- a/src/devices/cpu/dsp16/dsp16fe.cpp +++ b/src/devices/cpu/dsp16/dsp16fe.cpp @@ -9,28 +9,41 @@ #include "emu.h" #include "dsp16fe.h" +#include "cpu/drcfe.ipp" + /*********************************************************************** construction/destruction ***********************************************************************/ dsp16_device_base::frontend::frontend(dsp16_device_base &host, u32 window_start, u32 window_end, u32 max_sequence) - : drc_frontend(host, window_start, window_end, max_sequence) + : drc_frontend_base(host.space_config(AS_PROGRAM)->page_shift(), window_start, window_end, max_sequence) , m_host(host) { } +dsp16_device_base::frontend::~frontend() +{ +} + /*********************************************************************** drc_frontend implementation ***********************************************************************/ +dsp16_device_base::opcode_desc const *dsp16_device_base::frontend::describe_code(offs_t startpc) +{ + return do_describe_code( + [this] (opcode_desc &desc, opcode_desc const *prev) { return describe(desc, prev); }, + startpc); +} + bool dsp16_device_base::frontend::describe(opcode_desc &desc, opcode_desc const *prev) { // most instructions are one word long and run in one machine cycle desc.length = 1U; desc.cycles = 1U; - u16 const op(m_host.m_pcache.read_word(desc.physpc)); + u16 const op(m_host.m_pcache.read_word(desc.pc)); switch (op >> 11) { case 0x00: // goto JA @@ -38,8 +51,9 @@ bool dsp16_device_base::frontend::describe(opcode_desc &desc, opcode_desc const case 0x10: // call JA case 0x11: desc.cycles = 2U; - desc.targetpc = (desc.physpc & XAAU_I_EXT) | (op_ja(op) & XAAU_I_MASK); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH; + desc.targetpc = (desc.pc & XAAU_I_EXT) | (op_ja(op) & XAAU_I_MASK); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); if (BIT(op, 15)) flag_output_reg(desc, REG_BIT_XAAU_PR); return true; @@ -79,7 +93,7 @@ bool dsp16_device_base::frontend::describe(opcode_desc &desc, opcode_desc const case 0x08: // aT = R desc.cycles = 2U; if (op & 0x000fU) // reserved field? - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); flag_output_reg(desc, op_d(op) ? REG_BIT_DAU_A0 : REG_BIT_DAU_A1, REG_BIT_DAU_PSW); describe_r(desc, op, true, false); return true; @@ -88,7 +102,7 @@ bool dsp16_device_base::frontend::describe(opcode_desc &desc, opcode_desc const case 0x0b: // R = a1 desc.cycles = 2U; if (op & 0x000fU) // reserved field? - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); flag_input_reg(desc, BIT(op, 12) ? REG_BIT_DAU_A1 : REG_BIT_DAU_A0, REG_BIT_DAU_AUC); describe_r(desc, op, false, true); return true; @@ -97,14 +111,14 @@ bool dsp16_device_base::frontend::describe(opcode_desc &desc, opcode_desc const desc.length = 2U; desc.cycles = 2U; if (op & 0x000fU) // reserved field? - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); describe_r(desc, op, false, true); return true; case 0x0c: // Y = R desc.cycles = 2U; if (op & 0x0400U) // reserved field? - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); describe_r(desc, op, true, false); describe_y(desc, op, false, true); return true; @@ -124,7 +138,7 @@ bool dsp16_device_base::frontend::describe(opcode_desc &desc, opcode_desc const case 0x0f: // R = Y desc.cycles = 2U; if (op & 0x0400U) // reserved field? - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); describe_r(desc, op, false, true); describe_y(desc, op, true, false); return true; @@ -175,7 +189,7 @@ bool dsp16_device_base::frontend::describe(opcode_desc &desc, opcode_desc const case 0x1b: // F1 ; y = a1 ; x = *pt++[i] desc.cycles = 2U; if (op & 0x000fU) - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); flag_input_reg(desc, BIT(op, 12) ? REG_BIT_DAU_A1 : REG_BIT_DAU_A0, REG_BIT_DAU_AUC); flag_output_reg(desc, REG_BIT_DAU_Y); describe_f1(desc, op); @@ -184,7 +198,7 @@ bool dsp16_device_base::frontend::describe(opcode_desc &desc, opcode_desc const case 0x1a: // if CON # icall if (op & 0x03e0U) // reserved field? - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); if (BIT(op, 10)) return describe_icall(desc, op); else @@ -200,7 +214,7 @@ bool dsp16_device_base::frontend::describe(opcode_desc &desc, opcode_desc const return true; case 0x1e: // Reserved - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); return true; case 0x1f: // F1 ; y = Y ; x = *pt++[i] @@ -221,7 +235,7 @@ bool dsp16_device_base::frontend::describe(opcode_desc &desc, opcode_desc const u16 dsp16_device_base::frontend::read_op(opcode_desc const &desc, u16 offset) { - return m_host.m_pcache.read_word((desc.physpc & XAAU_I_EXT) | ((desc.physpc + offset) & XAAU_I_MASK)); + return m_host.m_pcache.read_word((desc.pc & XAAU_I_EXT) | ((desc.pc + offset) & XAAU_I_MASK)); } /*********************************************************************** @@ -232,16 +246,17 @@ bool dsp16_device_base::frontend::describe_goto_b(opcode_desc &desc, u16 op) { desc.cycles = 2U; if (op & 0x00ffU) - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); switch (op_b(op)) { case 0x0: // return flag_input_reg(desc, REG_BIT_XAAU_PR); break; case 0x1: // ireturn - desc.flags |= OPFLAG_CAN_CHANGE_MODES; // FIXME: is this flag useful for a switch in/out of interrupt service mode? + desc.set_can_change_modes(); // FIXME: is this flag useful for a switch in/out of interrupt service mode? flag_input_reg(desc, REG_BIT_XAAU_PI); break; case 0x2: // goto pt @@ -255,7 +270,7 @@ bool dsp16_device_base::frontend::describe_goto_b(opcode_desc &desc, u16 op) case 0x5: case 0x6: case 0x7: - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); break; } return true; @@ -276,16 +291,17 @@ bool dsp16_device_base::frontend::describe_if_con(opcode_desc &desc, u16 op) switch (op_con(op)) { case 0xe: // true - desc.targetpc = (desc.physpc & XAAU_I_EXT) | (op_ja(next) & XAAU_I_MASK); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH; + desc.targetpc = (desc.pc & XAAU_I_EXT) | (op_ja(next) & XAAU_I_MASK); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); if (BIT(next, 15)) flag_output_reg(desc, REG_BIT_XAAU_PR); break; case 0xf: // false break; default: - desc.targetpc = (desc.physpc & XAAU_I_EXT) | (op_ja(next) & XAAU_I_MASK); - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.targetpc = (desc.pc & XAAU_I_EXT) | (op_ja(next) & XAAU_I_MASK); + desc.set_is_conditional_branch(); if (BIT(next, 15)) flag_output_reg(desc, REG_BIT_XAAU_PR); } @@ -306,13 +322,15 @@ bool dsp16_device_base::frontend::describe_if_con(opcode_desc &desc, u16 op) case 0x5: case 0x6: case 0x7: - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); break; } if (op_b(next) == 0x1) // can't predicate ireturn? { desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_CAN_CHANGE_MODES; // FIXME: confirm appropriate flags + desc.set_is_unconditional_branch(); // FIXME: confirm appropriate flags + desc.set_end_sequence(); + desc.set_can_change_modes(); flag_input_reg(desc, REG_BIT_XAAU_PI); } else @@ -321,7 +339,8 @@ bool dsp16_device_base::frontend::describe_if_con(opcode_desc &desc, u16 op) { case 0xe: // true desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); switch (op_b(next)) { case 0x0: // return @@ -340,7 +359,7 @@ bool dsp16_device_base::frontend::describe_if_con(opcode_desc &desc, u16 op) break; default: desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.set_is_conditional_branch(); switch (op_b(next)) { case 0x0: // return @@ -359,7 +378,7 @@ bool dsp16_device_base::frontend::describe_if_con(opcode_desc &desc, u16 op) break; default: - desc.flags |= OPFLAG_INVALID_OPCODE; // can't predicate things that aren't branches? + desc.set_invalid_opcode(); // can't predicate things that aren't branches? } describe_con(desc, op, true); return true; @@ -369,18 +388,22 @@ bool dsp16_device_base::frontend::describe_icall(opcode_desc &desc, u16 op) { desc.cycles = 3U; if (0x000eU != op_con(op)) // CON must be true for icall? - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); switch (op_con(op)) { case 0xe: // true desc.targetpc = 0x0002U; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_CAN_CHANGE_MODES; // FIXME: confirm appropriate flags + desc.set_is_unconditional_branch(); // FIXME: confirm appropriate flags + desc.set_end_sequence(); + desc.set_can_change_modes(); break; case 0xf: // false break; default: desc.targetpc = 0x0002U; - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH | OPFLAG_CAN_CHANGE_MODES; // FIXME: confirm appropriate flags + desc.set_is_unconditional_branch(); // FIXME: confirm appropriate flags + desc.set_end_sequence(); + desc.set_can_change_modes(); } describe_con(desc, op, true); return true; @@ -390,7 +413,7 @@ bool dsp16_device_base::frontend::describe_do(opcode_desc &desc, u16 op) { u16 const ni(op_ni(op)), k(op_k(op)); if (2U > k) // p3-25: "The iteration count can be between 2 and 127, inclusive" - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); desc.length = ni + 1; u32 cycles(0U), romcycles(0U), cachecycles(0U); for (u16 i = 0; i < ni; ++i) @@ -436,7 +459,7 @@ bool dsp16_device_base::frontend::describe_do(opcode_desc &desc, u16 op) case 0x08: // aT = R romcycles = cachecycles = 2U; if (op & 0x000fU) // reserved field? - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); flag_output_reg(desc, op_d(op) ? REG_BIT_DAU_A0 : REG_BIT_DAU_A1, REG_BIT_DAU_PSW); describe_r(desc, op, true, false); break; @@ -445,7 +468,7 @@ bool dsp16_device_base::frontend::describe_do(opcode_desc &desc, u16 op) case 0x0b: // R = a1 romcycles = cachecycles = 2U; if (op & 0x000fU) // reserved field? - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); flag_input_reg(desc, BIT(op, 12) ? REG_BIT_DAU_A1 : REG_BIT_DAU_A0, REG_BIT_DAU_AUC); describe_r(desc, op, false, true); break; @@ -453,7 +476,7 @@ bool dsp16_device_base::frontend::describe_do(opcode_desc &desc, u16 op) case 0x0c: // Y = R romcycles = cachecycles = 2U; if (op & 0x0400U) // reserved field? - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); describe_r(desc, op, true, false); describe_y(desc, op, false, true); break; @@ -467,7 +490,7 @@ bool dsp16_device_base::frontend::describe_do(opcode_desc &desc, u16 op) case 0x0f: // R = Y romcycles = cachecycles = 2U; if (op & 0x0400U) // reserved field? - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); describe_r(desc, op, false, true); describe_y(desc, op, true, false); break; @@ -520,7 +543,7 @@ bool dsp16_device_base::frontend::describe_do(opcode_desc &desc, u16 op) romcycles = 2U; cachecycles = 1U; if (op & 0x000fU) - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); flag_input_reg(desc, BIT(op, 12) ? REG_BIT_DAU_A1 : REG_BIT_DAU_A0, REG_BIT_DAU_AUC); flag_output_reg(desc, REG_BIT_DAU_Y); describe_f1(desc, op); @@ -554,7 +577,7 @@ bool dsp16_device_base::frontend::describe_do(opcode_desc &desc, u16 op) case 0x18: // goto B case 0x1a: // if CON # icall case 0x1e: // Reserved - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); m_cache_valid = false; return false; // not going to get into what happens if you cache ineligible instructions } @@ -563,10 +586,11 @@ bool dsp16_device_base::frontend::describe_do(opcode_desc &desc, u16 op) } m_cache_cycles = cycles; m_cache_last_cycles = cycles + (romcycles - cachecycles); - m_cache_flags = desc.flags & (OPFLAG_READS_MEMORY | OPFLAG_WRITES_MEMORY); - std::copy_n(desc.regin, std::size(desc.regin), m_cache_regin); - std::copy_n(desc.regout, std::size(desc.regout), m_cache_regout); - std::copy_n(desc.regreq, std::size(desc.regreq), m_cache_regreq); + m_cache_regin = desc.regin; + m_cache_regout = desc.regout; + m_cache_regreq = desc.regreq; + m_cache_reads_memory = desc.reads_memory(); + m_cache_writes_memory = desc.writes_memory(); m_cache_valid = true; desc.cycles += (2U - romcycles) + ((k - 1) * cycles) + (romcycles - cachecycles); return true; @@ -577,21 +601,24 @@ bool dsp16_device_base::frontend::describe_redo(opcode_desc &desc, u16 op) desc.cycles = 2U; u16 const k(op_k(op)); if (2U > k) // p3-25: "The iteration count can be between 2 and 127, inclusive" - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); - // assume that the block follwoing the last do K { ... } we examined is still cached - we can check properly when we actually run + // assume that the block following the last do K { ... } we examined is still cached - we can check properly when we actually run if (!m_cache_valid) { - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); return false; } else { desc.cycles += ((k - 1) * m_cache_cycles) + m_cache_last_cycles; - desc.flags |= m_cache_flags; - std::copy_n(m_cache_regin, std::size(desc.regin), desc.regin); - std::copy_n(m_cache_regout, std::size(desc.regout), desc.regout); - std::copy_n(m_cache_regreq, std::size(desc.regreq), desc.regreq); + desc.regin = m_cache_regin; + desc.regout = m_cache_regout; + desc.regreq = m_cache_regreq; + if (m_cache_reads_memory) + desc.set_reads_memory(); + if (m_cache_writes_memory) + desc.set_writes_memory(); return true; } } @@ -663,7 +690,7 @@ void dsp16_device_base::frontend::describe_r(opcode_desc &desc, u16 op, bool rea case 0x1e: // pdx1 break; default: - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); } } @@ -680,7 +707,7 @@ void dsp16_device_base::frontend::describe_con(opcode_desc &desc, u16 op, bool i flag_input_reg(desc, REG_BIT_DAU_PSW); break; case 0x4: // heads/tails - throw emu_fatalerror("DSP16: unimplemented CON value %02X (PC = %04X)\n", con, desc.physpc); + throw emu_fatalerror("DSP16: unimplemented CON value %02X (PC = %04X)\n", con, desc.pc); case 0x5: // c0ge/c0lt case 0x6: // c1ge/c1lt { @@ -694,7 +721,7 @@ void dsp16_device_base::frontend::describe_con(opcode_desc &desc, u16 op, bool i case 0x7: // true/false break; default: - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); } } @@ -796,7 +823,7 @@ void dsp16_device_base::frontend::describe_f2(opcode_desc &desc, u16 op) flag_output_reg(desc, d, REG_BIT_DAU_PSW); break; case 0xa: // Reserved - desc.flags |= OPFLAG_INVALID_OPCODE; + desc.set_invalid_opcode(); break; case 0xc: // aD = y flag_input_reg(desc, REG_BIT_DAU_Y); @@ -807,7 +834,7 @@ void dsp16_device_base::frontend::describe_f2(opcode_desc &desc, u16 op) void dsp16_device_base::frontend::describe_x(opcode_desc &desc, u16 op) { - desc.flags |= OPFLAG_READS_MEMORY; // TODO: is reading ROM the same as memory for dependency purposes? + desc.set_reads_memory(); // TODO: is reading ROM the same as memory for dependency purposes? flag_input_reg(desc, REG_BIT_XAAU_PT); flag_output_reg(desc, REG_BIT_XAAU_PT, REG_BIT_DAU_X); if (op_x(op)) @@ -818,9 +845,9 @@ void dsp16_device_base::frontend::describe_y(opcode_desc &desc, u16 op, bool rea { u32 const r(REG_BIT_YAAU_R0 + ((op >> 2) & 0x0003U)); if (read) - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); if (write) - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); switch (op & 0x0003U) { case 0x0: // *rN @@ -845,7 +872,8 @@ void dsp16_device_base::frontend::describe_y(opcode_desc &desc, u16 op, bool rea void dsp16_device_base::frontend::describe_z(opcode_desc &desc, u16 op) { u32 const r(REG_BIT_YAAU_R0 + ((op >> 2) & 0x0003U)); - desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_WRITES_MEMORY; + desc.set_reads_memory(); + desc.set_writes_memory(); flag_output_reg(desc, r); switch (op & 0x0003U) { diff --git a/src/devices/cpu/dsp16/dsp16fe.h b/src/devices/cpu/dsp16/dsp16fe.h index 8dc3b96700e..1045aa5e2aa 100644 --- a/src/devices/cpu/dsp16/dsp16fe.h +++ b/src/devices/cpu/dsp16/dsp16fe.h @@ -15,7 +15,37 @@ #include "cpu/drcfe.h" -class dsp16_device_base::frontend : public drc_frontend +class dsp16_device_base::opcode_desc : public opcode_desc_base<opcode_desc, 32> +{ +public: + u32 cycles; + + void set_can_change_modes() { m_can_change_modes = true; } + void set_reads_memory() { m_reads_memory = true; } + void set_writes_memory() { m_writes_memory = true; } + + bool can_change_modes() const { return m_can_change_modes; } + bool reads_memory() const { return m_reads_memory; } + bool writes_memory() const { return m_writes_memory; } + + void reset(offs_t curpc, bool in_delay_slot) + { + opcode_desc_base::reset(curpc, in_delay_slot); + + cycles = 0; + m_can_change_modes = false; + m_reads_memory = false; + m_writes_memory = false; + } + +private: + bool m_can_change_modes; + bool m_reads_memory; + bool m_writes_memory; +}; + + +class dsp16_device_base::frontend : public drc_frontend_base<opcode_desc> { public: enum : u8 @@ -59,12 +89,13 @@ public: // construction/destruction frontend(dsp16_device_base &host, u32 window_start, u32 window_end, u32 max_sequence); + ~frontend(); -protected: - // drc_frontend implementation - virtual bool describe(opcode_desc &desc, opcode_desc const *prev) override; + opcode_desc const *describe_code(offs_t startpc); private: + bool describe(opcode_desc &desc, opcode_desc const *prev); + // program fetch helpers u16 read_op(opcode_desc const &desc, u16 offset); u16 read_op(opcode_desc const &desc) { return read_op(desc, 0U); } @@ -87,10 +118,10 @@ private: static void describe_z(opcode_desc &desc, u16 op); // field access helpers - static void flag_reg(u32 (&flags)[4]) { } - template <typename... T> static void flag_reg(u32 (&flags)[4], u8 reg0, T... regn) + static void flag_reg(opcode_desc::regmask &flags) { } + template <typename... T> static void flag_reg(opcode_desc::regmask &flags, u8 reg0, T... regn) { - flags[reg0 >> 5] |= (u32(1) << (reg0 & (u32(32) - 1))); + flags.set(reg0); flag_reg(flags, regn...); } template <typename... T> static void flag_input_reg(opcode_desc &desc, T... reg) { flag_reg(desc.regin, reg...); } @@ -101,8 +132,9 @@ private: dsp16_device_base &m_host; // for making sweeping assumptions - u32 m_cache_cycles = 0U, m_cache_last_cycles = 0U, m_cache_flags = 0U; - decltype(opcode_desc::regin) m_cache_regin, m_cache_regout, m_cache_regreq; + u32 m_cache_cycles = 0U, m_cache_last_cycles = 0U; + opcode_desc::regmask m_cache_regin, m_cache_regout, m_cache_regreq; + bool m_cache_reads_memory = false, m_cache_writes_memory = false; bool m_cache_valid = false; }; diff --git a/src/devices/cpu/dspp/dspp.cpp b/src/devices/cpu/dspp/dspp.cpp index 92aa9cb7f06..9d7ed45d37b 100644 --- a/src/devices/cpu/dspp/dspp.cpp +++ b/src/devices/cpu/dspp/dspp.cpp @@ -142,7 +142,14 @@ dspp_bulldog_device::dspp_bulldog_device(const machine_config &mconfig, const ch { } -dspp_device::dspp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor code_map_ctor, address_map_constructor data_map_ctor) : +dspp_device::dspp_device( + const machine_config &mconfig, + device_type type, + const char *tag, + device_t *owner, + uint32_t clock, + address_map_constructor code_map_ctor, + address_map_constructor data_map_ctor) : cpu_device(mconfig, type, tag, owner, clock), m_int_handler(*this), m_dma_read_handler(*this, 0), @@ -184,6 +191,10 @@ dspp_device::dspp_device(const machine_config &mconfig, device_type type, const #endif } +dspp_device::~dspp_device() +{ +} + //------------------------------------------------- // device_start - start up the device @@ -201,7 +212,7 @@ void dspp_device::device_start() uint32_t flags = 0; m_drcuml = std::make_unique<drcuml_state>(*this, m_cache, flags, 1, 16, 0); - m_drcfe = std::make_unique<dspp_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE); + m_drcfe = std::make_unique<frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE); } else { diff --git a/src/devices/cpu/dspp/dspp.h b/src/devices/cpu/dspp/dspp.h index b7220dea5af..f5a2bd770b7 100644 --- a/src/devices/cpu/dspp/dspp.h +++ b/src/devices/cpu/dspp/dspp.h @@ -13,7 +13,6 @@ #pragma once -#include "cpu/drcfe.h" #include "cpu/drcuml.h" @@ -21,18 +20,14 @@ // TYPE DEFINITIONS //************************************************************************** -class dspp_frontend; - // ======================> dspp_device class dspp_device : public cpu_device { - friend class dspp_frontend; public: // Construction/destruction - dspp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor code_map_ctor, - address_map_constructor data_map_ctor); dspp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + virtual ~dspp_device(); // Static configuration helpers auto int_handler() { return m_int_handler.bind(); } @@ -73,24 +68,36 @@ public: void host_gw_control_write(offs_t offset, u16 data); protected: - // device-level overrides + class frontend; + class opcode_desc; + + dspp_device( + const machine_config &mconfig, + device_type type, + const char *tag, + device_t *owner, + uint32_t clock, + address_map_constructor code_map_ctor, + address_map_constructor data_map_ctor); + + // device_t implementation virtual void device_start() override ATTR_COLD; virtual void device_reset() override ATTR_COLD; - // device_execute_interface overrides + // device_execute_interface implementation virtual uint32_t execute_min_cycles() const noexcept override; virtual uint32_t execute_max_cycles() const noexcept override; virtual void execute_run() override; - // device_memory_interface overrides + // device_memory_interface implementation virtual space_config_vector memory_space_config() const override; - // device_state_interface overrides + // device_state_interface implementation virtual void state_import(const device_state_entry &entry) override; virtual void state_export(const device_state_entry &entry) override; virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; - // device_disasm_interface overrides + // device_disasm_interface implementation virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; void code_map(address_map &map) ATTR_COLD; @@ -309,7 +316,7 @@ private: bool m_cache_dirty; drc_cache m_cache; std::unique_ptr<drcuml_state> m_drcuml; - std::unique_ptr<dspp_frontend> m_drcfe; + std::unique_ptr<frontend> m_drcfe; uint32_t m_drcoptions; /* internal compiler state */ diff --git a/src/devices/cpu/dspp/dsppdrc.cpp b/src/devices/cpu/dspp/dsppdrc.cpp index 4992c0acf6d..6ba81c5baf5 100644 --- a/src/devices/cpu/dspp/dsppdrc.cpp +++ b/src/devices/cpu/dspp/dsppdrc.cpp @@ -35,11 +35,6 @@ inline void dspp_device::alloc_handle(code_handle **handleptr, const char *name) *handleptr = m_drcuml->handle_alloc(name); } -static inline uint32_t epc(const opcode_desc *desc) -{ - return desc->pc; -} - #if 0 static void cfunc_unimplemented(void *param) @@ -210,7 +205,7 @@ void dspp_device::compile_block(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); @@ -238,7 +233,7 @@ void dspp_device::compile_block(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 compiler.abortlabel = compiler.labelnum++; @@ -249,7 +244,7 @@ void dspp_device::compile_block(offs_t pc) UML_LABEL(block, compiler.abortlabel); /* if we need to return to the start, do it */ - if (seqlast->flags & OPFLAG_RETURN_TO_START) + if (seqlast->return_to_start()) nextpc = pc; /* otherwise we just go to the next instruction */ @@ -281,13 +276,13 @@ void dspp_device::generate_checksum_block(drcuml_block &block, compiler_state *c if (m_drcuml->logging()) block.append_comment("[Validation for %08X]", seqhead->pc); // comment - /* loose verify or single instruction: just compare and fail */ if (false/*!(m_drcoptions & DSPPDRC_STRICT_VERIFY)*/ || seqhead->next() == nullptr) { - if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP)) + // loose verify or single instruction: just compare and fail + if (!seqhead->virtual_noop()) { - uint32_t sum = seqhead->opptr.w[0]; - uint32_t addr = seqhead->physpc; + uint32_t sum = seqhead->opptr[0]; + uint32_t addr = seqhead->pc; const void *base = m_code_cache.read_ptr(addr); UML_MOV(block, I0, 0); UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x2); // load i0,base,0,word @@ -296,27 +291,28 @@ void dspp_device::generate_checksum_block(drcuml_block &block, compiler_state *c UML_EXHc(block, COND_NE, *m_nocode, seqhead->pc); // exne nocode,seqhead->pc } } - - /* full verification; sum up everything */ else { + // full verification; sum up everything uint32_t sum = 0; - uint32_t addr = seqhead->physpc; + uint32_t addr = seqhead->pc; const void *base = m_code_cache.read_ptr(addr); UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x2); // load i0,base,0,dword - sum += seqhead->opptr.w[0]; + sum += seqhead->opptr[0]; for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next()) - if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP)) + { + if (!curdesc->virtual_noop()) { - addr = curdesc->physpc; + addr = curdesc->pc; base = m_code_cache.read_ptr(addr); assert(base != nullptr); UML_LOAD(block, I1, base, 0, SIZE_WORD, SCALE_x2); // load i1,base,dword UML_ADD(block, I0, I0, I1); // add i0,i0,i1 - sum += curdesc->opptr.w[0]; + sum += curdesc->opptr[0]; } + } 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 } } @@ -414,16 +410,8 @@ void dspp_device::generate_sequence_instruction(drcuml_block &block, compiler_st UML_DEBUG(block, desc->pc); // debug desc->pc } - /* if we hit an unmapped address, fatal error */ - if (desc->flags & OPFLAG_COMPILER_UNMAPPED) - { - UML_MOV(block, mem(&m_core->m_pc), desc->pc); // mov [pc],desc->pc - save_fast_iregs(block); // <save fastregs> - UML_EXIT(block, EXECUTE_UNMAPPED_CODE); // exit EXECUTE_UNMAPPED_CODE - } - /* unless this is a virtual no-op, it's a regular instruction */ - if (!(desc->flags & OPFLAG_VIRTUAL_NOOP)) + if (!desc->virtual_noop()) { generate_opcode(block, compiler, desc); } @@ -443,7 +431,7 @@ void dspp_device::generate_update_cycles(drcuml_block &block, compiler_state *co void dspp_device::generate_opcode(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc) { - uint16_t op = desc->opptr.w[0]; + uint16_t op = desc->opptr[0]; UML_SUB(block, mem(&m_core->m_tclock), mem(&m_core->m_tclock), 1); UML_CALLC(block, cfunc_update_fifo_dma, this); @@ -457,7 +445,7 @@ void dspp_device::generate_opcode(drcuml_block &block, compiler_state *compiler, //UML_TEST(block, mem(&m_core->m_flag_sleep), 1); //UML_JMPc(block, COND_NZ, compiler->abortlabel); - //UML_MOV(block, mem(&m_core->m_arg0), desc->physpc); + //UML_MOV(block, mem(&m_core->m_arg0), desc->pc); //UML_MOV(block, mem(&m_core->m_arg1), op); //UML_CALLC(block, cfunc_print_sums, this); @@ -509,7 +497,7 @@ void dspp_device::generate_set_rbase(drcuml_block &block, compiler_state *compil void dspp_device::generate_super_special(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc) { - uint16_t op = desc->opptr.w[0]; + uint16_t op = desc->opptr[0]; uint32_t sel = (op >> 7) & 7; switch (sel) @@ -560,7 +548,7 @@ void dspp_device::generate_super_special(drcuml_block &block, compiler_state *co void dspp_device::generate_special_opcode(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc) { - uint16_t op = desc->opptr.w[0]; + uint16_t op = desc->opptr[0]; switch ((op >> 10) & 7) { @@ -666,7 +654,7 @@ void dspp_device::generate_branch(drcuml_block &block, compiler_state *compiler, if (desc->targetpc != BRANCH_TARGET_DYNAMIC) { generate_update_cycles(block, &compiler_temp, desc->targetpc); // <subtract cycles> - if (desc->flags & OPFLAG_INTRABLOCK_BRANCH) + if (desc->intrablock_branch()) UML_JMP(block, desc->targetpc | 0x80000000); // jmp desc->targetpc | 0x80000000 else UML_HASHJMP(block, 0, desc->targetpc, *m_nocode); // hashjmp <mode>,desc->targetpc,nocode @@ -686,7 +674,7 @@ void dspp_device::generate_branch(drcuml_block &block, compiler_state *compiler, void dspp_device::generate_branch_opcode(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc) { - uint16_t op = desc->opptr.w[0]; + uint16_t op = desc->opptr[0]; if (m_drcuml->logging()) block.append_comment("branch_opcode"); @@ -734,7 +722,7 @@ void dspp_device::generate_branch_opcode(drcuml_block &block, compiler_state *co void dspp_device::generate_complex_branch_opcode(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc) { - uint16_t op = desc->opptr.w[0]; + uint16_t op = desc->opptr[0]; switch ((op >> 10) & 7) { @@ -929,7 +917,7 @@ void dspp_device::generate_parse_operands(drcuml_block &block, compiler_state *c void dspp_device::generate_read_next_operand(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc) { - //uint16_t op = (uint16_t)desc->opptr.w[0]; + //uint16_t op = desc->opptr[0]; code_label no_load; if (m_drcuml->logging()) @@ -977,7 +965,7 @@ void dspp_device::generate_write_next_operand(drcuml_block &block, compiler_stat void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc) { - uint16_t op = (uint16_t)desc->opptr.w[0]; + uint16_t op = desc->opptr[0]; uint32_t numops = (op >> 13) & 3; uint32_t muxa = (op >> 10) & 3; uint32_t muxb = (op >> 8) & 3; diff --git a/src/devices/cpu/dspp/dsppfe.cpp b/src/devices/cpu/dspp/dsppfe.cpp index 19b2cb1a3b8..f614a327bc9 100644 --- a/src/devices/cpu/dspp/dsppfe.cpp +++ b/src/devices/cpu/dspp/dsppfe.cpp @@ -10,71 +10,32 @@ #include "emu.h" #include "dsppfe.h" +#include "cpu/drcfe.ipp" -//#define REG_USED(desc,x) do { (desc).regin[0] |= 1 << (x); } while(0) -//#define REG_MODIFIED(desc,x) do { (desc).regout[0] |= 1 << (x); } while(0) - -#define CC_C_USED(desc) do { (desc).regin[0] |= 1 << 16; } while(0) -#define CC_C_MODIFIED(desc) do { (desc).regout[0] |= 1 << 16; } while(0) -#define CC_Z_USED(desc) do { (desc).regin[0] |= 1 << 16; } while(0) -#define CC_Z_MODIFIED(desc) do { (desc).regout[0] |= 1 << 16; } while(0) -#define CC_N_USED(desc) do { (desc).regin[0] |= 1 << 16; } while(0) -#define CC_N_MODIFIED(desc) do { (desc).regout[0] |= 1 << 16; } while(0) -#define CC_V_USED(desc) do { (desc).regin[0] |= 1 << 16; } while(0) -#define CC_V_MODIFIED(desc) do { (desc).regout[0] |= 1 << 16; } while(0) -#define CC_X_USED(desc) do { (desc).regin[0] |= 1 << 16; } while(0) -#define CC_X_MODIFIED(desc) do { (desc).regout[0] |= 1 << 16; } while(0) - -#define CC_FLAGS_MODIFIED(desc) do { } while(0) - -dspp_frontend::dspp_frontend(dspp_device *dspp, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) - : drc_frontend(*dspp, window_start, window_end, max_sequence), - m_dspp(dspp) + +dspp_device::frontend::frontend(dspp_device *dspp, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) + : drc_frontend_base(dspp->space_config(AS_PROGRAM)->page_shift(), window_start, window_end, max_sequence) + , m_dspp(dspp) +{ + +} + +dspp_device::frontend::~frontend() { +} + +dspp_device::opcode_desc const *dspp_device::frontend::describe_code(offs_t startpc) +{ + return do_describe_code( + [this] (opcode_desc &desc, opcode_desc const *prev) { return describe(desc, prev); }, + startpc); } -#if 0 -// opcode branch flags -const uint32_t OPFLAG_IS_UNCONDITIONAL_BRANCH = 0x00000001; // instruction is unconditional branch -const uint32_t OPFLAG_IS_CONDITIONAL_BRANCH = 0x00000002; // instruction is conditional branch -const uint32_t OPFLAG_IS_BRANCH = (OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_IS_CONDITIONAL_BRANCH); -const uint32_t OPFLAG_IS_BRANCH_TARGET = 0x00000004; // instruction is the target of a branch -const uint32_t OPFLAG_IN_DELAY_SLOT = 0x00000008; // instruction is in the delay slot of a branch -const uint32_t OPFLAG_INTRABLOCK_BRANCH = 0x00000010; // instruction branches within the block - -// opcode exception flags -const uint32_t OPFLAG_CAN_TRIGGER_SW_INT = 0x00000020; // instruction can trigger a software interrupt -const uint32_t OPFLAG_CAN_EXPOSE_EXTERNAL_INT = 0x00000040; // instruction can expose an external interrupt -const uint32_t OPFLAG_CAN_CAUSE_EXCEPTION = 0x00000080; // instruction may generate exception -const uint32_t OPFLAG_WILL_CAUSE_EXCEPTION = 0x00000100; // instruction will generate exception -const uint32_t OPFLAG_PRIVILEGED = 0x00000200; // instruction is privileged - -// opcode virtual->physical translation flags -const uint32_t OPFLAG_VALIDATE_TLB = 0x00000400; // instruction must validate TLB before execution -const uint32_t OPFLAG_MODIFIES_TRANSLATION = 0x00000800; // instruction modifies the TLB -const uint32_t OPFLAG_COMPILER_PAGE_FAULT = 0x00001000; // compiler hit a page fault when parsing -const uint32_t OPFLAG_COMPILER_UNMAPPED = 0x00002000; // compiler hit unmapped memory when parsing - -// opcode flags -const uint32_t OPFLAG_INVALID_OPCODE = 0x00004000; // instruction is invalid -const uint32_t OPFLAG_VIRTUAL_NOOP = 0x00008000; // instruction is a virtual no-op - -// opcode sequence flow flags -const uint32_t OPFLAG_REDISPATCH = 0x00010000; // instruction must redispatch after completion -const uint32_t OPFLAG_RETURN_TO_START = 0x00020000; // instruction must jump back to the beginning after completion -const uint32_t OPFLAG_END_SEQUENCE = 0x00040000; // this is the last instruction in a sequence -const uint32_t OPFLAG_CAN_CHANGE_MODES = 0x00080000; // instruction can change modes - -// execution semantics -const uint32_t OPFLAG_READS_MEMORY = 0x00100000; // instruction reads memory -const uint32_t OPFLAG_WRITES_MEMORY = 0x00200000; // instruction writes memory -#endif - -bool dspp_frontend::describe(opcode_desc &desc, const opcode_desc *prev) +bool dspp_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) { - uint16_t op = desc.opptr.w[0] = m_dspp->read_op(desc.physpc); + const uint16_t op = desc.opptr[0] = m_dspp->read_op(desc.pc); desc.cycles = 1; desc.length = 1; @@ -104,7 +65,7 @@ bool dspp_frontend::describe(opcode_desc &desc, const opcode_desc *prev) return true; } -void dspp_frontend::describe_special(uint16_t op, opcode_desc &desc) +void dspp_device::frontend::describe_special(uint16_t op, opcode_desc &desc) { switch ((op >> 10) & 7) { @@ -115,13 +76,15 @@ void dspp_frontend::describe_special(uint16_t op, opcode_desc &desc) { case 1: // BAC { - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); desc.targetpc = BRANCH_TARGET_DYNAMIC; return; } case 4: // RTS { - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); desc.targetpc = BRANCH_TARGET_DYNAMIC; return; } @@ -133,7 +96,8 @@ void dspp_frontend::describe_special(uint16_t op, opcode_desc &desc) case 7: // SLEEP { - desc.flags |= OPFLAG_END_SEQUENCE | OPFLAG_RETURN_TO_START; + desc.set_end_sequence(); + desc.set_return_to_start(); return; } @@ -148,13 +112,15 @@ void dspp_frontend::describe_special(uint16_t op, opcode_desc &desc) } case 1: // JUMP { - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); desc.targetpc = op & 0x3ff; return; } case 2: // JSR { - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); desc.targetpc = op & 0x3ff; return; } @@ -165,11 +131,11 @@ void dspp_frontend::describe_special(uint16_t op, opcode_desc &desc) } case 4: // MOVEREG { - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); // Indirect if (op & 0x0010) - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); parse_operands(op, desc, 1); return; @@ -180,84 +146,85 @@ void dspp_frontend::describe_special(uint16_t op, opcode_desc &desc) } case 6: // MOVED { - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); parse_operands(op, desc, 1); return; } case 7: // MOVEI { - desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_WRITES_MEMORY; + desc.set_reads_memory(); + desc.set_writes_memory(); parse_operands(op, desc, 1); return; } } } -void dspp_frontend::describe_branch(uint16_t op, opcode_desc &desc) +void dspp_device::frontend::describe_branch(uint16_t op, opcode_desc &desc) { const uint32_t select = (op >> 12) & 1; if (select == 0) { - CC_N_USED(desc); - CC_V_USED(desc); + desc.set_cc_n_used(); + desc.set_cc_v_used(); } else { - CC_C_USED(desc); - CC_Z_USED(desc); + desc.set_cc_c_used(); + desc.set_cc_z_used(); } // TODO: Can these be unconditional? - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.set_is_conditional_branch(); desc.targetpc = op & 0x3ff; } -void dspp_frontend::describe_complex_branch(uint16_t op, opcode_desc &desc) +void dspp_device::frontend::describe_complex_branch(uint16_t op, opcode_desc &desc) { switch ((op >> 10) & 7) { case 0: // BLT - CC_N_USED(desc); - CC_V_USED(desc); + desc.set_cc_n_used(); + desc.set_cc_v_used(); break; case 1: // BLE - CC_N_USED(desc); - CC_V_USED(desc); - CC_Z_USED(desc); + desc.set_cc_n_used(); + desc.set_cc_v_used(); + desc.set_cc_z_used(); break; case 2: // BGE - CC_N_USED(desc); - CC_V_USED(desc); + desc.set_cc_n_used(); + desc.set_cc_v_used(); break; case 3: // BGT - CC_N_USED(desc); - CC_V_USED(desc); - CC_Z_USED(desc); + desc.set_cc_n_used(); + desc.set_cc_v_used(); + desc.set_cc_z_used(); break; case 4: // BHI case 5: // BLS - CC_C_USED(desc); - CC_Z_USED(desc); + desc.set_cc_c_used(); + desc.set_cc_z_used(); break; case 6: // BXS case 7: // BXC - CC_X_USED(desc); + desc.set_cc_x_used(); break; } - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.set_is_conditional_branch(); desc.targetpc = op & 0x3ff; } -void dspp_frontend::describe_arithmetic(uint16_t op, opcode_desc &desc) +void dspp_device::frontend::describe_arithmetic(uint16_t op, opcode_desc &desc) { // Decode the various fields uint32_t numops = (op >> 13) & 3; - uint32_t muxa = (op >> 10) & 3; - uint32_t muxb = (op >> 8) & 3; - uint32_t alu_op = (op >> 4) & 0xf; - uint32_t barrel_code = op & 0xf; + const uint32_t muxa = (op >> 10) & 3; + const uint32_t muxb = (op >> 8) & 3; + const uint32_t alu_op = (op >> 4) & 0xf; + const uint32_t barrel_code = op & 0xf; // Check for operand overflow if (numops == 0 && ((muxa == 1) || (muxa == 2) || (muxb == 1) || (muxb == 2))) @@ -278,7 +245,7 @@ void dspp_frontend::describe_arithmetic(uint16_t op, opcode_desc &desc) if (muxa > 0 || muxb > 0) { - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); } switch (alu_op) @@ -304,32 +271,32 @@ void dspp_frontend::describe_arithmetic(uint16_t op, opcode_desc &desc) case 14: // _XOR case 15: // _XNOR { - CC_C_MODIFIED(desc); - CC_V_MODIFIED(desc); + desc.set_cc_c_modified(); + desc.set_cc_v_modified(); break; } case 3: // _+C case 5: // _-B { - CC_C_USED(desc); - CC_C_MODIFIED(desc); + desc.set_cc_c_used(); + desc.set_cc_c_modified(); break; } } - CC_N_MODIFIED(desc); - CC_Z_MODIFIED(desc); - CC_X_MODIFIED(desc); + desc.set_cc_n_modified(); + desc.set_cc_z_modified(); + desc.set_cc_x_modified(); } -void dspp_frontend::parse_operands(uint16_t op, opcode_desc &desc, uint32_t numops) +void dspp_device::frontend::parse_operands(uint16_t op, opcode_desc &desc, uint32_t numops) { uint32_t numregs = 0; uint32_t opidx = 0; while (opidx < numops) { - uint16_t operand = desc.opptr.w[opidx + 1] = m_dspp->read_op(desc.physpc + opidx + 1); + uint16_t operand = desc.opptr[opidx + 1] = m_dspp->read_op(desc.pc + opidx + 1); desc.length++; desc.cycles++; @@ -344,10 +311,10 @@ void dspp_frontend::parse_operands(uint16_t op, opcode_desc &desc, uint32_t numo else if((operand & 0xe000) == 0x8000) { if (operand & 0x0400) // Indirect - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); if (operand & 0x0800 )// Write Back - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); opidx++; } @@ -373,21 +340,21 @@ void dspp_frontend::parse_operands(uint16_t op, opcode_desc &desc, uint32_t numo if (regdi & 0x0010) { // Indirect - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); } if (numregs == 2) { // Write back if ((i == 0) && (operand & 0x1000)) - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); else if ((i == 1) && (operand & 0x0800)) - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); } else if (numregs == 1) { if (operand & 0x800) - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); } opidx++; } diff --git a/src/devices/cpu/dspp/dsppfe.h b/src/devices/cpu/dspp/dsppfe.h index 5c0023e313a..b4eccfda3ee 100644 --- a/src/devices/cpu/dspp/dsppfe.h +++ b/src/devices/cpu/dspp/dsppfe.h @@ -14,51 +14,81 @@ #pragma once #include "dspp.h" + #include "cpu/drcfe.h" +#include <cassert> +#include <algorithm> + //************************************************************************** -// MACROS +// TYPE DEFINITIONS //************************************************************************** -// register flags 0 -#define REGFLAG_R(n) (1 << (n)) -#define REGFLAG_RZ(n) (((n) == 0) ? 0 : REGFLAG_R(n)) +class dspp_device::opcode_desc : public opcode_desc_base<opcode_desc, 16> +{ +public: + uint16_t opptr[6]; // copy of opcode and operands -// register flags 1 -#define REGFLAG_FR(n) (1 << (n)) + uint32_t cycles; // number of cycles needed to execute -// register flags 2 -#define REGFLAG_CR(n) (0xf0000000 >> (4 * (n))) -#define REGFLAG_CR_BIT(n) (0x80000000 >> (n)) + void set_cc_c_used() { regin.set(REG_CC_C); } + void set_cc_c_modified() { regout.set(REG_CC_C); } + void set_cc_z_used() { regin.set(REG_CC_Z); } + void set_cc_z_modified() { regout.set(REG_CC_Z); } + void set_cc_n_used() { regin.set(REG_CC_N); } + void set_cc_n_modified() { regout.set(REG_CC_N); } + void set_cc_v_used() { regin.set(REG_CC_V); } + void set_cc_v_modified() { regout.set(REG_CC_V); } + void set_cc_x_used() { regin.set(REG_CC_X); } + void set_cc_x_modified() { regout.set(REG_CC_X); } -// register flags 3 -#define REGFLAG_XER_CA (1 << 0) -#define REGFLAG_XER_OV (1 << 1) -#define REGFLAG_XER_SO (1 << 2) -#define REGFLAG_XER_COUNT (1 << 3) -#define REGFLAG_CTR (1 << 4) -#define REGFLAG_LR (1 << 5) -#define REGFLAG_FPSCR(n) (1 << (6 + (n))) + void set_reads_memory() { m_reads_memory = true; } + void set_writes_memory() { m_writes_memory = true; } + bool reads_memory() const { return m_reads_memory; } + bool writes_memory() const { return m_writes_memory; } + uint32_t epc() const { return pc; } + + void reset(offs_t curpc, bool in_delay_slot) + { + static_assert(REG_COUNT <= 16); + + opcode_desc_base::reset(curpc, in_delay_slot); + + std::fill(std::begin(opptr), std::end(opptr), 0); + cycles = 0; + } + +private: + enum + { + REG_CC_C = 0, + REG_CC_Z, + REG_CC_N, + REG_CC_V, + REG_CC_X, + + REG_COUNT + }; + + bool m_reads_memory; + bool m_writes_memory; +}; -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** -class dspp_frontend : public drc_frontend +class dspp_device::frontend : public drc_frontend_base<opcode_desc> { public: // construction/destruction - dspp_frontend(dspp_device *dspp, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); + frontend(dspp_device *dspp, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); + ~frontend(); -protected: - // required overrides - virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override; + opcode_desc const *describe_code(offs_t startpc); private: - // inlines + bool describe(opcode_desc &desc, opcode_desc const *prev); // internal helpers void describe_special(uint16_t op, opcode_desc &desc); diff --git a/src/devices/cpu/e132xs/e132xs.cpp b/src/devices/cpu/e132xs/e132xs.cpp index b3a44a8f923..6d4b1792552 100644 --- a/src/devices/cpu/e132xs/e132xs.cpp +++ b/src/devices/cpu/e132xs/e132xs.cpp @@ -1620,7 +1620,7 @@ void hyperstone_device::device_start() m_drcuml->symbol_add(&m_core->arg1, sizeof(uint32_t), "arg1"); // initialize the front-end helper - m_drcfe = std::make_unique<e132xs_frontend>(*this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, m_single_instruction_mode ? 1 : COMPILE_MAX_SEQUENCE); + m_drcfe = std::make_unique<frontend>(*this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, m_single_instruction_mode ? 1 : COMPILE_MAX_SEQUENCE); // generate invariant code generate_invariant(); diff --git a/src/devices/cpu/e132xs/e132xs.h b/src/devices/cpu/e132xs/e132xs.h index 17b8012480b..a04c9762812 100644 --- a/src/devices/cpu/e132xs/e132xs.h +++ b/src/devices/cpu/e132xs/e132xs.h @@ -7,9 +7,7 @@ #include "32xsdasm.h" -#include "cpu/drcfe.h" #include "cpu/drcuml.h" -#include "cpu/drcumlsh.h" #include <utility> @@ -44,9 +42,6 @@ // TYPE DEFINITIONS //************************************************************************** -class e132xs_frontend; - - enum { E132XS_PC = 1, @@ -107,8 +102,6 @@ enum // Used by core CPU interface class hyperstone_device : public cpu_device, public hyperstone_disassembler::config { - friend class e132xs_frontend; - public: // input line numbers static inline constexpr int INPUT_INT1 = 0; @@ -125,6 +118,9 @@ public: virtual ~hyperstone_device() override; protected: + class frontend; + class opcode_desc; + using b_r_delegate = delegate<uint8_t (offs_t)>; using hw_r_delegate = delegate<uint16_t (offs_t)>; using w_r_delegate = delegate<uint32_t (offs_t)>; @@ -445,7 +441,7 @@ private: drc_cache m_cache; std::unique_ptr<drcuml_state> m_drcuml; - std::unique_ptr<e132xs_frontend> m_drcfe; + std::unique_ptr<frontend> m_drcfe; uint32_t m_drcoptions; bool m_single_instruction_mode; uint8_t m_cache_dirty; diff --git a/src/devices/cpu/e132xs/e132xsdrc.cpp b/src/devices/cpu/e132xs/e132xsdrc.cpp index 597f7576eb8..88b7bdc11fa 100644 --- a/src/devices/cpu/e132xs/e132xsdrc.cpp +++ b/src/devices/cpu/e132xs/e132xsdrc.cpp @@ -3,8 +3,11 @@ #include "emu.h" #include "e132xs.h" -#include "e132xsfe.h" + #include "32xsdefs.h" +#include "e132xsfe.h" + +#include "cpu/drcumlsh.h" /* map variables */ @@ -14,17 +17,6 @@ /*------------------------------------------------- - epc - compute the exception PC from a - descriptor --------------------------------------------------*/ - -static inline uint32_t epc(const opcode_desc *desc) -{ - return (desc->flags & OPFLAG_IN_DELAY_SLOT) ? desc->branch->pc : desc->pc; -} - - -/*------------------------------------------------- alloc_handle - allocate a handle if not already allocated -------------------------------------------------*/ @@ -294,7 +286,7 @@ void hyperstone_device::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); @@ -319,11 +311,11 @@ void hyperstone_device::code_compile_block(uint8_t mode, offs_t pc) } // validate this code block if we're not pointing into ROM - if (m_program->get_write_ptr(seqhead->physpc) != nullptr) + if (m_program->get_write_ptr(seqhead->pc) != nullptr) 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); UML_MOV(block, I7, 0); @@ -337,7 +329,7 @@ void hyperstone_device::code_compile_block(uint8_t mode, offs_t pc) } uint32_t nextpc; - if (seqlast->flags & OPFLAG_RETURN_TO_START) /* if we need to return to the start, do it */ + if (seqlast->return_to_start()) /* if we need to return to the start, do it */ nextpc = pc; else /* otherwise we just go to the next instruction */ nextpc = seqlast->pc + seqlast->length; @@ -695,10 +687,10 @@ void hyperstone_device::generate_checksum_block(drcuml_block &block, compiler_st /* loose verify or single instruction: just compare and fail */ if (!(m_drcoptions & E132XS_STRICT_VERIFY) || !seqhead->next()) { - if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP)) + if (!seqhead->virtual_noop()) { - uint32_t sum = seqhead->opptr.w[0]; - uint32_t addr = seqhead->physpc; + uint32_t sum = seqhead->opptr[0]; + uint32_t addr = seqhead->pc; const void *base = m_prptr(addr); if (!base) { @@ -708,32 +700,32 @@ void hyperstone_device::generate_checksum_block(drcuml_block &block, compiler_st auto const *delayslot = seqhead->delay.first(); const void *delaybase = nullptr; - if (delayslot && (seqhead->physpc != delayslot->physpc)) + if (delayslot && (seqhead->pc != delayslot->pc)) { - delaybase = m_prptr(delayslot->physpc); + delaybase = m_prptr(delayslot->pc); if (!delaybase) { - osd_printf_info("%s: cache read_ptr returned nullptr for address %08x\n", tag(), delayslot->physpc); + osd_printf_info("%s: cache read_ptr returned nullptr for address %08x\n", tag(), delayslot->pc); } } UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x1); - if (delayslot && (seqhead->physpc != delayslot->physpc)) + if (delayslot && (seqhead->pc != delayslot->pc)) { UML_LOAD(block, I1, delaybase, 0, SIZE_WORD, SCALE_x1); UML_ADD(block, I0, I0, I1); - sum += delayslot->opptr.w[0]; + sum += delayslot->opptr[0]; } UML_CMP(block, I0, sum); - UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); + UML_EXHc(block, COND_NE, *m_nocode, seqhead->epc()); } } else /* full verification; sum up everything */ { - uint32_t addr = seqhead->physpc; + uint32_t addr = seqhead->pc; const void *base = m_prptr(addr); if (!base) { @@ -743,32 +735,32 @@ void hyperstone_device::generate_checksum_block(drcuml_block &block, compiler_st UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x1); - uint32_t sum = seqhead->opptr.w[0]; + uint32_t sum = seqhead->opptr[0]; for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next()) { - if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP)) + if (!curdesc->virtual_noop()) { - addr = curdesc->physpc; + addr = curdesc->pc; base = m_prptr(addr); assert(base != nullptr); UML_LOAD(block, I1, base, 0, SIZE_WORD, SCALE_x1); UML_ADD(block, I0, I0, I1); - sum += curdesc->opptr.w[0]; + sum += curdesc->opptr[0]; - if (curdesc->delay.first() != nullptr && (curdesc == seqlast || (curdesc->next() != nullptr && curdesc->next()->physpc != curdesc->delay.first()->physpc))) + if (curdesc->delay.first() != nullptr && (curdesc == seqlast || (curdesc->next() != nullptr && curdesc->next()->pc != curdesc->delay.first()->pc))) { - addr = curdesc->delay.first()->physpc; + addr = curdesc->delay.first()->pc; base = m_prptr(addr); assert(base != nullptr); UML_LOAD(block, I1, base, 0, SIZE_WORD, SCALE_x1); UML_ADD(block, I0, I0, I1); - sum += curdesc->delay.first()->opptr.w[0]; + sum += curdesc->delay.first()->opptr[0]; } } } UML_CMP(block, I0, sum); - UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); + UML_EXHc(block, COND_NE, *m_nocode, seqhead->epc()); } } @@ -800,7 +792,7 @@ void hyperstone_device::generate_branch(drcuml_block &block, compiler_state &com generate_update_cycles(block); - if (desc && (mode == compiler.mode()) && (desc->flags & OPFLAG_INTRABLOCK_BRANCH)) + if (desc && (mode == compiler.mode()) && desc->intrablock_branch()) { assert(desc->targetpc != BRANCH_TARGET_DYNAMIC); @@ -831,8 +823,8 @@ void hyperstone_device::generate_branch(drcuml_block &block, compiler_state &com void hyperstone_device::generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { // 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[0]); // check for pending interrupts UML_SUB(block, I0, mem(&m_core->intblock), 1); @@ -851,7 +843,7 @@ void hyperstone_device::generate_sequence_instruction(drcuml_block &block, compi UML_DEBUG(block, desc->pc); } - if (!(desc->flags & OPFLAG_VIRTUAL_NOOP)) + if (!desc->virtual_noop()) { // set the PC map variable UML_MAPVAR(block, MAPVAR_PC, compiler.set_pc(desc->pc + desc->length)); @@ -898,7 +890,7 @@ void hyperstone_device::generate_sequence_instruction(drcuml_block &block, compi } else { - UML_MOV(block, mem(&m_core->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_core->arg0), desc->opptr[0]); UML_CALLC(block, &c_funcs::unimplemented, this); } } @@ -908,7 +900,7 @@ void hyperstone_device::generate_sequence_instruction(drcuml_block &block, compi bool hyperstone_device::generate_opcode(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - uint32_t op = (uint32_t)desc->opptr.w[0]; + uint32_t op = (uint32_t)desc->opptr[0]; switch (op >> 8) { diff --git a/src/devices/cpu/e132xs/e132xsdrc_ops.hxx b/src/devices/cpu/e132xs/e132xsdrc_ops.hxx index bc8675fa7c9..ee3cce9b584 100644 --- a/src/devices/cpu/e132xs/e132xsdrc_ops.hxx +++ b/src/devices/cpu/e132xs/e132xsdrc_ops.hxx @@ -37,7 +37,7 @@ uint32_t hyperstone_device::generate_get_const(const opcode_desc *desc) uint32_t hyperstone_device::generate_get_immediate_s(const opcode_desc *desc) { - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; switch (op & 0xf) { @@ -56,7 +56,7 @@ uint32_t hyperstone_device::generate_get_immediate_s(const opcode_desc *desc) uint32_t hyperstone_device::generate_get_pcrel(const opcode_desc *desc) { - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; if (op & 0x80) { @@ -332,7 +332,7 @@ uml::parameter hyperstone_device::generate_load_address_ad(drcuml_block &block, { return 0; } - else if ((code == PC_REGISTER) && ((desc->flags & OPFLAG_IN_DELAY_SLOT) || !compiler.check_delay())) + else if ((code == PC_REGISTER) && (desc->in_delay_slot() || !compiler.check_delay())) { if (!compiler.pc()) generate_raise_exception(block, compiler, desc, TRAPNO_POINTER_ERROR); @@ -578,7 +578,7 @@ void hyperstone_device::generate_update_nz_d(drcuml_block &block, compiler_state void hyperstone_device::generate_raise_exception(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint8_t trapno, uml::parameter sr) { - if (desc->flags & OPFLAG_IN_DELAY_SLOT) + if (desc->in_delay_slot()) { // definitely in delay slot - saved PC/ILC reflect delayed branch UML_OR(block, sr, sr, P_MASK); @@ -684,7 +684,7 @@ inline void hyperstone_device::generate_logic_op(drcuml_block &block, compiler_s UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t src_code = op & 0xf; @@ -751,7 +751,7 @@ void hyperstone_device::generate_software(drcuml_block &block, compiler_state &c { UML_MOV(block, I7, mem(&m_core->clock_cycles_6)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t num = op >> 8; const uint32_t src_code = op & 0xf; @@ -830,7 +830,7 @@ void hyperstone_device::generate_chk(drcuml_block &block, compiler_state &compil { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -891,7 +891,7 @@ void hyperstone_device::generate_movd(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_2)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t srcf_code = src_code + 1; @@ -1048,7 +1048,7 @@ void hyperstone_device::generate_divsu(drcuml_block &block, compiler_state &comp { UML_MOV(block, I7, mem(&m_core->clock_cycles_36)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t dstf_code = dst_code + 1; @@ -1131,7 +1131,7 @@ void hyperstone_device::generate_xm(drcuml_block &block, compiler_state &compile { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t src_code = op & 0xf; @@ -1179,7 +1179,7 @@ void hyperstone_device::generate_mask(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -1205,7 +1205,7 @@ void hyperstone_device::generate_sum(drcuml_block &block, compiler_state &compil { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -1215,7 +1215,7 @@ void hyperstone_device::generate_sum(drcuml_block &block, compiler_state &compil if (!SrcGlobal || !DstGlobal) UML_BFXU(block, I3, I2, FP_SHIFT, 7); - if (SrcGlobal && (src_code == PC_REGISTER) && ((desc->flags & OPFLAG_IN_DELAY_SLOT) || !compiler.check_delay())) + if (SrcGlobal && (src_code == PC_REGISTER) && (desc->in_delay_slot() || !compiler.check_delay())) { const uint64_t result = uint64_t(compiler.pc()) + src; const uint32_t flags = @@ -1248,7 +1248,7 @@ void hyperstone_device::generate_sums(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -1289,7 +1289,7 @@ void hyperstone_device::generate_cmp(drcuml_block &block, compiler_state &compil { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -1311,7 +1311,7 @@ void hyperstone_device::generate_mov(drcuml_block &block, compiler_state &compil { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -1431,7 +1431,7 @@ void hyperstone_device::generate_add(drcuml_block &block, compiler_state &compil { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -1439,7 +1439,7 @@ void hyperstone_device::generate_add(drcuml_block &block, compiler_state &compil if (!SrcGlobal || !DstGlobal) UML_BFXU(block, I3, I2, FP_SHIFT, 7); - if ((desc->flags & OPFLAG_IN_DELAY_SLOT) || !compiler.check_delay()) + if (desc->in_delay_slot() || !compiler.check_delay()) { const bool srcpc = SrcGlobal && (src_code == PC_REGISTER); const bool dstpc = DstGlobal && (dst_code == PC_REGISTER); @@ -1507,7 +1507,7 @@ void hyperstone_device::generate_adds(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -1547,7 +1547,7 @@ void hyperstone_device::generate_cmpb(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -1568,7 +1568,7 @@ void hyperstone_device::generate_subc(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -1601,7 +1601,7 @@ void hyperstone_device::generate_sub(drcuml_block &block, compiler_state &compil { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -1626,7 +1626,7 @@ void hyperstone_device::generate_subs(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -1666,7 +1666,7 @@ void hyperstone_device::generate_addc(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -1699,7 +1699,7 @@ void hyperstone_device::generate_neg(drcuml_block &block, compiler_state &compil { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t src_code = op & 0xf; @@ -1723,7 +1723,7 @@ void hyperstone_device::generate_negs(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t src_code = op & 0xf; @@ -1821,7 +1821,7 @@ void hyperstone_device::generate_not(drcuml_block &block, compiler_state &compil { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t src_code = op & 0xf; @@ -1845,7 +1845,7 @@ void hyperstone_device::generate_cmpi(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; uint32_t src; @@ -1872,7 +1872,7 @@ void hyperstone_device::generate_movi(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; uint32_t src; @@ -1956,7 +1956,7 @@ void hyperstone_device::generate_addi(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const bool roundeven = !(op & 0x10f); @@ -1970,7 +1970,7 @@ void hyperstone_device::generate_addi(drcuml_block &block, compiler_state &compi if (!DstGlobal) UML_BFXU(block, I3, I2, FP_SHIFT, 7); - if (DstGlobal && (dst_code == PC_REGISTER) && ((desc->flags & OPFLAG_IN_DELAY_SLOT) || !compiler.check_delay())) + if (DstGlobal && (dst_code == PC_REGISTER) && (desc->in_delay_slot() || !compiler.check_delay())) { uint64_t result; uint32_t flags; @@ -2034,7 +2034,7 @@ void hyperstone_device::generate_cmpbi(drcuml_block &block, compiler_state &comp { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t n = ((op & 0x100) >> 4) | (op & 0x0f); @@ -2092,7 +2092,7 @@ void hyperstone_device::generate_andni(drcuml_block &block, compiler_state &comp { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; uint32_t src; if (DRC_N_OP_MASK == 0x10f) @@ -2117,7 +2117,7 @@ void hyperstone_device::generate_ori(drcuml_block &block, compiler_state &compil { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; uint32_t src; if (ImmLong) @@ -2139,7 +2139,7 @@ void hyperstone_device::generate_xori(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; uint32_t src; if (ImmLong) @@ -2161,7 +2161,7 @@ void hyperstone_device::generate_shrdi(drcuml_block &block, compiler_state &comp { UML_MOV(block, I7, mem(&m_core->clock_cycles_2)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t n = HiN ? DRC_HI_N_VALUE : DRC_LO_N_VALUE; @@ -2195,7 +2195,7 @@ void hyperstone_device::generate_shrd(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_2)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -2238,7 +2238,7 @@ void hyperstone_device::generate_shr(drcuml_block &block, compiler_state &compil { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t src_code = op & 0xf; @@ -2270,7 +2270,7 @@ void hyperstone_device::generate_shri(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t n = HiN ? DRC_HI_N_VALUE : DRC_LO_N_VALUE; @@ -2300,7 +2300,7 @@ void hyperstone_device::generate_sardi(drcuml_block &block, compiler_state &comp { UML_MOV(block, I7, mem(&m_core->clock_cycles_2)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t n = HiN ? DRC_HI_N_VALUE : DRC_LO_N_VALUE; @@ -2334,7 +2334,7 @@ void hyperstone_device::generate_sard(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_2)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -2377,7 +2377,7 @@ void hyperstone_device::generate_sar(drcuml_block &block, compiler_state &compil { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t src_code = op & 0xf; @@ -2409,7 +2409,7 @@ void hyperstone_device::generate_sari(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t n = HiN ? DRC_HI_N_VALUE : DRC_LO_N_VALUE; @@ -2439,7 +2439,7 @@ void hyperstone_device::generate_shldi(drcuml_block &block, compiler_state &comp { UML_MOV(block, I7, mem(&m_core->clock_cycles_2)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t n = HiN ? DRC_HI_N_VALUE : DRC_LO_N_VALUE; @@ -2488,7 +2488,7 @@ void hyperstone_device::generate_shld(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_2)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -2544,7 +2544,7 @@ void hyperstone_device::generate_shl(drcuml_block &block, compiler_state &compil { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t src_code = op & 0xf; @@ -2593,7 +2593,7 @@ void hyperstone_device::generate_shli(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t n = HiN ? DRC_HI_N_VALUE : DRC_LO_N_VALUE; @@ -2637,7 +2637,7 @@ void hyperstone_device::generate_testlz(drcuml_block &block, compiler_state &com { UML_MOV(block, I7, mem(&m_core->clock_cycles_2)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t src_code = op & 0xf; @@ -2655,7 +2655,7 @@ void hyperstone_device::generate_rol(drcuml_block &block, compiler_state &compil { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t src_code = op & 0xf; @@ -2702,7 +2702,7 @@ void hyperstone_device::generate_rol(drcuml_block &block, compiler_state &compil template <hyperstone_device::reg_bank DstGlobal, hyperstone_device::reg_bank SrcGlobal> void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t srcf_code = src_code + 1; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -2845,7 +2845,7 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp template <hyperstone_device::reg_bank DstGlobal, hyperstone_device::reg_bank SrcGlobal> void hyperstone_device::generate_ldxx2(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t srcf_code = src_code + 1; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -2994,7 +2994,7 @@ void hyperstone_device::generate_ldxx2(drcuml_block &block, compiler_state &comp template <hyperstone_device::reg_bank DstGlobal, hyperstone_device::reg_bank SrcGlobal> void hyperstone_device::generate_stxx1(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -3121,7 +3121,7 @@ void hyperstone_device::generate_stxx1(drcuml_block &block, compiler_state &comp template <hyperstone_device::reg_bank DstGlobal, hyperstone_device::reg_bank SrcGlobal> void hyperstone_device::generate_stxx2(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -3280,7 +3280,7 @@ void hyperstone_device::generate_mulsu(drcuml_block &block, compiler_state &comp { UML_MOV(block, I7, mem(&m_core->clock_cycles_36)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t dstf_code = dst_code + 1; const uint32_t src_code = op & 0xf; @@ -3349,7 +3349,7 @@ void hyperstone_device::generate_mulsu(drcuml_block &block, compiler_state &comp template <hyperstone_device::reg_bank DstGlobal, hyperstone_device::reg_bank SrcGlobal> void hyperstone_device::generate_mul(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -3399,7 +3399,7 @@ void hyperstone_device::generate_set(drcuml_block &block, compiler_state &compil { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t n = op & 0xf; @@ -3479,7 +3479,7 @@ void hyperstone_device::generate_ldwr(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -3504,7 +3504,7 @@ void hyperstone_device::generate_lddr(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_2)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -3550,7 +3550,7 @@ void hyperstone_device::generate_ldwp(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -3582,7 +3582,7 @@ void hyperstone_device::generate_lddp(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_2)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -3634,7 +3634,7 @@ void hyperstone_device::generate_stwr(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -3668,7 +3668,7 @@ void hyperstone_device::generate_stdr(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_2)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -3719,7 +3719,7 @@ void hyperstone_device::generate_stwp(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -3764,7 +3764,7 @@ void hyperstone_device::generate_stdp(drcuml_block &block, compiler_state &compi { UML_MOV(block, I7, mem(&m_core->clock_cycles_2)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; @@ -3928,14 +3928,14 @@ void hyperstone_device::generate_dbr(drcuml_block &block, compiler_state &compil { UML_MOV(block, mem(&m_core->delay_slot_taken), 0); generate_update_cycles(block); - if (desc->flags & OPFLAG_INTRABLOCK_BRANCH) + if (desc->intrablock_branch()) UML_JMP(block, desc->targetpc | 0x80000000); else UML_HASHJMP(block, compiler.mode(), desc->targetpc, *m_nocode); } else { - UML_MOV(block, mem(&m_core->arg0), delayslot->opptr.w[0]); + UML_MOV(block, mem(&m_core->arg0), delayslot->opptr[0]); UML_CALLC(block, &c_funcs::unimplemented, this); } } @@ -3948,7 +3948,7 @@ void hyperstone_device::generate_frame(drcuml_block &block, compiler_state &comp { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t dst_code = (op & 0xf0) >> 4; UML_MOV(block, I2, DRC_SR); // I2 = SR @@ -3995,7 +3995,7 @@ void hyperstone_device::generate_call(drcuml_block &block, compiler_state &compi UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); UML_ROLINS(block, DRC_SR, ((desc->length >> 1) << ILC_SHIFT) | P_MASK, 0, ILC_MASK | P_MASK); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; uint16_t imm_1 = m_pr16(desc->pc + 2); int32_t extra_s = 0; @@ -4079,7 +4079,7 @@ void hyperstone_device::generate_trap_op(drcuml_block &block, compiler_state &co false, false, false, false, true, false, true, false, true, false, true, false, true, false, true, false }; - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint8_t trapno = (op & 0xfc) >> 2; const uint8_t code = ((op & 0x300) >> 6) | (op & 0x03); @@ -4101,7 +4101,7 @@ void hyperstone_device::generate_extend(drcuml_block &block, compiler_state &com { UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); - const uint16_t op = desc->opptr.w[0]; + const uint16_t op = desc->opptr[0]; const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; diff --git a/src/devices/cpu/e132xs/e132xsfe.cpp b/src/devices/cpu/e132xs/e132xsfe.cpp index 729bdad1a9f..87d9f0f36d1 100644 --- a/src/devices/cpu/e132xs/e132xsfe.cpp +++ b/src/devices/cpu/e132xs/e132xsfe.cpp @@ -10,38 +10,55 @@ #include "emu.h" #include "e132xsfe.h" + #include "32xsdefs.h" +#include "cpu/drcfe.ipp" + + #define FE_DST_CODE ((op & 0xf0) >> 4) #define FE_SRC_CODE (op & 0x0f) -#define SR_CODE (1 << 1) +#define SR_CODE (1) +#define G_CODE_BASE (0) + /*************************************************************************** INSTRUCTION PARSERS ***************************************************************************/ -e132xs_frontend::e132xs_frontend(hyperstone_device &cpu, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) - : drc_frontend(cpu, window_start, window_end, max_sequence) +hyperstone_device::frontend::frontend(hyperstone_device &cpu, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) + : drc_frontend_base(cpu.space_config(AS_PROGRAM)->page_shift(), window_start, window_end, max_sequence) , m_cpu(cpu) { } -inline uint16_t e132xs_frontend::read_word(opcode_desc &desc) +hyperstone_device::frontend::~frontend() +{ +} + +hyperstone_device::opcode_desc const *hyperstone_device::frontend::describe_code(offs_t startpc) +{ + return do_describe_code( + [this] (opcode_desc &desc, opcode_desc const *prev) { return describe(desc, prev); }, + startpc); +} + +inline uint16_t hyperstone_device::frontend::read_word(opcode_desc &desc) { - return m_cpu.m_pr16(desc.physpc); + return m_cpu.m_pr16(desc.pc); } -inline uint16_t e132xs_frontend::read_imm1(opcode_desc &desc) +inline uint16_t hyperstone_device::frontend::read_imm1(opcode_desc &desc) { - return m_cpu.m_pr16(desc.physpc + 2); + return m_cpu.m_pr16(desc.pc + 2); } -inline uint16_t e132xs_frontend::read_imm2(opcode_desc &desc) +inline uint16_t hyperstone_device::frontend::read_imm2(opcode_desc &desc) { - return m_cpu.m_pr16(desc.physpc + 4); + return m_cpu.m_pr16(desc.pc + 4); } -inline uint32_t e132xs_frontend::read_ldstxx_imm(opcode_desc &desc) +inline uint32_t hyperstone_device::frontend::read_ldstxx_imm(opcode_desc &desc) { const uint16_t imm1 = read_imm1(desc); uint32_t extra_s; @@ -63,7 +80,7 @@ inline uint32_t e132xs_frontend::read_ldstxx_imm(opcode_desc &desc) return extra_s; } -inline uint32_t e132xs_frontend::read_limm(opcode_desc &desc, uint16_t op) +inline uint32_t hyperstone_device::frontend::read_limm(opcode_desc &desc, uint16_t op) { static const int32_t immediate_values[16] = { @@ -88,7 +105,7 @@ inline uint32_t e132xs_frontend::read_limm(opcode_desc &desc, uint16_t op) } } -inline int32_t e132xs_frontend::decode_pcrel(opcode_desc &desc, uint16_t op) +inline int32_t hyperstone_device::frontend::decode_pcrel(opcode_desc &desc, uint16_t op) { if (op & 0x80) { @@ -111,7 +128,7 @@ inline int32_t e132xs_frontend::decode_pcrel(opcode_desc &desc, uint16_t op) } } -inline int32_t e132xs_frontend::decode_call(opcode_desc &desc) +inline int32_t hyperstone_device::frontend::decode_call(opcode_desc &desc) { const uint16_t imm_1 = read_imm1(desc); int32_t extra_s = 0; @@ -140,9 +157,9 @@ inline int32_t e132xs_frontend::decode_call(opcode_desc &desc) instruction -------------------------------------------------*/ -bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev) +bool hyperstone_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) { - uint16_t op = desc.opptr.w[0] = read_word(desc); + uint16_t op = desc.opptr[0] = read_word(desc); /* most instructions are 2 bytes and a single cycle */ desc.length = 2; @@ -156,295 +173,306 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev) switch (op >> 8) { case 0x00: // chk global,global - desc.regin[0] |= 1 << gdst_code; - desc.regin[0] |= 1 << gsrc_code; - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.set_can_cause_exception(); break; case 0x01: // chk global,local - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gdst_code; - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.set_can_cause_exception(); break; case 0x02: // chk local,global - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gsrc_code; - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.set_can_cause_exception(); break; case 0x03: // chk local,local - desc.regin[0] |= SR_CODE; - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + desc.regin.set(SR_CODE); + desc.set_can_cause_exception(); break; case 0x04: // movd global,global - desc.regin[0] |= 1 << gsrc_code; - desc.regin[0] |= 1 << gsrcf_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdstf_code; + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regin.set(G_CODE_BASE + gsrcf_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdstf_code); if (gdst_code == PC_REGISTER) { desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_CAN_CHANGE_MODES; + desc.set_is_unconditional_branch(); + desc.set_can_cause_exception(); + desc.set_end_sequence(); + desc.set_can_change_modes(); + desc.set_reads_memory(); } - desc.regout[0] |= SR_CODE; + desc.regout.set(SR_CODE); break; case 0x05: // movd global,local - desc.regin[0] |= SR_CODE; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdstf_code; + desc.regin.set(SR_CODE); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdstf_code); if (gdst_code == 0) { desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_is_unconditional_branch(); + desc.set_can_cause_exception(); + desc.set_end_sequence(); + desc.set_reads_memory(); } - desc.regout[0] |= SR_CODE; + desc.regout.set(SR_CODE); break; case 0x06: // movd local,global - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gsrc_code; - desc.regin[0] |= 1 << gsrcf_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regin.set(G_CODE_BASE + gsrcf_code); + desc.regout.set(SR_CODE); break; case 0x07: // movd local,local - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); break; case 0x08: // divu global,global case 0x0c: // divs global,global - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; - desc.regin[0] |= 1 << gsrc_code; - desc.regin[0] |= 1 << gdst_code; - desc.regin[0] |= 1 << gdstf_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdstf_code; - desc.regout[0] |= SR_CODE; + desc.set_can_cause_exception(); + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regin.set(G_CODE_BASE + gdstf_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdstf_code); + desc.regout.set(SR_CODE); break; case 0x09: // divu global,local case 0x0d: // divs global,local - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gdst_code; - desc.regin[0] |= 1 << gdstf_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdstf_code; - desc.regout[0] |= SR_CODE; + desc.set_can_cause_exception(); + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regin.set(G_CODE_BASE + gdstf_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdstf_code); + desc.regout.set(SR_CODE); break; case 0x0a: // divu local,global case 0x0e: // divs local,global - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gsrc_code; - desc.regout[0] |= SR_CODE; + desc.set_can_cause_exception(); + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regout.set(SR_CODE); break; case 0x0b: // divu local,local case 0x0f: // divs local,local - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.set_can_cause_exception(); + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); break; case 0x10: // xm global,global - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; - desc.regin[0] |= 1 << gsrc_code; - desc.regout[0] |= 1 << gdst_code; + desc.set_can_cause_exception(); + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regout.set(G_CODE_BASE + gdst_code); desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4; break; case 0x11: // xm global,local - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; - desc.regin[0] |= SR_CODE; - desc.regout[0] |= 1 << gdst_code; + desc.set_can_cause_exception(); + desc.regin.set(SR_CODE); + desc.regout.set(G_CODE_BASE + gdst_code); desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4; break; case 0x12: // xm local,global - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gsrc_code; + desc.set_can_cause_exception(); + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gsrc_code); desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4; break; case 0x13: // xm local,local - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; - desc.regin[0] |= SR_CODE; + desc.set_can_cause_exception(); + desc.regin.set(SR_CODE); desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4; break; case 0x14: // mask global,global - desc.regin[0] |= 1 << gsrc_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4; break; case 0x15: // mask global,local - desc.regin[0] |= SR_CODE; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4; break; case 0x16: // mask local,global - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gsrc_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regout.set(SR_CODE); desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4; break; case 0x17: // mask local,local - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4; break; case 0x18: // sum global,global case 0x1c: // sums global,global - desc.regin[0] |= 1 << gsrc_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4; - if (op & 0x4 && gsrc_code != SR_REGISTER) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + if (op & 0x4 && gsrc_code != SR_REGISTER) desc.set_can_cause_exception(); break; case 0x19: // sum global,local case 0x1d: // sums global,local - desc.regin[0] |= SR_CODE; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4; - if (op & 0x4) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + if (op & 0x4) desc.set_can_cause_exception(); break; case 0x1a: // sum local,global case 0x1e: // sums local,global - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gsrc_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regout.set(SR_CODE); desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4; - if (op & 0x4 && gsrc_code != SR_REGISTER) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + if (op & 0x4 && gsrc_code != SR_REGISTER) desc.set_can_cause_exception(); break; case 0x1b: // sum local,local case 0x1f: // sums local,local - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4; - if (op & 0x4) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + if (op & 0x4) desc.set_can_cause_exception(); break; case 0x20: // cmp global,global case 0x30: // cmpb global,global - desc.regin[0] |= 1 << gsrc_code; - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); break; case 0x21: // cmp global,local case 0x31: // cmpb global,local - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); break; case 0x22: // cmp local,global case 0x32: // cmpb local,global - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gsrc_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regout.set(SR_CODE); break; case 0x23: // cmp local,local case 0x33: // cmpb local,local - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); break; case 0x24: // mov global,global - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gsrc_code; - desc.regin[0] |= 1 << (gsrc_code + 16); - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regin.set(G_CODE_BASE + gsrc_code + 16); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); + desc.set_can_cause_exception(); if (gdst_code == PC_REGISTER) { if (gsrc_code != PC_REGISTER) desc.targetpc = BRANCH_TARGET_DYNAMIC; else - desc.targetpc = desc.physpc + desc.length; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = desc.pc + desc.length; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } else if (gdst_code == 5) // TPR_REGISTER & 0xf { - desc.flags |= OPFLAG_END_SEQUENCE; + desc.set_end_sequence(); } break; case 0x25: // mov global,local - desc.regin[0] |= SR_CODE; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + desc.regin.set(SR_CODE); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); + desc.set_can_cause_exception(); if (gdst_code == PC_REGISTER) { desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } else if (gdst_code == 5) // TPR_REGISTER & 0xf { - desc.flags |= OPFLAG_END_SEQUENCE; + desc.set_end_sequence(); } break; case 0x26: // mov local,global - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gsrc_code; - desc.regin[0] |= 1 << (gsrc_code + 16); - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regin.set(G_CODE_BASE + gsrc_code + 16); + desc.regout.set(SR_CODE); break; case 0x27: // mov local,local - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); break; case 0x28: // add global,global case 0x2c: // adds global,global case 0x48: // sub global,global case 0x4c: // subs global,global - desc.regin[0] |= 1 << gsrc_code; - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; - if (op & 0x04) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; // adds, subs + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); + if (op & 0x04) desc.set_can_cause_exception(); // adds, subs if (gdst_code == PC_REGISTER) { if (gsrc_code != PC_REGISTER) desc.targetpc = BRANCH_TARGET_DYNAMIC; else if (((op >> 8) == 0x28) || ((op >> 8) == 0x2c)) - desc.targetpc = (desc.physpc + desc.length) << 1; + desc.targetpc = (desc.pc + desc.length) << 1; else desc.targetpc = 0; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; case 0x29: // add global,local case 0x2d: // adds global,local case 0x49: // sub global,local case 0x4d: // subs global,local - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; - if (op & 0x04) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; // adds, subs + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); + if (op & 0x04) desc.set_can_cause_exception(); // adds, subs if (gdst_code == PC_REGISTER) { desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; case 0x2a: // add local,global case 0x2e: // adds local,global case 0x4a: // sub local,global case 0x4e: // subs local,global - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gsrc_code; - desc.regout[0] |= SR_CODE; - if (op & 0x04) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; // adds, subs + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regout.set(SR_CODE); + if (op & 0x04) desc.set_can_cause_exception(); // adds, subs break; case 0x2b: // add local,local case 0x2f: // adds local,local case 0x4b: // sub local,local case 0x4f: // subs local,local - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; - if (op & 0x04) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; // adds, subs + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); + if (op & 0x04) desc.set_can_cause_exception(); // adds, subs break; case 0x34: // andn global,global case 0x38: // or global,global case 0x3c: // xor global,global case 0x54: // and global,global - desc.regin[0] |= 1 << gsrc_code; - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); if (gdst_code == PC_REGISTER) { if (gsrc_code != PC_REGISTER) @@ -452,374 +480,393 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev) else if (((op >> 8) == 0x34) || ((op >> 8) == 0x3c)) desc.targetpc = 0; else - desc.targetpc = desc.physpc + desc.length; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = desc.pc + desc.length; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; case 0x35: // andn global,local case 0x39: // or global,local case 0x3d: // xor global,local case 0x55: // and global,local - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); if (gdst_code == PC_REGISTER) { desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; case 0x36: // andn local,global case 0x3a: // or local,global case 0x3e: // xor local,global case 0x56: // and local,global - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gsrc_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regout.set(SR_CODE); break; case 0x37: // andn local,local case 0x3b: // or local,local case 0x3f: // xor local,local case 0x57: // and local,local - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); break; case 0x40: // subc global,global case 0x50: // addc global,global - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gsrc_code; - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); if (gdst_code == PC_REGISTER) { desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; case 0x41: // subc global,local case 0x51: // addc global,local - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); if (gdst_code == PC_REGISTER) { desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; case 0x42: // subc local,global case 0x52: // addc local,global - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gsrc_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regout.set(SR_CODE); break; case 0x43: // subc local,local case 0x53: // addc local,local - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); break; case 0x44: // not global,global case 0x58: // neg global,global - desc.regin[0] |= 1 << gsrc_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); if (gdst_code == PC_REGISTER) { if (gsrc_code != PC_REGISTER) desc.targetpc = BRANCH_TARGET_DYNAMIC; else if ((op >> 8) == 0x44) - desc.targetpc = ~uint32_t(desc.physpc + desc.length) & ~uint32_t(1); + desc.targetpc = ~uint32_t(desc.pc + desc.length) & ~uint32_t(1); else - desc.targetpc = uint32_t(-int32_t(desc.physpc + desc.length)) & ~uint32_t(1); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = uint32_t(-int32_t(desc.pc + desc.length)) & ~uint32_t(1); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; case 0x45: // not global,local case 0x59: // neg global,local - desc.regin[0] |= SR_CODE; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); if (gdst_code == PC_REGISTER) { desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; case 0x46: // not local,global case 0x5a: // neg local,global - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gsrc_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regout.set(SR_CODE); break; case 0x47: // not local,local case 0x5b: // neg local,local - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); break; case 0x5c: // negs global,global - desc.regin[0] |= 1 << gsrc_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); + desc.set_can_cause_exception(); if (gdst_code == PC_REGISTER) { if (gsrc_code != PC_REGISTER) desc.targetpc = BRANCH_TARGET_DYNAMIC; else - desc.targetpc = uint32_t(-int32_t(desc.physpc + desc.length)) & ~uint32_t(1); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = uint32_t(-int32_t(desc.pc + desc.length)) & ~uint32_t(1); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; case 0x5d: // negs global,local - desc.regin[0] |= SR_CODE; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + desc.regin.set(SR_CODE); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); + desc.set_can_cause_exception(); if (gdst_code == PC_REGISTER) { desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; case 0x5e: // negs local,global - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gsrc_code; - desc.regout[0] |= SR_CODE; - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regout.set(SR_CODE); + desc.set_can_cause_exception(); break; case 0x5f: // negs local,local - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); + desc.set_can_cause_exception(); break; case 0x60: // cmpi global,simm case 0x70: // cmpbi global,simm - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); break; case 0x61: // cmpi global,limm case 0x71: // cmpbi global,limm - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); desc.length = hyperstone_device::imm_length(op) << 1; break; case 0x62: // cmpi local,simm case 0x72: // cmpbi local,simm - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); break; case 0x63: // cmpi local,limm case 0x73: // cmpbi local,limm - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); desc.length = hyperstone_device::imm_length(op) << 1; break; case 0x64: // movi global,simm - desc.regin[0] |= SR_CODE; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << (gdst_code + 16); - desc.regout[0] |= SR_CODE; - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + desc.regin.set(SR_CODE); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code + 16); + desc.regout.set(SR_CODE); + desc.set_can_cause_exception(); if (gdst_code == PC_REGISTER) { desc.targetpc = op & 0xe; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } else if (gdst_code == 5) // TPR_REGISTER & 0xf { - desc.flags |= OPFLAG_END_SEQUENCE; + desc.set_end_sequence(); } break; case 0x65: // movi global,limm - desc.regin[0] |= SR_CODE; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << (gdst_code + 16); - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code + 16); + desc.regout.set(SR_CODE); desc.length = hyperstone_device::imm_length(op) << 1; - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_can_cause_exception(); if (gdst_code == PC_REGISTER) { desc.targetpc = read_limm(desc, op) & ~uint32_t(1); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } else if (gdst_code == 5) // TPR_REGISTER & 0xf { - desc.flags |= OPFLAG_END_SEQUENCE; + desc.set_end_sequence(); } break; case 0x66: // movi local,simm - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); break; case 0x67: // movi local,limm - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); desc.length = hyperstone_device::imm_length(op) << 1; break; case 0x68: // addi global,simm case 0x6c: // addsi global,simm - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; - if (op & 0x04) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; // addsi + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); + if (op & 0x04) desc.set_can_cause_exception(); // addsi if (gdst_code == PC_REGISTER) { - desc.targetpc = desc.physpc + desc.length + (op & 0xe); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = desc.pc + desc.length + (op & 0xe); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; case 0x69: // addi global,limm case 0x6d: // addsi global,limm - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); desc.length = hyperstone_device::imm_length(op) << 1; - if (op & 0x04) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; // addsi + if (op & 0x04) desc.set_can_cause_exception(); // addsi if (gdst_code == PC_REGISTER) { desc.targetpc = desc.pc + desc.length + (read_limm(desc, op) & ~uint32_t(1)); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; case 0x6a: // addi local,simm case 0x6e: // addsi local,simm - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; - if (op & 0x04) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; // addsi + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); + if (op & 0x04) desc.set_can_cause_exception(); // addsi break; case 0x6b: // addi local,limm case 0x6f: // addsi local,limm - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); desc.length = hyperstone_device::imm_length(op) << 1; - if (op & 0x04) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; // addsi + if (op & 0x04) desc.set_can_cause_exception(); // addsi break; case 0x74: // andni global,simm - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); if (gdst_code == PC_REGISTER) { - desc.targetpc = (desc.physpc + desc.length) & ~uint32_t(op & 0xf); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = (desc.pc + desc.length) & ~uint32_t(op & 0xf); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; case 0x78: // ori global,simm - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); if (gdst_code == PC_REGISTER) { - desc.targetpc = (desc.physpc + desc.length) | (op & 0xe); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = (desc.pc + desc.length) | (op & 0xe); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; case 0x7c: // xori global,simm - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); if (gdst_code == PC_REGISTER) { - desc.targetpc = (desc.physpc + desc.length) ^ (op & 0xe); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = (desc.pc + desc.length) ^ (op & 0xe); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; case 0x75: // andni global,limm - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); desc.length = hyperstone_device::imm_length(op) << 1; if (gdst_code == PC_REGISTER) { - desc.targetpc = (desc.physpc + desc.length) & ~read_limm(desc, op); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = (desc.pc + desc.length) & ~read_limm(desc, op); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; case 0x79: // ori global,limm - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); desc.length = hyperstone_device::imm_length(op) << 1; if (gdst_code == PC_REGISTER) { - desc.targetpc = (desc.physpc + desc.length) | (read_limm(desc, op) & ~uint32_t(1)); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = (desc.pc + desc.length) | (read_limm(desc, op) & ~uint32_t(1)); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; case 0x7d: // xori global,limm - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); desc.length = hyperstone_device::imm_length(op) << 1; if (gdst_code == PC_REGISTER) { - desc.targetpc = (desc.physpc + desc.length) ^ (read_limm(desc, op) & ~uint32_t(1)); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = (desc.pc + desc.length) ^ (read_limm(desc, op) & ~uint32_t(1)); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; case 0x76: // andni local,simm case 0x7a: // ori local,simm case 0x7e: // xori local,simm - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); break; case 0x77: // andni local,limm case 0x7b: // ori local,limm case 0x7f: // xori local,limm - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); desc.length = hyperstone_device::imm_length(op) << 1; break; case 0x80: case 0x81: // shrdi case 0x84: case 0x85: // sardi case 0x88: case 0x89: // shldi - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); break; case 0x82: // shrd case 0x86: // sard case 0x8a: // shld - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); break; case 0x83: // shr case 0x87: // sar case 0x8b: // shl case 0x8f: // rol - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); break; case 0x8c: case 0x8d: // reserved return false; case 0x8e: // testlz - desc.regin[0] |= SR_CODE; + desc.regin.set(SR_CODE); break; case 0x90: // ldxx1 global,global { const uint16_t imm1 = read_imm1(desc); const uint32_t extra_s = read_ldstxx_imm(desc); - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gsrc_code; - if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regout[0] |= 1 << gsrcf_code; + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gsrc_code); + if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regout.set(G_CODE_BASE + gsrcf_code); desc.length = (imm1 & 0x8000) ? 6 : 4; - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); if (gdst_code == PC_REGISTER) { desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; } @@ -828,15 +875,16 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev) const uint16_t imm1 = read_imm1(desc); [[maybe_unused]] const uint32_t extra_s = read_ldstxx_imm(desc); - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gdst_code; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gdst_code); desc.length = (imm1 & 0x8000) ? 6 : 4; - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); if (gdst_code == PC_REGISTER) { desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; } @@ -845,12 +893,12 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev) const uint16_t imm1 = read_imm1(desc); const uint32_t extra_s = read_ldstxx_imm(desc); - desc.regin[0] |= SR_CODE; - desc.regout[0] |= 1 << gsrc_code; - if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regout[0] |= 1 << gsrcf_code; + desc.regin.set(SR_CODE); + desc.regout.set(G_CODE_BASE + gsrc_code); + if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regout.set(G_CODE_BASE + gsrcf_code); desc.length = (imm1 & 0x8000) ? 6 : 4; - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); break; } case 0x93: // ldxx1 local,local @@ -858,10 +906,10 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev) const uint16_t imm1 = read_imm1(desc); [[maybe_unused]] const uint32_t extra_s = read_ldstxx_imm(desc); - desc.regin[0] |= SR_CODE; + desc.regin.set(SR_CODE); desc.length = (imm1 & 0x8000) ? 6 : 4; - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); break; } case 0x94: // ldxx2 global,global @@ -869,17 +917,18 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev) const uint16_t imm1 = read_imm1(desc); const uint32_t extra_s = read_ldstxx_imm(desc); - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gsrc_code; - if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regout[0] |= 1 << gsrcf_code; + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gsrc_code); + if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regout.set(G_CODE_BASE + gsrcf_code); desc.length = (imm1 & 0x8000) ? 6 : 4; - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); if (gdst_code == PC_REGISTER) { desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; } @@ -888,16 +937,17 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev) const uint16_t imm1 = read_imm1(desc); [[maybe_unused]] const uint32_t extra_s = read_ldstxx_imm(desc); - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); desc.length = (imm1 & 0x8000) ? 6 : 4; - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); if (gdst_code == PC_REGISTER) { desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } break; } @@ -906,12 +956,12 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev) const uint16_t imm1 = read_imm1(desc); const uint32_t extra_s = read_ldstxx_imm(desc); - desc.regin[0] |= SR_CODE; - desc.regout[0] |= 1 << gsrc_code; - if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regout[0] |= 1 << gsrcf_code; + desc.regin.set(SR_CODE); + desc.regout.set(G_CODE_BASE + gsrc_code); + if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regout.set(G_CODE_BASE + gsrcf_code); desc.length = (imm1 & 0x8000) ? 6 : 4; - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); break; } case 0x97: // ldxx2 local,local @@ -919,10 +969,10 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev) const uint16_t imm1 = read_imm1(desc); [[maybe_unused]] const uint32_t extra_s = read_ldstxx_imm(desc); - desc.regin[0] |= SR_CODE; + desc.regin.set(SR_CODE); desc.length = (imm1 & 0x8000) ? 6 : 4; - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); break; } case 0x98: // stxx1 global,global @@ -930,12 +980,12 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev) const uint16_t imm1 = read_imm1(desc); const uint32_t extra_s = read_ldstxx_imm(desc); - desc.regin[0] |= 1 << gdst_code; - desc.regin[0] |= 1 << gsrc_code; - if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regin[0] |= 1 << gsrcf_code; + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regin.set(G_CODE_BASE + gsrc_code); + if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regin.set(G_CODE_BASE + gsrcf_code); desc.length = (imm1 & 0x8000) ? 6 : 4; - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); break; } case 0x99: // stxx1 global,local @@ -943,11 +993,11 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev) const uint16_t imm1 = read_imm1(desc); [[maybe_unused]] const uint32_t extra_s = read_ldstxx_imm(desc); - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gdst_code; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gdst_code); desc.length = (imm1 & 0x8000) ? 6 : 4; - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); break; } case 0x9a: // stxx1 local,global @@ -955,12 +1005,12 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev) const uint16_t imm1 = read_imm1(desc); const uint32_t extra_s = read_ldstxx_imm(desc); - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gsrc_code; - if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regin[0] |= 1 << gsrcf_code; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gsrc_code); + if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regin.set(G_CODE_BASE + gsrcf_code); desc.length = (imm1 & 0x8000) ? 6 : 4; - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); break; } case 0x9b: // stxx1 local,local @@ -968,10 +1018,10 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev) const uint16_t imm1 = read_imm1(desc); [[maybe_unused]] const uint32_t extra_s = read_ldstxx_imm(desc); - desc.regin[0] |= SR_CODE; + desc.regin.set(SR_CODE); desc.length = (imm1 & 0x8000) ? 6 : 4; - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); break; } case 0x9c: // stxx2 global,global @@ -979,13 +1029,13 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev) const uint16_t imm1 = read_imm1(desc); const uint32_t extra_s = read_ldstxx_imm(desc); - desc.regin[0] |= 1 << gdst_code; - desc.regin[0] |= 1 << gsrc_code; - if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regin[0] |= 1 << gsrcf_code; - desc.regout[0] |= 1 << gdst_code; + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regin.set(G_CODE_BASE + gsrc_code); + if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regin.set(G_CODE_BASE + gsrcf_code); + desc.regout.set(G_CODE_BASE + gdst_code); desc.length = (imm1 & 0x8000) ? 6 : 4; - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); break; } case 0x9d: // stxx2 global,local @@ -993,12 +1043,12 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev) const uint16_t imm1 = read_imm1(desc); [[maybe_unused]] const uint32_t extra_s = read_ldstxx_imm(desc); - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); desc.length = (imm1 & 0x8000) ? 6 : 4; - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); break; } case 0x9e: // stxx2 local,global @@ -1006,12 +1056,12 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev) const uint16_t imm1 = read_imm1(desc); const uint32_t extra_s = read_ldstxx_imm(desc); - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gsrc_code; - if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regin[0] |= 1 << gsrcf_code; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gsrc_code); + if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regin.set(G_CODE_BASE + gsrcf_code); desc.length = (imm1 & 0x8000) ? 6 : 4; - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); break; } case 0x9f: // stxx2 local,local @@ -1019,10 +1069,10 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev) const uint16_t imm1 = read_imm1(desc); [[maybe_unused]] const uint32_t extra_s = read_ldstxx_imm(desc); - desc.regin[0] |= SR_CODE; + desc.regin.set(SR_CODE); desc.length = (imm1 & 0x8000) ? 6 : 4; - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); break; } case 0xa0: // shri global (lo n) @@ -1031,9 +1081,9 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0xa5: // sari global (hi n) case 0xa8: // shli global (lo n) case 0xa9: // shli global (hi n) - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); break; case 0xa2: // shri local (lo n) case 0xa3: // shri local (hi n) @@ -1041,183 +1091,197 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0xa7: // sari local (hi n) case 0xaa: // shli local (lo n) case 0xab: // shli local (hi n) - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); break; case 0xac: case 0xad: case 0xae: case 0xaf: // reserved return false; case 0xb0: // mulu global,global case 0xb4: // muls global,global - desc.regin[0] |= 1 << gsrc_code; - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdstf_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdstf_code); + desc.regout.set(SR_CODE); break; case 0xb1: // mulu global,local case 0xb5: // muls global,local - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdstf_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdstf_code); + desc.regout.set(SR_CODE); break; case 0xb2: // mulu local,global case 0xb6: // muls local,global - desc.regin[0] |= 1 << gsrc_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regout.set(SR_CODE); break; case 0xb3: // mulu local,local case 0xb7: // muls local,local - desc.regout[0] |= SR_CODE; + desc.regout.set(SR_CODE); break; case 0xb8: // set global (lo n) case 0xb9: // set global (hi n) - desc.regin[0] |= SR_CODE; - desc.regout[0] |= 1 << gdst_code; + desc.regin.set(SR_CODE); + desc.regout.set(G_CODE_BASE + gdst_code); break; case 0xba: // set local (lo n) case 0xbb: // set local (hi n) break; case 0xbc: // mul global,global - desc.regin[0] |= 1 << gsrc_code; - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); break; case 0xbd: // muls global,local - desc.regin[0] |= 1 << gdst_code; - desc.regout[0] |= 1 << gdst_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(G_CODE_BASE + gdst_code); + desc.regout.set(G_CODE_BASE + gdst_code); + desc.regout.set(SR_CODE); break; case 0xbe: // muls local,global - desc.regin[0] |= 1 << gsrc_code; - desc.regout[0] |= SR_CODE; + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regout.set(SR_CODE); break; case 0xbf: // mulu local,local - desc.regout[0] |= SR_CODE; + desc.regout.set(SR_CODE); break; case 0xc0: case 0xc1: case 0xc2: case 0xc3: // software case 0xc4: case 0xc5: case 0xc6: case 0xc7: // software case 0xc8: case 0xc9: case 0xca: case 0xcb: // software case 0xcc: case 0xcd: // software - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_CHANGE_MODES; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + desc.set_can_change_modes(); break; case 0xce: // extend - 4 bytes - desc.regin[0] |= SR_CODE; - desc.regin[0] |= (3 << 14); // global regs 14, 15 - desc.regout[0] |= (3 << 14); // global regs 14, 15 + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + 14); // global regs 14, 15 + desc.regin.set(G_CODE_BASE + 15); + desc.regout.set(G_CODE_BASE + 14); // global regs 14, 15 + desc.regout.set(G_CODE_BASE + 15); desc.length = 4; break; case 0xcf: // do return false; case 0xd0: // ldwr global case 0xd4: // ldwp global - desc.regin[0] |= SR_CODE; - desc.regout[0] |= 1 << gsrc_code; - desc.flags |= OPFLAG_READS_MEMORY; + desc.regin.set(SR_CODE); + desc.regout.set(G_CODE_BASE + gsrc_code); + desc.set_reads_memory(); break; case 0xd1: // ldwr local case 0xd5: // ldwp local - desc.regin[0] |= SR_CODE; - desc.flags |= OPFLAG_READS_MEMORY; + desc.regin.set(SR_CODE); + desc.set_reads_memory(); break; case 0xd2: // lddr global case 0xd6: // lddp global - desc.regin[0] |= SR_CODE; - desc.regout[0] |= 1 << gsrc_code; - desc.regout[0] |= 1 << gsrcf_code; - desc.flags |= OPFLAG_READS_MEMORY; + desc.regin.set(SR_CODE); + desc.regout.set(G_CODE_BASE + gsrc_code); + desc.regout.set(G_CODE_BASE + gsrcf_code); + desc.set_reads_memory(); break; case 0xd3: // lddr local case 0xd7: // lddp local - desc.regin[0] |= SR_CODE; - desc.flags |= OPFLAG_READS_MEMORY; + desc.regin.set(SR_CODE); + desc.set_reads_memory(); break; case 0xd8: // stwr global case 0xdc: // stwp global - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gsrc_code; - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.set_writes_memory(); break; case 0xd9: // stwr local case 0xdd: // stwp local - desc.regin[0] |= SR_CODE; - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.regin.set(SR_CODE); + desc.set_writes_memory(); break; case 0xda: // stdr global case 0xde: // stdp global - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gsrc_code; - desc.regin[0] |= 1 << gsrcf_code; - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.regin.set(G_CODE_BASE + gsrcf_code); + desc.set_writes_memory(); break; case 0xdb: // stdr local case 0xdf: // stdp local - desc.regin[0] |= SR_CODE; - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.regin.set(SR_CODE); + desc.set_writes_memory(); break; case 0xe0: case 0xe1: case 0xe2: case 0xe3: // dbv, dbnv, dbe, dbne - could be 4 bytes (pcrel) case 0xe4: case 0xe5: case 0xe6: case 0xe7: // dbc, dbnc, dbse, dbht - could be 4 bytes (pcrel) case 0xe8: case 0xe9: case 0xea: case 0xeb: // dbn, dbnn, dblt, dbgt - could be 4 bytes (pcrel) - desc.regin[0] |= SR_CODE; - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.regin.set(SR_CODE); + desc.set_is_conditional_branch(); desc.delayslots = 1; desc.length = (op & 0x80) ? 4 : 2; - desc.targetpc = desc.physpc + desc.length + decode_pcrel(desc, op); + desc.targetpc = desc.pc + desc.length + decode_pcrel(desc, op); break; case 0xec: // dbr - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); desc.delayslots = 1; desc.length = (op & 0x80) ? 4 : 2; - desc.targetpc = desc.physpc + desc.length + decode_pcrel(desc, op); + desc.targetpc = desc.pc + desc.length + decode_pcrel(desc, op); break; case 0xed: // frame - desc.regin[0] |= SR_CODE; - desc.regout[0] |= SR_CODE; - desc.flags |= OPFLAG_WRITES_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.regin.set(SR_CODE); + desc.regout.set(SR_CODE); + desc.set_writes_memory(); break; case 0xee: // call global - desc.regin[0] |= SR_CODE; - desc.regin[0] |= 1 << gsrc_code; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.regin.set(SR_CODE); + desc.regin.set(G_CODE_BASE + gsrc_code); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4; if (gsrc_code == PC_REGISTER) - desc.targetpc = desc.physpc + desc.length + (decode_call(desc) & ~uint32_t(1)); + desc.targetpc = desc.pc + desc.length + (decode_call(desc) & ~uint32_t(1)); else if (gsrc_code == SR_REGISTER) desc.targetpc = decode_call(desc) & ~uint32_t(1); else desc.targetpc = BRANCH_TARGET_DYNAMIC; break; case 0xef: // call local - desc.regin[0] |= SR_CODE; + desc.regin.set(SR_CODE); desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4; break; case 0xf0: case 0xf1: case 0xf2: case 0xf3: // bv, bnv, be, bne case 0xf4: case 0xf5: case 0xf6: case 0xf7: // bc, bnc, bse, bht case 0xf8: case 0xf9: case 0xfa: case 0xfb: // bn, bnn, blt, bgt - desc.regin[0] |= SR_CODE; - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.regin.set(SR_CODE); + desc.set_is_conditional_branch(); desc.length = (op & 0x80) ? 4 : 2; desc.targetpc = desc.pc + desc.length + decode_pcrel(desc, op); break; case 0xfc: // br - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); desc.length = (op & 0x80) ? 4 : 2; desc.targetpc = desc.pc + desc.length + decode_pcrel(desc, op); break; case 0xfd: case 0xfe: case 0xff: // trap - desc.regin[0] |= SR_CODE; + desc.regin.set(SR_CODE); desc.targetpc = BRANCH_TARGET_DYNAMIC; if ((((op & 0x300) >> 6) | (op & 0x03)) == 15) - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_CAUSE_EXCEPTION; + { + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } else - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH | OPFLAG_CAN_CAUSE_EXCEPTION; + { + desc.set_is_conditional_branch(); + } + desc.set_can_cause_exception(); break; } return true; diff --git a/src/devices/cpu/e132xs/e132xsfe.h b/src/devices/cpu/e132xs/e132xsfe.h index c71849228e8..22dbf96c89c 100644 --- a/src/devices/cpu/e132xs/e132xsfe.h +++ b/src/devices/cpu/e132xs/e132xsfe.h @@ -6,19 +6,65 @@ #pragma once #include "e132xs.h" + #include "cpu/drcfe.h" -class e132xs_frontend : public drc_frontend +#include <algorithm> +#include <bitset> + + +class hyperstone_device::opcode_desc : public opcode_desc_base<opcode_desc, 32> { public: - e132xs_frontend(hyperstone_device &cpu, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); - void flush(); + uint16_t opptr[3]; // copy of up to 3 halfwords of opcode + + void set_can_change_modes() { m_extra_flags.set(CAN_CHANGE_MODES); } + void set_reads_memory() { m_extra_flags.set(READS_MEMORY); } + void set_writes_memory() { m_extra_flags.set(WRITES_MEMORY); } + + bool can_change_modes() const { return m_extra_flags[CAN_CHANGE_MODES]; } + bool reads_memory() const { return m_extra_flags[READS_MEMORY]; } + bool writes_memory() const { return m_extra_flags[WRITES_MEMORY]; } + + // epc - compute the exception PC + uint32_t epc() const + { + return in_delay_slot() ? branch->pc : pc; + } + + void reset(offs_t curpc, bool in_delay_slot) + { + opcode_desc_base::reset(curpc, in_delay_slot); + + std::fill(std::begin(opptr), std::end(opptr), 0); + m_extra_flags.reset(); + } protected: - // required overrides - virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override; + enum + { + CAN_CHANGE_MODES = 0, + READS_MEMORY, + WRITES_MEMORY, + + EXTRA_FLAG_COUNT + }; + + std::bitset<EXTRA_FLAG_COUNT> m_extra_flags; +}; + + +class hyperstone_device::frontend : public drc_frontend_base<opcode_desc> +{ +public: + frontend(hyperstone_device &cpu, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); + ~frontend(); + + opcode_desc const *describe_code(offs_t startpc); private: + bool describe(opcode_desc &desc, opcode_desc const *prev); + uint16_t read_word(opcode_desc &desc); uint16_t read_imm1(opcode_desc &desc); uint16_t read_imm2(opcode_desc &desc); diff --git a/src/devices/cpu/mb86235/mb86235.h b/src/devices/cpu/mb86235/mb86235.h index e3a660f1987..b7b9a830a0c 100644 --- a/src/devices/cpu/mb86235/mb86235.h +++ b/src/devices/cpu/mb86235/mb86235.h @@ -11,18 +11,13 @@ #pragma once -#include "cpu/drcfe.h" #include "cpu/drcuml.h" #include "machine/gen_fifo.h" -class mb86235_frontend; - class mb86235_device : public cpu_device { - friend class mb86235_frontend; - public: // construction/destruction mb86235_device(const machine_config &mconfig, const char *_tag, device_t *_owner, uint32_t clock); @@ -64,23 +59,26 @@ public: void internal_bbus(address_map &map) ATTR_COLD; protected: - // device-level overrides + class frontend; + class opcode_desc; + + // device_t implementation virtual void device_start() override ATTR_COLD; virtual void device_reset() override ATTR_COLD; - // device_execute_interface overrides + // device_execute_interface implementation virtual uint32_t execute_min_cycles() const noexcept override { return 1; } virtual uint32_t execute_max_cycles() const noexcept override { return 7; } virtual void execute_run() override; //virtual void execute_set_input(int inputnum, int state); - // device_memory_interface overrides + // device_memory_interface implementation virtual space_config_vector memory_space_config() const override; - // device_state_interface overrides + // device_state_interface implementation virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; - // device_disasm_interface overrides + // device_disasm_interface implementation virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; private: @@ -178,7 +176,7 @@ private: drc_cache m_cache; std::unique_ptr<drcuml_state> m_drcuml; - std::unique_ptr<mb86235_frontend> m_drcfe; + std::unique_ptr<frontend> m_drcfe; memory_access<12, 3, -3, ENDIANNESS_LITTLE>::cache m_pcache; memory_access<12, 3, -3, ENDIANNESS_LITTLE>::specific m_program; diff --git a/src/devices/cpu/mb86235/mb86235defs.h b/src/devices/cpu/mb86235/mb86235defs.h deleted file mode 100644 index 3156c239788..00000000000 --- a/src/devices/cpu/mb86235/mb86235defs.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef MAME_CPU_MB86235_MB86235DEFS_H -#define MAME_CPU_MB86235_MB86235DEFS_H - -#pragma once - - -#define OP_USERFLAG_FIFOIN 0x1 -#define OP_USERFLAG_FIFOOUT 0x2 -#define OP_USERFLAG_REPEAT 0x8 -#define OP_USERFLAG_REPEATED_OP 0x10 -#define OP_USERFLAG_PR_MASK 0x300 -#define OP_USERFLAG_PR_INC 0x100 -#define OP_USERFLAG_PR_DEC 0x200 -#define OP_USERFLAG_PR_ZERO 0x300 -#define OP_USERFLAG_PW_MASK 0xc00 -#define OP_USERFLAG_PW_INC 0x400 -#define OP_USERFLAG_PW_DEC 0x800 -#define OP_USERFLAG_PW_ZERO 0xc00 - -#endif // MAME_CPU_MB86235_MB86235DEFS_H diff --git a/src/devices/cpu/mb86235/mb86235drc.cpp b/src/devices/cpu/mb86235/mb86235drc.cpp index 67e562c865a..cfad532e8c3 100644 --- a/src/devices/cpu/mb86235/mb86235drc.cpp +++ b/src/devices/cpu/mb86235/mb86235drc.cpp @@ -8,14 +8,11 @@ #include "emu.h" #include "mb86235.h" + #include "mb86235fe.h" -#include "cpu/drcfe.h" -#include "cpu/drcuml.h" #include "cpu/drcumlsh.h" -#include "mb86235defs.h" - /* TODO: @@ -62,20 +59,20 @@ #define RPC uml::mem(&m_core->rpc) #define LPC uml::mem(&m_core->lpc) -#define AZ_CALC_REQUIRED ((desc->regreq[1] & 0x1) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define AN_CALC_REQUIRED ((desc->regreq[1] & 0x2) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define AV_CALC_REQUIRED ((desc->regreq[1] & 0x4) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define AU_CALC_REQUIRED ((desc->regreq[1] & 0x8) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define AD_CALC_REQUIRED ((desc->regreq[1] & 0x10) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define ZC_CALC_REQUIRED ((desc->regreq[1] & 0x20) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define IL_CALC_REQUIRED ((desc->regreq[1] & 0x40) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define NR_CALC_REQUIRED ((desc->regreq[1] & 0x80) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define ZD_CALC_REQUIRED ((desc->regreq[1] & 0x100) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define MN_CALC_REQUIRED ((desc->regreq[1] & 0x200) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define MZ_CALC_REQUIRED ((desc->regreq[1] & 0x400) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define MV_CALC_REQUIRED ((desc->regreq[1] & 0x800) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define MU_CALC_REQUIRED ((desc->regreq[1] & 0x1000) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define MD_CALC_REQUIRED ((desc->regreq[1] & 0x2000) || desc->flags & OPFLAG_IN_DELAY_SLOT) +#define AZ_CALC_REQUIRED (desc->az_calc_required()) +#define AN_CALC_REQUIRED (desc->an_calc_required()) +#define AV_CALC_REQUIRED (desc->av_calc_required()) +#define AU_CALC_REQUIRED (desc->au_calc_required()) +#define AD_CALC_REQUIRED (desc->ad_calc_required()) +#define ZC_CALC_REQUIRED (desc->zc_calc_required()) +#define IL_CALC_REQUIRED (desc->il_calc_required()) +#define NR_CALC_REQUIRED (desc->nr_calc_required()) +#define ZD_CALC_REQUIRED (desc->zd_calc_required()) +#define MN_CALC_REQUIRED (desc->mn_calc_required()) +#define MZ_CALC_REQUIRED (desc->mz_calc_required()) +#define MV_CALC_REQUIRED (desc->mv_calc_required()) +#define MU_CALC_REQUIRED (desc->mu_calc_required()) +#define MD_CALC_REQUIRED (desc->md_calc_required()) inline void mb86235_device::alloc_handle(uml::code_handle *&handleptr, const char *name) { @@ -267,7 +264,7 @@ void mb86235_device::compile_block(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); @@ -292,7 +289,7 @@ void mb86235_device::compile_block(offs_t pc) } /* 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 /* iterate over instructions in the sequence and compile them */ @@ -300,7 +297,7 @@ void mb86235_device::compile_block(offs_t pc) generate_sequence_instruction(block, compiler, curdesc); /* if we need to return to the start, do it */ - if (seqlast->flags & OPFLAG_RETURN_TO_START) + if (seqlast->return_to_start()) nextpc = pc; /* otherwise we just go to the next instruction */ else @@ -497,14 +494,14 @@ void mb86235_device::flush_cache() void mb86235_device::generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { /* add an entry for the log */ - // if (m_drcuml->logging() && !(desc->flags & OPFLAG_VIRTUAL_NOOP)) - // log_add_disasm_comment(block, desc->pc, desc->opptr.l[0]); + // if (m_drcuml->logging() && !desc->virtual_noop()) + // log_add_disasm_comment(block, desc->pc, desc->opptr); /* set the PC map variable */ UML_MAPVAR(block, MAPVAR_PC, desc->pc); // mapvar PC,desc->pc /* accumulate total cycles */ - compiler.cycles += desc->cycles; + compiler.cycles += 1; /* update the icount map variable */ UML_MAPVAR(block, MAPVAR_CYCLES, compiler.cycles); // mapvar CYCLES,compiler.cycles @@ -517,26 +514,18 @@ void mb86235_device::generate_sequence_instruction(drcuml_block &block, compiler UML_DEBUG(block, desc->pc); // debug desc->pc } - /* if we hit an unmapped address, fatal error */ - if (desc->flags & OPFLAG_COMPILER_UNMAPPED) - { - UML_MOV(block, mem(&m_core->pc), desc->pc); // mov [pc],desc->pc - save_fast_iregs(block); // <save fastregs> - UML_EXIT(block, EXECUTE_UNMAPPED_CODE); // exit EXECUTE_UNMAPPED_CODE - } - /* if this is an invalid opcode, generate the exception now */ - // if (desc->flags & OPFLAG_INVALID_OPCODE) + // if (desc->invalid_opcode()) // UML_EXH(block, *m_exception[EXCEPTION_PROGRAM], 0x80000); // exh exception_program,0x80000 /* unless this is a virtual no-op, it's a regular instruction */ - if (!(desc->flags & OPFLAG_VIRTUAL_NOOP)) + if (!desc->virtual_noop()) { /* compile the instruction */ if (!generate_opcode(block, compiler, desc)) { UML_MOV(block, mem(&m_core->pc), desc->pc); // mov [pc],desc->pc - UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]); // dmov [arg64],*desc->opptr.q + UML_DMOV(block, mem(&m_core->arg64), desc->opptr); // dmov [arg64],*desc->opptr UML_CALLC(block, cfunc_unimplemented, this); // callc cfunc_unimplemented,ppc } } @@ -724,19 +713,19 @@ bool mb86235_device::has_register_clash(const opcode_desc *desc, int outreg) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: // MA0-7 - if (desc->regin[0] & (1 << (16 + (outreg & 7)))) return true; + if (desc->ma_used(outreg & 7)) return true; break; case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: // MB0-7 - if (desc->regin[0] & (1 << (24 + (outreg & 7)))) return true; + if (desc->mb_used(outreg & 7)) return true; break; case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: // AA0-7 - if (desc->regin[0] & (1 << (outreg & 7))) return true; + if (desc->aa_used(outreg & 7)) return true; break; case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: // AB0-7 - if (desc->regin[0] & (1 << (8 + (outreg & 7)))) return true; + if (desc->ab_used(outreg & 7)) return true; break; } return false; @@ -761,26 +750,26 @@ bool mb86235_device::aluop_has_result(int aluop) bool mb86235_device::generate_opcode(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - uint64_t opcode = desc->opptr.q[0]; + uint64_t opcode = desc->opptr; bool fifoin_check = false; bool fifoout_check = false; // enable fifo in check if this opcode or the delay slot reads from FIFO - if (desc->userflags & OP_USERFLAG_FIFOIN) + if (desc->fifoin()) fifoin_check = true; if (desc->delayslots > 0) { - if (desc->delay.first()->userflags & OP_USERFLAG_FIFOIN) + if (desc->delay.first()->fifoin()) fifoin_check = true; } // enable fifo out check if this opcode or the delay slot writes to FIFO - if (desc->userflags & OP_USERFLAG_FIFOOUT) + if (desc->fifoout()) fifoout_check = true; if (desc->delayslots > 0) { - if (desc->delay.first()->userflags & OP_USERFLAG_FIFOOUT) + if (desc->delay.first()->fifoout()) fifoout_check = true; } @@ -912,48 +901,48 @@ bool mb86235_device::generate_opcode(drcuml_block &block, compiler_state &compil } // update PR and PW if needed - if ((desc->userflags & OP_USERFLAG_PR_MASK) != 0) + if (desc->pr() != 0) { - switch ((desc->userflags & OP_USERFLAG_PR_MASK) >> 8) + switch (desc->pr()) { - case 1: // PR++ + case opcode_desc::INC: // PR++ UML_ADD(block, PRP, PRP, 1); UML_CMP(block, PRP, 24); UML_MOVc(block, COND_GE, PRP, 0); break; - case 2: // PR-- + case opcode_desc::DEC: // PR-- UML_SUB(block, PRP, PRP, 1); UML_CMP(block, PRP, 0); UML_MOVc(block, COND_L, PRP, 23); break; - case 3: // PR#0 + case opcode_desc::ZERO: // PR#0 UML_MOV(block, PRP, 0); break; } } - if ((desc->userflags & OP_USERFLAG_PW_MASK) != 0) + if (desc->pw() != 0) { - switch ((desc->userflags & OP_USERFLAG_PW_MASK) >> 10) + switch (desc->pw()) { - case 1: // PW++ + case opcode_desc::INC: // PW++ UML_ADD(block, PWP, PWP, 1); UML_CMP(block, PWP, 24); UML_MOVc(block, COND_GE, PWP, 0); break; - case 2: // PW-- + case opcode_desc::DEC: // PW-- UML_SUB(block, PWP, PWP, 1); UML_CMP(block, PWP, 0); UML_MOVc(block, COND_L, PWP, 23); break; - case 3: // PW#0 + case opcode_desc::ZERO: // PW#0 UML_MOV(block, PWP, 0); break; } } // handle repeat - if (desc->userflags & OP_USERFLAG_REPEATED_OP) + if (desc->repeated_op()) { uml::code_label const no_repeat = compiler.labelnum++; UML_SUB(block, RPC, RPC, 1); @@ -961,7 +950,7 @@ bool mb86235_device::generate_opcode(drcuml_block &block, compiler_state &compil UML_JMPc(block, COND_LE, no_repeat); generate_update_cycles(block, compiler, desc->pc, true); - if (desc->flags & OPFLAG_INTRABLOCK_BRANCH) + if (desc->intrablock_branch()) UML_JMP(block, desc->pc | 0x80000000); else UML_HASHJMP(block, 0, desc->pc, *m_nocode); @@ -1365,7 +1354,7 @@ void mb86235_device::generate_branch(drcuml_block &block, compiler_state &compil if (desc->targetpc != BRANCH_TARGET_DYNAMIC) { generate_update_cycles(block, compiler_temp, desc->targetpc, true); - if (desc->flags & OPFLAG_INTRABLOCK_BRANCH) + if (desc->intrablock_branch()) UML_JMP(block, desc->targetpc | 0x80000000); // jmp targetpc | 0x80000000 else UML_HASHJMP(block, 0, desc->targetpc, *m_nocode); // hashjmp 0,targetpc,nocode @@ -1484,7 +1473,7 @@ void mb86235_device::generate_condition(drcuml_block &block, compiler_state &com void mb86235_device::generate_control(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - uint64_t op = desc->opptr.q[0]; + uint64_t op = desc->opptr; int ef1 = (op >> 16) & 0x3f; int ef2 = op & 0xffff; int cop = (op >> 22) & 0x1f; @@ -1593,7 +1582,7 @@ void mb86235_device::generate_control(drcuml_block &block, compiler_state &compi void mb86235_device::generate_xfer1(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - uint64_t opcode = desc->opptr.q[0]; + uint64_t opcode = desc->opptr; int dr = (opcode >> 12) & 0x7f; int sr = (opcode >> 19) & 0x7f; @@ -1657,13 +1646,13 @@ void mb86235_device::generate_xfer1(drcuml_block &block, compiler_state &compile void mb86235_device::generate_double_xfer1(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { UML_MOV(block, mem(&m_core->pc), desc->pc); - UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]); + UML_DMOV(block, mem(&m_core->arg64), desc->opptr); UML_CALLC(block, cfunc_unimplemented_double_xfer1, this); } void mb86235_device::generate_xfer2(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - uint64_t opcode = desc->opptr.q[0]; + uint64_t opcode = desc->opptr; int op = (opcode >> 39) & 3; int trm = (opcode >> 38) & 1; @@ -1752,13 +1741,13 @@ void mb86235_device::generate_xfer2(drcuml_block &block, compiler_state &compile void mb86235_device::generate_double_xfer2(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { UML_MOV(block, mem(&m_core->pc), desc->pc); - UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]); + UML_DMOV(block, mem(&m_core->arg64), desc->opptr); UML_CALLC(block, cfunc_unimplemented_double_xfer2, this); } void mb86235_device::generate_xfer3(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - uint64_t opcode = desc->opptr.q[0]; + uint64_t opcode = desc->opptr; uint32_t imm = (uint32_t)(opcode >> 27); int dr = (opcode >> 19) & 0x7f; @@ -1790,7 +1779,7 @@ void mb86235_device::generate_xfer3(drcuml_block &block, compiler_state &compile void mb86235_device::generate_pre_control(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - uint64_t op = desc->opptr.q[0]; + uint64_t op = desc->opptr; int ef1 = (op >> 16) & 0x3f; int ef2 = op & 0xffff; int cop = (op >> 22) & 0x1f; diff --git a/src/devices/cpu/mb86235/mb86235fe.cpp b/src/devices/cpu/mb86235/mb86235fe.cpp index 15151041d78..b82d1dca058 100644 --- a/src/devices/cpu/mb86235/mb86235fe.cpp +++ b/src/devices/cpu/mb86235/mb86235fe.cpp @@ -10,71 +10,41 @@ #include "emu.h" #include "mb86235fe.h" -#include "mb86235defs.h" - - -#define AA_USED(desc,x) do { (desc).regin[0] |= 1 << (x); } while(0) -#define AA_MODIFIED(desc,x) do { (desc).regout[0] |= 1 << (x); } while(0) -#define AB_USED(desc,x) do { (desc).regin[0] |= 1 << (8+(x)); } while(0) -#define AB_MODIFIED(desc,x) do { (desc).regout[0] |= 1 << (8+(x)); } while(0) -#define MA_USED(desc,x) do { (desc).regin[0] |= 1 << (16+(x)); } while(0) -#define MA_MODIFIED(desc,x) do { (desc).regout[0] |= 1 << (16+(x)); } while(0) -#define MB_USED(desc,x) do { (desc).regin[0] |= 1 << (24+(x)); } while(0) -#define MB_MODIFIED(desc,x) do { (desc).regout[0] |= 1 << (24+(x)); } while(0) -#define AR_USED(desc,x) do { (desc).regin[1] |= 1 << (24+(x)); } while(0) -#define AR_MODIFIED(desc,x) do { (desc).regout[1] |= 1 << (24+(x)); } while(0) - -#define AZ_USED(desc) do { (desc).regin[1] |= 1 << 0; } while (0) -#define AZ_MODIFIED(desc) do { (desc).regout[1] |= 1 << 0; } while (0) -#define AN_USED(desc) do { (desc).regin[1] |= 1 << 1; } while (0) -#define AN_MODIFIED(desc) do { (desc).regout[1] |= 1 << 1; } while (0) -#define AV_USED(desc) do { (desc).regin[1] |= 1 << 2; } while (0) -#define AV_MODIFIED(desc) do { (desc).regout[1] |= 1 << 2; } while (0) -#define AU_USED(desc) do { (desc).regin[1] |= 1 << 3; } while (0) -#define AU_MODIFIED(desc) do { (desc).regout[1] |= 1 << 3; } while (0) -#define AD_USED(desc) do { (desc).regin[1] |= 1 << 4; } while (0) -#define AD_MODIFIED(desc) do { (desc).regout[1] |= 1 << 4; } while (0) -#define ZC_USED(desc) do { (desc).regin[1] |= 1 << 5; } while (0) -#define ZC_MODIFIED(desc) do { (desc).regout[1] |= 1 << 5; } while (0) -#define IL_USED(desc) do { (desc).regin[1] |= 1 << 6; } while (0) -#define IL_MODIFIED(desc) do { (desc).regout[1] |= 1 << 6; } while (0) -#define NR_USED(desc) do { (desc).regin[1] |= 1 << 7; } while (0) -#define NR_MODIFIED(desc) do { (desc).regout[1] |= 1 << 7; } while (0) -#define ZD_USED(desc) do { (desc).regin[1] |= 1 << 8; } while (0) -#define ZD_MODIFIED(desc) do { (desc).regout[1] |= 1 << 8; } while (0) -#define MN_USED(desc) do { (desc).regin[1] |= 1 << 9; } while (0) -#define MN_MODIFIED(desc) do { (desc).regout[1] |= 1 << 9; } while (0) -#define MZ_USED(desc) do { (desc).regin[1] |= 1 << 10; } while (0) -#define MZ_MODIFIED(desc) do { (desc).regout[1] |= 1 << 10; } while (0) -#define MV_USED(desc) do { (desc).regin[1] |= 1 << 11; } while (0) -#define MV_MODIFIED(desc) do { (desc).regout[1] |= 1 << 11; } while (0) -#define MU_USED(desc) do { (desc).regin[1] |= 1 << 12; } while (0) -#define MU_MODIFIED(desc) do { (desc).regout[1] |= 1 << 12; } while (0) -#define MD_USED(desc) do { (desc).regin[1] |= 1 << 13; } while (0) -#define MD_MODIFIED(desc) do { (desc).regout[1] |= 1 << 13; } while (0) - - -mb86235_frontend::mb86235_frontend(mb86235_device *core, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) - : drc_frontend(*core, window_start, window_end, max_sequence), +#include "cpu/drcfe.ipp" + + +mb86235_device::frontend::frontend(mb86235_device *core, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) : + drc_frontend_base(core->space_config(AS_PROGRAM)->page_shift(), window_start, window_end, max_sequence), m_core(core) { } +mb86235_device::frontend::~frontend() +{ +} + + +mb86235_device::opcode_desc const *mb86235_device::frontend::describe_code(offs_t startpc) +{ + return do_describe_code( + [this] (opcode_desc &desc, opcode_desc const *prev) { return describe(desc, prev); }, + startpc); +} + -bool mb86235_frontend::describe(opcode_desc &desc, const opcode_desc *prev) +bool mb86235_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) { - uint64_t opcode = desc.opptr.q[0] = m_core->m_pcache.read_qword(desc.pc, 0); + uint64_t opcode = desc.opptr = m_core->m_pcache.read_qword(desc.pc, 0); desc.length = 1; - desc.cycles = 1; // repeatable instruction needs an entry point if (prev != nullptr) { - if (prev->userflags & OP_USERFLAG_REPEAT) + if (prev->repeat()) { - desc.flags |= OPFLAG_IS_BRANCH_TARGET; - desc.userflags |= OP_USERFLAG_REPEATED_OP; + desc.set_is_branch_target(); + desc.set_repeated_op(); } } @@ -127,32 +97,29 @@ bool mb86235_frontend::describe(opcode_desc &desc, const opcode_desc *prev) return true; } -void mb86235_frontend::describe_alu_input(opcode_desc &desc, int reg) +void mb86235_device::frontend::describe_alu_input(opcode_desc &desc, int reg) { switch (reg) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: - AA_USED(desc, reg & 7); + desc.set_aa_used(reg & 7); break; case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: - AB_USED(desc, reg & 7); + desc.set_ab_used(reg & 7); break; case 0x10: // PR break; case 0x11: // PR++ - desc.userflags &= ~OP_USERFLAG_PR_MASK; - desc.userflags |= OP_USERFLAG_PR_INC; + desc.set_pr_inc(); break; case 0x12: // PR-- - desc.userflags &= ~OP_USERFLAG_PR_MASK; - desc.userflags |= OP_USERFLAG_PR_DEC; + desc.set_pr_dec(); break; case 0x13: // PR#0 - desc.userflags &= ~OP_USERFLAG_PR_MASK; - desc.userflags |= OP_USERFLAG_PR_ZERO; + desc.set_pr_zero(); break; @@ -161,37 +128,37 @@ void mb86235_frontend::describe_alu_input(opcode_desc &desc, int reg) } } -void mb86235_frontend::describe_mul_input(opcode_desc &desc, int reg) +void mb86235_device::frontend::describe_mul_input(opcode_desc &desc, int reg) { switch (reg) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: - MA_USED(desc, reg & 7); + desc.set_ma_used(reg & 7); break; case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: - MB_USED(desc, reg & 7); + desc.set_mb_used(reg & 7); break; case 0x10: // PR break; case 0x11: // PR++ - if ((desc.userflags & OP_USERFLAG_PR_MASK) == 0) // ALU PR update has higher priority + if (desc.pr() == 0) // ALU PR update has higher priority { - desc.userflags |= OP_USERFLAG_PR_INC; + desc.set_pr_inc(); } break; case 0x12: // PR-- - if ((desc.userflags & OP_USERFLAG_PR_MASK) == 0) // ALU PR update has higher priority + if (desc.pr() == 0) // ALU PR update has higher priority { - desc.userflags |= OP_USERFLAG_PR_DEC; + desc.set_pr_dec(); } break; case 0x13: // PR#0 - if ((desc.userflags & OP_USERFLAG_PR_MASK) == 0) // ALU PR update has higher priority + if (desc.pr() == 0) // ALU PR update has higher priority { - desc.userflags |= OP_USERFLAG_PR_ZERO; + desc.set_pr_zero(); } break; @@ -200,24 +167,24 @@ void mb86235_frontend::describe_mul_input(opcode_desc &desc, int reg) } } -void mb86235_frontend::describe_alumul_output(opcode_desc &desc, int reg) +void mb86235_device::frontend::describe_alumul_output(opcode_desc &desc, int reg) { switch (reg >> 3) { case 0: - MA_MODIFIED(desc, reg & 7); + desc.set_ma_modified(reg & 7); break; case 1: - MB_MODIFIED(desc, reg & 7); + desc.set_mb_modified(reg & 7); break; case 2: - AA_MODIFIED(desc, reg & 7); + desc.set_aa_modified(reg & 7); break; case 3: - AB_MODIFIED(desc, reg & 7); + desc.set_ab_modified(reg & 7); break; default: @@ -225,34 +192,34 @@ void mb86235_frontend::describe_alumul_output(opcode_desc &desc, int reg) } } -void mb86235_frontend::describe_reg_read(opcode_desc &desc, int reg) +void mb86235_device::frontend::describe_reg_read(opcode_desc &desc, int reg) { switch (reg) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: // MA0-7 - MA_USED(desc, reg & 7); + desc.set_ma_used(reg & 7); break; case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: // AA0-7 - AA_USED(desc, reg & 7); + desc.set_aa_used(reg & 7); break; case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: // AR0-7 - AR_USED(desc, reg & 7); + desc.set_ar_used(reg & 7); break; case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: // MB0-7 - MB_USED(desc, reg & 7); + desc.set_mb_used(reg & 7); break; case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: // AB0-7 - AB_USED(desc, reg & 7); + desc.set_ab_used(reg & 7); break; case 0x31: // FI - desc.userflags |= OP_USERFLAG_FIFOIN; - desc.flags |= OPFLAG_IS_BRANCH_TARGET; // fifo check makes this a branch target + desc.set_fifoin(); + desc.set_is_branch_target(); // fifo check makes this a branch target break; case 0x32: // FO0 @@ -273,37 +240,37 @@ void mb86235_frontend::describe_reg_read(opcode_desc &desc, int reg) break; case 0x30: // PR - if ((desc.userflags & OP_USERFLAG_PR_MASK) == 0) // ALU and MUL PR updates have higher priority + if (desc.pr() == 0) // ALU and MUL PR updates have higher priority { - desc.userflags |= OP_USERFLAG_PR_INC; + desc.set_pr_inc(); } break; } } -void mb86235_frontend::describe_reg_write(opcode_desc &desc, int reg) +void mb86235_device::frontend::describe_reg_write(opcode_desc &desc, int reg) { switch (reg) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: // MA0-7 - MA_MODIFIED(desc, reg & 7); + desc.set_ma_modified(reg & 7); break; case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: // AA0-7 - AA_MODIFIED(desc, reg & 7); + desc.set_aa_modified(reg & 7); break; case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: // AR0-7 - AR_MODIFIED(desc, reg & 7); + desc.set_ar_modified(reg & 7); break; case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: // MB0-7 - MB_MODIFIED(desc, reg & 7); + desc.set_mb_modified(reg & 7); break; case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: // AB0-7 - AB_MODIFIED(desc, reg & 7); + desc.set_ab_modified(reg & 7); break; case 0x31: // FI @@ -311,8 +278,8 @@ void mb86235_frontend::describe_reg_write(opcode_desc &desc, int reg) case 0x32: // FO0 case 0x33: // FO1 - desc.userflags |= OP_USERFLAG_FIFOOUT; - desc.flags |= OPFLAG_IS_BRANCH_TARGET; // fifo check makes this a branch target + desc.set_fifoout(); + desc.set_is_branch_target(); // fifo check makes this a branch target break; case 0x10: // EB @@ -329,14 +296,13 @@ void mb86235_frontend::describe_reg_write(opcode_desc &desc, int reg) break; case 0x30: // PR - desc.userflags &= ~OP_USERFLAG_PW_MASK; - desc.userflags |= OP_USERFLAG_PW_INC; + desc.set_pw_inc(); break; } } -void mb86235_frontend::describe_alu(opcode_desc &desc, uint32_t aluop) +void mb86235_device::frontend::describe_alu(opcode_desc &desc, uint32_t aluop) { int i1 = (aluop >> 10) & 0xf; int i2 = (aluop >> 5) & 0x1f; @@ -347,218 +313,218 @@ void mb86235_frontend::describe_alu(opcode_desc &desc, uint32_t aluop) { case 0x00: // FADD describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AV_MODIFIED(desc); - AU_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_av_modified(); + desc.set_au_modified(); break; case 0x01: // FADDZ describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io); - ZC_MODIFIED(desc); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AV_MODIFIED(desc); - AU_MODIFIED(desc); - AD_MODIFIED(desc); + desc.set_zc_modified(); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_av_modified(); + desc.set_au_modified(); + desc.set_ad_modified(); break; case 0x02: // FSUB describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AV_MODIFIED(desc); - AU_MODIFIED(desc); - AD_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_av_modified(); + desc.set_au_modified(); + desc.set_ad_modified(); break; case 0x03: // FSUBZ describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io); - ZC_MODIFIED(desc); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AV_MODIFIED(desc); - AU_MODIFIED(desc); - AD_MODIFIED(desc); + desc.set_zc_modified(); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_av_modified(); + desc.set_au_modified(); + desc.set_ad_modified(); break; case 0x04: // FCMP describe_alu_input(desc, i1); describe_alu_input(desc, i2); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AV_MODIFIED(desc); - AU_MODIFIED(desc); - AD_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_av_modified(); + desc.set_au_modified(); + desc.set_ad_modified(); break; case 0x05: // FABS describe_alu_input(desc, i1); describe_alumul_output(desc, io); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AD_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_ad_modified(); break; case 0x06: // FABC describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AU_MODIFIED(desc); - AD_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_au_modified(); + desc.set_ad_modified(); break; case 0x07: // NOP break; case 0x08: // FEA describe_alu_input(desc, i1); describe_alumul_output(desc, io); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AV_MODIFIED(desc); - AD_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_av_modified(); + desc.set_ad_modified(); break; case 0x09: // FES describe_alu_input(desc, i1); describe_alumul_output(desc, io); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AU_MODIFIED(desc); - AD_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_au_modified(); + desc.set_ad_modified(); break; case 0x0a: // FRCP describe_alu_input(desc, i1); describe_alumul_output(desc, io); - ZD_MODIFIED(desc); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AU_MODIFIED(desc); - AD_MODIFIED(desc); + desc.set_zd_modified(); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_au_modified(); + desc.set_ad_modified(); break; case 0x0b: // FRSQ describe_alu_input(desc, i1); describe_alumul_output(desc, io); - NR_MODIFIED(desc); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AU_MODIFIED(desc); - AD_MODIFIED(desc); + desc.set_nr_modified(); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_au_modified(); + desc.set_ad_modified(); break; case 0x0c: // FLOG describe_alu_input(desc, i1); describe_alumul_output(desc, io); - IL_MODIFIED(desc); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AD_MODIFIED(desc); + desc.set_il_modified(); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_ad_modified(); break; case 0x0d: // CIF describe_alu_input(desc, i1); describe_alumul_output(desc, io); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); break; case 0x0e: // CFI describe_alu_input(desc, i1); describe_alumul_output(desc, io); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AV_MODIFIED(desc); - AD_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_av_modified(); + desc.set_ad_modified(); break; case 0x0f: // CFIB describe_alu_input(desc, i1); describe_alumul_output(desc, io); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AV_MODIFIED(desc); - AD_MODIFIED(desc); - AU_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_av_modified(); + desc.set_ad_modified(); + desc.set_au_modified(); break; case 0x10: // ADD describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AV_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_av_modified(); break; case 0x11: // ADDZ describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io); - ZC_MODIFIED(desc); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AV_MODIFIED(desc); + desc.set_zc_modified(); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_av_modified(); break; case 0x12: // SUB describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AV_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_av_modified(); break; case 0x13: // SUBZ describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io); - ZC_MODIFIED(desc); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AV_MODIFIED(desc); + desc.set_zc_modified(); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_av_modified(); break; case 0x14: // CMP describe_alu_input(desc, i1); describe_alu_input(desc, i2); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AV_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_av_modified(); break; case 0x15: // ABS describe_alu_input(desc, i1); describe_alumul_output(desc, io); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AV_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_av_modified(); break; case 0x16: // ATR describe_alu_input(desc, i1); describe_alumul_output(desc, io); break; case 0x17: // ATRZ describe_alu_input(desc, i1); describe_alumul_output(desc, io); - ZC_MODIFIED(desc); + desc.set_zc_modified(); break; case 0x18: // AND describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AV_MODIFIED(desc); - AU_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_av_modified(); + desc.set_au_modified(); break; case 0x19: // OR describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AV_MODIFIED(desc); - AU_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_av_modified(); + desc.set_au_modified(); break; case 0x1a: // XOR describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AV_MODIFIED(desc); - AU_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_av_modified(); + desc.set_au_modified(); break; case 0x1b: // NOT describe_alu_input(desc, i1); describe_alumul_output(desc, io); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AV_MODIFIED(desc); - AU_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_av_modified(); + desc.set_au_modified(); break; case 0x1c: // LSR describe_alu_input(desc, i1); describe_alumul_output(desc, io); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AV_MODIFIED(desc); - AU_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_av_modified(); + desc.set_au_modified(); break; case 0x1d: // LSL describe_alu_input(desc, i1); describe_alumul_output(desc, io); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); - AV_MODIFIED(desc); - AU_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); + desc.set_av_modified(); + desc.set_au_modified(); break; case 0x1e: // ASR describe_alu_input(desc, i1); describe_alumul_output(desc, io); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); break; case 0x1f: // ASL describe_alu_input(desc, i1); describe_alumul_output(desc, io); - AN_MODIFIED(desc); - AZ_MODIFIED(desc); + desc.set_an_modified(); + desc.set_az_modified(); break; } } -void mb86235_frontend::describe_mul(opcode_desc &desc, uint32_t mulop) +void mb86235_device::frontend::describe_mul(opcode_desc &desc, uint32_t mulop) { int i1 = (mulop >> 10) & 0xf; int i2 = (mulop >> 5) & 0x1f; @@ -572,78 +538,78 @@ void mb86235_frontend::describe_mul(opcode_desc &desc, uint32_t mulop) if (m) { // FMUL - MN_MODIFIED(desc); - MZ_MODIFIED(desc); - MV_MODIFIED(desc); - MU_MODIFIED(desc); - MD_MODIFIED(desc); + desc.set_mn_modified(); + desc.set_mz_modified(); + desc.set_mv_modified(); + desc.set_mu_modified(); + desc.set_md_modified(); } else { // MUL - MN_MODIFIED(desc); - MZ_MODIFIED(desc); - MV_MODIFIED(desc); + desc.set_mn_modified(); + desc.set_mz_modified(); + desc.set_mv_modified(); } } -void mb86235_frontend::describe_ea(opcode_desc &desc, int md, int arx, int ary, int disp) +void mb86235_device::frontend::describe_ea(opcode_desc &desc, int md, int arx, int ary, int disp) { switch (md) { case 0x0: // @ARx - AR_USED(desc, arx); + desc.set_ar_used(arx); break; case 0x1: // @ARx++ - AR_USED(desc, arx); AR_MODIFIED(desc, arx); + desc.set_ar_used(arx); desc.set_ar_modified(arx); break; case 0x2: // @ARx-- - AR_USED(desc, arx); AR_MODIFIED(desc, arx); + desc.set_ar_used(arx); desc.set_ar_modified(arx); break; case 0x3: // @ARx++disp - AR_USED(desc, arx); AR_MODIFIED(desc, arx); + desc.set_ar_used(arx); desc.set_ar_modified(arx); break; case 0x4: // @ARx+ARy - AR_USED(desc, arx); AR_USED(desc, ary); + desc.set_ar_used(arx); desc.set_ar_used(ary); break; case 0x5: // @ARx+ARy++ - AR_USED(desc, arx); AR_USED(desc, ary); AR_MODIFIED(desc, ary); + desc.set_ar_used(arx); desc.set_ar_used(ary); desc.set_ar_modified(ary); break; case 0x6: // @ARx+ARy-- - AR_USED(desc, arx); AR_USED(desc, ary); AR_MODIFIED(desc, ary); + desc.set_ar_used(arx); desc.set_ar_used(ary); desc.set_ar_modified(ary); break; case 0x7: // @ARx+ARy++disp - AR_USED(desc, arx); AR_USED(desc, ary); AR_MODIFIED(desc, ary); + desc.set_ar_used(arx); desc.set_ar_used(ary); desc.set_ar_modified(ary); break; case 0x8: // @ARx+ARyU - AR_USED(desc, arx); AR_USED(desc, ary); + desc.set_ar_used(arx); desc.set_ar_used(ary); break; case 0x9: // @ARx+ARyL - AR_USED(desc, arx); AR_USED(desc, ary); + desc.set_ar_used(arx); desc.set_ar_used(ary); break; case 0xa: // @ARx+disp - AR_USED(desc, arx); + desc.set_ar_used(arx); break; case 0xb: // @ARx+ARy+disp - AR_USED(desc, arx); AR_USED(desc, ary); + desc.set_ar_used(arx); desc.set_ar_used(ary); break; case 0xc: // @disp break; case 0xd: // @ARx+[ARy++] - AR_USED(desc, arx); AR_USED(desc, ary); AR_MODIFIED(desc, ary); + desc.set_ar_used(arx); desc.set_ar_used(ary); desc.set_ar_modified(ary); break; case 0xe: // @ARx+[ARy--] - AR_USED(desc, arx); AR_USED(desc, ary); AR_MODIFIED(desc, ary); + desc.set_ar_used(arx); desc.set_ar_used(ary); desc.set_ar_modified(ary); break; case 0xf: // @ARx+[ARy++disp] - AR_USED(desc, arx); AR_USED(desc, ary); AR_MODIFIED(desc, ary); + desc.set_ar_used(arx); desc.set_ar_used(ary); desc.set_ar_modified(ary); break; } } -void mb86235_frontend::describe_xfer1(opcode_desc &desc) +void mb86235_device::frontend::describe_xfer1(opcode_desc &desc) { - uint64_t opcode = desc.opptr.q[0]; + uint64_t opcode = desc.opptr; int dr = (opcode >> 12) & 0x7f; int sr = (opcode >> 19) & 0x7f; @@ -666,7 +632,7 @@ void mb86235_frontend::describe_xfer1(opcode_desc &desc) else { describe_ea(desc, md, sr & 7, ary, disp5); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); } if ((dr & 0x40) == 0) @@ -676,7 +642,7 @@ void mb86235_frontend::describe_xfer1(opcode_desc &desc) else { describe_ea(desc, md, dr & 7, ary, disp5); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); } } else @@ -685,26 +651,26 @@ void mb86235_frontend::describe_xfer1(opcode_desc &desc) if (dir == 0) { describe_reg_read(desc, dr & 0x3f); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); } else { describe_reg_write(desc, dr & 0x3f); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); } } } -void mb86235_frontend::describe_double_xfer1(opcode_desc &desc) +void mb86235_device::frontend::describe_double_xfer1(opcode_desc &desc) { - uint64_t opcode = desc.opptr.q[0]; + uint64_t opcode = desc.opptr; - fatalerror("mb86235_frontend: describe_double_xfer1 at %08X (%08X%08X)", desc.pc, (uint32_t)(opcode >> 32), (uint32_t)(opcode)); + fatalerror("mb86235_device::frontend: describe_double_xfer1 at %08X (%08X%08X)", desc.pc, (uint32_t)(opcode >> 32), (uint32_t)(opcode)); } -void mb86235_frontend::describe_xfer2(opcode_desc &desc) +void mb86235_device::frontend::describe_xfer2(opcode_desc &desc) { - uint64_t opcode = desc.opptr.q[0]; + uint64_t opcode = desc.opptr; int op = (opcode >> 39) & 3; int trm = (opcode >> 38) & 1; @@ -730,7 +696,7 @@ void mb86235_frontend::describe_xfer2(opcode_desc &desc) else { describe_ea(desc, md, sr & 7, ary, disp14); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); } if ((dr & 0x40) == 0) @@ -740,7 +706,7 @@ void mb86235_frontend::describe_xfer2(opcode_desc &desc) else { describe_ea(desc, md, dr & 7, ary, disp14); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); } } else @@ -749,31 +715,31 @@ void mb86235_frontend::describe_xfer2(opcode_desc &desc) if (dir == 0) { describe_reg_read(desc, dr & 0x3f); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); } else { describe_reg_write(desc, dr & 0x3f); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); } } } else if (op == 2) // MOV4 { - fatalerror("mb86235_frontend: describe_xfer2 MOV4 at %08X (%08X%08X)", desc.pc, (uint32_t)(opcode >> 32), (uint32_t)(opcode)); + fatalerror("mb86235_device::frontend: describe_xfer2 MOV4 at %08X (%08X%08X)", desc.pc, (uint32_t)(opcode >> 32), (uint32_t)(opcode)); } } -void mb86235_frontend::describe_double_xfer2(opcode_desc &desc) +void mb86235_device::frontend::describe_double_xfer2(opcode_desc &desc) { - uint64_t opcode = desc.opptr.q[0]; - fatalerror("mb86235_frontend: describe_double_xfer2 at %08X (%08X%08X)", desc.pc, (uint32_t)(opcode >> 32), (uint32_t)(opcode)); + uint64_t opcode = desc.opptr; + fatalerror("mb86235_device::frontend: describe_double_xfer2 at %08X (%08X%08X)", desc.pc, (uint32_t)(opcode >> 32), (uint32_t)(opcode)); } -void mb86235_frontend::describe_xfer3(opcode_desc &desc) +void mb86235_device::frontend::describe_xfer3(opcode_desc &desc) { - uint64_t opcode = desc.opptr.q[0]; + uint64_t opcode = desc.opptr; int dr = (opcode >> 19) & 0x7f; int disp = (opcode >> 7) & 0xfff; @@ -789,18 +755,18 @@ void mb86235_frontend::describe_xfer3(opcode_desc &desc) case 2: // RAM-A case 3: // RAM-B - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); describe_ea(desc, md, dr & 7, ary, disp); break; } } -void mb86235_frontend::describe_control(opcode_desc &desc) +void mb86235_device::frontend::describe_control(opcode_desc &desc) { - int ef1 = (desc.opptr.q[0] >> 16) & 0x3f; - int ef2 = desc.opptr.q[0] & 0xffff; - int cop = (desc.opptr.q[0] >> 22) & 0x1f; - int rel12 = util::sext<int>(desc.opptr.q[0], 12); + int ef1 = (desc.opptr >> 16) & 0x3f; + int ef2 = desc.opptr & 0xffff; + int cop = (desc.opptr >> 22) & 0x1f; + int rel12 = util::sext<unsigned>(desc.opptr, 12); switch (cop) { @@ -808,13 +774,13 @@ void mb86235_frontend::describe_control(opcode_desc &desc) break; case 0x01: // REP if (ef1 != 0) // ARx - AR_USED(desc, (ef2 >> 12) & 7); + desc.set_ar_used((ef2 >> 12) & 7); - desc.userflags |= OP_USERFLAG_REPEAT; + desc.set_repeat(); break; case 0x02: // SETL if (ef1 != 0) // ARx - AR_USED(desc, (ef2 >> 12) & 7); + desc.set_ar_used((ef2 >> 12) & 7); break; case 0x03: // CLRFI/CLRFO/CLRF break; @@ -837,24 +803,25 @@ void mb86235_frontend::describe_control(opcode_desc &desc) case 0x0d: // SETM #imm1, WAIT break; case 0x13: // DBLP rel12 - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.set_is_conditional_branch(); desc.targetpc = desc.pc + rel12; desc.delayslots = 1; break; case 0x14: // DBBC ARx:y, rel12 - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.set_is_conditional_branch(); desc.targetpc = desc.pc + rel12; desc.delayslots = 1; - AR_USED(desc, ((desc.opptr.q[0] >> 13) & 7)); + desc.set_ar_used(((desc.opptr >> 13) & 7)); break; case 0x15: // DBBS ARx:y, rel12 - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.set_is_conditional_branch(); desc.targetpc = desc.pc + rel12; desc.delayslots = 1; - AR_USED(desc, ((desc.opptr.q[0] >> 13) & 7)); + desc.set_ar_used(((desc.opptr >> 13) & 7)); break; case 0x1b: // DRET - 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; break; @@ -864,7 +831,7 @@ void mb86235_frontend::describe_control(opcode_desc &desc) case 0x18: // DCcc case 0x19: // DCNcc { - switch ((desc.opptr.q[0] >> 12) & 0xf) + switch ((desc.opptr >> 12) & 0xf) { case 0x0: desc.targetpc = ef2 & 0xfff; break; case 0x1: desc.targetpc = desc.pc + rel12; break; @@ -884,7 +851,7 @@ void mb86235_frontend::describe_control(opcode_desc &desc) case 0xf: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break; } - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.set_is_conditional_branch(); desc.delayslots = 1; break; } @@ -892,7 +859,7 @@ void mb86235_frontend::describe_control(opcode_desc &desc) case 0x1a: // DCALL case 0x12: // DJMP { - switch ((desc.opptr.q[0] >> 12) & 0xf) + switch ((desc.opptr >> 12) & 0xf) { case 0x0: desc.targetpc = ef2 & 0xfff; break; case 0x1: desc.targetpc = desc.pc + rel12; break; @@ -912,7 +879,8 @@ void mb86235_frontend::describe_control(opcode_desc &desc) case 0xf: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break; } - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); desc.delayslots = 1; break; } diff --git a/src/devices/cpu/mb86235/mb86235fe.h b/src/devices/cpu/mb86235/mb86235fe.h index ed160a98c0a..0cf63cb0982 100644 --- a/src/devices/cpu/mb86235/mb86235fe.h +++ b/src/devices/cpu/mb86235/mb86235fe.h @@ -13,20 +13,175 @@ #pragma once #include "mb86235.h" + #include "cpu/drcfe.h" -class mb86235_frontend : public drc_frontend +#include <cassert> + + +class mb86235_device::opcode_desc : public opcode_desc_base<opcode_desc, 56> +{ +public: + enum : uint8_t { INC = 1, DEC, ZERO }; + + uint64_t opptr; // copy of opcode + + void set_aa_used(unsigned n) { regin.set(REG_AA0 + n); } + void set_aa_modified(unsigned n) { regout.set(REG_AA0 + n); } + void set_ab_used(unsigned n) { regin.set(REG_AB0 + n); } + void set_ab_modified(unsigned n) { regout.set(REG_AB0 + n); } + void set_ma_used(unsigned n) { regin.set(REG_MA0 + n); } + void set_ma_modified(unsigned n) { regout.set(REG_MA0 + n); } + void set_mb_used(unsigned n) { regin.set(REG_MB0 + n); } + void set_mb_modified(unsigned n) { regout.set(REG_MB0 + n); } + void set_ar_used(unsigned n) { regin.set(REG_AR0 + n); } + void set_ar_modified(unsigned n) { regout.set(REG_AR0 + n); } + + void set_az_used() { regin.set(REG_AZ); } + void set_az_modified() { regout.set(REG_AZ); } + void set_an_used() { regin.set(REG_AN); } + void set_an_modified() { regout.set(REG_AN); } + void set_av_used() { regin.set(REG_AV); } + void set_av_modified() { regout.set(REG_AV); } + void set_au_used() { regin.set(REG_AU); } + void set_au_modified() { regout.set(REG_AU); } + void set_ad_used() { regin.set(REG_AD); } + void set_ad_modified() { regout.set(REG_AD); } + void set_zc_used() { regin.set(REG_ZC); } + void set_zc_modified() { regout.set(REG_ZC); } + void set_il_used() { regin.set(REG_IL); } + void set_il_modified() { regout.set(REG_IL); } + void set_nr_used() { regin.set(REG_NR); } + void set_nr_modified() { regout.set(REG_NR); } + void set_zd_used() { regin.set(REG_ZD); } + void set_zd_modified() { regout.set(REG_ZD); } + void set_mn_used() { regin.set(REG_MN); } + void set_mn_modified() { regout.set(REG_MN); } + void set_mz_used() { regin.set(REG_MZ); } + void set_mz_modified() { regout.set(REG_MZ); } + void set_mv_used() { regin.set(REG_MV); } + void set_mv_modified() { regout.set(REG_MV); } + void set_mu_used() { regin.set(REG_MU); } + void set_mu_modified() { regout.set(REG_MU); } + void set_md_used() { regin.set(REG_MD); } + void set_md_modified() { regout.set(REG_MD); } + + bool aa_used(unsigned n) const { return regin[REG_AA0 + n]; } + bool aa_modified(unsigned n) const { return regout[REG_AA0 + n]; } + bool ab_used(unsigned n) const { return regin[REG_AB0 + n]; } + bool ab_modified(unsigned n) const { return regout[REG_AB0 + n]; } + bool ma_used(unsigned n) const { return regin[REG_MA0 + n]; } + bool ma_modified(unsigned n) const { return regout[REG_MA0 + n]; } + bool mb_used(unsigned n) const { return regin[REG_MB0 + n]; } + bool mb_modified(unsigned n) const { return regout[REG_MB0 + n]; } + bool ar_used(unsigned n) const { return regin[REG_AR0 + n]; } + bool ar_modified(unsigned n) const { return regout[REG_AR0 + n]; } + + bool az_calc_required() const { return regreq[REG_AZ] || in_delay_slot(); } + bool an_calc_required() const { return regreq[REG_AN] || in_delay_slot(); } + bool av_calc_required() const { return regreq[REG_AV] || in_delay_slot(); } + bool au_calc_required() const { return regreq[REG_AU] || in_delay_slot(); } + bool ad_calc_required() const { return regreq[REG_AD] || in_delay_slot(); } + bool zc_calc_required() const { return regreq[REG_ZC] || in_delay_slot(); } + bool il_calc_required() const { return regreq[REG_IL] || in_delay_slot(); } + bool nr_calc_required() const { return regreq[REG_NR] || in_delay_slot(); } + bool zd_calc_required() const { return regreq[REG_ZD] || in_delay_slot(); } + bool mn_calc_required() const { return regreq[REG_MN] || in_delay_slot(); } + bool mz_calc_required() const { return regreq[REG_MZ] || in_delay_slot(); } + bool mv_calc_required() const { return regreq[REG_MV] || in_delay_slot(); } + bool mu_calc_required() const { return regreq[REG_MU] || in_delay_slot(); } + bool md_calc_required() const { return regreq[REG_MD] || in_delay_slot(); } + + void set_reads_memory() { m_reads_memory = true; } + void set_writes_memory() { m_writes_memory = true; } + void set_fifoin() { m_fifoin = true; } + void set_fifoout() { m_fifoout = true; } + void set_repeat() { m_repeat = true; } + void set_repeated_op() { m_repeated_op = true; } + void set_pr_inc() { m_pr = INC; } + void set_pr_dec() { m_pr = DEC; } + void set_pr_zero() { m_pr = ZERO; } + void set_pw_inc() { m_pw = INC; } + void set_pw_dec() { m_pw = DEC; } + void set_pw_zero() { m_pw = ZERO; } + + bool reads_memory() const { return m_reads_memory; } + bool writes_memory() const { return m_writes_memory; } + bool fifoin() const { return m_fifoin; } + bool fifoout() const { return m_fifoout; } + bool repeat() const { return m_repeat; } + bool repeated_op() const { return m_repeated_op; } + uint8_t pr() const { return m_pr; } + uint8_t pw() const { return m_pw; } + + void reset(offs_t curpc, bool in_delay_slot) + { + static_assert(REG_COUNT <= 56); + + opcode_desc_base::reset(curpc, in_delay_slot); + + opptr = 0; + m_reads_memory = false; + m_writes_memory = false; + m_fifoin = false; + m_fifoout = false; + m_repeat = false; + m_repeated_op = false; + m_pr = 0; + m_pw = 0; + } + +private: + enum + { + REG_AA0 = 0, + REG_AB0 = REG_AA0 + 8, + REG_MA0 = REG_AB0 + 8, + REG_MB0 = REG_MA0 + 8, + REG_AR0 = REG_MB0 + 8, + + REG_AZ = REG_AR0 + 8, + REG_AN, + REG_AV, + REG_AU, + REG_AD, + REG_ZC, + REG_IL, + REG_NR, + REG_ZD, + REG_MN, + REG_MZ, + REG_MV, + REG_MU, + REG_MD, + + REG_COUNT + }; + + bool m_reads_memory; + bool m_writes_memory; + bool m_fifoin; + bool m_fifoout; + bool m_repeat; + bool m_repeated_op; + uint8_t m_pr; + uint8_t m_pw; +}; + + +class mb86235_device::frontend : public drc_frontend_base<opcode_desc> { public: - mb86235_frontend(mb86235_device *core, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); + frontend(mb86235_device *core, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); + ~frontend(); -protected: - // required overrides - virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override; + opcode_desc const *describe_code(offs_t startpc); private: mb86235_device *m_core; + bool describe(opcode_desc &desc, opcode_desc const *prev); + void describe_alu(opcode_desc &desc, uint32_t aluop); void describe_mul(opcode_desc &desc, uint32_t mulop); void describe_xfer1(opcode_desc &desc); diff --git a/src/devices/cpu/mips/mips3.cpp b/src/devices/cpu/mips/mips3.cpp index a56f19a3b21..110aef87928 100644 --- a/src/devices/cpu/mips/mips3.cpp +++ b/src/devices/cpu/mips/mips3.cpp @@ -13,6 +13,7 @@ #include "mips3com.h" #include "mips3dsm.h" +#include "mips3fe.h" #include "ps2vu.h" #include "emuopts.h" @@ -219,6 +220,10 @@ mips3_device::mips3_device(const machine_config &mconfig, device_type type, cons set_vtlb_fixed_entries(2 * m_tlbentries + 2); } +mips3_device::~mips3_device() +{ +} + device_memory_interface::space_config_vector mips3_device::memory_space_config() const { return space_config_vector { @@ -486,7 +491,7 @@ void mips3_device::device_start() m_drcuml->symbol_add(&m_fpmode, sizeof(m_fpmode), "fpmode"); /* initialize the front-end helper */ - m_drcfe = std::make_unique<mips3_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE); + m_drcfe = std::make_unique<frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE); /* allocate memory for cache-local state and initialize it */ memcpy(m_fpmode, fpmode_source, sizeof(fpmode_source)); diff --git a/src/devices/cpu/mips/mips3.h b/src/devices/cpu/mips/mips3.h index 181df0e9a47..bcf6891bd0b 100644 --- a/src/devices/cpu/mips/mips3.h +++ b/src/devices/cpu/mips/mips3.h @@ -14,13 +14,14 @@ MIPS III/IV emulator. #pragma once +#include "ps2vu.h" -#include "cpu/drcfe.h" #include "cpu/drcuml.h" -#include "ps2vu.h" #include "divtlb.h" +#include <bitset> + DECLARE_DEVICE_TYPE(R4000BE, r4000be_device) DECLARE_DEVICE_TYPE(R4000LE, r4000le_device) @@ -257,11 +258,10 @@ INTERRUPT CONSTANTS STRUCTURES ***************************************************************************/ -class mips3_frontend; - class mips3_device : public cpu_device, public device_vtlb_interface { protected: - friend class mips3_frontend; + class frontend; + class opcode_desc; /* MIPS flavors */ enum mips3_flavor { @@ -303,6 +303,7 @@ protected: public: // construction/destruction mips3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, mips3_flavor flavor, endianness_t endiannes, uint32_t data_bits); + virtual ~mips3_device(); void set_drc_cache_size(size_t bytes) { m_drc_cache.set_size(bytes); } void set_icache_size(size_t icache_size) { c_icache_size = icache_size; } @@ -480,8 +481,8 @@ protected: /* core state */ drc_cache m_drc_cache; /* pointer to the DRC code cache */ - std::unique_ptr<drcuml_state> m_drcuml;/* DRC UML generator state */ - std::unique_ptr<mips3_frontend> m_drcfe; /* pointer to the DRC front-end state */ + std::unique_ptr<drcuml_state> m_drcuml; /* DRC UML generator state */ + std::unique_ptr<frontend> m_drcfe; /* pointer to the DRC front-end state */ uint32_t m_drcoptions; /* configurable DRC options */ /* internal stuff */ @@ -655,8 +656,8 @@ private: void generate_badcop(drcuml_block &block, const int cop); void log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32_t op); - 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(opcode_desc const &desc); + void log_register_list(const char *string, const std::bitset<68> ®list, const std::bitset<68> *regnostarlist); void log_opcode_desc(const opcode_desc *desclist, int indent); void load_elf(); @@ -1011,31 +1012,6 @@ public: }; - -class mips3_frontend : public drc_frontend { -public: - // construction/destruction - mips3_frontend(mips3_device *mips3, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); - -protected: - // required overrides - virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override; - -private: - // internal helpers - bool describe_special(uint32_t op, opcode_desc &desc); - bool describe_regimm(uint32_t op, opcode_desc &desc); - bool describe_idt(uint32_t op, opcode_desc &desc); - bool describe_cop0(uint32_t op, opcode_desc &desc); - bool describe_cop1(uint32_t op, opcode_desc &desc); - bool describe_cop1x(uint32_t op, opcode_desc &desc); - bool describe_cop2(uint32_t op, opcode_desc &desc); - - // internal state - mips3_device *m_mips3; -}; - - /*************************************************************************** COMPILER-SPECIFIC OPTIONS ***************************************************************************/ diff --git a/src/devices/cpu/mips/mips3drc.cpp b/src/devices/cpu/mips/mips3drc.cpp index f682da6b212..383c90529d0 100644 --- a/src/devices/cpu/mips/mips3drc.cpp +++ b/src/devices/cpu/mips/mips3drc.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles /*************************************************************************** - mips3drc.c + mips3drc.cpp Universal machine language-based MIPS III/IV emulator. @@ -24,11 +24,13 @@ ***************************************************************************/ #include "emu.h" +#include "mips3.h" + #include "mips3com.h" #include "mips3fe.h" #include "mips3dsm.h" #include "ps2vu.h" -#include "cpu/drcfe.h" + #include "cpu/drcuml.h" #include "cpu/drcumlsh.h" @@ -93,17 +95,6 @@ static const uint8_t fcc_shift[8] = { 23, 25, 26, 27, 28, 29, 30, 31 }; ***************************************************************************/ /*------------------------------------------------- - epc - compute the exception PC from a - descriptor --------------------------------------------------*/ - -static inline uint32_t epc(const opcode_desc *desc) -{ - return (desc->flags & OPFLAG_IN_DELAY_SLOT) ? (desc->pc - 3) : desc->pc; -} - - -/*------------------------------------------------- alloc_handle - allocate a handle if not already allocated -------------------------------------------------*/ @@ -340,7 +331,7 @@ void mips3_device::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); @@ -370,7 +361,7 @@ void mips3_device::code_compile_block(uint8_t mode, offs_t pc) generate_checksum_block(block, compiler, seqhead, seqlast, codelast); /* 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 } @@ -382,7 +373,7 @@ void mips3_device::code_compile_block(uint8_t mode, offs_t pc) } /* if we need to return to the start, do it */ - if (seqlast->flags & OPFLAG_RETURN_TO_START) + if (seqlast->return_to_start()) nextpc = pc; /* otherwise we just go to the next instruction */ @@ -393,7 +384,7 @@ void mips3_device::code_compile_block(uint8_t mode, offs_t pc) generate_update_cycles(block, compiler, nextpc, true); // <subtract cycles> /* if the last instruction can change modes, use a variable mode; otherwise, assume the same mode */ - if (seqlast->flags & OPFLAG_CAN_CHANGE_MODES) + if (seqlast->can_change_modes()) { UML_HASHJMP(block, mem(&m_core->mode), nextpc, *m_nocode); // hashjmp <mode>,nextpc,nocode } @@ -1155,18 +1146,18 @@ void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state & 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 & MIPS3DRC_STRICT_VERIFY) || seqhead->next() == nullptr) { - if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP)) + // loose verify or single instruction: just compare and fail + if (!seqhead->virtual_noop()) { - uint32_t sum = seqhead->opptr.l[0]; + uint32_t sum = seqhead->opptr; const void *base = m_prptr(seqhead->physpc); uint32_t low_bits = (seqhead->physpc & (m_data_bits == 64 ? 4 : 0)) ^ m_dword_xor; UML_LOAD(block, I0, base, low_bits, SIZE_DWORD, SCALE_x1); // load i0,base,0,dword if (seqhead->delay.first() != nullptr - && !(seqhead->delay.first()->flags & OPFLAG_VIRTUAL_NOOP) + && !seqhead->delay.first()->virtual_noop() && seqhead->physpc != seqhead->delay.first()->physpc) { uint32_t low_bits = (seqhead->delay.first()->physpc & (m_data_bits == 64 ? 4 : 0)) ^ m_dword_xor; @@ -1175,26 +1166,27 @@ void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state & UML_LOAD(block, I1, base, low_bits, SIZE_DWORD, SCALE_x1); // load i1,base,dword UML_ADD(block, I0, I0, I1); // add i0,i0,i1 - sum += seqhead->delay.first()->opptr.l[0]; + sum += seqhead->delay.first()->opptr; } - UML_CMP(block, I0, sum); // cmp i0,opptr[0] - UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc + UML_CMP(block, I0, sum); // 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 #if 0 for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next()) - if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP)) + { + if (!curdesc->virtual_noop()) { const void *base = m_prptr(seqhead->physpc); UML_LOAD(block, I0, base, m_dword_xor, SIZE_DWORD, SCALE_x1); // load i0,base,0,dword - UML_CMP(block, I0, curdesc->opptr.l[0]); // cmp i0,opptr[0] + UML_CMP(block, I0, curdesc->opptr); // cmp i0,opptr UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc } + } #else uint32_t sum = 0; const void *base = m_prptr(seqhead->physpc); @@ -1202,31 +1194,31 @@ void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state & const uint32_t last_physpc = codelast->physpc; uint32_t low_bits = (seqhead->physpc & data_bits_mask) ^ m_dword_xor; UML_LOAD(block, I0, base, low_bits, SIZE_DWORD, SCALE_x1); // load i0,base,0,dword - sum += seqhead->opptr.l[0]; - if ((m_drcoptions & MIPS3DRC_EXTRA_INSTR_CHECK) && !(codelast->flags & OPFLAG_VIRTUAL_NOOP) && last_physpc != seqhead->physpc) + sum += seqhead->opptr; + if ((m_drcoptions & MIPS3DRC_EXTRA_INSTR_CHECK) && !codelast->virtual_noop() && last_physpc != seqhead->physpc) { base = m_prptr(last_physpc); assert(base != nullptr); low_bits = (last_physpc & data_bits_mask) ^ m_dword_xor; UML_LOAD(block, I1, base, low_bits, SIZE_DWORD, SCALE_x1); // load i1,base,dword UML_ADD(block, I0, I0, I1); // add i0,i0,i1 - sum += codelast->opptr.l[0]; + sum += codelast->opptr; } if (!(m_drcoptions & MIPS3DRC_EXTRA_INSTR_CHECK)) { 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); assert(base != nullptr); low_bits = (curdesc->physpc & data_bits_mask) ^ m_dword_xor; UML_LOAD(block, I1, base, low_bits, SIZE_DWORD, SCALE_x1); // load i1,base,dword UML_ADD(block, I0, I0, I1); // add i0,i0,i1 - sum += curdesc->opptr.l[0]; + sum += curdesc->opptr; if (curdesc->delay.first() != nullptr - && !(curdesc->delay.first()->flags & OPFLAG_VIRTUAL_NOOP) + && !curdesc->delay.first()->virtual_noop() && (curdesc == seqlast || (curdesc->next() != nullptr && curdesc->next()->physpc != curdesc->delay.first()->physpc))) { base = m_prptr(curdesc->delay.first()->physpc); @@ -1234,7 +1226,7 @@ void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state & low_bits = (curdesc->delay.first()->physpc & data_bits_mask) ^ m_dword_xor; UML_LOAD(block, I1, base, low_bits, SIZE_DWORD, SCALE_x1); // load i1,base,dword UML_ADD(block, I0, I0, I1); // add i0,i0,i1 - sum += curdesc->delay.first()->opptr.l[0]; + sum += curdesc->delay.first()->opptr; } } } @@ -1243,7 +1235,7 @@ void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state & { for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next()) { - if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP)) + if (!curdesc->virtual_noop()) { // Skip the last if it was already included above if (curdesc->physpc != last_physpc) @@ -1253,11 +1245,11 @@ void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state & low_bits = (curdesc->physpc & data_bits_mask) ^ m_dword_xor; UML_LOAD(block, I1, base, low_bits, SIZE_DWORD, SCALE_x1); // load i1,base,dword UML_ADD(block, I0, I0, I1); // add i0,i0,i1 - sum += curdesc->opptr.l[0]; + sum += curdesc->opptr; } if (curdesc->delay.first() != nullptr - && !(curdesc->delay.first()->flags & OPFLAG_VIRTUAL_NOOP) + && !curdesc->delay.first()->virtual_noop() && (curdesc == seqlast || (curdesc->next() != nullptr && curdesc->next()->physpc != curdesc->delay.first()->physpc))) { base = m_prptr(curdesc->delay.first()->physpc); @@ -1265,13 +1257,13 @@ void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state & low_bits = (curdesc->delay.first()->physpc & data_bits_mask) ^ m_dword_xor; UML_LOAD(block, I1, base, low_bits, SIZE_DWORD, SCALE_x1); // load i1,base,dword UML_ADD(block, I0, I0, I1); // add i0,i0,i1 - sum += curdesc->delay.first()->opptr.l[0]; + sum += curdesc->delay.first()->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 if (DEBUG_STRICT_VERIFY) { // This code will do additional checks on the last instruction and last delay slot and indicate if the check failed @@ -1279,13 +1271,13 @@ void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state & uml::code_label check_failed = compiler.labelnum++; uml::code_label check_passed = compiler.labelnum++; // Check the last instruction - if (!(codelast->flags & OPFLAG_VIRTUAL_NOOP) && last_physpc != seqhead->physpc) + if (!codelast->virtual_noop() && (last_physpc != seqhead->physpc)) { base = m_prptr(last_physpc); assert(base != nullptr); low_bits = (last_physpc & (m_data_bits == 64 ? 4 : 0)) ^ m_dword_xor; UML_LOAD(block, I0, base, low_bits, SIZE_DWORD, SCALE_x1); // load i1,base,dword - sum = codelast->opptr.l[0]; + sum = codelast->opptr; UML_CMP(block, I0, sum); // cmp i0,sum UML_JMPc(block, COND_E, check_second); static const char text[] = "Last instr validation fail seq: %08X end: %08x\n"; @@ -1298,14 +1290,14 @@ void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state & UML_JMP(block, check_failed); // Check the last instruction delay slot UML_LABEL(block, check_second); - if (codelast->delay.first() != nullptr && !(codelast->delay.first()->flags & OPFLAG_VIRTUAL_NOOP) + if (codelast->delay.first() != nullptr && !codelast->delay.first()->virtual_noop() && last_physpc != seqhead->physpc) { base = m_prptr(codelast->delay.first()->physpc); assert(base != nullptr); low_bits = (codelast->delay.first()->physpc & (m_data_bits == 64 ? 4 : 0)) ^ m_dword_xor; UML_LOAD(block, I0, base, low_bits, SIZE_DWORD, SCALE_x1); // load i1,base,dword - sum = codelast->delay.first()->opptr.l[0]; + sum = codelast->delay.first()->opptr; UML_CMP(block, I0, sum); // cmp i0,sum UML_JMPc(block, COND_E, check_passed); static const char text[] = "Last delay slot validation fail seq: %08X end: %08x\n"; @@ -1319,7 +1311,7 @@ void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state & } UML_JMP(block, check_passed); UML_LABEL(block, check_failed); - UML_EXH(block, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc + UML_EXH(block, *m_nocode, seqhead->epc()); // exne nocode,seqhead->pc UML_LABEL(block, check_passed); } #endif @@ -1335,11 +1327,11 @@ void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state & void mips3_device::generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { /* add an entry for the log */ - if (m_drcuml->logging() && !(desc->flags & OPFLAG_VIRTUAL_NOOP)) - log_add_disasm_comment(block, desc->pc, desc->opptr.l[0]); + if (m_drcuml->logging() && !desc->virtual_noop()) + log_add_disasm_comment(block, desc->pc, desc->opptr); /* set the PC map variable */ - offs_t expc = (desc->flags & OPFLAG_IN_DELAY_SLOT) ? desc->pc - 3 : desc->pc; + const offs_t expc = desc->epc(); UML_MAPVAR(block, MAPVAR_PC, expc); // mapvar PC,expc /* accumulate total cycles */ @@ -1347,7 +1339,7 @@ void mips3_device::generate_sequence_instruction(drcuml_block &block, compiler_s /* is this a hotspot? */ for (int hotnum = 0; hotnum < MIPS3_MAX_HOTSPOTS; hotnum++) - if (m_hotspot[hotnum].pc != 0 && desc->pc == m_hotspot[hotnum].pc && desc->opptr.l[0] == m_hotspot[hotnum].opcode) + if (m_hotspot[hotnum].pc != 0 && desc->pc == m_hotspot[hotnum].pc && desc->opptr == m_hotspot[hotnum].opcode) { compiler.cycles += m_hotspot[hotnum].cycles; break; @@ -1372,7 +1364,7 @@ void mips3_device::generate_sequence_instruction(drcuml_block &block, compiler_s } /* if we hit an unmapped address, fatal error */ - if (desc->flags & OPFLAG_COMPILER_UNMAPPED) + if (desc->compiler_unmapped()) { UML_MOV(block, mem(&m_core->pc), desc->pc); // mov [pc],desc->pc save_fast_iregs(block); @@ -1380,7 +1372,7 @@ void mips3_device::generate_sequence_instruction(drcuml_block &block, compiler_s } /* if we hit a compiler page fault, it's just like a TLB mismatch */ - if (desc->flags & OPFLAG_COMPILER_PAGE_FAULT) + if (desc->compiler_page_fault()) { if (PRINTF_MMU) { @@ -1395,7 +1387,7 @@ void mips3_device::generate_sequence_instruction(drcuml_block &block, compiler_s } /* validate our TLB entry at this PC; if we fail, we need to handle it */ - if ((desc->flags & OPFLAG_VALIDATE_TLB) && (desc->pc < 0x80000000 || desc->pc >= 0xc0000000)) + if (desc->validate_tlb() && (desc->pc < 0x80000000 || desc->pc >= 0xc0000000)) { const vtlb_entry *tlbtable = vtlb_table(); @@ -1430,18 +1422,19 @@ void mips3_device::generate_sequence_instruction(drcuml_block &block, compiler_s } } - /* if this is an invalid opcode, generate the exception now */ - if (desc->flags & OPFLAG_INVALID_OPCODE) + if (desc->invalid_opcode()) + { + // if this is an invalid opcode, generate the exception now UML_EXH(block, *m_exception[EXCEPTION_INVALIDOP], 0); // exh invalidop,0 - - /* 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)) { UML_MOV(block, mem(&m_core->pc), desc->pc); // mov [pc],desc->pc - UML_MOV(block, mem(&m_core->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_core->arg0), desc->opptr); // mov [arg0],desc->opptr UML_CALLC(block, cfunc_unimplemented, this); // callc cfunc_unimplemented } } @@ -1455,7 +1448,7 @@ void mips3_device::generate_sequence_instruction(drcuml_block &block, compiler_s void mips3_device::generate_delay_slot_and_branch(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint8_t linkreg) { compiler_state compiler_temp(compiler); - uint32_t op = desc->opptr.l[0]; + const uint32_t op = desc->opptr; /* fetch the target register if dynamic, in case it is modified by the delay slot */ if (desc->targetpc == BRANCH_TARGET_DYNAMIC) @@ -1478,7 +1471,7 @@ void mips3_device::generate_delay_slot_and_branch(drcuml_block &block, compiler_ if (desc->targetpc != BRANCH_TARGET_DYNAMIC) { generate_update_cycles(block, compiler_temp, desc->targetpc, true); // <subtract cycles> - if (!(m_drcoptions & MIPS3DRC_DISABLE_INTRABLOCK) && (desc->flags & OPFLAG_INTRABLOCK_BRANCH)) + if (!(m_drcoptions & MIPS3DRC_DISABLE_INTRABLOCK) && desc->intrablock_branch()) { UML_JMP(block, desc->targetpc | 0x80000000); // jmp desc->targetpc | 0x80000000 } @@ -1509,9 +1502,9 @@ void mips3_device::generate_delay_slot_and_branch(drcuml_block &block, compiler_ bool mips3_device::generate_opcode(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - int in_delay_slot = ((desc->flags & OPFLAG_IN_DELAY_SLOT) != 0); - uint32_t op = desc->opptr.l[0]; - uint8_t opswitch = op >> 26; + const int in_delay_slot = desc->in_delay_slot(); + const uint32_t op = desc->opptr; + const uint8_t opswitch = op >> 26; uml::code_label skip; switch (opswitch) @@ -2047,8 +2040,8 @@ bool mips3_device::generate_opcode(drcuml_block &block, compiler_state &compiler bool mips3_device::generate_special(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - uint32_t op = desc->opptr.l[0]; - uint8_t opswitch = op & 63; + const uint32_t op = desc->opptr; + const uint8_t opswitch = op & 63; switch (opswitch) { @@ -2440,8 +2433,8 @@ bool mips3_device::generate_special(drcuml_block &block, compiler_state &compile bool mips3_device::generate_regimm(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - uint32_t op = desc->opptr.l[0]; - uint8_t opswitch = RTREG; + const uint32_t op = desc->opptr; + const uint8_t opswitch = RTREG; uml::code_label skip; switch (opswitch) @@ -2527,8 +2520,8 @@ bool mips3_device::generate_regimm(drcuml_block &block, compiler_state &compiler bool mips3_device::generate_idt(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - uint32_t op = desc->opptr.l[0]; - uint8_t opswitch = op & 0x1f; + const uint32_t op = desc->opptr; + const uint8_t opswitch = op & 0x1f; /* only enabled on IDT processors */ if (m_flavor != MIPS3_TYPE_R4650) @@ -2577,7 +2570,7 @@ bool mips3_device::generate_idt(drcuml_block &block, compiler_state &compiler, c bool mips3_device::generate_set_cop0_reg(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint8_t reg) { - int in_delay_slot = ((desc->flags & OPFLAG_IN_DELAY_SLOT) != 0); + const int in_delay_slot = desc->in_delay_slot(); uml::code_label link; switch (reg) @@ -2729,8 +2722,8 @@ void mips3_device::check_cop0_access(drcuml_block &block) bool mips3_device::generate_cop0(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - uint32_t op = desc->opptr.l[0]; - uint8_t opswitch = RSREG; + const uint32_t op = desc->opptr; + const uint8_t opswitch = RSREG; int skip; /* generate an exception if COP0 is disabled unless we are in kernel mode */ @@ -2865,7 +2858,7 @@ void mips3_device::check_cop1_access(drcuml_block &block) bool mips3_device::generate_cop1(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - uint32_t op = desc->opptr.l[0]; + const uint32_t op = desc->opptr; uml::code_label skip; uml::condition_t condition; @@ -3386,8 +3379,8 @@ bool mips3_device::generate_cop1(drcuml_block &block, compiler_state &compiler, bool mips3_device::generate_cop1x(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - int in_delay_slot = ((desc->flags & OPFLAG_IN_DELAY_SLOT) != 0); - uint32_t op = desc->opptr.l[0]; + const int in_delay_slot = desc->in_delay_slot(); + const uint32_t op = desc->opptr; check_cop1_access(block); @@ -3505,52 +3498,52 @@ void mips3_device::log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint flags -------------------------------------------------*/ -const char *mips3_device::log_desc_flags_to_string(uint32_t flags) +const char *mips3_device::log_desc_flags_to_string(opcode_desc const &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' : '.'; + *dest++ = desc.validate_tlb() ? 'V' : '.'; /* TLB modification */ - *dest++ = (flags & OPFLAG_MODIFIES_TRANSLATION) ? 'T' : '.'; + *dest++ = desc.modifies_translation() ? 'T' : '.'; /* redispatch */ - *dest++ = (flags & OPFLAG_REDISPATCH) ? 'R' : '.'; + *dest++ = desc.redispatch() ? 'R' : '.'; return tempbuf; } @@ -3559,49 +3552,52 @@ const char *mips3_device::log_desc_flags_to_string(uint32_t flags) log_register_list - log a list of GPR registers -------------------------------------------------*/ -void mips3_device::log_register_list(const char *string, const uint32_t *reglist, const uint32_t *regnostarlist) +void mips3_device::log_register_list(const char *string, const std::bitset<68> ®list, const std::bitset<68> *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 = 1; regnum < 32; regnum++) - if (reglist[0] & REGFLAG_R(regnum)) + for (int regnum = 1; regnum < 32; regnum++) + { + if (reglist[opcode_desc::REG_FLAG_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_FLAG_R0 + regnum]) m_drcuml->log_printf("*"); } + } - for (regnum = 0; regnum < 32; regnum++) - if (reglist[1] & REGFLAG_CPR1(regnum)) + for (int regnum = 0; regnum < 32; regnum++) + { + if (reglist[opcode_desc::REG_FLAG_CPR10 + regnum]) { m_drcuml->log_printf("%sfr%d", (count++ == 0) ? "" : ",", regnum); - if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_CPR1(regnum))) + if (regnostarlist && !(*regnostarlist)[opcode_desc::REG_FLAG_CPR10 + regnum]) m_drcuml->log_printf("*"); } + } - if (reglist[2] & REGFLAG_LO) + if (reglist[opcode_desc::REG_FLAG_LO]) { m_drcuml->log_printf("%slo", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[2] & REGFLAG_LO)) + if (regnostarlist && !(*regnostarlist)[opcode_desc::REG_FLAG_LO]) m_drcuml->log_printf("*"); } - if (reglist[2] & REGFLAG_HI) + if (reglist[opcode_desc::REG_FLAG_HI]) { m_drcuml->log_printf("%shi", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[2] & REGFLAG_HI)) + if (regnostarlist && !(*regnostarlist)[opcode_desc::REG_FLAG_HI]) m_drcuml->log_printf("*"); } - if (reglist[2] & REGFLAG_FCC) + if (reglist[opcode_desc::REG_FLAG_FCC]) { m_drcuml->log_printf("%sfcc", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[2] & REGFLAG_FCC)) + if (regnostarlist && !(*regnostarlist)[opcode_desc::REG_FLAG_FCC]) m_drcuml->log_printf("*"); } @@ -3627,23 +3623,23 @@ void mips3_device::log_opcode_desc(const opcode_desc *desclist, int indent) /* 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()) buffer << "<virtual nop>"; else { mips3_disassembler mips3d; - mips3d.dasm_one(buffer, desclist->pc, desclist->opptr.l[0]); + mips3d.dasm_one(buffer, desclist->pc, desclist->opptr); } } else buffer << "???"; const std::string buffer_string = buffer.str(); - m_drcuml->log_printf("%08X [%08X] t:%08X f:%s: %-30s", desclist->pc, desclist->physpc, desclist->targetpc, log_desc_flags_to_string(desclist->flags), buffer_string.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), buffer_string.c_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 */ @@ -3651,7 +3647,7 @@ void mips3_device::log_opcode_desc(const opcode_desc *desclist, int indent) 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"); } } diff --git a/src/devices/cpu/mips/mips3fe.cpp b/src/devices/cpu/mips/mips3fe.cpp index 49b86be681b..9984626f760 100644 --- a/src/devices/cpu/mips/mips3fe.cpp +++ b/src/devices/cpu/mips/mips3fe.cpp @@ -10,8 +10,10 @@ #include "emu.h" #include "mips3fe.h" + #include "mips3com.h" -#include "ps2vu.h" + +#include "cpu/drcfe.ipp" //************************************************************************** @@ -22,22 +24,31 @@ // mips3_frontend - constructor //------------------------------------------------- -mips3_frontend::mips3_frontend(mips3_device *mips3, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) - : drc_frontend(*mips3, window_start, window_end, max_sequence), - m_mips3(mips3) +mips3_device::frontend::frontend(mips3_device *mips3, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) + : drc_frontend_base(mips3->space_config(AS_PROGRAM)->page_shift(), window_start, window_end, max_sequence) + , m_mips3(mips3) { } +mips3_device::frontend::~frontend() +{ +} + +mips3_device::opcode_desc const *mips3_device::frontend::describe_code(offs_t startpc) +{ + return do_describe_code( + [this] (opcode_desc &desc, opcode_desc const *prev) { return describe(desc, prev); }, + startpc); +} + //------------------------------------------------- // describe - build a description of a single // instruction //------------------------------------------------- -bool mips3_frontend::describe(opcode_desc &desc, const opcode_desc *prev) +bool mips3_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) { - uint32_t op, opswitch; - // compute the physical PC assert((desc.physpc & 3) == 0); address_space *tspace; @@ -45,20 +56,24 @@ bool mips3_frontend::describe(opcode_desc &desc, const opcode_desc *prev) { // uh-oh: a page fault; leave the description empty and just if this is the first instruction, leave it empty and // mark as needing to validate; otherwise, just end the sequence here - desc.flags |= OPFLAG_VALIDATE_TLB | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_COMPILER_PAGE_FAULT | OPFLAG_VIRTUAL_NOOP | OPFLAG_END_SEQUENCE; + desc.set_validate_tlb(); + desc.set_can_cause_exception(); + desc.set_compiler_page_fault(); + desc.set_virtual_noop(); + desc.set_end_sequence(); return true; } // fetch the opcode assert((desc.physpc & 3) == 0); - op = desc.opptr.l[0] = m_mips3->m_pr32(desc.physpc); + const uint32_t op = desc.opptr = m_mips3->m_pr32(desc.physpc); // all instructions are 4 bytes and default to a single cycle each desc.length = 4; desc.cycles = 1; // parse the instruction - opswitch = op >> 26; + const uint32_t opswitch = op >> 26; switch (opswitch) { case 0x00: // SPECIAL @@ -85,14 +100,16 @@ bool mips3_frontend::describe(opcode_desc &desc, const opcode_desc *prev) return describe_idt(op, desc); case 0x02: // J - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); desc.targetpc = (desc.pc & 0xf0000000) | (LIMMVAL << 2); desc.delayslots = 1; return true; case 0x03: // JAL - desc.regout[0] |= REGFLAG_R(31); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_r_modified(31); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); desc.targetpc = (desc.pc & 0xf0000000) | (LIMMVAL << 2); desc.delayslots = 1; return true; @@ -102,11 +119,15 @@ bool mips3_frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x14: // BEQL case 0x15: // BNEL if ((opswitch == 0x04 || opswitch == 0x14) && RSREG == RTREG) - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + { + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } else { - desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.set_r_used(RSREG); + desc.set_r_used(RTREG); + desc.set_is_conditional_branch(); } desc.targetpc = desc.pc + 4 + SIMMVAL * 4; desc.delayslots = 1; @@ -118,11 +139,14 @@ bool mips3_frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x16: // BLEZL case 0x17: // BGTZL if ((opswitch == 0x06 || opswitch == 0x16) && RSREG == 0) - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + { + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } else { - desc.regin[0] |= REGFLAG_R(RSREG); - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.set_r_used(RSREG); + desc.set_is_conditional_branch(); } desc.targetpc = desc.pc + 4 + SIMMVAL * 4; desc.delayslots = 1; @@ -131,9 +155,9 @@ bool mips3_frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x08: // ADDI case 0x18: // DADDI - desc.regin[0] |= REGFLAG_R(RSREG); - desc.regout[0] |= REGFLAG_R(RTREG); - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_r_used(RSREG); + desc.set_r_modified(RTREG); + desc.set_can_cause_exception(); return true; case 0x09: // ADDIU @@ -143,19 +167,19 @@ bool mips3_frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x0d: // ORI case 0x0e: // XORI case 0x19: // DADDIU - desc.regin[0] |= REGFLAG_R(RSREG); - desc.regout[0] |= REGFLAG_R(RTREG); + desc.set_r_used(RSREG); + desc.set_r_modified(RTREG); return true; case 0x0f: // LUI - desc.regout[0] |= REGFLAG_R(RTREG); + desc.set_r_modified(RTREG); return true; case 0x1a: // LDL case 0x1b: // LDR case 0x22: // LWL case 0x26: // LWR - desc.regin[0] |= REGFLAG_R(RTREG); + desc.set_r_used(RTREG); [[fallthrough]]; case 0x20: // LB case 0x21: // LH @@ -166,9 +190,10 @@ bool mips3_frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x30: // LL case 0x34: // LLD case 0x37: // LD - desc.regin[0] |= REGFLAG_R(RSREG); - desc.regout[0] |= REGFLAG_R(RTREG); - desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_r_used(RSREG); + desc.set_r_modified(RTREG); + desc.set_reads_memory(); + desc.set_can_cause_exception(); return true; case 0x28: // SB @@ -179,41 +204,49 @@ bool mips3_frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x2d: // SDR case 0x2e: // SWR case 0x3f: // SD - desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); - desc.flags |= OPFLAG_WRITES_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_r_used(RSREG); + desc.set_r_used(RTREG); + desc.set_writes_memory(); + desc.set_can_cause_exception(); return true; case 0x38: // SC case 0x3c: // SCD - desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); - desc.regout[0] |= REGFLAG_R(RTREG); - desc.flags |= OPFLAG_WRITES_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_r_used(RSREG); + desc.set_r_used(RTREG); + desc.set_r_modified(RTREG); + desc.set_writes_memory(); + desc.set_can_cause_exception(); return true; case 0x31: // LWC1 case 0x35: // LDC1 - desc.regin[0] |= REGFLAG_R(RSREG); - desc.regout[1] |= REGFLAG_CPR1(RTREG); - desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_r_used(RSREG); + desc.set_cpr1_modified(RTREG); + desc.set_reads_memory(); + desc.set_can_cause_exception(); return true; case 0x39: // SWC1 case 0x3d: // SDC1 - desc.regin[0] |= REGFLAG_R(RSREG); - desc.regin[1] |= REGFLAG_CPR1(RTREG); - desc.flags |= OPFLAG_WRITES_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_r_used(RSREG); + desc.set_cpr1_used(RTREG); + desc.set_writes_memory(); + desc.set_can_cause_exception(); return true; case 0x32: // LWC2 case 0x36: // LDC2 - desc.regin[0] |= REGFLAG_R(RSREG); - desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_r_used(RSREG); + desc.set_reads_memory(); + desc.set_can_cause_exception(); return true; case 0x3a: // SWC2 case 0x3e: // SDC2 - desc.regin[0] |= REGFLAG_R(RSREG); - desc.flags |= OPFLAG_WRITES_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_r_used(RSREG); + desc.set_writes_memory(); + desc.set_can_cause_exception(); return true; case 0x33: // PREF @@ -234,7 +267,7 @@ bool mips3_frontend::describe(opcode_desc &desc, const opcode_desc *prev) // single instruction in the 'special' group //------------------------------------------------- -bool mips3_frontend::describe_special(uint32_t op, opcode_desc &desc) +bool mips3_device::frontend::describe_special(uint32_t op, opcode_desc &desc) { switch (op & 63) { @@ -247,15 +280,15 @@ bool mips3_frontend::describe_special(uint32_t op, opcode_desc &desc) case 0x3c: // DSLL32 case 0x3e: // DSRL32 case 0x3f: // DSRA32 - desc.regin[0] |= REGFLAG_R(RTREG); - desc.regout[0] |= REGFLAG_R(RDREG); + desc.set_r_used(RTREG); + desc.set_r_modified(RDREG); return true; case 0x0a: // MOVZ - MIPS IV case 0x0b: // MOVN - MIPS IV if (m_mips3->m_flavor < mips3_device::MIPS3_TYPE_MIPS_IV) return false; - desc.regin[0] |= REGFLAG_R(RDREG); + desc.set_r_used(RDREG); [[fallthrough]]; case 0x04: // SLLV case 0x06: // SRLV @@ -273,17 +306,19 @@ bool mips3_frontend::describe_special(uint32_t op, opcode_desc &desc) case 0x2b: // SLTU case 0x2d: // DADDU case 0x2f: // DSUBU - desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); - desc.regout[0] |= REGFLAG_R(RDREG); + desc.set_r_used(RSREG); + desc.set_r_used(RTREG); + desc.set_r_modified(RDREG); return true; case 0x20: // ADD case 0x22: // SUB case 0x2c: // DADD case 0x2e: // DSUB - desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); - desc.regout[0] |= REGFLAG_R(RDREG); - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_r_used(RSREG); + desc.set_r_used(RTREG); + desc.set_r_modified(RDREG); + desc.set_can_cause_exception(); return true; case 0x30: // TGE @@ -292,84 +327,96 @@ bool mips3_frontend::describe_special(uint32_t op, opcode_desc &desc) case 0x33: // TLTU case 0x34: // TEQ case 0x36: // TNE - desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_r_used(RSREG); + desc.set_r_used(RTREG); + desc.set_can_cause_exception(); return true; case 0x01: // MOVF - MIPS IV if (m_mips3->m_flavor < mips3_device::MIPS3_TYPE_MIPS_IV) return false; - desc.regin[0] |= REGFLAG_R(RSREG); - desc.regin[2] |= REGFLAG_FCC; - desc.regout[0] |= REGFLAG_R(RDREG); + desc.set_r_used(RSREG); + desc.set_fcc_used(); + desc.set_r_modified(RDREG); return true; case 0x08: // JR - desc.regin[0] |= REGFLAG_R(RSREG); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_r_used(RSREG); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); desc.targetpc = BRANCH_TARGET_DYNAMIC; desc.delayslots = 1; return true; case 0x09: // JALR - desc.regin[0] |= REGFLAG_R(RSREG); - desc.regout[0] |= REGFLAG_R(RDREG); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_r_used(RSREG); + desc.set_r_modified(RDREG); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); desc.targetpc = BRANCH_TARGET_DYNAMIC; desc.delayslots = 1; return true; case 0x10: // MFHI - desc.regin[2] |= REGFLAG_HI; - desc.regout[0] |= REGFLAG_R(RDREG); + desc.set_hi_used(); + desc.set_r_modified(RDREG); return true; case 0x11: // MTHI - desc.regin[0] |= REGFLAG_R(RSREG); - desc.regout[2] |= REGFLAG_HI; + desc.set_r_used(RSREG); + desc.set_hi_modified(); return true; case 0x12: // MFLO - desc.regin[2] |= REGFLAG_LO; - desc.regout[0] |= REGFLAG_R(RDREG); + desc.set_lo_used(); + desc.set_r_modified(RDREG); return true; case 0x13: // MTLO - desc.regin[0] |= REGFLAG_R(RSREG); - desc.regout[2] |= REGFLAG_LO; + desc.set_r_used(RSREG); + desc.set_lo_modified(); return true; case 0x18: // MULT case 0x19: // MULTU - desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); - desc.regout[2] |= REGFLAG_LO | REGFLAG_HI; + desc.set_r_used(RSREG); + desc.set_r_used(RTREG); + desc.set_lo_modified(); + desc.set_hi_modified(); desc.cycles = 3; return true; case 0x1a: // DIV case 0x1b: // DIVU - desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); - desc.regout[2] |= REGFLAG_LO | REGFLAG_HI; + desc.set_r_used(RSREG); + desc.set_r_used(RTREG); + desc.set_lo_modified(); + desc.set_hi_modified(); desc.cycles = 35; return true; case 0x1c: // DMULT case 0x1d: // DMULTU - desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); - desc.regout[2] |= REGFLAG_LO | REGFLAG_HI; + desc.set_r_used(RSREG); + desc.set_r_used(RTREG); + desc.set_lo_modified(); + desc.set_hi_modified(); desc.cycles = 7; return true; case 0x1e: // DDIV case 0x1f: // DDIVU - desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); - desc.regout[2] |= REGFLAG_LO | REGFLAG_HI; + desc.set_r_used(RSREG); + desc.set_r_used(RTREG); + desc.set_lo_modified(); + desc.set_hi_modified(); desc.cycles = 67; return true; case 0x0c: // SYSCALL case 0x0d: // BREAK - desc.flags |= OPFLAG_WILL_CAUSE_EXCEPTION | OPFLAG_END_SEQUENCE; + desc.set_will_cause_exception(); + desc.set_end_sequence(); return true; case 0x0f: // SYNC @@ -386,7 +433,7 @@ bool mips3_frontend::describe_special(uint32_t op, opcode_desc &desc) // single instruction in the 'regimm' group //------------------------------------------------- -bool mips3_frontend::describe_regimm(uint32_t op, opcode_desc &desc) +bool mips3_device::frontend::describe_regimm(uint32_t op, opcode_desc &desc) { switch (RTREG) { @@ -395,11 +442,14 @@ bool mips3_frontend::describe_regimm(uint32_t op, opcode_desc &desc) case 0x02: // BLTZL case 0x03: // BGEZL if (RTREG == 0x01 && RSREG == 0) - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + { + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } else { - desc.regin[0] |= REGFLAG_R(RSREG); - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.set_r_used(RSREG); + desc.set_is_conditional_branch(); } desc.targetpc = desc.pc + 4 + SIMMVAL * 4; desc.delayslots = 1; @@ -412,8 +462,8 @@ bool mips3_frontend::describe_regimm(uint32_t op, opcode_desc &desc) case 0x0b: // TLTIU case 0x0c: // TEQI case 0x0e: // TNEI - desc.regin[0] |= REGFLAG_R(RSREG); - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_r_used(RSREG); + desc.set_can_cause_exception(); return true; case 0x10: // BLTZAL @@ -421,13 +471,16 @@ bool mips3_frontend::describe_regimm(uint32_t op, opcode_desc &desc) case 0x12: // BLTZALL case 0x13: // BGEZALL if (RTREG == 0x11 && RSREG == 0) - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + { + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } else { - desc.regin[0] |= REGFLAG_R(RSREG); - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.set_r_used(RSREG); + desc.set_is_conditional_branch(); } - desc.regout[0] |= REGFLAG_R(31); + desc.set_r_modified(31); desc.targetpc = desc.pc + 4 + SIMMVAL * 4; desc.delayslots = 1; desc.skipslots = (RTREG & 0x02) ? 1 : 0; @@ -443,7 +496,7 @@ bool mips3_frontend::describe_regimm(uint32_t op, opcode_desc &desc) // instruction in the IDT-specific group //------------------------------------------------- -bool mips3_frontend::describe_idt(uint32_t op, opcode_desc &desc) +bool mips3_device::frontend::describe_idt(uint32_t op, opcode_desc &desc) { // only on the R4650 if (m_mips3->m_flavor != mips3_device::MIPS3_TYPE_R4650) @@ -453,14 +506,18 @@ bool mips3_frontend::describe_idt(uint32_t op, opcode_desc &desc) { case 0: // MAD case 1: // MADU - desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); - desc.regin[2] |= REGFLAG_LO | REGFLAG_HI; - desc.regout[2] |= REGFLAG_LO | REGFLAG_HI; + desc.set_r_used(RSREG); + desc.set_r_used(RTREG); + desc.set_lo_used(); + desc.set_hi_used(); + desc.set_lo_modified(); + desc.set_hi_modified(); return true; case 2: // MUL - desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); - desc.regout[0] |= REGFLAG_R(RDREG); + desc.set_r_used(RSREG); + desc.set_r_used(RTREG); + desc.set_r_modified(RDREG); desc.cycles = 3; return true; } @@ -474,10 +531,10 @@ bool mips3_frontend::describe_idt(uint32_t op, opcode_desc &desc) // single instruction in the COP0 group //------------------------------------------------- -bool mips3_frontend::describe_cop0(uint32_t op, opcode_desc &desc) +bool mips3_device::frontend::describe_cop0(uint32_t op, opcode_desc &desc) { // any COP0 instruction can potentially cause an exception - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_can_cause_exception(); switch (RSREG) { @@ -487,23 +544,27 @@ bool mips3_frontend::describe_cop0(uint32_t op, opcode_desc &desc) desc.cycles += MIPS3_COUNT_READ_CYCLES; if (RDREG == COP0_Cause) desc.cycles += MIPS3_CAUSE_READ_CYCLES; - desc.regout[0] |= REGFLAG_R(RTREG); + desc.set_r_modified(RTREG); return true; case 0x02: // CFCz - desc.regout[0] |= REGFLAG_R(RTREG); + desc.set_r_modified(RTREG); return true; case 0x04: // MTCz case 0x05: // DMTCz case 0x06: // CTCz - desc.regin[0] |= REGFLAG_R(RTREG); + desc.set_r_used(RTREG); if (RSREG == 0x04 || RSREG == 0x05) { if (RDREG == COP0_Cause) - desc.flags |= OPFLAG_CAN_TRIGGER_SW_INT; + desc.set_can_trigger_sw_int(); if (RDREG == COP0_Status) - desc.flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_CAN_CHANGE_MODES | OPFLAG_END_SEQUENCE; + { + desc.set_can_expose_external_int(); + desc.set_can_change_modes(); + desc.set_end_sequence(); + } } return true; @@ -512,7 +573,7 @@ bool mips3_frontend::describe_cop0(uint32_t op, opcode_desc &desc) { case 0x00: // BCzF case 0x01: // BCzT - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.set_is_conditional_branch(); desc.targetpc = desc.pc + 4 + SIMMVAL * 4; desc.delayslots = 1; return true; @@ -530,11 +591,13 @@ bool mips3_frontend::describe_cop0(uint32_t op, opcode_desc &desc) case 0x02: // TLBWI case 0x06: // TLBWR - desc.flags |= OPFLAG_MODIFIES_TRANSLATION; + desc.set_modifies_translation(); return true; case 0x18: // ERET - desc.flags |= OPFLAG_CAN_CHANGE_MODES | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + desc.set_can_change_modes(); return true; } return false; @@ -549,31 +612,31 @@ bool mips3_frontend::describe_cop0(uint32_t op, opcode_desc &desc) // single instruction in the COP1 group //------------------------------------------------- -bool mips3_frontend::describe_cop1(uint32_t op, opcode_desc &desc) +bool mips3_device::frontend::describe_cop1(uint32_t op, opcode_desc &desc) { // any COP1 instruction can potentially cause an exception -// desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + //desc.set_can_cause_exception(); switch (RSREG) { case 0x00: // MFCz case 0x01: // DMFCz - desc.regin[1] |= REGFLAG_CPR1(RDREG); - desc.regout[0] |= REGFLAG_R(RTREG); + desc.set_cpr1_used(RDREG); + desc.set_r_modified(RTREG); return true; case 0x02: // CFCz - desc.regout[0] |= REGFLAG_R(RTREG); + desc.set_r_modified(RTREG); return true; case 0x04: // MTCz case 0x05: // DMTCz - desc.regin[0] |= REGFLAG_R(RTREG); - desc.regout[1] |= REGFLAG_CPR1(RDREG); + desc.set_r_used(RTREG); + desc.set_cpr1_modified(RDREG); return true; case 0x06: // CTCz - desc.regin[0] |= REGFLAG_R(RTREG); + desc.set_r_used(RTREG); return true; case 0x08: // BC @@ -583,8 +646,8 @@ bool mips3_frontend::describe_cop1(uint32_t op, opcode_desc &desc) case 0x01: // BCzT case 0x02: // BCzFL case 0x03: // BCzTL - desc.regin[2] |= REGFLAG_FCC; - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.set_fcc_used(); + desc.set_is_conditional_branch(); desc.targetpc = desc.pc + 4 + SIMMVAL * 4; desc.delayslots = 1; desc.skipslots = (RTREG & 0x02) ? 1 : 0; @@ -605,8 +668,9 @@ bool mips3_frontend::describe_cop1(uint32_t op, opcode_desc &desc) case 0x01: // SUB case 0x02: // MUL case 0x03: // DIV - desc.regin[1] |= REGFLAG_CPR1(FSREG) | REGFLAG_CPR1(FTREG); - desc.regout[1] |= REGFLAG_CPR1(FDREG); + desc.set_cpr1_used(FSREG); + desc.set_cpr1_used(FTREG); + desc.set_cpr1_modified(FDREG); return true; case 0x15: // RECIP - MIPS IV @@ -630,21 +694,21 @@ bool mips3_frontend::describe_cop1(uint32_t op, opcode_desc &desc) case 0x21: // CVT.D case 0x24: // CVT.W case 0x25: // CVT.L - desc.regin[1] |= REGFLAG_CPR1(FSREG); - desc.regout[1] |= REGFLAG_CPR1(FDREG); + desc.set_cpr1_used(FSREG); + desc.set_cpr1_modified(FDREG); return true; case 0x11: // MOVT/F - MIPS IV if (m_mips3->m_flavor < mips3_device::MIPS3_TYPE_MIPS_IV) return false; - desc.regin[1] |= REGFLAG_CPR1(FSREG); - desc.regin[2] |= REGFLAG_FCC; - desc.regout[1] |= REGFLAG_CPR1(FDREG); + desc.set_cpr1_used(FSREG); + desc.set_fcc_used(); + desc.set_cpr1_modified(FDREG); return true; case 0x30: case 0x38: // C.F case 0x31: case 0x39: // C.UN - desc.regout[2] |= REGFLAG_FCC; + desc.set_fcc_modified(); return true; case 0x32: case 0x3a: // C.EQ @@ -653,8 +717,9 @@ bool mips3_frontend::describe_cop1(uint32_t op, opcode_desc &desc) case 0x35: case 0x3d: // C.ULT case 0x36: case 0x3e: // C.OLE case 0x37: case 0x3f: // C.ULE - desc.regin[1] |= REGFLAG_CPR1(FSREG) | REGFLAG_CPR1(FTREG); - desc.regout[2] |= REGFLAG_FCC; + desc.set_cpr1_used(FSREG); + desc.set_cpr1_used(FTREG); + desc.set_fcc_modified(); return true; } return false; @@ -669,7 +734,7 @@ bool mips3_frontend::describe_cop1(uint32_t op, opcode_desc &desc) // single instruction in the COP1X group //------------------------------------------------- -bool mips3_frontend::describe_cop1x(uint32_t op, opcode_desc &desc) +bool mips3_device::frontend::describe_cop1x(uint32_t op, opcode_desc &desc) { // any COP1 instruction can potentially cause an exception // desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; @@ -678,16 +743,18 @@ bool mips3_frontend::describe_cop1x(uint32_t op, opcode_desc &desc) { case 0x00: // LWXC1 case 0x01: // LDXC1 - desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); - desc.regout[1] |= REGFLAG_CPR1(FDREG); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_r_used(RSREG); + desc.set_r_used(RTREG); + desc.set_cpr1_modified(FDREG); + desc.set_reads_memory(); return true; case 0x08: // SWXC1 case 0x09: // SDXC1 - desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); - desc.regin[1] |= REGFLAG_CPR1(FDREG); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_r_used(RSREG); + desc.set_r_used(RTREG); + desc.set_cpr1_used(FDREG); + desc.set_writes_memory(); return true; case 0x0f: // PREFX @@ -698,8 +765,10 @@ bool mips3_frontend::describe_cop1x(uint32_t op, opcode_desc &desc) case 0x28: case 0x29: // MSUB case 0x30: case 0x31: // NMADD case 0x38: case 0x39: // NMSUB - desc.regin[1] |= REGFLAG_CPR1(FSREG) | REGFLAG_CPR1(FTREG) | REGFLAG_CPR1(FRREG); - desc.regout[1] |= REGFLAG_CPR1(FDREG); + desc.set_cpr1_used(FSREG); + desc.set_cpr1_used(FTREG); + desc.set_cpr1_used(FRREG); + desc.set_cpr1_modified(FDREG); return true; } @@ -712,23 +781,23 @@ bool mips3_frontend::describe_cop1x(uint32_t op, opcode_desc &desc) // single instruction in the COP2 group //------------------------------------------------- -bool mips3_frontend::describe_cop2(uint32_t op, opcode_desc &desc) +bool mips3_device::frontend::describe_cop2(uint32_t op, opcode_desc &desc) { // any COP2 instruction can potentially cause an exception - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_can_cause_exception(); switch (RSREG) { case 0x00: // MFCz case 0x01: // DMFCz case 0x02: // CFCz - desc.regout[0] |= REGFLAG_R(RTREG); + desc.set_r_modified(RTREG); return true; case 0x04: // MTCz case 0x05: // DMTCz case 0x06: // CTCz - desc.regin[0] |= REGFLAG_R(RTREG); + desc.set_r_used(RTREG); return true; case 0x08: // BC @@ -736,7 +805,7 @@ bool mips3_frontend::describe_cop2(uint32_t op, opcode_desc &desc) { case 0x00: // BCzF case 0x01: // BCzT - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.set_is_conditional_branch(); desc.targetpc = desc.pc + 4 + SIMMVAL * 4; desc.delayslots = 1; return true; diff --git a/src/devices/cpu/mips/mips3fe.h b/src/devices/cpu/mips/mips3fe.h index 0b8e9d79fec..322c007417a 100644 --- a/src/devices/cpu/mips/mips3fe.h +++ b/src/devices/cpu/mips/mips3fe.h @@ -12,21 +12,121 @@ #pragma once +#include "mips3.h" + +#include "cpu/drcfe.h" + +#include <cassert> +#include <bitset> + //************************************************************************** -// MACROS +// STRUCTURES //************************************************************************** -// register flags 0 -#define REGFLAG_R(n) (((n) == 0) ? 0 : (1 << (n))) +class mips3_device::opcode_desc : public opcode_desc_base<opcode_desc, 68> +{ +public: + enum + { + REG_FLAG_R0 = 0, + REG_FLAG_CPR10 = REG_FLAG_R0 + 32, + REG_FLAG_LO = REG_FLAG_CPR10 + 32, + REG_FLAG_HI, + REG_FLAG_FCC, + + REG_FLAG_COUNT + }; + + offs_t physpc; // physical PC of this opcode + + uint32_t opptr; // copy of opcode + + uint32_t cycles; // number of cycles needed to execute + + void set_r_used(unsigned n) { if (n) regin.set(REG_FLAG_R0 + n); } + void set_r_modified(unsigned n) { if (n) regout.set(REG_FLAG_R0 + n); } + void set_cpr1_used(unsigned n) { regin.set(REG_FLAG_CPR10 + n); } + void set_cpr1_modified(unsigned n) { regout.set(REG_FLAG_CPR10 + n); } + void set_lo_used() { regin.set(REG_FLAG_LO); } + void set_lo_modified() { regout.set(REG_FLAG_LO); } + void set_hi_used() { regin.set(REG_FLAG_HI); } + void set_hi_modified() { regout.set(REG_FLAG_HI); } + void set_fcc_used() { regin.set(REG_FLAG_FCC); } + void set_fcc_modified() { regout.set(REG_FLAG_FCC); } + + void set_can_trigger_sw_int() { m_extra_flags.set(CAN_TRIGGER_SW_INT); } + void set_can_expose_external_int() { m_extra_flags.set(CAN_EXPOSE_EXTERNAL_INT); } + void set_modifies_translation() { m_extra_flags.set(MODIFIES_TRANSLATION); } + void set_compiler_unmapped() { m_extra_flags.set(COMPILER_UNMAPPED); } + void set_can_change_modes() { m_extra_flags.set(CAN_CHANGE_MODES); } + void set_reads_memory() { m_extra_flags.set(READS_MEMORY); } + void set_writes_memory() { m_extra_flags.set(WRITES_MEMORY); } + + bool can_trigger_sw_int() { return m_extra_flags[CAN_TRIGGER_SW_INT]; } + bool can_expose_external_int() { return m_extra_flags[CAN_EXPOSE_EXTERNAL_INT]; } + bool modifies_translation() const { return m_extra_flags[MODIFIES_TRANSLATION]; } + bool compiler_unmapped() const { return m_extra_flags[COMPILER_UNMAPPED]; } + bool can_change_modes() const { return m_extra_flags[CAN_CHANGE_MODES]; } + bool reads_memory() const { return m_extra_flags[READS_MEMORY]; } + bool writes_memory() const { return m_extra_flags[WRITES_MEMORY]; } + + // compute the exception PC + uint32_t epc() const { return in_delay_slot() ? (pc - 3) : pc; } + + void reset(offs_t curpc, bool in_delay_slot) + { + static_assert(REG_FLAG_COUNT <= 68); + + opcode_desc_base::reset(curpc, in_delay_slot); + + physpc = curpc; + opptr = 0; + cycles = 0; + m_extra_flags.reset(); + } + +private: + enum + { + CAN_TRIGGER_SW_INT = 0, + CAN_EXPOSE_EXTERNAL_INT, + MODIFIES_TRANSLATION, + COMPILER_UNMAPPED, + CAN_CHANGE_MODES, + READS_MEMORY, + WRITES_MEMORY, + + EXTRA_FLAG_COUNT + }; + + std::bitset<EXTRA_FLAG_COUNT> m_extra_flags; +}; + + +class mips3_device::frontend : public drc_frontend_base<opcode_desc> +{ +public: + // construction/destruction + frontend(mips3_device *mips3, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); + ~frontend(); + + opcode_desc const *describe_code(offs_t startpc); -// register flags 1 -#define REGFLAG_CPR1(n) (1 << (n)) +private: + bool describe(opcode_desc &desc, opcode_desc const *prev); -// register flags 2 -#define REGFLAG_LO (1 << 0) -#define REGFLAG_HI (1 << 1) -#define REGFLAG_FCC (1 << 2) + // internal helpers + bool describe_special(uint32_t op, opcode_desc &desc); + bool describe_regimm(uint32_t op, opcode_desc &desc); + bool describe_idt(uint32_t op, opcode_desc &desc); + bool describe_cop0(uint32_t op, opcode_desc &desc); + bool describe_cop1(uint32_t op, opcode_desc &desc); + bool describe_cop1x(uint32_t op, opcode_desc &desc); + bool describe_cop2(uint32_t op, opcode_desc &desc); + // internal state + mips3_device *m_mips3; +}; #endif // MAME_CPU_MIPS_MIPS3FE_H diff --git a/src/devices/cpu/powerpc/ppc.h b/src/devices/cpu/powerpc/ppc.h index 08aedd46741..d00bcac10a1 100644 --- a/src/devices/cpu/powerpc/ppc.h +++ b/src/devices/cpu/powerpc/ppc.h @@ -15,13 +15,13 @@ #include "ppc_dasm.h" -#include "cpu/drcfe.h" #include "cpu/drcuml.h" #include "cpu/drcumlsh.h" #include "divtlb.h" #include <algorithm> +#include <bitset> /*************************************************************************** @@ -180,6 +180,7 @@ class ppc_device : public cpu_device, public device_vtlb_interface { protected: class frontend; + class opcode_desc; /* PowerPC flavors */ enum powerpc_flavor @@ -699,8 +700,8 @@ protected: bool generate_instruction_3b(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc); bool generate_instruction_3f(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc); void log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32_t op); - 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 &desc); + void log_register_list(const char *string, const std::bitset<128> ®list, const std::bitset<128> *regnostarlist); void log_opcode_desc(const opcode_desc *desclist, int indent); private: diff --git a/src/devices/cpu/powerpc/ppcdrc.cpp b/src/devices/cpu/powerpc/ppcdrc.cpp index 38eaa3a6908..ecb4fe09024 100644 --- a/src/devices/cpu/powerpc/ppcdrc.cpp +++ b/src/devices/cpu/powerpc/ppcdrc.cpp @@ -16,10 +16,10 @@ #include "emu.h" #include "ppc.h" + #include "ppccom.h" #include "ppcfe.h" -#include "cpu/drcfe.h" #include "cpu/drcuml.h" #include "cpu/drcumlsh.h" @@ -348,9 +348,11 @@ void ppc_device::code_compile_block(uint8_t mode, offs_t pc) block.append_comment("-------------------------"); // comment /* determine the last instruction in this sequence */ - for (seqlast = seqhead; seqlast != nullptr; seqlast = seqlast->next()) - if (seqlast->flags & OPFLAG_END_SEQUENCE) + for (seqlast = seqhead; seqlast; seqlast = seqlast->next()) + { + if (seqlast->end_sequence()) break; + } assert(seqlast != nullptr); /* if we don't have a hash for this mode/pc, or if we are overriding all, add one */ @@ -379,7 +381,7 @@ void ppc_device::code_compile_block(uint8_t mode, offs_t pc) generate_checksum_block(block, &compiler, seqhead, seqlast); // <checksum> /* 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 /* iterate over instructions in the sequence and compile them */ @@ -387,7 +389,7 @@ void ppc_device::code_compile_block(uint8_t mode, offs_t pc) generate_sequence_instruction(block, &compiler, curdesc); // <instruction> /* if we need to return to the start, do it */ - if (seqlast->flags & OPFLAG_RETURN_TO_START) + if (seqlast->return_to_start()) nextpc = pc; /* otherwise we just go to the next instruction */ @@ -398,7 +400,7 @@ void ppc_device::code_compile_block(uint8_t mode, offs_t pc) generate_update_cycles(block, &compiler, nextpc, true); // <subtract cycles> /* if the last instruction can change modes, use a variable mode; otherwise, assume the same mode */ - if (seqlast->flags & OPFLAG_CAN_CHANGE_MODES) + if (seqlast->can_change_modes()) UML_HASHJMP(block, mem(&m_core->mode), nextpc, *m_nocode);// hashjmp <mode>,nextpc,nocode else if (seqlast->next() == nullptr || seqlast->next()->pc != nextpc) UML_HASHJMP(block, m_core->mode, nextpc, *m_nocode);// hashjmp <mode>,nextpc,nocode @@ -1573,11 +1575,11 @@ void ppc_device::generate_checksum_block(drcuml_block &block, compiler_state *co /* loose verify or single instruction: just compare and fail */ if (!(m_drcoptions & PPCDRC_STRICT_VERIFY) || seqhead->next() == nullptr) { - if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP)) + if (!seqhead->virtual_noop()) { const void *base = m_prptr(seqhead->physpc); UML_LOAD(block, I0, base, 0, SIZE_DWORD, SCALE_x4); // load i0,base,dword - UML_CMP(block, I0, seqhead->opptr.l[0]); // cmp i0,*opptr + UML_CMP(block, I0, seqhead->opptr); // cmp i0,*opptr UML_EXHc(block, COND_NE, *m_nocode, seqhead->pc); // exne nocode,seqhead->pc } } @@ -1587,28 +1589,32 @@ void ppc_device::generate_checksum_block(drcuml_block &block, compiler_state *co { #if 0 for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next()) - if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP)) + { + if (!curdesc->virtual_noop()) { const void *base = m_prptr(seqhead->physpc); - UML_LOAD(block, I0, base, 0, SIZE_DWORD, SCALE_x4); // load i0,base,dword - UML_CMP(block, I0, curdesc->opptr.l[0]); // cmp i0,*opptr - UML_EXHc(block, COND_NE, *m_nocode, seqhead->pc); // exne nocode,seqhead->pc + UML_LOAD(block, I0, base, 0, SIZE_DWORD, SCALE_x4); + UML_CMP(block, I0, curdesc->opptr); + UML_EXHc(block, COND_NE, *m_nocode, seqhead->pc); } + } #else uint32_t sum = 0; const void *base = m_prptr(seqhead->physpc); - UML_LOAD(block, I0, base, 0, SIZE_DWORD, SCALE_x4); // load i0,base,dword - sum += seqhead->opptr.l[0]; + UML_LOAD(block, I0, base, 0, SIZE_DWORD, SCALE_x4); + 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_DWORD, SCALE_x4); // load i1,base,dword - UML_ADD(block, I0, I0, I1); // add i0,i0,i1 - sum += curdesc->opptr.l[0]; + UML_LOAD(block, I1, base, 0, SIZE_DWORD, SCALE_x4); + UML_ADD(block, I0, I0, I1); + sum += curdesc->opptr; } - UML_CMP(block, I0, sum); // cmp i0,sum - UML_EXHc(block, COND_NE, *m_nocode, seqhead->pc); // exne nocode,seqhead->pc + } + UML_CMP(block, I0, sum); + UML_EXHc(block, COND_NE, *m_nocode, seqhead->pc); #endif } } @@ -1624,8 +1630,8 @@ void ppc_device::generate_sequence_instruction(drcuml_block &block, compiler_sta int hotnum; /* add an entry for the log */ - if (m_drcuml->logging() && !(desc->flags & OPFLAG_VIRTUAL_NOOP)) - log_add_disasm_comment(block, desc->pc, desc->opptr.l[0]); + if (m_drcuml->logging() && !desc->virtual_noop()) + log_add_disasm_comment(block, desc->pc, desc->opptr); /* set the PC map variable */ UML_MAPVAR(block, MAPVAR_PC, desc->pc); // mapvar PC,desc->pc @@ -1635,7 +1641,7 @@ void ppc_device::generate_sequence_instruction(drcuml_block &block, compiler_sta /* is this a hotspot? */ for (hotnum = 0; hotnum < PPC_MAX_HOTSPOTS; hotnum++) - if (m_hotspot[hotnum].pc != 0 && desc->pc == m_hotspot[hotnum].pc && desc->opptr.l[0] == m_hotspot[hotnum].opcode) + if (m_hotspot[hotnum].pc != 0 && desc->pc == m_hotspot[hotnum].pc && desc->opptr == m_hotspot[hotnum].opcode) { compiler->cycles += m_hotspot[hotnum].cycles; break; @@ -1661,7 +1667,7 @@ void ppc_device::generate_sequence_instruction(drcuml_block &block, compiler_sta } /* if we hit an unmapped address, fatal error */ - if (desc->flags & OPFLAG_COMPILER_UNMAPPED) + if (desc->compiler_unmapped()) { UML_MOV(block, mem(&m_core->pc), desc->pc); // mov [pc],desc->pc save_fast_iregs(block); // <save fastregs> @@ -1670,7 +1676,7 @@ void ppc_device::generate_sequence_instruction(drcuml_block &block, compiler_sta } /* if we hit a compiler page fault, it's just like a TLB mismatch */ - if (desc->flags & OPFLAG_COMPILER_PAGE_FAULT) + if (desc->compiler_page_fault()) { if (PRINTF_MMU) { @@ -1687,7 +1693,7 @@ void ppc_device::generate_sequence_instruction(drcuml_block &block, compiler_sta // validate our TLB entry at this PC; if we fail, we need to handle it // TODO: this code is highly sus based on the PPC architecture manual, but I'll only disable for 601 for now - if ((desc->flags & OPFLAG_VALIDATE_TLB) && (m_core->mode & MODE_DATA_TRANSLATION) && !(m_cap & PPCCAP_601BAT)) + if (desc->validate_tlb() && (m_core->mode & MODE_DATA_TRANSLATION) && !(m_cap & PPCCAP_601BAT)) { const vtlb_entry *tlbtable = vtlb_table(); @@ -1725,23 +1731,25 @@ void ppc_device::generate_sequence_instruction(drcuml_block &block, compiler_sta } } - /* if this is an invalid opcode, generate the exception now */ - if (desc->flags & OPFLAG_INVALID_OPCODE) - UML_EXH(block, *m_exception[EXCEPTION_PROGRAM], 0x80000); // exh exception_program,0x80000 - - /* if this is a privileged opcode in user mode, generate the exception */ - else if ((desc->flags & OPFLAG_PRIVILEGED) && (m_core->mode & MODE_USER)) + if (desc->invalid_opcode()) + { + // if this is an invalid opcode, generate the exception now + UML_EXH(block, *m_exception[EXCEPTION_PROGRAM], 0x80000); + } + else if (desc->privileged() && (m_core->mode & MODE_USER)) + { + // if this is a privileged opcode in user mode, generate the exception UML_EXH(block, *m_exception[EXCEPTION_PROGRAM], 0x40000); // exh exception_program,0x40000 - - /* 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)) { - UML_MOV(block, mem(&m_core->pc), desc->pc); // mov [pc],desc->pc - UML_MOV(block, mem(&m_core->arg0), desc->opptr.l[0]); // mov [arg0],*desc->opptr.l - UML_CALLC(block, cfunc_unimplemented, this); // callc cfunc_unimplemented,ppc + UML_MOV(block, mem(&m_core->pc), desc->pc); + UML_MOV(block, mem(&m_core->arg0), desc->opptr); + UML_CALLC(block, cfunc_unimplemented, this); } } } @@ -1758,9 +1766,9 @@ void ppc_device::generate_compute_flags(drcuml_block &block, const opcode_desc * /* modify inputs based on required flags */ if (!DISABLE_FLAG_OPTIMIZATIONS) { - if (!(desc->regreq[3] & frontend::REGFLAG_XER_CA)) + if (!frontend::REGFLAG_XER_CA(desc->regreq)) xermask &= ~XER_CA; - if (!(desc->regreq[2] & frontend::REGFLAG_CR(0))) + if (!frontend::REGFLAG_CR(desc->regreq, 0)) updatecr = 0; } xerflags = ((xermask & XER_OV) ? uml::FLAG_V : 0) | ((xermask & XER_CA) ? uml::FLAG_C : 0); @@ -1845,11 +1853,11 @@ void ppc_device::generate_fp_flags(drcuml_block &block, const opcode_desc *desc, /* for now, only handle the FPRF field */ if (updatefprf) { - int regnum = G_RD(desc->opptr.l[0]); + int regnum = G_RD(desc->opptr); if (m_fdregmap[regnum].is_float_register()) UML_FDMOV(block, mem(&m_core->f[regnum]), freg(m_fdregmap[regnum].freg() - REG_F0)); - UML_MOV(block, mem(&m_core->param0), G_RD(desc->opptr.l[0])); + UML_MOV(block, mem(&m_core->param0), G_RD(desc->opptr)); UML_CALLC(block, (c_function)cfunc_ppccom_update_fprf, this); } } @@ -1879,7 +1887,7 @@ void ppc_device::generate_branch(drcuml_block &block, compiler_state *compiler, if (desc->targetpc != BRANCH_TARGET_DYNAMIC) { generate_update_cycles(block, &compiler_temp, desc->targetpc, true); // <subtract cycles> - if (desc->flags & OPFLAG_INTRABLOCK_BRANCH) + if (desc->intrablock_branch()) UML_JMP(block, desc->targetpc | 0x80000000); // jmp desc->targetpc | 0x80000000 else UML_HASHJMP(block, m_core->mode, desc->targetpc, *m_nocode); @@ -1933,7 +1941,7 @@ void ppc_device::generate_branch_bo(drcuml_block &block, compiler_state *compile bool ppc_device::generate_opcode(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc) { - uint32_t op = desc->opptr.l[0]; + uint32_t op = desc->opptr; uint32_t opswitch = op >> 26; switch (opswitch) @@ -2331,7 +2339,7 @@ bool ppc_device::generate_opcode(drcuml_block &block, compiler_state *compiler, bool ppc_device::generate_instruction_13(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc) { - uint32_t op = desc->opptr.l[0]; + uint32_t op = desc->opptr; uint32_t opswitch = (op >> 1) & 0x3ff; switch (opswitch) @@ -2468,7 +2476,7 @@ bool ppc_device::generate_instruction_13(drcuml_block &block, compiler_state *co bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc) { - uint32_t op = desc->opptr.l[0]; + uint32_t op = desc->opptr; uint32_t opswitch = (op >> 1) & 0x3ff; int item; @@ -2963,7 +2971,7 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co UML_CMP(block, I2, 0x00000020); // cmp rb,0x20 UML_JMPc(block, COND_S, compiler->labelnum); // bs 1: - if (DISABLE_FLAG_OPTIMIZATIONS || (desc->regreq[3] & frontend::REGFLAG_XER_CA)) + if (DISABLE_FLAG_OPTIMIZATIONS || frontend::REGFLAG_XER_CA(desc->regreq)) { // for shift amt > 32, carry flag is the sign bit of Rs and the sign bit fills all bit positions UML_TEST(block, R32(G_RS(op)), 0x80000000); @@ -2974,7 +2982,7 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co UML_JMP(block, compiler->labelnum+1); // bra 2: UML_LABEL(block, compiler->labelnum++); // 1: - if (DISABLE_FLAG_OPTIMIZATIONS || (desc->regreq[3] & frontend::REGFLAG_XER_CA)) + if (DISABLE_FLAG_OPTIMIZATIONS || frontend::REGFLAG_XER_CA(desc->regreq)) { UML_SHL(block, I1, 0xffffffff, I2); // shl i1,0xffffffff,i2 UML_XOR(block, I1, I1, ~0); // xor i1,i1,~0 @@ -2995,7 +3003,7 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co return true; case 0x338: /* SRAWIx */ - if (DISABLE_FLAG_OPTIMIZATIONS || (desc->regreq[3] & frontend::REGFLAG_XER_CA)) + if (DISABLE_FLAG_OPTIMIZATIONS || frontend::REGFLAG_XER_CA(desc->regreq)) { UML_AND(block, I0, R32(G_RS(op)), ~(0xffffffff << (G_SH(op) & 31)));// and i0,rs,~(0xffffffff << (sh & 31)) UML_SAR(block, I1, R32(G_RS(op)), 31); // sar i1,rs,31 @@ -3618,7 +3626,7 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co bool ppc_device::generate_instruction_3b(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc) { - uint32_t op = desc->opptr.l[0]; + uint32_t op = desc->opptr; uint32_t opswitch = (op >> 1) & 0x1f; switch (opswitch) @@ -3726,7 +3734,7 @@ bool ppc_device::generate_instruction_3b(drcuml_block &block, compiler_state *co bool ppc_device::generate_instruction_3f(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc) { - uint32_t op = desc->opptr.l[0]; + uint32_t op = desc->opptr; uint32_t opswitch = (op >> 1) & 0x3ff; if (opswitch & 0x10) @@ -3916,52 +3924,49 @@ void ppc_device::log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32 flags -------------------------------------------------*/ -const char *ppc_device::log_desc_flags_to_string(uint32_t flags) +const char *ppc_device::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; } @@ -3970,7 +3975,7 @@ const char *ppc_device::log_desc_flags_to_string(uint32_t flags) log_register_list - log a list of GPR registers -------------------------------------------------*/ -void ppc_device::log_register_list(const char *string, const uint32_t *reglist, const uint32_t *regnostarlist) +void ppc_device::log_register_list(const char *string, const std::bitset<128> ®list, const std::bitset<128> *regnostarlist) { static const char *const crtext[4] = { "lt", "gt", "eq", "so" }; int count = 0; @@ -3978,92 +3983,102 @@ void ppc_device::log_register_list(const char *string, const uint32_t *reglist, int crnum; /* skip if nothing */ - if (reglist[0] == 0 && reglist[1] == 0 && reglist[2] == 0 && reglist[3] == 0) + if (reglist.none()) return; m_drcuml->log_printf("[%s:", string); for (regnum = 0; regnum < 32; regnum++) - if (reglist[0] & frontend::REGFLAG_R(regnum)) + { + if (frontend::REGFLAG_R(reglist, regnum)) { m_drcuml->log_printf("%sr%d", (count++ == 0) ? "" : ",", regnum); - if (regnostarlist != nullptr && !(regnostarlist[0] & frontend::REGFLAG_R(regnum))) + if (regnostarlist && !frontend::REGFLAG_R(*regnostarlist, regnum)) m_drcuml->log_printf("*"); } + } for (regnum = 0; regnum < 32; regnum++) - if (reglist[1] & frontend::REGFLAG_FR(regnum)) + { + if (frontend::REGFLAG_FR(reglist, regnum)) { m_drcuml->log_printf("%sfr%d", (count++ == 0) ? "" : ",", regnum); - if (regnostarlist != nullptr && !(regnostarlist[1] & frontend::REGFLAG_FR(regnum))) + if (regnostarlist && !frontend::REGFLAG_FR(*regnostarlist, regnum)) m_drcuml->log_printf("*"); } + } for (regnum = 0; regnum < 8; regnum++) - if (reglist[2] & frontend::REGFLAG_CR(regnum)) + { + if (frontend::REGFLAG_CR(reglist, regnum)) { - if ((reglist[2] & frontend::REGFLAG_CR(regnum)) == frontend::REGFLAG_CR(regnum) && (regnostarlist == nullptr || (regnostarlist[2] & frontend::REGFLAG_CR(regnum)) == frontend::REGFLAG_CR(regnum))) + if ((frontend::REGFLAG_CR(reglist, regnum) == 0x0f) && (!regnostarlist || (frontend::REGFLAG_CR(*regnostarlist, regnum) == 0x0f))) { m_drcuml->log_printf("%scr%d", (count++ == 0) ? "" : ",", regnum); - if (regnostarlist != nullptr && !(regnostarlist[2] & frontend::REGFLAG_CR(regnum))) + if (regnostarlist && !frontend::REGFLAG_CR(*regnostarlist, regnum)) m_drcuml->log_printf("*"); } else { for (crnum = 0; crnum < 4; crnum++) - if (reglist[2] & frontend::REGFLAG_CR_BIT(regnum * 4 + crnum)) + { + if (frontend::REGFLAG_CR_BIT(reglist, regnum * 4 + crnum)) { m_drcuml->log_printf("%scr%d[%s]", (count++ == 0) ? "" : ",", regnum, crtext[crnum]); - if (regnostarlist != nullptr && !(regnostarlist[2] & frontend::REGFLAG_CR_BIT(regnum * 4 + crnum))) + if (regnostarlist && !frontend::REGFLAG_CR_BIT(*regnostarlist, regnum * 4 + crnum)) m_drcuml->log_printf("*"); } + } } } + } - if (reglist[3] & frontend::REGFLAG_XER_CA) + if (frontend::REGFLAG_XER_CA(reglist)) { m_drcuml->log_printf("%sxer_ca", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[3] & frontend::REGFLAG_XER_CA)) + if (regnostarlist && !frontend::REGFLAG_XER_CA(*regnostarlist)) m_drcuml->log_printf("*"); } - if (reglist[3] & frontend::REGFLAG_XER_OV) + if (frontend::REGFLAG_XER_OV(reglist)) { m_drcuml->log_printf("%sxer_ov", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[3] & frontend::REGFLAG_XER_OV)) + if (regnostarlist && !frontend::REGFLAG_XER_OV(*regnostarlist)) m_drcuml->log_printf("*"); } - if (reglist[3] & frontend::REGFLAG_XER_SO) + if (frontend::REGFLAG_XER_SO(reglist)) { m_drcuml->log_printf("%sxer_so", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[3] & frontend::REGFLAG_XER_SO)) + if (regnostarlist && !frontend::REGFLAG_XER_SO(*regnostarlist)) m_drcuml->log_printf("*"); } - if (reglist[3] & frontend::REGFLAG_XER_COUNT) + if (frontend::REGFLAG_XER_COUNT(reglist)) { m_drcuml->log_printf("%sxer_count", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[3] & frontend::REGFLAG_XER_COUNT)) + if (regnostarlist && !frontend::REGFLAG_XER_COUNT(*regnostarlist)) m_drcuml->log_printf("*"); } - if (reglist[3] & frontend::REGFLAG_CTR) + if (frontend::REGFLAG_CTR(reglist)) { m_drcuml->log_printf("%sctr", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[3] & frontend::REGFLAG_CTR)) + if (regnostarlist && !frontend::REGFLAG_CTR(*regnostarlist)) m_drcuml->log_printf("*"); } - if (reglist[3] & frontend::REGFLAG_LR) + if (frontend::REGFLAG_LR(reglist)) { m_drcuml->log_printf("%slr", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[3] & frontend::REGFLAG_LR)) + if (regnostarlist && !frontend::REGFLAG_LR(*regnostarlist)) m_drcuml->log_printf("*"); } for (regnum = 0; regnum < 8; regnum++) - if (reglist[3] & frontend::REGFLAG_FPSCR(regnum)) + { + if (frontend::REGFLAG_FPSCR(reglist, regnum)) { m_drcuml->log_printf("%sfpscr%d", (count++ == 0) ? "" : ",", regnum); - if (regnostarlist != nullptr && !(regnostarlist[3] & frontend::REGFLAG_FPSCR(regnum))) + if (regnostarlist && !frontend::REGFLAG_FPSCR(*regnostarlist, regnum)) m_drcuml->log_printf("*"); } + } m_drcuml->log_printf("] "); } @@ -4090,20 +4105,20 @@ void ppc_device::log_opcode_desc(const opcode_desc *desclist, int indent) /* disassemble 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()) buffer << "<virtual nop>"; else - m_dasm.dasm_one(buffer, desclist->pc, desclist->opptr.l[0]); + m_dasm.dasm_one(buffer, desclist->pc, desclist->opptr); } else buffer << "???"; buffer.put('\0'); - m_drcuml->log_printf("%08X [%08X] t:%08X f:%s: %-30s", desclist->pc, desclist->physpc, desclist->targetpc, log_desc_flags_to_string(desclist->flags), &buffer.vec()[0]); + m_drcuml->log_printf("%08X [%08X] t:%08X f:%s: %-30s", desclist->pc, desclist->physpc, desclist->targetpc, log_desc_flags_to_string(*desclist), &buffer.vec()[0]); /* 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 */ @@ -4111,7 +4126,7 @@ void ppc_device::log_opcode_desc(const opcode_desc *desclist, int indent) 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"); } } diff --git a/src/devices/cpu/powerpc/ppcfe.cpp b/src/devices/cpu/powerpc/ppcfe.cpp index 1e8fb105ee1..1819d906ba7 100644 --- a/src/devices/cpu/powerpc/ppcfe.cpp +++ b/src/devices/cpu/powerpc/ppcfe.cpp @@ -10,41 +10,44 @@ #include "emu.h" #include "ppcfe.h" + #include "ppccom.h" +#include "cpu/drcfe.ipp" + //************************************************************************** // MACROS //************************************************************************** -#define GPR_USED(desc, x) do { (desc).regin[0] |= REGFLAG_R(x); } while (0) -#define GPR_USED_OR_ZERO(desc, x) do { (desc).regin[0] |= ((x) == 0 ? 0 : REGFLAG_R(x)); } while (0) -#define GPR_MODIFIED(desc, x) do { (desc).regout[0] |= REGFLAG_R(x); } while (0) +#define GPR_USED(desc, x) do { (desc).regin.set(REG_BIT_R0 + x); } while (0) +#define GPR_USED_OR_ZERO(desc, x) do { if (x) GPR_USED((desc), x); } while (0) +#define GPR_MODIFIED(desc, x) do { (desc).regout.set(REG_BIT_R0 + x); } while (0) -#define FPR_USED(desc, x) do { (desc).regin[1] |= REGFLAG_FR(x); } while (0) -#define FPR_MODIFIED(desc, x) do { (desc).regout[1] |= REGFLAG_FR(x); } while (0) +#define FPR_USED(desc, x) do { (desc).regin.set(REG_BIT_FR0 + x); } while (0) +#define FPR_MODIFIED(desc, x) do { (desc).regout.set(REG_BIT_FR0 + x); } while (0) -#define CR_USED(desc, x) do { (desc).regin[2] |= REGFLAG_CR(x); } while (0) -#define CR_BIT_USED(desc, x) do { (desc).regin[2] |= REGFLAG_CR_BIT(x); } while (0) -#define CR_MODIFIED(desc, x) do { (desc).regout[2] |= REGFLAG_CR(x); } while (0) -#define CR_BIT_MODIFIED(desc, x) do { (desc).regout[2] |= REGFLAG_CR_BIT(x); } while (0) +#define CR_USED(desc, x) do { CR_BIT_USED((desc), (x * 4) + 0); CR_BIT_USED((desc), (x * 4) + 1); CR_BIT_USED((desc), (x * 4) + 2); CR_BIT_USED((desc), (x * 4) + 3); } while (0) +#define CR_BIT_USED(desc, x) do { (desc).regin.set(64 + 31 - x); } while (0) +#define CR_MODIFIED(desc, x) do { CR_BIT_MODIFIED((desc), (x * 4) + 0); CR_BIT_MODIFIED((desc), (x * 4) + 1); CR_BIT_MODIFIED((desc), (x * 4) + 2); CR_BIT_MODIFIED((desc), (x * 4) + 3); } while (0) +#define CR_BIT_MODIFIED(desc, x) do { (desc).regout.set(64 + 31 - x); } while (0) -#define XER_CA_USED(desc) do { (desc).regin[3] |= REGFLAG_XER_CA; } while (0) -#define XER_OV_USED(desc) do { (desc).regin[3] |= REGFLAG_XER_OV; } while (0) -#define XER_SO_USED(desc) do { (desc).regin[3] |= REGFLAG_XER_SO; } while (0) -#define XER_COUNT_USED(desc) do { (desc).regin[3] |= REGFLAG_XER_COUNT; } while (0) -#define XER_CA_MODIFIED(desc) do { (desc).regout[3] |= REGFLAG_XER_CA; } while (0) -#define XER_OV_MODIFIED(desc) do { (desc).regout[3] |= REGFLAG_XER_OV; } while (0) -#define XER_SO_MODIFIED(desc) do { (desc).regout[3] |= REGFLAG_XER_SO; } while (0) -#define XER_COUNT_MODIFIED(desc) do { (desc).regout[3] |= REGFLAG_XER_COUNT; } while (0) +#define XER_CA_USED(desc) do { (desc).regin.set(REG_BIT_XER_CA); } while (0) +#define XER_OV_USED(desc) do { (desc).regin.set(REG_BIT_XER_OV); } while (0) +#define XER_SO_USED(desc) do { (desc).regin.set(REG_BIT_XER_SO); } while (0) +#define XER_COUNT_USED(desc) do { (desc).regin.set(REG_BIT_XER_COUNT); } while (0) +#define XER_CA_MODIFIED(desc) do { (desc).regout.set(REG_BIT_XER_CA); } while (0) +#define XER_OV_MODIFIED(desc) do { (desc).regout.set(REG_BIT_XER_OV); } while (0) +#define XER_SO_MODIFIED(desc) do { (desc).regout.set(REG_BIT_XER_SO); } while (0) +#define XER_COUNT_MODIFIED(desc) do { (desc).regout.set(REG_BIT_XER_COUNT); } while (0) -#define CTR_USED(desc) do { (desc).regin[3] |= REGFLAG_CTR; } while (0) -#define CTR_MODIFIED(desc) do { (desc).regout[3] |= REGFLAG_CTR; } while (0) -#define LR_USED(desc) do { (desc).regin[3] |= REGFLAG_LR; } while (0) -#define LR_MODIFIED(desc) do { (desc).regout[3] |= REGFLAG_LR; } while (0) +#define CTR_USED(desc) do { (desc).regin.set(REG_BIT_CTR); } while (0) +#define CTR_MODIFIED(desc) do { (desc).regout.set(REG_BIT_CTR); } while (0) +#define LR_USED(desc) do { (desc).regin.set(REG_BIT_LR); } while (0) +#define LR_MODIFIED(desc) do { (desc).regout.set(REG_BIT_LR); } while (0) -#define FPSCR_USED(desc, x) do { (desc).regin[3] |= REGFLAG_FPSCR(x); } while (0) -#define FPSCR_MODIFIED(desc, x) do { (desc).regout[3] |= REGFLAG_FPSCR(x); } while (0) +#define FPSCR_USED(desc, x) do { (desc).regin.set(REG_BIT_FPSCR0 + x); } while (0) +#define FPSCR_MODIFIED(desc, x) do { (desc).regout.set(REG_BIT_FPSCR0 + x); } while (0) @@ -57,11 +60,22 @@ //------------------------------------------------- ppc_device::frontend::frontend(ppc_device &ppc, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) - : drc_frontend(ppc, window_start, window_end, max_sequence) + : drc_frontend_base(ppc.space_config(AS_PROGRAM)->page_shift(), window_start, window_end, max_sequence) , m_ppc(ppc) { } +ppc_device::frontend::~frontend() +{ +} + +ppc_device::opcode_desc const *ppc_device::frontend::describe_code(offs_t startpc) +{ + return do_describe_code( + [this] (opcode_desc &desc, opcode_desc const *prev) { return describe(desc, prev); }, + startpc); +} + //------------------------------------------------- // describe - build a description of a single @@ -70,7 +84,6 @@ ppc_device::frontend::frontend(ppc_device &ppc, uint32_t window_start, uint32_t bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) { - uint32_t op, opswitch; int regnum; // compute the physical PC @@ -78,19 +91,23 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) { // uh-oh: a page fault; leave the description empty and just if this is the first instruction, leave it empty and // mark as needing to validate; otherwise, just end the sequence here - desc.flags |= OPFLAG_VALIDATE_TLB | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_COMPILER_PAGE_FAULT | OPFLAG_VIRTUAL_NOOP | OPFLAG_END_SEQUENCE; + desc.set_validate_tlb(); + desc.set_can_cause_exception(); + desc.set_compiler_page_fault(); + desc.set_virtual_noop(); + desc.set_end_sequence(); return true; } // fetch the opcode - op = desc.opptr.l[0] = m_ppc.m_pr32(desc.physpc); + const uint32_t op = desc.opptr = m_ppc.m_pr32(desc.physpc); // all instructions are 4 bytes and default to a single cycle each desc.length = 4; desc.cycles = 1; // parse the instruction - opswitch = op >> 26; + const uint32_t opswitch = op >> 26; switch (opswitch) { case 0x02: // TDI - 64-bit only @@ -101,7 +118,7 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x03: // TWI GPR_USED(desc, G_RA(op)); - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_can_cause_exception(); if (is_603_class()) desc.cycles = 2; // 603 return true; @@ -162,7 +179,7 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) { CR_BIT_USED(desc, G_BI(op)); // branch folding - if (prev == nullptr || prev->regout[2] == 0) + if (prev == nullptr || REGFLAG_CR(prev->regout) == 0) desc.cycles = 0; } if (!(G_BO(op) & 0x04)) @@ -173,9 +190,14 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) if (op & M_LK) LR_MODIFIED(desc); if ((G_BO(op) & 0x14) == 0x14) - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + { + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } else - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + { + desc.set_is_conditional_branch(); + } desc.targetpc = (int16_t)(G_BD(op) << 2) + ((op & M_AA) ? 0 : desc.pc); if (desc.targetpc == desc.pc && desc.cycles == 0) desc.cycles = 1; @@ -184,7 +206,7 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x11: // SC if (!(m_ppc.m_cap & (PPCCAP_OEA | PPCCAP_4XX))) return false; - desc.flags |= OPFLAG_WILL_CAUSE_EXCEPTION; + desc.set_will_cause_exception(); if (is_601_class()) desc.cycles = 16; // 601 else if (is_603_class()) @@ -196,7 +218,8 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x12: // Bx if (op & M_LK) LR_MODIFIED(desc); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); desc.targetpc = ((int32_t)(G_LI(op) << 8) >> 6) + ((op & M_AA) ? 0 : desc.pc); // branch folding if (desc.targetpc != desc.pc) @@ -263,7 +286,7 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x2a: // LHA GPR_USED_OR_ZERO(desc, G_RA(op)); GPR_MODIFIED(desc, G_RD(op)); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); return true; case 0x21: // LWZU @@ -275,7 +298,7 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) GPR_USED(desc, G_RA(op)); GPR_MODIFIED(desc, G_RD(op)); GPR_MODIFIED(desc, G_RA(op)); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); return true; case 0x24: // STW @@ -283,7 +306,7 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x2c: // STH GPR_USED_OR_ZERO(desc, G_RA(op)); GPR_USED(desc, G_RS(op)); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); return true; case 0x25: // STWU @@ -294,7 +317,7 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) GPR_USED(desc, G_RA(op)); GPR_USED(desc, G_RS(op)); GPR_MODIFIED(desc, G_RA(op)); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); return true; case 0x2e: // LMW @@ -305,7 +328,7 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) if (regnum != G_RA(op) || ((m_ppc.m_cap & PPCCAP_4XX) && regnum == 31)) GPR_MODIFIED(desc, regnum); } - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); desc.cycles = 32 - G_RD(op); return true; @@ -313,7 +336,7 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) GPR_USED_OR_ZERO(desc, G_RA(op)); for (regnum = G_RS(op); regnum < 32; regnum++) GPR_USED(desc, regnum); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); desc.cycles = 32 - G_RS(op); return true; @@ -323,7 +346,7 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) return false; GPR_USED_OR_ZERO(desc, G_RA(op)); FPR_MODIFIED(desc, G_RD(op)); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); return true; case 0x31: // LFSU @@ -335,7 +358,7 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) GPR_USED(desc, G_RA(op)); GPR_MODIFIED(desc, G_RA(op)); FPR_MODIFIED(desc, G_RD(op)); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); return true; case 0x34: // STFS @@ -344,7 +367,7 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) return false; GPR_USED_OR_ZERO(desc, G_RA(op)); FPR_USED(desc, G_RS(op)); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); return true; case 0x35: // STFSU @@ -356,7 +379,7 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) GPR_USED(desc, G_RA(op)); GPR_MODIFIED(desc, G_RA(op)); FPR_USED(desc, G_RS(op)); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); return true; case 0x3b: // 0x3b group @@ -386,7 +409,7 @@ bool ppc_device::frontend::describe_13(uint32_t op, opcode_desc &desc, const opc CR_USED(desc, G_CRFS(op)); CR_MODIFIED(desc, G_CRFD(op)); // CR logical folding - if (prev == nullptr || prev->regout[2] == 0) + if (prev == nullptr || REGFLAG_CR(prev->regout) == 0) desc.cycles = 0; return true; @@ -402,9 +425,14 @@ bool ppc_device::frontend::describe_13(uint32_t op, opcode_desc &desc, const opc if (op & M_LK) LR_MODIFIED(desc); if ((G_BO(op) & 0x14) == 0x14) - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + { + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } else - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + { + desc.set_is_conditional_branch(); + } desc.targetpc = BRANCH_TARGET_DYNAMIC; return true; @@ -420,14 +448,18 @@ bool ppc_device::frontend::describe_13(uint32_t op, opcode_desc &desc, const opc CR_BIT_USED(desc, G_CRBB(op)); CR_BIT_MODIFIED(desc, G_CRBD(op)); // CR logical folding - if (prev == nullptr || prev->regout[2] == 0) + if (prev == nullptr || REGFLAG_CR(prev->regout) == 0) desc.cycles = 0; return true; case 0x032: // RFI if (!(m_ppc.m_cap & (PPCCAP_OEA | PPCCAP_4XX))) return false; - desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CHANGE_MODES | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_is_unconditional_branch(); + desc.set_can_cause_exception(); + desc.set_end_sequence(); + desc.set_privileged(); + desc.set_can_change_modes(); desc.targetpc = BRANCH_TARGET_DYNAMIC; if (is_601_class()) desc.cycles = 13; // 601 @@ -440,7 +472,11 @@ bool ppc_device::frontend::describe_13(uint32_t op, opcode_desc &desc, const opc case 0x033: // RFCI if (!(m_ppc.m_cap & PPCCAP_4XX)) return false; - desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CHANGE_MODES | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_is_unconditional_branch(); + desc.set_can_cause_exception(); + desc.set_end_sequence(); + desc.set_privileged(); + desc.set_can_change_modes(); desc.targetpc = BRANCH_TARGET_DYNAMIC; return true; @@ -460,9 +496,14 @@ bool ppc_device::frontend::describe_13(uint32_t op, opcode_desc &desc, const opc if (op & M_LK) LR_MODIFIED(desc); if ((G_BO(op) & 0x14) == 0x14) - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + { + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } else - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + { + desc.set_is_conditional_branch(); + } desc.targetpc = BRANCH_TARGET_DYNAMIC; return true; } @@ -523,7 +564,7 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x004: // TW GPR_USED(desc, G_RA(op)); GPR_USED(desc, G_RB(op)); - desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_can_cause_exception(); if (is_603_class()) desc.cycles = 2; // 603 return true; @@ -736,7 +777,7 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc GPR_USED_OR_ZERO(desc, G_RA(op)); GPR_USED(desc, G_RB(op)); GPR_MODIFIED(desc, G_RD(op)); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); return true; case 0x018: // SLWx @@ -800,7 +841,8 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc return false; GPR_USED_OR_ZERO(desc, G_RA(op)); GPR_USED(desc, G_RB(op)); - desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_can_cause_exception(); + desc.set_privileged(); return true; case 0x037: // LWZUX @@ -813,7 +855,7 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc GPR_USED(desc, G_RB(op)); GPR_MODIFIED(desc, G_RD(op)); GPR_MODIFIED(desc, G_RA(op)); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); return true; case 0x153: // MFSPR @@ -831,7 +873,10 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc XER_SO_USED(desc); } if (spr & 0x010) - desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION; + { + desc.set_can_cause_exception(); + desc.set_privileged(); + } if ((m_ppc.m_cap & PPCCAP_4XX) && spr == SPR4XX_TBLU) desc.cycles = POWERPC_COUNT_READ_TBL; else if ((m_ppc.m_cap & PPCCAP_VEA) && spr == SPRVEA_TBL_R) @@ -842,20 +887,24 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x053: // MFMSR GPR_MODIFIED(desc, G_RD(op)); - desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_CAN_EXPOSE_EXTERNAL_INT; + desc.set_can_cause_exception(); + desc.set_can_expose_external_int(); + desc.set_privileged(); if (is_601_class()) desc.cycles = 2; // 601 return true; case 0x253: // MFSR GPR_MODIFIED(desc, G_RD(op)); - desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_can_cause_exception(); + desc.set_privileged(); return true; case 0x293: // MFSRIN GPR_USED(desc, G_RB(op)); GPR_MODIFIED(desc, G_RD(op)); - desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_can_cause_exception(); + desc.set_privileged(); return true; case 0x173: // MFTB @@ -900,7 +949,10 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x092: // MTMSR GPR_USED(desc, G_RS(op)); - desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_CAN_CHANGE_MODES | OPFLAG_END_SEQUENCE; + desc.set_can_cause_exception(); + desc.set_end_sequence(); + desc.set_privileged(); + desc.set_can_change_modes(); if (is_601_class()) desc.cycles = 17; // 601 else if (is_603_class()) @@ -911,7 +963,8 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc if (!(m_ppc.m_cap & PPCCAP_OEA)) return false; GPR_USED(desc, G_RS(op)); - desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_can_cause_exception(); + desc.set_privileged(); return true; case 0x1d3: // MTSPR @@ -929,7 +982,10 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc XER_SO_MODIFIED(desc); } if (spr & 0x010) - desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION; + { + desc.set_can_cause_exception(); + desc.set_privileged(); + } return true; case 0x1b6: // ECOWX @@ -945,7 +1001,7 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc GPR_USED_OR_ZERO(desc, G_RA(op)); GPR_USED(desc, G_RB(op)); GPR_USED(desc, G_RS(op)); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); return true; case 0x0b7: // STWUX @@ -957,7 +1013,7 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc GPR_USED(desc, G_RB(op)); GPR_USED(desc, G_RS(op)); GPR_MODIFIED(desc, G_RA(op)); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); return true; case 0x0f2: // MTSRIN @@ -965,27 +1021,31 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc return false; GPR_USED(desc, G_RS(op)); GPR_USED(desc, G_RB(op)); - desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_can_cause_exception(); + desc.set_privileged(); return true; case 0x132: // TLBIE if (!(m_ppc.m_cap & PPCCAP_OEA)) return false; GPR_USED(desc, G_RB(op)); - desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_can_cause_exception(); + desc.set_privileged(); return true; case 0x172: // TLBIA if (!(m_ppc.m_cap & PPCCAP_OEA) || (m_ppc.m_cap & PPCCAP_603_MMU)) return false; - desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_can_cause_exception(); + desc.set_privileged(); return true; case 0x3d2: // TLBLD case 0x3f2: // TLBLI if (!(m_ppc.m_cap & PPCCAP_603_MMU) && !is_602_class()) return false; - desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_can_cause_exception(); + desc.set_privileged(); return true; case 0x200: // MCRXR @@ -1004,7 +1064,7 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc XER_COUNT_USED(desc); for (regnum = 0; regnum < 32; regnum++) GPR_MODIFIED(desc, regnum); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); return true; case 0x217: // LFSX @@ -1014,13 +1074,14 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc GPR_USED_OR_ZERO(desc, G_RA(op)); GPR_USED(desc, G_RB(op)); FPR_MODIFIED(desc, G_RD(op)); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); return true; case 0x236: // TLBSYNC if (!(m_ppc.m_cap & PPCCAP_OEA)) return false; - desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_can_cause_exception(); + desc.set_privileged(); return true; case 0x256: // SYNC @@ -1041,14 +1102,14 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc GPR_USED(desc, G_RB(op)); GPR_MODIFIED(desc, G_RA(op)); FPR_MODIFIED(desc, G_RD(op)); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); return true; case 0x255: // LSWI GPR_USED_OR_ZERO(desc, G_RA(op)); for (regnum = 0; regnum < ((G_NB(op) - 1) & 0x1f) + 1; regnum += 4) GPR_MODIFIED(desc, (G_RD(op) + regnum / 4) % 32); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); desc.cycles = (((G_NB(op) - 1) & 0x1f) + 1 + 3) / 4; return true; @@ -1058,14 +1119,14 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc XER_COUNT_USED(desc); for (regnum = 0; regnum < 32; regnum++) GPR_USED(desc, regnum); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); return true; case 0x2d5: // STSWI GPR_USED_OR_ZERO(desc, G_RA(op)); for (regnum = 0; regnum < ((G_NB(op) - 1) & 0x1f) + 1; regnum += 4) GPR_USED(desc, (G_RD(op) + regnum / 4) % 32); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); desc.cycles = (((G_NB(op) - 1) & 0x1f) + 1 + 3) / 4; return true; @@ -1077,7 +1138,7 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc GPR_USED_OR_ZERO(desc, G_RA(op)); GPR_USED(desc, G_RB(op)); FPR_USED(desc, G_RS(op)); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); return true; case 0x2b7: // STFSUX @@ -1090,7 +1151,7 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc GPR_USED(desc, G_RB(op)); GPR_MODIFIED(desc, G_RA(op)); FPR_USED(desc, G_RS(op)); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); return true; case 0x338: // SRAWIx @@ -1109,7 +1170,7 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc return false; GPR_USED_OR_ZERO(desc, G_RA(op)); GPR_USED(desc, G_RB(op)); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); return true; case 0x106: // ICBT @@ -1119,7 +1180,8 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc return false; GPR_USED_OR_ZERO(desc, G_RA(op)); GPR_USED(desc, G_RB(op)); - desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_can_cause_exception(); + desc.set_privileged(); return true; case 0x1e6: // DCREAD @@ -1129,42 +1191,48 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc GPR_USED_OR_ZERO(desc, G_RA(op)); GPR_USED(desc, G_RB(op)); GPR_MODIFIED(desc, G_RT(op)); - desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_can_cause_exception(); + desc.set_privileged(); return true; case 0x143: // MFDCR if (!(m_ppc.m_cap & PPCCAP_4XX)) return false; GPR_MODIFIED(desc, G_RD(op)); - desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION; + desc.set_can_cause_exception(); + desc.set_privileged(); return true; case 0x1c3: // MTDCR if (!(m_ppc.m_cap & PPCCAP_4XX)) return false; GPR_USED(desc, G_RS(op)); - desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_CAN_EXPOSE_EXTERNAL_INT; + desc.set_can_cause_exception(); + desc.set_can_expose_external_int(); + desc.set_privileged(); return true; case 0x083: // WRTEE if (!(m_ppc.m_cap & PPCCAP_4XX)) return false; GPR_USED(desc, G_RS(op)); - desc.flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT; + desc.set_can_expose_external_int(); return true; case 0x0a3: // WRTEEI if (!(m_ppc.m_cap & PPCCAP_4XX)) return false; if (op & MSR_EE) - desc.flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT; + desc.set_can_expose_external_int(); return true; case 0x254: // ESA case 0x274: // DSA if (!is_602_class()) return false; - desc.flags |= OPFLAG_CAN_CHANGE_MODES | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_END_SEQUENCE; + desc.set_can_cause_exception(); + desc.set_end_sequence(); + desc.set_can_change_modes(); return true; case 0x14b: // DIV (POWER) diff --git a/src/devices/cpu/powerpc/ppcfe.h b/src/devices/cpu/powerpc/ppcfe.h index 40b82bd8756..840a72c448f 100644 --- a/src/devices/cpu/powerpc/ppcfe.h +++ b/src/devices/cpu/powerpc/ppcfe.h @@ -16,42 +16,101 @@ #include "cpu/drcfe.h" +#include <bitset> + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** -class ppc_device::frontend : public drc_frontend +class ppc_device::opcode_desc : public opcode_desc_base<opcode_desc, 128> { public: - // register flags 0 - static constexpr u32 REGFLAG_R(unsigned n) { return 1U << n; } - static constexpr u32 REGFLAG_RZ(unsigned n) { return !n ? 0U : REGFLAG_R(n); } - - // register flags 1 - static constexpr u32 REGFLAG_FR(unsigned n) { return 1U << n; } - - // register flags 2 - static constexpr u32 REGFLAG_CR(unsigned n) { return 0xf0000000U >> (4 * n); } - static constexpr u32 REGFLAG_CR_BIT(unsigned n) { return 0x80000000U >> n; } - - // register flags 3 - static constexpr u32 REGFLAG_XER_CA = 1U << 0; - static constexpr u32 REGFLAG_XER_OV = 1U << 1; - static constexpr u32 REGFLAG_XER_SO = 1U << 2; - static constexpr u32 REGFLAG_XER_COUNT = 1U << 3; - static constexpr u32 REGFLAG_CTR = 1U << 4; - static constexpr u32 REGFLAG_LR = 1U << 5; - static constexpr u32 REGFLAG_FPSCR(unsigned n) { return 1U << (6 + n); } + offs_t physpc; // physical PC of this opcode + + u32 opptr; // copy of opcode + + u32 cycles; // number of cycles needed to execute + + void set_can_expose_external_int() { m_extra_flags.set(CAN_EXPOSE_EXTERNAL_INT); } + void set_privileged() { m_extra_flags.set(PRIVILEGED); } + void set_compiler_unmapped() { m_extra_flags.set(COMPILER_UNMAPPED); } + void set_can_change_modes() { m_extra_flags.set(CAN_CHANGE_MODES); } + void set_reads_memory() { m_extra_flags.set(READS_MEMORY); } + void set_writes_memory() { m_extra_flags.set(WRITES_MEMORY); } + + bool can_expose_external_int() const { return m_extra_flags[CAN_EXPOSE_EXTERNAL_INT]; } + bool privileged() const { return m_extra_flags[PRIVILEGED]; } + bool compiler_unmapped() const { return m_extra_flags[COMPILER_UNMAPPED]; } + bool can_change_modes() const { return m_extra_flags[CAN_CHANGE_MODES]; } + bool reads_memory() const { return m_extra_flags[READS_MEMORY]; } + bool writes_memory() const { return m_extra_flags[WRITES_MEMORY]; } + + void reset(offs_t curpc, bool in_delay_slot) + { + opcode_desc_base::reset(curpc, in_delay_slot); + + physpc = curpc; + opptr = 0; + cycles = 0; + m_extra_flags.reset(); + } + +protected: + enum + { + CAN_EXPOSE_EXTERNAL_INT = 0, + PRIVILEGED, + COMPILER_UNMAPPED, + CAN_CHANGE_MODES, + READS_MEMORY, + WRITES_MEMORY, + + EXTRA_FLAG_COUNT + }; + + std::bitset<EXTRA_FLAG_COUNT> m_extra_flags; +}; + +class ppc_device::frontend : public drc_frontend_base<opcode_desc> +{ +public: + static constexpr bool REGFLAG_R(const opcode_desc::regmask &r, unsigned n) { return r[REG_BIT_R0 + n]; } + static constexpr bool REGFLAG_RZ(const opcode_desc::regmask &r, unsigned n) { return n && REGFLAG_R(r, n); } + static constexpr bool REGFLAG_FR(const opcode_desc::regmask &r, unsigned n) { return r[REG_BIT_FR0 + n]; } + static constexpr uint32_t REGFLAG_CR(const opcode_desc::regmask &r) { return uint32_t(((r << 32) >> (128 - 32)).to_ulong()); } + static constexpr uint8_t REGFLAG_CR(const opcode_desc::regmask &r, unsigned n) { return uint8_t(((r << ((4 * n) + 32)) >> (128 - 4)).to_ulong()); } + static constexpr bool REGFLAG_CR_BIT(const opcode_desc::regmask &r, unsigned n) { return r[64 + 31 - n]; } + static constexpr bool REGFLAG_XER_CA(const opcode_desc::regmask &r) { return r[REG_BIT_XER_CA]; } + static constexpr bool REGFLAG_XER_OV(const opcode_desc::regmask &r) { return r[REG_BIT_XER_OV]; } + static constexpr bool REGFLAG_XER_SO(const opcode_desc::regmask &r) { return r[REG_BIT_XER_SO]; } + static constexpr bool REGFLAG_XER_COUNT(const opcode_desc::regmask &r) { return r[REG_BIT_XER_COUNT]; } + static constexpr bool REGFLAG_CTR(const opcode_desc::regmask &r) { return r[REG_BIT_CTR]; } + static constexpr bool REGFLAG_LR(const opcode_desc::regmask &r) { return r[REG_BIT_LR]; } + static constexpr bool REGFLAG_FPSCR(const opcode_desc::regmask &r, unsigned n) { return r[REG_BIT_FPSCR0 + n]; } // construction/destruction frontend(ppc_device &ppc, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); + ~frontend(); + + opcode_desc const *describe_code(offs_t startpc); protected: - // required overrides - virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override; + enum + { + REG_BIT_R0 = 0, + REG_BIT_FR0 = 32, + REG_BIT_XER_CA = 96, + REG_BIT_XER_OV, + REG_BIT_XER_SO, + REG_BIT_XER_COUNT, + REG_BIT_CTR, + REG_BIT_LR, + REG_BIT_FPSCR0 + }; + + bool describe(opcode_desc &desc, const opcode_desc *prev); -private: // inlines uint32_t compute_spr(uint32_t spr) const { return ((spr >> 5) | (spr << 5)) & 0x3ff; } bool is_403_class() const { return (m_ppc.m_flavor == ppc_device::PPC_MODEL_403GA || m_ppc.m_flavor == ppc_device::PPC_MODEL_403GB || m_ppc.m_flavor == ppc_device::PPC_MODEL_403GC || m_ppc.m_flavor == ppc_device::PPC_MODEL_403GCX || m_ppc.m_flavor == ppc_device::PPC_MODEL_405GP); } @@ -69,5 +128,4 @@ private: ppc_device &m_ppc; }; - #endif // MAME_CPU_POWERPC_PPCFE_H 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 diff --git a/src/devices/cpu/sharc/sharc.cpp b/src/devices/cpu/sharc/sharc.cpp index 4104f82aab2..a7466fd012f 100644 --- a/src/devices/cpu/sharc/sharc.cpp +++ b/src/devices/cpu/sharc/sharc.cpp @@ -619,7 +619,7 @@ void adsp21062_device::device_start() m_drcuml->symbol_add(&m_core->lstkp, sizeof(m_core->lstkp), "lstkp"); m_drcuml->symbol_add(&m_core->px, sizeof(m_core->px), "px"); - m_drcfe = std::make_unique<sharc_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, COMPILE_MAX_SEQUENCE); + m_drcfe = std::make_unique<frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, COMPILE_MAX_SEQUENCE); for (int i = 0; i < 16; i++) m_regmap[i] = uml::mem(&m_core->r[i]); diff --git a/src/devices/cpu/sharc/sharc.h b/src/devices/cpu/sharc/sharc.h index b11b47f8688..0094437238f 100644 --- a/src/devices/cpu/sharc/sharc.h +++ b/src/devices/cpu/sharc/sharc.h @@ -5,16 +5,11 @@ #pragma once -#include "cpu/drcfe.h" #include "cpu/drcuml.h" -class sharc_frontend; - class adsp21062_device : public cpu_device { - friend class sharc_frontend; - public: enum sharc_boot_mode { @@ -48,30 +43,6 @@ public: uint32_t iop_r(offs_t offset); void iop_w(offs_t offset, uint32_t data); - enum ASTAT_FLAGS : uint32_t - { - // ASTAT flags - AZ = 0x000001, // ALU result zero - AV = 0x000002, // ALU overflow - AN = 0x000004, // ALU result negative - AC = 0x000008, // ALU fixed-point carry - AS = 0x000010, // ALU X input sign - AI = 0x000020, // ALU floating-point invalid operation - MN = 0x000040, // Multiplier result negative - MV = 0x000080, // Multiplier overflow - MU = 0x000100, // Multiplier underflow - MI = 0x000200, // Multiplier floating-point invalid operation - AF = 0x000400, - SV = 0x000800, // Shifter overflow - SZ = 0x001000, // Shifter result zero - SS = 0x002000, // Shifter input sign - BTF = 0x040000, // Bit Test Flag - FLG0 = 0x080000, // FLAG0 - FLG1 = 0x100000, // FLAG1 - FLG2 = 0x200000, // FLAG2 - FLG3 = 0x400000 // FLAG3 - }; - enum ASTAT_SHIFT { AZ_SHIFT = 0, @@ -148,6 +119,27 @@ protected: void data_4m(address_map &map) ATTR_COLD; private: + // ASTAT flags + static constexpr uint32_t AZ = 0x0000'0001; // ALU result zero + static constexpr uint32_t AV = 0x0000'0002; // ALU overflow + static constexpr uint32_t AN = 0x0000'0004; // ALU result negative + static constexpr uint32_t AC = 0x0000'0008; // ALU fixed-point carry + static constexpr uint32_t AS = 0x0000'0010; // ALU X input sign + static constexpr uint32_t AI = 0x0000'0020; // ALU floating-point invalid operation + static constexpr uint32_t MN = 0x0000'0040; // Multiplier result negative + static constexpr uint32_t MV = 0x0000'0080; // Multiplier overflow + static constexpr uint32_t MU = 0x0000'0100; // Multiplier underflow + static constexpr uint32_t MI = 0x0000'0200; // Multiplier floating-point invalid operation + static constexpr uint32_t AF = 0x0000'0400; + static constexpr uint32_t SV = 0x0000'0800; // Shifter overflow + static constexpr uint32_t SZ = 0x0000'1000; // Shifter result zero + static constexpr uint32_t SS = 0x0000'2000; // Shifter input sign + static constexpr uint32_t BTF = 0x0004'0000; // Bit Test Flag + static constexpr uint32_t FLG0 = 0x0008'0000; // FLAG0 + static constexpr uint32_t FLG1 = 0x0010'0000; // FLAG1 + static constexpr uint32_t FLG2 = 0x0020'0000; // FLAG2 + static constexpr uint32_t FLG3 = 0x0040'0000; // FLAG3 + // STKY flags static constexpr uint32_t AUS = 0x0000'0001; // ALU floating-point underflow static constexpr uint32_t AVS = 0x0000'0002; // ALU floating-point overflow @@ -242,6 +234,9 @@ private: struct alignas(16) sharc_internal_state; + class frontend; + class opcode_desc; + static const SHARC_OP s_sharc_opcode_table[]; static const size_t s_num_ops; @@ -259,7 +254,7 @@ private: // UML stuff drc_cache m_cache; std::unique_ptr<drcuml_state> m_drcuml; - std::unique_ptr<sharc_frontend> m_drcfe; + std::unique_ptr<frontend> m_drcfe; uml::parameter m_regmap[16]; uml::code_handle *m_entry; diff --git a/src/devices/cpu/sharc/sharcdrc.cpp b/src/devices/cpu/sharc/sharcdrc.cpp index 5ec296217ed..f3ecdfe3b1a 100644 --- a/src/devices/cpu/sharc/sharcdrc.cpp +++ b/src/devices/cpu/sharc/sharcdrc.cpp @@ -13,11 +13,11 @@ #include "sharcfe.h" #include "sharcinternal.ipp" -#include "cpu/drcfe.h" #include "cpu/drcuml.h" #include "cpu/drcumlsh.h" +#define USE_ASTAT_ELISION 1 #define USE_FAST_APPROX 0 #define USE_SWAPDQ 0 @@ -77,21 +77,21 @@ #define MRF mem(&m_core->mrf) #define MRB mem(&m_core->mrb) -#define AZ_CALC_REQUIRED ((desc->regreq[0] & 0x00010000) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define AV_CALC_REQUIRED ((desc->regreq[0] & 0x00020000) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define AN_CALC_REQUIRED ((desc->regreq[0] & 0x00040000) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define AC_CALC_REQUIRED ((desc->regreq[0] & 0x00080000) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define AS_CALC_REQUIRED ((desc->regreq[0] & 0x00100000) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define AI_CALC_REQUIRED ((desc->regreq[0] & 0x00200000) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define MN_CALC_REQUIRED ((desc->regreq[0] & 0x00400000) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define MV_CALC_REQUIRED ((desc->regreq[0] & 0x00800000) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define MU_CALC_REQUIRED ((desc->regreq[0] & 0x01000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define MI_CALC_REQUIRED ((desc->regreq[0] & 0x02000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define SV_CALC_REQUIRED ((desc->regreq[0] & 0x04000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define SZ_CALC_REQUIRED ((desc->regreq[0] & 0x08000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define SS_CALC_REQUIRED ((desc->regreq[0] & 0x10000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define BTF_CALC_REQUIRED ((desc->regreq[0] & 0x20000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define AF_CALC_REQUIRED ((desc->regreq[0] & 0x40000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) +#define AZ_CALC_REQUIRED (!USE_ASTAT_ELISION || desc->az_calc_required()) +#define AV_CALC_REQUIRED (!USE_ASTAT_ELISION || desc->av_calc_required()) +#define AN_CALC_REQUIRED (!USE_ASTAT_ELISION || desc->an_calc_required()) +#define AC_CALC_REQUIRED (!USE_ASTAT_ELISION || desc->ac_calc_required()) +#define AS_CALC_REQUIRED (!USE_ASTAT_ELISION || desc->as_calc_required()) +#define AI_CALC_REQUIRED (!USE_ASTAT_ELISION || desc->ai_calc_required()) +#define MN_CALC_REQUIRED (!USE_ASTAT_ELISION || desc->mn_calc_required()) +#define MV_CALC_REQUIRED (!USE_ASTAT_ELISION || desc->mv_calc_required()) +#define MU_CALC_REQUIRED (!USE_ASTAT_ELISION || desc->mu_calc_required()) +#define MI_CALC_REQUIRED (!USE_ASTAT_ELISION || desc->mi_calc_required()) +#define SV_CALC_REQUIRED (!USE_ASTAT_ELISION || desc->sv_calc_required()) +#define SZ_CALC_REQUIRED (!USE_ASTAT_ELISION || desc->sz_calc_required()) +#define SS_CALC_REQUIRED (!USE_ASTAT_ELISION || desc->ss_calc_required()) +#define BTF_CALC_REQUIRED (!USE_ASTAT_ELISION || desc->btf_calc_required()) +#define AF_CALC_REQUIRED (!USE_ASTAT_ELISION || desc->af_calc_required()) namespace { @@ -1160,7 +1160,7 @@ void adsp21062_device::compile_block(offs_t pc) { // determine the last instruction in this sequence seqlast = seqhead; - while (seqlast && !(seqlast->flags & OPFLAG_END_SEQUENCE)) + while (seqlast && !seqlast->end_sequence()) seqlast = seqlast->next(); assert(seqlast != nullptr); @@ -1185,7 +1185,7 @@ void adsp21062_device::compile_block(offs_t pc) } // 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); // iterate over instructions in the sequence and compile them @@ -1200,7 +1200,7 @@ void adsp21062_device::compile_block(offs_t pc) } uint32_t nextpc; - if (seqlast->flags & OPFLAG_RETURN_TO_START) + if (seqlast->return_to_start()) nextpc = pc; // if we need to return to the start, do it else nextpc = seqlast->pc + (seqlast->skipslots + 1); // otherwise we just go to the next instruction @@ -1352,14 +1352,14 @@ void adsp21062_device::static_generate_reset_cache() void adsp21062_device::generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, bool last_delayslot) { /* add an entry for the log */ -// if (m_drcuml->logging() && !(desc->flags & OPFLAG_VIRTUAL_NOOP)) -// log_add_disasm_comment(block, desc->pc, desc->opptr.l[0]); +// if (m_drcuml->logging() && !desc->virtual_noop()) +// log_add_disasm_comment(block, desc->pc, desc->opptr); /* set the PC map variable */ UML_MAPVAR(block, MAPVAR_PC, desc->pc); // mapvar PC,desc->pc /* accumulate total cycles */ - compiler.cycles += desc->cycles; + compiler.cycles += 1; /* update the icount map variable */ UML_MAPVAR(block, MAPVAR_CYCLES, compiler.cycles); // mapvar CYCLES,compiler.cycles @@ -1372,33 +1372,25 @@ void adsp21062_device::generate_sequence_instruction(drcuml_block &block, compil UML_DEBUG(block, desc->pc); // debug desc->pc } - /* if we hit an unmapped address, fatal error */ - if (desc->flags & OPFLAG_COMPILER_UNMAPPED) - { - UML_MOV(block, mem(&m_core->pc), desc->pc); // mov [pc],desc->pc - save_fast_iregs(block); // <save fastregs> - UML_EXIT(block, EXECUTE_UNMAPPED_CODE); // exit EXECUTE_UNMAPPED_CODE - } - // handle a special case where call is used as the last operation in a loop - if ((desc->userflags & OP_USERFLAG_CALL) && (desc->userflags & OP_USERFLAG_LOOP)) + if (desc->call() && desc->loop()) { UML_MOV(block, I0, desc->pc); UML_CALLH(block, *m_call_loop_check); } /* if this is an invalid opcode, generate the exception now */ -// if (desc->flags & OPFLAG_INVALID_OPCODE) +// if (desc->invalid_opcode()) // UML_EXH(block, *m_exception[EXCEPTION_PROGRAM], 0x80000); // exh exception_program,0x80000 /* unless this is a virtual no-op, it's a regular instruction */ - if (!(desc->flags & OPFLAG_VIRTUAL_NOOP)) + if (!desc->virtual_noop()) { /* compile the instruction */ if (!generate_opcode(block, compiler, desc)) { UML_MOV(block, mem(&m_core->pc), desc->pc); // mov [pc],desc->pc - UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]); // dmov [arg64],*desc->opptr.q + UML_DMOV(block, mem(&m_core->arg64), desc->opptr); // dmov [arg64],*desc->opptr UML_CALLC(block, cfunc_unimplemented, this); // callc cfunc_unimplemented,ppc } } @@ -1438,34 +1430,31 @@ void adsp21062_device::generate_sequence_instruction(drcuml_block &block, compil // insert loop check at this instruction if needed - if (desc->userflags & OP_USERFLAG_LOOP) + if (desc->loop()) { UML_DMOV(block, I0, (uint64_t(compiler.cycles) << 32) | desc->pc); UML_CALLH(block, *m_loop_check); } // copy ASTAT bits over for conditional loop - if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY) - { - if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_AZ) - UML_MOV(block, mem(&m_core->astat_delay_copy.az), mem(&m_core->astat_drc.az)); - if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_AN) - UML_MOV(block, mem(&m_core->astat_delay_copy.an), mem(&m_core->astat_drc.an)); - if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_AV) - UML_MOV(block, mem(&m_core->astat_delay_copy.av), mem(&m_core->astat_drc.av)); - if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_AC) - UML_MOV(block, mem(&m_core->astat_delay_copy.ac), mem(&m_core->astat_drc.ac)); - if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_MN) - UML_MOV(block, mem(&m_core->astat_delay_copy.mn), mem(&m_core->astat_drc.mn)); - if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_MV) - UML_MOV(block, mem(&m_core->astat_delay_copy.mv), mem(&m_core->astat_drc.mv)); - if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_SV) - UML_MOV(block, mem(&m_core->astat_delay_copy.sv), mem(&m_core->astat_drc.sv)); - if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_SZ) - UML_MOV(block, mem(&m_core->astat_delay_copy.sz), mem(&m_core->astat_drc.sz)); - if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_BTF) - UML_MOV(block, mem(&m_core->astat_delay_copy.btf), mem(&m_core->astat_drc.btf)); - } + if (desc->astat_delay_copy_az()) + UML_MOV(block, mem(&m_core->astat_delay_copy.az), mem(&m_core->astat_drc.az)); + if (desc->astat_delay_copy_an()) + UML_MOV(block, mem(&m_core->astat_delay_copy.an), mem(&m_core->astat_drc.an)); + if (desc->astat_delay_copy_av()) + UML_MOV(block, mem(&m_core->astat_delay_copy.av), mem(&m_core->astat_drc.av)); + if (desc->astat_delay_copy_ac()) + UML_MOV(block, mem(&m_core->astat_delay_copy.ac), mem(&m_core->astat_drc.ac)); + if (desc->astat_delay_copy_mn()) + UML_MOV(block, mem(&m_core->astat_delay_copy.mn), mem(&m_core->astat_drc.mn)); + if (desc->astat_delay_copy_mv()) + UML_MOV(block, mem(&m_core->astat_delay_copy.mv), mem(&m_core->astat_drc.mv)); + if (desc->astat_delay_copy_sv()) + UML_MOV(block, mem(&m_core->astat_delay_copy.sv), mem(&m_core->astat_drc.sv)); + if (desc->astat_delay_copy_sz()) + UML_MOV(block, mem(&m_core->astat_delay_copy.sz), mem(&m_core->astat_drc.sz)); + if (desc->astat_delay_copy_btf()) + UML_MOV(block, mem(&m_core->astat_delay_copy.btf), mem(&m_core->astat_drc.btf)); } void adsp21062_device::generate_update_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param, bool allow_exception) @@ -1714,7 +1703,7 @@ void adsp21062_device::generate_call(drcuml_block &block, compiler_state &compil } // if this is the last instruction of a loop, we need to use the return PC from the resolved loop - if (desc->userflags & OP_USERFLAG_CALL && desc->userflags & OP_USERFLAG_LOOP) + if (desc->call() && desc->loop()) { UML_MOV(block, I0, mem(&m_core->temp_return)); } @@ -1732,7 +1721,7 @@ void adsp21062_device::generate_call(drcuml_block &block, compiler_state &compil if (desc->targetpc != BRANCH_TARGET_DYNAMIC) { generate_update_cycles(block, compiler_temp, desc->targetpc, true); - if (desc->flags & OPFLAG_INTRABLOCK_BRANCH) + if (desc->intrablock_branch()) UML_JMP(block, desc->targetpc | 0x80000000); else UML_HASHJMP(block, 0, desc->targetpc, *m_nocode); @@ -1799,7 +1788,7 @@ void adsp21062_device::generate_jump(drcuml_block &block, compiler_state &compil if (desc->targetpc != BRANCH_TARGET_DYNAMIC) { generate_update_cycles(block, compiler_temp, desc->targetpc, true); - if (desc->flags & OPFLAG_INTRABLOCK_BRANCH) + if (desc->intrablock_branch()) UML_JMP(block, desc->targetpc | 0x80000000); // jmp targetpc | 0x80000000 else UML_HASHJMP(block, 0, desc->targetpc, *m_nocode); // hashjmp 0,targetpc,nocode @@ -2175,42 +2164,42 @@ void adsp21062_device::generate_write_ureg(drcuml_block &block, compiler_state & UML_XOR(block, I1, mem(&m_core->astat), data); UML_MOV(block, mem(&m_core->astat), data & (FLG0 | FLG1 | FLG2 | FLG3)); UML_MOV(block, mem(&m_core->astat_drc.cacc), BIT(data, 24, 8)); - UML_MOV(block, ASTAT_AF, BIT(data, AF_SHIFT)); - UML_MOV(block, ASTAT_BTF, BIT(data, BTF_SHIFT)); - UML_MOV(block, ASTAT_SS, BIT(data, SS_SHIFT)); - UML_MOV(block, ASTAT_SZ, BIT(data, SZ_SHIFT)); - UML_MOV(block, ASTAT_SV, BIT(data, SV_SHIFT)); - UML_MOV(block, ASTAT_MI, BIT(data, MI_SHIFT)); - UML_MOV(block, ASTAT_MU, BIT(data, MU_SHIFT)); - UML_MOV(block, ASTAT_MV, BIT(data, MV_SHIFT)); - UML_MOV(block, ASTAT_MN, BIT(data, MN_SHIFT)); - UML_MOV(block, ASTAT_AI, BIT(data, AI_SHIFT)); - UML_MOV(block, ASTAT_AS, BIT(data, AS_SHIFT)); - UML_MOV(block, ASTAT_AC, BIT(data, AC_SHIFT)); - UML_MOV(block, ASTAT_AN, BIT(data, AN_SHIFT)); - UML_MOV(block, ASTAT_AV, BIT(data, AV_SHIFT)); - UML_MOV(block, ASTAT_AZ, BIT(data, AZ_SHIFT)); + if (AF_CALC_REQUIRED) UML_MOV(block, ASTAT_AF, BIT(data, AF_SHIFT)); + if (BTF_CALC_REQUIRED) UML_MOV(block, ASTAT_BTF, BIT(data, BTF_SHIFT)); + if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, BIT(data, SS_SHIFT)); + if (SZ_CALC_REQUIRED) UML_MOV(block, ASTAT_SZ, BIT(data, SZ_SHIFT)); + if (SV_CALC_REQUIRED) UML_MOV(block, ASTAT_SV, BIT(data, SV_SHIFT)); + if (MI_CALC_REQUIRED) UML_MOV(block, ASTAT_MI, BIT(data, MI_SHIFT)); + if (MU_CALC_REQUIRED) UML_MOV(block, ASTAT_MU, BIT(data, MU_SHIFT)); + if (MV_CALC_REQUIRED) UML_MOV(block, ASTAT_MV, BIT(data, MV_SHIFT)); + if (MN_CALC_REQUIRED) UML_MOV(block, ASTAT_MN, BIT(data, MN_SHIFT)); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, BIT(data, AI_SHIFT)); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, BIT(data, AS_SHIFT)); + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, BIT(data, AC_SHIFT)); + if (AN_CALC_REQUIRED) UML_MOV(block, ASTAT_AN, BIT(data, AN_SHIFT)); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, BIT(data, AV_SHIFT)); + if (AZ_CALC_REQUIRED) UML_MOV(block, ASTAT_AZ, BIT(data, AZ_SHIFT)); } else { UML_XOR(block, I1, I0, mem(&m_core->astat)); UML_AND(block, mem(&m_core->astat), I0, FLG0 | FLG1 | FLG2 | FLG3); UML_BFXU(block, mem(&m_core->astat_drc.cacc), I0, 24, 8); - UML_BFXU(block, ASTAT_AF, I0, AF_SHIFT, 1); - UML_BFXU(block, ASTAT_BTF, I0, BTF_SHIFT, 1); - UML_BFXU(block, ASTAT_SS, I0, SS_SHIFT, 1); - UML_BFXU(block, ASTAT_SZ, I0, SZ_SHIFT, 1); - UML_BFXU(block, ASTAT_SV, I0, SV_SHIFT, 1); - UML_BFXU(block, ASTAT_MI, I0, MI_SHIFT, 1); - UML_BFXU(block, ASTAT_MU, I0, MU_SHIFT, 1); - UML_BFXU(block, ASTAT_MV, I0, MV_SHIFT, 1); - UML_BFXU(block, ASTAT_MN, I0, MN_SHIFT, 1); - UML_BFXU(block, ASTAT_AI, I0, AI_SHIFT, 1); - UML_BFXU(block, ASTAT_AS, I0, AS_SHIFT, 1); - UML_BFXU(block, ASTAT_AC, I0, AC_SHIFT, 1); - UML_BFXU(block, ASTAT_AN, I0, AN_SHIFT, 1); - UML_BFXU(block, ASTAT_AV, I0, AV_SHIFT, 1); - UML_BFXU(block, ASTAT_AZ, I0, AZ_SHIFT, 1); + if (AF_CALC_REQUIRED) UML_BFXU(block, ASTAT_AF, I0, AF_SHIFT, 1); + if (BTF_CALC_REQUIRED) UML_BFXU(block, ASTAT_BTF, I0, BTF_SHIFT, 1); + if (SS_CALC_REQUIRED) UML_BFXU(block, ASTAT_SS, I0, SS_SHIFT, 1); + if (SZ_CALC_REQUIRED) UML_BFXU(block, ASTAT_SZ, I0, SZ_SHIFT, 1); + if (SV_CALC_REQUIRED) UML_BFXU(block, ASTAT_SV, I0, SV_SHIFT, 1); + if (MI_CALC_REQUIRED) UML_BFXU(block, ASTAT_MI, I0, MI_SHIFT, 1); + if (MU_CALC_REQUIRED) UML_BFXU(block, ASTAT_MU, I0, MU_SHIFT, 1); + if (MV_CALC_REQUIRED) UML_BFXU(block, ASTAT_MV, I0, MV_SHIFT, 1); + if (MN_CALC_REQUIRED) UML_BFXU(block, ASTAT_MN, I0, MN_SHIFT, 1); + if (AI_CALC_REQUIRED) UML_BFXU(block, ASTAT_AI, I0, AI_SHIFT, 1); + if (AS_CALC_REQUIRED) UML_BFXU(block, ASTAT_AS, I0, AS_SHIFT, 1); + if (AC_CALC_REQUIRED) UML_BFXU(block, ASTAT_AC, I0, AC_SHIFT, 1); + if (AN_CALC_REQUIRED) UML_BFXU(block, ASTAT_AN, I0, AN_SHIFT, 1); + if (AV_CALC_REQUIRED) UML_BFXU(block, ASTAT_AV, I0, AV_SHIFT, 1); + if (AZ_CALC_REQUIRED) UML_BFXU(block, ASTAT_AZ, I0, AZ_SHIFT, 1); } UML_SHL(block, I0, MODE2, FLG0_SHIFT - 15); UML_AND(block, I0, I0, I1); @@ -2284,7 +2273,7 @@ void adsp21062_device::generate_write_ureg(drcuml_block &block, compiler_state & bool adsp21062_device::generate_opcode(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - uint64_t opcode = desc->opptr.q[0]; + uint64_t const opcode = desc->opptr; switch ((opcode >> 45) & 7) { @@ -2862,72 +2851,72 @@ bool adsp21062_device::generate_opcode(drcuml_block &block, compiler_state &comp break; case 0xc: // ASTAT // TODO: does this need delay? - if (data & ASTAT_FLAGS::AZ) + if (AZ_CALC_REQUIRED && (data & AZ)) UML_MOV(block, ASTAT_AZ, 1); - if (data & ASTAT_FLAGS::AV) + if (AV_CALC_REQUIRED && (data & AV)) UML_MOV(block, ASTAT_AV, 1); - if (data & ASTAT_FLAGS::AN) + if (AN_CALC_REQUIRED && (data & AN)) UML_MOV(block, ASTAT_AN, 1); - if (data & ASTAT_FLAGS::AC) + if (AC_CALC_REQUIRED && (data & AC)) UML_MOV(block, ASTAT_AC, 1); - if (data & ASTAT_FLAGS::AS) + if (AS_CALC_REQUIRED && (data & AS)) UML_MOV(block, ASTAT_AS, 1); - if (data & ASTAT_FLAGS::AI) + if (AI_CALC_REQUIRED && (data & AI)) UML_MOV(block, ASTAT_AI, 1); - if (data & ASTAT_FLAGS::MN) + if (MN_CALC_REQUIRED && (data & MN)) UML_MOV(block, ASTAT_MN, 1); - if (data & ASTAT_FLAGS::MV) + if (MV_CALC_REQUIRED && (data & MV)) UML_MOV(block, ASTAT_MV, 1); - if (data & ASTAT_FLAGS::MU) + if (MU_CALC_REQUIRED && (data & MU)) UML_MOV(block, ASTAT_MU, 1); - if (data & ASTAT_FLAGS::MI) + if (MI_CALC_REQUIRED && (data & MI)) UML_MOV(block, ASTAT_MI, 1); - if (data & ASTAT_FLAGS::AF) + if (AF_CALC_REQUIRED && (data & AF)) UML_MOV(block, ASTAT_AF, 1); - if (data & ASTAT_FLAGS::SV) + if (SV_CALC_REQUIRED && (data & SV)) UML_MOV(block, ASTAT_SV, 1); - if (data & ASTAT_FLAGS::SZ) + if (SZ_CALC_REQUIRED && (data & SZ)) UML_MOV(block, ASTAT_SZ, 1); - if (data & ASTAT_FLAGS::SS) + if (SS_CALC_REQUIRED && (data & SS)) UML_MOV(block, ASTAT_SS, 1); - if (data & ASTAT_FLAGS::BTF) + if (BTF_CALC_REQUIRED && (data & BTF)) UML_MOV(block, ASTAT_BTF, 1); - if (data & (ASTAT_FLAGS::FLG0 | ASTAT_FLAGS::FLG1 | ASTAT_FLAGS::FLG2 | ASTAT_FLAGS::FLG3)) + if (data & (FLG0 | FLG1 | FLG2 | FLG3)) { UML_MOV(block, I0, mem(&m_core->astat)); - UML_ROLAND(block, I1, MODE2, FLG0_SHIFT - 15, data & (ASTAT_FLAGS::FLG0 | ASTAT_FLAGS::FLG1 | ASTAT_FLAGS::FLG2 | ASTAT_FLAGS::FLG3)); - UML_OR(block, mem(&m_core->astat), I0, data & (ASTAT_FLAGS::FLG0 | ASTAT_FLAGS::FLG1 | ASTAT_FLAGS::FLG2 | ASTAT_FLAGS::FLG3)); + UML_ROLAND(block, I1, MODE2, FLG0_SHIFT - 15, data & (FLG0 | FLG1 | FLG2 | FLG3)); + UML_OR(block, mem(&m_core->astat), I0, data & (FLG0 | FLG1 | FLG2 | FLG3)); UML_XOR(block, I0, I0, 0xffffffff); UML_AND(block, I0, I0, I1); } - if (data & ASTAT_FLAGS::FLG0) + if (data & FLG0) { uml::code_label const skip = compiler.labelnum++; - UML_TEST(block, I0, ASTAT_FLAGS::FLG0); + UML_TEST(block, I0, FLG0); UML_JMPc(block, COND_Z, skip); UML_CALLC(block, cfunc_update_flag_out<0>, this); UML_LABEL(block, skip); } - if (data & ASTAT_FLAGS::FLG1) + if (data & FLG1) { uml::code_label const skip = compiler.labelnum++; - UML_TEST(block, I0, ASTAT_FLAGS::FLG1); + UML_TEST(block, I0, FLG1); UML_JMPc(block, COND_Z, skip); UML_CALLC(block, cfunc_update_flag_out<1>, this); UML_LABEL(block, skip); } - if (data & ASTAT_FLAGS::FLG2) + if (data & FLG2) { uml::code_label const skip = compiler.labelnum++; - UML_TEST(block, I0, ASTAT_FLAGS::FLG2); + UML_TEST(block, I0, FLG2); UML_JMPc(block, COND_Z, skip); UML_CALLC(block, cfunc_update_flag_out<2>, this); UML_LABEL(block, skip); } - if (data & ASTAT_FLAGS::FLG3) + if (data & FLG3) { uml::code_label const skip = compiler.labelnum++; - UML_TEST(block, I0, ASTAT_FLAGS::FLG3); + UML_TEST(block, I0, FLG3); UML_JMPc(block, COND_Z, skip); UML_CALLC(block, cfunc_update_flag_out<3>, this); UML_LABEL(block, skip); @@ -2975,71 +2964,71 @@ bool adsp21062_device::generate_opcode(drcuml_block &block, compiler_state &comp break; case 0xc: // ASTAT // TODO: does this need delay? - if (data & ASTAT_FLAGS::AZ) + if (AZ_CALC_REQUIRED && (data & AZ)) UML_MOV(block, ASTAT_AZ, 0); - if (data & ASTAT_FLAGS::AV) + if (AV_CALC_REQUIRED && (data & AV)) UML_MOV(block, ASTAT_AV, 0); - if (data & ASTAT_FLAGS::AN) + if (AN_CALC_REQUIRED && (data & AN)) UML_MOV(block, ASTAT_AN, 0); - if (data & ASTAT_FLAGS::AC) + if (AC_CALC_REQUIRED && (data & AC)) UML_MOV(block, ASTAT_AC, 0); - if (data & ASTAT_FLAGS::AS) + if (AS_CALC_REQUIRED && (data & AS)) UML_MOV(block, ASTAT_AS, 0); - if (data & ASTAT_FLAGS::AI) + if (AI_CALC_REQUIRED && (data & AI)) UML_MOV(block, ASTAT_AI, 0); - if (data & ASTAT_FLAGS::MN) + if (MN_CALC_REQUIRED && (data & MN)) UML_MOV(block, ASTAT_MN, 0); - if (data & ASTAT_FLAGS::MV) + if (MV_CALC_REQUIRED && (data & MV)) UML_MOV(block, ASTAT_MV, 0); - if (data & ASTAT_FLAGS::MU) + if (MU_CALC_REQUIRED && (data & MU)) UML_MOV(block, ASTAT_MU, 0); - if (data & ASTAT_FLAGS::MI) + if (MI_CALC_REQUIRED && (data & MI)) UML_MOV(block, ASTAT_MI, 0); - if (data & ASTAT_FLAGS::AF) + if (AF_CALC_REQUIRED && (data & AF)) UML_MOV(block, ASTAT_AF, 0); - if (data & ASTAT_FLAGS::SV) + if (SV_CALC_REQUIRED && (data & SV)) UML_MOV(block, ASTAT_SV, 0); - if (data & ASTAT_FLAGS::SZ) + if (SZ_CALC_REQUIRED && (data & SZ)) UML_MOV(block, ASTAT_SZ, 0); - if (data & ASTAT_FLAGS::SS) + if (SS_CALC_REQUIRED && (data & SS)) UML_MOV(block, ASTAT_SS, 0); - if (data & ASTAT_FLAGS::BTF) + if (BTF_CALC_REQUIRED && (data & BTF)) UML_MOV(block, ASTAT_BTF, 0); - if (data & (ASTAT_FLAGS::FLG0 | ASTAT_FLAGS::FLG1 | ASTAT_FLAGS::FLG2 | ASTAT_FLAGS::FLG3)) + if (data & (FLG0 | FLG1 | FLG2 | FLG3)) { UML_MOV(block, I0, mem(&m_core->astat)); - UML_ROLAND(block, I1, MODE2, FLG0_SHIFT - 15, data & (ASTAT_FLAGS::FLG0 | ASTAT_FLAGS::FLG1 | ASTAT_FLAGS::FLG2 | ASTAT_FLAGS::FLG3)); - UML_AND(block, mem(&m_core->astat), I0, ~data & (ASTAT_FLAGS::FLG0 | ASTAT_FLAGS::FLG1 | ASTAT_FLAGS::FLG2 | ASTAT_FLAGS::FLG3)); + UML_ROLAND(block, I1, MODE2, FLG0_SHIFT - 15, data & (FLG0 | FLG1 | FLG2 | FLG3)); + UML_AND(block, mem(&m_core->astat), I0, ~data & (FLG0 | FLG1 | FLG2 | FLG3)); UML_AND(block, I0, I0, I1); } - if (data & ASTAT_FLAGS::FLG0) + if (data & FLG0) { uml::code_label const skip = compiler.labelnum++; - UML_TEST(block, I0, ASTAT_FLAGS::FLG0); + UML_TEST(block, I0, FLG0); UML_JMPc(block, COND_Z, skip); UML_CALLC(block, cfunc_update_flag_out<0>, this); UML_LABEL(block, skip); } - if (data & ASTAT_FLAGS::FLG1) + if (data & FLG1) { uml::code_label const skip = compiler.labelnum++; - UML_TEST(block, I0, ASTAT_FLAGS::FLG1); + UML_TEST(block, I0, FLG1); UML_JMPc(block, COND_Z, skip); UML_CALLC(block, cfunc_update_flag_out<1>, this); UML_LABEL(block, skip); } - if (data & ASTAT_FLAGS::FLG2) + if (data & FLG2) { uml::code_label const skip = compiler.labelnum++; - UML_TEST(block, I0, ASTAT_FLAGS::FLG2); + UML_TEST(block, I0, FLG2); UML_JMPc(block, COND_Z, skip); UML_CALLC(block, cfunc_update_flag_out<2>, this); UML_LABEL(block, skip); } - if (data & ASTAT_FLAGS::FLG3) + if (data & FLG3) { uml::code_label const skip = compiler.labelnum++; - UML_TEST(block, I0, ASTAT_FLAGS::FLG3); + UML_TEST(block, I0, FLG3); UML_JMPc(block, COND_Z, skip); UML_CALLC(block, cfunc_update_flag_out<3>, this); UML_LABEL(block, skip); @@ -3251,13 +3240,13 @@ bool adsp21062_device::generate_opcode(drcuml_block &block, compiler_state &comp int const compute = op_get_compute(opcode); bool temp_pm_dreg = false; - if (compute != 0 && pmd && desc->regout[0] & (1 << pm_dreg)) + if (compute != 0 && pmd && desc->regout[pm_dreg]) { UML_MOV(block, mem(&m_core->dreg_temp), REG(pm_dreg)); temp_pm_dreg = true; } bool temp_dm_dreg = false; - if (compute != 0 && dmd && desc->regout[0] & (1 << dm_dreg)) + if (compute != 0 && dmd && desc->regout[dm_dreg]) { UML_MOV(block, mem(&m_core->dreg_temp2), REG(dm_dreg)); temp_dm_dreg = true; @@ -3342,7 +3331,7 @@ bool adsp21062_device::generate_opcode(drcuml_block &block, compiler_state &comp bool temp_ureg = false; // save UREG if compute writes to it - if (compute != 0 && ureg_is_dreg && desc->regout[0] & (1 << (ureg & 0xf))) + if (compute != 0 && ureg_is_dreg && desc->regout[ureg & 0xf]) { UML_MOV(block, mem(&m_core->dreg_temp), REG(ureg & 0xf)); temp_ureg = true; @@ -3427,7 +3416,7 @@ bool adsp21062_device::generate_opcode(drcuml_block &block, compiler_state &comp bool temp_ureg = false; // save UREG if compute writes to it - if (compute != 0 && src_is_dreg && desc->regout[0] & (1 << (src_ureg & 0xf))) + if (compute != 0 && src_is_dreg && desc->regout[src_ureg & 0xf]) { UML_MOV(block, mem(&m_core->dreg_temp), REG(src_ureg & 0xf)); temp_ureg = true; @@ -3479,7 +3468,7 @@ bool adsp21062_device::generate_opcode(drcuml_block &block, compiler_state &comp bool temp_dreg = false; // save dreg if compute writes to it - if (compute != 0 && BIT(desc->regout[0], dreg)) + if (compute != 0 && desc->regout[dreg]) { UML_MOV(block, mem(&m_core->dreg_temp), REG(dreg)); temp_dreg = true; @@ -3586,7 +3575,7 @@ bool adsp21062_device::generate_opcode(drcuml_block &block, compiler_state &comp bool temp_dreg = false; // save dreg if shiftop writes to it - if (BIT(desc->regout[0], dreg)) + if (desc->regout[dreg]) { UML_MOV(block, mem(&m_core->dreg_temp), REG(dreg)); temp_dreg = true; @@ -3689,7 +3678,7 @@ bool adsp21062_device::generate_opcode(drcuml_block &block, compiler_state &comp // DREG -> DM bool temp_dreg = false; // save dreg if compute writes to it - if (BIT(desc->regout[0], dreg)) + if (desc->regout[dreg]) { UML_MOV(block, mem(&m_core->dreg_temp), REG(dreg)); temp_dreg = true; @@ -3747,7 +3736,7 @@ bool adsp21062_device::generate_opcode(drcuml_block &block, compiler_state &comp // DREG -> DM bool temp_dreg = false; // save dreg if compute writes to it - if (BIT(desc->regout[0], dreg)) + if (desc->regout[dreg]) { UML_MOV(block, mem(&m_core->dreg_temp), REG(dreg)); temp_dreg = true; @@ -3792,13 +3781,13 @@ bool adsp21062_device::generate_opcode(drcuml_block &block, compiler_state &comp void adsp21062_device::generate_unimplemented_compute(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { UML_MOV(block, mem(&m_core->pc), desc->pc); - UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]); + UML_DMOV(block, mem(&m_core->arg64), desc->opptr); UML_CALLC(block, cfunc_unimplemented_compute, this); } void adsp21062_device::generate_compute(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - uint64_t const opcode = desc->opptr.q[0]; + uint64_t const opcode = desc->opptr; if (op_get_compute(opcode) == 0) return; @@ -5635,7 +5624,7 @@ void adsp21062_device::generate_shift_imm(drcuml_block &block, compiler_state &c case 0x13: // FDEP Rx BY <bit6>:<len6> (SE) case 0x1b: // Rn = Rn OR FDEP Rx BY <bit6>:<len6> (SE) UML_MOV(block, mem(&m_core->pc), desc->pc); - UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]); + UML_DMOV(block, mem(&m_core->arg64), desc->opptr); UML_CALLC(block, cfunc_unimplemented_shiftimm, this); break; @@ -5811,7 +5800,7 @@ void adsp21062_device::generate_shift_imm(drcuml_block &block, compiler_state &c default: UML_MOV(block, mem(&m_core->pc), desc->pc); - UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]); + UML_DMOV(block, mem(&m_core->arg64), desc->opptr); UML_CALLC(block, cfunc_unimplemented_compute, this); return; } diff --git a/src/devices/cpu/sharc/sharcfe.cpp b/src/devices/cpu/sharc/sharcfe.cpp index ff0074b02bf..6fee42cf68d 100644 --- a/src/devices/cpu/sharc/sharcfe.cpp +++ b/src/devices/cpu/sharc/sharcfe.cpp @@ -12,92 +12,47 @@ #include "sharcinternal.ipp" +#include "cpu/drcfe.ipp" -#define REG_USED(desc,x) do { (desc).regin[0] |= 1 << (x); } while(0) -#define REG_MODIFIED(desc,x) do { (desc).regout[0] |= 1 << (x); } while(0) - -#define AZ_USED(desc) do { (desc).regin[0] |= 1 << 16; } while(0) -#define AZ_MODIFIED(desc) do { (desc).regout[0] |= 1 << 16; } while(0) -#define AV_USED(desc) do { (desc).regin[0] |= 1 << 17; } while(0) -#define AV_MODIFIED(desc) do { (desc).regout[0] |= 1 << 17; } while(0) -#define AN_USED(desc) do { (desc).regin[0] |= 1 << 18; } while(0) -#define AN_MODIFIED(desc) do { (desc).regout[0] |= 1 << 18; } while(0) -#define AC_USED(desc) do { (desc).regin[0] |= 1 << 19; } while(0) -#define AC_MODIFIED(desc) do { (desc).regout[0] |= 1 << 19; } while(0) -#define AS_USED(desc) do { (desc).regin[0] |= 1 << 20; } while(0) -#define AS_MODIFIED(desc) do { (desc).regout[0] |= 1 << 20; } while(0) -#define AI_USED(desc) do { (desc).regin[0] |= 1 << 21; } while(0) -#define AI_MODIFIED(desc) do { (desc).regout[0] |= 1 << 21; } while(0) -#define MN_USED(desc) do { (desc).regin[0] |= 1 << 22; } while(0) -#define MN_MODIFIED(desc) do { (desc).regout[0] |= 1 << 22; } while(0) -#define MV_USED(desc) do { (desc).regin[0] |= 1 << 23; } while(0) -#define MV_MODIFIED(desc) do { (desc).regout[0] |= 1 << 23; } while(0) -#define MU_USED(desc) do { (desc).regin[0] |= 1 << 24; } while(0) -#define MU_MODIFIED(desc) do { (desc).regout[0] |= 1 << 24; } while(0) -#define MI_USED(desc) do { (desc).regin[0] |= 1 << 25; } while(0) -#define MI_MODIFIED(desc) do { (desc).regout[0] |= 1 << 25; } while(0) -#define SV_USED(desc) do { (desc).regin[0] |= 1 << 26; } while(0) -#define SV_MODIFIED(desc) do { (desc).regout[0] |= 1 << 26; } while(0) -#define SZ_USED(desc) do { (desc).regin[0] |= 1 << 27; } while(0) -#define SZ_MODIFIED(desc) do { (desc).regout[0] |= 1 << 27; } while(0) -#define SS_USED(desc) do { (desc).regin[0] |= 1 << 28; } while(0) -#define SS_MODIFIED(desc) do { (desc).regout[0] |= 1 << 28; } while(0) -#define BTF_USED(desc) do { (desc).regin[0] |= 1 << 29; } while(0) -#define BTF_MODIFIED(desc) do { (desc).regout[0] |= 1 << 29; } while(0) -#define AF_USED(desc) do { (desc).regin[0] |= 1 << 30; } while(0) -#define AF_MODIFIED(desc) do { (desc).regout[0] |= 1 << 30; } while(0) - -#define ALU_FLAGS_MODIFIED(desc) do { AZ_MODIFIED(desc);AN_MODIFIED(desc);AV_MODIFIED(desc);AC_MODIFIED(desc);AS_MODIFIED(desc);AI_MODIFIED(desc); } while(0) -#define MULT_FLAGS_MODIFIED(desc) do { MN_MODIFIED(desc);MV_MODIFIED(desc);MU_MODIFIED(desc);MI_MODIFIED(desc); } while(0) -#define SHIFT_FLAGS_MODIFIED(desc) do { SZ_MODIFIED(desc);SV_MODIFIED(desc);SS_MODIFIED(desc); } while(0) - - -#define PM_I_USED(desc,x) do { (desc).regin[1] |= 1 << (x); } while(0) -#define PM_I_MODIFIED(desc,x) do { (desc).regout[1] |= 1 << (x); } while(0) -#define PM_M_USED(desc,x) do { (desc).regin[1] |= 1 << ((x) + 8); } while(0) -#define PM_M_MODIFIED(desc,x) do { (desc).regout[1] |= 1 << ((x) + 8); } while(0) -#define PM_B_USED(desc,x) do { (desc).regin[1] |= 1 << ((x) + 16); } while(0) -#define PM_B_MODIFIED(desc,x) do { (desc).regout[1] |= 1 << ((x) + 16); } while(0) -#define PM_L_USED(desc,x) do { (desc).regin[1] |= 1 << ((x) + 24); } while(0) -#define PM_L_MODIFIED(desc,x) do { (desc).regout[1] |= 1 << ((x) + 24); } while(0) - -#define DM_I_USED(desc,x) do { (desc).regin[2] |= 1 << (x); } while(0) -#define DM_I_MODIFIED(desc,x) do { (desc).regout[2] |= 1 << (x); } while(0) -#define DM_M_USED(desc,x) do { (desc).regin[2] |= 1 << ((x) + 8); } while(0) -#define DM_M_MODIFIED(desc,x) do { (desc).regout[2] |= 1 << ((x) + 8); } while(0) -#define DM_B_USED(desc,x) do { (desc).regin[2] |= 1 << ((x) + 16); } while(0) -#define DM_B_MODIFIED(desc,x) do { (desc).regout[2] |= 1 << ((x) + 16); } while(0) -#define DM_L_USED(desc,x) do { (desc).regin[2] |= 1 << ((x) + 24); } while(0) -#define DM_L_MODIFIED(desc,x) do { (desc).regout[2] |= 1 << ((x) + 24); } while(0) - - -sharc_frontend::sharc_frontend(adsp21062_device *sharc, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) - : drc_frontend(*sharc, window_start, window_end, max_sequence) + +adsp21062_device::frontend::frontend(adsp21062_device *sharc, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) + : drc_frontend_base(sharc->space_config(AS_PROGRAM)->page_shift(), window_start, window_end, max_sequence) , m_sharc(sharc) { m_loopmap = std::make_unique<LOOP_ENTRY[]>(0x20000); } +adsp21062_device::frontend::~frontend() +{ +} -void sharc_frontend::flush() +adsp21062_device::opcode_desc const *adsp21062_device::frontend::describe_code(offs_t startpc) { - LOOP_ENTRY* map = m_loopmap.get(); + return do_describe_code( + [this] (opcode_desc &desc, opcode_desc const *prev) { return describe(desc, prev); }, + startpc); +} + + +void adsp21062_device::frontend::flush() +{ + LOOP_ENTRY *map = m_loopmap.get(); memset(map, 0, sizeof(LOOP_ENTRY) * 0x20000); } -void sharc_frontend::add_loop_entry(uint32_t pc, uint8_t type, uint32_t userflags) +void adsp21062_device::frontend::add_loop_entry(uint32_t pc, uint8_t type, opcode_desc::extra_flags const &userflags) { uint32_t l2 = pc >> 17; uint32_t l1 = pc & 0x1ffff; if (l2 != 0x1) - fatalerror("sharc_frontend::add_loop_entry: PC = %08X", pc); + fatalerror("adsp21062_device::frontend::add_loop_entry: PC = %08X", pc); LOOP_ENTRY* map = m_loopmap.get(); uint32_t current_type = map[l1].entrytype; - uint32_t current_userflags = map[l1].userflags; + opcode_desc::extra_flags current_userflags = map[l1].userflags; current_type |= type; current_userflags |= userflags; @@ -106,28 +61,29 @@ void sharc_frontend::add_loop_entry(uint32_t pc, uint8_t type, uint32_t userflag map[l1].userflags = current_userflags; } -void sharc_frontend::insert_loop(const LOOP_DESCRIPTOR &loopdesc) +void adsp21062_device::frontend::insert_loop(const LOOP_DESCRIPTOR &loopdesc) { add_loop_entry(loopdesc.start_pc, LOOP_ENTRY_START, 0); add_loop_entry(loopdesc.end_pc, LOOP_ENTRY_EVALUATION, 0); if (loopdesc.astat_check_pc != 0xffffffff) { uint32_t flags = m_sharc->do_condition_astat_bits(loopdesc.condition); - uint32_t userflags = 0; - if (flags & adsp21062_device::ASTAT_FLAGS::AZ) { userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_AZ; } - if (flags & adsp21062_device::ASTAT_FLAGS::AN) { userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_AN; } - if (flags & adsp21062_device::ASTAT_FLAGS::AV) { userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_AV; } - if (flags & adsp21062_device::ASTAT_FLAGS::AC) { userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_AC; } - if (flags & adsp21062_device::ASTAT_FLAGS::MN) { userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_MN; } - if (flags & adsp21062_device::ASTAT_FLAGS::MV) { userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_MV; } - if (flags & adsp21062_device::ASTAT_FLAGS::SV) { userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_SV; } - if (flags & adsp21062_device::ASTAT_FLAGS::SZ) { userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_SZ; } - if (flags & adsp21062_device::ASTAT_FLAGS::BTF) { userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_BTF; } + opcode_desc::extra_flags userflags; + userflags.reset(); + if (flags & AZ) { userflags.set(opcode_desc::ASTAT_DELAY_COPY_AZ); } + if (flags & AN) { userflags.set(opcode_desc::ASTAT_DELAY_COPY_AN); } + if (flags & AV) { userflags.set(opcode_desc::ASTAT_DELAY_COPY_AV); } + if (flags & AC) { userflags.set(opcode_desc::ASTAT_DELAY_COPY_AC); } + if (flags & MN) { userflags.set(opcode_desc::ASTAT_DELAY_COPY_MN); } + if (flags & MV) { userflags.set(opcode_desc::ASTAT_DELAY_COPY_MV); } + if (flags & SV) { userflags.set(opcode_desc::ASTAT_DELAY_COPY_SV); } + if (flags & SZ) { userflags.set(opcode_desc::ASTAT_DELAY_COPY_SZ); } + if (flags & BTF) { userflags.set(opcode_desc::ASTAT_DELAY_COPY_BTF); } add_loop_entry(loopdesc.astat_check_pc, LOOP_ENTRY_ASTAT_CHECK, userflags); } } -bool sharc_frontend::is_loop_evaluation(uint32_t pc) +bool adsp21062_device::frontend::is_loop_evaluation(uint32_t pc) { uint32_t l2 = pc >> 17; uint32_t l1 = pc & 0x1ffff; @@ -142,7 +98,7 @@ bool sharc_frontend::is_loop_evaluation(uint32_t pc) return false; } -bool sharc_frontend::is_loop_start(uint32_t pc) +bool adsp21062_device::frontend::is_loop_start(uint32_t pc) { uint32_t l2 = pc >> 17; uint32_t l1 = pc & 0x1ffff; @@ -157,7 +113,7 @@ bool sharc_frontend::is_loop_start(uint32_t pc) return false; } -bool sharc_frontend::is_astat_delay_check(uint32_t pc) +bool adsp21062_device::frontend::is_astat_delay_check(uint32_t pc) { uint32_t l2 = pc >> 17; uint32_t l1 = pc & 0x1ffff; @@ -173,39 +129,38 @@ bool sharc_frontend::is_astat_delay_check(uint32_t pc) } -bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) +bool adsp21062_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) { - uint64_t opcode = desc.opptr.q[0] = m_sharc->pm_read48(desc.physpc); + uint64_t opcode = desc.opptr = m_sharc->pm_read48(desc.pc); desc.length = 1; - desc.cycles = 1; // handle looping if (is_astat_delay_check(desc.pc)) { - LOOP_ENTRY* map = m_loopmap.get(); + LOOP_ENTRY *map = m_loopmap.get(); int index = desc.pc & 0x1ffff; - desc.userflags |= map[index].userflags; - if (map[index].userflags & OP_USERFLAG_ASTAT_DELAY_COPY_AZ) { AZ_USED(desc); } - if (map[index].userflags & OP_USERFLAG_ASTAT_DELAY_COPY_AN) { AN_USED(desc); } - if (map[index].userflags & OP_USERFLAG_ASTAT_DELAY_COPY_AV) { AV_USED(desc); } - if (map[index].userflags & OP_USERFLAG_ASTAT_DELAY_COPY_AC) { AC_USED(desc); } - if (map[index].userflags & OP_USERFLAG_ASTAT_DELAY_COPY_MN) { MN_USED(desc); } - if (map[index].userflags & OP_USERFLAG_ASTAT_DELAY_COPY_MV) { MV_USED(desc); } - if (map[index].userflags & OP_USERFLAG_ASTAT_DELAY_COPY_SV) { SV_USED(desc); } - if (map[index].userflags & OP_USERFLAG_ASTAT_DELAY_COPY_SZ) { SZ_USED(desc); } - if (map[index].userflags & OP_USERFLAG_ASTAT_DELAY_COPY_BTF) { BTF_USED(desc); } + desc.set_extra_flags(map[index].userflags); + if (map[index].userflags[opcode_desc::ASTAT_DELAY_COPY_AZ]) { desc.set_az_used(); } + if (map[index].userflags[opcode_desc::ASTAT_DELAY_COPY_AN]) { desc.set_an_used(); } + if (map[index].userflags[opcode_desc::ASTAT_DELAY_COPY_AV]) { desc.set_av_used(); } + if (map[index].userflags[opcode_desc::ASTAT_DELAY_COPY_AC]) { desc.set_ac_used(); } + if (map[index].userflags[opcode_desc::ASTAT_DELAY_COPY_MN]) { desc.set_mn_used(); } + if (map[index].userflags[opcode_desc::ASTAT_DELAY_COPY_MV]) { desc.set_mv_used(); } + if (map[index].userflags[opcode_desc::ASTAT_DELAY_COPY_SV]) { desc.set_sv_used(); } + if (map[index].userflags[opcode_desc::ASTAT_DELAY_COPY_SZ]) { desc.set_sz_used(); } + if (map[index].userflags[opcode_desc::ASTAT_DELAY_COPY_BTF]) { desc.set_btf_used(); } } if (is_loop_start(desc.pc)) { - desc.flags |= OPFLAG_IS_BRANCH_TARGET; + desc.set_is_branch_target(); } if (is_loop_evaluation(desc.pc)) { - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; - desc.userflags |= OP_USERFLAG_LOOP; + desc.set_is_conditional_branch(); + desc.set_loop(); } @@ -220,7 +175,7 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) if (opcode & 0x008000000000U) { // IDLE - desc.flags |= OPFLAG_END_SEQUENCE; + desc.set_end_sequence(); } else { @@ -267,16 +222,16 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) if (g) { // PM - PM_I_USED(desc, i); - PM_I_MODIFIED(desc, i); - PM_M_USED(desc, m); + desc.set_pm_i_used(i); + desc.set_pm_i_modified(i); + desc.set_pm_m_used(m); } else { // DM - DM_I_USED(desc, i); - DM_I_MODIFIED(desc, i); - DM_M_USED(desc, m); + desc.set_dm_i_used(i); + desc.set_dm_i_modified(i); + desc.set_dm_m_used(m); } break; } @@ -289,16 +244,21 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) uint32_t const address = opcode & 0xffffff; if (m_sharc->if_condition_always_true(cond)) - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + { + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } else - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + { + desc.set_is_conditional_branch(); + } describe_if_condition(desc, cond); desc.targetpc = address; - desc.delayslots = (j) ? 2 : 0; + desc.delayslots = j ? 2 : 0; - desc.userflags |= (b) ? OP_USERFLAG_CALL : 0; + if (b) desc.set_call(); break; } @@ -310,16 +270,21 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) uint32_t const address = opcode & 0xffffff; if (m_sharc->if_condition_always_true(cond)) - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + { + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } else - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + { + desc.set_is_conditional_branch(); + } describe_if_condition(desc, cond); desc.targetpc = desc.pc + util::sext(address, 24); - desc.delayslots = (j) ? 2 : 0; + desc.delayslots = j ? 2 : 0; - desc.userflags |= (b) ? OP_USERFLAG_CALL : 0; + if (b) desc.set_call(); break; } @@ -335,19 +300,24 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) return false; if (m_sharc->if_condition_always_true(cond)) - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + { + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } else - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + { + desc.set_is_conditional_branch(); + } describe_if_condition(desc, cond); - PM_I_USED(desc, pmi); - PM_M_USED(desc, pmm); + desc.set_pm_i_used(pmi); + desc.set_pm_m_used(pmm); desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.delayslots = (j) ? 2 : 0; + desc.delayslots = j ? 2 : 0; - desc.userflags |= (b) ? OP_USERFLAG_CALL : 0; + if (b) desc.set_call(); break; } @@ -361,16 +331,21 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) return false; if (m_sharc->if_condition_always_true(cond)) - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + { + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } else - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + { + desc.set_is_conditional_branch(); + } describe_if_condition(desc, cond); desc.targetpc = desc.pc + op_get_reladdr(opcode); - desc.delayslots = (j) ? 2 : 0; + desc.delayslots = j ? 2 : 0; - desc.userflags |= (b) ? OP_USERFLAG_CALL : 0; + if (b) desc.set_call(); break; } @@ -383,14 +358,19 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) return false; if (m_sharc->if_condition_always_true(cond)) - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + { + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } else - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + { + desc.set_is_conditional_branch(); + } describe_if_condition(desc, cond); desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.delayslots = (j) ? 2 : 0; + desc.delayslots = j ? 2 : 0; break; } @@ -403,14 +383,19 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) return false; if (m_sharc->if_condition_always_true(cond)) - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + { + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } else - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + { + desc.set_is_conditional_branch(); + } describe_if_condition(desc, cond); desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.delayslots = (j) ? 2 : 0; + desc.delayslots = j ? 2 : 0; break; } @@ -473,7 +458,6 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) else loop.astat_check_pc = loop.end_pc; - insert_loop(loop); break; } @@ -497,13 +481,13 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) { if (!describe_ureg_access(desc, ureg, UREG_READ)) return false; - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); } else { if (!describe_ureg_access(desc, ureg, UREG_WRITE)) return false; - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); } break; } @@ -518,79 +502,98 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) { case 0: // SET case 1: // CLEAR + if (sreg == 0x7c) // ASTAT + { + if (data & AZ) desc.set_az_modified(); + if (data & AV) desc.set_av_modified(); + if (data & AN) desc.set_an_modified(); + if (data & AC) desc.set_ac_modified(); + if (data & AS) desc.set_as_modified(); + if (data & AI) desc.set_ai_modified(); + if (data & MN) desc.set_mn_modified(); + if (data & MV) desc.set_mv_modified(); + if (data & MU) desc.set_mu_modified(); + if (data & MI) desc.set_mi_modified(); + if (data & SV) desc.set_sv_modified(); + if (data & SZ) desc.set_sz_modified(); + if (data & SS) desc.set_ss_modified(); + if (data & BTF) desc.set_btf_modified(); + if (data & AF) desc.set_af_modified(); + } + break; case 2: // TOGGLE if (sreg == 0x7c) // ASTAT { - if (data & adsp21062_device::AZ) + if (data & AZ) { - AZ_USED(desc); AZ_MODIFIED(desc); + desc.set_az_used(); desc.set_az_modified(); } - if (data & adsp21062_device::AV) + if (data & AV) { - AV_USED(desc); AV_MODIFIED(desc); + desc.set_av_used(); desc.set_av_modified(); } - if (data & adsp21062_device::AN) + if (data & AN) { - AN_USED(desc); AN_MODIFIED(desc); + desc.set_an_used(); desc.set_an_modified(); } - if (data & adsp21062_device::AC) + if (data & AC) { - AC_USED(desc); AC_MODIFIED(desc); + desc.set_ac_used(); desc.set_ac_modified(); } - if (data & adsp21062_device::AS) + if (data & AS) { - AS_USED(desc); AS_MODIFIED(desc); + desc.set_as_used(); desc.set_as_modified(); } - if (data & adsp21062_device::AI) + if (data & AI) { - AI_USED(desc); AI_MODIFIED(desc); + desc.set_ai_used(); desc.set_ai_modified(); } - if (data & adsp21062_device::MN) + if (data & MN) { - MN_USED(desc); MN_MODIFIED(desc); + desc.set_mn_used(); desc.set_mn_modified(); } - if (data & adsp21062_device::MV) + if (data & MV) { - MV_USED(desc); MV_MODIFIED(desc); + desc.set_mv_used(); desc.set_mv_modified(); } - if (data & adsp21062_device::MU) + if (data & MU) { - MU_USED(desc); MU_MODIFIED(desc); + desc.set_mu_used(); desc.set_mu_modified(); } - if (data & adsp21062_device::MI) + if (data & MI) { - MI_USED(desc); MI_MODIFIED(desc); + desc.set_mi_used(); desc.set_mi_modified(); } - if (data & adsp21062_device::SV) + if (data & SV) { - SV_USED(desc); SV_MODIFIED(desc); + desc.set_sv_used(); desc.set_sv_modified(); } - if (data & adsp21062_device::SZ) + if (data & SZ) { - SZ_USED(desc); SZ_MODIFIED(desc); + desc.set_sz_used(); desc.set_sz_modified(); } - if (data & adsp21062_device::SS) + if (data & SS) { - SS_USED(desc); SS_MODIFIED(desc); + desc.set_ss_used(); desc.set_ss_modified(); } - if (data & adsp21062_device::BTF) + if (data & BTF) { - BTF_USED(desc); BTF_MODIFIED(desc); + desc.set_btf_used(); desc.set_btf_modified(); } - if (data & adsp21062_device::AF) + if (data & AF) { - AF_USED(desc); AF_MODIFIED(desc); + desc.set_af_used(); desc.set_af_modified(); } } break; case 4: // TEST case 5: // XOR - BTF_MODIFIED(desc); + desc.set_btf_modified(); break; default: - fatalerror("sharc_frontend::describe: system reg bit manipulation %d", bop); + fatalerror("adsp21062_device::frontend::describe: system reg bit manipulation %d", bop); return false; } break; @@ -600,7 +603,7 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) { if (opcode & 0x008000000000U) // bit reverse { - fatalerror("sharc_frontend::describe: bit reverse unimplemented"); + fatalerror("adsp21062_device::frontend::describe: bit reverse unimplemented"); } else // modify { @@ -608,9 +611,9 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) int const i = (opcode >> 32) & 0x7; if (g) - PM_I_USED(desc, i); + desc.set_pm_i_used(i); else - DM_I_USED(desc, i); + desc.set_dm_i_used(i); } break; } @@ -619,15 +622,15 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) break; case 0x18: // cjump |000|11000| - fatalerror("sharc_frontend::describe: cjump unimplemented"); + fatalerror("adsp21062_device::frontend::describe: cjump unimplemented"); break; case 0x19: // rframe |000|11001| - fatalerror("sharc_frontend::describe: rframe unimplemented"); + fatalerror("adsp21062_device::frontend::describe: rframe unimplemented"); break; default: - fatalerror("sharc_frontend::describe: unknown subop %02X in opcode %04X%08X", subop, (uint16_t)(opcode >> 32), (uint32_t)(opcode)); + fatalerror("adsp21062_device::frontend::describe: unknown subop %02X in opcode %04X%08X", subop, (uint16_t)(opcode >> 32), (uint32_t)(opcode)); return false; } break; @@ -647,34 +650,34 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) int const pmd = (opcode >> 37) & 0x1; int const dmd = (opcode >> 44) & 0x1; - PM_I_USED(desc, pmi); - PM_I_MODIFIED(desc, pmi); - PM_M_USED(desc, pmm); + desc.set_pm_i_used(pmi); + desc.set_pm_i_modified(pmi); + desc.set_pm_m_used(pmm); if (pmd) { - REG_USED(desc, pm_dreg); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_reg_used(pm_dreg); + desc.set_writes_memory(); } else { - REG_MODIFIED(desc, pm_dreg); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reg_modified(pm_dreg); + desc.set_reads_memory(); } - DM_I_USED(desc, dmi); - DM_I_MODIFIED(desc, dmi); - DM_M_USED(desc, dmm); + desc.set_dm_i_used(dmi); + desc.set_dm_i_modified(dmi); + desc.set_dm_m_used(dmm); if (dmd) { - REG_USED(desc, dm_dreg); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_reg_used(dm_dreg); + desc.set_writes_memory(); } else { - REG_MODIFIED(desc, dm_dreg); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reg_modified(dm_dreg); + desc.set_reads_memory(); } break; } @@ -697,26 +700,26 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) { if (!describe_ureg_access(desc, ureg, UREG_READ)) return false; - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); } else { if (!describe_ureg_access(desc, ureg, UREG_WRITE)) return false; - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_writes_memory(); } if (g) { // PM - PM_I_USED(desc, i); - PM_M_USED(desc, m); + desc.set_pm_i_used(i); + desc.set_pm_m_used(m); } else { // DM - DM_I_USED(desc, i); - DM_M_USED(desc, m); + desc.set_dm_i_used(i); + desc.set_dm_m_used(m); } break; @@ -753,33 +756,33 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) if (d) { - REG_USED(desc, dreg); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_reg_used(dreg); + desc.set_writes_memory(); } else { - REG_MODIFIED(desc, dreg); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reg_modified(dreg); + desc.set_reads_memory(); } if (g) { // PM - PM_I_USED(desc, i); + desc.set_pm_i_used(i); if (u) // post-modify with update { - PM_I_MODIFIED(desc, i); + desc.set_pm_i_modified(i); } } else { // DM - DM_I_USED(desc, i); + desc.set_dm_i_used(i); if (u) // post-modify with update { - DM_I_MODIFIED(desc, i); + desc.set_dm_i_modified(i); } } } @@ -794,21 +797,21 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) int const m = (opcode >> 38) & 0x7; int const g = (opcode >> 37) & 0x1; - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); if (g) { // PM - PM_I_USED(desc, i); - PM_I_MODIFIED(desc, i); - PM_M_USED(desc, m); + desc.set_pm_i_used(i); + desc.set_pm_i_modified(i); + desc.set_pm_m_used(m); } else { // DM - DM_I_USED(desc, i); - DM_I_MODIFIED(desc, i); - DM_M_USED(desc, m); + desc.set_dm_i_used(i); + desc.set_dm_i_modified(i); + desc.set_dm_m_used(m); } } else // immediate shift / dreg <-> DM|PM |100|0| @@ -830,28 +833,28 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) if (d) { - REG_USED(desc, dreg); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_reg_used(dreg); + desc.set_writes_memory(); } else { - REG_MODIFIED(desc, dreg); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reg_modified(dreg); + desc.set_reads_memory(); } if (g) { // PM - PM_I_USED(desc, i); - PM_I_MODIFIED(desc, i); - PM_M_USED(desc, m); + desc.set_pm_i_used(i); + desc.set_pm_i_modified(i); + desc.set_pm_m_used(m); } else { // DM - DM_I_USED(desc, i); - DM_I_MODIFIED(desc, i); - DM_M_USED(desc, m); + desc.set_dm_i_used(i); + desc.set_dm_i_modified(i); + desc.set_dm_m_used(m); } } break; @@ -868,19 +871,19 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) { if (!describe_ureg_access(desc, ureg, UREG_READ)) return false; - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); } else { if (!describe_ureg_access(desc, ureg, UREG_WRITE)) return false; - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); } if (g) - PM_I_USED(desc, i); + desc.set_pm_i_used(i); else - DM_I_USED(desc, i); + desc.set_dm_i_used(i); break; } @@ -898,27 +901,32 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) return false; if (m_sharc->if_condition_always_true(cond)) - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + { + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } else - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + { + desc.set_is_conditional_branch(); + } describe_if_condition(desc, cond); - PM_I_USED(desc, pmi); - PM_M_USED(desc, pmm); - DM_I_USED(desc, dmi); - DM_I_MODIFIED(desc, dmi); - DM_M_USED(desc, dmm); + desc.set_pm_i_used(pmi); + desc.set_pm_m_used(pmm); + desc.set_dm_i_used(dmi); + desc.set_dm_i_modified(dmi); + desc.set_dm_m_used(dmm); if (d) { - REG_USED(desc, dreg); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_reg_used(dreg); + desc.set_writes_memory(); } else { - REG_MODIFIED(desc, dreg); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reg_modified(dreg); + desc.set_reads_memory(); } desc.targetpc = BRANCH_TARGET_DYNAMIC; @@ -938,25 +946,30 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) return false; if (m_sharc->if_condition_always_true(cond)) - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + { + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } else - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + { + desc.set_is_conditional_branch(); + } describe_if_condition(desc, cond); - DM_I_USED(desc, dmi); - DM_I_MODIFIED(desc, dmi); - DM_M_USED(desc, dmm); + desc.set_dm_i_used(dmi); + desc.set_dm_i_modified(dmi); + desc.set_dm_m_used(dmm); if (d) { - REG_USED(desc, dreg); - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_reg_used(dreg); + desc.set_writes_memory(); } else { - REG_MODIFIED(desc, dreg); - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reg_modified(dreg); + desc.set_reads_memory(); } desc.targetpc = desc.pc + op_get_reladdr(opcode); @@ -968,7 +981,7 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) return true; } -bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) +bool adsp21062_device::frontend::describe_compute(opcode_desc &desc, uint64_t opcode) { // skip if no-op if ((opcode & 0x7fffff) == 0) @@ -993,80 +1006,80 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) switch (multiop) { case 0x00: // Rn = MRxx - REG_MODIFIED(desc, rn); + desc.set_reg_modified(rn); break; case 0x01: // MRxx = Rn - REG_USED(desc, rn); + desc.set_reg_used(rn); break; case 0x07: // Ra = Rx + Ry, Rs = Rx - Ry case 0x0f: // Fa = Fx + Fy, Fs = Fx - Fy - REG_USED(desc, rx); - REG_USED(desc, ry); - REG_MODIFIED(desc, ra); - REG_MODIFIED(desc, rs); - ALU_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_reg_modified(ra); + desc.set_reg_modified(rs); + desc.set_alu_flags_modified(); break; case 0x04: // Rm = R3-0 * R7-4 (SSFR), Ra = R11-8 + R15-12 case 0x05: // Rm = R3-0 * R7-4 (SSFR), Ra = R11-8 - R15-12 case 0x06: // Rm = R3-0 * R7-4 (SSFR), Ra = (R11-8 + R15-12) / 2 - REG_USED(desc, fxm); - REG_USED(desc, fym); - REG_USED(desc, fxa); - REG_USED(desc, fya); - REG_MODIFIED(desc, fm); - REG_MODIFIED(desc, fa); - ALU_FLAGS_MODIFIED(desc); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(fxm); + desc.set_reg_used(fym); + desc.set_reg_used(fxa); + desc.set_reg_used(fya); + desc.set_reg_modified(fm); + desc.set_reg_modified(fa); + desc.set_alu_flags_modified(); + desc.set_mult_flags_modified(); break; case 0x08: // MRF = MRF + R3-0 * R7-4 (SSF), Ra = R11-8 + R15-12 case 0x09: // MRF = MRF + R3-0 * R7-4 (SSF), Ra = R11-8 - R15-12 case 0x0a: // MRF = MRF + R3-0 * R7-4 (SSF), Ra = (R11-8 + R15-12) / 2 - REG_USED(desc, fxm); - REG_USED(desc, fym); - REG_USED(desc, fxa); - REG_USED(desc, fya); - ALU_FLAGS_MODIFIED(desc); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(fxm); + desc.set_reg_used(fym); + desc.set_reg_used(fxa); + desc.set_reg_used(fya); + desc.set_alu_flags_modified(); + desc.set_mult_flags_modified(); break; case 0x0c: // Rm = MRF + R3-0 * R7-4 (SSFR), Ra = R11-8 + R15-12 case 0x0d: // Rm = MRF + R3-0 * R7-4 (SSFR), Ra = R11-8 - R15-12 case 0x0e: // Rm = MRF + R3-0 * R7-4 (SSFR), Ra = (R11-8 + R15-12) / 2 - REG_USED(desc, fxm); - REG_USED(desc, fym); - REG_USED(desc, fxa); - REG_USED(desc, fya); - REG_MODIFIED(desc, fm); - REG_MODIFIED(desc, fa); - ALU_FLAGS_MODIFIED(desc); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(fxm); + desc.set_reg_used(fym); + desc.set_reg_used(fxa); + desc.set_reg_used(fya); + desc.set_reg_modified(fm); + desc.set_reg_modified(fa); + desc.set_alu_flags_modified(); + desc.set_mult_flags_modified(); break; case 0x10: // MRF = MRF - R3-0 * R7-4 (SSF), Ra = R11-8 + R15-12 case 0x11: // MRF = MRF - R3-0 * R7-4 (SSF), Ra = R11-8 - R15-12 case 0x12: // MRF = MRF - R3-0 * R7-4 (SSF), Ra = (R11-8 + R15-12) / 2 - REG_USED(desc, fxm); - REG_USED(desc, fym); - REG_USED(desc, fxa); - REG_USED(desc, fya); - ALU_FLAGS_MODIFIED(desc); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(fxm); + desc.set_reg_used(fym); + desc.set_reg_used(fxa); + desc.set_reg_used(fya); + desc.set_alu_flags_modified(); + desc.set_mult_flags_modified(); break; case 0x14: // Rm = MRF - R3-0 * R7-4 (SSFR), Ra = R11-8 + R15-12 case 0x15: // Rm = MRF - R3-0 * R7-4 (SSFR), Ra = R11-8 - R15-12 case 0x16: // Rm = MRF - R3-0 * R7-4 (SSFR), Ra = (R11-8 + R15-12) / 2 - REG_USED(desc, fxm); - REG_USED(desc, fym); - REG_USED(desc, fxa); - REG_USED(desc, fya); - REG_MODIFIED(desc, fm); - REG_MODIFIED(desc, fa); - ALU_FLAGS_MODIFIED(desc); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(fxm); + desc.set_reg_used(fym); + desc.set_reg_used(fxa); + desc.set_reg_used(fya); + desc.set_reg_modified(fm); + desc.set_reg_modified(fa); + desc.set_alu_flags_modified(); + desc.set_mult_flags_modified(); break; case 0x18: // Fm = F3-0 * F7-4, Fa = F11-8 + F15-12 @@ -1076,56 +1089,56 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0x1c: // Fm = F3-0 * F7-4, Fa = (F11-8 + F15-12) / 2 case 0x1e: // Fm = F3-0 * F7-4, Fa = MAX(F11-8, F15-12) case 0x1f: // Fm = F3-0 * F7-4, Fa = MIN(F11-8, F15-12) - REG_USED(desc, fxm); - REG_USED(desc, fym); - REG_USED(desc, fxa); - REG_USED(desc, fya); - REG_MODIFIED(desc, fm); - REG_MODIFIED(desc, fa); - ALU_FLAGS_MODIFIED(desc); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(fxm); + desc.set_reg_used(fym); + desc.set_reg_used(fxa); + desc.set_reg_used(fya); + desc.set_reg_modified(fm); + desc.set_reg_modified(fa); + desc.set_alu_flags_modified(); + desc.set_mult_flags_modified(); break; case 0x1d: // Fm = F3-0 * F7-4, Fa = ABS F11-8 - REG_USED(desc, fxm); - REG_USED(desc, fym); - REG_USED(desc, fxa); - REG_MODIFIED(desc, fm); - REG_MODIFIED(desc, fa); - ALU_FLAGS_MODIFIED(desc); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(fxm); + desc.set_reg_used(fym); + desc.set_reg_used(fxa); + desc.set_reg_modified(fm); + desc.set_reg_modified(fa); + desc.set_alu_flags_modified(); + desc.set_mult_flags_modified(); break; case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: // Rm = R3-0 * R7-4 (SSFR), Ra = R11-8 + R15-12, Rs = R11-8 - R15-12 - REG_USED(desc, fxm); - REG_USED(desc, fym); - REG_USED(desc, fxa); - REG_USED(desc, fya); - REG_MODIFIED(desc, fm); - REG_MODIFIED(desc, fa); - REG_MODIFIED(desc, (opcode >> 16) & 0xf); - ALU_FLAGS_MODIFIED(desc); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(fxm); + desc.set_reg_used(fym); + desc.set_reg_used(fxa); + desc.set_reg_used(fya); + desc.set_reg_modified(fm); + desc.set_reg_modified(fa); + desc.set_reg_modified((opcode >> 16) & 0xf); + desc.set_alu_flags_modified(); + desc.set_mult_flags_modified(); break; case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: // Fm = F3-0 * F7-4, Fa = F11-8 + F15-12, Fs = F11-8 - F15-12 - REG_USED(desc, fxm); - REG_USED(desc, fym); - REG_USED(desc, fxa); - REG_USED(desc, fya); - REG_MODIFIED(desc, fm); - REG_MODIFIED(desc, fa); - REG_MODIFIED(desc, (opcode >> 16) & 0xf); - ALU_FLAGS_MODIFIED(desc); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(fxm); + desc.set_reg_used(fym); + desc.set_reg_used(fxa); + desc.set_reg_used(fya); + desc.set_reg_modified(fm); + desc.set_reg_modified(fa); + desc.set_reg_modified((opcode >> 16) & 0xf); + desc.set_alu_flags_modified(); + desc.set_mult_flags_modified(); break; default: - fatalerror("sharc_frontend::describe_compute: unknown multiop %02X in opcode %04X%08X at %08X", multiop, (uint16_t)(opcode >> 32), (uint32_t)(opcode), desc.pc); + fatalerror("adsp21062_device::frontend::describe_compute: unknown multiop %02X in opcode %04X%08X at %08X", multiop, (uint16_t)(opcode >> 32), (uint32_t)(opcode), desc.pc); return false; } } @@ -1161,28 +1174,28 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0xe2: // Fn = MAX(Fx, Fy) case 0xe3: // Fn = CLIP Fx BY Fy case 0xe0: // Fn = Fx COPYSIGN Fy - REG_USED(desc, rx); - REG_USED(desc, ry); - REG_MODIFIED(desc, rn); - ALU_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_reg_modified(rn); + desc.set_alu_flags_modified(); break; case 0x05: // Rn = Rx + Ry + CI case 0x06: // Rn = Rx - Ry + CI - 1 case 0x25: // Rn = Rx + CI case 0x26: // Rn = Rx + CI - 1 - REG_USED(desc, rx); - REG_USED(desc, ry); - REG_MODIFIED(desc, rn); - AC_USED(desc); - ALU_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_reg_modified(rn); + desc.set_ac_used(); + desc.set_alu_flags_modified(); break; case 0x0a: // COMP(Rx, Ry) case 0x8a: // COMP(Fx, Fy) - REG_USED(desc, rx); - REG_USED(desc, ry); - ALU_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_alu_flags_modified(); break; case 0x29: // Rn = Rx + 1 @@ -1202,20 +1215,20 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0xca: // Fn = FLOAT Rx case 0xc4: // Fn = RECIPS Fx case 0xc5: // Fn = RSQRTS Fx - REG_USED(desc, rx); - REG_MODIFIED(desc, rn); - ALU_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_modified(rn); + desc.set_alu_flags_modified(); break; case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: { /* Fixed-point Dual Add/Subtract */ - REG_USED(desc, rx); - REG_USED(desc, ry); - REG_MODIFIED(desc, rn); - REG_MODIFIED(desc, ra); - ALU_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_reg_modified(rn); + desc.set_reg_modified(ra); + desc.set_alu_flags_modified(); break; } @@ -1223,16 +1236,16 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: { /* Floating-point Dual Add/Subtract */ - REG_USED(desc, rx); - REG_USED(desc, ry); - REG_MODIFIED(desc, rn); - REG_MODIFIED(desc, ra); - ALU_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_reg_modified(rn); + desc.set_reg_modified(ra); + desc.set_alu_flags_modified(); break; } default: - fatalerror("sharc_frontend::describe_compute: unknown ALU op %02X in opcode %04X%08X at %08X", operation, (uint16_t)(opcode >> 32), (uint32_t)(opcode), desc.pc); + fatalerror("adsp21062_device::frontend::describe_compute: unknown ALU op %02X in opcode %04X%08X at %08X", operation, (uint16_t)(opcode >> 32), (uint32_t)(opcode), desc.pc); return false; } break; @@ -1254,10 +1267,10 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0x70: // Rn = Rx * Ry (SSI) case 0x78: // Rn = Rx * Ry (SSF) case 0x79: // Rn = Rx * Ry (SSFR) - REG_USED(desc, rx); - REG_USED(desc, ry); - REG_MODIFIED(desc, rn); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_reg_modified(rn); + desc.set_mult_flags_modified(); break; case 0x44: // MRF = Rx * Ry (UUI) @@ -1273,9 +1286,9 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0x7c: // MRF = Rx * Ry (SSF) case 0x7d: // MRF = Rx * Ry (SSFR) // TODO: track MRF? - REG_USED(desc, rx); - REG_USED(desc, ry); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_mult_flags_modified(); break; case 0x46: // MRB = Rx * Ry (UUI) @@ -1291,9 +1304,9 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0x7e: // MRB = Rx * Ry (SSF) case 0x7f: // MRB = Rx * Ry (SSFR) // TODO: track MRB? - REG_USED(desc, rx); - REG_USED(desc, ry); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_mult_flags_modified(); break; case 0x80: // Rn = MRF + Rx * Ry (UUI) @@ -1309,10 +1322,10 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0xb8: // Rn = MRF + Rx * Ry (SSF) case 0xb9: // Rn = MRF + Rx * Ry (SSFR) // TODO: track MRF? - REG_USED(desc, rx); - REG_USED(desc, ry); - REG_MODIFIED(desc, rn); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_reg_modified(rn); + desc.set_mult_flags_modified(); break; case 0x82: // Rn = MRB + Rx * Ry (UUI) @@ -1328,10 +1341,10 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0xba: // Rn = MRB + Rx * Ry (SSF) case 0xbb: // Rn = MRB + Rx * Ry (SSFR) // TODO: track MRB? - REG_USED(desc, rx); - REG_USED(desc, ry); - REG_MODIFIED(desc, rn); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_reg_modified(rn); + desc.set_mult_flags_modified(); break; case 0x84: // MRF = MRF + Rx * Ry (UUI) @@ -1347,9 +1360,9 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0xbc: // MRF = MRF + Rx * Ry (SSF) case 0xbd: // MRF = MRF + Rx * Ry (SSFR) // TODO: track MRF? - REG_USED(desc, rx); - REG_USED(desc, ry); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_mult_flags_modified(); break; case 0x86: // MRB = MRB + Rx * Ry (UUI) @@ -1366,9 +1379,9 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0xbf: // MRB = MRB + Rx * Ry (SSFR) break; // TODO: track MRB? - REG_USED(desc, rx); - REG_USED(desc, ry); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_mult_flags_modified(); break; case 0xc0: // Rn = MRF - Rx * Ry (UUI) @@ -1384,10 +1397,10 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0xf8: // Rn = MRF - Rx * Ry (SSF) case 0xf9: // Rn = MRF - Rx * Ry (SSFR) // TODO: track MRF? - REG_USED(desc, rx); - REG_USED(desc, ry); - REG_MODIFIED(desc, rn); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_reg_modified(rn); + desc.set_mult_flags_modified(); break; case 0xc2: // Rn = MRB - Rx * Ry (UUI) @@ -1403,10 +1416,10 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0xfa: // Rn = MRB - Rx * Ry (SSF) case 0xfb: // Rn = MRB - Rx * Ry (SSFR) // TODO: track MRB? - REG_USED(desc, rx); - REG_USED(desc, ry); - REG_MODIFIED(desc, rn); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_reg_modified(rn); + desc.set_mult_flags_modified(); break; case 0xc4: // MRF = MRF - Rx * Ry (UUI) @@ -1422,9 +1435,9 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0xfc: // MRF = MRF - Rx * Ry (SSF) case 0xfd: // MRF = MRF - Rx * Ry (SSFR) // TODO: track MRF? - REG_USED(desc, rx); - REG_USED(desc, ry); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_mult_flags_modified(); break; case 0xc6: // MRB = MRB - Rx * Ry (UUI) @@ -1440,9 +1453,9 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0xfe: // MRB = MRB - Rx * Ry (SSF) case 0xff: // MRB = MRB - Rx * Ry (SSFR) // TODO: track MRB? - REG_USED(desc, rx); - REG_USED(desc, ry); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_mult_flags_modified(); break; case 0x00: // Rn = SAT MRF (UI) @@ -1450,8 +1463,8 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0x08: // Rn = SAT MRF (UF) case 0x09: // Rn = SAT MRF (SF) // TODO: track MRF? - REG_MODIFIED(desc, rn); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_modified(rn); + desc.set_mult_flags_modified(); break; case 0x02: // Rn = SAT MRB (UI) @@ -1459,8 +1472,8 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0x0a: // Rn = SAT MRB (UF) case 0x0b: // Rn = SAT MRB (SF) // TODO: track MRB? - REG_MODIFIED(desc, rn); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_modified(rn); + desc.set_mult_flags_modified(); break; case 0x04: // MRF = SAT MRF (UI) @@ -1468,7 +1481,7 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0x0c: // MRF = SAT MRF (UF) case 0x0d: // MRF = SAT MRF (SF) // TODO: track MRF? - MULT_FLAGS_MODIFIED(desc); + desc.set_mult_flags_modified(); break; case 0x06: // MRB = SAT MRB (UI) @@ -1476,47 +1489,47 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0x0e: // MRB = SAT MRB (UF) case 0x0f: // MRB = SAT MRB (SF) // TODO: track MRB? - MULT_FLAGS_MODIFIED(desc); + desc.set_mult_flags_modified(); break; case 0x18: // Rn = RND MRF (U) case 0x19: // Rn = RND MRF (S) - REG_MODIFIED(desc, rn); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_modified(rn); + desc.set_mult_flags_modified(); break; case 0x1a: // Rn = RND MRB (U) case 0x1b: // Rn = RND MRB (S) - REG_MODIFIED(desc, rn); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_modified(rn); + desc.set_mult_flags_modified(); break; case 0x1c: // MRF = RND MRF (U) case 0x1d: // MRF = RND MRF (S) - MULT_FLAGS_MODIFIED(desc); + desc.set_mult_flags_modified(); break; case 0x1e: // MRB = RND MRB (U) case 0x1f: // MRB = RND MRB (S) - MULT_FLAGS_MODIFIED(desc); + desc.set_mult_flags_modified(); break; case 0x14: // MRF = 0 - MULT_FLAGS_MODIFIED(desc); + desc.set_mult_flags_modified(); break; case 0x16: // MRB = 0 - MULT_FLAGS_MODIFIED(desc); + desc.set_mult_flags_modified(); break; case 0x30: // Fn = Fx * Fy - REG_USED(desc, rx); - REG_USED(desc, ry); - REG_MODIFIED(desc, rn); - MULT_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_reg_modified(rn); + desc.set_mult_flags_modified(); break; default: - fatalerror("sharc_frontend::describe_compute: unknown mult op %02X in opcode %04X%08X at %08X", operation, (uint16_t)(opcode >> 32), (uint32_t)(opcode), desc.pc); + fatalerror("adsp21062_device::frontend::describe_compute: unknown mult op %02X in opcode %04X%08X at %08X", operation, (uint16_t)(opcode >> 32), (uint32_t)(opcode), desc.pc); } break; } @@ -1534,27 +1547,27 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0x4c: // Rn = FDEP Rx BY Ry | <bit6>:<len6> (SE) case 0x40: // Rn = FEXT Rx BY Ry | <bit6>:<len6> case 0x48: // Rn = FEXT Rx BY Ry | <bit6>:<len6> (SE) - REG_USED(desc, rx); - REG_USED(desc, ry); - REG_MODIFIED(desc, rn); - SHIFT_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_reg_modified(rn); + desc.set_shift_flags_modified(); break; case 0x20: // Rn = Rn OR LSHIFT Rx BY Ry | <data8> case 0x24: // Rn = Rn OR ASHIFT Rx BY Ry | <data8> case 0x64: // Rn = Rn OR FDEP Rx BY Ry | <bit6>:<len6> case 0x6c: // Rn = Rn OR FDEP Rx BY Ry | <bit6>:<len6> (SE) - REG_USED(desc, rx); - REG_USED(desc, ry); - REG_USED(desc, rn); - REG_MODIFIED(desc, rn); - SHIFT_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_reg_used(rn); + desc.set_reg_modified(rn); + desc.set_shift_flags_modified(); break; case 0xcc: // BTST Rx BY Ry | <data8> - REG_USED(desc, rx); - REG_USED(desc, ry); - SHIFT_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(ry); + desc.set_shift_flags_modified(); break; case 0x80: // Rn = EXP Rx @@ -1563,19 +1576,19 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) case 0x8c: // Rn = LEFTO Rx case 0x90: // Rn = FPACK Fx case 0x94: // Fn = FUNPACK Rx - REG_USED(desc, rx); - REG_MODIFIED(desc, rn); - SHIFT_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_modified(rn); + desc.set_shift_flags_modified(); break; default: - fatalerror("sharc_frontend::describe_compute: unknown shift op %02X in opcode %04X%08X at %08X", operation, (uint16_t)(opcode >> 32), (uint32_t)(opcode), desc.pc); + fatalerror("adsp21062_device::frontend::describe_compute: unknown shift op %02X in opcode %04X%08X at %08X", operation, (uint16_t)(opcode >> 32), (uint32_t)(opcode), desc.pc); } break; } default: - fatalerror("sharc_frontend::describe_compute: unknown operation type in opcode %04X%08X at %08X", (uint16_t)(opcode >> 32), (uint32_t)(opcode), desc.pc); + fatalerror("adsp21062_device::frontend::describe_compute: unknown operation type in opcode %04X%08X at %08X", (uint16_t)(opcode >> 32), (uint32_t)(opcode), desc.pc); return false; } } @@ -1583,68 +1596,68 @@ bool sharc_frontend::describe_compute(opcode_desc &desc, uint64_t opcode) return true; } -bool sharc_frontend::describe_ureg_access(opcode_desc &desc, int reg, UREG_ACCESS access) +bool adsp21062_device::frontend::describe_ureg_access(opcode_desc &desc, int reg, UREG_ACCESS access) { switch (reg) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: if (access == UREG_READ) - REG_USED(desc, reg); + desc.set_reg_used(reg); else - REG_MODIFIED(desc, reg); + desc.set_reg_modified(reg); break; case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: if (access == UREG_READ) - DM_I_USED(desc, reg & 7); + desc.set_dm_i_used(reg & 7); else - DM_I_MODIFIED(desc, reg & 7); + desc.set_dm_i_modified(reg & 7); break; case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: if (access == UREG_READ) - PM_I_USED(desc, reg & 7); + desc.set_pm_i_used(reg & 7); else - PM_I_MODIFIED(desc, reg & 7); + desc.set_pm_i_modified(reg & 7); break; case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: if (access == UREG_READ) - DM_M_USED(desc, reg & 7); + desc.set_dm_m_used(reg & 7); else - DM_M_MODIFIED(desc, reg & 7); + desc.set_dm_m_modified(reg & 7); break; case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: if (access == UREG_READ) - PM_M_USED(desc, reg & 7); + desc.set_pm_m_used(reg & 7); else - PM_M_MODIFIED(desc, reg & 7); + desc.set_pm_m_modified(reg & 7); break; case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: if (access == UREG_READ) - DM_L_USED(desc, reg & 7); + desc.set_dm_l_used(reg & 7); else - DM_L_MODIFIED(desc, reg & 7); + desc.set_dm_l_modified(reg & 7); break; case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: if (access == UREG_READ) - PM_L_USED(desc, reg & 7); + desc.set_pm_l_used(reg & 7); else - PM_L_MODIFIED(desc, reg & 7); + desc.set_pm_l_modified(reg & 7); break; case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: if (access == UREG_READ) - DM_B_USED(desc, reg & 7); + desc.set_dm_b_used(reg & 7); else - DM_B_MODIFIED(desc, reg & 7); + desc.set_dm_b_modified(reg & 7); break; case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: if (access == UREG_READ) - PM_B_USED(desc, reg & 7); + desc.set_pm_b_used(reg & 7); else - PM_B_MODIFIED(desc, reg & 7); + desc.set_pm_b_modified(reg & 7); break; case 0x60: // FADDR @@ -1677,29 +1690,29 @@ bool sharc_frontend::describe_ureg_access(opcode_desc &desc, int reg, UREG_ACCES case 0x7c: // ASTAT if (access == UREG_READ) { - AZ_USED(desc); - AN_USED(desc); - AV_USED(desc); - AC_USED(desc); - AS_USED(desc); - AI_USED(desc); - MN_USED(desc); - MV_USED(desc); - MU_USED(desc); - MI_USED(desc); - SV_USED(desc); - SZ_USED(desc); - SS_USED(desc); - BTF_USED(desc); - AF_USED(desc); + desc.set_az_used(); + desc.set_an_used(); + desc.set_av_used(); + desc.set_ac_used(); + desc.set_as_used(); + desc.set_ai_used(); + desc.set_mn_used(); + desc.set_mv_used(); + desc.set_mu_used(); + desc.set_mi_used(); + desc.set_sv_used(); + desc.set_sz_used(); + desc.set_ss_used(); + desc.set_btf_used(); + desc.set_af_used(); } else { - ALU_FLAGS_MODIFIED(desc); - MULT_FLAGS_MODIFIED(desc); - SHIFT_FLAGS_MODIFIED(desc); - BTF_MODIFIED(desc); - AF_MODIFIED(desc); + desc.set_alu_flags_modified(); + desc.set_mult_flags_modified(); + desc.set_shift_flags_modified(); + desc.set_btf_modified(); + desc.set_af_modified(); } break; @@ -1717,14 +1730,14 @@ bool sharc_frontend::describe_ureg_access(opcode_desc &desc, int reg, UREG_ACCES break; default: - fatalerror("sharc_frontend::describe_ureg_access: unknown UREG %02X", reg); + fatalerror("adsp21062_device::frontend::describe_ureg_access: unknown UREG %02X", reg); return false; } return true; } -bool sharc_frontend::describe_shiftop_imm(opcode_desc &desc, int shiftop, int rn, int rx) +bool adsp21062_device::frontend::describe_shiftop_imm(opcode_desc &desc, int shiftop, int rn, int rx) { switch (shiftop) { @@ -1738,56 +1751,56 @@ bool sharc_frontend::describe_shiftop_imm(opcode_desc &desc, int shiftop, int rn case 0x30: // BSET Rx BY <data8> case 0x31: // BCLR Rx By <data8> case 0x32: // BTGL Rx BY <data8> - REG_USED(desc, rx); - REG_MODIFIED(desc, rn); - SHIFT_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_modified(rn); + desc.set_shift_flags_modified(); break; case 0x08: // Rn = Rn OR LSHIFT Rx BY <data8> case 0x19: // Rn = Rn OR FDEP Rx BY <bit6>:<len6> case 0x1b: // Rn = Rn OR FDEP Rx BY <bit6>:<len6> (SE) - REG_USED(desc, rx); - REG_USED(desc, rn); - REG_MODIFIED(desc, rn); - SHIFT_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_reg_used(rn); + desc.set_reg_modified(rn); + desc.set_shift_flags_modified(); break; case 0x33: // BTST Rx BY <data8> - REG_USED(desc, rx); - SHIFT_FLAGS_MODIFIED(desc); + desc.set_reg_used(rx); + desc.set_shift_flags_modified(); break; default: - fatalerror("sharc_frontend::describe_shiftop_imm: unknown op %02X at %08X", shiftop, desc.pc); + fatalerror("adsp21062_device::frontend::describe_shiftop_imm: unknown op %02X at %08X", shiftop, desc.pc); return false; } return true; } -void sharc_frontend::describe_if_condition(opcode_desc &desc, int condition) +void adsp21062_device::frontend::describe_if_condition(opcode_desc &desc, int condition) { switch (condition) { - case 0x00: AZ_USED(desc); break; /* EQ */ - case 0x01: AZ_USED(desc); AN_USED(desc); break; /* LT */ - case 0x02: AZ_USED(desc); AN_USED(desc); break; /* LE */ - case 0x03: AC_USED(desc); break; /* AC */ - case 0x04: AV_USED(desc); break; /* AV */ - case 0x05: MV_USED(desc); break; /* MV */ - case 0x06: MN_USED(desc); break; /* MS */ - case 0x07: SV_USED(desc); break; /* SV */ - case 0x08: SZ_USED(desc); break; /* SZ */ - case 0x0d: BTF_USED(desc); break; /* TF */ - case 0x10: AZ_USED(desc); break; /* NOT EQUAL */ - case 0x11: AZ_USED(desc); AN_USED(desc); break; /* GE */ - case 0x12: AZ_USED(desc); AN_USED(desc); break; /* GT */ - case 0x13: AC_USED(desc); break; /* NOT AC */ - case 0x14: AV_USED(desc); break; /* NOT AV */ - case 0x15: MV_USED(desc); break; /* NOT MV */ - case 0x16: MN_USED(desc); break; /* NOT MS */ - case 0x17: SV_USED(desc); break; /* NOT SV */ - case 0x18: SZ_USED(desc); break; /* NOT SZ */ - case 0x1d: BTF_USED(desc); break; /* NOT TF */ + case 0x00: desc.set_az_used(); break; // EQ + case 0x01: desc.set_az_used(); desc.set_an_used(); break; // LT + case 0x02: desc.set_az_used(); desc.set_an_used(); break; // LE + case 0x03: desc.set_ac_used(); break; // AC + case 0x04: desc.set_av_used(); break; // AV + case 0x05: desc.set_mv_used(); break; // MV + case 0x06: desc.set_mn_used(); break; // MS + case 0x07: desc.set_sv_used(); break; // SV + case 0x08: desc.set_sz_used(); break; // SZ + case 0x0d: desc.set_btf_used(); break; // TF + case 0x10: desc.set_az_used(); break; // NOT EQUAL + case 0x11: desc.set_az_used(); desc.set_an_used(); break; // GE + case 0x12: desc.set_az_used(); desc.set_an_used(); break; // GT + case 0x13: desc.set_ac_used(); break; // NOT AC + case 0x14: desc.set_av_used(); break; // NOT AV + case 0x15: desc.set_mv_used(); break; // NOT MV + case 0x16: desc.set_mn_used(); break; // NOT MS + case 0x17: desc.set_sv_used(); break; // NOT SV + case 0x18: desc.set_sz_used(); break; // NOT SZ + case 0x1d: desc.set_btf_used(); break; // NOT TF } } diff --git a/src/devices/cpu/sharc/sharcfe.h b/src/devices/cpu/sharc/sharcfe.h index 1d52b216664..01be597b2a5 100644 --- a/src/devices/cpu/sharc/sharcfe.h +++ b/src/devices/cpu/sharc/sharcfe.h @@ -12,15 +12,225 @@ #pragma once #include "sharc.h" + #include "cpu/drcfe.h" +#include <cassert> +#include <bitset> + -class sharc_frontend : public drc_frontend +class adsp21062_device::opcode_desc : public opcode_desc_base<opcode_desc, 96> { public: - sharc_frontend(adsp21062_device *sharc, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); + enum + { + LOOP = 0, + ASTAT_DELAY_COPY_AZ, + ASTAT_DELAY_COPY_AN, + ASTAT_DELAY_COPY_AC, + ASTAT_DELAY_COPY_AV, + ASTAT_DELAY_COPY_MV, + ASTAT_DELAY_COPY_MN, + ASTAT_DELAY_COPY_SV, + ASTAT_DELAY_COPY_SZ, + ASTAT_DELAY_COPY_BTF, + CALL, + + READS_MEMORY, + WRITES_MEMORY, + + EXTRA_FLAG_COUNT + }; + + using extra_flags = std::bitset<EXTRA_FLAG_COUNT>; + + uint64_t opptr; // copy of opcode + + void set_reg_used(unsigned x) { regin.set(REG_R0 + x); } + void set_reg_modified(unsigned x) { regout.set(REG_R0 + x); } + + void set_az_used() { regin.set(REG_AZ); } + void set_az_modified() { regout.set(REG_AZ); } + void set_av_used() { regin.set(REG_AV); } + void set_av_modified() { regout.set(REG_AV); } + void set_an_used() { regin.set(REG_AN); } + void set_an_modified() { regout.set(REG_AN); } + void set_ac_used() { regin.set(REG_AC); } + void set_ac_modified() { regout.set(REG_AC); } + void set_as_used() { regin.set(REG_AS); } + void set_as_modified() { regout.set(REG_AS); } + void set_ai_used() { regin.set(REG_AI); } + void set_ai_modified() { regout.set(REG_AI); } + void set_mn_used() { regin.set(REG_MN); } + void set_mn_modified() { regout.set(REG_MN); } + void set_mv_used() { regin.set(REG_MV); } + void set_mv_modified() { regout.set(REG_MV); } + void set_mu_used() { regin.set(REG_MU); } + void set_mu_modified() { regout.set(REG_MU); } + void set_mi_used() { regin.set(REG_MI); } + void set_mi_modified() { regout.set(REG_MI); } + void set_sv_used() { regin.set(REG_SV); } + void set_sv_modified() { regout.set(REG_SV); } + void set_sz_used() { regin.set(REG_SZ); } + void set_sz_modified() { regout.set(REG_SZ); } + void set_ss_used() { regin.set(REG_SS); } + void set_ss_modified() { regout.set(REG_SS); } + void set_btf_used() { regin.set(REG_BTF); } + void set_btf_modified() { regout.set(REG_BTF); } + void set_af_used() { regin.set(REG_AF); } + void set_af_modified() { regout.set(REG_AF); } + + void set_pm_i_used(unsigned x) { regin.set(REG_PM_I0 + x); } + void set_pm_i_modified(unsigned x) { regout.set(REG_PM_I0 + x); } + void set_pm_m_used(unsigned x) { regin.set(REG_PM_M0 + x); } + void set_pm_m_modified(unsigned x) { regout.set(REG_PM_M0 + x); } + void set_pm_b_used(unsigned x) { regin.set(REG_PM_B0 + x); } + void set_pm_b_modified(unsigned x) { regout.set(REG_PM_B0 + x); } + void set_pm_l_used(unsigned x) { regin.set(REG_PM_L0 + x); } + void set_pm_l_modified(unsigned x) { regout.set(REG_PM_L0 + x); } + + void set_dm_i_used(unsigned x) { regin.set(REG_DM_I0 + x); } + void set_dm_i_modified(unsigned x) { regout.set(REG_DM_I0 + x); } + void set_dm_m_used(unsigned x) { regin.set(REG_DM_M0 + x); } + void set_dm_m_modified(unsigned x) { regout.set(REG_DM_M0 + x); } + void set_dm_b_used(unsigned x) { regin.set(REG_DM_B0 + x); } + void set_dm_b_modified(unsigned x) { regout.set(REG_DM_B0 + x); } + void set_dm_l_used(unsigned x) { regin.set(REG_DM_L0 + x); } + void set_dm_l_modified(unsigned x) { regout.set(REG_DM_L0 + x); } + + void set_alu_flags_modified() + { + set_az_modified(); + set_an_modified(); + set_av_modified(); + set_ac_modified(); + set_as_modified(); + set_ai_modified(); + } + + void set_mult_flags_modified() + { + set_mn_modified(); + set_mv_modified(); + set_mu_modified(); + set_mi_modified(); + } + + void set_shift_flags_modified() + { + set_sz_modified(); + set_sv_modified(); + set_ss_modified(); + } + + bool az_calc_required() const { return regreq[REG_AZ] || in_delay_slot(); } + bool av_calc_required() const { return regreq[REG_AV] || in_delay_slot(); } + bool an_calc_required() const { return regreq[REG_AN] || in_delay_slot(); } + bool ac_calc_required() const { return regreq[REG_AC] || in_delay_slot(); } + bool as_calc_required() const { return regreq[REG_AS] || in_delay_slot(); } + bool ai_calc_required() const { return regreq[REG_AI] || in_delay_slot(); } + bool mn_calc_required() const { return regreq[REG_MN] || in_delay_slot(); } + bool mv_calc_required() const { return regreq[REG_MV] || in_delay_slot(); } + bool mu_calc_required() const { return regreq[REG_MU] || in_delay_slot(); } + bool mi_calc_required() const { return regreq[REG_MI] || in_delay_slot(); } + bool sv_calc_required() const { return regreq[REG_SV] || in_delay_slot(); } + bool sz_calc_required() const { return regreq[REG_SZ] || in_delay_slot(); } + bool ss_calc_required() const { return regreq[REG_SS] || in_delay_slot(); } + bool btf_calc_required() const { return regreq[REG_BTF] || in_delay_slot(); } + bool af_calc_required() const { return regreq[REG_AF] || in_delay_slot(); } + + void set_loop() { m_extra_flags.set(LOOP); } + void set_astat_delay_copy_az() { m_extra_flags.set(ASTAT_DELAY_COPY_AZ); } + void set_astat_delay_copy_an() { m_extra_flags.set(ASTAT_DELAY_COPY_AN); } + void set_astat_delay_copy_ac() { m_extra_flags.set(ASTAT_DELAY_COPY_AC); } + void set_astat_delay_copy_av() { m_extra_flags.set(ASTAT_DELAY_COPY_AV); } + void set_astat_delay_copy_mv() { m_extra_flags.set(ASTAT_DELAY_COPY_MV); } + void set_astat_delay_copy_mn() { m_extra_flags.set(ASTAT_DELAY_COPY_MN); } + void set_astat_delay_copy_sv() { m_extra_flags.set(ASTAT_DELAY_COPY_SV); } + void set_astat_delay_copy_sz() { m_extra_flags.set(ASTAT_DELAY_COPY_SZ); } + void set_astat_delay_copy_btf() { m_extra_flags.set(ASTAT_DELAY_COPY_BTF); } + void set_call() { m_extra_flags.set(CALL); } + void set_reads_memory() { m_extra_flags.set(READS_MEMORY); } + void set_writes_memory() { m_extra_flags.set(WRITES_MEMORY); } + + void set_extra_flags(extra_flags const &flags) + { + m_extra_flags |= flags; + } + + bool loop() const { return m_extra_flags[LOOP]; } + bool astat_delay_copy_az() const { return m_extra_flags[ASTAT_DELAY_COPY_AZ]; } + bool astat_delay_copy_an() const { return m_extra_flags[ASTAT_DELAY_COPY_AN]; } + bool astat_delay_copy_ac() const { return m_extra_flags[ASTAT_DELAY_COPY_AC]; } + bool astat_delay_copy_av() const { return m_extra_flags[ASTAT_DELAY_COPY_AV]; } + bool astat_delay_copy_mv() const { return m_extra_flags[ASTAT_DELAY_COPY_MV]; } + bool astat_delay_copy_mn() const { return m_extra_flags[ASTAT_DELAY_COPY_MN]; } + bool astat_delay_copy_sv() const { return m_extra_flags[ASTAT_DELAY_COPY_SV]; } + bool astat_delay_copy_sz() const { return m_extra_flags[ASTAT_DELAY_COPY_SZ]; } + bool astat_delay_copy_btf() const { return m_extra_flags[ASTAT_DELAY_COPY_BTF]; } + bool call() const { return m_extra_flags[CALL]; } + bool reads_memory() const { return m_extra_flags[READS_MEMORY]; } + bool writes_memory() const { return m_extra_flags[WRITES_MEMORY]; } + + void reset(offs_t curpc, bool in_delay_slot) + { + static_assert(REG_COUNT <= 96); + + opcode_desc_base::reset(curpc, in_delay_slot); + + opptr = 0; + m_extra_flags.reset(); + } + +private: + enum + { + REG_R0 = 0, + + REG_AZ = REG_R0 + 16, + REG_AV, + REG_AN, + REG_AC, + REG_AS, + REG_AI, + REG_MN, + REG_MV, + REG_MU, + REG_MI, + REG_SV, + REG_SZ, + REG_SS, + REG_BTF, + REG_AF, + + REG_PM_I0, + REG_PM_M0 = REG_PM_I0 + 8, + REG_PM_B0 = REG_PM_M0 + 8, + REG_PM_L0 = REG_PM_B0 + 8, + + REG_DM_I0 = REG_PM_L0 + 8, + REG_DM_M0 = REG_DM_I0 + 8, + REG_DM_B0 = REG_DM_M0 + 8, + REG_DM_L0 = REG_DM_B0 + 8, + + REG_COUNT = REG_DM_L0 + 8 + }; + + extra_flags m_extra_flags; +}; + + +class adsp21062_device::frontend : public drc_frontend_base<opcode_desc> +{ +public: + frontend(adsp21062_device *sharc, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); + ~frontend(); + + opcode_desc const *describe_code(offs_t startpc); + void flush(); +private: enum UREG_ACCESS { UREG_READ, @@ -43,7 +253,7 @@ public: struct LOOP_ENTRY { uint16_t entrytype; - uint32_t userflags; + opcode_desc::extra_flags userflags; }; struct LOOP_DESCRIPTOR @@ -55,18 +265,15 @@ public: int condition; }; -protected: - // required overrides - virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override; + bool describe(opcode_desc &desc, const opcode_desc *prev); -private: bool describe_compute(opcode_desc &desc, uint64_t opcode); bool describe_ureg_access(opcode_desc &desc, int reg, UREG_ACCESS access); bool describe_shiftop_imm(opcode_desc &desc, int shiftop, int rn, int rx); void describe_if_condition(opcode_desc &desc, int condition); void insert_loop(const LOOP_DESCRIPTOR &loopdesc); - void add_loop_entry(uint32_t pc, uint8_t type, uint32_t userflags); + void add_loop_entry(uint32_t pc, uint8_t type, opcode_desc::extra_flags const &userflags); bool is_loop_evaluation(uint32_t pc); bool is_loop_start(uint32_t pc); bool is_astat_delay_check(uint32_t pc); diff --git a/src/devices/cpu/sharc/sharcinternal.ipp b/src/devices/cpu/sharc/sharcinternal.ipp index 8b57f0403a3..e4ad191122a 100644 --- a/src/devices/cpu/sharc/sharcinternal.ipp +++ b/src/devices/cpu/sharc/sharcinternal.ipp @@ -8,21 +8,6 @@ #include <algorithm> -// DRC instruction description flags -constexpr uint32_t OP_USERFLAG_LOOP = 0x00000001; -constexpr uint32_t OP_USERFLAG_ASTAT_DELAY_COPY_AZ = 0x00001000; -constexpr uint32_t OP_USERFLAG_ASTAT_DELAY_COPY_AN = 0x00002000; -constexpr uint32_t OP_USERFLAG_ASTAT_DELAY_COPY_AC = 0x00004000; -constexpr uint32_t OP_USERFLAG_ASTAT_DELAY_COPY_AV = 0x00008000; -constexpr uint32_t OP_USERFLAG_ASTAT_DELAY_COPY_MV = 0x00010000; -constexpr uint32_t OP_USERFLAG_ASTAT_DELAY_COPY_MN = 0x00020000; -constexpr uint32_t OP_USERFLAG_ASTAT_DELAY_COPY_SV = 0x00040000; -constexpr uint32_t OP_USERFLAG_ASTAT_DELAY_COPY_SZ = 0x00080000; -constexpr uint32_t OP_USERFLAG_ASTAT_DELAY_COPY_BTF = 0x00100000; -constexpr uint32_t OP_USERFLAG_ASTAT_DELAY_COPY = 0x001ff000; -constexpr uint32_t OP_USERFLAG_CALL = 0x10000000; - - // constants for IEEE754 single-precision float format constexpr uint32_t FLOAT_INFINITY = 0x7f800000; constexpr uint32_t FLOAT_SIGN_MASK = 0x80000000; diff --git a/src/devices/cpu/unsp/unsp.cpp b/src/devices/cpu/unsp/unsp.cpp index 5f580c8ce28..657d5f0671e 100644 --- a/src/devices/cpu/unsp/unsp.cpp +++ b/src/devices/cpu/unsp/unsp.cpp @@ -26,6 +26,12 @@ #include <climits> + +#define SINGLE_INSTRUCTION_MODE (0) + +#define ENABLE_UNSP_DRC (0) + + DEFINE_DEVICE_TYPE(UNSP, unsp_device, "unsp", "SunPlus u'nSP (ISA 1.0)") // 1.1 is just 1.0 with better CPI? DEFINE_DEVICE_TYPE(UNSP_11, unsp_11_device, "unsp_11", "SunPlus u'nSP (ISA 1.1)") @@ -248,7 +254,7 @@ void unsp_device::device_start() m_drcuml->symbol_add(&m_core->m_icount, sizeof(m_core->m_icount), "icount"); /* initialize the front-end helper */ - m_drcfe = std::make_unique<unsp_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE); + m_drcfe = std::make_unique<frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE); /* mark the cache dirty so it is updated on next execute */ m_cache_dirty = true; diff --git a/src/devices/cpu/unsp/unsp.h b/src/devices/cpu/unsp/unsp.h index 05d8871cb76..0372a491ffb 100644 --- a/src/devices/cpu/unsp/unsp.h +++ b/src/devices/cpu/unsp/unsp.h @@ -17,23 +17,15 @@ #pragma once -#include "cpu/drcfe.h" -#include "cpu/drcuml.h" -#include "cpu/drcumlsh.h" #include "unspdefs.h" +#include "cpu/drcuml.h" + + /*************************************************************************** CONSTANTS ***************************************************************************/ -/* map variables */ -#define MAPVAR_PC M0 -#define MAPVAR_CYCLES M1 - -#define SINGLE_INSTRUCTION_MODE (0) - -#define ENABLE_UNSP_DRC (0) - #define UNSP_LOG_OPCODES (0) #define UNSP_LOG_REGS (0) @@ -41,8 +33,6 @@ // TYPE DEFINITIONS //************************************************************************** -class unsp_frontend; - // ======================> unsp_device enum @@ -177,6 +167,10 @@ protected: int m_icount; }; + class frontend; + class opcode_desc; + + unsp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal); // device_t implementation @@ -300,7 +294,7 @@ private: drc_cache m_drccache; std::unique_ptr<drcuml_state> m_drcuml; - std::unique_ptr<unsp_frontend> m_drcfe; + std::unique_ptr<frontend> m_drcfe; uint32_t m_drcoptions; uint8_t m_cache_dirty; diff --git a/src/devices/cpu/unsp/unspdrc.cpp b/src/devices/cpu/unsp/unspdrc.cpp index a8162b82b22..e041d1020d5 100644 --- a/src/devices/cpu/unsp/unspdrc.cpp +++ b/src/devices/cpu/unsp/unspdrc.cpp @@ -4,8 +4,20 @@ #include "emu.h" #include "unsp.h" -#include "unspfe.h" + #include "unspdefs.h" +#include "unspfe.h" + +#include "cpu/drcumlsh.h" + + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +/* map variables */ +#define MAPVAR_PC M0 + void unsp_device::invalidate_cache() { @@ -179,7 +191,7 @@ void unsp_device::code_compile_block(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); @@ -204,11 +216,11 @@ void unsp_device::code_compile_block(offs_t pc) } /* validate this code block if we're not pointing into ROM */ - if (m_program.space().get_write_ptr(seqhead->physpc) != nullptr) + if (m_program.space().get_write_ptr(seqhead->pc) != nullptr) 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); /* iterate over instructions in the sequence and compile them */ @@ -525,9 +537,9 @@ void unsp_device::generate_checksum_block(drcuml_block &block, compiler_state &c } /* full verification; sum up everything */ - void *memptr = m_program.space().get_write_ptr(seqhead->physpc); + void *memptr = m_program.space().get_write_ptr(seqhead->pc); UML_LOAD(block, I0, memptr, 0, SIZE_WORD, SCALE_x2); - uint32_t sum = seqhead->opptr.w[0]; + uint32_t sum = seqhead->opptr[0]; for (int i = 1; i < seqhead->length; i++) { UML_LOAD(block, I1, memptr, i, SIZE_WORD, SCALE_x2); @@ -536,12 +548,12 @@ void unsp_device::generate_checksum_block(drcuml_block &block, compiler_state &c } for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next()) { - if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP)) + if (!curdesc->virtual_noop()) { - memptr = m_program.space().get_write_ptr(curdesc->physpc); + memptr = m_program.space().get_write_ptr(curdesc->pc); UML_LOAD(block, I1, memptr, 0, SIZE_WORD, SCALE_x2); UML_ADD(block, I0, I0, I1); - sum += curdesc->opptr.w[0]; + sum += curdesc->opptr[0]; for (int i = 1; i < curdesc->length; i++) { UML_LOAD(block, I1, memptr, i, SIZE_WORD, SCALE_x2); @@ -603,8 +615,8 @@ void unsp_device::generate_branch(drcuml_block &block, compiler_state &compiler, void unsp_device::generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { /* 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[0]); /* set the PC map variable */ UML_MAPVAR(block, MAPVAR_PC, desc->pc); @@ -620,14 +632,14 @@ void unsp_device::generate_sequence_instruction(drcuml_block &block, compiler_st UML_CALLC(block, cfunc_log_regs, this); #endif - if (!(desc->flags & OPFLAG_VIRTUAL_NOOP)) + if (!desc->virtual_noop()) { /* compile the instruction */ if (!generate_opcode(block, compiler, desc)) { UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), desc->pc, 16, 0x3f); UML_AND(block, mem(&m_core->m_r[REG_PC]), desc->pc, 0x0000ffff); - UML_MOV(block, mem(&m_core->m_arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_core->m_arg0), desc->opptr[0]); UML_CALLC(block, cfunc_unimplemented, this); } } @@ -700,7 +712,7 @@ void unsp_device::generate_update_nz(drcuml_block &block) bool unsp_device::generate_opcode(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { - uint32_t op = (uint32_t)desc->opptr.w[0]; + const uint32_t op = uint32_t(desc->opptr[0]); generate_add_lpc(block, 1); @@ -1032,7 +1044,7 @@ bool unsp_device::generate_opcode(drcuml_block &block, compiler_state &compiler, return false; // MULS - UML_MOV(block, mem(&m_core->m_arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_core->m_arg0), desc->opptr[0]); UML_CALLC(block, ccfunc_muls, this); return true; diff --git a/src/devices/cpu/unsp/unspfe.cpp b/src/devices/cpu/unsp/unspfe.cpp index f93423379a1..43bd4952ef4 100644 --- a/src/devices/cpu/unsp/unspfe.cpp +++ b/src/devices/cpu/unsp/unspfe.cpp @@ -10,21 +10,36 @@ #include "emu.h" #include "unspfe.h" + #include "unspdefs.h" +#include "cpu/drcfe.ipp" + + /*************************************************************************** INSTRUCTION PARSERS ***************************************************************************/ -unsp_frontend::unsp_frontend(unsp_device *unsp, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) - : drc_frontend(*unsp, window_start, window_end, max_sequence) +unsp_device::frontend::frontend(unsp_device *unsp, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) + : drc_frontend_base(unsp->space_config(AS_PROGRAM)->page_shift(), window_start, window_end, max_sequence) , m_cpu(unsp) { } -inline uint16_t unsp_frontend::read_op_word(opcode_desc &desc, int offset) +unsp_device::frontend::~frontend() +{ +} + +unsp_device::opcode_desc const *unsp_device::frontend::describe_code(offs_t startpc) { - return m_cpu->m_cache.read_word(desc.physpc + offset); + return do_describe_code( + [this] (opcode_desc &desc, opcode_desc const *prev) { return describe(desc, prev); }, + startpc); +} + +inline uint16_t unsp_device::frontend::read_op_word(opcode_desc &desc, int offset) +{ + return m_cpu->m_cache.read_word(desc.pc + offset); } /*------------------------------------------------- @@ -32,9 +47,9 @@ inline uint16_t unsp_frontend::read_op_word(opcode_desc &desc, int offset) instruction -------------------------------------------------*/ -bool unsp_frontend::describe(opcode_desc &desc, const opcode_desc *prev) +bool unsp_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) { - uint16_t op = desc.opptr.w[0] = read_op_word(desc, 0); + const uint16_t op = desc.opptr[0] = read_op_word(desc, 0); /* most instructions are 1 word */ desc.length = 1; @@ -69,17 +84,19 @@ bool unsp_frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 11: // JG case 12: // JVC case 13: // JVS - desc.regin[0] |= 1 << unsp_device::REG_SR; - desc.regout[0] |= 1 << unsp_device::REG_SR; - desc.regout[0] |= 1 << unsp_device::REG_PC; + desc.regin.set(unsp_device::REG_SR); + desc.regout.set(unsp_device::REG_SR); + desc.regout.set(unsp_device::REG_PC); desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_conditional_branch(); + desc.set_end_sequence(); return true; case 14: // JMP - desc.regout[0] |= 1 << unsp_device::REG_SR; - desc.regout[0] |= 1 << unsp_device::REG_PC; + desc.regout.set(unsp_device::REG_SR); + desc.regout.set(unsp_device::REG_PC); desc.targetpc = desc.pc + 1 + ((op1 == 0) ? opimm : (0 - opimm)); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); return true; default: return false; @@ -90,12 +107,12 @@ bool unsp_frontend::describe(opcode_desc &desc, const opcode_desc *prev) uint16_t r0 = opn; uint16_t r1 = opa; desc.cycles = 4 + 2 * r0; - desc.regin[0] |= 1 << opb; - desc.regout[0] |= 1 << opb; - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.regin.set(opb); + desc.regout.set(opb); + desc.set_writes_memory(); while (r0--) { - desc.regin[0] |= 1 << r1; + desc.regin.set(r1); r1--; } return true; @@ -105,12 +122,14 @@ bool unsp_frontend::describe(opcode_desc &desc, const opcode_desc *prev) if (op == 0x9a98) // reti { desc.cycles = 8; - desc.regin[0] |= 1 << unsp_device::REG_SP; - desc.regout[0] |= 1 << unsp_device::REG_SP; - desc.regout[0] |= 1 << unsp_device::REG_SR; - desc.regout[0] |= 1 << unsp_device::REG_PC; + desc.regin.set(unsp_device::REG_SP); + desc.regout.set(unsp_device::REG_SP); + desc.regout.set(unsp_device::REG_SR); + desc.regout.set(unsp_device::REG_PC); desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_READS_MEMORY; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + desc.set_reads_memory(); return true; } else @@ -118,16 +137,18 @@ bool unsp_frontend::describe(opcode_desc &desc, const opcode_desc *prev) uint16_t r0 = opn; uint16_t r1 = opa; desc.cycles = 4 + 2 * r0; - desc.regin[0] |= 1 << opb; - desc.regout[0] |= 1 << opb; - desc.flags |= OPFLAG_READS_MEMORY; + desc.regin.set(opb); + desc.regout.set(opb); + desc.set_reads_memory(); while (r0--) { r1++; - desc.regout[0] |= 1 << r1; - if (r1 == unsp_device::REG_PC) { - desc.flags |= OPFLAG_END_SEQUENCE | OPFLAG_IS_UNCONDITIONAL_BRANCH; + desc.regout.set(r1); + if (r1 == unsp_device::REG_PC) + { + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } } return true; @@ -142,10 +163,10 @@ bool unsp_frontend::describe(opcode_desc &desc, const opcode_desc *prev) if(opn == 1 && opa != 7) { desc.cycles = 12; - desc.regin[0] |= 1 << opa; - desc.regin[0] |= 1 << opb; - desc.regout[0] |= 1 << unsp_device::REG_R3; - desc.regout[0] |= 1 << unsp_device::REG_R4; + desc.regin.set(opa); + desc.regin.set(opb); + desc.regout.set(unsp_device::REG_R3); + desc.regout.set(unsp_device::REG_R4); return true; } return false; @@ -156,12 +177,15 @@ bool unsp_frontend::describe(opcode_desc &desc, const opcode_desc *prev) desc.cycles = 9; desc.length = 2; desc.targetpc = read_op_word(desc, 1) | ((op & 0x3f) << 16); - desc.flags = OPFLAG_READS_MEMORY | OPFLAG_WRITES_MEMORY | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - desc.regin[0] |= 1 << unsp_device::REG_PC; - desc.regin[0] |= 1 << unsp_device::REG_SP; - desc.regout[0] |= 1 << unsp_device::REG_SP; - desc.regout[0] |= 1 << unsp_device::REG_SR; - desc.regout[0] |= 1 << unsp_device::REG_PC; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + desc.set_reads_memory(); + desc.set_writes_memory(); + desc.regin.set(unsp_device::REG_PC); + desc.regin.set(unsp_device::REG_SP); + desc.regout.set(unsp_device::REG_SP); + desc.regout.set(unsp_device::REG_SR); + desc.regout.set(unsp_device::REG_PC); return true; } return false; @@ -172,10 +196,12 @@ bool unsp_frontend::describe(opcode_desc &desc, const opcode_desc *prev) desc.cycles = 5; desc.length = 2; desc.targetpc = read_op_word(desc, 1) | ((op & 0x3f) << 16); - desc.flags = OPFLAG_READS_MEMORY | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - desc.regin[0] |= 1 << unsp_device::REG_PC; - desc.regout[0] |= 1 << unsp_device::REG_SR; - desc.regout[0] |= 1 << unsp_device::REG_PC; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + desc.set_reads_memory(); + desc.regin.set(unsp_device::REG_PC); + desc.regout.set(unsp_device::REG_SR); + desc.regout.set(unsp_device::REG_PC); return true; } return false; @@ -201,13 +227,14 @@ bool unsp_frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x06: case 0x07: // MULS - desc.regin[0] |= 1 << opa; - desc.regin[0] |= 1 << opb; - desc.regout[0] |= 1 << opa; - desc.regout[0] |= 1 << opb; - desc.regout[0] |= 1 << unsp_device::REG_R3; - desc.regout[0] |= 1 << unsp_device::REG_R4; - desc.flags = OPFLAG_READS_MEMORY | OPFLAG_WRITES_MEMORY; + desc.regin.set(opa); + desc.regin.set(opb); + desc.regout.set(opa); + desc.regout.set(opb); + desc.regout.set(unsp_device::REG_R3); + desc.regout.set(unsp_device::REG_R4); + desc.set_reads_memory(); + desc.set_writes_memory(); return true; default: @@ -217,15 +244,15 @@ bool unsp_frontend::describe(opcode_desc &desc, const opcode_desc *prev) // At this point, we should be dealing solely with ALU ops. - desc.regin[0] |= 1 << opa; + desc.regin.set(opa); switch (op1) { case 0x00: // r, [bp+imm6] desc.cycles = 6; - desc.regin[0] |= 1 << unsp_device::REG_BP; + desc.regin.set(unsp_device::REG_BP); if (op0 != 0x0d) - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); break; case 0x01: // r, imm6 @@ -241,21 +268,21 @@ bool unsp_frontend::describe(opcode_desc &desc, const opcode_desc *prev) switch (lsbits) { case 0: // r, [r] - desc.regin[0] |= 1 << unsp_device::REG_SR; - desc.regin[0] |= 1 << opb; + desc.regin.set(unsp_device::REG_SR); + desc.regin.set(opb); if (op0 != 0x0d) - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); break; case 1: // r, [<ds:>r--] case 2: // r, [<ds:>r++] case 3: // r, [<ds:>++r] - desc.regin[0] |= 1 << unsp_device::REG_SR; - desc.regin[0] |= 1 << opb; - desc.regout[0] |= 1 << unsp_device::REG_SR; - desc.regout[0] |= 1 << opb; + desc.regin.set(unsp_device::REG_SR); + desc.regin.set(opb); + desc.regout.set(unsp_device::REG_SR); + desc.regout.set(opb); if (op0 != 0x0d) - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); break; } } @@ -264,17 +291,17 @@ bool unsp_frontend::describe(opcode_desc &desc, const opcode_desc *prev) switch (lsbits) { case 0: // r, [r] - desc.regin[0] |= 1 << opb; + desc.regin.set(opb); if (op0 != 0x0d) - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); break; case 1: // r, [r--] case 2: // r, [r++] case 3: // r, [++r] - desc.regin[0] |= 1 << opb; - desc.regout[0] |= 1 << opb; + desc.regin.set(opb); + desc.regout.set(opb); if (op0 != 0x0d) - desc.flags |= OPFLAG_READS_MEMORY; + desc.set_reads_memory(); break; } } @@ -285,49 +312,49 @@ bool unsp_frontend::describe(opcode_desc &desc, const opcode_desc *prev) switch (opn) { case 0x00: // r - desc.cycles = (opa == 7 ? 5 : 3); - desc.regin[0] |= 1 << opb; + desc.cycles = (opa == 7) ? 5 : 3; + desc.regin.set(opb); break; case 0x01: // imm16 - desc.cycles = (opa == 7 ? 5 : 4); + desc.cycles = (opa == 7) ? 5 : 4; desc.length = 2; - desc.regin[0] |= 1 << opb; - desc.regin[0] |= 1 << unsp_device::REG_SR; - desc.regin[0] |= 1 << unsp_device::REG_PC; - desc.regout[0] |= 1 << unsp_device::REG_SR; - desc.regout[0] |= 1 << unsp_device::REG_PC; - desc.flags |= OPFLAG_READS_MEMORY; + desc.regin.set(opb); + desc.regin.set(unsp_device::REG_SR); + desc.regin.set(unsp_device::REG_PC); + desc.regout.set(unsp_device::REG_SR); + desc.regout.set(unsp_device::REG_PC); + desc.set_reads_memory(); break; case 0x02: // [imm16] case 0x03: // store [imm16], r - desc.cycles = (opa == 7 ? 8 : 7); + desc.cycles = (opa == 7) ? 8 : 7; desc.length = 2; - desc.regin[0] |= 1 << opb; - desc.regin[0] |= 1 << unsp_device::REG_SR; - desc.regin[0] |= 1 << unsp_device::REG_PC; - desc.regout[0] |= 1 << unsp_device::REG_SR; - desc.regout[0] |= 1 << unsp_device::REG_PC; - desc.flags |= OPFLAG_READS_MEMORY; + desc.regin.set(opb); + desc.regin.set(unsp_device::REG_SR); + desc.regin.set(unsp_device::REG_PC); + desc.regout.set(unsp_device::REG_SR); + desc.regout.set(unsp_device::REG_PC); + desc.set_reads_memory(); break; default: // Shifted ops - desc.cycles = (opa == 7 ? 5 : 3); - desc.regin[0] |= 1 << opb; + desc.cycles = (opa == 7) ? 5 : 3; + desc.regin.set(opb); break; } break; case 0x05: // More shifted ops case 0x06: // Rotated ops - desc.cycles = (opa == 7 ? 5 : 3); - desc.regin[0] |= 1 << opb; + desc.cycles = (opa == 7) ? 5 : 3; + desc.regin.set(opb); break; case 0x07: // Direct 8 - desc.cycles = (opa == 7 ? 6 : 5); - desc.flags |= OPFLAG_READS_MEMORY; + desc.cycles = (opa == 7) ? 6 : 5; + desc.set_reads_memory(); break; default: @@ -346,28 +373,29 @@ bool unsp_frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x09: // Load case 0x0a: // OR case 0x0b: // AND - desc.regout[0] |= 1 << unsp_device::REG_SR; + desc.regout.set(unsp_device::REG_SR); break; case 0x04: // Compare case 0x0c: // Test - desc.regout[0] |= 1 << unsp_device::REG_SR; + desc.regout.set(unsp_device::REG_SR); return true; case 0x0d: // Store - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); return true; } if (op1 == 0x04 && opn == 0x03) // store [imm16], r { - desc.flags |= OPFLAG_WRITES_MEMORY; + desc.set_writes_memory(); } else { - desc.regout[0] |= 1 << opa; + desc.regout.set(opa); if (opa == 7) { desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); } } diff --git a/src/devices/cpu/unsp/unspfe.h b/src/devices/cpu/unsp/unspfe.h index c30b2721e0a..60f9c4e6ce8 100644 --- a/src/devices/cpu/unsp/unspfe.h +++ b/src/devices/cpu/unsp/unspfe.h @@ -6,22 +6,55 @@ #pragma once #include "unsp.h" + #include "cpu/drcfe.h" -class unsp_frontend : public drc_frontend +#include <algorithm> + + +class unsp_device::opcode_desc : public opcode_desc_base<opcode_desc, 16> +{ +public: + uint16_t opptr[2]; // copy of opcode + + uint32_t cycles; // number of cycles needed to execute + + void set_reads_memory() { m_reads_memory = true; } + void set_writes_memory() { m_writes_memory = true; } + + bool reads_memory() const { return m_reads_memory; } + bool writes_memory() const { return m_writes_memory; } + + void reset(offs_t curpc, bool in_delay_slot) + { + opcode_desc_base::reset(curpc, in_delay_slot); + + std::fill(std::begin(opptr), std::end(opptr), 0); + cycles = 0; + m_reads_memory = false; + m_writes_memory = false; + } + +private: + bool m_reads_memory; + bool m_writes_memory; +}; + + +class unsp_device::frontend : public drc_frontend_base<opcode_desc> { public: - unsp_frontend(unsp_device *unsp, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); - void flush(); + frontend(unsp_device *unsp, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); + ~frontend(); -protected: - // required overrides - virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override; + opcode_desc const *describe_code(offs_t startpc); private: - inline uint16_t read_op_word(opcode_desc &desc, int offset); + bool describe(opcode_desc &desc, const opcode_desc *prev); + + uint16_t read_op_word(opcode_desc &desc, int offset); unsp_device *m_cpu; }; -#endif /* MAME_CPU_UNSP_UNSPFE_H */ +#endif // MAME_CPU_UNSP_UNSPFE_H diff --git a/src/devices/sound/swp30.h b/src/devices/sound/swp30.h index 671130a9d40..fa03df9e50d 100644 --- a/src/devices/sound/swp30.h +++ b/src/devices/sound/swp30.h @@ -8,9 +8,9 @@ #pragma once -#include "cpu/drcfe.h" #include "cpu/drcuml.h" + class swp30_disassembler : public util::disasm_interface { public: |
