Annotation of hatari/src/cpu/jit/compemu.h, revision 1.1.1.3

1.1.1.3 ! root        1: /*
        !             2:  * compiler/compemu.h - Public interface and definitions
        !             3:  *
        !             4:  * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
        !             5:  *
        !             6:  * Inspired by Christian Bauer's Basilisk II
        !             7:  *
        !             8:  * This file is part of the ARAnyM project which builds a new and powerful
        !             9:  * TOS/FreeMiNT compatible virtual machine running on almost any hardware.
        !            10:  *
        !            11:  * JIT compiler m68k -> IA-32 and AMD64
        !            12:  *
        !            13:  * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer
        !            14:  * Adaptation for Basilisk II and improvements, copyright 2000-2004 Gwenole Beauchesne
        !            15:  * Portions related to CPU detection come from linux/arch/i386/kernel/setup.c
        !            16:  *
        !            17:  * ARAnyM is free software; you can redistribute it and/or modify
        !            18:  * it under the terms of the GNU General Public License as published by
        !            19:  * the Free Software Foundation; either version 2 of the License, or
        !            20:  * (at your option) any later version.
        !            21:  *
        !            22:  * ARAnyM is distributed in the hope that it will be useful,
        !            23:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            24:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            25:  * GNU General Public License for more details.
        !            26:  *
        !            27:  * You should have received a copy of the GNU General Public License
        !            28:  * along with ARAnyM; if not, write to the Free Software
        !            29:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
        !            30:  */
1.1       root       31: 
1.1.1.3 ! root       32: #ifndef COMPEMU_H
        !            33: #define COMPEMU_H
1.1       root       34: 
1.1.1.3 ! root       35: #include "newcpu.h"
        !            36: 
        !            37: #ifdef UAE
1.1       root       38: #ifdef CPU_64_BIT
                     39: typedef uae_u64 uintptr;
                     40: #else
                     41: typedef uae_u32 uintptr;
                     42: #endif
1.1.1.3 ! root       43: /* FIXME: cpummu.cpp also checks for USE_JIT, possibly others */
        !            44: #define USE_JIT
        !            45: #endif
1.1       root       46: 
1.1.1.3 ! root       47: #ifdef USE_JIT
        !            48: 
        !            49: #ifdef JIT_DEBUG
        !            50: /* dump some information (m68k block, x86 block addresses) about the compiler state */
        !            51: extern void compiler_dumpstate(void);
        !            52: #endif
        !            53: 
        !            54: /* Now that we do block chaining, and also have linked lists on each tag,
        !            55:    TAGMASK can be much smaller and still do its job. Saves several megs
        !            56:    of memory! */
        !            57: #define TAGMASK 0x0000ffff
1.1       root       58: #define TAGSIZE (TAGMASK+1)
                     59: #define MAXRUN 1024
1.1.1.3 ! root       60: #define cacheline(x) (((uintptr)x)&TAGMASK)
1.1       root       61: 
                     62: extern uae_u8* start_pc_p;
                     63: extern uae_u32 start_pc;
                     64: 
1.1.1.3 ! root       65: struct blockinfo_t;
1.1       root       66: 
1.1.1.3 ! root       67: struct cpu_history {
1.1       root       68:   uae_u16* location;
                     69:   uae_u8  specmem;
1.1.1.3 ! root       70: };
1.1       root       71: 
1.1.1.3 ! root       72: union cacheline {
        !            73:        cpuop_func* handler;
        !            74:        blockinfo_t * bi;
        !            75: };
        !            76: 
        !            77: /* Use new spill/reload strategy when calling external functions */
        !            78: #define USE_OPTIMIZED_CALLS 0
        !            79: #if USE_OPTIMIZED_CALLS
        !            80: #error implementation in progress
        !            81: #endif
1.1       root       82: 
1.1.1.3 ! root       83: /* (gb) When on, this option can save save up to 30% compilation time
        !            84:  *  when many lazy flushes occur (e.g. apps in MacOS 8.x).
        !            85:  */
        !            86: #define USE_SEPARATE_BIA 1
        !            87: 
        !            88: /* Use chain of checksum_info_t to compute the block checksum */
        !            89: #define USE_CHECKSUM_INFO 1
        !            90: 
        !            91: /* Use code inlining, aka follow-up of constant jumps */
        !            92: #define USE_INLINING 1
        !            93: 
        !            94: /* Inlining requires the chained checksuming information */
        !            95: #if USE_INLINING
        !            96: #undef  USE_CHECKSUM_INFO
        !            97: #define USE_CHECKSUM_INFO 1
        !            98: #endif
1.1       root       99: 
1.1.1.3 ! root      100: /* Does flush_icache_range() only check for blocks falling in the requested range? */
        !           101: #define LAZY_FLUSH_ICACHE_RANGE 0
1.1       root      102: 
                    103: #define USE_F_ALIAS 1
                    104: #define USE_OFFSET 1
                    105: #define COMP_DEBUG 1
                    106: 
                    107: #if COMP_DEBUG
                    108: #define Dif(x) if (x)
                    109: #else
                    110: #define Dif(x) if (0)
                    111: #endif
                    112: 
                    113: #define SCALE 2
                    114: 
                    115: #define BYTES_PER_INST 10240  /* paranoid ;-) */
1.1.1.3 ! root      116: #if defined(CPU_arm)
        !           117: #define LONGEST_68K_INST 256 /* The number of bytes the longest possible
        !           118:                               68k instruction takes */
        !           119: #else
1.1       root      120: #define LONGEST_68K_INST 16 /* The number of bytes the longest possible
                    121:                               68k instruction takes */
1.1.1.3 ! root      122: #endif
1.1       root      123: #define MAX_CHECKSUM_LEN 2048 /* The maximum size we calculate checksums
                    124:                                 for. Anything larger will be flushed
                    125:                                 unconditionally even with SOFT_FLUSH */
                    126: #define MAX_HOLD_BI 3  /* One for the current block, and up to two
                    127:                          for jump targets */
                    128: 
                    129: #define INDIVIDUAL_INST 0
                    130: #define FLAG_C    0x0010
                    131: #define FLAG_V    0x0008
                    132: #define FLAG_Z    0x0004
                    133: #define FLAG_N    0x0002
                    134: #define FLAG_X    0x0001
                    135: #define FLAG_CZNV (FLAG_C | FLAG_Z | FLAG_N | FLAG_V)
                    136: #define FLAG_ZNV  (FLAG_Z | FLAG_N | FLAG_V)
                    137: 
                    138: #define KILLTHERAT 1  /* Set to 1 to avoid some partial_rat_stalls */
                    139: 
1.1.1.3 ! root      140: #if defined(CPU_arm)
        !           141: #define USE_DATA_BUFFER
        !           142: #define N_REGS 13  /* really 16, but 13 to 15 are SP, LR, PC */
        !           143: #else
        !           144: #if defined(CPU_x86_64)
        !           145: #define N_REGS 16 /* really only 15, but they are numbered 0-3,5-15 */
1.1       root      146: #else
                    147: #define N_REGS 8  /* really only 7, but they are numbered 0,1,2,3,5,6,7 */
1.1.1.3 ! root      148: #endif
        !           149: #endif
1.1       root      150: #define N_FREGS 6 /* That leaves us two positions on the stack to play with */
                    151: 
                    152: /* Functions exposed to newcpu, or to what was moved from newcpu.c to
                    153:  * compemu_support.c */
                    154: extern void init_comp(void);
                    155: extern void flush(int save_regs);
                    156: extern void small_flush(int save_regs);
                    157: extern void set_target(uae_u8* t);
1.1.1.3 ! root      158: extern uae_u8* get_target(void);
1.1       root      159: extern void freescratch(void);
                    160: extern void build_comp(void);
                    161: extern void set_cache_state(int enabled);
                    162: extern int get_cache_state(void);
                    163: extern uae_u32 get_jitted_size(void);
                    164: #ifdef JIT
                    165: extern void flush_icache(uaecptr ptr, int n);
1.1.1.2   root      166: extern void flush_icache_hard(uaecptr ptr, int n);
1.1.1.3 ! root      167: static inline void flush_icache(int n)
        !           168: {
        !           169:        flush_icache(0, n);
        !           170: }
        !           171: static inline void flush_icache_hard(int n)
        !           172: {
        !           173:        flush_icache(0, n);
        !           174: }
1.1       root      175: #endif
                    176: extern void alloc_cache(void);
                    177: extern int check_for_cache_miss(void);
                    178: 
1.1.1.3 ! root      179: /* JIT FPU compilation */
        !           180: extern void comp_fpp_opp (uae_u32 opcode, uae_u16 extra);
        !           181: extern void comp_fbcc_opp (uae_u32 opcode);
        !           182: extern void comp_fscc_opp (uae_u32 opcode, uae_u16 extra);
        !           183: void comp_fdbcc_opp (uae_u32 opcode, uae_u16 extra);
        !           184: void comp_ftrapcc_opp (uae_u32 opcode, uaecptr oldpc);
        !           185: void comp_fsave_opp (uae_u32 opcode);
        !           186: void comp_frestore_opp (uae_u32 opcode);
1.1       root      187: 
                    188: extern uae_u32 needed_flags;
                    189: extern uae_u8* comp_pc_p;
                    190: extern void* pushall_call_handler;
                    191: 
                    192: #define VREGS 32
                    193: #define VFREGS 16
                    194: 
                    195: #define INMEM 1
                    196: #define CLEAN 2
                    197: #define DIRTY 3
                    198: #define UNDEF 4
                    199: #define ISCONST 5
                    200: 
                    201: typedef struct {
                    202:   uae_u32* mem;
                    203:   uae_u32 val;
                    204:   uae_u8 is_swapped;
                    205:   uae_u8 status;
1.1.1.3 ! root      206:   uae_s8 realreg; /* gb-- realreg can hold -1 */
1.1       root      207:   uae_u8 realind; /* The index in the holds[] array */
                    208:   uae_u8 needflush;
                    209:   uae_u8 validsize;
                    210:   uae_u8 dirtysize;
                    211:   uae_u8 dummy;
                    212: } reg_status;
                    213: 
                    214: typedef struct {
                    215:   uae_u32* mem;
                    216:   double val;
                    217:   uae_u8 status;
1.1.1.3 ! root      218:   uae_s8 realreg; /* gb-- realreg can hold -1 */
1.1       root      219:   uae_u8 realind;
                    220:   uae_u8 needflush;
                    221: } freg_status;
                    222: 
                    223: #define PC_P 16
                    224: #define FLAGX 17
                    225: #define FLAGTMP 18
                    226: #define NEXT_HANDLER 19
                    227: #define S1 20
                    228: #define S2 21
                    229: #define S3 22
                    230: #define S4 23
                    231: #define S5 24
                    232: #define S6 25
                    233: #define S7 26
                    234: #define S8 27
                    235: #define S9 28
                    236: #define S10 29
                    237: #define S11 30
                    238: #define S12 31
                    239: 
                    240: #define FP_RESULT 8
                    241: #define FS1 9
                    242: #define FS2 10
                    243: #define FS3 11
                    244: 
                    245: typedef struct {
                    246:   uae_u32 touched;
                    247:   uae_s8 holds[VREGS];
                    248:   uae_u8 nholds;
                    249:   uae_u8 canbyte;
                    250:   uae_u8 canword;
                    251:   uae_u8 locked;
                    252: } n_status;
                    253: 
                    254: typedef struct {
                    255:   uae_u32 touched;
                    256:   uae_s8 holds[VFREGS];
                    257:   uae_u8 nholds;
                    258:   uae_u8 locked;
                    259: } fn_status;
                    260: 
                    261: /* For flag handling */
                    262: #define NADA 1
                    263: #define TRASH 2
                    264: #define VALID 3
                    265: 
                    266: /* needflush values */
                    267: #define NF_SCRATCH   0
                    268: #define NF_TOMEM     1
                    269: #define NF_HANDLER   2
                    270: 
                    271: typedef struct {
                    272:     /* Integer part */
                    273:     reg_status state[VREGS];
                    274:     n_status   nat[N_REGS];
                    275:     uae_u32 flags_on_stack;
                    276:     uae_u32 flags_in_flags;
                    277:     uae_u32 flags_are_important;
                    278:     /* FPU part */
                    279:     freg_status fate[VFREGS];
                    280:     fn_status   fat[N_FREGS];
                    281: 
                    282:     /* x86 FPU part */
                    283:     uae_s8 spos[N_FREGS];
                    284:     uae_s8 onstack[6];
                    285:     uae_s8 tos;
                    286: } bigstate;
                    287: 
                    288: typedef struct {
1.1.1.3 ! root      289:        /* Integer part */
        !           290:        uae_s8 virt[VREGS];
        !           291:        uae_s8 nat[N_REGS];
1.1       root      292: } smallstate;
                    293: 
                    294: extern int touchcnt;
                    295: 
1.1.1.3 ! root      296: #define IMM  uae_s32
        !           297: #define RR1  uae_u32
        !           298: #define RR2  uae_u32
        !           299: #define RR4  uae_u32
        !           300: /*
        !           301:   R1, R2, R4 collides with ARM registers defined in ucontext
1.1       root      302: #define R1  uae_u32
                    303: #define R2  uae_u32
                    304: #define R4  uae_u32
1.1.1.3 ! root      305: */
1.1       root      306: #define W1  uae_u32
                    307: #define W2  uae_u32
                    308: #define W4  uae_u32
                    309: #define RW1 uae_u32
                    310: #define RW2 uae_u32
                    311: #define RW4 uae_u32
                    312: #define MEMR uae_u32
                    313: #define MEMW uae_u32
                    314: #define MEMRW uae_u32
                    315: 
                    316: #define FW   uae_u32
                    317: #define FR   uae_u32
                    318: #define FRW  uae_u32
                    319: 
                    320: #define MIDFUNC(nargs,func,args) void func args
                    321: #define MENDFUNC(nargs,func,args)
                    322: #define COMPCALL(func) func
                    323: 
1.1.1.3 ! root      324: #define LOWFUNC(flags,mem,nargs,func,args) static inline void func args
1.1       root      325: #define LENDFUNC(flags,mem,nargs,func,args)
                    326: 
1.1.1.3 ! root      327: /* What we expose to the outside */
        !           328: #define DECLARE_MIDFUNC(func) extern void func
        !           329: 
        !           330: #if defined(CPU_arm)
        !           331: 
        !           332: #include "compemu_midfunc_arm.h"
        !           333: 
        !           334: #if defined(USE_JIT2)
        !           335: #include "compemu_midfunc_arm2.h"
        !           336: #endif
1.1       root      337: #endif
                    338: 
1.1.1.3 ! root      339: #if defined(CPU_i386) || defined(CPU_x86_64)
        !           340: #include "compemu_midfunc_x86.h"
        !           341: #endif
1.1       root      342: 
1.1.1.3 ! root      343: #undef DECLARE_MIDFUNC
1.1       root      344: 
                    345: extern int failure;
                    346: #define FAIL(x) do { failure|=x; } while (0)
                    347: 
                    348: /* Convenience functions exposed to gencomp */
                    349: extern uae_u32 m68k_pc_offset;
                    350: extern void readbyte(int address, int dest, int tmp);
                    351: extern void readword(int address, int dest, int tmp);
                    352: extern void readlong(int address, int dest, int tmp);
                    353: extern void writebyte(int address, int source, int tmp);
                    354: extern void writeword(int address, int source, int tmp);
                    355: extern void writelong(int address, int source, int tmp);
                    356: extern void writeword_clobber(int address, int source, int tmp);
                    357: extern void writelong_clobber(int address, int source, int tmp);
                    358: extern void get_n_addr(int address, int dest, int tmp);
                    359: extern void get_n_addr_jmp(int address, int dest, int tmp);
                    360: extern void calc_disp_ea_020(int base, uae_u32 dp, int target, int tmp);
1.1.1.3 ! root      361: /* Set native Z flag only if register is zero */
        !           362: extern void set_zero(int r, int tmp);
1.1       root      363: extern int kill_rodent(int r);
1.1.1.3 ! root      364: #define SYNC_PC_OFFSET 100
1.1       root      365: extern void sync_m68k_pc(void);
                    366: extern uae_u32 get_const(int r);
                    367: extern int  is_const(int r);
                    368: extern void register_branch(uae_u32 not_taken, uae_u32 taken, uae_u8 cond);
                    369: 
                    370: #define comp_get_ibyte(o) do_get_mem_byte((uae_u8 *)(comp_pc_p + (o) + 1))
                    371: #define comp_get_iword(o) do_get_mem_word((uae_u16 *)(comp_pc_p + (o)))
                    372: #define comp_get_ilong(o) do_get_mem_long((uae_u32 *)(comp_pc_p + (o)))
                    373: 
                    374: struct blockinfo_t;
                    375: 
                    376: typedef struct dep_t {
                    377:   uae_u32*            jmp_off;
                    378:   struct blockinfo_t* target;
1.1.1.3 ! root      379:   struct blockinfo_t* source;
1.1       root      380:   struct dep_t**      prev_p;
                    381:   struct dep_t*       next;
                    382: } dependency;
                    383: 
1.1.1.3 ! root      384: typedef struct checksum_info_t {
        !           385:   uae_u8 *start_p;
        !           386:   uae_u32 length;
        !           387:   struct checksum_info_t *next;
        !           388: } checksum_info;
        !           389: 
1.1       root      390: typedef struct blockinfo_t {
                    391:     uae_s32 count;
                    392:     cpuop_func* direct_handler_to_use;
                    393:     cpuop_func* handler_to_use;
                    394:     /* The direct handler does not check for the correct address */
                    395: 
                    396:     cpuop_func* handler;
                    397:     cpuop_func* direct_handler;
                    398: 
                    399:     cpuop_func* direct_pen;
                    400:     cpuop_func* direct_pcc;
                    401: 
                    402:     uae_u8* nexthandler;
                    403:     uae_u8* pc_p;
                    404: 
                    405:     uae_u32 c1;
                    406:     uae_u32 c2;
1.1.1.3 ! root      407: #if USE_CHECKSUM_INFO
        !           408:     checksum_info *csi;
        !           409: #else
1.1       root      410:     uae_u32 len;
1.1.1.3 ! root      411:     uae_u32 min_pcp;
        !           412: #endif
1.1       root      413: 
                    414:     struct blockinfo_t* next_same_cl;
                    415:     struct blockinfo_t** prev_same_cl_p;
                    416:     struct blockinfo_t* next;
                    417:     struct blockinfo_t** prev_p;
                    418: 
                    419:     uae_u8 optlevel;
                    420:     uae_u8 needed_flags;
                    421:     uae_u8 status;
                    422:     uae_u8 havestate;
                    423: 
                    424:     dependency  dep[2];  /* Holds things we depend on */
                    425:     dependency* deplist; /* List of things that depend on this */
                    426:     smallstate  env;
1.1.1.3 ! root      427: 
        !           428: #ifdef JIT_DEBUG
        !           429:     /* (gb) size of the compiled block (direct handler) */
        !           430:     uae_u32 direct_handler_size;
        !           431: #endif
1.1       root      432: } blockinfo;
                    433: 
1.1.1.3 ! root      434: #define BI_INVALID 0
        !           435: #define BI_ACTIVE 1
        !           436: #define BI_NEED_RECOMP 2
        !           437: #define BI_NEED_CHECK 3
        !           438: #define BI_CHECKING 4
        !           439: #define BI_COMPILING 5
        !           440: #define BI_FINALIZING 6
        !           441: 
        !           442: void execute_normal(void);
        !           443: void exec_nostats(void);
        !           444: void do_nothing(void);
        !           445: 
        !           446: #else
        !           447: 
        !           448: static inline void flush_icache(int) { }
        !           449: static inline void build_comp() { }
        !           450: 
        !           451: #endif /* !USE_JIT */
        !           452: 
        !           453: #ifdef UAE
1.1       root      454: 
                    455: typedef struct {
                    456:     uae_u8 type;
                    457:     uae_u8 reg;
                    458:     uae_u32 next;
                    459: } regacc;
                    460: 
1.1.1.3 ! root      461: #define JIT_EXCEPTION_HANDLER
        !           462: // #define JIT_ALWAYS_DISTRUST
1.1       root      463: 
1.1.1.3 ! root      464: /* ARAnyM uses fpu_register name, used in scratch_t */
        !           465: /* FIXME: check that no ARAnyM code assumes different floating point type */
        !           466: typedef fptype fpu_register;
        !           467: 
        !           468: extern void compile_block(cpu_history* pc_hist, int blocklen, int totcyles);
        !           469: 
        !           470: #define MAXCYCLES (1000 * CYCLE_UNIT)
        !           471: #define scaled_cycles(x) (currprefs.m68k_speed<0?(((x)/SCALE)?(((x)/SCALE<MAXCYCLES?((x)/SCALE):MAXCYCLES)):1):(x))
        !           472: 
        !           473: /* Flags for Bernie during development/debugging. Should go away eventually */
        !           474: #define DISTRUST_CONSISTENT_MEM 0
        !           475: 
        !           476: typedef struct {
        !           477:     uae_u8 use_flags;
        !           478:     uae_u8 set_flags;
        !           479:     uae_u8 is_jump;
        !           480:     uae_u8 is_addx;
        !           481:     uae_u8 is_const_jump;
        !           482: } op_properties;
        !           483: 
        !           484: extern op_properties prop[65536];
        !           485: 
        !           486: STATIC_INLINE int end_block(uae_u16 opcode)
        !           487: {
        !           488:     return prop[opcode].is_jump ||
        !           489:        (prop[opcode].is_const_jump && !currprefs.comp_constjump);
        !           490: }
        !           491: 
        !           492: #ifdef _WIN32
        !           493: LONG WINAPI EvalException(LPEXCEPTION_POINTERS info);
        !           494: #if defined(_MSC_VER) && !defined(NO_WIN32_EXCEPTION_HANDLER)
        !           495: #ifdef _WIN64
        !           496: /* Structured exception handling is table based for Windows x86-64, so
        !           497:  * Windows will not be able to find the exception handler. */
        !           498: #else
        !           499: #define USE_STRUCTURED_EXCEPTION_HANDLING
        !           500: #endif
        !           501: #endif
        !           502: #endif
        !           503: 
        !           504: void jit_abort(const char *format,...);
        !           505: #if SIZEOF_TCHAR != 1
        !           506: void jit_abort(const TCHAR *format, ...);
        !           507: #endif
        !           508: 
        !           509: #else
        !           510: 
        !           511: #define jit_abort(...) abort()
        !           512: #define jit_log panicbug
        !           513: #define jit_log2(...)
        !           514: 
        !           515: #endif
        !           516: 
        !           517: #ifdef CPU_64_BIT
        !           518: static inline uae_u32 check_uae_p32(uae_u64 address, const char *file, int line)
        !           519: {
        !           520:        if (address > (uintptr_t) 0xffffffff) {
        !           521:                jit_abort("JIT: 64-bit pointer (0x%llx) at %s:%d (fatal)",
        !           522:                        address, file, line);
        !           523:        }
        !           524:        return (uae_u32) address;
        !           525: }
        !           526: #define uae_p32(x) (check_uae_p32((uae_u64)(x), __FILE__, __LINE__))
        !           527: #else
        !           528: #define uae_p32(x) ((uae_u32)(x))
        !           529: #endif
        !           530: 
        !           531: #endif /* COMPEMU_H */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.