diff options
Diffstat (limited to 'src/emu/cpu/x86drc.h')
-rw-r--r-- | src/emu/cpu/x86drc.h | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/src/emu/cpu/x86drc.h b/src/emu/cpu/x86drc.h new file mode 100644 index 00000000000..b3985b720d5 --- /dev/null +++ b/src/emu/cpu/x86drc.h @@ -0,0 +1,194 @@ +/*************************************************************************** + + x86drc.h + + x86 Dynamic recompiler support routines. + + Copyright (c) 1996-2007, Nicola Salmoria and the MAME Team. + Visit http://mamedev.org for licensing and usage restrictions. + +***************************************************************************/ + +#pragma once + +#ifndef __X86DRC_H__ +#define __X86DRC_H__ + +#include "cpuintrf.h" +#include "x86emit.h" + + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +/* PC and pointer pair */ +typedef struct _pc_ptr_pair pc_ptr_pair; +struct _pc_ptr_pair +{ + UINT32 pc; + x86code * target; +}; + + +/* core interface structure for the drc common code */ +typedef struct _drc_core drc_core; +struct _drc_core +{ + UINT8 * cache_base; /* base pointer to the compiler cache */ + UINT8 * cache_top; /* current top of cache */ + UINT8 * cache_danger; /* high water mark for the end */ + UINT8 * cache_end; /* end of cache memory */ + size_t cache_size; /* cache allocated size */ + UINT8 cache_allocated; /* did the DRC core allocate the cache? */ + + x86code *** lookup_l1; /* level 1 lookup */ + x86code ** lookup_l2_recompile; /* level 2 lookup populated with recompile pointers */ + UINT8 l1bits; /* number of bits in level 1 lookup */ + UINT8 l2bits; /* number of bits in level 2 lookup */ + UINT8 l1shift; /* shift to go from PC to level 1 lookup */ + UINT32 l2mask; /* mask to go from PC to level 2 lookup */ + UINT8 l2scale; /* scale to get from masked PC value to final level 2 lookup */ + + void (*entry_point)(void); /* pointer to asm entry point */ + x86code * out_of_cycles; /* pointer to out of cycles jump point */ + x86code * recompile; /* pointer to recompile jump point */ + x86code * dispatch; /* pointer to dispatch jump point */ + x86code * flush; /* pointer to flush jump point */ + + UINT32 * pcptr; /* pointer to where the PC is stored */ + UINT32 * icountptr; /* pointer to where the icount is stored */ + UINT32 * esiptr; /* pointer to where the volatile data in ESI is stored */ + UINT8 pc_in_memory; /* true if the PC is stored in memory */ + UINT8 icount_in_memory; /* true if the icount is stored in memory */ + + UINT8 uses_fp; /* true if we need the FP unit */ + UINT8 uses_sse; /* true if we need the SSE unit */ + UINT16 fpcw_curr; /* current FPU control word */ + UINT32 mxcsr_curr; /* current SSE control word */ + UINT16 fpcw_save; /* saved FPU control word */ + UINT32 mxcsr_save; /* saved SSE control word */ + + pc_ptr_pair *sequence_list; /* PC/pointer sets for the current instruction sequence */ + UINT32 sequence_count; /* number of instructions in the current sequence */ + UINT32 sequence_count_max; /* max number of instructions in the current sequence */ + pc_ptr_pair *tentative_list; /* PC/pointer sets for tentative branches */ + UINT32 tentative_count; /* number of tentative branches */ + UINT32 tentative_count_max; /* max number of tentative branches */ + + void (*cb_reset)(struct _drc_core *drc); /* callback when the cache is reset */ + void (*cb_recompile)(struct _drc_core *drc); /* callback when code needs to be recompiled */ + void (*cb_entrygen)(struct _drc_core *drc); /* callback before generating the dispatcher on entry */ +}; + + +/* configuration structure for the drc common code */ +typedef struct _drc_config drc_config; +struct _drc_config +{ + UINT8 * cache_base; /* base pointer to the compiler cache */ + UINT32 cache_size; /* size of cache to allocate */ + UINT32 max_instructions; /* maximum instructions per sequence */ + UINT8 address_bits; /* number of live address bits in the PC */ + UINT8 lsbs_to_ignore; /* number of LSBs to ignore on the PC */ + UINT8 uses_fp; /* true if we need the FP unit */ + UINT8 uses_sse; /* true if we need the SSE unit */ + UINT8 pc_in_memory; /* true if the PC is stored in memory */ + UINT8 icount_in_memory; /* true if the icount is stored in memory */ + + UINT32 * pcptr; /* pointer to where the PC is stored */ + UINT32 * icountptr; /* pointer to where the icount is stored */ + UINT32 * esiptr; /* pointer to where the volatile data in ESI is stored */ + + void (*cb_reset)(drc_core *drc); /* callback when the cache is reset */ + void (*cb_recompile)(drc_core *drc); /* callback when code needs to be recompiled */ + void (*cb_entrygen)(drc_core *drc); /* callback before generating the dispatcher on entry */ +}; + + +/* structure to hold link data to be filled in later */ +typedef struct _link_info link_info; +struct _link_info +{ + UINT8 size; + UINT8 * target; +}; + + + +/*************************************************************************** + MACROS +***************************************************************************/ + +/* use this macro in emit_* instructions to make them shorter */ +#define DRCTOP &drc->cache_top + + + +/*************************************************************************** + HELPER MACROS +***************************************************************************/ + +/* useful macros for accessing hi/lo portions of 64-bit values */ +#define LO(x) (&(((UINT32 *)(UINT32)(x))[0])) +#define HI(x) (&(((UINT32 *)(UINT32)(x))[1])) + + + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +/* features */ +#define CPUID_FEATURES_MMX (1 << 23) +#define CPUID_FEATURES_SSE (1 << 26) +#define CPUID_FEATURES_SSE2 (1 << 25) +#define CPUID_FEATURES_CMOV (1 << 15) +#define CPUID_FEATURES_TSC (1 << 4) + + + +/*************************************************************************** + FUNCTION PROTOTYPES +***************************************************************************/ + +/* init/shutdown */ +drc_core *drc_init(UINT8 cpunum, drc_config *config); +void *drc_alloc(drc_core *drc, size_t amount); +void drc_cache_reset(drc_core *drc); +void drc_execute(drc_core *drc); +void drc_exit(drc_core *drc); + +/* code management */ +void drc_begin_sequence(drc_core *drc, UINT32 pc); +void drc_end_sequence(drc_core *drc); +void drc_register_code_at_cache_top(drc_core *drc, UINT32 pc); +void *drc_get_code_at_pc(drc_core *drc, UINT32 pc); + +/* standard appendages */ +void drc_append_dispatcher(drc_core *drc); +void drc_append_fixed_dispatcher(drc_core *drc, UINT32 newpc); +void drc_append_tentative_fixed_dispatcher(drc_core *drc, UINT32 newpc); +void drc_append_call_debugger(drc_core *drc); +void drc_append_standard_epilogue(drc_core *drc, INT32 cycles, INT32 pcdelta, int allow_exit); +void drc_append_save_volatiles(drc_core *drc); +void drc_append_restore_volatiles(drc_core *drc); +void drc_append_save_call_restore(drc_core *drc, x86code *target, UINT32 stackadj); +void drc_append_verify_code(drc_core *drc, void *code, UINT8 length); + +void drc_append_set_fp_rounding(drc_core *drc, UINT8 regindex); +void drc_append_set_temp_fp_rounding(drc_core *drc, UINT8 rounding); +void drc_append_restore_fp_rounding(drc_core *drc); + +void drc_append_set_sse_rounding(drc_core *drc, UINT8 regindex); +void drc_append_set_temp_sse_rounding(drc_core *drc, UINT8 rounding); +void drc_append_restore_sse_rounding(drc_core *drc); + +/* disassembling drc code */ +void drc_dasm(FILE *f, const void *begin, const void *end); + +/* x86 CPU features */ +UINT32 drc_x86_get_features(void); + + +#endif /* __X86DRC_H__ */ |