summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/drcfe.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/cpu/drcfe.c')
-rw-r--r--src/emu/cpu/drcfe.c508
1 files changed, 201 insertions, 307 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);
}