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

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
1.1.1.4 ! root       28:  * along with ARAnyM; if not, write to the Free Software Foundation,
        !            29:  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
1.1.1.3   root       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
1.1.1.4 ! root      165: extern void flush_icache(int n);
        !           166: extern void flush_icache_hard(int n);
1.1       root      167: #endif
                    168: extern void alloc_cache(void);
                    169: extern int check_for_cache_miss(void);
                    170: 
1.1.1.3   root      171: /* JIT FPU compilation */
                    172: extern void comp_fpp_opp (uae_u32 opcode, uae_u16 extra);
                    173: extern void comp_fbcc_opp (uae_u32 opcode);
                    174: extern void comp_fscc_opp (uae_u32 opcode, uae_u16 extra);
                    175: void comp_fdbcc_opp (uae_u32 opcode, uae_u16 extra);
                    176: void comp_ftrapcc_opp (uae_u32 opcode, uaecptr oldpc);
                    177: void comp_fsave_opp (uae_u32 opcode);
                    178: void comp_frestore_opp (uae_u32 opcode);
1.1       root      179: 
                    180: extern uae_u32 needed_flags;
                    181: extern uae_u8* comp_pc_p;
                    182: extern void* pushall_call_handler;
                    183: 
                    184: #define VREGS 32
                    185: #define VFREGS 16
                    186: 
                    187: #define INMEM 1
                    188: #define CLEAN 2
                    189: #define DIRTY 3
                    190: #define UNDEF 4
                    191: #define ISCONST 5
                    192: 
                    193: typedef struct {
                    194:   uae_u32* mem;
                    195:   uae_u32 val;
                    196:   uae_u8 is_swapped;
                    197:   uae_u8 status;
1.1.1.3   root      198:   uae_s8 realreg; /* gb-- realreg can hold -1 */
1.1       root      199:   uae_u8 realind; /* The index in the holds[] array */
                    200:   uae_u8 needflush;
                    201:   uae_u8 validsize;
                    202:   uae_u8 dirtysize;
                    203:   uae_u8 dummy;
                    204: } reg_status;
                    205: 
                    206: typedef struct {
                    207:   uae_u32* mem;
                    208:   double val;
                    209:   uae_u8 status;
1.1.1.3   root      210:   uae_s8 realreg; /* gb-- realreg can hold -1 */
1.1       root      211:   uae_u8 realind;
                    212:   uae_u8 needflush;
                    213: } freg_status;
                    214: 
                    215: #define PC_P 16
                    216: #define FLAGX 17
                    217: #define FLAGTMP 18
                    218: #define NEXT_HANDLER 19
                    219: #define S1 20
                    220: #define S2 21
                    221: #define S3 22
                    222: #define S4 23
                    223: #define S5 24
                    224: #define S6 25
                    225: #define S7 26
                    226: #define S8 27
                    227: #define S9 28
                    228: #define S10 29
                    229: #define S11 30
                    230: #define S12 31
                    231: 
                    232: #define FP_RESULT 8
                    233: #define FS1 9
                    234: #define FS2 10
                    235: #define FS3 11
                    236: 
                    237: typedef struct {
                    238:   uae_u32 touched;
                    239:   uae_s8 holds[VREGS];
                    240:   uae_u8 nholds;
                    241:   uae_u8 canbyte;
                    242:   uae_u8 canword;
                    243:   uae_u8 locked;
                    244: } n_status;
                    245: 
                    246: typedef struct {
                    247:   uae_u32 touched;
                    248:   uae_s8 holds[VFREGS];
                    249:   uae_u8 nholds;
                    250:   uae_u8 locked;
                    251: } fn_status;
                    252: 
                    253: /* For flag handling */
                    254: #define NADA 1
                    255: #define TRASH 2
                    256: #define VALID 3
                    257: 
                    258: /* needflush values */
                    259: #define NF_SCRATCH   0
                    260: #define NF_TOMEM     1
                    261: #define NF_HANDLER   2
                    262: 
                    263: typedef struct {
                    264:     /* Integer part */
                    265:     reg_status state[VREGS];
                    266:     n_status   nat[N_REGS];
                    267:     uae_u32 flags_on_stack;
                    268:     uae_u32 flags_in_flags;
                    269:     uae_u32 flags_are_important;
                    270:     /* FPU part */
                    271:     freg_status fate[VFREGS];
                    272:     fn_status   fat[N_FREGS];
                    273: 
                    274:     /* x86 FPU part */
                    275:     uae_s8 spos[N_FREGS];
                    276:     uae_s8 onstack[6];
                    277:     uae_s8 tos;
                    278: } bigstate;
                    279: 
                    280: typedef struct {
1.1.1.3   root      281:        /* Integer part */
                    282:        uae_s8 virt[VREGS];
                    283:        uae_s8 nat[N_REGS];
1.1       root      284: } smallstate;
                    285: 
                    286: extern int touchcnt;
                    287: 
1.1.1.3   root      288: #define IMM  uae_s32
                    289: #define RR1  uae_u32
                    290: #define RR2  uae_u32
                    291: #define RR4  uae_u32
                    292: /*
                    293:   R1, R2, R4 collides with ARM registers defined in ucontext
1.1       root      294: #define R1  uae_u32
                    295: #define R2  uae_u32
                    296: #define R4  uae_u32
1.1.1.3   root      297: */
1.1       root      298: #define W1  uae_u32
                    299: #define W2  uae_u32
                    300: #define W4  uae_u32
                    301: #define RW1 uae_u32
                    302: #define RW2 uae_u32
                    303: #define RW4 uae_u32
                    304: #define MEMR uae_u32
                    305: #define MEMW uae_u32
                    306: #define MEMRW uae_u32
                    307: 
                    308: #define FW   uae_u32
                    309: #define FR   uae_u32
                    310: #define FRW  uae_u32
                    311: 
                    312: #define MIDFUNC(nargs,func,args) void func args
                    313: #define MENDFUNC(nargs,func,args)
                    314: #define COMPCALL(func) func
                    315: 
1.1.1.3   root      316: #define LOWFUNC(flags,mem,nargs,func,args) static inline void func args
1.1       root      317: #define LENDFUNC(flags,mem,nargs,func,args)
                    318: 
1.1.1.3   root      319: /* What we expose to the outside */
                    320: #define DECLARE_MIDFUNC(func) extern void func
                    321: 
                    322: #if defined(CPU_arm)
                    323: 
                    324: #include "compemu_midfunc_arm.h"
                    325: 
                    326: #if defined(USE_JIT2)
                    327: #include "compemu_midfunc_arm2.h"
                    328: #endif
1.1       root      329: #endif
                    330: 
1.1.1.3   root      331: #if defined(CPU_i386) || defined(CPU_x86_64)
                    332: #include "compemu_midfunc_x86.h"
                    333: #endif
1.1       root      334: 
1.1.1.3   root      335: #undef DECLARE_MIDFUNC
1.1       root      336: 
                    337: extern int failure;
                    338: #define FAIL(x) do { failure|=x; } while (0)
                    339: 
                    340: /* Convenience functions exposed to gencomp */
                    341: extern uae_u32 m68k_pc_offset;
                    342: extern void readbyte(int address, int dest, int tmp);
                    343: extern void readword(int address, int dest, int tmp);
                    344: extern void readlong(int address, int dest, int tmp);
                    345: extern void writebyte(int address, int source, int tmp);
                    346: extern void writeword(int address, int source, int tmp);
                    347: extern void writelong(int address, int source, int tmp);
                    348: extern void writeword_clobber(int address, int source, int tmp);
                    349: extern void writelong_clobber(int address, int source, int tmp);
                    350: extern void get_n_addr(int address, int dest, int tmp);
                    351: extern void get_n_addr_jmp(int address, int dest, int tmp);
                    352: extern void calc_disp_ea_020(int base, uae_u32 dp, int target, int tmp);
1.1.1.3   root      353: /* Set native Z flag only if register is zero */
                    354: extern void set_zero(int r, int tmp);
1.1       root      355: extern int kill_rodent(int r);
1.1.1.3   root      356: #define SYNC_PC_OFFSET 100
1.1       root      357: extern void sync_m68k_pc(void);
                    358: extern uae_u32 get_const(int r);
                    359: extern int  is_const(int r);
                    360: extern void register_branch(uae_u32 not_taken, uae_u32 taken, uae_u8 cond);
                    361: 
                    362: #define comp_get_ibyte(o) do_get_mem_byte((uae_u8 *)(comp_pc_p + (o) + 1))
                    363: #define comp_get_iword(o) do_get_mem_word((uae_u16 *)(comp_pc_p + (o)))
                    364: #define comp_get_ilong(o) do_get_mem_long((uae_u32 *)(comp_pc_p + (o)))
                    365: 
                    366: struct blockinfo_t;
                    367: 
                    368: typedef struct dep_t {
                    369:   uae_u32*            jmp_off;
                    370:   struct blockinfo_t* target;
1.1.1.3   root      371:   struct blockinfo_t* source;
1.1       root      372:   struct dep_t**      prev_p;
                    373:   struct dep_t*       next;
                    374: } dependency;
                    375: 
1.1.1.3   root      376: typedef struct checksum_info_t {
                    377:   uae_u8 *start_p;
                    378:   uae_u32 length;
                    379:   struct checksum_info_t *next;
                    380: } checksum_info;
                    381: 
1.1       root      382: typedef struct blockinfo_t {
                    383:     uae_s32 count;
                    384:     cpuop_func* direct_handler_to_use;
                    385:     cpuop_func* handler_to_use;
                    386:     /* The direct handler does not check for the correct address */
                    387: 
                    388:     cpuop_func* handler;
                    389:     cpuop_func* direct_handler;
                    390: 
                    391:     cpuop_func* direct_pen;
                    392:     cpuop_func* direct_pcc;
                    393: 
                    394:     uae_u8* nexthandler;
                    395:     uae_u8* pc_p;
                    396: 
                    397:     uae_u32 c1;
                    398:     uae_u32 c2;
1.1.1.3   root      399: #if USE_CHECKSUM_INFO
                    400:     checksum_info *csi;
                    401: #else
1.1       root      402:     uae_u32 len;
1.1.1.3   root      403:     uae_u32 min_pcp;
                    404: #endif
1.1       root      405: 
                    406:     struct blockinfo_t* next_same_cl;
                    407:     struct blockinfo_t** prev_same_cl_p;
                    408:     struct blockinfo_t* next;
                    409:     struct blockinfo_t** prev_p;
                    410: 
                    411:     uae_u8 optlevel;
                    412:     uae_u8 needed_flags;
                    413:     uae_u8 status;
                    414:     uae_u8 havestate;
                    415: 
                    416:     dependency  dep[2];  /* Holds things we depend on */
                    417:     dependency* deplist; /* List of things that depend on this */
                    418:     smallstate  env;
1.1.1.3   root      419: 
                    420: #ifdef JIT_DEBUG
                    421:     /* (gb) size of the compiled block (direct handler) */
                    422:     uae_u32 direct_handler_size;
                    423: #endif
1.1       root      424: } blockinfo;
                    425: 
1.1.1.3   root      426: #define BI_INVALID 0
                    427: #define BI_ACTIVE 1
                    428: #define BI_NEED_RECOMP 2
                    429: #define BI_NEED_CHECK 3
                    430: #define BI_CHECKING 4
                    431: #define BI_COMPILING 5
                    432: #define BI_FINALIZING 6
                    433: 
                    434: void execute_normal(void);
                    435: void exec_nostats(void);
                    436: void do_nothing(void);
                    437: 
                    438: #else
                    439: 
                    440: static inline void flush_icache(int) { }
                    441: static inline void build_comp() { }
                    442: 
                    443: #endif /* !USE_JIT */
                    444: 
                    445: #ifdef UAE
1.1       root      446: 
                    447: typedef struct {
                    448:     uae_u8 type;
                    449:     uae_u8 reg;
                    450:     uae_u32 next;
                    451: } regacc;
                    452: 
1.1.1.3   root      453: #define JIT_EXCEPTION_HANDLER
                    454: // #define JIT_ALWAYS_DISTRUST
1.1       root      455: 
1.1.1.3   root      456: /* ARAnyM uses fpu_register name, used in scratch_t */
                    457: /* FIXME: check that no ARAnyM code assumes different floating point type */
                    458: typedef fptype fpu_register;
                    459: 
                    460: extern void compile_block(cpu_history* pc_hist, int blocklen, int totcyles);
                    461: 
                    462: #define MAXCYCLES (1000 * CYCLE_UNIT)
                    463: #define scaled_cycles(x) (currprefs.m68k_speed<0?(((x)/SCALE)?(((x)/SCALE<MAXCYCLES?((x)/SCALE):MAXCYCLES)):1):(x))
                    464: 
                    465: /* Flags for Bernie during development/debugging. Should go away eventually */
                    466: #define DISTRUST_CONSISTENT_MEM 0
                    467: 
                    468: typedef struct {
                    469:     uae_u8 use_flags;
                    470:     uae_u8 set_flags;
                    471:     uae_u8 is_jump;
                    472:     uae_u8 is_addx;
                    473:     uae_u8 is_const_jump;
                    474: } op_properties;
                    475: 
                    476: extern op_properties prop[65536];
                    477: 
                    478: STATIC_INLINE int end_block(uae_u16 opcode)
                    479: {
                    480:     return prop[opcode].is_jump ||
                    481:        (prop[opcode].is_const_jump && !currprefs.comp_constjump);
                    482: }
                    483: 
                    484: #ifdef _WIN32
                    485: LONG WINAPI EvalException(LPEXCEPTION_POINTERS info);
                    486: #if defined(_MSC_VER) && !defined(NO_WIN32_EXCEPTION_HANDLER)
                    487: #ifdef _WIN64
                    488: /* Structured exception handling is table based for Windows x86-64, so
                    489:  * Windows will not be able to find the exception handler. */
                    490: #else
                    491: #define USE_STRUCTURED_EXCEPTION_HANDLING
                    492: #endif
                    493: #endif
                    494: #endif
                    495: 
                    496: void jit_abort(const char *format,...);
                    497: #if SIZEOF_TCHAR != 1
                    498: void jit_abort(const TCHAR *format, ...);
                    499: #endif
                    500: 
                    501: #else
                    502: 
                    503: #define jit_abort(...) abort()
                    504: #define jit_log panicbug
                    505: #define jit_log2(...)
                    506: 
                    507: #endif
                    508: 
                    509: #ifdef CPU_64_BIT
                    510: static inline uae_u32 check_uae_p32(uae_u64 address, const char *file, int line)
                    511: {
                    512:        if (address > (uintptr_t) 0xffffffff) {
                    513:                jit_abort("JIT: 64-bit pointer (0x%llx) at %s:%d (fatal)",
                    514:                        address, file, line);
                    515:        }
                    516:        return (uae_u32) address;
                    517: }
                    518: #define uae_p32(x) (check_uae_p32((uae_u64)(x), __FILE__, __LINE__))
                    519: #else
                    520: #define uae_p32(x) ((uae_u32)(x))
                    521: #endif
                    522: 
                    523: #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.