diff options
Diffstat (limited to 'src/emu/cpu/drcfe.h')
-rw-r--r-- | src/emu/cpu/drcfe.h | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/src/emu/cpu/drcfe.h b/src/emu/cpu/drcfe.h new file mode 100644 index 00000000000..44661034251 --- /dev/null +++ b/src/emu/cpu/drcfe.h @@ -0,0 +1,188 @@ +/*************************************************************************** + + drcfe.h + + Generic dynamic recompiler frontend structures and utilities. + + Copyright (c) 2007, Aaron Giles + Released for general use under the MAME license + Visit http://mamedev.org for licensing and usage restrictions. + +**************************************************************************** + + Concepts: + + Dynamic recompiling cores are generally broken into a platform-neutral + "frontend", which performs some level of analysis on the code, and a + platform-specific "backend", which generates the recompiled machine + code. + + The frontend's job is generally to walk through the instruction stream, + identifying basic blocks, or "sequences" of code that can be compiled + and optimized as a unit. This scanning involves recursively walking + the instruction stream, following branches, etc., within a specific + "code window", relative to the current PC. + + As the frontend walks through the code, it generates a list of opcode + "descriptions", one per visited opcode, providing information about + code flow, exception handling, and other characteristics. Once the + walkthrough is finished, these descriptions are assembled together into + a linked list and returned for further processing by the backend. + +***************************************************************************/ + +#ifndef __DRCFE_H__ +#define __DRCFE_H__ + +#ifdef PTR64 +#include "x64drc.h" +#else +#include "x86drc.h" +#endif + + + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +/* this defines a branch targetpc that is dynamic at runtime */ +#define 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 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 */ + +/* opcode virtual->physical translation flags */ +#define OPFLAG_VALIDATE_TLB 0x00000200 /* instruction must validate TLB before execution */ +#define OPFLAG_MODIFIES_TRANSLATION 0x00000400 /* instruction modifies the TLB */ +#define OPFLAG_COMPILER_PAGE_FAULT 0x00000800 /* compiler hit a page fault when parsing */ +#define OPFLAG_COMPILER_UNMAPPED 0x00001000 /* compiler hit unmapped memory when parsing */ + +/* opcode flags */ +#define OPFLAG_INVALID_OPCODE 0x00002000 /* instruction is invalid */ +#define OPFLAG_VIRTUAL_NOOP 0x00004000 /* instruction is a virtual no-op */ + +/* opcode sequence flow flags */ +#define OPFLAG_REDISPATCH 0x00008000 /* instruction must redispatch after completion */ +#define OPFLAG_RETURN_TO_START 0x00010000 /* instruction must jump back to the beginning after completion */ +#define OPFLAG_END_SEQUENCE 0x00020000 /* this is the last instruction in a sequence */ +#define OPFLAG_CAN_CHANGE_MODES 0x00040000 /* instruction can change modes */ + +/* execution semantics */ +#define OPFLAG_READS_MEMORY 0x00080000 /* instruction reads memory */ +#define OPFLAG_WRITES_MEMORY 0x00100000 /* instruction writes memory */ +#define OPFLAG_VARIABLE_SHIFT 0x00200000 /* instruction performs a variable count shift */ +#define OPFLAG_MULTIPLY_DIVIDE 0x00400000 /* instruction performs a multiply/divide */ + + + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +/* opaque internal state */ +typedef struct _drcfe_state drcfe_state; + + +/* register information as bitmasks */ +typedef struct _drc_reginfo drc_reginfo; +struct _drc_reginfo +{ + UINT64 used; /* bitmask of used registers */ + UINT64 modified; /* bitmask of modified registers */ + UINT64 constant; /* bitmask of constant registers */ + UINT64 liveread; /* bitmask of registers that are live for reading */ + UINT64 livewrite; /* bitmask of registers that are live for writing */ +}; + + +/* 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 * 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 */ + + /* pointer to the current opcode */ + union + { + void * v; + UINT8 * b; + UINT16 * w; + UINT32 * l; + UINT64 * q; + } 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 */ + drc_reginfo gpr; /* register info for GPRs */ + drc_reginfo fpr; /* register info for FPRs */ +}; + + +/* callback function that is used to describe a single opcode */ +typedef int (*drcfe_describe)(void *param, opcode_desc *desc); + + +/* description of a given opcode */ +typedef struct _drcfe_config drcfe_config; +struct _drcfe_config +{ + 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 describe; /* callback to describe a single instruction */ +}; + +/* + for each register: + callback to load + callback to store + pointer to memory + if (pointer != NULL) + - can return reference to memory for operations + else + - must always load/store from register +*/ + + +/*************************************************************************** + FUNCTION PROTOTYPES +***************************************************************************/ + +/* initializate the drcfe state */ +drcfe_state *drcfe_init(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 |