int sh2_drc_init(SH2 *sh2); void sh2_drc_finish(SH2 *sh2); void sh2_drc_wcheck_ram(uint32_t a, unsigned len, SH2 *sh2); void sh2_drc_wcheck_da(uint32_t a, unsigned len, SH2 *sh2); #ifdef DRC_SH2 void sh2_drc_mem_setup(SH2 *sh2); void sh2_drc_flush_all(void); #else #define sh2_drc_mem_setup(x) #define sh2_drc_flush_all() #define sh2_drc_frame() #endif #define BLOCK_INSN_LIMIT 1024 /* op_flags */ #define OF_DELAY_OP (1 << 0) #define OF_BTARGET (1 << 1) #define OF_LOOP (3 << 2) // NONE, IDLE, DELAY, POLL loop #define OF_B_IN_DS (1 << 4) #define OF_DELAY_INSN (1 << 5) // DT, (TODO ADD+CMP?) #define OF_POLL_INSN (1 << 6) // MOV @(...),Rn (no post increment), TST @(...) #define OF_BASIC_LOOP (1 << 7) // pinnable loop without any branches in it #define OF_IDLE_LOOP (1 << 2) #define OF_DELAY_LOOP (2 << 2) #define OF_POLL_LOOP (3 << 2) unsigned short scan_block(uint32_t base_pc, int is_slave, unsigned char *op_flags, uint32_t *end_pc, uint32_t *base_literals, uint32_t *end_literals); #if defined(DRC_SH2) && defined(__GNUC__) // direct access to some host CPU registers used by the DRC if gcc is used. // XXX MUST match SHR_SR definitions in cpu/drc/emit_*.c; should be moved there // XXX yuck, there's no portable way to determine register size. Use long long // if target is 64 bit and data model is ILP32 or LLP64(windows), else long #if defined(__arm__) #define DRC_SR_REG "r10" #define DRC_REG_LL 0 // 32 bit #elif defined(__aarch64__) #define DRC_SR_REG "r28" #define DRC_REG_LL (__ILP32__ || _WIN32) #elif defined(__mips__) #define DRC_SR_REG "s6" #define DRC_REG_LL (_MIPS_SIM == _ABIN32) #elif defined(__riscv__) || defined(__riscv) #define DRC_SR_REG "s11" #define DRC_REG_LL 0 // no ABI for (__ILP32__ && __riscv_xlen != 32) #elif defined(__powerpc__) #define DRC_SR_REG "r30" #define DRC_REG_LL 0 // no ABI for __ILP32__ #elif defined(__i386__) #define DRC_SR_REG "edi" #define DRC_REG_LL 0 // 32 bit #elif defined(__x86_64__) #define DRC_SR_REG "rbx" #define DRC_REG_LL (__ILP32__ || _WIN32) #endif #endif #ifdef DRC_SR_REG // XXX this is more clear but produces too much overhead for slow platforms extern void REGPARM(1) (*sh2_drc_save_sr)(SH2 *sh2); extern void REGPARM(1) (*sh2_drc_restore_sr)(SH2 *sh2); // NB: sh2_sr MUST have register size if optimizing with -O3 (-fif-conversion) #if DRC_REG_LL #define DRC_DECLARE_SR register long long _sh2_sr asm(DRC_SR_REG) #else #define DRC_DECLARE_SR register long _sh2_sr asm(DRC_SR_REG) #endif #define DRC_SAVE_SR(sh2) \ if (likely((sh2->state&(SH2_STATE_RUN|SH2_STATE_SLEEP)) == SH2_STATE_RUN)) \ sh2->sr = (s32)_sh2_sr // sh2_drc_save_sr(sh2) #define DRC_RESTORE_SR(sh2) \ if (likely((sh2->state&(SH2_STATE_RUN|SH2_STATE_SLEEP)) == SH2_STATE_RUN)) \ _sh2_sr = (s32)sh2->sr // sh2_drc_restore_sr(sh2) #else #define DRC_DECLARE_SR #define DRC_SAVE_SR(sh2) #define DRC_RESTORE_SR(sh2) #endif