summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2011-01-04 15:54:16 +0000
committer Aaron Giles <aaron@aarongiles.com>2011-01-04 15:54:16 +0000
commit9e5207ce91c362e4c9f51443ebcb7ffb7119cb76 (patch)
tree0052cd14a788e4b576a5852763d95f88017c8759
parent68ebcf02543e03d9e051e26884bb226a4d5c78b3 (diff)
C++-ified drcfe and the associated frontends. You now create a
frontend by deriving from drc_frontend and implementing the describe method. RB, if you send me your latest SH4 WIP, I'll convert it for you if this makes you cranky. :)
-rw-r--r--src/emu/cpu/drcfe.c508
-rw-r--r--src/emu/cpu/drcfe.h224
-rw-r--r--src/emu/cpu/mips/mips3drc.c78
-rw-r--r--src/emu/cpu/mips/mips3fe.c1234
-rw-r--r--src/emu/cpu/mips/mips3fe.h75
-rw-r--r--src/emu/cpu/powerpc/ppcdrc.c37
-rw-r--r--src/emu/cpu/powerpc/ppcfe.c1456
-rw-r--r--src/emu/cpu/powerpc/ppcfe.h81
-rw-r--r--src/emu/cpu/rsp/rspdrc.c33
-rw-r--r--src/emu/cpu/rsp/rspfe.c431
-rw-r--r--src/emu/cpu/rsp/rspfe.h40
-rw-r--r--src/emu/cpu/sh2/sh2comn.h25
-rw-r--r--src/emu/cpu/sh2/sh2drc.c37
-rw-r--r--src/emu/cpu/sh2/sh2fe.c716
14 files changed, 2509 insertions, 2466 deletions
diff --git a/src/emu/cpu/drcfe.c b/src/emu/cpu/drcfe.c
index c4dee7cc9aa..f39bfaf0bb1 100644
--- a/src/emu/cpu/drcfe.c
+++ b/src/emu/cpu/drcfe.c
@@ -4,9 +4,36 @@
Generic dynamic recompiler frontend structures and utilities.
+****************************************************************************
+
Copyright Aaron Giles
- Released for general non-commercial use under the MAME license
- Visit http://mamedev.org for licensing and usage restrictions.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
****************************************************************************
@@ -21,219 +48,120 @@
#include "drcfe.h"
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
-#define MAX_STACK_DEPTH 100
+const UINT32 MAX_STACK_DEPTH = 100;
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
-/* an entry that maps branches for our code walking */
-typedef struct _pc_stack_entry pc_stack_entry;
-struct _pc_stack_entry
+// an entry that maps branches for our code walking
+struct pc_stack_entry
{
offs_t targetpc;
offs_t srcpc;
};
-/* internal state */
-struct _drcfe_state
-{
- /* configuration parameters */
- UINT32 window_start; /* code window start offset = startpc - window_start */
- UINT32 window_end; /* code window end offset = startpc + window_end */
- UINT32 max_sequence; /* maximum instructions to include in a sequence */
-
- drcfe_describe_func describe; /* callback to describe a single instruction */
- void * param; /* parameter for the callback */
-
- /* CPU parameters */
- cpu_device * cpudevice; /* CPU device object */
- address_space *program; /* program address space for this CPU */
- offs_t pageshift; /* shift to convert address to a page index */
-
- /* opcode descriptor arrays */
- opcode_desc * desc_live_list; /* head of list of live descriptions */
- opcode_desc * desc_free_list; /* head of list of free descriptions */
- opcode_desc ** desc_array; /* array of descriptions in PC order */
- UINT32 desc_array_size; /* size of the array */
-};
-
-
-
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-static opcode_desc *describe_one(drcfe_state *drcfe, offs_t curpc, const opcode_desc *prevdesc);
-static opcode_desc **build_sequence(drcfe_state *drcfe, opcode_desc **tailptr, int start, int end, UINT32 endflag);
-static void accumulate_required_backwards(opcode_desc *desc, UINT32 *reqmask);
-static void release_descriptions(drcfe_state *drcfe, opcode_desc *desc);
-
-
-/***************************************************************************
- INLINE FUNCTIONS
-***************************************************************************/
-
-/*-------------------------------------------------
- desc_alloc - allocate a new opcode description
--------------------------------------------------*/
-
-INLINE opcode_desc *desc_alloc(drcfe_state *drcfe)
-{
- opcode_desc *desc = drcfe->desc_free_list;
-
- /* pull a description off of the free list or allocate a new one */
- if (desc != NULL)
- drcfe->desc_free_list = desc->next;
- else
- desc = auto_alloc(drcfe->cpudevice->machine, opcode_desc);
- return desc;
-}
+//**************************************************************************
+// DRC FRONTEND
+//**************************************************************************
+//-------------------------------------------------
+// drc_frontend - constructor
+//-------------------------------------------------
-/*-------------------------------------------------
- desc_free - free an opcode description
--------------------------------------------------*/
-
-INLINE void desc_free(drcfe_state *drcfe, opcode_desc *desc)
+drc_frontend::drc_frontend(device_t &cpu, UINT32 window_start, UINT32 window_end, UINT32 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)->m_page_shift),
+ m_desc_live_list(cpu.machine->m_respool),
+ m_desc_allocator(cpu.machine->m_respool),
+ m_desc_array(auto_alloc_array_clear(cpu.machine, opcode_desc *, window_end + window_start + 2))
{
- /* just put ourselves on the free list */
- desc->next = drcfe->desc_free_list;
- drcfe->desc_free_list = desc;
}
+//-------------------------------------------------
+// ~drc_frontend - destructor
+//-------------------------------------------------
-/***************************************************************************
- CORE IMPLEMENTATION
-***************************************************************************/
-
-/*-------------------------------------------------
- drcfe_init - initializate the drcfe state
--------------------------------------------------*/
-
-drcfe_state *drcfe_init(device_t *cpu, const drcfe_config *config, void *param)
+drc_frontend::~drc_frontend()
{
- drcfe_state *drcfe;
-
- /* allocate some memory to hold the state */
- drcfe = auto_alloc_clear(cpu->machine, drcfe_state);
-
- /* allocate the description array */
- drcfe->desc_array = auto_alloc_array_clear(cpu->machine, opcode_desc *, config->window_end + config->window_start + 2);
-
- /* copy in configuration information */
- drcfe->window_start = config->window_start;
- drcfe->window_end = config->window_end;
- drcfe->max_sequence = config->max_sequence;
- drcfe->describe = config->describe;
- drcfe->param = param;
+ // release any descriptions we've accumulated
+ release_descriptions();
- /* initialize the state */
- drcfe->cpudevice = downcast<cpu_device *>(cpu);
- drcfe->program = drcfe->cpudevice->space(AS_PROGRAM);
- drcfe->pageshift = drcfe->cpudevice->space_config(AS_PROGRAM)->m_page_shift;
-
- return drcfe;
+ // free the description array
+ auto_free(m_cpudevice.machine, m_desc_array);
}
-/*-------------------------------------------------
- drcfe_exit - clean up after ourselves
--------------------------------------------------*/
+//-------------------------------------------------
+// describe_code - describe a sequence of code
+// that falls within the configured window
+// relative to the specified startpc
+//-------------------------------------------------
-void drcfe_exit(drcfe_state *drcfe)
+const opcode_desc *drc_frontend::describe_code(offs_t startpc)
{
- /* release any descriptions we've accumulated */
- release_descriptions(drcfe, drcfe->desc_live_list);
-
- /* free our free list of descriptions */
- while (drcfe->desc_free_list != NULL)
- {
- opcode_desc *freeme = drcfe->desc_free_list;
- drcfe->desc_free_list = drcfe->desc_free_list->next;
- auto_free(drcfe->cpudevice->machine, freeme);
- }
-
- /* free the description array */
- auto_free(drcfe->cpudevice->machine, drcfe->desc_array);
-
- /* free the object itself */
- auto_free(drcfe->cpudevice->machine, drcfe);
-}
-
+ // release any descriptions we've accumulated
+ release_descriptions();
-/*-------------------------------------------------
- drcfe_describe_code - describe a sequence of
- code that falls within the configured window
- relative to the specified startpc
--------------------------------------------------*/
-
-const opcode_desc *drcfe_describe_code(drcfe_state *drcfe, offs_t startpc)
-{
- offs_t minpc = startpc - MIN(drcfe->window_start, startpc);
- offs_t maxpc = startpc + MIN(drcfe->window_end, 0xffffffff - startpc);
+ // add the initial PC to the stack
pc_stack_entry pcstack[MAX_STACK_DEPTH];
pc_stack_entry *pcstackptr = &pcstack[0];
- opcode_desc **tailptr;
-
- /* release any descriptions we've accumulated */
- release_descriptions(drcfe, drcfe->desc_live_list);
- drcfe->desc_live_list = NULL;
-
- /* add the initial PC to the stack */
pcstackptr->srcpc = 0;
pcstackptr->targetpc = startpc;
pcstackptr++;
- /* loop while we still have a stack */
+ // loop while we still have a stack
+ offs_t minpc = startpc - MIN(m_window_start, startpc);
+ offs_t maxpc = startpc + MIN(m_window_end, 0xffffffff - startpc);
while (pcstackptr != &pcstack[0])
{
+ // if we've already hit this PC, just mark it a branch target and continue
pc_stack_entry *curstack = --pcstackptr;
- opcode_desc *curdesc;
- offs_t curpc;
-
- /* if we've already hit this PC, just mark it a branch target and continue */
- curdesc = drcfe->desc_array[curstack->targetpc - minpc];
+ opcode_desc *curdesc = m_desc_array[curstack->targetpc - minpc];
if (curdesc != NULL)
{
curdesc->flags |= OPFLAG_IS_BRANCH_TARGET;
- /* if the branch crosses a page boundary, mark the target as needing to revalidate */
- if (drcfe->pageshift != 0 && ((curstack->srcpc ^ curdesc->pc) >> drcfe->pageshift) != 0)
+ // 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;
- /* continue processing */
+ // continue processing
continue;
}
- /* loop until we exit the block */
- for (curpc = curstack->targetpc; curpc >= minpc && curpc < maxpc && drcfe->desc_array[curpc - minpc] == NULL; curpc += drcfe->desc_array[curpc - minpc]->length)
+ // loop until we exit the block
+ for (offs_t curpc = curstack->targetpc; curpc >= minpc && curpc < maxpc && m_desc_array[curpc - minpc] == NULL; curpc += m_desc_array[curpc - minpc]->length)
{
- /* allocate a new description and describe this instruction */
- drcfe->desc_array[curpc - minpc] = curdesc = describe_one(drcfe, curpc, curdesc);
+ // allocate a new description and describe this instruction
+ m_desc_array[curpc - minpc] = curdesc = describe_one(curpc, curdesc);
- /* first instruction in a sequence is always a branch target */
+ // first instruction in a sequence is always a branch target
if (curpc == curstack->targetpc)
curdesc->flags |= OPFLAG_IS_BRANCH_TARGET;
- /* stop if we hit a page fault */
+ // stop if we hit a page fault
if (curdesc->flags & OPFLAG_COMPILER_PAGE_FAULT)
break;
- /* if we are the first instruction in the whole window, we must validate the TLB */
- if (curpc == startpc && drcfe->pageshift != 0)
+ // 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;
- /* if we are a branch within the block range, add the branch target to our stack */
+ // 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])
{
curdesc->flags |= OPFLAG_INTRABLOCK_BRANCH;
@@ -242,131 +170,113 @@ const opcode_desc *drcfe_describe_code(drcfe_state *drcfe, offs_t startpc)
pcstackptr++;
}
- /* if we're done, we're done */
+ // if we're done, we're done
if (curdesc->flags & OPFLAG_END_SEQUENCE)
break;
}
}
- /* now build the list of descriptions in order */
- /* first from startpc -> maxpc, then from minpc -> startpc */
- tailptr = build_sequence(drcfe, &drcfe->desc_live_list, startpc - minpc, maxpc - minpc, OPFLAG_REDISPATCH);
- tailptr = build_sequence(drcfe, tailptr, minpc - minpc, startpc - minpc, OPFLAG_RETURN_TO_START);
- return drcfe->desc_live_list;
+ // 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);
+ return m_desc_live_list.first();
}
+//-------------------------------------------------
+// describe_one - describe a single instruction,
+// recursively describing opcodes in delay
+// slots of branches as well
+//-------------------------------------------------
-/***************************************************************************
- INTERNAL HELPERS
-***************************************************************************/
-
-/*-------------------------------------------------
- describe_one - describe a single instruction,
- recursively describing opcodes in delay
- slots of branches as well
--------------------------------------------------*/
-
-static opcode_desc *describe_one(drcfe_state *drcfe, offs_t curpc, const opcode_desc *prevdesc)
+opcode_desc *drc_frontend::describe_one(offs_t curpc, const opcode_desc *prevdesc)
{
- opcode_desc *desc = desc_alloc(drcfe);
-
- /* initialize the description */
+ // initialize the description
+ opcode_desc *desc = m_desc_allocator.alloc();
memset(desc, 0, sizeof(*desc));
desc->pc = curpc;
desc->physpc = curpc;
desc->targetpc = BRANCH_TARGET_DYNAMIC;
- /* call the callback to describe an instruction */
- if (!(*drcfe->describe)(drcfe->param, desc, prevdesc))
+ // call the callback to describe an instruction
+ if (!describe(*desc, prevdesc))
{
desc->flags |= OPFLAG_WILL_CAUSE_EXCEPTION | OPFLAG_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 (drcfe->pageshift != 0 && (((curpc - 1) ^ (curpc + desc->length - 1)) >> drcfe->pageshift) != 0)
+ // 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;
- /* validate stuff */
+ // validate stuff
assert(desc->length > 0 || (desc->flags & OPFLAG_VIRTUAL_NOOP) != 0);
- /* if we are a branch with delay slots, recursively walk those */
+ // if we are a branch with delay slots, recursively walk those
if (desc->flags & OPFLAG_IS_BRANCH)
{
- opcode_desc **tailptr = &desc->delay;
+ // iterate over slots and describe them
offs_t delaypc = curpc + desc->length;
opcode_desc *prev = desc;
- UINT8 slotnum;
-
- /* iterate over slots and describe them */
- for (slotnum = 0; slotnum < desc->delayslots; slotnum++)
+ for (UINT8 slotnum = 0; slotnum < desc->delayslots; slotnum++)
{
- /* recursively describe the next instruction */
- *tailptr = describe_one(drcfe, delaypc, prev);
- if (*tailptr == NULL)
+ // recursively describe the next instruction
+ opcode_desc *delaydesc = describe_one(delaypc, prev);
+ if (delaydesc == NULL)
break;
+ desc->delay.append(*delaydesc);
+ prev = desc;
- /* set the delay slot flag and a pointer back to the original branch */
- (*tailptr)->flags |= OPFLAG_IN_DELAY_SLOT;
- (*tailptr)->branch = desc;
- (*tailptr)->prev = prev;
- prev = *tailptr;
+ // set the delay slot flag and a pointer back to the original branch
+ delaydesc->flags |= OPFLAG_IN_DELAY_SLOT;
+ delaydesc->branch = desc;
- /* stop if we hit a page fault */
- if ((*tailptr)->flags & OPFLAG_COMPILER_PAGE_FAULT)
+ // stop if we hit a page fault
+ if (delaydesc->flags & OPFLAG_COMPILER_PAGE_FAULT)
break;
- /* otherwise, advance */
- delaypc += (*tailptr)->length;
- tailptr = &(*tailptr)->next;
+ // otherwise, advance
+ delaypc += delaydesc->length;
}
}
-
return desc;
}
-/*-------------------------------------------------
- build_sequence - build an ordered sequence
- of instructions
--------------------------------------------------*/
+//-------------------------------------------------
+// build_sequence - build an ordered sequence
+// of instructions
+//-------------------------------------------------
-static opcode_desc **build_sequence(drcfe_state *drcfe, opcode_desc **tailptr, int start, int end, UINT32 endflag)
+void drc_frontend::build_sequence(int start, int end, UINT32 endflag)
{
- opcode_desc *prev = NULL;
+ // iterate in order from start to end, picking up all non-NULL instructions
int consecutive = 0;
int seqstart = -1;
int skipsleft = 0;
- int descnum;
-
- /* iterate in order from start to end, picking up all non-NULL instructions */
- for (descnum = start; descnum < end; descnum++)
- if (drcfe->desc_array[descnum] != NULL)
+ for (int descnum = start; descnum < end; descnum++)
+ if (m_desc_array[descnum] != NULL)
{
- opcode_desc *curdesc = drcfe->desc_array[descnum];
- opcode_desc *nextdesc = NULL;
- int nextdescnum;
- UINT8 skipnum;
-
- /* determine the next instruction, taking skips into account */
- nextdescnum = descnum + curdesc->length;
- nextdesc = (nextdescnum < end) ? drcfe->desc_array[nextdescnum] : NULL;
- for (skipnum = 0; skipnum < curdesc->skipslots && nextdesc != NULL; skipnum++)
+ // determine the next instruction, taking skips into account
+ opcode_desc *curdesc = m_desc_array[descnum];
+ int nextdescnum = descnum + curdesc->length;
+ opcode_desc *nextdesc = (nextdescnum < end) ? m_desc_array[nextdescnum] : NULL;
+ for (UINT8 skipnum = 0; skipnum < curdesc->skipslots && nextdesc != NULL; skipnum++)
{
nextdescnum = nextdescnum + nextdesc->length;
- nextdesc = (nextdescnum < end) ? drcfe->desc_array[nextdescnum] : NULL;
+ nextdesc = (nextdescnum < end) ? m_desc_array[nextdescnum] : NULL;
}
- /* start a new sequence if we aren't already in the middle of one */
+ // start a new sequence if we aren't already in the middle of one
if (seqstart == -1 && skipsleft == 0)
{
- /* tag all start-of-sequence instructions as needing TLB verification */
+ // tag all start-of-sequence instructions as needing TLB verification
curdesc->flags |= OPFLAG_VALIDATE_TLB | OPFLAG_CAN_CAUSE_EXCEPTION;
seqstart = descnum;
}
- /* if we are the last instruction, indicate end-of-sequence and redispatch */
+ // if we are the last instruction, indicate end-of-sequence and redispatch
if (nextdesc == NULL)
{
curdesc->flags |= OPFLAG_END_SEQUENCE;
@@ -374,134 +284,118 @@ static opcode_desc **build_sequence(drcfe_state *drcfe, opcode_desc **tailptr, i
curdesc->flags |= endflag;
}
- /* otherwise, do some analysis based on the next instruction */
+ // otherwise, do some analysis based on the next instruction
else
{
- opcode_desc *scandesc = NULL;
+ // if there are instructions between us and the next instruction, we must end our sequence here
int scandescnum;
-
- /* if there are instructions between us and the next instruction, we must end our sequence here */
+ opcode_desc *scandesc = NULL;
for (scandescnum = descnum + 1; scandescnum < end; scandescnum++)
{
- scandesc = drcfe->desc_array[scandescnum];
+ scandesc = m_desc_array[scandescnum];
if (scandesc != NULL || scandesc == nextdesc)
break;
}
if (scandesc != nextdesc)
curdesc->flags |= OPFLAG_END_SEQUENCE;
- /* if the next instruction is a branch target, mark this instruction as end of 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 we exceed the maximum consecutive count, cut off the sequence */
- if (++consecutive >= drcfe->max_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)
consecutive = 0;
- /* if this is the end of a sequence, work backwards */
+ // if this is the end of a sequence, work backwards
if (curdesc->flags & OPFLAG_END_SEQUENCE)
{
+ // figure out which registers we *must* generate, assuming at the end all must be
UINT32 reqmask[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
- int backdesc;
-
- /* figure out which registers we *must* generate, assuming at the end all must be */
if (seqstart != -1)
- for (backdesc = descnum; backdesc != seqstart - 1; backdesc--)
- if (drcfe->desc_array[backdesc] != NULL)
- accumulate_required_backwards(drcfe->desc_array[backdesc], reqmask);
+ for (int backdesc = descnum; backdesc != seqstart - 1; backdesc--)
+ if (m_desc_array[backdesc] != NULL)
+ accumulate_required_backwards(*m_desc_array[backdesc], reqmask);
- /* reset the register states */
+ // reset the register states
seqstart = -1;
}
- /* if we have instructions remaining to be skipped, and this instruction is a branch target */
- /* belay the skip order */
+ // 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))
skipsleft = 0;
- /* if we're not getting skipped, add us to the end of the list and clear our array slot */
+ // if we're not getting skipped, add us to the end of the list and clear our array slot
if (skipsleft == 0)
- {
- *tailptr = curdesc;
- tailptr = &curdesc->next;
- curdesc->prev = prev;
- prev = curdesc;
- }
+ m_desc_live_list.append(*curdesc);
else
- desc_free(drcfe, curdesc);
+ m_desc_allocator.reclaim(*curdesc);
- /* if the current instruction starts skipping, reset our skip count */
- /* otherwise, just decrement */
+ // if the current instruction starts skipping, reset our skip count
+ // otherwise, just decrement
if (curdesc->skipslots > 0)
skipsleft = curdesc->skipslots;
else if (skipsleft > 0)
skipsleft--;
}
- /* zap the array */
- memset(&drcfe->desc_array[start], 0, (end - start) * sizeof(drcfe->desc_array[0]));
-
- /* return the final tailptr */
- return tailptr;
+ // zap the array
+ memset(&m_desc_array[start], 0, (end - start) * sizeof(m_desc_array[0]));
}
-/*-------------------------------------------------
- accumulate_required_backwards - recursively
- accumulate live register liveness information
- walking in a backwards direction
--------------------------------------------------*/
+//-------------------------------------------------
+// accumulate_required_backwards - recursively
+// accumulate live register liveness information
+// walking in a backwards direction
+//-------------------------------------------------
-static void accumulate_required_backwards(opcode_desc *desc, UINT32 *reqmask)
+void drc_frontend::accumulate_required_backwards(opcode_desc &desc, UINT32 *reqmask)
{
- /* recursively handle delay slots */
- if (desc->delay != NULL)
- accumulate_required_backwards(desc->delay, reqmask);
+ // recursively handle delay slots
+ if (desc.delay.first() != NULL)
+ accumulate_required_backwards(*desc.delay.first(), reqmask);
- /* if this is a branch, we have to reset our requests */
- if (desc->flags & OPFLAG_IS_BRANCH)
+ // 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;
- /* 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];
-
- /* 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];
-
- /* 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];
+ // 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];
+
+ // 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];
+
+ // 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];
}
-/*-------------------------------------------------
- release_descriptions - release any
- descriptions we've allocated back to the
- free list
-------------------------------------------------*/
+//-------------------------------------------------
+// release_descriptions - release any
+// descriptions we've allocated back to the
+// free list
+//------------------------------------------------
-static void release_descriptions(drcfe_state *drcfe, opcode_desc *desc)
+void drc_frontend::release_descriptions()
{
- /* loop while we still have valid entries */
- while (desc != NULL)
- {
- opcode_desc *freeme = desc;
-
- /* recursively release delay slots */
- if (desc->delay != NULL)
- release_descriptions(drcfe, desc->delay);
- desc = desc->next;
- desc_free(drcfe, freeme);
- }
+ // release all delay slots first
+ for (opcode_desc *curdesc = m_desc_live_list.first(); curdesc != NULL; curdesc = curdesc->next())
+ m_desc_allocator.reclaim_all(curdesc->delay);
+
+ // reclaim all the descriptors
+ m_desc_allocator.reclaim_all(m_desc_live_list);
}
diff --git a/src/emu/cpu/drcfe.h b/src/emu/cpu/drcfe.h
index 38de85a6ccf..7849aed73c9 100644
--- a/src/emu/cpu/drcfe.h
+++ b/src/emu/cpu/drcfe.h
@@ -4,9 +4,36 @@
Generic dynamic recompiler frontend structures and utilities.
+****************************************************************************
+
Copyright Aaron Giles
- Released for general non-commercial use under the MAME license
- Visit http://mamedev.org for licensing and usage restrictions.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
****************************************************************************
@@ -37,125 +64,130 @@
#define __DRCFE_H__
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
-/* this defines a branch targetpc that is dynamic at runtime */
-#define BRANCH_TARGET_DYNAMIC (~0)
+// this defines a branch targetpc that is dynamic at runtime
+const offs_t BRANCH_TARGET_DYNAMIC = ~0;
-/* opcode branch flags */
-#define OPFLAG_IS_UNCONDITIONAL_BRANCH 0x00000001 /* instruction is unconditional branch */
-#define OPFLAG_IS_CONDITIONAL_BRANCH 0x00000002 /* instruction is conditional branch */
-#define OPFLAG_IS_BRANCH (OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_IS_CONDITIONAL_BRANCH)
-#define OPFLAG_IS_BRANCH_TARGET 0x00000004 /* instruction is the target of a branch */
-#define OPFLAG_IN_DELAY_SLOT 0x00000008 /* instruction is in the delay slot of a branch */
-#define OPFLAG_INTRABLOCK_BRANCH 0x00000010 /* instruction branches within the block */
+// opcode branch flags
+const UINT32 OPFLAG_IS_UNCONDITIONAL_BRANCH = 0x00000001; // instruction is unconditional branch
+const UINT32 OPFLAG_IS_CONDITIONAL_BRANCH = 0x00000002; // instruction is conditional branch
+const UINT32 OPFLAG_IS_BRANCH = (OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_IS_CONDITIONAL_BRANCH);
+const UINT32 OPFLAG_IS_BRANCH_TARGET = 0x00000004; // instruction is the target of a branch
+const UINT32 OPFLAG_IN_DELAY_SLOT = 0x00000008; // instruction is in the delay slot of a branch
+const UINT32 OPFLAG_INTRABLOCK_BRANCH = 0x00000010; // instruction branches within the block
-/* opcode exception flags */
-#define OPFLAG_CAN_TRIGGER_SW_INT 0x00000020 /* instruction can trigger a software interrupt */
-#define OPFLAG_CAN_EXPOSE_EXTERNAL_INT 0x00000040 /* instruction can expose an external interrupt */
-#define OPFLAG_CAN_CAUSE_EXCEPTION 0x00000080 /* instruction may generate exception */
-#define OPFLAG_WILL_CAUSE_EXCEPTION 0x00000100 /* instruction will generate exception */
-#define OPFLAG_PRIVILEGED 0x00000200 /* instruction is privileged */
+// opcode exception flags
+const UINT32 OPFLAG_CAN_TRIGGER_SW_INT = 0x00000020; // instruction can trigger a software interrupt
+const UINT32 OPFLAG_CAN_EXPOSE_EXTERNAL_INT = 0x00000040; // instruction can expose an external interrupt
+const UINT32 OPFLAG_CAN_CAUSE_EXCEPTION = 0x00000080; // instruction may generate exception
+const UINT32 OPFLAG_WILL_CAUSE_EXCEPTION = 0x00000100; // instruction will generate exception
+const UINT32 OPFLAG_PRIVILEGED = 0x00000200; // instruction is privileged
-/* opcode virtual->physical translation flags */
-#define OPFLAG_VALIDATE_TLB 0x00000400 /* instruction must validate TLB before execution */
-#define OPFLAG_MODIFIES_TRANSLATION 0x00000800 /* instruction modifies the TLB */
-#define OPFLAG_COMPILER_PAGE_FAULT 0x00001000 /* compiler hit a page fault when parsing */
-#define OPFLAG_COMPILER_UNMAPPED 0x00002000 /* compiler hit unmapped memory when parsing */
+// opcode virtual->physical translation flags
+const UINT32 OPFLAG_VALIDATE_TLB = 0x00000400; // instruction must validate TLB before execution
+const UINT32 OPFLAG_MODIFIES_TRANSLATION = 0x00000800; // instruction modifies the TLB
+const UINT32 OPFLAG_COMPILER_PAGE_FAULT = 0x00001000; // compiler hit a page fault when parsing
+const UINT32 OPFLAG_COMPILER_UNMAPPED = 0x00002000; // compiler hit unmapped memory when parsing
-/* opcode flags */
-#define OPFLAG_INVALID_OPCODE 0x00004000 /* instruction is invalid */
-#define OPFLAG_VIRTUAL_NOOP 0x00008000 /* instruction is a virtual no-op */
+// opcode flags
+const UINT32 OPFLAG_INVALID_OPCODE = 0x00004000; // instruction is invalid
+const UINT32 OPFLAG_VIRTUAL_NOOP = 0x00008000; // instruction is a virtual no-op
-/* opcode sequence flow flags */
-#define OPFLAG_REDISPATCH 0x00010000 /* instruction must redispatch after completion */
-#define OPFLAG_RETURN_TO_START 0x00020000 /* instruction must jump back to the beginning after completion */
-#define OPFLAG_END_SEQUENCE 0x00040000 /* this is the last instruction in a sequence */
-#define OPFLAG_CAN_CHANGE_MODES 0x00080000 /* instruction can change modes */
+// opcode sequence flow flags
+const UINT32 OPFLAG_REDISPATCH = 0x00010000; // instruction must redispatch after completion
+const UINT32 OPFLAG_RETURN_TO_START = 0x00020000; // instruction must jump back to the beginning after completion
+const UINT32 OPFLAG_END_SEQUENCE = 0x00040000; // this is the last instruction in a sequence
+const UINT32 OPFLAG_CAN_CHANGE_MODES = 0x00080000; // instruction can change modes
-/* execution semantics */
-#define OPFLAG_READS_MEMORY 0x00100000 /* instruction reads memory */
-#define OPFLAG_WRITES_MEMORY 0x00200000 /* instruction writes memory */
+// execution semantics
+const UINT32 OPFLAG_READS_MEMORY = 0x00100000; // instruction reads memory
+const UINT32 OPFLAG_WRITES_MEMORY = 0x00200000; // instruction writes memory
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
-/* opaque internal state */
-typedef struct _drcfe_state drcfe_state;
+// description of a given opcode
+struct opcode_desc
+{
+ opcode_desc *next() const { return m_next; }
+ // 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
-/* description of a given opcode */
-typedef struct _opcode_desc opcode_desc;
-struct _opcode_desc
-{
- /* links to other descriptions */
- opcode_desc * next; /* pointer to next description */
- opcode_desc * prev; /* pointer to previous description */
- opcode_desc * branch; /* pointer back to branch description for delay slots */
- opcode_desc * 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 */
+ // 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
{
UINT8 b[16];
UINT16 w[8];
UINT32 l[4];
UINT64 q[2];
- } opptr; /* pointer to opcode memory */
-
- /* information about this instruction's execution */
- UINT8 length; /* length in bytes of this opcode */
- UINT8 delayslots; /* number of delay slots (for branches) */
- UINT8 skipslots; /* number of skip slots (for branches) */
- UINT32 flags; /* OPFLAG_* opcode flags */
- UINT32 cycles; /* number of cycles needed to execute */
-
- /* register usage information */
- UINT32 regin[4]; /* input registers */
- UINT32 regout[4]; /* output registers */
- UINT32 regreq[4]; /* required output registers */
+ } opptr; // pointer to opcode memory
+
+ // information about this instruction's execution
+ UINT8 length; // length in bytes of this opcode
+ UINT8 delayslots; // number of delay slots (for branches)
+ UINT8 skipslots; // number of skip slots (for branches)
+ UINT32 flags; // OPFLAG_* opcode flags
+ UINT32 cycles; // number of cycles needed to execute
+
+ // register usage information
+ UINT32 regin[4]; // input registers
+ UINT32 regout[4]; // output registers
+ UINT32 regreq[4]; // required output registers
};
-/* callback function that is used to describe a single opcode */
-typedef int (*drcfe_describe_func)(void *param, opcode_desc *desc, const opcode_desc *prev);
-
-
-/* description of a given opcode */
-typedef struct _drcfe_config drcfe_config;
-struct _drcfe_config
+// DRC frontend state
+class drc_frontend
{
- UINT32 window_start; /* code window start offset = startpc - window_start */
- UINT32 window_end; /* code window end offset = startpc + window_end */
- UINT32 max_sequence; /* maximum instructions to include in a sequence */
- drcfe_describe_func describe; /* callback to describe a single instruction */
+public:
+ // construction/destruction
+ drc_frontend(device_t &cpu, UINT32 window_start, UINT32 window_end, UINT32 max_sequence);
+ virtual ~drc_frontend();
+
+ // describe a block
+ const opcode_desc *describe_code(offs_t startpc);
+
+protected:
+ // required overrides
+ virtual bool describe(opcode_desc &desc, const opcode_desc *prev) = 0;
+
+private:
+ // internal helpers
+ opcode_desc *describe_one(offs_t curpc, const opcode_desc *prevdesc);
+ void build_sequence(int start, int end, UINT32 endflag);
+ void accumulate_required_backwards(opcode_desc &desc, UINT32 *reqmask);
+ void release_descriptions();
+
+ // configuration parameters
+ UINT32 m_window_start; // code window start offset = startpc - window_start
+ UINT32 m_window_end; // code window end offset = startpc + window_end
+ UINT32 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
+
+ // 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
+ opcode_desc ** m_desc_array; // array of descriptions in PC order
};
-
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-/* initializate the drcfe state */
-drcfe_state *drcfe_init(device_t *cpu, const drcfe_config *config, void *param);
-
-/* clean up after ourselves */
-void drcfe_exit(drcfe_state *drcfe);
-
-/* describe a sequence of code that falls within the configured window relative to the specified startpc */
-const opcode_desc *drcfe_describe_code(drcfe_state *drcfe, offs_t startpc);
-
-
#endif /* __DRCFE_H__ */
diff --git a/src/emu/cpu/mips/mips3drc.c b/src/emu/cpu/mips/mips3drc.c
index 69c1d07e1ac..86e12e91a9d 100644
--- a/src/emu/cpu/mips/mips3drc.c
+++ b/src/emu/cpu/mips/mips3drc.c
@@ -4,9 +4,36 @@
Universal machine language-based MIPS III/IV emulator.
+****************************************************************************
+
Copyright Aaron Giles
- Released for general non-commercial use under the MAME license
- Visit http://mamedev.org for licensing and usage restrictions.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
****************************************************************************
@@ -159,7 +186,7 @@ struct _mips3imp_state
/* core state */
drccache * cache; /* pointer to the DRC code cache */
drcuml_state * drcuml; /* DRC UML generator state */
- drcfe_state * drcfe; /* pointer to the DRC front-end state */
+ mips3_frontend * drcfe; /* pointer to the DRC front-end state */
UINT32 drcoptions; /* configurable DRC options */
/* internal stuff */
@@ -360,13 +387,6 @@ INLINE void save_fast_iregs(mips3_state *mips3, drcuml_block *block)
static void mips3_init(mips3_flavor flavor, int bigendian, legacy_cpu_device *device, device_irq_callback irqcallback)
{
- drcfe_config feconfig =
- {
- COMPILE_BACKWARDS_BYTES, /* code window start offset = startpc - window_start */
- COMPILE_FORWARDS_BYTES, /* code window end offset = startpc + window_end */
- COMPILE_MAX_SEQUENCE, /* maximum instructions to include in a sequence */
- mips3fe_describe /* callback to describe a single instruction */
- };
mips3_state *mips3;
drccache *cache;
drcbe_info beinfo;
@@ -445,9 +465,7 @@ static void mips3_init(mips3_flavor flavor, int bigendian, legacy_cpu_device *de
drcuml_symbol_add(mips3->impstate->drcuml, &mips3->impstate->fpmode, sizeof(mips3->impstate->fpmode), "fpmode");
/* initialize the front-end helper */
- if (SINGLE_INSTRUCTION_MODE)
- feconfig.max_sequence = 1;
- mips3->impstate->drcfe = drcfe_init(device, &feconfig, mips3);
+ mips3->impstate->drcfe = auto_alloc(device->machine, mips3_frontend(*mips3, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE));
/* allocate memory for cache-local state and initialize it */
memcpy(mips3->impstate->fpmode, fpmode_source, sizeof(fpmode_source));
@@ -546,7 +564,7 @@ static CPU_EXIT( mips3 )
mips3com_exit(mips3);
/* clean up the DRC */
- drcfe_exit(mips3->impstate->drcfe);
+ auto_free(device->machine, mips3->impstate->drcfe);
drcuml_free(mips3->impstate->drcuml);
drccache_free(mips3->impstate->cache);
}
@@ -745,7 +763,7 @@ static void code_compile_block(mips3_state *mips3, UINT8 mode, offs_t pc)
g_profiler.start(PROFILER_DRC_COMPILE);
/* get a description of this sequence */
- desclist = drcfe_describe_code(mips3->impstate->drcfe, pc);
+ desclist = mips3->impstate->drcfe->describe_code(pc);
if (LOG_UML || LOG_NATIVE)
log_opcode_desc(drcuml, desclist, 0);
@@ -757,7 +775,7 @@ static void code_compile_block(mips3_state *mips3, UINT8 mode, offs_t pc)
block = drcuml_block_begin(drcuml, 4096, &errorbuf);
/* loop until we get through all instruction sequences */
- for (seqhead = desclist; seqhead != NULL; seqhead = seqlast->next)
+ for (seqhead = desclist; seqhead != NULL; seqhead = seqlast->next())
{
const opcode_desc *curdesc;
UINT32 nextpc;
@@ -767,7 +785,7 @@ static void code_compile_block(mips3_state *mips3, UINT8 mode, offs_t pc)
UML_COMMENT(block, "-------------------------"); // comment
/* determine the last instruction in this sequence */
- for (seqlast = seqhead; seqlast != NULL; seqlast = seqlast->next)
+ for (seqlast = seqhead; seqlast != NULL; seqlast = seqlast->next())
if (seqlast->flags & OPFLAG_END_SEQUENCE)
break;
assert(seqlast != NULL);
@@ -802,7 +820,7 @@ static void code_compile_block(mips3_state *mips3, UINT8 mode, offs_t pc)
UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc | 0x80000000
/* iterate over instructions in the sequence and compile them */
- for (curdesc = seqhead; curdesc != seqlast->next; curdesc = curdesc->next)
+ for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next())
generate_sequence_instruction(mips3, block, &compiler, curdesc);
/* if we need to return to the start, do it */
@@ -820,7 +838,7 @@ static void code_compile_block(mips3_state *mips3, UINT8 mode, offs_t pc)
if (seqlast->flags & OPFLAG_CAN_CHANGE_MODES)
UML_HASHJMP(block, MEM(&mips3->impstate->mode), IMM(nextpc), mips3->impstate->nocode);
// hashjmp <mode>,nextpc,nocode
- else if (seqlast->next == NULL || seqlast->next->pc != nextpc)
+ else if (seqlast->next() == NULL || seqlast->next()->pc != nextpc)
UML_HASHJMP(block, IMM(mips3->impstate->mode), IMM(nextpc), mips3->impstate->nocode);
// hashjmp <mode>,nextpc,nocode
}
@@ -1521,7 +1539,7 @@ static void generate_checksum_block(mips3_state *mips3, drcuml_block *block, com
UML_COMMENT(block, "[Validation for %08X]", seqhead->pc); // comment
/* loose verify or single instruction: just compare and fail */
- if (!(mips3->impstate->drcoptions & MIPS3DRC_STRICT_VERIFY) || seqhead->next == NULL)
+ if (!(mips3->impstate->drcoptions & MIPS3DRC_STRICT_VERIFY) || seqhead->next() == NULL)
{
if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP))
{
@@ -1536,7 +1554,7 @@ static void generate_checksum_block(mips3_state *mips3, drcuml_block *block, com
else
{
#if 0
- for (curdesc = seqhead->next; curdesc != seqlast->next; curdesc = curdesc->next)
+ for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
{
void *base = mips3->direct->read_decrypted_ptr(seqhead->physpc);
@@ -1549,7 +1567,7 @@ static void generate_checksum_block(mips3_state *mips3, drcuml_block *block, com
void *base = mips3->direct->read_decrypted_ptr(seqhead->physpc);
UML_LOAD(block, IREG(0), base, IMM(0), DWORD); // load i0,base,0,dword
sum += seqhead->opptr.l[0];
- for (curdesc = seqhead->next; curdesc != seqlast->next; curdesc = curdesc->next)
+ for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
{
base = mips3->direct->read_decrypted_ptr(curdesc->physpc);
@@ -1557,12 +1575,12 @@ static void generate_checksum_block(mips3_state *mips3, drcuml_block *block, com
UML_ADD(block, IREG(0), IREG(0), IREG(1)); // add i0,i0,i1
sum += curdesc->opptr.l[0];
- if (curdesc->delay != NULL && (curdesc == seqlast || (curdesc->next != NULL && curdesc->next->physpc != curdesc->delay->physpc)))
+ if (curdesc->delay.first() != NULL && (curdesc == seqlast || (curdesc->next() != NULL && curdesc->next()->physpc != curdesc->delay.first()->physpc)))
{
- base = mips3->direct->read_decrypted_ptr(curdesc->delay->physpc);
+ base = mips3->direct->read_decrypted_ptr(curdesc->delay.first()->physpc);
UML_LOAD(block, IREG(1), base, IMM(0), DWORD); // load i1,base,dword
UML_ADD(block, IREG(0), IREG(0), IREG(1)); // add i0,i0,i1
- sum += curdesc->delay->opptr.l[0];
+ sum += curdesc->delay.first()->opptr.l[0];
}
}
UML_CMP(block, IREG(0), IMM(sum)); // cmp i0,sum
@@ -1710,8 +1728,8 @@ static void generate_delay_slot_and_branch(mips3_state *mips3, drcuml_block *blo
UML_DMOV(block, R64(linkreg), IMM((INT32)(desc->pc + 8))); // dmov <linkreg>,desc->pc + 8
/* compile the delay slot using temporary compiler state */
- assert(desc->delay != NULL);
- generate_sequence_instruction(mips3, block, &compiler_temp, desc->delay); // <next instruction>
+ assert(desc->delay.first() != NULL);
+ generate_sequence_instruction(mips3, block, &compiler_temp, desc->delay.first()); // <next instruction>
/* update the cycles and jump through the hash table to the target */
if (desc->targetpc != BRANCH_TARGET_DYNAMIC)
@@ -3648,7 +3666,7 @@ static void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, i
drcuml_log_printf(drcuml, "\nDescriptor list @ %08X\n", desclist->pc);
/* output each descriptor */
- for ( ; desclist != NULL; desclist = desclist->next)
+ for ( ; desclist != NULL; desclist = desclist->next())
{
char buffer[100];
@@ -3669,8 +3687,8 @@ static void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, i
drcuml_log_printf(drcuml, "\n");
/* if we have a delay slot, output it recursively */
- if (desclist->delay != NULL)
- log_opcode_desc(drcuml, desclist->delay, indent + 1);
+ if (desclist->delay.first() != NULL)
+ log_opcode_desc(drcuml, desclist->delay.first(), indent + 1);
/* at the end of a sequence add a dividing line */
if (desclist->flags & OPFLAG_END_SEQUENCE)
diff --git a/src/emu/cpu/mips/mips3fe.c b/src/emu/cpu/mips/mips3fe.c
index b7254c27b4a..dbc5b8f40bd 100644
--- a/src/emu/cpu/mips/mips3fe.c
+++ b/src/emu/cpu/mips/mips3fe.c
@@ -4,9 +4,36 @@
Front-end for MIPS3 recompiler
+****************************************************************************
+
Copyright Aaron Giles
- Released for general non-commercial use under the MAME license
- Visit http://mamedev.org for licensing and usage restrictions.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
@@ -15,740 +42,729 @@
#include "mips3com.h"
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-static int describe_instruction_special(mips3_state *mips, UINT32 op, opcode_desc *desc);
-static int describe_instruction_regimm(mips3_state *mips, UINT32 op, opcode_desc *desc);
-static int describe_instruction_idt(mips3_state *mips, UINT32 op, opcode_desc *desc);
-static int describe_instruction_cop0(mips3_state *mips, UINT32 op, opcode_desc *desc);
-static int describe_instruction_cop1(mips3_state *mips, UINT32 op, opcode_desc *desc);
-static int describe_instruction_cop1x(mips3_state *mips, UINT32 op, opcode_desc *desc);
-static int describe_instruction_cop2(mips3_state *mips, UINT32 op, opcode_desc *desc);
+//**************************************************************************
+// MIPS3 FRONTEND
+//**************************************************************************
+//-------------------------------------------------
+// mips3_frontend - constructor
+//-------------------------------------------------
+mips3_frontend::mips3_frontend(mips3_state &state, UINT32 window_start, UINT32 window_end, UINT32 max_sequence)
+ : drc_frontend(*state.device, window_start, window_end, max_sequence),
+ m_context(state)
+{
+}
-/***************************************************************************
- INSTRUCTION PARSERS
-***************************************************************************/
-/*-------------------------------------------------
- describe_instruction - build a description
- of a single instruction
--------------------------------------------------*/
+//-------------------------------------------------
+// describe - build a description of a single
+// instruction
+//-------------------------------------------------
-int mips3fe_describe(void *param, opcode_desc *desc, const opcode_desc *prev)
+bool mips3_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
{
- mips3_state *mips = (mips3_state *)param;
UINT32 op, opswitch;
- /* compute the physical PC */
- assert((desc->physpc & 3) == 0);
- if (!mips3com_translate_address(mips, ADDRESS_SPACE_PROGRAM, TRANSLATE_FETCH, &desc->physpc))
+ // compute the physical PC
+ assert((desc.physpc & 3) == 0);
+ if (!mips3com_translate_address(&m_context, ADDRESS_SPACE_PROGRAM, TRANSLATE_FETCH, &desc.physpc))
{
- /* 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;
- return TRUE;
+ // 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;
+ return true;
}
- /* fetch the opcode */
- assert((desc->physpc & 3) == 0);
- op = desc->opptr.l[0] = mips->direct->read_decrypted_dword(desc->physpc);
+ // fetch the opcode
+ assert((desc.physpc & 3) == 0);
+ op = desc.opptr.l[0] = m_context.direct->read_decrypted_dword(desc.physpc);
- /* all instructions are 4 bytes and default to a single cycle each */
- desc->length = 4;
- desc->cycles = 1;
+ // all instructions are 4 bytes and default to a single cycle each
+ desc.length = 4;
+ desc.cycles = 1;
- /* parse the instruction */
+ // parse the instruction
opswitch = op >> 26;
switch (opswitch)
{
- case 0x00: /* SPECIAL */
- return describe_instruction_special(mips, op, desc);
-
- case 0x01: /* REGIMM */
- return describe_instruction_regimm(mips, op, desc);
-
- case 0x10: /* COP0 */
- return describe_instruction_cop0(mips, op, desc);
-
- case 0x11: /* COP1 */
- return describe_instruction_cop1(mips, op, desc);
-
- case 0x12: /* COP2 */
- return describe_instruction_cop2(mips, op, desc);
-
- case 0x13: /* COP1X - MIPS IV */
- if (mips->flavor < MIPS3_TYPE_MIPS_IV)
- return FALSE;
- return describe_instruction_cop1x(mips, op, desc);
-
- case 0x1c: /* IDT-specific opcodes: mad/madu/mul on R4640/4650, msub on RC32364 */
- return describe_instruction_idt(mips, op, desc);
-
- case 0x02: /* J */
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_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->targetpc = (desc->pc & 0xf0000000) | (LIMMVAL << 2);
- desc->delayslots = 1;
- return TRUE;
-
- case 0x04: /* BEQ */
- case 0x05: /* BNE */
- case 0x14: /* BEQL */
- case 0x15: /* BNEL */
+ case 0x00: // SPECIAL
+ return describe_special(op, desc);
+
+ case 0x01: // REGIMM
+ return describe_regimm(op, desc);
+
+ case 0x10: // COP0
+ return describe_cop0(op, desc);
+
+ case 0x11: // COP1
+ return describe_cop1(op, desc);
+
+ case 0x12: // COP2
+ return describe_cop2(op, desc);
+
+ case 0x13: // COP1X - MIPS IV
+ if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
+ return false;
+ return describe_cop1x(op, desc);
+
+ case 0x1c: // IDT-specific opcodes: mad/madu/mul on R4640/4650, msub on RC32364
+ return describe_idt(op, desc);
+
+ case 0x02: // J
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_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.targetpc = (desc.pc & 0xf0000000) | (LIMMVAL << 2);
+ desc.delayslots = 1;
+ return true;
+
+ case 0x04: // BEQ
+ case 0x05: // BNE
+ case 0x14: // BEQL
+ case 0x15: // BNEL
if ((opswitch == 0x04 || opswitch == 0x14) && RSREG == RTREG)
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
else
{
- desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
- desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
}
- desc->targetpc = desc->pc + 4 + (SIMMVAL << 2);
- desc->delayslots = 1;
- desc->skipslots = (opswitch & 0x10) ? 1 : 0;
- return TRUE;
-
- case 0x06: /* BLEZ */
- case 0x07: /* BGTZ */
- case 0x16: /* BLEZL */
- case 0x17: /* BGTZL */
+ desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
+ desc.delayslots = 1;
+ desc.skipslots = (opswitch & 0x10) ? 1 : 0;
+ return true;
+
+ case 0x06: // BLEZ
+ case 0x07: // BGTZ
+ case 0x16: // BLEZL
+ case 0x17: // BGTZL
if ((opswitch == 0x06 || opswitch == 0x16) && RSREG == 0)
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
else
{
- desc->regin[0] |= REGFLAG_R(RSREG);
- desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
}
- desc->targetpc = desc->pc + 4 + (SIMMVAL << 2);
- desc->delayslots = 1;
- desc->skipslots = (opswitch & 0x10) ? 1 : 0;
- return TRUE;
-
- case 0x08: /* ADDI */
- case 0x18: /* DADDI */
- desc->regin[0] |= REGFLAG_R(RSREG);
- desc->regout[0] |= REGFLAG_R(RTREG);
- desc->flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
- return TRUE;
-
- case 0x09: /* ADDIU */
- case 0x0a: /* SLTI */
- case 0x0b: /* SLTIU */
- case 0x0c: /* ANDI */
- case 0x0d: /* ORI */
- case 0x0e: /* XORI */
- case 0x19: /* DADDIU */
- desc->regin[0] |= REGFLAG_R(RSREG);
- desc->regout[0] |= REGFLAG_R(RTREG);
- return TRUE;
-
- case 0x0f: /* LUI */
- desc->regout[0] |= REGFLAG_R(RTREG);
- return TRUE;
-
- case 0x1a: /* LDL */
- case 0x1b: /* LDR */
- case 0x22: /* LWL */
- case 0x26: /* LWR */
- desc->regin[0] |= REGFLAG_R(RTREG);
- case 0x20: /* LB */
- case 0x21: /* LH */
- case 0x23: /* LW */
- case 0x24: /* LBU */
- case 0x25: /* LHU */
- case 0x27: /* LWU */
- 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;
- return TRUE;
-
- case 0x28: /* SB */
- case 0x29: /* SH */
- case 0x2a: /* SWL */
- case 0x2b: /* SW */
- case 0x2c: /* SDL */
- 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;
- 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;
- 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;
- 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;
- return TRUE;
-
- case 0x32: /* LWC2 */
- case 0x36: /* LDC2 */
- desc->regin[0] |= REGFLAG_R(RSREG);
- desc->flags |= OPFLAG_READS_MEMORY | OPFLAG_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;
- return TRUE;
-
- case 0x33: /* PREF */
- if (mips->flavor < MIPS3_TYPE_MIPS_IV)
- return FALSE;
- case 0x2f: /* CACHE */
- /* effective no-op */
- return TRUE;
+ desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
+ desc.delayslots = 1;
+ desc.skipslots = (opswitch & 0x10) ? 1 : 0;
+ return true;
+
+ case 0x08: // ADDI
+ case 0x18: // DADDI
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x09: // ADDIU
+ case 0x0a: // SLTI
+ case 0x0b: // SLTIU
+ case 0x0c: // ANDI
+ case 0x0d: // ORI
+ case 0x0e: // XORI
+ case 0x19: // DADDIU
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x0f: // LUI
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x1a: // LDL
+ case 0x1b: // LDR
+ case 0x22: // LWL
+ case 0x26: // LWR
+ desc.regin[0] |= REGFLAG_R(RTREG);
+ case 0x20: // LB
+ case 0x21: // LH
+ case 0x23: // LW
+ case 0x24: // LBU
+ case 0x25: // LHU
+ case 0x27: // LWU
+ 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;
+ return true;
+
+ case 0x28: // SB
+ case 0x29: // SH
+ case 0x2a: // SWL
+ case 0x2b: // SW
+ case 0x2c: // SDL
+ 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;
+ 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;
+ 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;
+ 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;
+ return true;
+
+ case 0x32: // LWC2
+ case 0x36: // LDC2
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_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;
+ return true;
+
+ case 0x33: // PREF
+ if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
+ return false;
+ case 0x2f: // CACHE
+ // effective no-op
+ return true;
}
- return FALSE;
+ return false;
}
-/*-------------------------------------------------
- describe_instruction_special - build a
- description of a single instruction in the
- 'special' group
--------------------------------------------------*/
+//-------------------------------------------------
+// describe_special - build a description of a
+// single instruction in the 'special' group
+//-------------------------------------------------
-static int describe_instruction_special(mips3_state *mips, UINT32 op, opcode_desc *desc)
+bool mips3_frontend::describe_special(UINT32 op, opcode_desc &desc)
{
switch (op & 63)
{
- case 0x00: /* SLL */
- case 0x02: /* SRL */
- case 0x03: /* SRA */
- case 0x38: /* DSLL */
- case 0x3a: /* DSRL */
- case 0x3b: /* DSRA */
- case 0x3c: /* DSLL32 */
- case 0x3e: /* DSRL32 */
- case 0x3f: /* DSRA32 */
- desc->regin[0] |= REGFLAG_R(RTREG);
- desc->regout[0] |= REGFLAG_R(RDREG);
- return TRUE;
-
- case 0x0a: /* MOVZ - MIPS IV */
- case 0x0b: /* MOVN - MIPS IV */
- if (mips->flavor < MIPS3_TYPE_MIPS_IV)
- return FALSE;
- desc->regin[0] |= REGFLAG_R(RDREG);
- case 0x04: /* SLLV */
- case 0x06: /* SRLV */
- case 0x07: /* SRAV */
- case 0x14: /* DSLLV */
- case 0x16: /* DSRLV */
- case 0x17: /* DSRAV */
- case 0x21: /* ADDU */
- case 0x23: /* SUBU */
- case 0x24: /* AND */
- case 0x25: /* OR */
- case 0x26: /* XOR */
- case 0x27: /* NOR */
- case 0x2a: /* SLT */
- case 0x2b: /* SLTU */
- case 0x2d: /* DADDU */
- case 0x2f: /* DSUBU */
- desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
- desc->regout[0] |= REGFLAG_R(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;
- return TRUE;
-
- case 0x30: /* TGE */
- case 0x31: /* TGEU */
- case 0x32: /* TLT */
- case 0x33: /* TLTU */
- case 0x34: /* TEQ */
- case 0x36: /* TNE */
- desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
- desc->flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
- return TRUE;
-
- case 0x01: /* MOVF - MIPS IV */
- if (mips->flavor < MIPS3_TYPE_MIPS_IV)
- return FALSE;
- desc->regin[0] |= REGFLAG_R(RSREG);
- desc->regin[2] |= REGFLAG_FCC;
- desc->regout[0] |= REGFLAG_R(RDREG);
- return TRUE;
-
- case 0x08: /* JR */
- desc->regin[0] |= REGFLAG_R(RSREG);
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_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->targetpc = BRANCH_TARGET_DYNAMIC;
- desc->delayslots = 1;
- return TRUE;
-
- case 0x10: /* MFHI */
- desc->regin[0] |= REGFLAG_HI;
- desc->regout[0] |= REGFLAG_R(RDREG);
- return TRUE;
-
- case 0x11: /* MTHI */
- desc->regin[0] |= REGFLAG_R(RSREG);
- desc->regout[0] |= REGFLAG_HI;
- return TRUE;
-
- case 0x12: /* MFLO */
- desc->regin[2] |= REGFLAG_LO;
- desc->regout[0] |= REGFLAG_R(RDREG);
- return TRUE;
-
- case 0x13: /* MTLO */
- desc->regin[0] |= REGFLAG_R(RSREG);
- desc->regout[2] |= REGFLAG_LO;
- 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->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->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->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->cycles = 67;
- return TRUE;
-
- case 0x0c: /* SYSCALL */
- case 0x0d: /* BREAK */
- desc->flags |= OPFLAG_WILL_CAUSE_EXCEPTION | OPFLAG_END_SEQUENCE;
- return TRUE;
-
- case 0x0f: /* SYNC */
- /* effective no-op */
- return TRUE;
+ case 0x00: // SLL
+ case 0x02: // SRL
+ case 0x03: // SRA
+ case 0x38: // DSLL
+ case 0x3a: // DSRL
+ case 0x3b: // DSRA
+ case 0x3c: // DSLL32
+ case 0x3e: // DSRL32
+ case 0x3f: // DSRA32
+ desc.regin[0] |= REGFLAG_R(RTREG);
+ desc.regout[0] |= REGFLAG_R(RDREG);
+ return true;
+
+ case 0x0a: // MOVZ - MIPS IV
+ case 0x0b: // MOVN - MIPS IV
+ if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
+ return false;
+ desc.regin[0] |= REGFLAG_R(RDREG);
+ case 0x04: // SLLV
+ case 0x06: // SRLV
+ case 0x07: // SRAV
+ case 0x14: // DSLLV
+ case 0x16: // DSRLV
+ case 0x17: // DSRAV
+ case 0x21: // ADDU
+ case 0x23: // SUBU
+ case 0x24: // AND
+ case 0x25: // OR
+ case 0x26: // XOR
+ case 0x27: // NOR
+ case 0x2a: // SLT
+ case 0x2b: // SLTU
+ case 0x2d: // DADDU
+ case 0x2f: // DSUBU
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.regout[0] |= REGFLAG_R(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;
+ return true;
+
+ case 0x30: // TGE
+ case 0x31: // TGEU
+ case 0x32: // TLT
+ case 0x33: // TLTU
+ case 0x34: // TEQ
+ case 0x36: // TNE
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x01: // MOVF - MIPS IV
+ if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
+ return false;
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.regin[2] |= REGFLAG_FCC;
+ desc.regout[0] |= REGFLAG_R(RDREG);
+ return true;
+
+ case 0x08: // JR
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_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.targetpc = BRANCH_TARGET_DYNAMIC;
+ desc.delayslots = 1;
+ return true;
+
+ case 0x10: // MFHI
+ desc.regin[0] |= REGFLAG_HI;
+ desc.regout[0] |= REGFLAG_R(RDREG);
+ return true;
+
+ case 0x11: // MTHI
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.regout[0] |= REGFLAG_HI;
+ return true;
+
+ case 0x12: // MFLO
+ desc.regin[2] |= REGFLAG_LO;
+ desc.regout[0] |= REGFLAG_R(RDREG);
+ return true;
+
+ case 0x13: // MTLO
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.regout[2] |= REGFLAG_LO;
+ 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.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.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.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.cycles = 67;
+ return true;
+
+ case 0x0c: // SYSCALL
+ case 0x0d: // BREAK
+ desc.flags |= OPFLAG_WILL_CAUSE_EXCEPTION | OPFLAG_END_SEQUENCE;
+ return true;
+
+ case 0x0f: // SYNC
+ // effective no-op
+ return true;
}
- return FALSE;
+ return false;
}
-/*-------------------------------------------------
- describe_instruction_regimm - build a
- description of a single instruction in the
- 'regimm' group
--------------------------------------------------*/
+//-------------------------------------------------
+// describe_regimm - build a description of a
+// single instruction in the 'regimm' group
+//-------------------------------------------------
-static int describe_instruction_regimm(mips3_state *mips, UINT32 op, opcode_desc *desc)
+bool mips3_frontend::describe_regimm(UINT32 op, opcode_desc &desc)
{
switch (RTREG)
{
- case 0x00: /* BLTZ */
- case 0x01: /* BGEZ */
- case 0x02: /* BLTZL */
- case 0x03: /* BGEZL */
+ case 0x00: // BLTZ
+ case 0x01: // BGEZ
+ case 0x02: // BLTZL
+ case 0x03: // BGEZL
if (RTREG == 0x01 && RSREG == 0)
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
else
{
- desc->regin[0] |= REGFLAG_R(RSREG);
- desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
}
- desc->targetpc = desc->pc + 4 + (SIMMVAL << 2);
- desc->delayslots = 1;
- desc->skipslots = (RTREG & 0x02) ? 1 : 0;
- return TRUE;
-
- case 0x08: /* TGEI */
- case 0x09: /* TGEIU */
- case 0x0a: /* TLTI */
- case 0x0b: /* TLTIU */
- case 0x0c: /* TEQI */
- case 0x0e: /* TNEI */
- desc->regin[0] |= REGFLAG_R(RSREG);
- desc->flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
- return TRUE;
-
- case 0x10: /* BLTZAL */
- case 0x11: /* BGEZAL */
- case 0x12: /* BLTZALL */
- case 0x13: /* BGEZALL */
+ desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
+ desc.delayslots = 1;
+ desc.skipslots = (RTREG & 0x02) ? 1 : 0;
+ return true;
+
+ case 0x08: // TGEI
+ case 0x09: // TGEIU
+ case 0x0a: // TLTI
+ case 0x0b: // TLTIU
+ case 0x0c: // TEQI
+ case 0x0e: // TNEI
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x10: // BLTZAL
+ case 0x11: // BGEZAL
+ case 0x12: // BLTZALL
+ case 0x13: // BGEZALL
if (RTREG == 0x11 && RSREG == 0)
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
else
{
- desc->regin[0] |= REGFLAG_R(RSREG);
- desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
}
- desc->regout[0] |= REGFLAG_R(31);
- desc->targetpc = desc->pc + 4 + (SIMMVAL << 2);
- desc->delayslots = 1;
- desc->skipslots = (RTREG & 0x02) ? 1 : 0;
- return TRUE;
+ desc.regout[0] |= REGFLAG_R(31);
+ desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
+ desc.delayslots = 1;
+ desc.skipslots = (RTREG & 0x02) ? 1 : 0;
+ return true;
}
- return FALSE;
+ return false;
}
-/*-------------------------------------------------
- describe_instruction_idt - build a
- description of a single instruction in the
- IDT-specific group
--------------------------------------------------*/
+//-------------------------------------------------
+// describe_idt - build a description of a single
+// instruction in the IDT-specific group
+//-------------------------------------------------
-static int describe_instruction_idt(mips3_state *mips, UINT32 op, opcode_desc *desc)
+bool mips3_frontend::describe_idt(UINT32 op, opcode_desc &desc)
{
- /* only on the R4650 */
- if (mips->flavor != MIPS3_TYPE_R4650)
- return FALSE;
+ // only on the R4650
+ if (m_context.flavor != MIPS3_TYPE_R4650)
+ return false;
switch (op & 0x1f)
{
- 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;
- return TRUE;
-
- case 2: /* MUL */
- desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
- desc->regout[0] |= REGFLAG_R(RDREG);
- desc->cycles = 3;
- return TRUE;
+ 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;
+ return true;
+
+ case 2: // MUL
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.regout[0] |= REGFLAG_R(RDREG);
+ desc.cycles = 3;
+ return true;
}
- return FALSE;
+ return false;
}
-/*-------------------------------------------------
- describe_instruction_cop0 - build a
- description of a single instruction in the
- COP0 group
--------------------------------------------------*/
+//-------------------------------------------------
+// describe_cop0 - build a description of a
+// single instruction in the COP0 group
+//-------------------------------------------------
-static int describe_instruction_cop0(mips3_state *mips, UINT32 op, opcode_desc *desc)
+bool mips3_frontend::describe_cop0(UINT32 op, opcode_desc &desc)
{
- /* any COP0 instruction can potentially cause an exception */
- desc->flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+ // any COP0 instruction can potentially cause an exception
+ desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
switch (RSREG)
{
- case 0x00: /* MFCz */
- case 0x01: /* DMFCz */
+ case 0x00: // MFCz
+ case 0x01: // DMFCz
if (RDREG == COP0_Count)
- desc->cycles += MIPS3_COUNT_READ_CYCLES;
+ desc.cycles += MIPS3_COUNT_READ_CYCLES;
if (RDREG == COP0_Cause)
- desc->cycles += MIPS3_CAUSE_READ_CYCLES;
- desc->regout[0] |= REGFLAG_R(RTREG);
- return TRUE;
-
- case 0x02: /* CFCz */
- desc->regout[0] |= REGFLAG_R(RTREG);
- return TRUE;
-
- case 0x04: /* MTCz */
- case 0x05: /* DMTCz */
- case 0x06: /* CTCz */
- desc->regin[0] |= REGFLAG_R(RTREG);
+ desc.cycles += MIPS3_CAUSE_READ_CYCLES;
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x02: // CFCz
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x04: // MTCz
+ case 0x05: // DMTCz
+ case 0x06: // CTCz
+ desc.regin[0] |= REGFLAG_R(RTREG);
if (RSREG == 0x04 || RSREG == 0x05)
{
if (RDREG == COP0_Cause)
- desc->flags |= OPFLAG_CAN_TRIGGER_SW_INT;
+ desc.flags |= OPFLAG_CAN_TRIGGER_SW_INT;
if (RDREG == COP0_Status)
- desc->flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_CAN_CHANGE_MODES | OPFLAG_END_SEQUENCE;
+ desc.flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_CAN_CHANGE_MODES | OPFLAG_END_SEQUENCE;
}
- return TRUE;
+ return true;
- case 0x08: /* BC */
+ case 0x08: // BC
switch (RTREG)
{
- case 0x00: /* BCzF */
- case 0x01: /* BCzT */
- desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
- desc->targetpc = desc->pc + 4 + (SIMMVAL << 2);
- desc->delayslots = 1;
- return TRUE;
+ case 0x00: // BCzF
+ case 0x01: // BCzT
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
+ desc.delayslots = 1;
+ return true;
}
- return FALSE;
+ return false;
case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
- case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: /* COP */
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: // COP
switch (op & 0x01ffffff)
{
- case 0x01: /* TLBR */
- case 0x08: /* TLBP */
- case 0x20: /* WAIT */
- return TRUE;
-
- case 0x02: /* TLBWI */
- case 0x06: /* TLBWR */
- desc->flags |= OPFLAG_MODIFIES_TRANSLATION;
- return TRUE;
-
- case 0x18: /* ERET */
- desc->flags |= OPFLAG_CAN_CHANGE_MODES | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- return TRUE;
+ case 0x01: // TLBR
+ case 0x08: // TLBP
+ case 0x20: // WAIT
+ return true;
+
+ case 0x02: // TLBWI
+ case 0x06: // TLBWR
+ desc.flags |= OPFLAG_MODIFIES_TRANSLATION;
+ return true;
+
+ case 0x18: // ERET
+ desc.flags |= OPFLAG_CAN_CHANGE_MODES | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ return true;
}
- return FALSE;
+ return false;
}
- return FALSE;
+ return false;
}
-/*-------------------------------------------------
- describe_instruction_cop1 - build a
- description of a single instruction in the
- COP1 group
--------------------------------------------------*/
+//-------------------------------------------------
+// describe_cop1 - build a description of a
+// single instruction in the COP1 group
+//-------------------------------------------------
-static int describe_instruction_cop1(mips3_state *mips, UINT32 op, opcode_desc *desc)
+bool mips3_frontend::describe_cop1(UINT32 op, opcode_desc &desc)
{
- /* any COP1 instruction can potentially cause an exception */
-// desc->flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+ // any COP1 instruction can potentially cause an exception
+// desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
switch (RSREG)
{
- case 0x00: /* MFCz */
- case 0x01: /* DMFCz */
- desc->regin[1] |= REGFLAG_CPR1(RDREG);
- desc->regout[0] |= REGFLAG_R(RTREG);
- return TRUE;
-
- case 0x02: /* CFCz */
- desc->regout[0] |= REGFLAG_R(RTREG);
- return TRUE;
-
- case 0x04: /* MTCz */
- case 0x05: /* DMTCz */
- desc->regin[0] |= REGFLAG_R(RTREG);
- desc->regout[1] |= REGFLAG_CPR1(RDREG);
- return TRUE;
-
- case 0x06: /* CTCz */
- desc->regin[0] |= REGFLAG_R(RTREG);
- return TRUE;
-
- case 0x08: /* BC */
+ case 0x00: // MFCz
+ case 0x01: // DMFCz
+ desc.regin[1] |= REGFLAG_CPR1(RDREG);
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x02: // CFCz
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x04: // MTCz
+ case 0x05: // DMTCz
+ desc.regin[0] |= REGFLAG_R(RTREG);
+ desc.regout[1] |= REGFLAG_CPR1(RDREG);
+ return true;
+
+ case 0x06: // CTCz
+ desc.regin[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x08: // BC
switch (RTREG & 3)
{
- case 0x00: /* BCzF */
- case 0x01: /* BCzT */
- case 0x02: /* BCzFL */
- case 0x03: /* BCzTL */
- desc->regin[2] |= REGFLAG_FCC;
- desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
- desc->targetpc = desc->pc + 4 + (SIMMVAL << 2);
- desc->delayslots = 1;
- desc->skipslots = (RTREG & 0x02) ? 1 : 0;
- return TRUE;
+ case 0x00: // BCzF
+ case 0x01: // BCzT
+ case 0x02: // BCzFL
+ case 0x03: // BCzTL
+ desc.regin[2] |= REGFLAG_FCC;
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
+ desc.delayslots = 1;
+ desc.skipslots = (RTREG & 0x02) ? 1 : 0;
+ return true;
}
- return FALSE;
+ return false;
case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
- case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: /* COP */
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: // COP
switch (op & 0x3f)
{
- case 0x12: /* MOVZ - MIPS IV */
- case 0x13: /* MOVN - MIPS IV */
- if (mips->flavor < MIPS3_TYPE_MIPS_IV)
- return FALSE;
- case 0x00: /* ADD */
- case 0x01: /* SUB */
- case 0x02: /* MUL */
- case 0x03: /* DIV */
- desc->regin[1] |= REGFLAG_CPR1(FSREG) | REGFLAG_CPR1(FTREG);
- desc->regout[1] |= REGFLAG_CPR1(FDREG);
- return TRUE;
-
- case 0x15: /* RECIP - MIPS IV */
- case 0x16: /* RSQRT - MIPS IV */
- if (mips->flavor < MIPS3_TYPE_MIPS_IV)
- return FALSE;
- case 0x04: /* SQRT */
- case 0x05: /* ABS */
- case 0x06: /* MOV */
- case 0x07: /* NEG */
- case 0x08: /* ROUND.L */
- case 0x09: /* TRUNC.L */
- case 0x0a: /* CEIL.L */
- case 0x0b: /* FLOOR.L */
- case 0x0c: /* ROUND.W */
- case 0x0d: /* TRUNC.W */
- case 0x0e: /* CEIL.W */
- case 0x0f: /* FLOOR.W */
- case 0x20: /* CVT.S */
- case 0x21: /* CVT.D */
- case 0x24: /* CVT.W */
- case 0x25: /* CVT.L */
- desc->regin[1] |= REGFLAG_CPR1(FSREG);
- desc->regout[1] |= REGFLAG_CPR1(FDREG);
- return TRUE;
-
- case 0x11: /* MOVT/F - MIPS IV */
- if (mips->flavor < MIPS3_TYPE_MIPS_IV)
- return FALSE;
- desc->regin[1] |= REGFLAG_CPR1(FSREG);
- desc->regin[2] |= REGFLAG_FCC;
- desc->regout[1] |= REGFLAG_CPR1(FDREG);
- return TRUE;
-
- case 0x30: case 0x38: /* C.F */
- case 0x31: case 0x39: /* C.UN */
- desc->regout[2] |= REGFLAG_FCC;
- return TRUE;
-
- case 0x32: case 0x3a: /* C.EQ */
- case 0x33: case 0x3b: /* C.UEQ */
- case 0x34: case 0x3c: /* C.OLT */
- 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;
- return TRUE;
+ case 0x12: // MOVZ - MIPS IV
+ case 0x13: // MOVN - MIPS IV
+ if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
+ return false;
+ case 0x00: // ADD
+ case 0x01: // SUB
+ case 0x02: // MUL
+ case 0x03: // DIV
+ desc.regin[1] |= REGFLAG_CPR1(FSREG) | REGFLAG_CPR1(FTREG);
+ desc.regout[1] |= REGFLAG_CPR1(FDREG);
+ return true;
+
+ case 0x15: // RECIP - MIPS IV
+ case 0x16: // RSQRT - MIPS IV
+ if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
+ return false;
+ case 0x04: // SQRT
+ case 0x05: // ABS
+ case 0x06: // MOV
+ case 0x07: // NEG
+ case 0x08: // ROUND.L
+ case 0x09: // TRUNC.L
+ case 0x0a: // CEIL.L
+ case 0x0b: // FLOOR.L
+ case 0x0c: // ROUND.W
+ case 0x0d: // TRUNC.W
+ case 0x0e: // CEIL.W
+ case 0x0f: // FLOOR.W
+ case 0x20: // CVT.S
+ case 0x21: // CVT.D
+ case 0x24: // CVT.W
+ case 0x25: // CVT.L
+ desc.regin[1] |= REGFLAG_CPR1(FSREG);
+ desc.regout[1] |= REGFLAG_CPR1(FDREG);
+ return true;
+
+ case 0x11: // MOVT/F - MIPS IV
+ if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
+ return false;
+ desc.regin[1] |= REGFLAG_CPR1(FSREG);
+ desc.regin[2] |= REGFLAG_FCC;
+ desc.regout[1] |= REGFLAG_CPR1(FDREG);
+ return true;
+
+ case 0x30: case 0x38: // C.F
+ case 0x31: case 0x39: // C.UN
+ desc.regout[2] |= REGFLAG_FCC;
+ return true;
+
+ case 0x32: case 0x3a: // C.EQ
+ case 0x33: case 0x3b: // C.UEQ
+ case 0x34: case 0x3c: // C.OLT
+ 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;
+ return true;
}
- return FALSE;
+ return false;
}
- return FALSE;
+ return false;
}
-/*-------------------------------------------------
- describe_instruction_cop1x - build a
- description of a single instruction in the
- COP1X group
--------------------------------------------------*/
+//-------------------------------------------------
+// describe_cop1x - build a description of a
+// single instruction in the COP1X group
+//-------------------------------------------------
-static int describe_instruction_cop1x(mips3_state *mips, UINT32 op, opcode_desc *desc)
+bool mips3_frontend::describe_cop1x(UINT32 op, opcode_desc &desc)
{
- /* any COP1 instruction can potentially cause an exception */
-// desc->flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+ // any COP1 instruction can potentially cause an exception
+// desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
switch (op & 0x3f)
{
- 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;
- 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;
- return TRUE;
-
- case 0x0f: /* PREFX */
- /* effective no-op */
- return TRUE;
-
- case 0x20: case 0x21: /* MADD */
- 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);
- return TRUE;
+ 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;
+ 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;
+ return true;
+
+ case 0x0f: // PREFX
+ // effective no-op
+ return true;
+
+ case 0x20: case 0x21: // MADD
+ 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);
+ return true;
}
- return FALSE;
+ return false;
}
-/*-------------------------------------------------
- describe_instruction_cop2 - build a
- description of a single instruction in the
- COP2 group
--------------------------------------------------*/
+//-------------------------------------------------
+// describe_cop2 - build a description of a
+// single instruction in the COP2 group
+//-------------------------------------------------
-static int describe_instruction_cop2(mips3_state *mips, UINT32 op, opcode_desc *desc)
+bool mips3_frontend::describe_cop2(UINT32 op, opcode_desc &desc)
{
- /* any COP2 instruction can potentially cause an exception */
- desc->flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+ // any COP2 instruction can potentially cause an exception
+ desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
switch (RSREG)
{
- case 0x00: /* MFCz */
- case 0x01: /* DMFCz */
- case 0x02: /* CFCz */
- desc->regout[0] |= REGFLAG_R(RTREG);
- return TRUE;
-
- case 0x04: /* MTCz */
- case 0x05: /* DMTCz */
- case 0x06: /* CTCz */
- desc->regin[0] |= REGFLAG_R(RTREG);
- return TRUE;
-
- case 0x08: /* BC */
+ case 0x00: // MFCz
+ case 0x01: // DMFCz
+ case 0x02: // CFCz
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x04: // MTCz
+ case 0x05: // DMTCz
+ case 0x06: // CTCz
+ desc.regin[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x08: // BC
switch (RTREG)
{
- case 0x00: /* BCzF */
- case 0x01: /* BCzT */
- desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
- desc->targetpc = desc->pc + 4 + (SIMMVAL << 2);
- desc->delayslots = 1;
- return TRUE;
+ case 0x00: // BCzF
+ case 0x01: // BCzT
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
+ desc.delayslots = 1;
+ return true;
}
- return FALSE;
+ return false;
}
- return FALSE;
+ return false;
}
diff --git a/src/emu/cpu/mips/mips3fe.h b/src/emu/cpu/mips/mips3fe.h
index 6ba3cc2c21f..aefcc676795 100644
--- a/src/emu/cpu/mips/mips3fe.h
+++ b/src/emu/cpu/mips/mips3fe.h
@@ -4,9 +4,36 @@
Front-end for MIPS3 recompiler
+****************************************************************************
+
Copyright Aaron Giles
- Released for general non-commercial use under the MAME license
- Visit http://mamedev.org for licensing and usage restrictions.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
@@ -15,30 +42,54 @@
#ifndef __MIPS3FE_H__
#define __MIPS3FE_H__
+#include "mips3com.h"
#include "cpu/drcfe.h"
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
+//**************************************************************************
+// MACROS
+//**************************************************************************
-/* register flags 0 */
+// register flags 0
#define REGFLAG_R(n) (((n) == 0) ? 0 : (1 << (n)))
-/* register flags 1 */
+// register flags 1
#define REGFLAG_CPR1(n) (1 << (n))
-/* register flags 2 */
+// register flags 2
#define REGFLAG_LO (1 << 0)
#define REGFLAG_HI (1 << 1)
#define REGFLAG_FCC (1 << 2)
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class mips3_frontend : public drc_frontend
+{
+public:
+ // construction/destruction
+ mips3_frontend(mips3_state &state, UINT32 window_start, UINT32 window_end, UINT32 max_sequence);
+
+protected:
+ // required overrides
+ virtual bool describe(opcode_desc &desc, const opcode_desc *prev);
+
+private:
+ // internal helpers
+ bool describe_special(UINT32 op, opcode_desc &desc);
+ bool describe_regimm(UINT32 op, opcode_desc &desc);
+ bool describe_idt(UINT32 op, opcode_desc &desc);
+ bool describe_cop0(UINT32 op, opcode_desc &desc);
+ bool describe_cop1(UINT32 op, opcode_desc &desc);
+ bool describe_cop1x(UINT32 op, opcode_desc &desc);
+ bool describe_cop2(UINT32 op, opcode_desc &desc);
+
+ // internal state
+ mips3_state &m_context;
+};
-int mips3fe_describe(void *param, opcode_desc *desc, const opcode_desc *prev);
#endif /* __MIPS3FE_H__ */
diff --git a/src/emu/cpu/powerpc/ppcdrc.c b/src/emu/cpu/powerpc/ppcdrc.c
index 067443a1bc8..520b0729743 100644
--- a/src/emu/cpu/powerpc/ppcdrc.c
+++ b/src/emu/cpu/powerpc/ppcdrc.c
@@ -165,7 +165,7 @@ struct _ppcimp_state
/* core state */
drccache * cache; /* pointer to the DRC code cache */
drcuml_state * drcuml; /* DRC UML generator state */
- drcfe_state * drcfe; /* pointer to the DRC front-end state */
+ ppc_frontend * drcfe; /* pointer to the DRC front-end state */
UINT32 drcoptions; /* configurable DRC options */
/* parameters for subroutines */
@@ -548,13 +548,6 @@ INLINE UINT32 compute_spr(UINT32 spr)
static void ppcdrc_init(powerpc_flavor flavor, UINT8 cap, int tb_divisor, legacy_cpu_device *device, device_irq_callback irqcallback)
{
- drcfe_config feconfig =
- {
- COMPILE_BACKWARDS_BYTES, /* code window start offset = startpc - window_start */
- COMPILE_FORWARDS_BYTES, /* code window end offset = startpc + window_end */
- COMPILE_MAX_SEQUENCE, /* maximum instructions to include in a sequence */
- ppcfe_describe /* callback to describe a single instruction */
- };
powerpc_state *ppc;
drcbe_info beinfo;
UINT32 flags = 0;
@@ -633,9 +626,7 @@ static void ppcdrc_init(powerpc_flavor flavor, UINT8 cap, int tb_divisor, legacy
drcuml_symbol_add(ppc->impstate->drcuml, &ppc->impstate->fcmp_cr_table, sizeof(ppc->impstate->fcmp_cr_table), "fcmp_cr_table");
/* initialize the front-end helper */
- if (SINGLE_INSTRUCTION_MODE)
- feconfig.max_sequence = 1;
- ppc->impstate->drcfe = drcfe_init(device, &feconfig, ppc);
+ ppc->impstate->drcfe = auto_alloc(device->machine, ppc_frontend(*ppc, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE));
/* initialize the implementation state tables */
memcpy(ppc->impstate->fpmode, fpmode_source, sizeof(fpmode_source));
@@ -738,7 +729,7 @@ static CPU_EXIT( ppcdrc )
ppccom_exit(ppc);
/* clean up the DRC */
- drcfe_exit(ppc->impstate->drcfe);
+ auto_free(device->machine, ppc->impstate->drcfe);
drcuml_free(ppc->impstate->drcuml);
drccache_free(ppc->impstate->cache);
}
@@ -950,7 +941,7 @@ static void code_compile_block(powerpc_state *ppc, UINT8 mode, offs_t pc)
g_profiler.start(PROFILER_DRC_COMPILE);
/* get a description of this sequence */
- desclist = drcfe_describe_code(ppc->impstate->drcfe, pc);
+ desclist = ppc->impstate->drcfe->describe_code(pc);
if (LOG_UML || LOG_NATIVE)
log_opcode_desc(drcuml, desclist, 0);
@@ -962,7 +953,7 @@ static void code_compile_block(powerpc_state *ppc, UINT8 mode, offs_t pc)
block = drcuml_block_begin(drcuml, 4096, &errorbuf);
/* loop until we get through all instruction sequences */
- for (seqhead = desclist; seqhead != NULL; seqhead = seqlast->next)
+ for (seqhead = desclist; seqhead != NULL; seqhead = seqlast->next())
{
const opcode_desc *curdesc;
UINT32 nextpc;
@@ -972,7 +963,7 @@ static void code_compile_block(powerpc_state *ppc, UINT8 mode, offs_t pc)
UML_COMMENT(block, "-------------------------"); // comment
/* determine the last instruction in this sequence */
- for (seqlast = seqhead; seqlast != NULL; seqlast = seqlast->next)
+ for (seqlast = seqhead; seqlast != NULL; seqlast = seqlast->next())
if (seqlast->flags & OPFLAG_END_SEQUENCE)
break;
assert(seqlast != NULL);
@@ -1007,7 +998,7 @@ static void code_compile_block(powerpc_state *ppc, UINT8 mode, offs_t pc)
UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc | 0x80000000
/* iterate over instructions in the sequence and compile them */
- for (curdesc = seqhead; curdesc != seqlast->next; curdesc = curdesc->next)
+ for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next())
generate_sequence_instruction(ppc, block, &compiler, curdesc); // <instruction>
/* if we need to return to the start, do it */
@@ -1024,7 +1015,7 @@ static void code_compile_block(powerpc_state *ppc, UINT8 mode, offs_t pc)
/* if the last instruction can change modes, use a variable mode; otherwise, assume the same mode */
if (seqlast->flags & OPFLAG_CAN_CHANGE_MODES)
UML_HASHJMP(block, MEM(&ppc->impstate->mode), IMM(nextpc), ppc->impstate->nocode);// hashjmp <mode>,nextpc,nocode
- else if (seqlast->next == NULL || seqlast->next->pc != nextpc)
+ else if (seqlast->next() == NULL || seqlast->next()->pc != nextpc)
UML_HASHJMP(block, IMM(ppc->impstate->mode), IMM(nextpc), ppc->impstate->nocode);// hashjmp <mode>,nextpc,nocode
}
@@ -2093,7 +2084,7 @@ static void generate_checksum_block(powerpc_state *ppc, drcuml_block *block, com
UML_COMMENT(block, "[Validation for %08X]", seqhead->pc); // comment
/* loose verify or single instruction: just compare and fail */
- if (!(ppc->impstate->drcoptions & PPCDRC_STRICT_VERIFY) || seqhead->next == NULL)
+ if (!(ppc->impstate->drcoptions & PPCDRC_STRICT_VERIFY) || seqhead->next() == NULL)
{
if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP))
{
@@ -2108,7 +2099,7 @@ static void generate_checksum_block(powerpc_state *ppc, drcuml_block *block, com
else
{
#if 0
- for (curdesc = seqhead->next; curdesc != seqlast->next; curdesc = curdesc->next)
+ for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
{
void *base = ppc->direct->read_decrypted_ptr(seqhead->physpc, ppc->codexor);
@@ -2121,7 +2112,7 @@ static void generate_checksum_block(powerpc_state *ppc, drcuml_block *block, com
void *base = ppc->direct->read_decrypted_ptr(seqhead->physpc, ppc->codexor);
UML_LOAD(block, IREG(0), base, IMM(0), DWORD); // load i0,base,dword
sum += seqhead->opptr.l[0];
- for (curdesc = seqhead->next; curdesc != seqlast->next; curdesc = curdesc->next)
+ for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
{
base = ppc->direct->read_decrypted_ptr(curdesc->physpc, ppc->codexor);
@@ -4240,7 +4231,7 @@ static void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, i
drcuml_log_printf(drcuml, "\nDescriptor list @ %08X\n", desclist->pc);
/* output each descriptor */
- for ( ; desclist != NULL; desclist = desclist->next)
+ for ( ; desclist != NULL; desclist = desclist->next())
{
char buffer[100];
@@ -4263,8 +4254,8 @@ static void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, i
drcuml_log_printf(drcuml, "\n");
/* if we have a delay slot, output it recursively */
- if (desclist->delay != NULL)
- log_opcode_desc(drcuml, desclist->delay, indent + 1);
+ if (desclist->delay.first() != NULL)
+ log_opcode_desc(drcuml, desclist->delay.first(), indent + 1);
/* at the end of a sequence add a dividing line */
if (desclist->flags & OPFLAG_END_SEQUENCE)
diff --git a/src/emu/cpu/powerpc/ppcfe.c b/src/emu/cpu/powerpc/ppcfe.c
index dcd0336ccf5..b27cc783331 100644
--- a/src/emu/cpu/powerpc/ppcfe.c
+++ b/src/emu/cpu/powerpc/ppcfe.c
@@ -4,9 +4,36 @@
Front-end for PowerPC recompiler
+****************************************************************************
+
Copyright Aaron Giles
- Released for general non-commercial use under the MAME license
- Visit http://mamedev.org for licensing and usage restrictions.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
@@ -15,204 +42,147 @@
#include "ppccom.h"
-/***************************************************************************
- 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 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 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)
+//**************************************************************************
+// MACROS
+//**************************************************************************
-#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 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 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 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)
-
-
-
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
+#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)
-static int describe_instruction_13(powerpc_state *ppc, UINT32 op, opcode_desc *desc, const opcode_desc *prev);
-static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *desc, const opcode_desc *prev);
-static int describe_instruction_3b(powerpc_state *ppc, UINT32 op, opcode_desc *desc, const opcode_desc *prev);
-static int describe_instruction_3f(powerpc_state *ppc, UINT32 op, opcode_desc *desc, const opcode_desc *prev);
+#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 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 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)
-/***************************************************************************
- INLINE FUNCTIONS
-***************************************************************************/
+#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)
-/*-------------------------------------------------
- compute_spr - compute the SPR index from the
- SPR field of an opcode
--------------------------------------------------*/
-INLINE UINT32 compute_spr(UINT32 spr)
-{
- return ((spr >> 5) | (spr << 5)) & 0x3ff;
-}
+//**************************************************************************
+// PPC FRONTEND
+//**************************************************************************
-/*-------------------------------------------------
- is_403_class - are we one of the 403 variants?
--------------------------------------------------*/
+//-------------------------------------------------
+// ppc_frontend - constructor
+//-------------------------------------------------
-INLINE int is_403_class(const powerpc_state *ppc)
+ppc_frontend::ppc_frontend(powerpc_state &state, UINT32 window_start, UINT32 window_end, UINT32 max_sequence)
+ : drc_frontend(*state.device, window_start, window_end, max_sequence),
+ m_context(state)
{
- return (ppc->flavor == PPC_MODEL_403GA || ppc->flavor == PPC_MODEL_403GB || ppc->flavor == PPC_MODEL_403GC || ppc->flavor == PPC_MODEL_403GCX || ppc->flavor == PPC_MODEL_405GP);
}
-/*-------------------------------------------------
- is_601_class - are we one of the 601 variants?
--------------------------------------------------*/
-
-INLINE int is_601_class(const powerpc_state *ppc)
-{
- return (ppc->flavor == PPC_MODEL_601);
-}
-
-
-/*-------------------------------------------------
- is_602_class - are we one of the 602 variants?
--------------------------------------------------*/
-
-INLINE int is_602_class(const powerpc_state *ppc)
-{
- return (ppc->flavor == PPC_MODEL_602);
-}
-
-
-/*-------------------------------------------------
- is_603_class - are we one of the 603 variants?
--------------------------------------------------*/
-
-INLINE int is_603_class(const powerpc_state *ppc)
-{
- return (ppc->flavor == PPC_MODEL_603 || ppc->flavor == PPC_MODEL_603E || ppc->flavor == PPC_MODEL_603EV || ppc->flavor == PPC_MODEL_603R);
-}
-
-
-
-/***************************************************************************
- INSTRUCTION PARSERS
-***************************************************************************/
-
-/*-------------------------------------------------
- ppcfe_describe - build a description
- of a single instruction
--------------------------------------------------*/
+//-------------------------------------------------
+// describe - build a description of a single
+// instruction
+//-------------------------------------------------
-int ppcfe_describe(void *param, opcode_desc *desc, const opcode_desc *prev)
+bool ppc_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
{
- powerpc_state *ppc = (powerpc_state *)param;
UINT32 op, opswitch;
int regnum;
- /* compute the physical PC */
- if (!ppccom_translate_address(ppc, ADDRESS_SPACE_PROGRAM, TRANSLATE_FETCH, &desc->physpc))
+ // compute the physical PC
+ if (!ppccom_translate_address(&m_context, ADDRESS_SPACE_PROGRAM, TRANSLATE_FETCH, &desc.physpc))
{
- /* 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;
- return TRUE;
+ // 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;
+ return true;
}
- /* fetch the opcode */
- op = desc->opptr.l[0] = ppc->direct->read_decrypted_dword(desc->physpc, ppc->codexor);
+ // fetch the opcode
+ op = desc.opptr.l[0] = m_context.direct->read_decrypted_dword(desc.physpc, m_context.codexor);
- /* all instructions are 4 bytes and default to a single cycle each */
- desc->length = 4;
- desc->cycles = 1;
+ // all instructions are 4 bytes and default to a single cycle each
+ desc.length = 4;
+ desc.cycles = 1;
- /* parse the instruction */
+ // parse the instruction
opswitch = op >> 26;
switch (opswitch)
{
- case 0x02: /* TDI - 64-bit only */
- case 0x1e: /* 0x1e group - 64-bit only */
- case 0x3a: /* 0x3a group - 64-bit only */
- case 0x3e: /* 0x3e group - 64-bit only */
- return FALSE;
+ case 0x02: // TDI - 64-bit only
+ case 0x1e: // 0x1e group - 64-bit only
+ case 0x3a: // 0x3a group - 64-bit only
+ case 0x3e: // 0x3e group - 64-bit only
+ return false;
- case 0x03: /* TWI */
+ case 0x03: // TWI
GPR_USED(desc, G_RA(op));
- desc->flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
- if (is_603_class(ppc))
- desc->cycles = 2; /* 603 */
- return TRUE;
+ desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+ if (is_603_class())
+ desc.cycles = 2; // 603
+ return true;
- case 0x07: /* MULLI */
+ case 0x07: // MULLI
GPR_USED(desc, G_RA(op));
GPR_MODIFIED(desc, G_RD(op));
- if (is_403_class(ppc))
- desc->cycles = 4; /* 4XX */
- else if (is_601_class(ppc))
- desc->cycles = 5; /* 601 */
- else if (is_603_class(ppc))
- desc->cycles = 2; /* 603: 2-3 */
+ if (is_403_class())
+ desc.cycles = 4; // 4XX
+ else if (is_601_class())
+ desc.cycles = 5; // 601
+ else if (is_603_class())
+ desc.cycles = 2; // 603: 2-3
else
- desc->cycles = 2; /* ??? */
- return TRUE;
+ desc.cycles = 2; // ???
+ return true;
- case 0x0e: /* ADDI */
- case 0x0f: /* ADDIS */
+ case 0x0e: // ADDI
+ case 0x0f: // ADDIS
GPR_USED_OR_ZERO(desc, G_RA(op));
GPR_MODIFIED(desc, G_RD(op));
- return TRUE;
+ return true;
- case 0x0a: /* CMPLI */
- case 0x0b: /* CMPI */
+ case 0x0a: // CMPLI
+ case 0x0b: // CMPI
GPR_USED(desc, G_RA(op));
XER_SO_USED(desc);
CR_MODIFIED(desc, G_CRFD(op));
- return TRUE;
+ return true;
- case 0x08: /* SUBFIC */
- case 0x0c: /* ADDIC */
+ case 0x08: // SUBFIC
+ case 0x0c: // ADDIC
GPR_USED(desc, G_RA(op));
GPR_MODIFIED(desc, G_RD(op));
XER_CA_MODIFIED(desc);
- return TRUE;
+ return true;
- case 0x0d: /* ADDIC. */
+ case 0x0d: // ADDIC.
GPR_USED(desc, G_RA(op));
XER_SO_USED(desc);
GPR_MODIFIED(desc, G_RT(op));
XER_CA_MODIFIED(desc);
CR_MODIFIED(desc, 0);
- return TRUE;
+ return true;
- case 0x10: /* BCx */
+ case 0x10: // BCx
if (!(G_BO(op) & 0x10))
{
CR_BIT_USED(desc, G_BI(op));
- /* branch folding */
+ // branch folding
if (prev == NULL || prev->regout[2] == 0)
- desc->cycles = 0;
+ desc.cycles = 0;
}
if (!(G_BO(op) & 0x04))
{
@@ -222,40 +192,40 @@ int ppcfe_describe(void *param, 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.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
else
- desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
- desc->targetpc = (INT16)(G_BD(op) << 2) + ((op & M_AA) ? 0 : desc->pc);
- if (desc->targetpc == desc->pc && desc->cycles == 0)
- desc->cycles = 1;
- return TRUE;
-
- case 0x11: /* SC */
- if (!(ppc->cap & (PPCCAP_OEA | PPCCAP_4XX)))
- return FALSE;
- desc->flags |= OPFLAG_WILL_CAUSE_EXCEPTION;
- if (is_601_class(ppc))
- desc->cycles = 16; /* 601 */
- else if (is_603_class(ppc))
- desc->cycles = 3; /* 603 */
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.targetpc = (INT16)(G_BD(op) << 2) + ((op & M_AA) ? 0 : desc.pc);
+ if (desc.targetpc == desc.pc && desc.cycles == 0)
+ desc.cycles = 1;
+ return true;
+
+ case 0x11: // SC
+ if (!(m_context.cap & (PPCCAP_OEA | PPCCAP_4XX)))
+ return false;
+ desc.flags |= OPFLAG_WILL_CAUSE_EXCEPTION;
+ if (is_601_class())
+ desc.cycles = 16; // 601
+ else if (is_603_class())
+ desc.cycles = 3; // 603
else
- desc->cycles = 3; /* ??? */
- return TRUE;
+ desc.cycles = 3; // ???
+ return true;
- case 0x12: /* Bx */
+ case 0x12: // Bx
if (op & M_LK)
LR_MODIFIED(desc);
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- desc->targetpc = ((INT32)(G_LI(op) << 8) >> 6) + ((op & M_AA) ? 0 : desc->pc);
- /* branch folding */
- if (desc->targetpc != desc->pc)
- desc->cycles = 0;
- return TRUE;
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.targetpc = ((INT32)(G_LI(op) << 8) >> 6) + ((op & M_AA) ? 0 : desc.pc);
+ // branch folding
+ if (desc.targetpc != desc.pc)
+ desc.cycles = 0;
+ return true;
- case 0x13: /* 0x13 group */
- return describe_instruction_13(ppc, op, desc, prev);
+ case 0x13: // 0x13 group
+ return describe_13(op, desc, prev);
- case 0x14: /* RLWIMIx */
+ case 0x14: // RLWIMIx
GPR_USED(desc, G_RS(op));
GPR_USED(desc, G_RA(op));
GPR_MODIFIED(desc, G_RA(op));
@@ -264,9 +234,9 @@ int ppcfe_describe(void *param, opcode_desc *desc, const opcode_desc *prev)
XER_SO_USED(desc);
CR_MODIFIED(desc, 0);
}
- return TRUE;
+ return true;
- case 0x15: /* RLWINMx */
+ case 0x15: // RLWINMx
GPR_USED(desc, G_RS(op));
GPR_MODIFIED(desc, G_RA(op));
if (op & M_RC)
@@ -274,9 +244,9 @@ int ppcfe_describe(void *param, opcode_desc *desc, const opcode_desc *prev)
XER_SO_USED(desc);
CR_MODIFIED(desc, 0);
}
- return TRUE;
+ return true;
- case 0x17: /* RLWNMx */
+ case 0x17: // RLWNMx
GPR_USED(desc, G_RS(op));
GPR_USED(desc, G_RB(op));
GPR_MODIFIED(desc, G_RA(op));
@@ -285,133 +255,133 @@ int ppcfe_describe(void *param, opcode_desc *desc, const opcode_desc *prev)
XER_SO_USED(desc);
CR_MODIFIED(desc, 0);
}
- return TRUE;
+ return true;
- case 0x18: /* ORI */
- case 0x19: /* ORIS */
- case 0x1a: /* XORI */
- case 0x1b: /* XORIS */
+ case 0x18: // ORI
+ case 0x19: // ORIS
+ case 0x1a: // XORI
+ case 0x1b: // XORIS
GPR_USED(desc, G_RS(op));
GPR_MODIFIED(desc, G_RA(op));
- return TRUE;
+ return true;
- case 0x1c: /* ANDI. */
- case 0x1d: /* ANDIS. */
+ case 0x1c: // ANDI.
+ case 0x1d: // ANDIS.
GPR_USED(desc, G_RS(op));
XER_SO_USED(desc);
GPR_MODIFIED(desc, G_RA(op));
CR_MODIFIED(desc, 0);
- return TRUE;
+ return true;
- case 0x1f: /* 0x1f group */
- return describe_instruction_1f(ppc, op, desc, prev);
+ case 0x1f: // 0x1f group
+ return describe_1f(op, desc, prev);
- case 0x20: /* LWZ */
- case 0x22: /* LBZ */
- case 0x28: /* LHZ */
- case 0x2a: /* LHA */
+ case 0x20: // LWZ
+ case 0x22: // LBZ
+ case 0x28: // LHZ
+ case 0x2a: // LHA
GPR_USED_OR_ZERO(desc, G_RA(op));
GPR_MODIFIED(desc, G_RD(op));
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
- case 0x21: /* LWZU */
- case 0x23: /* LBZU */
- case 0x29: /* LHZU */
- case 0x2b: /* LHAU */
+ case 0x21: // LWZU
+ case 0x23: // LBZU
+ case 0x29: // LHZU
+ case 0x2b: // LHAU
if (G_RA(op) == 0 || G_RA(op) == G_RD(op))
- return FALSE;
+ return false;
GPR_USED(desc, G_RA(op));
GPR_MODIFIED(desc, G_RD(op));
GPR_MODIFIED(desc, G_RA(op));
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
- case 0x24: /* STW */
- case 0x26: /* STB */
- case 0x2c: /* STH */
+ case 0x24: // STW
+ case 0x26: // STB
+ case 0x2c: // STH
GPR_USED_OR_ZERO(desc, G_RA(op));
GPR_USED(desc, G_RS(op));
- desc->flags |= OPFLAG_WRITES_MEMORY;
- return TRUE;
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
- case 0x25: /* STWU */
- case 0x27: /* STBU */
- case 0x2d: /* STHU */
+ case 0x25: // STWU
+ case 0x27: // STBU
+ case 0x2d: // STHU
if (G_RA(op) == 0)
- return FALSE;
+ return false;
GPR_USED(desc, G_RA(op));
GPR_USED(desc, G_RS(op));
GPR_MODIFIED(desc, G_RA(op));
- desc->flags |= OPFLAG_WRITES_MEMORY;
- return TRUE;
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
- case 0x2e: /* LMW */
+ case 0x2e: // LMW
GPR_USED_OR_ZERO(desc, G_RA(op));
for (regnum = G_RD(op); regnum < 32; regnum++)
GPR_MODIFIED(desc, regnum);
- desc->flags |= OPFLAG_READS_MEMORY;
- desc->cycles = 32 - G_RD(op);
- return TRUE;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ desc.cycles = 32 - G_RD(op);
+ return true;
- case 0x2f: /* STMW */
+ case 0x2f: // STMW
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->cycles = 32 - G_RS(op);
- return TRUE;
-
- case 0x30: /* LFS */
- case 0x32: /* LFD */
- if (!(ppc->cap & PPCCAP_FPU))
- return FALSE;
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ desc.cycles = 32 - G_RS(op);
+ return true;
+
+ case 0x30: // LFS
+ case 0x32: // LFD
+ if (!(m_context.cap & PPCCAP_FPU))
+ return false;
GPR_USED_OR_ZERO(desc, G_RA(op));
FPR_MODIFIED(desc, G_RD(op));
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
- case 0x31: /* LFSU */
- case 0x33: /* LFDU */
- if (!(ppc->cap & PPCCAP_FPU))
- return FALSE;
+ case 0x31: // LFSU
+ case 0x33: // LFDU
+ if (!(m_context.cap & PPCCAP_FPU))
+ return false;
if (G_RA(op) == 0)
- return FALSE;
+ return false;
GPR_USED(desc, G_RA(op));
GPR_MODIFIED(desc, G_RA(op));
FPR_MODIFIED(desc, G_RD(op));
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
- case 0x34: /* STFS */
- case 0x36: /* STFD */
- if (!(ppc->cap & PPCCAP_FPU))
- return FALSE;
+ case 0x34: // STFS
+ case 0x36: // STFD
+ if (!(m_context.cap & PPCCAP_FPU))
+ return false;
GPR_USED_OR_ZERO(desc, G_RA(op));
FPR_USED(desc, G_RS(op));
- desc->flags |= OPFLAG_WRITES_MEMORY;
- return TRUE;
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
- case 0x35: /* STFSU */
- case 0x37: /* STFDU */
- if (!(ppc->cap & PPCCAP_FPU))
- return FALSE;
+ case 0x35: // STFSU
+ case 0x37: // STFDU
+ if (!(m_context.cap & PPCCAP_FPU))
+ return false;
if (G_RA(op) == 0)
- return FALSE;
+ return false;
GPR_USED(desc, G_RA(op));
GPR_MODIFIED(desc, G_RA(op));
FPR_USED(desc, G_RS(op));
- desc->flags |= OPFLAG_WRITES_MEMORY;
- return TRUE;
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
- case 0x3b: /* 0x3b group */
- return describe_instruction_3b(ppc, op, desc, prev);
+ case 0x3b: // 0x3b group
+ return describe_3b(op, desc, prev);
- case 0x3f: /* 0x3f group */
- return describe_instruction_3f(ppc, op, desc, prev);
+ case 0x3f: // 0x3f group
+ return describe_3f(op, desc, prev);
}
- return FALSE;
+ return false;
}
@@ -421,21 +391,21 @@ int ppcfe_describe(void *param, opcode_desc *desc, const opcode_desc *prev)
0x13 group
-------------------------------------------------*/
-static int describe_instruction_13(powerpc_state *ppc, UINT32 op, opcode_desc *desc, const opcode_desc *prev)
+bool ppc_frontend::describe_13(UINT32 op, opcode_desc &desc, const opcode_desc *prev)
{
UINT32 opswitch = (op >> 1) & 0x3ff;
switch (opswitch)
{
- case 0x000: /* MTCRF */
+ case 0x000: // MTCRF
CR_USED(desc, G_CRFS(op));
CR_MODIFIED(desc, G_CRFD(op));
- /* CR logical folding */
+ // CR logical folding
if (prev == NULL || prev->regout[2] == 0)
- desc->cycles = 0;
- return TRUE;
+ desc.cycles = 0;
+ return true;
- case 0x010: /* BCLRx */
+ case 0x010: // BCLRx
LR_USED(desc);
if (!(G_BO(op) & 0x10))
CR_BIT_USED(desc, G_BI(op));
@@ -447,72 +417,72 @@ static int describe_instruction_13(powerpc_state *ppc, UINT32 op, opcode_desc *d
if (op & M_LK)
LR_MODIFIED(desc);
if ((G_BO(op) & 0x14) == 0x14)
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
else
- desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
- desc->targetpc = BRANCH_TARGET_DYNAMIC;
- return TRUE;
-
- case 0x021: /* CRNOR */
- case 0x081: /* CRANDC */
- case 0x0c1: /* CRXOR */
- case 0x0e1: /* CRNAND */
- case 0x101: /* CRAND */
- case 0x121: /* CREQV */
- case 0x1a1: /* CRORC */
- case 0x1c1: /* CROR */
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ return true;
+
+ case 0x021: // CRNOR
+ case 0x081: // CRANDC
+ case 0x0c1: // CRXOR
+ case 0x0e1: // CRNAND
+ case 0x101: // CRAND
+ case 0x121: // CREQV
+ case 0x1a1: // CRORC
+ case 0x1c1: // CROR
CR_BIT_USED(desc, G_CRBA(op));
CR_BIT_USED(desc, G_CRBB(op));
CR_BIT_MODIFIED(desc, G_CRBD(op));
- /* CR logical folding */
+ // CR logical folding
if (prev == NULL || prev->regout[2] == 0)
- desc->cycles = 0;
- return TRUE;
-
- case 0x032: /* RFI */
- if (!(ppc->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->targetpc = BRANCH_TARGET_DYNAMIC;
- if (is_601_class(ppc))
- desc->cycles = 13; /* 601 */
- else if (is_603_class(ppc))
- desc->cycles = 3; /* 603 */
+ desc.cycles = 0;
+ return true;
+
+ case 0x032: // RFI
+ if (!(m_context.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.targetpc = BRANCH_TARGET_DYNAMIC;
+ if (is_601_class())
+ desc.cycles = 13; // 601
+ else if (is_603_class())
+ desc.cycles = 3; // 603
else
- desc->cycles = 3; /* ??? */
- return TRUE;
-
- case 0x033: /* RFCI */
- if (!(ppc->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->targetpc = BRANCH_TARGET_DYNAMIC;
- return TRUE;
-
- case 0x096: /* ISYNC */
- if (!(ppc->cap & (PPCCAP_VEA | PPCCAP_4XX)))
- return FALSE;
- if (is_601_class(ppc))
- desc->cycles = 6; /* 601 */
- return TRUE;
-
- case 0x210: /* BCCTRx */
+ desc.cycles = 3; // ???
+ return true;
+
+ case 0x033: // RFCI
+ if (!(m_context.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.targetpc = BRANCH_TARGET_DYNAMIC;
+ return true;
+
+ case 0x096: // ISYNC
+ if (!(m_context.cap & (PPCCAP_VEA | PPCCAP_4XX)))
+ return false;
+ if (is_601_class())
+ desc.cycles = 6; // 601
+ return true;
+
+ case 0x210: // BCCTRx
CTR_USED(desc);
if (!(G_BO(op) & 0x10))
CR_BIT_USED(desc, G_BI(op));
if (!(G_BO(op) & 0x04))
- return FALSE;
+ return false;
if (op & M_LK)
LR_MODIFIED(desc);
if ((G_BO(op) & 0x14) == 0x14)
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
else
- desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
- desc->targetpc = BRANCH_TARGET_DYNAMIC;
- return TRUE;
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ return true;
}
- return FALSE;
+ return false;
}
@@ -522,59 +492,59 @@ static int describe_instruction_13(powerpc_state *ppc, UINT32 op, opcode_desc *d
0x1f group
-------------------------------------------------*/
-static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *desc, const opcode_desc *prev)
+bool ppc_frontend::describe_1f(UINT32 op, opcode_desc &desc, const opcode_desc *prev)
{
UINT32 opswitch = (op >> 1) & 0x3ff;
int spr, regnum;
switch (opswitch)
{
- case 0x009: /* MULHDUx - 64-bit only */
- case 0x015: /* LDX - 64-bit only */
- case 0x01b: /* SLDx - 64-bit only */
- case 0x035: /* LDUX - 64-bit only */
- case 0x03a: /* CNTLZDx - 64-bit only */
- case 0x044: /* TD - 64-bit only */
- case 0x049: /* MULHDx - 64-bit only */
- case 0x054: /* LDARX - 64-bit only */
- case 0x095: /* STDX - 64-bit only */
- case 0x0b5: /* STDUX - 64-bit only */
- case 0x0d6: /* STDCX. - 64-bit only */
- case 0x0e9: /* MULLD - 64-bit only */
- case 0x2e9: /* MULLDO - 64-bit only */
- case 0x155: /* LWAX - 64-bit only */
- case 0x175: /* LWAUX - 64-bit only */
- case 0x33a: /* SRADIx - 64-bit only */
- case 0x33b: /* SRADIx - 64-bit only */
- case 0x1b2: /* SLBIE - 64-bit only */
- case 0x1c9: /* DIVDUx - 64-bit only */
- case 0x3c9: /* DIVDUOx - 64-bit only */
- case 0x1e9: /* DIVDx - 64-bit only */
- case 0x3e9: /* DIVDOx - 64-bit only */
- case 0x1f2: /* SLBIA - 64-bit only */
- case 0x21b: /* SRDx - 64-bit only */
- case 0x31a: /* SRADx - 64-bit only */
- case 0x3da: /* EXTSW - 64-bit only */
- return FALSE;
-
- case 0x000: /* CMP */
- case 0x020: /* CMPL */
+ case 0x009: // MULHDUx - 64-bit only
+ case 0x015: // LDX - 64-bit only
+ case 0x01b: // SLDx - 64-bit only
+ case 0x035: // LDUX - 64-bit only
+ case 0x03a: // CNTLZDx - 64-bit only
+ case 0x044: // TD - 64-bit only
+ case 0x049: // MULHDx - 64-bit only
+ case 0x054: // LDARX - 64-bit only
+ case 0x095: // STDX - 64-bit only
+ case 0x0b5: // STDUX - 64-bit only
+ case 0x0d6: // STDCX. - 64-bit only
+ case 0x0e9: // MULLD - 64-bit only
+ case 0x2e9: // MULLDO - 64-bit only
+ case 0x155: // LWAX - 64-bit only
+ case 0x175: // LWAUX - 64-bit only
+ case 0x33a: // SRADIx - 64-bit only
+ case 0x33b: // SRADIx - 64-bit only
+ case 0x1b2: // SLBIE - 64-bit only
+ case 0x1c9: // DIVDUx - 64-bit only
+ case 0x3c9: // DIVDUOx - 64-bit only
+ case 0x1e9: // DIVDx - 64-bit only
+ case 0x3e9: // DIVDOx - 64-bit only
+ case 0x1f2: // SLBIA - 64-bit only
+ case 0x21b: // SRDx - 64-bit only
+ case 0x31a: // SRADx - 64-bit only
+ case 0x3da: // EXTSW - 64-bit only
+ return false;
+
+ case 0x000: // CMP
+ case 0x020: // CMPL
GPR_USED(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
XER_SO_USED(desc);
CR_MODIFIED(desc, G_CRFD(op));
- return TRUE;
+ return true;
- case 0x004: /* TW */
+ case 0x004: // TW
GPR_USED(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
- desc->flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
- if (is_603_class(ppc))
- desc->cycles = 2; /* 603 */
- return TRUE;
+ desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+ if (is_603_class())
+ desc.cycles = 2; // 603
+ return true;
- case 0x008: /* SUBFCx */
- case 0x00a: /* ADDCx */
+ case 0x008: // SUBFCx
+ case 0x00a: // ADDCx
GPR_USED(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
GPR_MODIFIED(desc, G_RD(op));
@@ -584,10 +554,10 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
XER_SO_USED(desc);
CR_MODIFIED(desc, 0);
}
- return TRUE;
+ return true;
- case 0x088: /* SUBFEx */
- case 0x08a: /* ADDEx */
+ case 0x088: // SUBFEx
+ case 0x08a: // ADDEx
GPR_USED(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
XER_CA_USED(desc);
@@ -598,12 +568,12 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
XER_SO_USED(desc);
CR_MODIFIED(desc, 0);
}
- return TRUE;
+ return true;
- case 0x0c8: /* SUBFZEx */
- case 0x0ca: /* ADDZEx */
- case 0x0e8: /* SUBFMEx */
- case 0x0ea: /* ADDMEx */
+ case 0x0c8: // SUBFZEx
+ case 0x0ca: // ADDZEx
+ case 0x0e8: // SUBFMEx
+ case 0x0ea: // ADDMEx
GPR_USED(desc, G_RA(op));
XER_CA_USED(desc);
GPR_MODIFIED(desc, G_RD(op));
@@ -613,11 +583,11 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
XER_SO_USED(desc);
CR_MODIFIED(desc, 0);
}
- return TRUE;
+ return true;
- case 0x00b: /* MULHWUx */
- case 0x04b: /* MULHWx */
- case 0x0eb: /* MULLWx */
+ case 0x00b: // MULHWUx
+ case 0x04b: // MULHWx
+ case 0x0eb: // MULLWx
GPR_USED(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
GPR_MODIFIED(desc, G_RD(op));
@@ -626,18 +596,18 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
XER_SO_USED(desc);
CR_MODIFIED(desc, 0);
}
- if (is_403_class(ppc))
- desc->cycles = 4; /* 4XX */
- else if (is_601_class(ppc))
- desc->cycles = 5; /* 601: 5/9/10 */
- else if (is_603_class(ppc))
- desc->cycles = 2; /* 603: 2,3,4,5,6 */
+ if (is_403_class())
+ desc.cycles = 4; // 4XX
+ else if (is_601_class())
+ desc.cycles = 5; // 601: 5/9/10
+ else if (is_603_class())
+ desc.cycles = 2; // 603: 2,3,4,5,6
else
- desc->cycles = 2; /* ??? */
- return TRUE;
+ desc.cycles = 2; // ???
+ return true;
- case 0x1cb: /* DIVWUx */
- case 0x1eb: /* DIVWx */
+ case 0x1cb: // DIVWUx
+ case 0x1eb: // DIVWx
GPR_USED(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
GPR_MODIFIED(desc, G_RD(op));
@@ -646,18 +616,18 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
XER_SO_USED(desc);
CR_MODIFIED(desc, 0);
}
- if (is_403_class(ppc))
- desc->cycles = 33; /* 4XX */
- else if (is_601_class(ppc))
- desc->cycles = 36; /* 601 */
- else if (is_603_class(ppc))
- desc->cycles = 37; /* 603 */
+ if (is_403_class())
+ desc.cycles = 33; // 4XX
+ else if (is_601_class())
+ desc.cycles = 36; // 601
+ else if (is_603_class())
+ desc.cycles = 37; // 603
else
- desc->cycles = 33; /* ??? */
- return TRUE;
+ desc.cycles = 33; // ???
+ return true;
- case 0x028: /* SUBFx */
- case 0x10a: /* ADDx */
+ case 0x028: // SUBFx
+ case 0x10a: // ADDx
GPR_USED(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
GPR_MODIFIED(desc, G_RD(op));
@@ -666,10 +636,10 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
XER_SO_USED(desc);
CR_MODIFIED(desc, 0);
}
- return TRUE;
+ return true;
- case 0x208: /* SUBFCOx */
- case 0x20a: /* ADDCOx */
+ case 0x208: // SUBFCOx
+ case 0x20a: // ADDCOx
GPR_USED(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
GPR_MODIFIED(desc, G_RD(op));
@@ -678,10 +648,10 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
XER_CA_MODIFIED(desc);
if (op & M_RC)
CR_MODIFIED(desc, 0);
- return TRUE;
+ return true;
- case 0x288: /* SUBFEOx */
- case 0x28a: /* ADDEOx */
+ case 0x288: // SUBFEOx
+ case 0x28a: // ADDEOx
GPR_USED(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
XER_CA_USED(desc);
@@ -691,12 +661,12 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
XER_CA_MODIFIED(desc);
if (op & M_RC)
CR_MODIFIED(desc, 0);
- return TRUE;
+ return true;
- case 0x2c8: /* SUBFZEOx */
- case 0x2ca: /* ADDZEOx */
- case 0x2e8: /* SUBFMEOx */
- case 0x2ea: /* ADDMEOx */
+ case 0x2c8: // SUBFZEOx
+ case 0x2ca: // ADDZEOx
+ case 0x2e8: // SUBFMEOx
+ case 0x2ea: // ADDMEOx
GPR_USED(desc, G_RA(op));
XER_CA_USED(desc);
GPR_MODIFIED(desc, G_RD(op));
@@ -705,9 +675,9 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
XER_CA_MODIFIED(desc);
if (op & M_RC)
CR_MODIFIED(desc, 0);
- return TRUE;
+ return true;
- case 0x2eb: /* MULLWOx */
+ case 0x2eb: // MULLWOx
GPR_USED(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
GPR_MODIFIED(desc, G_RD(op));
@@ -715,18 +685,18 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
XER_SO_MODIFIED(desc);
if (op & M_RC)
CR_MODIFIED(desc, 0);
- if (is_403_class(ppc))
- desc->cycles = 4; /* 4XX */
- else if (is_601_class(ppc))
- desc->cycles = 5; /* 601: 5/9/10 */
- else if (is_603_class(ppc))
- desc->cycles = 2; /* 603: 2,3,4,5,6 */
+ if (is_403_class())
+ desc.cycles = 4; // 4XX
+ else if (is_601_class())
+ desc.cycles = 5; // 601: 5/9/10
+ else if (is_603_class())
+ desc.cycles = 2; // 603: 2,3,4,5,6
else
- desc->cycles = 2; /* ??? */
- return TRUE;
+ desc.cycles = 2; // ???
+ return true;
- case 0x3cb: /* DIVWUOx */
- case 0x3eb: /* DIVWOx */
+ case 0x3cb: // DIVWUOx
+ case 0x3eb: // DIVWOx
GPR_USED(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
GPR_MODIFIED(desc, G_RD(op));
@@ -734,18 +704,18 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
XER_SO_MODIFIED(desc);
if (op & M_RC)
CR_MODIFIED(desc, 0);
- if (is_403_class(ppc))
- desc->cycles = 33; /* 4XX */
- else if (is_601_class(ppc))
- desc->cycles = 36; /* 601 */
- else if (is_603_class(ppc))
- desc->cycles = 37; /* 603 */
+ if (is_403_class())
+ desc.cycles = 33; // 4XX
+ else if (is_601_class())
+ desc.cycles = 36; // 601
+ else if (is_603_class())
+ desc.cycles = 37; // 603
else
- desc->cycles = 33; /* ??? */
- return TRUE;
+ desc.cycles = 33; // ???
+ return true;
- case 0x228: /* SUBFOx */
- case 0x30a: /* ADDOx */
+ case 0x228: // SUBFOx
+ case 0x30a: // ADDOx
GPR_USED(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
GPR_MODIFIED(desc, G_RD(op));
@@ -753,9 +723,9 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
XER_SO_MODIFIED(desc);
if (op & M_RC)
CR_MODIFIED(desc, 0);
- return TRUE;
+ return true;
- case 0x013: /* MFCR */
+ case 0x013: // MFCR
CR_USED(desc, 0);
CR_USED(desc, 1);
CR_USED(desc, 2);
@@ -765,33 +735,33 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
CR_USED(desc, 6);
CR_USED(desc, 7);
GPR_MODIFIED(desc, G_RD(op));
- return TRUE;
-
- case 0x136: /* ECIWX */
- if (!(ppc->cap & PPCCAP_VEA))
- return FALSE;
- case 0x014: /* LWARX */
- case 0x017: /* LWZX */
- case 0x057: /* LBZX */
- case 0x117: /* LHZX */
- case 0x157: /* LHAX */
- case 0x216: /* LWBRX */
- case 0x316: /* LHBRX */
+ return true;
+
+ case 0x136: // ECIWX
+ if (!(m_context.cap & PPCCAP_VEA))
+ return false;
+ case 0x014: // LWARX
+ case 0x017: // LWZX
+ case 0x057: // LBZX
+ case 0x117: // LHZX
+ case 0x157: // LHAX
+ case 0x216: // LWBRX
+ case 0x316: // LHBRX
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;
- return TRUE;
-
- case 0x018: /* SLWx */
- case 0x01c: /* ANDx */
- case 0x03c: /* ANDCx */
- case 0x07c: /* NORx */
- case 0x11c: /* EQVx */
- case 0x13c: /* XORx */
- case 0x19c: /* ORCx */
- case 0x1bc: /* ORx */
- case 0x1dc: /* NANDx */
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x018: // SLWx
+ case 0x01c: // ANDx
+ case 0x03c: // ANDCx
+ case 0x07c: // NORx
+ case 0x11c: // EQVx
+ case 0x13c: // XORx
+ case 0x19c: // ORCx
+ case 0x1bc: // ORx
+ case 0x1dc: // NANDx
GPR_USED(desc, G_RS(op));
GPR_USED(desc, G_RB(op));
GPR_MODIFIED(desc, G_RA(op));
@@ -800,10 +770,10 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
XER_SO_USED(desc);
CR_MODIFIED(desc, 0);
}
- return TRUE;
+ return true;
- case 0x218: /* SRWx */
- case 0x318: /* SRAWx */
+ case 0x218: // SRWx
+ case 0x318: // SRAWx
GPR_USED(desc, G_RS(op));
GPR_USED(desc, G_RB(op));
GPR_MODIFIED(desc, G_RA(op));
@@ -813,11 +783,11 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
XER_SO_USED(desc);
CR_MODIFIED(desc, 0);
}
- return TRUE;
+ return true;
- case 0x01a: /* CNTLZWx */
- case 0x39a: /* EXTSHx */
- case 0x3ba: /* EXTSBx */
+ case 0x01a: // CNTLZWx
+ case 0x39a: // EXTSHx
+ case 0x3ba: // EXTSBx
GPR_USED(desc, G_RS(op));
GPR_MODIFIED(desc, G_RA(op));
if (op & M_RC)
@@ -825,42 +795,42 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
XER_SO_USED(desc);
CR_MODIFIED(desc, 0);
}
- return TRUE;
-
- case 0x036: /* DCBST */
- case 0x056: /* DCBF */
- case 0x0f6: /* DCBTST */
- case 0x116: /* DCBT */
- case 0x2f6: /* DCBA */
- case 0x3d6: /* ICBI */
- if (!(ppc->cap & (PPCCAP_VEA | PPCCAP_4XX)))
- return FALSE;
+ return true;
+
+ case 0x036: // DCBST
+ case 0x056: // DCBF
+ case 0x0f6: // DCBTST
+ case 0x116: // DCBT
+ case 0x2f6: // DCBA
+ case 0x3d6: // ICBI
+ if (!(m_context.cap & (PPCCAP_VEA | PPCCAP_4XX)))
+ return false;
GPR_USED_OR_ZERO(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
- return TRUE;
+ return true;
- case 0x1d6: /* DCBI */
- if (!(ppc->cap & (PPCCAP_OEA | PPCCAP_4XX)))
- return FALSE;
+ case 0x1d6: // DCBI
+ if (!(m_context.cap & (PPCCAP_OEA | PPCCAP_4XX)))
+ return false;
GPR_USED_OR_ZERO(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
- desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
- return TRUE;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
- case 0x037: /* LWZUX */
- case 0x077: /* LBZUX */
- case 0x137: /* LHZUX */
- case 0x177: /* LHAUX */
+ case 0x037: // LWZUX
+ case 0x077: // LBZUX
+ case 0x137: // LHZUX
+ case 0x177: // LHAUX
if (G_RA(op) == 0 || G_RA(op) == G_RD(op))
- return FALSE;
+ return false;
GPR_USED(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
GPR_MODIFIED(desc, G_RD(op));
GPR_MODIFIED(desc, G_RA(op));
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
- case 0x153: /* MFSPR */
+ case 0x153: // MFSPR
GPR_MODIFIED(desc, G_RD(op));
spr = compute_spr(G_SPR(op));
if (spr == SPR_LR)
@@ -875,43 +845,43 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
XER_SO_USED(desc);
}
if (spr & 0x010)
- desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
- if ((ppc->cap & PPCCAP_4XX) && spr == SPR4XX_TBLU)
- desc->cycles = POWERPC_COUNT_READ_TBL;
- else if ((ppc->cap & PPCCAP_VEA) && spr == SPRVEA_TBL_R)
- desc->cycles = POWERPC_COUNT_READ_TBL;
- else if ((ppc->cap & PPCCAP_OEA) && spr == SPROEA_DEC)
- desc->cycles = POWERPC_COUNT_READ_DEC;
- return TRUE;
-
- case 0x053: /* MFMSR */
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ if ((m_context.cap & PPCCAP_4XX) && spr == SPR4XX_TBLU)
+ desc.cycles = POWERPC_COUNT_READ_TBL;
+ else if ((m_context.cap & PPCCAP_VEA) && spr == SPRVEA_TBL_R)
+ desc.cycles = POWERPC_COUNT_READ_TBL;
+ else if ((m_context.cap & PPCCAP_OEA) && spr == SPROEA_DEC)
+ desc.cycles = POWERPC_COUNT_READ_DEC;
+ return true;
+
+ case 0x053: // MFMSR
GPR_MODIFIED(desc, G_RD(op));
- desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_CAN_EXPOSE_EXTERNAL_INT;
- if (is_601_class(ppc))
- desc->cycles = 2; /* 601 */
- return TRUE;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_CAN_EXPOSE_EXTERNAL_INT;
+ if (is_601_class())
+ desc.cycles = 2; // 601
+ return true;
- case 0x253: /* MFSR */
+ case 0x253: // MFSR
GPR_MODIFIED(desc, G_RD(op));
- desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
- return TRUE;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
- case 0x293: /* MFSRIN */
+ case 0x293: // MFSRIN
GPR_USED(desc, G_RB(op));
GPR_MODIFIED(desc, G_RD(op));
- desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
- return TRUE;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
- case 0x173: /* MFTB */
- if (!(ppc->cap & PPCCAP_VEA))
- return FALSE;
+ case 0x173: // MFTB
+ if (!(m_context.cap & PPCCAP_VEA))
+ return false;
GPR_MODIFIED(desc, G_RD(op));
spr = compute_spr(G_SPR(op));
if (spr == SPRVEA_TBL_R)
- desc->cycles = POWERPC_COUNT_READ_TBL;
- return TRUE;
+ desc.cycles = POWERPC_COUNT_READ_TBL;
+ return true;
- case 0x068: /* NEGx */
+ case 0x068: // NEGx
GPR_USED(desc, G_RA(op));
GPR_MODIFIED(desc, G_RD(op));
if (op & M_RC)
@@ -919,18 +889,18 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
XER_SO_USED(desc);
CR_MODIFIED(desc, 0);
}
- return TRUE;
+ return true;
- case 0x268: /* NEGOx */
+ case 0x268: // NEGOx
GPR_USED(desc, G_RA(op));
GPR_MODIFIED(desc, G_RD(op));
XER_OV_MODIFIED(desc);
XER_SO_MODIFIED(desc);
if (op & M_RC)
CR_MODIFIED(desc, 0);
- return TRUE;
+ return true;
- case 0x090: /* MTCRF */
+ case 0x090: // MTCRF
GPR_USED(desc, G_RS(op));
if (G_CRM(op) & 0x80) CR_MODIFIED(desc, 0);
if (G_CRM(op) & 0x40) CR_MODIFIED(desc, 1);
@@ -940,25 +910,25 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
if (G_CRM(op) & 0x04) CR_MODIFIED(desc, 5);
if (G_CRM(op) & 0x02) CR_MODIFIED(desc, 6);
if (G_CRM(op) & 0x01) CR_MODIFIED(desc, 7);
- return TRUE;
+ return true;
- case 0x092: /* MTMSR */
+ case 0x092: // MTMSR
GPR_USED(desc, G_RS(op));
- desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_CAN_CHANGE_MODES | OPFLAG_END_SEQUENCE;
- if (is_601_class(ppc))
- desc->cycles = 17; /* 601 */
- else if (is_603_class(ppc))
- desc->cycles = 2; /* 603 */
- return TRUE;
-
- case 0x0d2: /* MTSR */
- if (!(ppc->cap & PPCCAP_OEA))
- return FALSE;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_CAN_CHANGE_MODES | OPFLAG_END_SEQUENCE;
+ if (is_601_class())
+ desc.cycles = 17; // 601
+ else if (is_603_class())
+ desc.cycles = 2; // 603
+ return true;
+
+ case 0x0d2: // MTSR
+ if (!(m_context.cap & PPCCAP_OEA))
+ return false;
GPR_USED(desc, G_RS(op));
- desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
- return TRUE;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
- case 0x1d3: /* MTSPR */
+ case 0x1d3: // MTSPR
GPR_USED(desc, G_RS(op));
spr = compute_spr(G_SPR(op));
if (spr == SPR_LR)
@@ -973,65 +943,65 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
XER_SO_MODIFIED(desc);
}
if (spr & 0x010)
- desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
- return TRUE;
-
- case 0x1b6: /* ECOWX */
- if (!(ppc->cap & PPCCAP_VEA))
- return FALSE;
- case 0x096: /* STWCX. */
- case 0x097: /* STWX */
- case 0x0d7: /* STBX */
- case 0x197: /* STHX */
- case 0x296: /* STWBRX */
- case 0x396: /* STHBRX */
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x1b6: // ECOWX
+ if (!(m_context.cap & PPCCAP_VEA))
+ return false;
+ case 0x096: // STWCX.
+ case 0x097: // STWX
+ case 0x0d7: // STBX
+ case 0x197: // STHX
+ case 0x296: // STWBRX
+ case 0x396: // STHBRX
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;
- return TRUE;
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
- case 0x0b7: /* STWUX */
- case 0x0f7: /* STBUX */
- case 0x1b7: /* STHUX */
+ case 0x0b7: // STWUX
+ case 0x0f7: // STBUX
+ case 0x1b7: // STHUX
if (G_RA(op) == 0)
- return FALSE;
+ return false;
GPR_USED(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
GPR_USED(desc, G_RS(op));
GPR_MODIFIED(desc, G_RA(op));
- desc->flags |= OPFLAG_WRITES_MEMORY;
- return TRUE;
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
- case 0x0f2: /* MTSRIN */
- if (!(ppc->cap & PPCCAP_OEA))
- return FALSE;
+ case 0x0f2: // MTSRIN
+ if (!(m_context.cap & PPCCAP_OEA))
+ return false;
GPR_USED(desc, G_RS(op));
GPR_USED(desc, G_RB(op));
- desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
- return TRUE;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
- case 0x132: /* TLBIE */
- if (!(ppc->cap & PPCCAP_OEA))
- return FALSE;
+ case 0x132: // TLBIE
+ if (!(m_context.cap & PPCCAP_OEA))
+ return false;
GPR_USED(desc, G_RB(op));
- desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
- return TRUE;
-
- case 0x172: /* TLBIA */
- if (!(ppc->cap & PPCCAP_OEA) || (ppc->cap & PPCCAP_603_MMU))
- return FALSE;
- desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
- return TRUE;
-
- case 0x3d2: /* TLBLD */
- case 0x3f2: /* TLBLI */
- if (!(ppc->cap & PPCCAP_603_MMU) && !is_602_class(ppc))
- return FALSE;
- desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
- return TRUE;
-
- case 0x200: /* MCRXR */
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x172: // TLBIA
+ if (!(m_context.cap & PPCCAP_OEA) || (m_context.cap & PPCCAP_603_MMU))
+ return false;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x3d2: // TLBLD
+ case 0x3f2: // TLBLI
+ if (!(m_context.cap & PPCCAP_603_MMU) && !is_602_class())
+ return false;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x200: // MCRXR
XER_CA_USED(desc);
XER_OV_USED(desc);
XER_SO_USED(desc);
@@ -1039,104 +1009,104 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
XER_CA_MODIFIED(desc);
XER_OV_MODIFIED(desc);
XER_SO_MODIFIED(desc);
- return TRUE;
+ return true;
- case 0x215: /* LSWX */
+ case 0x215: // LSWX
GPR_USED_OR_ZERO(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
XER_COUNT_USED(desc);
for (regnum = 0; regnum < 32; regnum++)
GPR_MODIFIED(desc, regnum);
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
- case 0x217: /* LFSX */
- case 0x257: /* LFDX */
- if (!(ppc->cap & PPCCAP_FPU))
- return FALSE;
+ case 0x217: // LFSX
+ case 0x257: // LFDX
+ if (!(m_context.cap & PPCCAP_FPU))
+ return false;
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;
- return TRUE;
-
- case 0x236: /* TLBSYNC */
- if (!(ppc->cap & PPCCAP_OEA))
- return FALSE;
- desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
- return TRUE;
-
- case 0x256: /* SYNC */
- return TRUE;
-
- case 0x356: /* EIEIO */
- if (!(ppc->cap & PPCCAP_VEA))
- return FALSE;
- return TRUE;
-
- case 0x237: /* LFSUX */
- case 0x277: /* LFDUX */
- if (!(ppc->cap & PPCCAP_FPU))
- return FALSE;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x236: // TLBSYNC
+ if (!(m_context.cap & PPCCAP_OEA))
+ return false;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x256: // SYNC
+ return true;
+
+ case 0x356: // EIEIO
+ if (!(m_context.cap & PPCCAP_VEA))
+ return false;
+ return true;
+
+ case 0x237: // LFSUX
+ case 0x277: // LFDUX
+ if (!(m_context.cap & PPCCAP_FPU))
+ return false;
if (G_RA(op) == 0)
- return FALSE;
+ return false;
GPR_USED(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
GPR_MODIFIED(desc, G_RA(op));
FPR_MODIFIED(desc, G_RD(op));
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
- case 0x255: /* LSWI */
+ 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->cycles = (((G_NB(op) - 1) & 0x1f) + 1 + 3) / 4;
- return TRUE;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ desc.cycles = (((G_NB(op) - 1) & 0x1f) + 1 + 3) / 4;
+ return true;
- case 0x295: /* STSWX */
+ case 0x295: // STSWX
GPR_USED_OR_ZERO(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
XER_COUNT_USED(desc);
for (regnum = 0; regnum < 32; regnum++)
GPR_USED(desc, regnum);
- desc->flags |= OPFLAG_WRITES_MEMORY;
- return TRUE;
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
- case 0x2d5: /* STSWI */
+ 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->cycles = (((G_NB(op) - 1) & 0x1f) + 1 + 3) / 4;
- return TRUE;
-
- case 0x297: /* STFSX */
- case 0x2d7: /* STFDX */
- case 0x3d7: /* STFIWX */
- if (!(ppc->cap & PPCCAP_FPU))
- return FALSE;
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ desc.cycles = (((G_NB(op) - 1) & 0x1f) + 1 + 3) / 4;
+ return true;
+
+ case 0x297: // STFSX
+ case 0x2d7: // STFDX
+ case 0x3d7: // STFIWX
+ if (!(m_context.cap & PPCCAP_FPU))
+ return false;
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;
- return TRUE;
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
- case 0x2b7: /* STFSUX */
- case 0x2f7: /* STFDUX */
- if (!(ppc->cap & PPCCAP_FPU))
- return FALSE;
+ case 0x2b7: // STFSUX
+ case 0x2f7: // STFDUX
+ if (!(m_context.cap & PPCCAP_FPU))
+ return false;
if (G_RA(op) == 0)
- return FALSE;
+ return false;
GPR_USED_OR_ZERO(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
GPR_MODIFIED(desc, G_RA(op));
FPR_USED(desc, G_RS(op));
- desc->flags |= OPFLAG_WRITES_MEMORY;
- return TRUE;
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
- case 0x338: /* SRAWIx */
+ case 0x338: // SRAWIx
GPR_USED(desc, G_RS(op));
GPR_MODIFIED(desc, G_RA(op));
XER_CA_MODIFIED(desc);
@@ -1145,73 +1115,73 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
XER_SO_USED(desc);
CR_MODIFIED(desc, 0);
}
- return TRUE;
+ return true;
- case 0x3f6: /* DCBZ */
- if (!(ppc->cap & (PPCCAP_VEA | PPCCAP_4XX)))
- return FALSE;
+ case 0x3f6: // DCBZ
+ if (!(m_context.cap & (PPCCAP_VEA | PPCCAP_4XX)))
+ return false;
GPR_USED_OR_ZERO(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
- desc->flags |= OPFLAG_WRITES_MEMORY;
- return TRUE;
-
- case 0x106: /* ICBT */
- case 0x1c6: /* DCCCI */
- case 0x3c6: /* ICCCI */
- if (!(ppc->cap & PPCCAP_4XX))
- return FALSE;
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x106: // ICBT
+ case 0x1c6: // DCCCI
+ case 0x3c6: // ICCCI
+ if (!(m_context.cap & PPCCAP_4XX))
+ return false;
GPR_USED_OR_ZERO(desc, G_RA(op));
GPR_USED(desc, G_RB(op));
- desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
- return TRUE;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
- case 0x1e6: /* DCREAD */
- case 0x3e6: /* ICREAD */
- if (!(ppc->cap & PPCCAP_4XX))
- return FALSE;
+ case 0x1e6: // DCREAD
+ case 0x3e6: // ICREAD
+ if (!(m_context.cap & PPCCAP_4XX))
+ return false;
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;
- return TRUE;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
- case 0x143: /* MFDCR */
- if (!(ppc->cap & PPCCAP_4XX))
- return FALSE;
+ case 0x143: // MFDCR
+ if (!(m_context.cap & PPCCAP_4XX))
+ return false;
GPR_MODIFIED(desc, G_RD(op));
- desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
- return TRUE;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
- case 0x1c3: /* MTDCR */
- if (!(ppc->cap & PPCCAP_4XX))
- return FALSE;
+ case 0x1c3: // MTDCR
+ if (!(m_context.cap & PPCCAP_4XX))
+ return false;
GPR_USED(desc, G_RS(op));
- desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_CAN_EXPOSE_EXTERNAL_INT;
- return TRUE;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_CAN_EXPOSE_EXTERNAL_INT;
+ return true;
- case 0x083: /* WRTEE */
- if (!(ppc->cap & PPCCAP_4XX))
- return FALSE;
+ case 0x083: // WRTEE
+ if (!(m_context.cap & PPCCAP_4XX))
+ return false;
GPR_USED(desc, G_RS(op));
- desc->flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT;
- return TRUE;
+ desc.flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT;
+ return true;
- case 0x0a3: /* WRTEEI */
- if (!(ppc->cap & PPCCAP_4XX))
- return FALSE;
+ case 0x0a3: // WRTEEI
+ if (!(m_context.cap & PPCCAP_4XX))
+ return false;
if (op & MSR_EE)
- desc->flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT;
- return TRUE;
-
- case 0x254: /* ESA */
- case 0x274: /* DSA */
- if (!is_602_class(ppc))
- return FALSE;
- desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
- return TRUE;
+ desc.flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT;
+ return true;
+
+ case 0x254: // ESA
+ case 0x274: // DSA
+ if (!is_602_class())
+ return false;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
}
- return FALSE;
+ return false;
}
@@ -1221,62 +1191,62 @@ static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *d
0x3b group
-------------------------------------------------*/
-static int describe_instruction_3b(powerpc_state *ppc, UINT32 op, opcode_desc *desc, const opcode_desc *prev)
+bool ppc_frontend::describe_3b(UINT32 op, opcode_desc &desc, const opcode_desc *prev)
{
UINT32 opswitch = (op >> 1) & 0x1f;
- if (!(ppc->cap & PPCCAP_FPU))
- return FALSE;
+ if (!(m_context.cap & PPCCAP_FPU))
+ return false;
switch (opswitch)
{
- case 0x12: /* FDIVSx */
+ case 0x12: // FDIVSx
FPR_USED(desc, G_RA(op));
FPR_USED(desc, G_RB(op));
FPR_MODIFIED(desc, G_RD(op));
if (op & M_RC)
CR_MODIFIED(desc, 1);
- if (is_601_class(ppc))
- desc->cycles = 17; /* 601 */
- else if (is_603_class(ppc))
- desc->cycles = 18; /* 603 */
+ if (is_601_class())
+ desc.cycles = 17; // 601
+ else if (is_603_class())
+ desc.cycles = 18; // 603
else
- desc->cycles = 17; /* ??? */
+ desc.cycles = 17; // ???
FPSCR_MODIFIED(desc, 4);
- return TRUE;
+ return true;
- case 0x14: /* FSUBSx */
- case 0x15: /* FADDSx */
+ case 0x14: // FSUBSx
+ case 0x15: // FADDSx
FPR_USED(desc, G_RA(op));
FPR_USED(desc, G_RB(op));
FPR_MODIFIED(desc, G_RD(op));
if (op & M_RC)
CR_MODIFIED(desc, 1);
FPSCR_MODIFIED(desc, 4);
- return TRUE;
+ return true;
- case 0x19: /* FMULSx - not the same form as FSUB/FADD! */
+ case 0x19: // FMULSx - not the same form as FSUB/FADD!
FPR_USED(desc, G_RA(op));
FPR_USED(desc, G_REGC(op));
FPR_MODIFIED(desc, G_RD(op));
if (op & M_RC)
CR_MODIFIED(desc, 1);
FPSCR_MODIFIED(desc, 4);
- return TRUE;
+ return true;
- case 0x16: /* FSQRTSx */
- case 0x18: /* FRESx */
+ case 0x16: // FSQRTSx
+ case 0x18: // FRESx
FPR_USED(desc, G_RB(op));
FPR_MODIFIED(desc, G_RD(op));
if (op & M_RC)
CR_MODIFIED(desc, 1);
FPSCR_MODIFIED(desc, 4);
- return TRUE;
+ return true;
- case 0x1c: /* FMSUBSx */
- case 0x1d: /* FMADDSx */
- case 0x1e: /* FNMSUBSx */
- case 0x1f: /* FNMADDSx */
+ case 0x1c: // FMSUBSx
+ case 0x1d: // FMADDSx
+ case 0x1e: // FNMSUBSx
+ case 0x1f: // FNMADDSx
FPR_USED(desc, G_RA(op));
FPR_USED(desc, G_RB(op));
FPR_USED(desc, G_REGC(op));
@@ -1284,10 +1254,10 @@ static int describe_instruction_3b(powerpc_state *ppc, UINT32 op, opcode_desc *d
if (op & M_RC)
CR_MODIFIED(desc, 1);
FPSCR_MODIFIED(desc, 4);
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
@@ -1297,132 +1267,132 @@ static int describe_instruction_3b(powerpc_state *ppc, UINT32 op, opcode_desc *d
0x3f group
-------------------------------------------------*/
-static int describe_instruction_3f(powerpc_state *ppc, UINT32 op, opcode_desc *desc, const opcode_desc *prev)
+bool ppc_frontend::describe_3f(UINT32 op, opcode_desc &desc, const opcode_desc *prev)
{
UINT32 opswitch = (op >> 1) & 0x3ff;
- if (!(ppc->cap & PPCCAP_FPU))
- return FALSE;
+ if (!(m_context.cap & PPCCAP_FPU))
+ return false;
if (opswitch & 0x10)
{
opswitch &= 0x1f;
switch (opswitch)
{
- case 0x12: /* FDIVx */
+ case 0x12: // FDIVx
FPR_USED(desc, G_RA(op));
FPR_USED(desc, G_RB(op));
FPR_MODIFIED(desc, G_RD(op));
if (op & M_RC)
CR_MODIFIED(desc, 1);
- if (is_601_class(ppc))
- desc->cycles = 31; /* 601 */
- else if (is_603_class(ppc))
- desc->cycles = 33; /* 603 */
+ if (is_601_class())
+ desc.cycles = 31; // 601
+ else if (is_603_class())
+ desc.cycles = 33; // 603
else
- desc->cycles = 31; /* ??? */
+ desc.cycles = 31; // ???
FPSCR_MODIFIED(desc, 4);
- return TRUE;
+ return true;
- case 0x19: /* FMULx */
+ case 0x19: // FMULx
FPR_USED(desc, G_RA(op));
FPR_USED(desc, G_REGC(op));
FPR_MODIFIED(desc, G_RD(op));
if (op & M_RC)
CR_MODIFIED(desc, 1);
- desc->cycles = 2; /* 601/603 */
+ desc.cycles = 2; // 601/603
FPSCR_MODIFIED(desc, 4);
- return TRUE;
+ return true;
- case 0x14: /* FSUBx */
- case 0x15: /* FADDx */
+ case 0x14: // FSUBx
+ case 0x15: // FADDx
FPR_USED(desc, G_RA(op));
FPR_USED(desc, G_RB(op));
FPR_MODIFIED(desc, G_RD(op));
if (op & M_RC)
CR_MODIFIED(desc, 1);
FPSCR_MODIFIED(desc, 4);
- return TRUE;
+ return true;
- case 0x16: /* FSQRTx */
- case 0x1a: /* FSQRTEx */
+ case 0x16: // FSQRTx
+ case 0x1a: // FSQRTEx
FPR_USED(desc, G_RB(op));
FPR_MODIFIED(desc, G_RD(op));
if (op & M_RC)
CR_MODIFIED(desc, 1);
FPSCR_MODIFIED(desc, 4);
- return TRUE;
+ return true;
- case 0x17: /* FSELx */
+ case 0x17: // FSELx
FPR_USED(desc, G_RA(op));
FPR_USED(desc, G_RB(op));
FPR_USED(desc, G_REGC(op));
FPR_MODIFIED(desc, G_RD(op));
if (op & M_RC)
CR_MODIFIED(desc, 1);
- desc->cycles = 2; /* 601/603 */
- return TRUE;
+ desc.cycles = 2; // 601/603
+ return true;
- case 0x1c: /* FMSUBx */
- case 0x1d: /* FMADDx */
- case 0x1e: /* FNMSUBx */
- case 0x1f: /* FNMADDx */
+ case 0x1c: // FMSUBx
+ case 0x1d: // FMADDx
+ case 0x1e: // FNMSUBx
+ case 0x1f: // FNMADDx
FPR_USED(desc, G_RA(op));
FPR_USED(desc, G_RB(op));
FPR_USED(desc, G_REGC(op));
FPR_MODIFIED(desc, G_RD(op));
if (op & M_RC)
CR_MODIFIED(desc, 1);
- desc->cycles = 2; /* 601/603 */
+ desc.cycles = 2; // 601/603
FPSCR_MODIFIED(desc, 4);
- return TRUE;
+ return true;
}
}
else
{
switch (opswitch)
{
- case 0x32e: /* FCTIDx - 64-bit only */
- case 0x32f: /* FCTIDZx - 64-bit only */
- case 0x34e: /* FCFIDx - 64-bit only */
- return FALSE;
+ case 0x32e: // FCTIDx - 64-bit only
+ case 0x32f: // FCTIDZx - 64-bit only
+ case 0x34e: // FCFIDx - 64-bit only
+ return false;
- case 0x000: /* FCMPU */
- case 0x020: /* FCMPO */
+ case 0x000: // FCMPU
+ case 0x020: // FCMPO
FPR_USED(desc, G_RA(op));
FPR_USED(desc, G_RB(op));
CR_MODIFIED(desc, G_CRFD(op));
- return TRUE;
+ return true;
- case 0x00c: /* FRSPx */
- case 0x00e: /* FCTIWx */
- case 0x00f: /* FCTIWZx */
+ case 0x00c: // FRSPx
+ case 0x00e: // FCTIWx
+ case 0x00f: // FCTIWZx
FPSCR_MODIFIED(desc, 4);
- case 0x028: /* FNEGx */
- case 0x048: /* FMRx */
- case 0x088: /* FNABSx */
- case 0x108: /* FABSx */
+ case 0x028: // FNEGx
+ case 0x048: // FMRx
+ case 0x088: // FNABSx
+ case 0x108: // FABSx
FPR_USED(desc, G_RB(op));
FPR_MODIFIED(desc, G_RD(op));
if (op & M_RC)
CR_MODIFIED(desc, 1);
- return TRUE;
+ return true;
- case 0x026: /* MTFSB1x */
- case 0x046: /* MTFSB0x */
+ case 0x026: // MTFSB1x
+ case 0x046: // MTFSB0x
FPSCR_MODIFIED(desc, G_CRBD(op) / 4);
- return TRUE;
+ return true;
- case 0x040: /* MCRFS */
+ case 0x040: // MCRFS
FPSCR_USED(desc, G_CRFS(op));
CR_MODIFIED(desc, G_CRFD(op));
- return TRUE;
+ return true;
- case 0x086: /* MTFSFIx */
+ case 0x086: // MTFSFIx
FPSCR_MODIFIED(desc, G_CRFD(op));
- return TRUE;
+ return true;
- case 0x247: /* MFFSx */
+ case 0x247: // MFFSx
FPSCR_USED(desc, 0);
FPSCR_USED(desc, 1);
FPSCR_USED(desc, 2);
@@ -1432,9 +1402,9 @@ static int describe_instruction_3f(powerpc_state *ppc, UINT32 op, opcode_desc *d
FPSCR_USED(desc, 6);
FPSCR_USED(desc, 7);
FPR_MODIFIED(desc, G_RD(op));
- return TRUE;
+ return true;
- case 0x2c7: /* MTFSFx */
+ case 0x2c7: // MTFSFx
FPR_USED(desc, G_RB(op));
if (G_CRM(op) & 0x80) FPSCR_MODIFIED(desc, 0);
if (G_CRM(op) & 0x40) FPSCR_MODIFIED(desc, 1);
@@ -1444,9 +1414,9 @@ static int describe_instruction_3f(powerpc_state *ppc, UINT32 op, opcode_desc *d
if (G_CRM(op) & 0x04) FPSCR_MODIFIED(desc, 5);
if (G_CRM(op) & 0x02) FPSCR_MODIFIED(desc, 6);
if (G_CRM(op) & 0x01) FPSCR_MODIFIED(desc, 7);
- return TRUE;
+ return true;
}
}
- return FALSE;
+ return false;
}
diff --git a/src/emu/cpu/powerpc/ppcfe.h b/src/emu/cpu/powerpc/ppcfe.h
index 27886e1806a..b3209e4358c 100644
--- a/src/emu/cpu/powerpc/ppcfe.h
+++ b/src/emu/cpu/powerpc/ppcfe.h
@@ -4,34 +4,62 @@
Front-end for PowerPC recompiler
+****************************************************************************
+
Copyright Aaron Giles
- Released for general non-commercial use under the MAME license
- Visit http://mamedev.org for licensing and usage restrictions.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
#ifndef __PPCFE_H__
#define __PPCFE_H__
+#include "ppccom.h"
#include "cpu/drcfe.h"
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
+//**************************************************************************
+// MACROS
+//**************************************************************************
-/* register flags 0 */
+// register flags 0
#define REGFLAG_R(n) (1 << (n))
#define REGFLAG_RZ(n) (((n) == 0) ? 0 : REGFLAG_R(n))
-/* register flags 1 */
+// register flags 1
#define REGFLAG_FR(n) (1 << (n))
-/* register flags 2 */
+// register flags 2
#define REGFLAG_CR(n) (0xf0000000 >> (4 * (n)))
#define REGFLAG_CR_BIT(n) (0x80000000 >> (n))
-/* register flags 3 */
+// register flags 3
#define REGFLAG_XER_CA (1 << 0)
#define REGFLAG_XER_OV (1 << 1)
#define REGFLAG_XER_SO (1 << 2)
@@ -42,10 +70,37 @@
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class ppc_frontend : public drc_frontend
+{
+public:
+ // construction/destruction
+ ppc_frontend(powerpc_state &state, UINT32 window_start, UINT32 window_end, UINT32 max_sequence);
+
+protected:
+ // required overrides
+ virtual bool describe(opcode_desc &desc, const opcode_desc *prev);
+
+private:
+ // inlines
+ UINT32 compute_spr(UINT32 spr) const { return ((spr >> 5) | (spr << 5)) & 0x3ff; }
+ bool is_403_class() const { return (m_context.flavor == PPC_MODEL_403GA || m_context.flavor == PPC_MODEL_403GB || m_context.flavor == PPC_MODEL_403GC || m_context.flavor == PPC_MODEL_403GCX || m_context.flavor == PPC_MODEL_405GP); }
+ bool is_601_class() const { return (m_context.flavor == PPC_MODEL_601); }
+ bool is_602_class() const { return (m_context.flavor == PPC_MODEL_602); }
+ bool is_603_class() const { return (m_context.flavor == PPC_MODEL_603 || m_context.flavor == PPC_MODEL_603E || m_context.flavor == PPC_MODEL_603EV || m_context.flavor == PPC_MODEL_603R); }
+
+ // internal helpers
+ bool describe_13(UINT32 op, opcode_desc &desc, const opcode_desc *prev);
+ bool describe_1f(UINT32 op, opcode_desc &desc, const opcode_desc *prev);
+ bool describe_3b(UINT32 op, opcode_desc &desc, const opcode_desc *prev);
+ bool describe_3f(UINT32 op, opcode_desc &desc, const opcode_desc *prev);
+
+ // internal state
+ powerpc_state &m_context;
+};
-int ppcfe_describe(void *param, opcode_desc *desc, const opcode_desc *prev);
#endif /* __PPCFE_H__ */
diff --git a/src/emu/cpu/rsp/rspdrc.c b/src/emu/cpu/rsp/rspdrc.c
index 84a39f46b78..10a65bb74f5 100644
--- a/src/emu/cpu/rsp/rspdrc.c
+++ b/src/emu/cpu/rsp/rspdrc.c
@@ -106,7 +106,7 @@ struct _rspimp_state
/* core state */
drccache * cache; /* pointer to the DRC code cache */
drcuml_state * drcuml; /* DRC UML generator state */
- drcfe_state * drcfe; /* pointer to the DRC front-end state */
+ rsp_frontend * drcfe; /* pointer to the DRC front-end state */
UINT32 drcoptions; /* configurable DRC options */
/* internal stuff */
@@ -603,13 +603,6 @@ static void rspcom_init(rsp_state *rsp, legacy_cpu_device *device, device_irq_ca
static CPU_INIT( rsp )
{
- drcfe_config feconfig =
- {
- COMPILE_BACKWARDS_BYTES, /* code window start offset = startpc - window_start */
- COMPILE_FORWARDS_BYTES, /* code window end offset = startpc + window_end */
- COMPILE_MAX_SEQUENCE, /* maximum instructions to include in a sequence */
- rspfe_describe /* callback to describe a single instruction */
- };
rsp_state *rsp;
drccache *cache;
UINT32 flags = 0;
@@ -669,11 +662,7 @@ static CPU_INIT( rsp )
drcuml_symbol_add(rsp->impstate->drcuml, &rsp->impstate->numcycles, sizeof(rsp->impstate->numcycles), "numcycles");
/* initialize the front-end helper */
- if (SINGLE_INSTRUCTION_MODE)
- {
- feconfig.max_sequence = 1;
- }
- rsp->impstate->drcfe = drcfe_init(device, &feconfig, rsp);
+ rsp->impstate->drcfe = auto_alloc(device->machine, rsp_frontend(*rsp, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE));
/* compute the register parameters */
for (regnum = 0; regnum < 32; regnum++)
@@ -721,7 +710,7 @@ static CPU_EXIT( rsp )
rsp_state *rsp = get_safe_token(device);
/* clean up the DRC */
- drcfe_exit(rsp->impstate->drcfe);
+ auto_free(device->machine, rsp->impstate->drcfe);
drcuml_free(rsp->impstate->drcuml);
drccache_free(rsp->impstate->cache);
}
@@ -3479,7 +3468,7 @@ static void code_compile_block(rsp_state *rsp, offs_t pc)
g_profiler.start(PROFILER_DRC_COMPILE);
/* get a description of this sequence */
- desclist = drcfe_describe_code(rsp->impstate->drcfe, pc);
+ desclist = rsp->impstate->drcfe->describe_code(pc);
/* if we get an error back, flush the cache and try again */
if (setjmp(errorbuf) != 0)
@@ -3491,7 +3480,7 @@ static void code_compile_block(rsp_state *rsp, offs_t pc)
block = drcuml_block_begin(drcuml, 8192, &errorbuf);
/* loop until we get through all instruction sequences */
- for (seqhead = desclist; seqhead != NULL; seqhead = seqlast->next)
+ for (seqhead = desclist; seqhead != NULL; seqhead = seqlast->next())
{
const opcode_desc *curdesc;
UINT32 nextpc;
@@ -3501,7 +3490,7 @@ static void code_compile_block(rsp_state *rsp, offs_t pc)
UML_COMMENT(block, "-------------------------"); // comment
/* determine the last instruction in this sequence */
- for (seqlast = seqhead; seqlast != NULL; seqlast = seqlast->next)
+ for (seqlast = seqhead; seqlast != NULL; seqlast = seqlast->next())
if (seqlast->flags & OPFLAG_END_SEQUENCE)
break;
assert(seqlast != NULL);
@@ -3536,7 +3525,7 @@ static void code_compile_block(rsp_state *rsp, offs_t pc)
UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc
/* iterate over instructions in the sequence and compile them */
- for (curdesc = seqhead; curdesc != seqlast->next; curdesc = curdesc->next)
+ for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next())
generate_sequence_instruction(rsp, block, &compiler, curdesc);
/* if we need to return to the start, do it */
@@ -3551,7 +3540,7 @@ static void code_compile_block(rsp_state *rsp, offs_t pc)
generate_update_cycles(rsp, block, &compiler, IMM(nextpc), TRUE); // <subtract cycles>
/* if the last instruction can change modes, use a variable mode; otherwise, assume the same mode */
- if (seqlast->next == NULL || seqlast->next->pc != nextpc)
+ if (seqlast->next() == NULL || seqlast->next()->pc != nextpc)
UML_HASHJMP(block, IMM(0), IMM(nextpc), rsp->impstate->nocode); // hashjmp <mode>,nextpc,nocode
}
@@ -3800,7 +3789,7 @@ static void generate_checksum_block(rsp_state *rsp, drcuml_block *block, compile
UML_COMMENT(block, "[Validation for %08X]", seqhead->pc | 0x1000); // comment
}
/* loose verify or single instruction: just compare and fail */
- if (!(rsp->impstate->drcoptions & RSPDRC_STRICT_VERIFY) || seqhead->next == NULL)
+ if (!(rsp->impstate->drcoptions & RSPDRC_STRICT_VERIFY) || seqhead->next() == NULL)
{
if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP))
{
@@ -3818,7 +3807,7 @@ static void generate_checksum_block(rsp_state *rsp, drcuml_block *block, compile
void *base = rsp->direct->read_decrypted_ptr(seqhead->physpc | 0x1000);
UML_LOAD(block, IREG(0), base, IMM(0), DWORD); // load i0,base,0,dword
sum += seqhead->opptr.l[0];
- for (curdesc = seqhead->next; curdesc != seqlast->next; curdesc = curdesc->next)
+ for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
{
base = rsp->direct->read_decrypted_ptr(curdesc->physpc | 0x1000);
@@ -3910,7 +3899,7 @@ static void generate_delay_slot_and_branch(rsp_state *rsp, drcuml_block *block,
/* compile the delay slot using temporary compiler state */
assert(desc->delay != NULL);
- generate_sequence_instruction(rsp, block, &compiler_temp, desc->delay); // <next instruction>
+ generate_sequence_instruction(rsp, block, &compiler_temp, desc->delay.first()); // <next instruction>
/* update the cycles and jump through the hash table to the target */
if (desc->targetpc != BRANCH_TARGET_DYNAMIC)
diff --git a/src/emu/cpu/rsp/rspfe.c b/src/emu/cpu/rsp/rspfe.c
index 9fcad914577..225d1d551ff 100644
--- a/src/emu/cpu/rsp/rspfe.c
+++ b/src/emu/cpu/rsp/rspfe.c
@@ -1,4 +1,4 @@
- /***************************************************************************
+/***************************************************************************
rspfe.c
@@ -14,294 +14,291 @@
#include "rspfe.h"
#include "rsp.h"
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
+//**************************************************************************
+// RSP FRONTEND
+//**************************************************************************
-static int describe_instruction_special(rsp_state *rsp, UINT32 op, opcode_desc *desc);
-static int describe_instruction_regimm(rsp_state *rsp, UINT32 op, opcode_desc *desc);
-static int describe_instruction_cop0(rsp_state *rsp, UINT32 op, opcode_desc *desc);
-static int describe_instruction_cop2(rsp_state *rsp, UINT32 op, opcode_desc *desc);
+//-------------------------------------------------
+// rsp_frontend - constructor
+//-------------------------------------------------
+
+rsp_frontend::rsp_frontend(rsp_state &state, UINT32 window_start, UINT32 window_end, UINT32 max_sequence)
+ : drc_frontend(*state.device, window_start, window_end, max_sequence),
+ m_context(state)
+{
+}
-/***************************************************************************
- INSTRUCTION PARSERS
-***************************************************************************/
-/*-------------------------------------------------
- describe_instruction - build a description
- of a single instruction
--------------------------------------------------*/
+//-------------------------------------------------
+// describe - build a description of a single
+// instruction
+//-------------------------------------------------
-int rspfe_describe(void *param, opcode_desc *desc, const opcode_desc *prev)
+bool rsp_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
{
- rsp_state *rsp = (rsp_state *)param;
UINT32 op, opswitch;
- /* fetch the opcode */
- op = desc->opptr.l[0] = rsp->direct->read_decrypted_dword(desc->physpc | 0x1000);
+ // fetch the opcode
+ op = desc.opptr.l[0] = m_context.direct->read_decrypted_dword(desc.physpc | 0x1000);
- /* all instructions are 4 bytes and default to a single cycle each */
- desc->length = 4;
- desc->cycles = 1;
+ // all instructions are 4 bytes and default to a single cycle each
+ desc.length = 4;
+ desc.cycles = 1;
- /* parse the instruction */
+ // parse the instruction
opswitch = op >> 26;
switch (opswitch)
{
- case 0x00: /* SPECIAL */
- return describe_instruction_special(rsp, op, desc);
+ case 0x00: // SPECIAL
+ return describe_special(op, desc);
- case 0x01: /* REGIMM */
- return describe_instruction_regimm(rsp, op, desc);
+ case 0x01: // REGIMM
+ return describe_regimm(op, desc);
- case 0x10: /* COP0 */
- return describe_instruction_cop0(rsp, op, desc);
+ case 0x10: // COP0
+ return describe_cop0(op, desc);
- case 0x12: /* COP2 */
- return describe_instruction_cop2(rsp, op, desc);
+ case 0x12: // COP2
+ return describe_cop2(op, desc);
- case 0x02: /* J */
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- desc->targetpc = ((LIMMVAL << 2) & 0x00000fff) | 0x1000;
- desc->delayslots = 1;
- return TRUE;
+ case 0x02: // J
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.targetpc = ((LIMMVAL << 2) & 0x00000fff) | 0x1000;
+ desc.delayslots = 1;
+ return true;
- case 0x03: /* JAL */
- desc->regout[0] |= REGFLAG_R(31);
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- desc->targetpc = ((LIMMVAL << 2) & 0x00000fff) | 0x1000;
- desc->delayslots = 1;
- return TRUE;
+ case 0x03: // JAL
+ desc.regout[0] |= REGFLAG_R(31);
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.targetpc = ((LIMMVAL << 2) & 0x00000fff) | 0x1000;
+ desc.delayslots = 1;
+ return true;
- case 0x04: /* BEQ */
- case 0x05: /* BNE */
+ case 0x04: // BEQ
+ case 0x05: // BNE
if ((opswitch == 0x04 || opswitch == 0x14) && RSREG == RTREG)
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
else
{
- desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
- desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
}
- desc->targetpc = ((desc->pc + 4 + (SIMMVAL << 2)) & 0x00000fff) | 0x1000;
- desc->delayslots = 1;
- desc->skipslots = (opswitch & 0x10) ? 1 : 0;
- return TRUE;
+ desc.targetpc = ((desc.pc + 4 + (SIMMVAL << 2)) & 0x00000fff) | 0x1000;
+ desc.delayslots = 1;
+ desc.skipslots = (opswitch & 0x10) ? 1 : 0;
+ return true;
- case 0x06: /* BLEZ */
- case 0x07: /* BGTZ */
+ case 0x06: // BLEZ
+ case 0x07: // BGTZ
if ((opswitch == 0x06 || opswitch == 0x16) && RSREG == 0)
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
else
{
- desc->regin[0] |= REGFLAG_R(RSREG);
- desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
}
- desc->targetpc = ((desc->pc + 4 + (SIMMVAL << 2)) & 0x00000fff) | 0x1000;
- desc->delayslots = 1;
- desc->skipslots = (opswitch & 0x10) ? 1 : 0;
- return TRUE;
-
- case 0x08: /* ADDI */
- desc->regin[0] |= REGFLAG_R(RSREG);
- desc->regout[0] |= REGFLAG_R(RTREG);
- return TRUE;
-
- case 0x09: /* ADDIU */
- case 0x0a: /* SLTI */
- case 0x0b: /* SLTIU */
- case 0x0c: /* ANDI */
- case 0x0d: /* ORI */
- case 0x0e: /* XORI */
- desc->regin[0] |= REGFLAG_R(RSREG);
- desc->regout[0] |= REGFLAG_R(RTREG);
- return TRUE;
-
- case 0x0f: /* LUI */
- desc->regout[0] |= REGFLAG_R(RTREG);
- return TRUE;
-
- case 0x20: /* LB */
- case 0x21: /* LH */
- case 0x23: /* LW */
- case 0x24: /* LBU */
- case 0x25: /* LHU */
- case 0x27: /* LWU */
- desc->regin[0] |= REGFLAG_R(RSREG);
- desc->regout[0] |= REGFLAG_R(RTREG);
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
-
- case 0x28: /* SB */
- case 0x29: /* SH */
- case 0x2b: /* SW */
- desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
- desc->flags |= OPFLAG_WRITES_MEMORY;
- return TRUE;
-
- case 0x32: /* LWC2 */
- desc->regin[0] |= REGFLAG_R(RSREG);
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
-
- case 0x3a: /* SWC2 */
- desc->regin[0] |= REGFLAG_R(RSREG);
- desc->flags |= OPFLAG_WRITES_MEMORY;
- return TRUE;
+ desc.targetpc = ((desc.pc + 4 + (SIMMVAL << 2)) & 0x00000fff) | 0x1000;
+ desc.delayslots = 1;
+ desc.skipslots = (opswitch & 0x10) ? 1 : 0;
+ return true;
+
+ case 0x08: // ADDI
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x09: // ADDIU
+ case 0x0a: // SLTI
+ case 0x0b: // SLTIU
+ case 0x0c: // ANDI
+ case 0x0d: // ORI
+ case 0x0e: // XORI
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x0f: // LUI
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x20: // LB
+ case 0x21: // LH
+ case 0x23: // LW
+ case 0x24: // LBU
+ case 0x25: // LHU
+ case 0x27: // LWU
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x28: // SB
+ case 0x29: // SH
+ case 0x2b: // SW
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x32: // LWC2
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x3a: // SWC2
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
}
- return FALSE;
+ return false;
}
-/*-------------------------------------------------
- describe_instruction_special - build a
- description of a single instruction in the
- 'special' group
--------------------------------------------------*/
+//-------------------------------------------------
+// describe_special - build a description of a
+// single instruction in the 'special' group
+//-------------------------------------------------
-static int describe_instruction_special(rsp_state *rsp, UINT32 op, opcode_desc *desc)
+bool rsp_frontend::describe_special(UINT32 op, opcode_desc &desc)
{
switch (op & 63)
{
- case 0x00: /* SLL */
- case 0x02: /* SRL */
- case 0x03: /* SRA */
- desc->regin[0] |= REGFLAG_R(RTREG);
- desc->regout[0] |= REGFLAG_R(RDREG);
- return TRUE;
-
- case 0x04: /* SLLV */
- case 0x06: /* SRLV */
- case 0x07: /* SRAV */
- case 0x21: /* ADDU */
- case 0x23: /* SUBU */
- case 0x24: /* AND */
- case 0x25: /* OR */
- case 0x26: /* XOR */
- case 0x27: /* NOR */
- case 0x2a: /* SLT */
- case 0x2b: /* SLTU */
- desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
- desc->regout[0] |= REGFLAG_R(RDREG);
- return TRUE;
-
- case 0x20: /* ADD */
- case 0x22: /* SUB */
- desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
- desc->regout[0] |= REGFLAG_R(RDREG);
- return TRUE;
-
- case 0x08: /* JR */
- desc->regin[0] |= REGFLAG_R(RSREG);
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_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->targetpc = BRANCH_TARGET_DYNAMIC;
- desc->delayslots = 1;
- return TRUE;
-
- case 0x0d: /* BREAK */
- desc->flags |= OPFLAG_END_SEQUENCE;
- desc->targetpc = BRANCH_TARGET_DYNAMIC;
- return TRUE;
+ case 0x00: // SLL
+ case 0x02: // SRL
+ case 0x03: // SRA
+ desc.regin[0] |= REGFLAG_R(RTREG);
+ desc.regout[0] |= REGFLAG_R(RDREG);
+ return true;
+
+ case 0x04: // SLLV
+ case 0x06: // SRLV
+ case 0x07: // SRAV
+ case 0x21: // ADDU
+ case 0x23: // SUBU
+ case 0x24: // AND
+ case 0x25: // OR
+ case 0x26: // XOR
+ case 0x27: // NOR
+ case 0x2a: // SLT
+ case 0x2b: // SLTU
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.regout[0] |= REGFLAG_R(RDREG);
+ return true;
+
+ case 0x20: // ADD
+ case 0x22: // SUB
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.regout[0] |= REGFLAG_R(RDREG);
+ return true;
+
+ case 0x08: // JR
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_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.targetpc = BRANCH_TARGET_DYNAMIC;
+ desc.delayslots = 1;
+ return true;
+
+ case 0x0d: // BREAK
+ desc.flags |= OPFLAG_END_SEQUENCE;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ return true;
}
- return FALSE;
+ return false;
}
-/*-------------------------------------------------
- describe_instruction_regimm - build a
- description of a single instruction in the
- 'regimm' group
--------------------------------------------------*/
+//-------------------------------------------------
+// describe_regimm - build a description of a
+// single instruction in the 'regimm' group
+//-------------------------------------------------
-static int describe_instruction_regimm(rsp_state *rsp, UINT32 op, opcode_desc *desc)
+bool rsp_frontend::describe_regimm(UINT32 op, opcode_desc &desc)
{
switch (RTREG)
{
- case 0x00: /* BLTZ */
- case 0x01: /* BGEZ */
+ case 0x00: // BLTZ
+ case 0x01: // BGEZ
if (RTREG == 0x01 && RSREG == 0)
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
else
{
- desc->regin[0] |= REGFLAG_R(RSREG);
- desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
}
- desc->targetpc = ((desc->pc + 4 + (SIMMVAL << 2)) & 0x00000fff) | 0x1000;
- desc->delayslots = 1;
- desc->skipslots = (RTREG & 0x02) ? 1 : 0;
- return TRUE;
+ desc.targetpc = ((desc.pc + 4 + (SIMMVAL << 2)) & 0x00000fff) | 0x1000;
+ desc.delayslots = 1;
+ desc.skipslots = (RTREG & 0x02) ? 1 : 0;
+ return true;
- case 0x10: /* BLTZAL */
- case 0x11: /* BGEZAL */
+ case 0x10: // BLTZAL
+ case 0x11: // BGEZAL
if (RTREG == 0x11 && RSREG == 0)
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
else
{
- desc->regin[0] |= REGFLAG_R(RSREG);
- desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
}
- desc->regout[0] |= REGFLAG_R(31);
- desc->targetpc = ((desc->pc + 4 + (SIMMVAL << 2)) & 0x00000fff) | 0x1000;
- desc->delayslots = 1;
- desc->skipslots = (RTREG & 0x02) ? 1 : 0;
- return TRUE;
+ desc.regout[0] |= REGFLAG_R(31);
+ desc.targetpc = ((desc.pc + 4 + (SIMMVAL << 2)) & 0x00000fff) | 0x1000;
+ desc.delayslots = 1;
+ desc.skipslots = (RTREG & 0x02) ? 1 : 0;
+ return true;
}
- return FALSE;
+ return false;
}
-/*-------------------------------------------------
- describe_instruction_cop0 - build a
- description of a single instruction in the
- COP0 group
--------------------------------------------------*/
+//-------------------------------------------------
+// describe_cop0 - build a description of a
+// single instruction in the COP0 group
+//-------------------------------------------------
-static int describe_instruction_cop0(rsp_state *rsp, UINT32 op, opcode_desc *desc)
+bool rsp_frontend::describe_cop0(UINT32 op, opcode_desc &desc)
{
switch (RSREG)
{
- case 0x00: /* MFCz */
- desc->regout[0] |= REGFLAG_R(RTREG);
- return TRUE;
+ case 0x00: // MFCz
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
- case 0x04: /* MTCz */
- desc->regin[0] |= REGFLAG_R(RTREG);
- return TRUE;
+ case 0x04: // MTCz
+ desc.regin[0] |= REGFLAG_R(RTREG);
+ return true;
}
- return FALSE;
+ return false;
}
-/*-------------------------------------------------
- describe_instruction_cop2 - build a
- description of a single instruction in the
- COP2 group
--------------------------------------------------*/
+//-------------------------------------------------
+// describe_cop2 - build a description of a
+// single instruction in the COP2 group
+//-------------------------------------------------
-static int describe_instruction_cop2(rsp_state *rsp, UINT32 op, opcode_desc *desc)
+bool rsp_frontend::describe_cop2(UINT32 op, opcode_desc &desc)
{
switch (RSREG)
{
- case 0x00: /* MFCz */
- case 0x02: /* CFCz */
- desc->regout[0] |= REGFLAG_R(RTREG);
- return TRUE;
-
- case 0x04: /* MTCz */
- case 0x06: /* CTCz */
- desc->regin[0] |= REGFLAG_R(RTREG);
- return TRUE;
+ case 0x00: // MFCz
+ case 0x02: // CFCz
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x04: // MTCz
+ case 0x06: // CTCz
+ desc.regin[0] |= REGFLAG_R(RTREG);
+ return true;
}
- return FALSE;
+ return false;
}
diff --git a/src/emu/cpu/rsp/rspfe.h b/src/emu/cpu/rsp/rspfe.h
index 176351b8b12..b032c306b2b 100644
--- a/src/emu/cpu/rsp/rspfe.h
+++ b/src/emu/cpu/rsp/rspfe.h
@@ -15,20 +15,44 @@
#ifndef __RSPFE_H__
#define __RSPFE_H__
+#include "rsp.h"
#include "cpu/drcfe.h"
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
-/* register flags 0 */
+// register flags 0
#define REGFLAG_R(n) (((n) == 0) ? 0 : (1 << (n)))
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-int rspfe_describe(void *param, opcode_desc *desc, const opcode_desc *prev);
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class rsp_frontend : public drc_frontend
+{
+public:
+ // construction/destruction
+ rsp_frontend(rsp_state &state, UINT32 window_start, UINT32 window_end, UINT32 max_sequence);
+
+protected:
+ // required overrides
+ virtual bool describe(opcode_desc &desc, const opcode_desc *prev);
+
+private:
+ // internal helpers
+ bool describe_special(UINT32 op, opcode_desc &desc);
+ bool describe_regimm(UINT32 op, opcode_desc &desc);
+ bool describe_cop0(UINT32 op, opcode_desc &desc);
+ bool describe_cop2(UINT32 op, opcode_desc &desc);
+
+ // internal state
+ rsp_state &m_context;
+};
+
+
#endif /* __RSPFE_H__ */
diff --git a/src/emu/cpu/sh2/sh2comn.h b/src/emu/cpu/sh2/sh2comn.h
index e70ea929ed0..cf72e90df48 100644
--- a/src/emu/cpu/sh2/sh2comn.h
+++ b/src/emu/cpu/sh2/sh2comn.h
@@ -21,6 +21,7 @@
#include "cpu/drcfe.h"
#include "cpu/drcuml.h"
#include "cpu/drcumlsh.h"
+class sh2_frontend;
#endif
#define SH2_CODE_XOR(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(2,0))
@@ -155,7 +156,7 @@ typedef struct
#ifdef USE_SH2DRC
drccache * cache; /* pointer to the DRC code cache */
drcuml_state * drcuml; /* DRC UML generator state */
- drcfe_state * drcfe; /* pointer to the DRC front-end state */
+ sh2_frontend * drcfe; /* pointer to the DRC front-end state */
UINT32 drcoptions; /* configurable DRC options */
/* internal stuff */
@@ -184,6 +185,28 @@ typedef struct
#endif
} sh2_state;
+#ifdef USE_SH2DRC
+class sh2_frontend : public drc_frontend
+{
+public:
+ sh2_frontend(sh2_state &state, UINT32 window_start, UINT32 window_end, UINT32 max_sequence);
+
+protected:
+ virtual bool describe(opcode_desc &desc, const opcode_desc *prev);
+
+private:
+ bool describe_group_0(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+ bool describe_group_2(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+ bool describe_group_3(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+ bool describe_group_4(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+ bool describe_group_6(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+ bool describe_group_8(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+ bool describe_group_12(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+
+ sh2_state &m_context;
+};
+#endif
+
void sh2_common_init(sh2_state *sh2, legacy_cpu_device *device, device_irq_callback irqcallback);
void sh2_recalc_irq(sh2_state *sh2);
void sh2_set_irq_line(sh2_state *sh2, int irqline, int state);
diff --git a/src/emu/cpu/sh2/sh2drc.c b/src/emu/cpu/sh2/sh2drc.c
index fa1745332e2..d340426b076 100644
--- a/src/emu/cpu/sh2/sh2drc.c
+++ b/src/emu/cpu/sh2/sh2drc.c
@@ -674,13 +674,6 @@ static void cfunc_SUBV(void *param)
static CPU_INIT( sh2 )
{
- drcfe_config feconfig =
- {
- COMPILE_BACKWARDS_BYTES, /* code window start offset = startpc - window_start */
- COMPILE_FORWARDS_BYTES, /* code window end offset = startpc + window_end */
- COMPILE_MAX_SEQUENCE, /* maximum instructions to include in a sequence */
- sh2_describe /* callback to describe a single instruction */
- };
sh2_state *sh2 = get_safe_token(device);
drccache *cache;
drcbe_info beinfo;
@@ -733,9 +726,7 @@ static CPU_INIT( sh2 )
drcuml_symbol_add(sh2->drcuml, &sh2->mach, sizeof(sh2->macl), "mach");
/* initialize the front-end helper */
- if (SINGLE_INSTRUCTION_MODE)
- feconfig.max_sequence = 1;
- sh2->drcfe = drcfe_init(device, &feconfig, sh2);
+ sh2->drcfe = auto_alloc(device->machine, sh2_frontend(*sh2, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE));
/* compute the register parameters */
for (regnum = 0; regnum < 16; regnum++)
@@ -779,7 +770,7 @@ static CPU_EXIT( sh2 )
sh2_state *sh2 = get_safe_token(device);
/* clean up the DRC */
- drcfe_exit(sh2->drcfe);
+ auto_free(device->machine, sh2->drcfe);
drcuml_free(sh2->drcuml);
drccache_free(sh2->cache);
}
@@ -941,7 +932,7 @@ static void code_compile_block(sh2_state *sh2, UINT8 mode, offs_t pc)
g_profiler.start(PROFILER_DRC_COMPILE);
/* get a description of this sequence */
- desclist = drcfe_describe_code(sh2->drcfe, pc);
+ desclist = sh2->drcfe->describe_code(pc);
if (LOG_UML || LOG_NATIVE)
log_opcode_desc(drcuml, desclist, 0);
@@ -953,7 +944,7 @@ static void code_compile_block(sh2_state *sh2, UINT8 mode, offs_t pc)
block = drcuml_block_begin(drcuml, 4096, &errorbuf);
/* loop until we get through all instruction sequences */
- for (seqhead = desclist; seqhead != NULL; seqhead = seqlast->next)
+ for (seqhead = desclist; seqhead != NULL; seqhead = seqlast->next())
{
const opcode_desc *curdesc;
UINT32 nextpc;
@@ -963,7 +954,7 @@ static void code_compile_block(sh2_state *sh2, UINT8 mode, offs_t pc)
UML_COMMENT(block, "-------------------------"); // comment
/* determine the last instruction in this sequence */
- for (seqlast = seqhead; seqlast != NULL; seqlast = seqlast->next)
+ for (seqlast = seqhead; seqlast != NULL; seqlast = seqlast->next())
if (seqlast->flags & OPFLAG_END_SEQUENCE)
break;
assert(seqlast != NULL);
@@ -1000,7 +991,7 @@ static void code_compile_block(sh2_state *sh2, UINT8 mode, offs_t pc)
}
/* iterate over instructions in the sequence and compile them */
- for (curdesc = seqhead; curdesc != seqlast->next; curdesc = curdesc->next)
+ for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next())
{
generate_sequence_instruction(sh2, block, &compiler, curdesc, 0xffffffff);
}
@@ -1020,7 +1011,7 @@ static void code_compile_block(sh2_state *sh2, UINT8 mode, offs_t pc)
generate_update_cycles(sh2, block, &compiler, IMM(nextpc), TRUE); // <subtract cycles>
/* SH2 has no modes */
- if (seqlast->next == NULL || seqlast->next->pc != nextpc)
+ if (seqlast->next() == NULL || seqlast->next()->pc != nextpc)
{
UML_HASHJMP(block, IMM(0), IMM(nextpc), sh2->nocode);
}
@@ -1390,7 +1381,7 @@ static void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, i
drcuml_log_printf(drcuml, "\nDescriptor list @ %08X\n", desclist->pc);
/* output each descriptor */
- for ( ; desclist != NULL; desclist = desclist->next)
+ for ( ; desclist != NULL; desclist = desclist->next())
{
char buffer[100];
@@ -1411,8 +1402,8 @@ static void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, i
drcuml_log_printf(drcuml, "\n");
/* if we have a delay slot, output it recursively */
- if (desclist->delay != NULL)
- log_opcode_desc(drcuml, desclist->delay, indent + 1);
+ if (desclist->delay.first() != NULL)
+ log_opcode_desc(drcuml, desclist->delay.first(), indent + 1);
/* at the end of a sequence add a dividing line */
if (desclist->flags & OPFLAG_END_SEQUENCE)
@@ -1524,7 +1515,7 @@ static void generate_checksum_block(sh2_state *sh2, drcuml_block *block, compile
UML_COMMENT(block, "[Validation for %08X]", seqhead->pc); // comment
/* loose verify or single instruction: just compare and fail */
- if (!(sh2->drcoptions & SH2DRC_STRICT_VERIFY) || seqhead->next == NULL)
+ if (!(sh2->drcoptions & SH2DRC_STRICT_VERIFY) || seqhead->next() == NULL)
{
if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP))
{
@@ -1539,7 +1530,7 @@ static void generate_checksum_block(sh2_state *sh2, drcuml_block *block, compile
else
{
#if 0
- for (curdesc = seqhead->next; curdesc != seqlast->next; curdesc = curdesc->next)
+ for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
{
base = sh2->direct->read_decrypted_ptr(curdesc->physpc, SH2_CODE_XOR(0));
@@ -1552,7 +1543,7 @@ static void generate_checksum_block(sh2_state *sh2, drcuml_block *block, compile
void *base = sh2->direct->read_decrypted_ptr(seqhead->physpc, SH2_CODE_XOR(0));
UML_LOAD(block, IREG(0), base, IMM(0), WORD); // load i0,base,word
sum += seqhead->opptr.w[0];
- for (curdesc = seqhead->next; curdesc != seqlast->next; curdesc = curdesc->next)
+ for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
{
base = sh2->direct->read_decrypted_ptr(curdesc->physpc, SH2_CODE_XOR(0));
@@ -1662,7 +1653,7 @@ static void generate_delay_slot(sh2_state *sh2, drcuml_block *block, compiler_st
/* compile the delay slot using temporary compiler state */
assert(desc->delay != NULL);
- generate_sequence_instruction(sh2, block, &compiler_temp, desc->delay, ovrpc); // <next instruction>
+ generate_sequence_instruction(sh2, block, &compiler_temp, desc->delay.first(), ovrpc); // <next instruction>
/* update the label */
compiler->labelnum = compiler_temp.labelnum;
diff --git a/src/emu/cpu/sh2/sh2fe.c b/src/emu/cpu/sh2/sh2fe.c
index f4c18d61eea..fa02e66b7af 100644
--- a/src/emu/cpu/sh2/sh2fe.c
+++ b/src/emu/cpu/sh2/sh2fe.c
@@ -14,116 +14,108 @@
#include "sh2comn.h"
#include "cpu/drcfe.h"
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-static int describe_group_0(sh2_state *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode);
-static int describe_group_2(sh2_state *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode);
-static int describe_group_3(sh2_state *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode);
-static int describe_group_4(sh2_state *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode);
-static int describe_group_6(sh2_state *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode);
-static int describe_group_8(sh2_state *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode);
-static int describe_group_12(sh2_state *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode);
-
-
/***************************************************************************
INSTRUCTION PARSERS
***************************************************************************/
+sh2_frontend::sh2_frontend(sh2_state &state, UINT32 window_start, UINT32 window_end, UINT32 max_sequence)
+ : drc_frontend(*state.device, window_start, window_end, max_sequence),
+ m_context(state)
+{
+}
+
/*-------------------------------------------------
describe_instruction - build a description
of a single instruction
-------------------------------------------------*/
-int sh2_describe(void *param, opcode_desc *desc, const opcode_desc *prev)
+bool sh2_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
{
- sh2_state *context = (sh2_state *)param;
UINT16 opcode;
/* fetch the opcode */
- opcode = desc->opptr.w[0] = context->direct->read_decrypted_word(desc->physpc, SH2_CODE_XOR(0));
+ opcode = desc.opptr.w[0] = m_context.direct->read_decrypted_word(desc.physpc, SH2_CODE_XOR(0));
/* all instructions are 2 bytes and most are a single cycle */
- desc->length = 2;
- desc->cycles = 1;
+ desc.length = 2;
+ desc.cycles = 1;
switch (opcode>>12)
{
case 0:
- return describe_group_0(context, desc, prev, opcode);
+ return describe_group_0(desc, prev, opcode);
case 1: // MOVLS4
- desc->regin[0] |= REGFLAG_R(Rn) | REGFLAG_R(Rm);
- desc->flags |= OPFLAG_WRITES_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn) | REGFLAG_R(Rm);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
case 2:
- return describe_group_2(context, desc, prev, opcode);
+ return describe_group_2(desc, prev, opcode);
case 3:
- return describe_group_3(context, desc, prev, opcode);
+ return describe_group_3(desc, prev, opcode);
case 4:
- return describe_group_4(context, desc, prev, opcode);
+ return describe_group_4(desc, prev, opcode);
case 5: // MOVLL4
- desc->regin[0] |= REGFLAG_R(Rm);
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
case 6:
- return describe_group_6(context, desc, prev, opcode);
+ return describe_group_6(desc, prev, opcode);
case 7: // ADDI
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regout[0] |= REGFLAG_R(Rn);
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
case 8:
- return describe_group_8(context, desc, prev, opcode);
+ return describe_group_8(desc, prev, opcode);
case 9: // MOVWI
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
case 11: // BSR
- desc->regout[1] |= REGFLAG_PR;
+ desc.regout[1] |= REGFLAG_PR;
// (intentional fallthrough - BSR is BRA with the addition of PR = the return address)
case 10: // BRA
{
INT32 disp = ((INT32)opcode << 20) >> 20;
- 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;
+ 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(context, desc, prev, opcode);
+ return describe_group_12(desc, prev, opcode);
case 13: // MOVLI
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
case 14: // MOVI
- desc->regout[0] |= REGFLAG_R(Rn);
- return TRUE;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
case 15: // NOP
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
-static int describe_group_0(sh2_state *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode)
+bool sh2_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode)
{
switch (opcode & 0x3F)
{
@@ -143,20 +135,20 @@ static int describe_group_0(sh2_state *context, opcode_desc *desc, const opcode_
case 0x39: // NOP();
case 0x3a: // NOP();
case 0x3b: // NOP();
- return TRUE;
+ return true;
case 0x02: // STCSR(Rn);
- desc->regout[0] |= REGFLAG_R(Rn);
- return TRUE;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
case 0x03: // BSRF(Rn);
- desc->regout[1] |= REGFLAG_PR;
+ desc.regout[1] |= REGFLAG_PR;
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- desc->targetpc = BRANCH_TARGET_DYNAMIC;
- desc->delayslots = 1;
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ desc.delayslots = 1;
- return TRUE;
+ return true;
case 0x04: // MOVBS0(Rm, Rn);
case 0x05: // MOVWS0(Rm, Rn);
@@ -170,37 +162,37 @@ static int describe_group_0(sh2_state *context, opcode_desc *desc, const opcode_
case 0x34: // MOVBS0(Rm, Rn);
case 0x35: // MOVWS0(Rm, Rn);
case 0x36: // MOVLS0(Rm, Rn);
- desc->regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn) | REGFLAG_R(0);
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn) | REGFLAG_R(0);
+ desc.flags |= OPFLAG_READS_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(Rn) | REGFLAG_R(Rm);
- desc->regout[1] |= REGFLAG_MACL;
- desc->cycles = 2;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn) | REGFLAG_R(Rm);
+ desc.regout[1] |= REGFLAG_MACL;
+ desc.cycles = 2;
+ return true;
case 0x08: // CLRT();
- desc->regout[1] |= REGFLAG_SR;
- return TRUE;
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
case 0x0a: // STSMACH(Rn);
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_MACH;
- return TRUE;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_MACH;
+ return true;
case 0x0b: // RTS();
- desc->regin[1] |= REGFLAG_PR;
+ desc.regin[1] |= REGFLAG_PR;
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- desc->targetpc = BRANCH_TARGET_DYNAMIC;
- desc->delayslots = 1;
- desc->cycles = 2;
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ desc.delayslots = 1;
+ desc.cycles = 2;
- return TRUE;
+ return true;
case 0x0c: // MOVBL0(Rm, Rn);
case 0x0d: // MOVWL0(Rm, Rn);
@@ -214,133 +206,133 @@ static int describe_group_0(sh2_state *context, opcode_desc *desc, const opcode_
case 0x3c: // MOVBL0(Rm, Rn);
case 0x3d: // MOVWL0(Rm, Rn);
case 0x3e: // MOVLL0(Rm, Rn);
- desc->regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(0);
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(0);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_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(Rm) | REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_MACL | REGFLAG_MACH;
- desc->cycles = 3;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH;
+ desc.cycles = 3;
+ return true;
case 0x12: // STCGBR(Rn);
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->regin[1] |= REGFLAG_GBR;
- return TRUE;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_GBR;
+ return true;
case 0x18: // SETT();
- desc->regout[1] |= REGFLAG_SR;
- return TRUE;
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
case 0x19: // DIV0U();
- desc->regout[1] |= REGFLAG_SR;
- return TRUE;
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
case 0x1a: // STSMACL(Rn);
- desc->regin[1] |= REGFLAG_MACL;
- desc->regout[0] |= REGFLAG_R(Rn);
- return TRUE;
+ desc.regin[1] |= REGFLAG_MACL;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
case 0x1b: // SLEEP();
- desc->cycles = 3;
- return TRUE;
+ desc.cycles = 3;
+ return true;
case 0x22: // STCVBR(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_VBR;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_VBR;
+ return true;
case 0x23: // BRAF(Rn);
- desc->regin[0] |= REGFLAG_R(Rm);
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- desc->targetpc = BRANCH_TARGET_DYNAMIC;
- desc->delayslots = 1;
- desc->cycles = 2;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm);
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_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;
- return TRUE;
+ desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH;
+ return true;
case 0x29: // MOVT(Rn);
- desc->regin[1] |= REGFLAG_SR;
- desc->regout[0] |= REGFLAG_R(Rn);
- return TRUE;
+ desc.regin[1] |= REGFLAG_SR;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
case 0x2a: // STSPR(Rn);
- desc->regin[1] |= REGFLAG_PR;
- desc->regout[0] |= REGFLAG_R(Rn);
- return TRUE;
+ desc.regin[1] |= REGFLAG_PR;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
case 0x2b: // RTE();
- desc->regin[0] |= REGFLAG_R(15);
- desc->regout[0] |= REGFLAG_R(15);
+ desc.regin[0] |= REGFLAG_R(15);
+ desc.regout[0] |= REGFLAG_R(15);
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_EXPOSE_EXTERNAL_INT;
- desc->targetpc = BRANCH_TARGET_DYNAMIC;
- desc->delayslots = 1;
- desc->cycles = 4;
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_EXPOSE_EXTERNAL_INT;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ desc.delayslots = 1;
+ desc.cycles = 4;
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
-static int describe_group_2(sh2_state *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode)
+bool sh2_frontend::describe_group_2(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode)
{
switch (opcode & 15)
{
case 0: // MOVBS(Rm, Rn);
case 1: // MOVWS(Rm, Rn);
case 2: // MOVLS(Rm, Rn);
- desc->regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc->flags |= OPFLAG_WRITES_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
case 3: // NOP();
- return TRUE;
+ return true;
case 4: // MOVBM(Rm, Rn);
case 5: // MOVWM(Rm, Rn);
case 6: // MOVLM(Rm, Rn);
case 13: // XTRCT(Rm, Rn);
- desc->regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->flags |= OPFLAG_WRITES_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
case 7: // DIV0S(Rm, Rn);
case 8: // TST(Rm, Rn);
case 12: // CMPSTR(Rm, Rn);
- desc->regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_SR;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
case 9: // AND(Rm, Rn);
case 10: // XOR(Rm, Rn);
case 11: // OR(Rm, Rn);
- desc->regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc->regout[0] |= REGFLAG_R(Rn);
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
case 14: // MULU(Rm, Rn);
case 15: // MULS(Rm, Rn);
- desc->regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_MACL | REGFLAG_MACH;
- desc->cycles = 2;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH;
+ desc.cycles = 2;
+ return true;
}
- return FALSE;
+ return false;
}
-static int describe_group_3(sh2_state *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode)
+bool sh2_frontend::describe_group_3(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode)
{
switch (opcode & 15)
{
@@ -349,47 +341,47 @@ static int describe_group_3(sh2_state *context, opcode_desc *desc, const opcode_
case 3: // CMPGE(Rm, Rn);
case 6: // CMPHI(Rm, Rn);
case 7: // CMPGT(Rm, Rn);
- desc->regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_SR;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
case 1: // NOP();
case 9: // NOP();
- return TRUE;
+ return true;
case 4: // DIV1(Rm, Rn);
- desc->regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_SR;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
case 5: // DMULU(Rm, Rn);
case 13: // DMULS(Rm, Rn);
- desc->regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_MACL | REGFLAG_MACH;
- desc->cycles = 2;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH;
+ desc.cycles = 2;
+ return true;
case 8: // SUB(Rm, Rn);
case 12: // ADD(Rm, Rn);
- desc->regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc->regout[0] |= REGFLAG_R(Rn);
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ 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(Rm) | REGFLAG_R(Rn);
- desc->regin[1] |= REGFLAG_SR;
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_SR;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_SR;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
}
- return FALSE;
+ return false;
}
-static int describe_group_4(sh2_state *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode)
+bool sh2_frontend::describe_group_4(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode)
{
switch (opcode & 0x3F)
{
@@ -397,39 +389,39 @@ static int describe_group_4(sh2_state *context, opcode_desc *desc, const opcode_
case 0x01: // SHLR(Rn);
case 0x04: // ROTL(Rn);
case 0x05: // ROTR(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_SR;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
case 0x02: // STSMMACH(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regin[1] |= REGFLAG_MACH;
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->flags |= OPFLAG_WRITES_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_MACH;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
case 0x03: // STCMSR(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->cycles = 2;
- desc->flags |= OPFLAG_WRITES_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.cycles = 2;
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
case 0x06: // LDSMMACH(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_MACH;
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_MACH;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
case 0x07: // LDCMSR(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_SR;
- desc->cycles = 3;
- desc->flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_END_SEQUENCE;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ desc.cycles = 3;
+ desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_END_SEQUENCE;
+ return true;
case 0x08: // SHLL2(Rn);
case 0x09: // SHLR2(Rn);
@@ -437,159 +429,159 @@ static int describe_group_4(sh2_state *context, opcode_desc *desc, const opcode_
case 0x19: // SHLR8(Rn);
case 0x28: // SHLL16(Rn);
case 0x29: // SHLR16(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regout[0] |= REGFLAG_R(Rn);
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
case 0x0a: // LDSMACH(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_MACH;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_MACH;
+ return true;
case 0x0b: // JSR(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_PR;
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- desc->targetpc = BRANCH_TARGET_DYNAMIC;
- desc->delayslots = 1;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_PR;
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ desc.delayslots = 1;
+ return true;
case 0x0e: // LDCSR(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_SR;
- desc->flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_END_SEQUENCE;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ desc.flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_END_SEQUENCE;
+ 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(Rm) | REGFLAG_R(Rn);
- desc->regin[1] |= REGFLAG_MACL | REGFLAG_MACH;
- desc->regout[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_MACL | REGFLAG_MACH;
- desc->cycles = 3;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_MACL | REGFLAG_MACH;
+ desc.regout[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH;
+ desc.cycles = 3;
+ return true;
case 0x10: // DT(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regin[1] |= REGFLAG_SR;
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_SR;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_SR;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
case 0x11: // CMPPZ(Rn);
case 0x15: // CMPPL(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regin[1] |= REGFLAG_SR;
- desc->regout[1] |= REGFLAG_SR;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_SR;
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
case 0x12: // STSMMACL(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regin[1] |= REGFLAG_MACL;
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->flags |= OPFLAG_WRITES_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_MACL;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
case 0x13: // STCMGBR(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regin[1] |= REGFLAG_GBR;
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->flags |= OPFLAG_WRITES_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_GBR;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
case 0x16: // LDSMMACL(Rn);
- desc->regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc->regout[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_MACL;
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_MACL;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
case 0x17: // LDCMGBR(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_GBR;
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_GBR;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
case 0x1a: // LDSMACL(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_MACL;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_MACL;
+ return true;
case 0x1b: // TAS(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regin[1] |= REGFLAG_SR;
- desc->regout[1] |= REGFLAG_SR;
- desc->cycles = 4;
- desc->flags |= OPFLAG_READS_MEMORY | OPFLAG_WRITES_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_SR;
+ desc.regout[1] |= REGFLAG_SR;
+ desc.cycles = 4;
+ desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_WRITES_MEMORY;
+ return true;
case 0x1e: // LDCGBR(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_GBR;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_GBR;
+ return true;
case 0x20: // SHAL(Rn);
case 0x21: // SHAR(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_SR;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
case 0x22: // STSMPR(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regin[1] |= REGFLAG_PR;
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->flags |= OPFLAG_WRITES_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_PR;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
case 0x23: // STCMVBR(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regin[1] |= REGFLAG_VBR;
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->flags |= OPFLAG_WRITES_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_VBR;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
case 0x24: // ROTCL(Rn);
case 0x25: // ROTCR(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regin[1] |= REGFLAG_SR;
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_SR;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_SR;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
case 0x26: // LDSMPR(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_PR;
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_PR;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
case 0x27: // LDCMVBR(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_VBR;
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_VBR;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
case 0x2a: // LDSPR(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_PR;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_PR;
+ return true;
case 0x2b: // JMP(Rm);
- desc->regin[0] |= REGFLAG_R(Rm);
- desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- desc->targetpc = BRANCH_TARGET_DYNAMIC;
- desc->delayslots = 1;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm);
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ desc.delayslots = 1;
+ return true;
case 0x2e: // LDCVBR(Rn);
- desc->regin[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_VBR;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_VBR;
+ return true;
case 0x0c: // NOP();
case 0x0d: // NOP();
@@ -613,13 +605,13 @@ static int describe_group_4(sh2_state *context, opcode_desc *desc, const opcode_
case 0x3c: // NOP();
case 0x3d: // NOP();
case 0x3e: // NOP();
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
-static int describe_group_6(sh2_state *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode)
+bool sh2_frontend::describe_group_6(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode)
{
switch (opcode & 15)
{
@@ -634,33 +626,33 @@ static int describe_group_6(sh2_state *context, opcode_desc *desc, const opcode_
case 13: // EXTUW(Rm, Rn);
case 14: // EXTSB(Rm, Rn);
case 15: // EXTSW(Rm, Rn);
- desc->regin[0] |= REGFLAG_R(Rm);
- desc->regout[0] |= REGFLAG_R(Rn);
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
case 4: // MOVBP(Rm, Rn);
case 5: // MOVWP(Rm, Rn);
case 6: // MOVLP(Rm, Rn);
- desc->regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
case 8: // SWAPB(Rm, Rn);
- desc->regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc->regout[0] |= REGFLAG_R(Rn);
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
case 10: // NEGC(Rm, Rn);
- desc->regin[0] |= REGFLAG_R(Rm);
- desc->regout[0] |= REGFLAG_R(Rn);
- desc->regout[1] |= REGFLAG_SR;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
}
- return FALSE;
+ return false;
}
-static int describe_group_8(sh2_state *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode)
+bool sh2_frontend::describe_group_8(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode)
{
INT32 disp;
@@ -668,9 +660,9 @@ static int describe_group_8(sh2_state *context, opcode_desc *desc, const opcode_
{
case 0 << 8: // MOVBS4(opcode & 0x0f, Rm);
case 1 << 8: // MOVWS4(opcode & 0x0f, Rm);
- desc->regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(0);
- desc->flags |= OPFLAG_WRITES_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(0);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
case 2<< 8: // NOP();
case 3<< 8: // NOP();
@@ -679,94 +671,94 @@ static int describe_group_8(sh2_state *context, opcode_desc *desc, const opcode_
case 10<< 8: // NOP();
case 12<< 8: // NOP();
case 14<< 8: // NOP();
- return TRUE;
+ return true;
case 4<< 8: // MOVBL4(Rm, opcode & 0x0f);
case 5<< 8: // MOVWL4(Rm, opcode & 0x0f);
- desc->regin[0] |= REGFLAG_R(Rm);
- desc->regout[0] |= REGFLAG_R(0);
- desc->flags |= OPFLAG_READS_MEMORY;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm);
+ desc.regout[0] |= REGFLAG_R(0);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
case 8<< 8: // CMPIM(opcode & 0xff);
- desc->regin[0] |= REGFLAG_R(Rm);
- desc->regin[1] |= REGFLAG_SR;
- desc->regout[1] |= REGFLAG_SR;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(Rm);
+ desc.regin[1] |= REGFLAG_SR;
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
case 9<< 8: // BT(opcode & 0xff);
case 11<< 8: // BF(opcode & 0xff);
- desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
- desc->cycles = 3;
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.cycles = 3;
disp = ((INT32)opcode << 24) >> 24;
- desc->targetpc = (desc->pc + 2) + disp * 2 + 2;
- return TRUE;
+ desc.targetpc = (desc.pc + 2) + disp * 2 + 2;
+ return true;
case 13<< 8: // BTS(opcode & 0xff);
case 15<< 8: // BFS(opcode & 0xff);
- desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
- desc->cycles = 2;
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.cycles = 2;
disp = ((INT32)opcode << 24) >> 24;
- desc->targetpc = (desc->pc + 2) + disp * 2 + 2;
- desc->delayslots = 1;
- return TRUE;
+ desc.targetpc = (desc.pc + 2) + disp * 2 + 2;
+ desc.delayslots = 1;
+ return true;
}
- return FALSE;
+ return false;
}
-static int describe_group_12(sh2_state *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode)
+bool sh2_frontend::describe_group_12(opcode_desc &desc, const opcode_desc *prev, UINT16 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;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(0);
+ desc.flags |= OPFLAG_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->cycles = 8;
- desc->targetpc = BRANCH_TARGET_DYNAMIC;
- desc->flags |= OPFLAG_READS_MEMORY | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(15);
+ desc.regin[1] |= REGFLAG_VBR;
+ desc.regout[0] |= REGFLAG_R(15);
+ desc.cycles = 8;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ 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;
- return TRUE;
+ desc.regout[0] |= REGFLAG_R(0);
+ desc.flags |= OPFLAG_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;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(0);
+ desc.regin[1] |= REGFLAG_SR;
+ desc.regout[1] |= REGFLAG_SR;
+ 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);
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(0);
+ desc.regout[0] |= REGFLAG_R(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;
- return TRUE;
+ desc.regin[0] |= REGFLAG_R(0);
+ desc.regin[1] |= REGFLAG_SR | REGFLAG_GBR;
+ desc.regout[1] |= REGFLAG_SR;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
}
- return FALSE;
+ return false;
}