diff options
Diffstat (limited to 'src/emu/cpu/drcfe.h')
-rw-r--r-- | src/emu/cpu/drcfe.h | 224 |
1 files changed, 128 insertions, 96 deletions
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__ */ |