Annotation of previous/src/cpu/jit/compemu_support_codegen.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  *  compiler/compemu_support.cpp - Core dynamic translation engine
                      3:  *
                      4:  *  Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer
                      5:  *
                      6:  *  Adaptation for Basilisk II and improvements, copyright 2000-2005
                      7:  *    Gwenole Beauchesne
                      8:  *
                      9:  *  Basilisk II (C) 1997-2008 Christian Bauer
                     10:  *  
                     11:  *  This program is free software; you can redistribute it and/or modify
                     12:  *  it under the terms of the GNU General Public License as published by
                     13:  *  the Free Software Foundation; either version 2 of the License, or
                     14:  *  (at your option) any later version.
                     15:  *
                     16:  *  This program is distributed in the hope that it will be useful,
                     17:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
                     18:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     19:  *  GNU General Public License for more details.
                     20:  *
                     21:  *  You should have received a copy of the GNU General Public License
                     22:  *  along with this program; if not, write to the Free Software
                     23:  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     24:  */
                     25: 
                     26: #if 0
                     27: #if !REAL_ADDRESSING && !DIRECT_ADDRESSING
                     28: #error "Only Real or Direct Addressing is supported with the JIT Compiler"
                     29: #endif
                     30: 
                     31: #if X86_ASSEMBLY && !SAHF_SETO_PROFITABLE
                     32: #error "Only [LS]AHF scheme to [gs]et flags is supported with the JIT Compiler"
                     33: #endif
                     34: #endif
                     35: 
                     36: /* NOTE: support for AMD64 assumes translation cache and other code
                     37:  * buffers are allocated into a 32-bit address space because (i) B2/JIT
                     38:  * code is not 64-bit clean and (ii) it's faster to resolve branches
                     39:  * that way.
                     40:  */
                     41: #if 0
                     42: #if !defined(__i386__) && !defined(__x86_64__)
                     43: #error "Only IA-32 and X86-64 targets are supported with the JIT Compiler"
                     44: #endif
                     45: #endif
                     46: 
                     47: #define USE_MATCH 0
                     48: 
                     49: /* kludge for Brian, so he can compile under MSVC++ */
                     50: #define USE_NORMAL_CALLING_CONVENTION 0
                     51: 
                     52: #ifndef WIN32
                     53: #include <unistd.h>
                     54: #include <sys/types.h>
                     55: #include <sys/mman.h>
                     56: #endif
                     57: 
                     58: #include <stdlib.h>
                     59: #include <fcntl.h>
                     60: #include <errno.h>
                     61: 
                     62: #include "sysconfig.h"
                     63: #include "sysdeps.h"
                     64: #if 0
                     65: #include "cpu_emulation.h"
                     66: #include "main.h"
                     67: #include "prefs.h"
                     68: #include "user_strings.h"
                     69: #include "vm_alloc.h"
                     70: #endif
                     71: 
                     72: //#include "machdep/m68k.h"
                     73: #include "memory.h"
                     74: //#include "readcpu.h"
                     75: #include "newcpu.h"
                     76: #include "comptbl.h"
                     77: #include "jit/compemu_codegen.h"
                     78: #include "fpu/fpu.h"
                     79: #include "fpu/flags.h"
                     80: 
                     81: #define DEBUG 1
                     82: #include "debug.h"
                     83: 
                     84: #ifdef ENABLE_MON
                     85: #include "mon.h"
                     86: #endif
                     87: 
                     88: #ifndef WIN32
                     89: #define PROFILE_COMPILE_TIME           1
                     90: #define PROFILE_UNTRANSLATED_INSNS     1
                     91: #endif
                     92: 
                     93: #if defined(__x86_64__) && 0
                     94: #define RECORD_REGISTER_USAGE          1
                     95: #endif
                     96: 
                     97: #ifdef WIN32
                     98: #undef write_log
                     99: #define write_log dummy_write_log
                    100: static void dummy_write_log(const char *, ...) { }
                    101: #endif
                    102: 
                    103: #if JIT_DEBUG
                    104: #undef abort
                    105: #define abort() do { \
                    106:        fprintf(stderr, "Abort in file %s at line %d\n", __FILE__, __LINE__); \
                    107:        exit(EXIT_FAILURE); \
                    108: } while (0)
                    109: #endif
                    110: 
                    111: #if RECORD_REGISTER_USAGE
                    112: static uint64 reg_count[16];
                    113: static int reg_count_local[16];
                    114: 
                    115: static int reg_count_compare(const void *ap, const void *bp)
                    116: {
                    117:     const int a = *((int *)ap);
                    118:     const int b = *((int *)bp);
                    119:     return reg_count[b] - reg_count[a];
                    120: }
                    121: #endif
                    122: 
                    123: #if PROFILE_COMPILE_TIME
                    124: #include <time.h>
                    125: static uae_u32 compile_count   = 0;
                    126: static clock_t compile_time            = 0;
                    127: static clock_t emul_start_time = 0;
                    128: static clock_t emul_end_time   = 0;
                    129: #endif
                    130: 
                    131: #if PROFILE_UNTRANSLATED_INSNS
                    132: const int untranslated_top_ten = 20;
                    133: static uae_u32 raw_cputbl_count[65536] = { 0, };
                    134: static uae_u16 opcode_nums[65536];
                    135: 
                    136: static int untranslated_compfn(const void *e1, const void *e2)
                    137: {
                    138:        return raw_cputbl_count[*(const uae_u16 *)e1] < raw_cputbl_count[*(const uae_u16 *)e2];
                    139: }
                    140: #endif
                    141: 
                    142: static compop_func *compfunctbl[65536];
                    143: static compop_func *nfcompfunctbl[65536];
                    144: static cpuop_func *nfcpufunctbl[65536];
                    145: uae_u8* comp_pc_p;
                    146: 
                    147: // From newcpu.cpp
                    148: extern bool quit_program;
                    149: 
                    150: // gb-- Extra data for Basilisk II/JIT
                    151: #if JIT_DEBUG
                    152: static bool            JITDebug                        = false;        // Enable runtime disassemblers through mon?
                    153: #else
                    154: const bool             JITDebug                        = false;        // Don't use JIT debug mode at all
                    155: #endif
                    156: #if USE_INLINING
                    157: static bool            follow_const_jumps      = true;         // Flag: translation through constant jumps     
                    158: #else
                    159: const bool             follow_const_jumps      = false;
                    160: #endif
                    161: 
                    162: const uae_u32  MIN_CACHE_SIZE          = 1024;         // Minimal translation cache size (1 MB)
                    163: static uae_u32 cache_size                      = 0;            // Size of total cache allocated for compiled blocks
                    164: static uae_u32 current_cache_size      = 0;            // Cache grows upwards: how much has been consumed already
                    165: static bool            lazy_flush                      = true;         // Flag: lazy translation cache invalidation
                    166: static bool            avoid_fpu                       = true;         // Flag: compile FPU instructions ?
                    167: static bool            have_cmov                       = false;        // target has CMOV instructions ?
                    168: static bool            have_lahf_lm            = true;         // target has LAHF supported in long mode ?
                    169: static bool            have_rat_stall          = true;         // target has partial register stalls ?
                    170: const bool             tune_alignment          = true;         // Tune code alignments for running CPU ?
                    171: const bool             tune_nop_fillers        = true;         // Tune no-op fillers for architecture
                    172: static bool            setzflg_uses_bsf        = false;        // setzflg virtual instruction can use native BSF instruction correctly?
                    173: static int             align_loops                     = 32;           // Align the start of loops
                    174: static int             align_jumps                     = 32;           // Align the start of jumps
                    175: static int             optcount[10]            = {
                    176:        10,             // How often a block has to be executed before it is translated
                    177:        0,              // How often to use naive translation
                    178:        0, 0, 0, 0,
                    179:        -1, -1, -1, -1
                    180: };
                    181: 
                    182: struct op_properties {
                    183:        uae_u8 use_flags;
                    184:        uae_u8 set_flags;
                    185:        uae_u8 is_addx;
                    186:        uae_u8 cflow;
                    187: };
                    188: static op_properties prop[65536];
                    189: 
                    190: static inline int end_block(uae_u32 opcode)
                    191: {
                    192:        return (prop[opcode].cflow & fl_end_block);
                    193: }
                    194: 
                    195: static inline bool is_const_jump(uae_u32 opcode)
                    196: {
                    197:        return (prop[opcode].cflow == fl_const_jump);
                    198: }
                    199: 
                    200: static inline bool may_trap(uae_u32 opcode)
                    201: {
                    202:        return (prop[opcode].cflow & fl_trap);
                    203: }
                    204: 
                    205: static inline unsigned int cft_map (unsigned int f)
                    206: {
                    207: #ifndef HAVE_GET_WORD_UNSWAPPED
                    208:     return f;
                    209: #else
                    210:     return ((f >> 8) & 255) | ((f & 255) << 8);
                    211: #endif
                    212: }
                    213: 
                    214: uae_u8* start_pc_p;
                    215: uae_u32 start_pc;
                    216: uae_u32 current_block_pc_p;
                    217: static uintptr current_block_start_target;
                    218: uae_u32 needed_flags;
                    219: static uintptr next_pc_p;
                    220: static uintptr taken_pc_p;
                    221: static int branch_cc;
                    222: static int redo_current_block;
                    223: 
                    224: int segvcount=0;
                    225: int soft_flush_count=0;
                    226: int hard_flush_count=0;
                    227: int checksum_count=0;
                    228: static uae_u8* current_compile_p=NULL;
                    229: static uae_u8* max_compile_start;
                    230: static uae_u8* compiled_code=NULL;
                    231: static uae_s32 reg_alloc_run;
                    232: const int POPALLSPACE_SIZE = 1024; /* That should be enough space */
                    233: static uae_u8* popallspace=NULL;
                    234: 
                    235: void* pushall_call_handler=NULL;
                    236: static void* popall_do_nothing=NULL;
                    237: static void* popall_exec_nostats=NULL;
                    238: static void* popall_execute_normal=NULL;
                    239: static void* popall_cache_miss=NULL;
                    240: static void* popall_recompile_block=NULL;
                    241: static void* popall_check_checksum=NULL;
                    242: 
                    243: /* The 68k only ever executes from even addresses. So right now, we
                    244:  * waste half the entries in this array
                    245:  * UPDATE: We now use those entries to store the start of the linked
                    246:  * lists that we maintain for each hash result.
                    247:  */
                    248: cacheline cache_tags[TAGSIZE];
                    249: int letit=0;
                    250: blockinfo* hold_bi[MAX_HOLD_BI];
                    251: blockinfo* active;
                    252: blockinfo* dormant;
                    253: 
                    254: /* 68040 */
                    255: extern struct cputbl op_smalltbl_0_nf[];
                    256: extern struct comptbl op_smalltbl_0_comp_nf[];
                    257: extern struct comptbl op_smalltbl_0_comp_ff[];
                    258: 
                    259: /* 68020 + 68881 */
                    260: extern struct cputbl op_smalltbl_1_nf[];
                    261: 
                    262: /* 68020 */
                    263: extern struct cputbl op_smalltbl_2_nf[];
                    264: 
                    265: /* 68010 */
                    266: extern struct cputbl op_smalltbl_3_nf[];
                    267: 
                    268: /* 68000 */
                    269: extern struct cputbl op_smalltbl_4_nf[];
                    270: 
                    271: /* 68000 slow but compatible.  */
                    272: extern struct cputbl op_smalltbl_5_nf[];
                    273: 
                    274: static void flush_icache_hard(int n);
                    275: static void flush_icache_lazy(int n);
                    276: static void flush_icache_none(int n);
                    277: void (*flush_icache)(int n) = flush_icache_none;
                    278: 
                    279: 
                    280: 
                    281: bigstate live;
                    282: smallstate empty_ss;
                    283: smallstate default_ss;
                    284: static int optlev;
                    285: 
                    286: static int writereg(int r, int size);
                    287: static void unlock2(int r);
                    288: static void setlock(int r);
                    289: static int readreg_specific(int r, int size, int spec);
                    290: static int writereg_specific(int r, int size, int spec);
                    291: static void prepare_for_call_1(void);
                    292: static void prepare_for_call_2(void);
                    293: static void align_target(uae_u32 a);
                    294: 
                    295: static uae_s32 nextused[VREGS];
                    296: 
                    297: uae_u32 m68k_pc_offset;
                    298: 
                    299: /* Some arithmetic ooperations can be optimized away if the operands
                    300:  * are known to be constant. But that's only a good idea when the
                    301:  * side effects they would have on the flags are not important. This
                    302:  * variable indicates whether we need the side effects or not
                    303:  */
                    304: uae_u32 needflags=0;
                    305: 
                    306: /* Flag handling is complicated.
                    307:  *
                    308:  * x86 instructions create flags, which quite often are exactly what we
                    309:  * want. So at times, the "68k" flags are actually in the x86 flags.
                    310:  *
                    311:  * Then again, sometimes we do x86 instructions that clobber the x86
                    312:  * flags, but don't represent a corresponding m68k instruction. In that
                    313:  * case, we have to save them.
                    314:  *
                    315:  * We used to save them to the stack, but now store them back directly
                    316:  * into the regflags.cznv of the traditional emulation. Thus some odd
                    317:  * names.
                    318:  *
                    319:  * So flags can be in either of two places (used to be three; boy were
                    320:  * things complicated back then!); And either place can contain either
                    321:  * valid flags or invalid trash (and on the stack, there was also the
                    322:  * option of "nothing at all", now gone). A couple of variables keep
                    323:  * track of the respective states.
                    324:  *
                    325:  * To make things worse, we might or might not be interested in the flags.
                    326:  * by default, we are, but a call to dont_care_flags can change that
                    327:  * until the next call to live_flags. If we are not, pretty much whatever
                    328:  * is in the register and/or the native flags is seen as valid.
                    329:  */
                    330: 
                    331: static __inline__ blockinfo* get_blockinfo(uae_u32 cl)
                    332: {
                    333:     return cache_tags[cl+1].bi;
                    334: }
                    335: 
                    336: static __inline__ blockinfo* get_blockinfo_addr(void* addr)
                    337: {
                    338:     blockinfo*  bi=get_blockinfo(cacheline(addr));
                    339: 
                    340:     while (bi) {
                    341:        if (bi->pc_p==addr)
                    342:            return bi;
                    343:        bi=bi->next_same_cl;
                    344:     }
                    345:     return NULL;
                    346: }
                    347: 
                    348:                
                    349: /*******************************************************************
                    350:  * All sorts of list related functions for all of the lists        *
                    351:  *******************************************************************/
                    352: 
                    353: static __inline__ void remove_from_cl_list(blockinfo* bi)
                    354: {
                    355:     uae_u32 cl=cacheline(bi->pc_p);
                    356: 
                    357:     if (bi->prev_same_cl_p) 
                    358:        *(bi->prev_same_cl_p)=bi->next_same_cl;
                    359:     if (bi->next_same_cl)
                    360:        bi->next_same_cl->prev_same_cl_p=bi->prev_same_cl_p;
                    361:     if (cache_tags[cl+1].bi)
                    362:        cache_tags[cl].handler=cache_tags[cl+1].bi->handler_to_use;
                    363:     else
                    364:        cache_tags[cl].handler=(cpuop_func *)popall_execute_normal;
                    365: }
                    366: 
                    367: static __inline__ void remove_from_list(blockinfo* bi)
                    368: {
                    369:     if (bi->prev_p) 
                    370:        *(bi->prev_p)=bi->next;
                    371:     if (bi->next)
                    372:        bi->next->prev_p=bi->prev_p;
                    373: }
                    374: 
                    375: static __inline__ void remove_from_lists(blockinfo* bi)
                    376: {
                    377:     remove_from_list(bi);
                    378:     remove_from_cl_list(bi);
                    379: }
                    380: 
                    381: static __inline__ void add_to_cl_list(blockinfo* bi)
                    382: {
                    383:     uae_u32 cl=cacheline(bi->pc_p);
                    384:     
                    385:     if (cache_tags[cl+1].bi)
                    386:        cache_tags[cl+1].bi->prev_same_cl_p=&(bi->next_same_cl);
                    387:     bi->next_same_cl=cache_tags[cl+1].bi;
                    388: 
                    389:     cache_tags[cl+1].bi=bi;
                    390:     bi->prev_same_cl_p=&(cache_tags[cl+1].bi);
                    391:        
                    392:     cache_tags[cl].handler=bi->handler_to_use;
                    393: }
                    394: 
                    395: static __inline__ void raise_in_cl_list(blockinfo* bi)
                    396: {
                    397:     remove_from_cl_list(bi);
                    398:     add_to_cl_list(bi);
                    399: }
                    400: 
                    401: static __inline__ void add_to_active(blockinfo* bi)
                    402: {
                    403:     if (active) 
                    404:        active->prev_p=&(bi->next);
                    405:     bi->next=active;
                    406: 
                    407:     active=bi;
                    408:     bi->prev_p=&active;
                    409: }
                    410: 
                    411: static __inline__ void add_to_dormant(blockinfo* bi)
                    412: {
                    413:     if (dormant) 
                    414:        dormant->prev_p=&(bi->next);
                    415:     bi->next=dormant;
                    416: 
                    417:     dormant=bi;
                    418:     bi->prev_p=&dormant;
                    419: }
                    420: 
                    421: static __inline__ void remove_dep(dependency* d)
                    422: {
                    423:     if (d->prev_p) 
                    424:        *(d->prev_p)=d->next;
                    425:     if (d->next)
                    426:        d->next->prev_p=d->prev_p;
                    427:     d->prev_p=NULL;
                    428:     d->next=NULL;
                    429: }
                    430: 
                    431: /* This block's code is about to be thrown away, so it no longer
                    432:    depends on anything else */
                    433: static __inline__ void remove_deps(blockinfo* bi)
                    434: {
                    435:     remove_dep(&(bi->dep[0]));
                    436:     remove_dep(&(bi->dep[1]));
                    437: }
                    438: 
                    439: static __inline__ void adjust_jmpdep(dependency* d, cpuop_func* a)
                    440: {
                    441:     *(d->jmp_off)=(uintptr)a-((uintptr)d->jmp_off+4);
                    442: }
                    443: 
                    444: /********************************************************************
                    445:  * Soft flush handling support functions                            *
                    446:  ********************************************************************/
                    447: 
                    448: static __inline__ void set_dhtu(blockinfo* bi, cpuop_func* dh)
                    449: {
                    450:     //write_log("bi is %p\n",bi);
                    451:     if (dh!=bi->direct_handler_to_use) {
                    452:        dependency* x=bi->deplist;
                    453:        //write_log("bi->deplist=%p\n",bi->deplist);
                    454:        while (x) {
                    455:            //write_log("x is %p\n",x);
                    456:            //write_log("x->next is %p\n",x->next);
                    457:            //write_log("x->prev_p is %p\n",x->prev_p);
                    458:            
                    459:            if (x->jmp_off) {
                    460:                adjust_jmpdep(x,dh);
                    461:            }
                    462:            x=x->next;
                    463:        }
                    464:        bi->direct_handler_to_use=dh;
                    465:     }
                    466: }
                    467: 
                    468: static __inline__ void invalidate_block(blockinfo* bi)
                    469: {
                    470:     int i;
                    471: 
                    472:     bi->optlevel=0;
                    473:     bi->count=optcount[0]-1;
                    474:     bi->handler=NULL;
                    475:     bi->handler_to_use=(cpuop_func *)popall_execute_normal;
                    476:     bi->direct_handler=NULL;
                    477:     set_dhtu(bi,bi->direct_pen);
                    478:     bi->needed_flags=0xff;
                    479:        bi->status=BI_INVALID;
                    480:     for (i=0;i<2;i++) {
                    481:        bi->dep[i].jmp_off=NULL;
                    482:        bi->dep[i].target=NULL;
                    483:     }
                    484:     remove_deps(bi);
                    485: }
                    486: 
                    487: static __inline__ void create_jmpdep(blockinfo* bi, int i, uae_u32* jmpaddr, uae_u32 target)
                    488: {
                    489:     blockinfo*  tbi=get_blockinfo_addr((void*)(uintptr)target);
                    490:     
                    491:     Dif(!tbi) {
                    492:        write_log("Could not create jmpdep!\n");
                    493:        abort();
                    494:     }
                    495:     bi->dep[i].jmp_off=jmpaddr;
                    496:        bi->dep[i].source=bi;
                    497:     bi->dep[i].target=tbi;
                    498:     bi->dep[i].next=tbi->deplist;
                    499:     if (bi->dep[i].next) 
                    500:        bi->dep[i].next->prev_p=&(bi->dep[i].next);
                    501:     bi->dep[i].prev_p=&(tbi->deplist);
                    502:     tbi->deplist=&(bi->dep[i]);
                    503: }
                    504: 
                    505: static __inline__ void block_need_recompile(blockinfo * bi)
                    506: {
                    507:   uae_u32 cl = cacheline(bi->pc_p);
                    508:   
                    509:   set_dhtu(bi, bi->direct_pen);
                    510:   bi->direct_handler = bi->direct_pen;
                    511:   
                    512:   bi->handler_to_use = (cpuop_func *)popall_execute_normal;
                    513:   bi->handler = (cpuop_func *)popall_execute_normal;
                    514:   if (bi == cache_tags[cl + 1].bi)
                    515:        cache_tags[cl].handler = (cpuop_func *)popall_execute_normal;
                    516:   bi->status = BI_NEED_RECOMP;
                    517: }
                    518: 
                    519: static __inline__ void mark_callers_recompile(blockinfo * bi)
                    520: {
                    521:   dependency *x = bi->deplist;
                    522: 
                    523:   while (x)    {
                    524:        dependency *next = x->next;     /* This disappears when we mark for
                    525:                                                                 * recompilation and thus remove the
                    526:                                                                 * blocks from the lists */
                    527:        if (x->jmp_off) {
                    528:          blockinfo *cbi = x->source;
                    529: 
                    530:          Dif(cbi->status == BI_INVALID) {
                    531:                // write_log("invalid block in dependency list\n"); // FIXME?
                    532:                // abort();
                    533:          }
                    534:          if (cbi->status == BI_ACTIVE || cbi->status == BI_NEED_CHECK) {
                    535:                block_need_recompile(cbi);
                    536:                mark_callers_recompile(cbi);
                    537:          }
                    538:          else if (cbi->status == BI_COMPILING) {
                    539:                redo_current_block = 1;
                    540:          }
                    541:          else if (cbi->status == BI_NEED_RECOMP) {
                    542:                /* nothing */
                    543:          }
                    544:          else {
                    545:                //write_log("Status %d in mark_callers\n",cbi->status); // FIXME?
                    546:          }
                    547:        }
                    548:        x = next;
                    549:   }
                    550: }
                    551: 
                    552: static __inline__ blockinfo* get_blockinfo_addr_new(void* addr, int setstate)
                    553: {
                    554:     blockinfo*  bi=get_blockinfo_addr(addr);
                    555:     int i;
                    556: 
                    557:     if (!bi) {
                    558:        for (i=0;i<MAX_HOLD_BI && !bi;i++) {
                    559:            if (hold_bi[i]) {
                    560:                uae_u32 cl=cacheline(addr);
                    561:                
                    562:                bi=hold_bi[i];
                    563:                hold_bi[i]=NULL;
                    564:                bi->pc_p=(uae_u8 *)addr;
                    565:                invalidate_block(bi);
                    566:                add_to_active(bi);
                    567:                add_to_cl_list(bi);
                    568:                
                    569:            }
                    570:        }
                    571:     }
                    572:     if (!bi) {
                    573:        write_log("Looking for blockinfo, can't find free one\n");
                    574:        abort();
                    575:     }
                    576:     return bi;
                    577: }
                    578: 
                    579: static void prepare_block(blockinfo* bi);
                    580: 
                    581: /* Managment of blockinfos.
                    582: 
                    583:    A blockinfo struct is allocated whenever a new block has to be
                    584:    compiled. If the list of free blockinfos is empty, we allocate a new
                    585:    pool of blockinfos and link the newly created blockinfos altogether
                    586:    into the list of free blockinfos. Otherwise, we simply pop a structure
                    587:    off the free list.
                    588: 
                    589:    Blockinfo are lazily deallocated, i.e. chained altogether in the
                    590:    list of free blockinfos whenvever a translation cache flush (hard or
                    591:    soft) request occurs.
                    592: */
                    593: 
                    594: template< class T >
                    595: class LazyBlockAllocator
                    596: {
                    597:        enum {
                    598:                kPoolSize = 1 + 4096 / sizeof(T)
                    599:        };
                    600:        struct Pool {
                    601:                T chunk[kPoolSize];
                    602:                Pool * next;
                    603:        };
                    604:        Pool * mPools;
                    605:        T * mChunks;
                    606: public:
                    607:        LazyBlockAllocator() : mPools(0), mChunks(0) { }
                    608:        ~LazyBlockAllocator();
                    609:        T * acquire();
                    610:        void release(T * const);
                    611: };
                    612: 
                    613: template< class T >
                    614: LazyBlockAllocator<T>::~LazyBlockAllocator()
                    615: {
                    616:        Pool * currentPool = mPools;
                    617:        while (currentPool) {
                    618:                Pool * deadPool = currentPool;
                    619:                currentPool = currentPool->next;
                    620:                free(deadPool);
                    621:        }
                    622: }
                    623: 
                    624: template< class T >
                    625: T * LazyBlockAllocator<T>::acquire()
                    626: {
                    627:        if (!mChunks) {
                    628:                // There is no chunk left, allocate a new pool and link the
                    629:                // chunks into the free list
                    630:                Pool * newPool = (Pool *)malloc(sizeof(Pool));
                    631:                for (T * chunk = &newPool->chunk[0]; chunk < &newPool->chunk[kPoolSize]; chunk++) {
                    632:                        chunk->next = mChunks;
                    633:                        mChunks = chunk;
                    634:                }
                    635:                newPool->next = mPools;
                    636:                mPools = newPool;
                    637:        }
                    638:        T * chunk = mChunks;
                    639:        mChunks = chunk->next;
                    640:        return chunk;
                    641: }
                    642: 
                    643: template< class T >
                    644: void LazyBlockAllocator<T>::release(T * const chunk)
                    645: {
                    646:        chunk->next = mChunks;
                    647:        mChunks = chunk;
                    648: }
                    649: 
                    650: template< class T >
                    651: class HardBlockAllocator
                    652: {
                    653: public:
                    654:        T * acquire() {
                    655:                T * data = (T *)current_compile_p;
                    656:                current_compile_p += sizeof(T);
                    657:                return data;
                    658:        }
                    659: 
                    660:        void release(T * const chunk) {
                    661:                // Deallocated on invalidation
                    662:        }
                    663: };
                    664: 
                    665: #if USE_SEPARATE_BIA
                    666: static LazyBlockAllocator<blockinfo> BlockInfoAllocator;
                    667: static LazyBlockAllocator<checksum_info> ChecksumInfoAllocator;
                    668: #else
                    669: static HardBlockAllocator<blockinfo> BlockInfoAllocator;
                    670: static HardBlockAllocator<checksum_info> ChecksumInfoAllocator;
                    671: #endif
                    672: 
                    673: static __inline__ checksum_info *alloc_checksum_info(void)
                    674: {
                    675:        checksum_info *csi = ChecksumInfoAllocator.acquire();
                    676:        csi->next = NULL;
                    677:        return csi;
                    678: }
                    679: 
                    680: static __inline__ void free_checksum_info(checksum_info *csi)
                    681: {
                    682:        csi->next = NULL;
                    683:        ChecksumInfoAllocator.release(csi);
                    684: }
                    685: 
                    686: static __inline__ void free_checksum_info_chain(checksum_info *csi)
                    687: {
                    688:        while (csi != NULL) {
                    689:                checksum_info *csi2 = csi->next;
                    690:                free_checksum_info(csi);
                    691:                csi = csi2;
                    692:        }
                    693: }
                    694: 
                    695: static __inline__ blockinfo *alloc_blockinfo(void)
                    696: {
                    697:        blockinfo *bi = BlockInfoAllocator.acquire();
                    698: #if USE_CHECKSUM_INFO
                    699:        bi->csi = NULL;
                    700: #endif
                    701:        return bi;
                    702: }
                    703: 
                    704: static __inline__ void free_blockinfo(blockinfo *bi)
                    705: {
                    706: #if USE_CHECKSUM_INFO
                    707:        free_checksum_info_chain(bi->csi);
                    708:        bi->csi = NULL;
                    709: #endif
                    710:        BlockInfoAllocator.release(bi);
                    711: }
                    712: 
                    713: static __inline__ void alloc_blockinfos(void) 
                    714: {
                    715:     int i;
                    716:     blockinfo* bi;
                    717: 
                    718:     for (i=0;i<MAX_HOLD_BI;i++) {
                    719:        if (hold_bi[i])
                    720:            return;
                    721:        bi=hold_bi[i]=alloc_blockinfo();
                    722:        prepare_block(bi);
                    723:     }
                    724: }
                    725: 
                    726: /********************************************************************
                    727:  * Functions to emit data into memory, and other general support    *
                    728:  ********************************************************************/
                    729: 
                    730: static uae_u8* target;
                    731: 
                    732: static  void emit_init(void)
                    733: {
                    734: }
                    735: 
                    736: static __inline__ void emit_byte(uae_u8 x)
                    737: {
                    738:     *target++=x;
                    739: }
                    740: 
                    741: static __inline__ void emit_word(uae_u16 x)
                    742: {
                    743:     *((uae_u16*)target)=x;
                    744:     target+=2;
                    745: }
                    746: 
                    747: static __inline__ void emit_long(uae_u32 x)
                    748: {
                    749:     *((uae_u32*)target)=x;
                    750:     target+=4;
                    751: }
                    752: 
                    753: static __inline__ void emit_quad(uae_u64 x)
                    754: {
                    755:     *((uae_u64*)target)=x;
                    756:     target+=8;
                    757: }
                    758: 
                    759: static __inline__ void emit_block(const uae_u8 *block, uae_u32 blocklen)
                    760: {
                    761:        memcpy((uae_u8 *)target,block,blocklen);
                    762:        target+=blocklen;
                    763: }
                    764: 
                    765: static __inline__ uae_u32 reverse32(uae_u32 v)
                    766: {
                    767: #if 1
                    768:        // gb-- We have specialized byteswapping functions, just use them
                    769:        return do_byteswap_32(v);
                    770: #else
                    771:        return ((v>>24)&0xff) | ((v>>8)&0xff00) | ((v<<8)&0xff0000) | ((v<<24)&0xff000000);
                    772: #endif
                    773: }
                    774: 
                    775: /********************************************************************
                    776:  * Getting the information about the target CPU                     *
                    777:  ********************************************************************/
                    778: 
                    779: #include "codegen_x86.cpp"
                    780: 
                    781: void set_target(uae_u8* t)
                    782: {
                    783:     target=t;
                    784: }
                    785: 
                    786: static __inline__ uae_u8* get_target_noopt(void)
                    787: {
                    788:     return target;
                    789: }
                    790: 
                    791: __inline__ uae_u8* get_target(void)
                    792: {
                    793:     return get_target_noopt();
                    794: }
                    795: 
                    796: 
                    797: /********************************************************************
                    798:  * Flags status handling. EMIT TIME!                                *
                    799:  ********************************************************************/
                    800: 
                    801: static void bt_l_ri_noclobber(R4 r, IMM i);
                    802: 
                    803: static void make_flags_live_internal(void)
                    804: {
                    805:     if (live.flags_in_flags==VALID)
                    806:        return;
                    807:     Dif (live.flags_on_stack==TRASH) {
                    808:        write_log("Want flags, got something on stack, but it is TRASH\n");
                    809:        abort();
                    810:     }
                    811:     if (live.flags_on_stack==VALID) {
                    812:        int tmp;
                    813:        tmp=readreg_specific(FLAGTMP,4,FLAG_NREG2);
                    814:        raw_reg_to_flags(tmp);
                    815:        unlock2(tmp);
                    816: 
                    817:        live.flags_in_flags=VALID;
                    818:        return;
                    819:     }
                    820:     write_log("Huh? live.flags_in_flags=%d, live.flags_on_stack=%d, but need to make live\n",
                    821:           live.flags_in_flags,live.flags_on_stack);
                    822:     abort();
                    823: }
                    824: 
                    825: static void flags_to_stack(void)
                    826: {
                    827:     if (live.flags_on_stack==VALID)
                    828:        return;
                    829:     if (!live.flags_are_important) {
                    830:        live.flags_on_stack=VALID;
                    831:        return;
                    832:     }
                    833:     Dif (live.flags_in_flags!=VALID)
                    834:        abort();
                    835:     else  {
                    836:        int tmp;
                    837:        tmp=writereg_specific(FLAGTMP,4,FLAG_NREG1);
                    838:        raw_flags_to_reg(tmp);
                    839:        unlock2(tmp);
                    840:     }
                    841:     live.flags_on_stack=VALID;
                    842: }
                    843: 
                    844: static __inline__ void clobber_flags(void)
                    845: {
                    846:     if (live.flags_in_flags==VALID && live.flags_on_stack!=VALID)
                    847:        flags_to_stack();
                    848:     live.flags_in_flags=TRASH;
                    849: }
                    850: 
                    851: /* Prepare for leaving the compiled stuff */
                    852: static __inline__ void flush_flags(void)
                    853: {
                    854:     flags_to_stack();
                    855:     return;
                    856: }
                    857: 
                    858: int touchcnt;
                    859: 
                    860: /********************************************************************
                    861:  * Partial register flushing for optimized calls                    *
                    862:  ********************************************************************/
                    863: 
                    864: struct regusage {
                    865:        uae_u16 rmask;
                    866:        uae_u16 wmask;
                    867: };
                    868: 
                    869: static inline void ru_set(uae_u16 *mask, int reg)
                    870: {
                    871: #if USE_OPTIMIZED_CALLS
                    872:        *mask |= 1 << reg;
                    873: #endif
                    874: }
                    875: 
                    876: static inline bool ru_get(const uae_u16 *mask, int reg)
                    877: {
                    878: #if USE_OPTIMIZED_CALLS
                    879:        return (*mask & (1 << reg));
                    880: #else
                    881:        /* Default: instruction reads & write to register */
                    882:        return true;
                    883: #endif
                    884: }
                    885: 
                    886: static inline void ru_set_read(regusage *ru, int reg)
                    887: {
                    888:        ru_set(&ru->rmask, reg);
                    889: }
                    890: 
                    891: static inline void ru_set_write(regusage *ru, int reg)
                    892: {
                    893:        ru_set(&ru->wmask, reg);
                    894: }
                    895: 
                    896: static inline bool ru_read_p(const regusage *ru, int reg)
                    897: {
                    898:        return ru_get(&ru->rmask, reg);
                    899: }
                    900: 
                    901: static inline bool ru_write_p(const regusage *ru, int reg)
                    902: {
                    903:        return ru_get(&ru->wmask, reg);
                    904: }
                    905: 
                    906: static void ru_fill_ea(regusage *ru, int reg, amodes mode,
                    907:                                           wordsizes size, int write_mode)
                    908: {
                    909:        switch (mode) {
                    910:        case Areg:
                    911:                reg += 8;
                    912:                /* fall through */
                    913:        case Dreg:
                    914:                ru_set(write_mode ? &ru->wmask : &ru->rmask, reg);
                    915:                break;
                    916:        case Ad16:
                    917:                /* skip displacment */
                    918:                m68k_pc_offset += 2;
                    919:        case Aind:
                    920:        case Aipi:
                    921:        case Apdi:
                    922:                ru_set_read(ru, reg+8);
                    923:                break;
                    924:        case Ad8r:
                    925:                ru_set_read(ru, reg+8);
                    926:                /* fall through */
                    927:        case PC8r: {
                    928:                uae_u16 dp = comp_get_iword((m68k_pc_offset+=2)-2);
                    929:                reg = (dp >> 12) & 15;
                    930:                ru_set_read(ru, reg);
                    931:                if (dp & 0x100)
                    932:                        m68k_pc_offset += (((dp & 0x30) >> 3) & 7) + ((dp & 3) * 2);
                    933:                break;
                    934:        }
                    935:        case PC16:
                    936:        case absw:
                    937:        case imm0:
                    938:        case imm1:
                    939:                m68k_pc_offset += 2;
                    940:                break;
                    941:        case absl:
                    942:        case imm2:
                    943:                m68k_pc_offset += 4;
                    944:                break;
                    945:        case immi:
                    946:                m68k_pc_offset += (size == sz_long) ? 4 : 2;
                    947:                break;
                    948:        }
                    949: }
                    950: 
                    951: /* TODO: split into a static initialization part and a dynamic one
                    952:    (instructions depending on extension words) */
                    953: static void ru_fill(regusage *ru, uae_u32 opcode)
                    954: {
                    955:        m68k_pc_offset += 2;
                    956: 
                    957:        /* Default: no register is used or written to */
                    958:        ru->rmask = 0;
                    959:        ru->wmask = 0;
                    960: 
                    961:        uae_u32 real_opcode = cft_map(opcode);
                    962:        struct instr *dp = &table68k[real_opcode];
                    963: 
                    964:        bool rw_dest = true;
                    965:        bool handled = false;
                    966: 
                    967:        /* Handle some instructions specifically */
                    968:        uae_u16 reg, ext;
                    969:        switch (dp->mnemo) {
                    970:        case i_BFCHG:
                    971:        case i_BFCLR:
                    972:        case i_BFEXTS:
                    973:        case i_BFEXTU:
                    974:        case i_BFFFO:
                    975:        case i_BFINS:
                    976:        case i_BFSET:
                    977:        case i_BFTST:
                    978:                ext = comp_get_iword((m68k_pc_offset+=2)-2);
                    979:                if (ext & 0x800) ru_set_read(ru, (ext >> 6) & 7);
                    980:                if (ext & 0x020) ru_set_read(ru, ext & 7);
                    981:                ru_fill_ea(ru, dp->dreg, (amodes)dp->dmode, (wordsizes)dp->size, 1);
                    982:                if (dp->dmode == Dreg)
                    983:                        ru_set_read(ru, dp->dreg);
                    984:                switch (dp->mnemo) {
                    985:                case i_BFEXTS:
                    986:                case i_BFEXTU:
                    987:                case i_BFFFO:
                    988:                        ru_set_write(ru, (ext >> 12) & 7);
                    989:                        break;
                    990:                case i_BFINS:
                    991:                        ru_set_read(ru, (ext >> 12) & 7);
                    992:                        /* fall through */
                    993:                case i_BFCHG:
                    994:                case i_BFCLR:
                    995:                case i_BSET:
                    996:                        if (dp->dmode == Dreg)
                    997:                                ru_set_write(ru, dp->dreg);
                    998:                        break;
                    999:                }
                   1000:                handled = true;
                   1001:                rw_dest = false;
                   1002:                break;
                   1003: 
                   1004:        case i_BTST:
                   1005:                rw_dest = false;
                   1006:                break;
                   1007: 
                   1008:        case i_CAS:
                   1009:        {
                   1010:                ext = comp_get_iword((m68k_pc_offset+=2)-2);
                   1011:                int Du = ext & 7;
                   1012:                ru_set_read(ru, Du);
                   1013:                int Dc = (ext >> 6) & 7;
                   1014:                ru_set_read(ru, Dc);
                   1015:                ru_set_write(ru, Dc);
                   1016:                break;
                   1017:        }
                   1018:        case i_CAS2:
                   1019:        {
                   1020:                int Dc1, Dc2, Du1, Du2, Rn1, Rn2;
                   1021:                ext = comp_get_iword((m68k_pc_offset+=2)-2);
                   1022:                Rn1 = (ext >> 12) & 15;
                   1023:                Du1 = (ext >> 6) & 7;
                   1024:                Dc1 = ext & 7;
                   1025:                ru_set_read(ru, Rn1);
                   1026:                ru_set_read(ru, Du1);
                   1027:                ru_set_read(ru, Dc1);
                   1028:                ru_set_write(ru, Dc1);
                   1029:                ext = comp_get_iword((m68k_pc_offset+=2)-2);
                   1030:                Rn2 = (ext >> 12) & 15;
                   1031:                Du2 = (ext >> 6) & 7;
                   1032:                Dc2 = ext & 7;
                   1033:                ru_set_read(ru, Rn2);
                   1034:                ru_set_read(ru, Du2);
                   1035:                ru_set_write(ru, Dc2);
                   1036:                break;
                   1037:        }
                   1038:        case i_DIVL: case i_MULL:
                   1039:                m68k_pc_offset += 2;
                   1040:                break;
                   1041:        case i_LEA:
                   1042:        case i_MOVE: case i_MOVEA: case i_MOVE16:
                   1043:                rw_dest = false;
                   1044:                break;
                   1045:        case i_PACK: case i_UNPK:
                   1046:                rw_dest = false;
                   1047:                m68k_pc_offset += 2;
                   1048:                break;
                   1049:        case i_TRAPcc:
                   1050:                m68k_pc_offset += (dp->size == sz_long) ? 4 : 2;
                   1051:                break;
                   1052:        case i_RTR:
                   1053:                /* do nothing, just for coverage debugging */
                   1054:                break;
                   1055:        /* TODO: handle EXG instruction */
                   1056:        }
                   1057: 
                   1058:        /* Handle A-Traps better */
                   1059:        if ((real_opcode & 0xf000) == 0xa000) {
                   1060:                handled = true;
                   1061:        }
                   1062: 
                   1063:        /* Handle EmulOps better */
                   1064:        if ((real_opcode & 0xff00) == 0x7100) {
                   1065:                handled = true;
                   1066:                ru->rmask = 0xffff;
                   1067:                ru->wmask = 0;
                   1068:        }
                   1069: 
                   1070:        if (dp->suse && !handled)
                   1071:                ru_fill_ea(ru, dp->sreg, (amodes)dp->smode, (wordsizes)dp->size, 0);
                   1072: 
                   1073:        if (dp->duse && !handled)
                   1074:                ru_fill_ea(ru, dp->dreg, (amodes)dp->dmode, (wordsizes)dp->size, 1);
                   1075: 
                   1076:        if (rw_dest)
                   1077:                ru->rmask |= ru->wmask;
                   1078: 
                   1079:        handled = handled || dp->suse || dp->duse;
                   1080: 
                   1081:        /* Mark all registers as used/written if the instruction may trap */
                   1082:        if (may_trap(opcode)) {
                   1083:                handled = true;
                   1084:                ru->rmask = 0xffff;
                   1085:                ru->wmask = 0xffff;
                   1086:        }
                   1087: 
                   1088:        if (!handled) {
                   1089:                write_log("ru_fill: %04x = { %04x, %04x }\n",
                   1090:                                  real_opcode, ru->rmask, ru->wmask);
                   1091:                abort();
                   1092:        }
                   1093: }
                   1094: 
                   1095: /********************************************************************
                   1096:  * register allocation per block logging                            *
                   1097:  ********************************************************************/
                   1098: 
                   1099: static uae_s8 vstate[VREGS];
                   1100: static uae_s8 vwritten[VREGS];
                   1101: static uae_s8 nstate[N_REGS];
                   1102: 
                   1103: #define L_UNKNOWN -127
                   1104: #define L_UNAVAIL -1
                   1105: #define L_NEEDED -2
                   1106: #define L_UNNEEDED -3
                   1107: 
                   1108: static __inline__ void big_to_small_state(bigstate * b, smallstate * s)
                   1109: {
                   1110:   int i;
                   1111:        
                   1112:   for (i = 0; i < VREGS; i++)
                   1113:        s->virt[i] = vstate[i];
                   1114:   for (i = 0; i < N_REGS; i++)
                   1115:        s->nat[i] = nstate[i];
                   1116: }
                   1117: 
                   1118: static __inline__ int callers_need_recompile(bigstate * b, smallstate * s)
                   1119: {
                   1120:   int i;
                   1121:   int reverse = 0;
                   1122: 
                   1123:   for (i = 0; i < VREGS; i++) {
                   1124:        if (vstate[i] != L_UNNEEDED && s->virt[i] == L_UNNEEDED)
                   1125:          return 1;
                   1126:        if (vstate[i] == L_UNNEEDED && s->virt[i] != L_UNNEEDED)
                   1127:          reverse++;
                   1128:   }
                   1129:   for (i = 0; i < N_REGS; i++) {
                   1130:        if (nstate[i] >= 0 && nstate[i] != s->nat[i])
                   1131:          return 1;
                   1132:        if (nstate[i] < 0 && s->nat[i] >= 0)
                   1133:          reverse++;
                   1134:   }
                   1135:   if (reverse >= 2 && USE_MATCH)
                   1136:        return 1;       /* In this case, it might be worth recompiling the
                   1137:                                 * callers */
                   1138:   return 0;
                   1139: }
                   1140: 
                   1141: static __inline__ void log_startblock(void)
                   1142: {
                   1143:   int i;
                   1144: 
                   1145:   for (i = 0; i < VREGS; i++) {
                   1146:        vstate[i] = L_UNKNOWN;
                   1147:        vwritten[i] = 0;
                   1148:   }
                   1149:   for (i = 0; i < N_REGS; i++)
                   1150:        nstate[i] = L_UNKNOWN;
                   1151: }
                   1152: 
                   1153: /* Using an n-reg for a temp variable */
                   1154: static __inline__ void log_isused(int n)
                   1155: {
                   1156:   if (nstate[n] == L_UNKNOWN)
                   1157:        nstate[n] = L_UNAVAIL;
                   1158: }
                   1159: 
                   1160: static __inline__ void log_visused(int r)
                   1161: {
                   1162:   if (vstate[r] == L_UNKNOWN)
                   1163:        vstate[r] = L_NEEDED;
                   1164: }
                   1165: 
                   1166: static __inline__ void do_load_reg(int n, int r)
                   1167: {
                   1168:   if (r == FLAGTMP)
                   1169:        raw_load_flagreg(n, r);
                   1170:   else if (r == FLAGX)
                   1171:        raw_load_flagx(n, r);
                   1172:   else
                   1173:        raw_mov_l_rm(n, (uintptr) live.state[r].mem);
                   1174: }
                   1175: 
                   1176: static __inline__ void check_load_reg(int n, int r)
                   1177: {
                   1178:   raw_mov_l_rm(n, (uintptr) live.state[r].mem);
                   1179: }
                   1180: 
                   1181: static __inline__ void log_vwrite(int r)
                   1182: {
                   1183:   vwritten[r] = 1;
                   1184: }
                   1185: 
                   1186: /* Using an n-reg to hold a v-reg */
                   1187: static __inline__ void log_isreg(int n, int r)
                   1188: {
                   1189:   static int count = 0;
                   1190:   
                   1191:   if (nstate[n] == L_UNKNOWN && r < 16 && !vwritten[r] && USE_MATCH)
                   1192:        nstate[n] = r;
                   1193:   else {
                   1194:        do_load_reg(n, r);
                   1195:        if (nstate[n] == L_UNKNOWN)
                   1196:          nstate[n] = L_UNAVAIL;
                   1197:   }
                   1198:   if (vstate[r] == L_UNKNOWN)
                   1199:        vstate[r] = L_NEEDED;
                   1200: }
                   1201: 
                   1202: static __inline__ void log_clobberreg(int r)
                   1203: {
                   1204:   if (vstate[r] == L_UNKNOWN)
                   1205:        vstate[r] = L_UNNEEDED;
                   1206: }
                   1207: 
                   1208: /* This ends all possibility of clever register allocation */
                   1209: 
                   1210: static __inline__ void log_flush(void)
                   1211: {
                   1212:   int i;
                   1213:   
                   1214:   for (i = 0; i < VREGS; i++)
                   1215:        if (vstate[i] == L_UNKNOWN)
                   1216:          vstate[i] = L_NEEDED;
                   1217:   for (i = 0; i < N_REGS; i++)
                   1218:        if (nstate[i] == L_UNKNOWN)
                   1219:          nstate[i] = L_UNAVAIL;
                   1220: }
                   1221: 
                   1222: static __inline__ void log_dump(void)
                   1223: {
                   1224:   int i;
                   1225:   
                   1226:   return;
                   1227:   
                   1228:   write_log("----------------------\n");
                   1229:   for (i = 0; i < N_REGS; i++) {
                   1230:        switch (nstate[i]) {
                   1231:        case L_UNKNOWN:
                   1232:          write_log("Nat %d : UNKNOWN\n", i);
                   1233:          break;
                   1234:        case L_UNAVAIL:
                   1235:          write_log("Nat %d : UNAVAIL\n", i);
                   1236:          break;
                   1237:        default:
                   1238:          write_log("Nat %d : %d\n", i, nstate[i]);
                   1239:          break;
                   1240:        }
                   1241:   }
                   1242:   for (i = 0; i < VREGS; i++) {
                   1243:        if (vstate[i] == L_UNNEEDED)
                   1244:          write_log("Virt %d: UNNEEDED\n", i);
                   1245:   }
                   1246: }
                   1247: 
                   1248: /********************************************************************
                   1249:  * register status handling. EMIT TIME!                             *
                   1250:  ********************************************************************/
                   1251: 
                   1252: static __inline__ void set_status(int r, int status)
                   1253: {
                   1254:        if (status == ISCONST)
                   1255:                log_clobberreg(r);
                   1256:     live.state[r].status=status;
                   1257: }
                   1258: 
                   1259: static __inline__ int isinreg(int r)
                   1260: {
                   1261:     return live.state[r].status==CLEAN || live.state[r].status==DIRTY;
                   1262: }
                   1263: 
                   1264: static __inline__ void adjust_nreg(int r, uae_u32 val)
                   1265: {
                   1266:     if (!val)
                   1267:        return;
                   1268:     raw_lea_l_brr(r,r,val);
                   1269: }
                   1270: 
                   1271: static  void tomem(int r)
                   1272: {
                   1273:     int rr=live.state[r].realreg;
                   1274: 
                   1275:     if (isinreg(r)) {
                   1276:        if (live.state[r].val && live.nat[rr].nholds==1
                   1277:                && !live.nat[rr].locked) {
                   1278:            // write_log("RemovingA offset %x from reg %d (%d) at %p\n",
                   1279:            //   live.state[r].val,r,rr,target); 
                   1280:            adjust_nreg(rr,live.state[r].val);
                   1281:            live.state[r].val=0;
                   1282:            live.state[r].dirtysize=4;
                   1283:            set_status(r,DIRTY);
                   1284:        }
                   1285:     }
                   1286: 
                   1287:     if (live.state[r].status==DIRTY) {
                   1288:        switch (live.state[r].dirtysize) {
                   1289:         case 1: raw_mov_b_mr((uintptr)live.state[r].mem,rr); break;
                   1290:         case 2: raw_mov_w_mr((uintptr)live.state[r].mem,rr); break;
                   1291:         case 4: raw_mov_l_mr((uintptr)live.state[r].mem,rr); break;
                   1292:         default: abort();
                   1293:        }
                   1294:        log_vwrite(r);
                   1295:        set_status(r,CLEAN);
                   1296:        live.state[r].dirtysize=0;
                   1297:     }
                   1298: }
                   1299: 
                   1300: static __inline__ int isconst(int r)
                   1301: {
                   1302:     return live.state[r].status==ISCONST;
                   1303: }
                   1304: 
                   1305: int is_const(int r)
                   1306: {
                   1307:     return isconst(r);
                   1308: }
                   1309: 
                   1310: static __inline__ void writeback_const(int r)
                   1311: {
                   1312:     if (!isconst(r))
                   1313:        return;
                   1314:     Dif (live.state[r].needflush==NF_HANDLER) {
                   1315:        write_log("Trying to write back constant NF_HANDLER!\n");
                   1316:        abort();
                   1317:     }
                   1318: 
                   1319:     raw_mov_l_mi((uintptr)live.state[r].mem,live.state[r].val);
                   1320:        log_vwrite(r);
                   1321:     live.state[r].val=0;
                   1322:     set_status(r,INMEM);
                   1323: }
                   1324: 
                   1325: static __inline__ void tomem_c(int r)
                   1326: {
                   1327:     if (isconst(r)) {
                   1328:        writeback_const(r);
                   1329:     }
                   1330:     else
                   1331:        tomem(r);
                   1332: }
                   1333: 
                   1334: static  void evict(int r)
                   1335: {
                   1336:     int rr;
                   1337: 
                   1338:     if (!isinreg(r))
                   1339:        return;
                   1340:     tomem(r);
                   1341:     rr=live.state[r].realreg;
                   1342: 
                   1343:     Dif (live.nat[rr].locked &&
                   1344:        live.nat[rr].nholds==1) {
                   1345:        write_log("register %d in nreg %d is locked!\n",r,live.state[r].realreg);
                   1346:        abort();
                   1347:     }
                   1348: 
                   1349:     live.nat[rr].nholds--;
                   1350:     if (live.nat[rr].nholds!=live.state[r].realind) { /* Was not last */
                   1351:        int topreg=live.nat[rr].holds[live.nat[rr].nholds];
                   1352:        int thisind=live.state[r].realind;
                   1353:        
                   1354:        live.nat[rr].holds[thisind]=topreg;
                   1355:        live.state[topreg].realind=thisind;
                   1356:     }
                   1357:     live.state[r].realreg=-1;
                   1358:     set_status(r,INMEM);
                   1359: }
                   1360: 
                   1361: static __inline__ void free_nreg(int r)
                   1362: {
                   1363:     int i=live.nat[r].nholds;
                   1364: 
                   1365:     while (i) {
                   1366:        int vr;
                   1367: 
                   1368:        --i;
                   1369:        vr=live.nat[r].holds[i];
                   1370:        evict(vr);
                   1371:     }
                   1372:     Dif (live.nat[r].nholds!=0) {
                   1373:        write_log("Failed to free nreg %d, nholds is %d\n",r,live.nat[r].nholds);
                   1374:        abort();
                   1375:     }
                   1376: }
                   1377: 
                   1378: /* Use with care! */
                   1379: static __inline__ void isclean(int r)
                   1380: {
                   1381:     if (!isinreg(r))
                   1382:        return;
                   1383:     live.state[r].validsize=4;
                   1384:     live.state[r].dirtysize=0;
                   1385:     live.state[r].val=0;
                   1386:     set_status(r,CLEAN);
                   1387: }
                   1388: 
                   1389: static __inline__ void disassociate(int r)
                   1390: {
                   1391:     isclean(r);
                   1392:     evict(r);
                   1393: }
                   1394: 
                   1395: static __inline__ void set_const(int r, uae_u32 val)
                   1396: {
                   1397:     disassociate(r);
                   1398:     live.state[r].val=val;
                   1399:     set_status(r,ISCONST);
                   1400: }
                   1401: 
                   1402: static __inline__ uae_u32 get_offset(int r)
                   1403: {
                   1404:     return live.state[r].val;
                   1405: }
                   1406: 
                   1407: static  int alloc_reg_hinted(int r, int size, int willclobber, int hint)
                   1408: {
                   1409:     int bestreg;
                   1410:     uae_s32 when;
                   1411:     int i;
                   1412:     uae_s32 badness=0; /* to shut up gcc */
                   1413:     bestreg=-1;
                   1414:     when=2000000000;
                   1415: 
                   1416:     /* XXX use a regalloc_order table? */
                   1417:     for (i=0;i<N_REGS;i++) {
                   1418:        badness=live.nat[i].touched;
                   1419:        if (live.nat[i].nholds==0)
                   1420:            badness=0;
                   1421:        if (i==hint)  
                   1422:            badness-=200000000;
                   1423:        if (!live.nat[i].locked && badness<when) {
                   1424:            if ((size==1 && live.nat[i].canbyte) ||
                   1425:                (size==2 && live.nat[i].canword) ||
                   1426:                (size==4)) {
                   1427:                bestreg=i;
                   1428:                when=badness;
                   1429:                if (live.nat[i].nholds==0 && hint<0)
                   1430:                    break;
                   1431:                if (i==hint)
                   1432:                    break;
                   1433:            }
                   1434:        }
                   1435:     }
                   1436:     Dif (bestreg==-1)
                   1437:        abort();
                   1438: 
                   1439:     if (live.nat[bestreg].nholds>0) {
                   1440:        free_nreg(bestreg);
                   1441:     }
                   1442:     if (isinreg(r)) {
                   1443:        int rr=live.state[r].realreg;
                   1444:        /* This will happen if we read a partially dirty register at a
                   1445:           bigger size */
                   1446:        Dif (willclobber || live.state[r].validsize>=size)
                   1447:            abort();
                   1448:        Dif (live.nat[rr].nholds!=1)
                   1449:            abort();
                   1450:        if (size==4 && live.state[r].validsize==2) {
                   1451:                log_isused(bestreg);
                   1452:                log_visused(r);
                   1453:            raw_mov_l_rm(bestreg,(uintptr)live.state[r].mem);
                   1454:            raw_bswap_32(bestreg);
                   1455:            raw_zero_extend_16_rr(rr,rr);
                   1456:            raw_zero_extend_16_rr(bestreg,bestreg);
                   1457:            raw_bswap_32(bestreg);
                   1458:            raw_lea_l_brr_indexed(rr,rr,bestreg,1,0);
                   1459:            live.state[r].validsize=4;
                   1460:            live.nat[rr].touched=touchcnt++;
                   1461:            return rr;
                   1462:        }
                   1463:        if (live.state[r].validsize==1) {
                   1464:            /* Nothing yet */
                   1465:        }
                   1466:        evict(r);
                   1467:     }
                   1468: 
                   1469:     if (!willclobber) {
                   1470:        if (live.state[r].status!=UNDEF) {
                   1471:            if (isconst(r)) {
                   1472:                raw_mov_l_ri(bestreg,live.state[r].val);
                   1473:                live.state[r].val=0;
                   1474:                live.state[r].dirtysize=4;
                   1475:                set_status(r,DIRTY);
                   1476:                log_isused(bestreg);
                   1477:            }
                   1478:            else {
                   1479:                log_isreg(bestreg, r);  /* This will also load it! */
                   1480:                live.state[r].dirtysize=0;
                   1481:                set_status(r,CLEAN);
                   1482:            }
                   1483:        }
                   1484:        else {
                   1485:            live.state[r].val=0;
                   1486:            live.state[r].dirtysize=0;
                   1487:            set_status(r,CLEAN);
                   1488:                log_isused(bestreg);
                   1489:        }
                   1490:        live.state[r].validsize=4;
                   1491:     }
                   1492:     else { /* this is the easiest way, but not optimal. FIXME! */
                   1493:        /* Now it's trickier, but hopefully still OK */
                   1494:        if (!isconst(r) || size==4) {
                   1495:            live.state[r].validsize=size;
                   1496:            live.state[r].dirtysize=size;
                   1497:            live.state[r].val=0;
                   1498:            set_status(r,DIRTY);
                   1499:                if (size == 4) {
                   1500:                        log_clobberreg(r);
                   1501:                        log_isused(bestreg);
                   1502:                }
                   1503:                else {
                   1504:                        log_visused(r);
                   1505:                        log_isused(bestreg);
                   1506:                }
                   1507:        }
                   1508:        else {
                   1509:            if (live.state[r].status!=UNDEF)
                   1510:                raw_mov_l_ri(bestreg,live.state[r].val);
                   1511:            live.state[r].val=0;
                   1512:            live.state[r].validsize=4;
                   1513:            live.state[r].dirtysize=4;
                   1514:            set_status(r,DIRTY);
                   1515:                log_isused(bestreg);
                   1516:        }
                   1517:     }
                   1518:     live.state[r].realreg=bestreg;
                   1519:     live.state[r].realind=live.nat[bestreg].nholds;
                   1520:     live.nat[bestreg].touched=touchcnt++;
                   1521:     live.nat[bestreg].holds[live.nat[bestreg].nholds]=r;
                   1522:     live.nat[bestreg].nholds++;
                   1523: 
                   1524:     return bestreg;
                   1525: }
                   1526: 
                   1527: static  int alloc_reg(int r, int size, int willclobber)
                   1528: {
                   1529:     return alloc_reg_hinted(r,size,willclobber,-1);
                   1530: }
                   1531: 
                   1532: static  void unlock2(int r)
                   1533: {
                   1534:     Dif (!live.nat[r].locked)
                   1535:        abort();
                   1536:     live.nat[r].locked--;
                   1537: }
                   1538: 
                   1539: static  void setlock(int r)
                   1540: {
                   1541:     live.nat[r].locked++;
                   1542: }
                   1543: 
                   1544: 
                   1545: static void mov_nregs(int d, int s)
                   1546: {
                   1547:     int ns=live.nat[s].nholds;
                   1548:     int nd=live.nat[d].nholds;
                   1549:     int i;
                   1550: 
                   1551:     if (s==d)
                   1552:        return;
                   1553: 
                   1554:     if (nd>0) 
                   1555:        free_nreg(d);
                   1556: 
                   1557:        log_isused(d);
                   1558:     raw_mov_l_rr(d,s);
                   1559: 
                   1560:     for (i=0;i<live.nat[s].nholds;i++) {
                   1561:        int vs=live.nat[s].holds[i];
                   1562: 
                   1563:        live.state[vs].realreg=d;
                   1564:        live.state[vs].realind=i;
                   1565:        live.nat[d].holds[i]=vs;
                   1566:     }
                   1567:     live.nat[d].nholds=live.nat[s].nholds;
                   1568: 
                   1569:     live.nat[s].nholds=0;
                   1570: }
                   1571: 
                   1572: 
                   1573: static __inline__ void make_exclusive(int r, int size, int spec)
                   1574: {
                   1575:     int clobber;
                   1576:     reg_status oldstate;
                   1577:     int rr=live.state[r].realreg;
                   1578:     int nr;
                   1579:     int nind;
                   1580:     int ndirt=0;
                   1581:     int i;
                   1582: 
                   1583:     if (!isinreg(r))
                   1584:        return;
                   1585:     if (live.nat[rr].nholds==1)
                   1586:        return;
                   1587:     for (i=0;i<live.nat[rr].nholds;i++) {
                   1588:        int vr=live.nat[rr].holds[i];
                   1589:        if (vr!=r && 
                   1590:            (live.state[vr].status==DIRTY || live.state[vr].val))
                   1591:            ndirt++;
                   1592:     }
                   1593:     if (!ndirt && size<live.state[r].validsize && !live.nat[rr].locked) { 
                   1594:        /* Everything else is clean, so let's keep this register */
                   1595:        for (i=0;i<live.nat[rr].nholds;i++) {
                   1596:            int vr=live.nat[rr].holds[i];
                   1597:            if (vr!=r) {
                   1598:                evict(vr);
                   1599:                i--; /* Try that index again! */
                   1600:            }
                   1601:        }
                   1602:        Dif (live.nat[rr].nholds!=1) {
                   1603:            write_log("natreg %d holds %d vregs, %d not exclusive\n",
                   1604:                   rr,live.nat[rr].nholds,r);
                   1605:            abort();
                   1606:        }
                   1607:        return;
                   1608:     }
                   1609: 
                   1610:     /* We have to split the register */
                   1611:     oldstate=live.state[r];
                   1612: 
                   1613:     setlock(rr); /* Make sure this doesn't go away */
                   1614:     /* Forget about r being in the register rr */
                   1615:     disassociate(r);
                   1616:     /* Get a new register, that we will clobber completely */
                   1617:     if (oldstate.status==DIRTY) {
                   1618:        /* If dirtysize is <4, we need a register that can handle the
                   1619:           eventual smaller memory store! Thanks to Quake68k for exposing
                   1620:           this detail ;-) */
                   1621:        nr=alloc_reg_hinted(r,oldstate.dirtysize,1,spec);
                   1622:     }
                   1623:     else {
                   1624:        nr=alloc_reg_hinted(r,4,1,spec);
                   1625:     }
                   1626:     nind=live.state[r].realind;
                   1627:     live.state[r]=oldstate;   /* Keep all the old state info */
                   1628:     live.state[r].realreg=nr;
                   1629:     live.state[r].realind=nind;
                   1630: 
                   1631:     if (size<live.state[r].validsize) {
                   1632:        if (live.state[r].val) {
                   1633:            /* Might as well compensate for the offset now */
                   1634:            raw_lea_l_brr(nr,rr,oldstate.val);
                   1635:            live.state[r].val=0;
                   1636:            live.state[r].dirtysize=4;
                   1637:            set_status(r,DIRTY);
                   1638:        }
                   1639:        else
                   1640:            raw_mov_l_rr(nr,rr);  /* Make another copy */
                   1641:     }
                   1642:     unlock2(rr); 
                   1643: }
                   1644: 
                   1645: static __inline__ void add_offset(int r, uae_u32 off)
                   1646: {
                   1647:     live.state[r].val+=off;
                   1648: }
                   1649: 
                   1650: static __inline__ void remove_offset(int r, int spec)
                   1651: {
                   1652:     reg_status oldstate;
                   1653:     int rr;
                   1654: 
                   1655:     if (isconst(r))
                   1656:        return;
                   1657:     if (live.state[r].val==0)
                   1658:        return;
                   1659:     if (isinreg(r) && live.state[r].validsize<4) 
                   1660:        evict(r);
                   1661: 
                   1662:     if (!isinreg(r)) 
                   1663:        alloc_reg_hinted(r,4,0,spec);
                   1664: 
                   1665:     Dif (live.state[r].validsize!=4) {
                   1666:        write_log("Validsize=%d in remove_offset\n",live.state[r].validsize);
                   1667:        abort();
                   1668:     }
                   1669:     make_exclusive(r,0,-1);
                   1670:     /* make_exclusive might have done the job already */
                   1671:     if (live.state[r].val==0)
                   1672:        return;
                   1673:     
                   1674:     rr=live.state[r].realreg;
                   1675: 
                   1676:     if (live.nat[rr].nholds==1) {
                   1677:        //write_log("RemovingB offset %x from reg %d (%d) at %p\n",
                   1678:        //       live.state[r].val,r,rr,target); 
                   1679:        adjust_nreg(rr,live.state[r].val);
                   1680:        live.state[r].dirtysize=4;
                   1681:        live.state[r].val=0;
                   1682:        set_status(r,DIRTY);
                   1683:        return;
                   1684:     }
                   1685:     write_log("Failed in remove_offset\n");
                   1686:     abort();
                   1687: }
                   1688: 
                   1689: static __inline__ void remove_all_offsets(void)
                   1690: {
                   1691:     int i;
                   1692: 
                   1693:     for (i=0;i<VREGS;i++)
                   1694:        remove_offset(i,-1);
                   1695: }
                   1696: 
                   1697: static inline void flush_reg_count(void)
                   1698: {
                   1699: #if RECORD_REGISTER_USAGE
                   1700:     for (int r = 0; r < 16; r++)
                   1701:        if (reg_count_local[r])
                   1702:            ADDQim(reg_count_local[r], ((uintptr)reg_count) + (8 * r), X86_NOREG, X86_NOREG, 1);
                   1703: #endif
                   1704: }
                   1705: 
                   1706: static inline void record_register(int r)
                   1707: {
                   1708: #if RECORD_REGISTER_USAGE
                   1709:     if (r < 16)
                   1710:        reg_count_local[r]++;
                   1711: #endif
                   1712: }
                   1713: 
                   1714: static __inline__ int readreg_general(int r, int size, int spec, int can_offset)
                   1715: {
                   1716:     int n;
                   1717:     int answer=-1;
                   1718:     
                   1719:     record_register(r);
                   1720:        if (live.state[r].status==UNDEF) {
                   1721:                write_log("WARNING: Unexpected read of undefined register %d\n",r);
                   1722:        }
                   1723:     if (!can_offset)
                   1724:        remove_offset(r,spec);
                   1725:     
                   1726:     if (isinreg(r) && live.state[r].validsize>=size) {
                   1727:        n=live.state[r].realreg;
                   1728:        switch(size) {
                   1729:         case 1: 
                   1730:            if (live.nat[n].canbyte || spec>=0) { 
                   1731:                answer=n; 
                   1732:            }
                   1733:            break;
                   1734:         case 2: 
                   1735:            if (live.nat[n].canword || spec>=0) { 
                   1736:                answer=n; 
                   1737:            }
                   1738:            break;
                   1739:         case 4: 
                   1740:            answer=n; 
                   1741:            break;
                   1742:         default: abort();
                   1743:        }
                   1744:        if (answer<0)
                   1745:            evict(r);
                   1746:     }
                   1747:     /* either the value was in memory to start with, or it was evicted and 
                   1748:        is in memory now */
                   1749:     if (answer<0) {
                   1750:        answer=alloc_reg_hinted(r,spec>=0?4:size,0,spec);
                   1751:     }
                   1752: 
                   1753:     if (spec>=0 && spec!=answer) {
                   1754:        /* Too bad */
                   1755:        mov_nregs(spec,answer);
                   1756:        answer=spec;
                   1757:     }
                   1758:     live.nat[answer].locked++;
                   1759:     live.nat[answer].touched=touchcnt++;
                   1760:     return answer;
                   1761: }
                   1762: 
                   1763: 
                   1764: 
                   1765: static int readreg(int r, int size)
                   1766: {
                   1767:     return readreg_general(r,size,-1,0);
                   1768: }
                   1769: 
                   1770: static int readreg_specific(int r, int size, int spec)
                   1771: {
                   1772:     return readreg_general(r,size,spec,0);
                   1773: }
                   1774: 
                   1775: static int readreg_offset(int r, int size)
                   1776: {
                   1777:     return readreg_general(r,size,-1,1);
                   1778: }
                   1779: 
                   1780: /* writereg_general(r, size, spec)
                   1781:  *
                   1782:  * INPUT
                   1783:  * - r    : mid-layer register
                   1784:  * - size : requested size (1/2/4)
                   1785:  * - spec : -1 if find or make a register free, otherwise specifies
                   1786:  *          the physical register to use in any case
                   1787:  *
                   1788:  * OUTPUT
                   1789:  * - hard (physical, x86 here) register allocated to virtual register r
                   1790:  */
                   1791: static __inline__ int writereg_general(int r, int size, int spec)
                   1792: {
                   1793:     int n;
                   1794:     int answer=-1;
                   1795: 
                   1796:     record_register(r);
                   1797:     if (size<4) {
                   1798:        remove_offset(r,spec);
                   1799:     }
                   1800: 
                   1801:     make_exclusive(r,size,spec);
                   1802:     if (isinreg(r)) {
                   1803:        int nvsize=size>live.state[r].validsize?size:live.state[r].validsize;
                   1804:        int ndsize=size>live.state[r].dirtysize?size:live.state[r].dirtysize;
                   1805:        n=live.state[r].realreg;
                   1806: 
                   1807:        Dif (live.nat[n].nholds!=1)
                   1808:            abort();
                   1809:        switch(size) {
                   1810:         case 1: 
                   1811:            if (live.nat[n].canbyte || spec>=0) { 
                   1812:                live.state[r].dirtysize=ndsize;
                   1813:                live.state[r].validsize=nvsize;
                   1814:                answer=n;
                   1815:            }
                   1816:            break;
                   1817:         case 2: 
                   1818:            if (live.nat[n].canword || spec>=0) { 
                   1819:                live.state[r].dirtysize=ndsize;
                   1820:                live.state[r].validsize=nvsize;
                   1821:                answer=n;
                   1822:            }
                   1823:            break;
                   1824:         case 4: 
                   1825:            live.state[r].dirtysize=ndsize;
                   1826:            live.state[r].validsize=nvsize;
                   1827:            answer=n;
                   1828:            break;
                   1829:         default: abort();
                   1830:        }
                   1831:        if (answer<0)
                   1832:            evict(r);
                   1833:     }
                   1834:     /* either the value was in memory to start with, or it was evicted and 
                   1835:        is in memory now */
                   1836:     if (answer<0) {
                   1837:        answer=alloc_reg_hinted(r,size,1,spec);
                   1838:     }
                   1839:     if (spec>=0 && spec!=answer) {
                   1840:        mov_nregs(spec,answer);
                   1841:        answer=spec;
                   1842:     }
                   1843:     if (live.state[r].status==UNDEF)
                   1844:        live.state[r].validsize=4;
                   1845:     live.state[r].dirtysize=size>live.state[r].dirtysize?size:live.state[r].dirtysize;
                   1846:     live.state[r].validsize=size>live.state[r].validsize?size:live.state[r].validsize;
                   1847:     
                   1848:     live.nat[answer].locked++;
                   1849:     live.nat[answer].touched=touchcnt++;
                   1850:     if (size==4) {
                   1851:        live.state[r].val=0;
                   1852:     }
                   1853:     else {
                   1854:        Dif (live.state[r].val) {
                   1855:            write_log("Problem with val\n");
                   1856:            abort();
                   1857:        }
                   1858:     }
                   1859:     set_status(r,DIRTY);
                   1860:     return answer;
                   1861: }
                   1862: 
                   1863: static int writereg(int r, int size)
                   1864: {
                   1865:     return writereg_general(r,size,-1);
                   1866: }
                   1867: 
                   1868: static int writereg_specific(int r, int size, int spec)
                   1869: {
                   1870:     return writereg_general(r,size,spec);
                   1871: }
                   1872: 
                   1873: static __inline__ int rmw_general(int r, int wsize, int rsize, int spec)
                   1874: {
                   1875:     int n;
                   1876:     int answer=-1;
                   1877:     
                   1878:     record_register(r);
                   1879:        if (live.state[r].status==UNDEF) {
                   1880:                write_log("WARNING: Unexpected read of undefined register %d\n",r);
                   1881:        }
                   1882:     remove_offset(r,spec);
                   1883:     make_exclusive(r,0,spec);
                   1884: 
                   1885:     Dif (wsize<rsize) {
                   1886:        write_log("Cannot handle wsize<rsize in rmw_general()\n");
                   1887:        abort();
                   1888:     }
                   1889:     if (isinreg(r) && live.state[r].validsize>=rsize) {
                   1890:        n=live.state[r].realreg;
                   1891:        Dif (live.nat[n].nholds!=1)
                   1892:            abort();
                   1893: 
                   1894:        switch(rsize) {
                   1895:         case 1: 
                   1896:            if (live.nat[n].canbyte || spec>=0) { 
                   1897:                answer=n; 
                   1898:            }
                   1899:            break;
                   1900:         case 2: 
                   1901:            if (live.nat[n].canword || spec>=0) { 
                   1902:                answer=n; 
                   1903:            }
                   1904:            break;
                   1905:         case 4: 
                   1906:            answer=n; 
                   1907:            break;
                   1908:         default: abort();
                   1909:        }
                   1910:        if (answer<0)
                   1911:            evict(r);
                   1912:     }
                   1913:     /* either the value was in memory to start with, or it was evicted and 
                   1914:        is in memory now */
                   1915:     if (answer<0) {
                   1916:        answer=alloc_reg_hinted(r,spec>=0?4:rsize,0,spec);
                   1917:     }
                   1918: 
                   1919:     if (spec>=0 && spec!=answer) {
                   1920:        /* Too bad */
                   1921:        mov_nregs(spec,answer);
                   1922:        answer=spec;
                   1923:     }
                   1924:     if (wsize>live.state[r].dirtysize)
                   1925:        live.state[r].dirtysize=wsize;
                   1926:     if (wsize>live.state[r].validsize)
                   1927:        live.state[r].validsize=wsize;
                   1928:     set_status(r,DIRTY);
                   1929: 
                   1930:     live.nat[answer].locked++;
                   1931:     live.nat[answer].touched=touchcnt++;
                   1932: 
                   1933:     Dif (live.state[r].val) {
                   1934:        write_log("Problem with val(rmw)\n");
                   1935:        abort();
                   1936:     }
                   1937:     return answer;
                   1938: }
                   1939: 
                   1940: static int rmw(int r, int wsize, int rsize) 
                   1941: {
                   1942:     return rmw_general(r,wsize,rsize,-1);
                   1943: }
                   1944: 
                   1945: static int rmw_specific(int r, int wsize, int rsize, int spec) 
                   1946: {
                   1947:     return rmw_general(r,wsize,rsize,spec);
                   1948: }
                   1949: 
                   1950: 
                   1951: /* needed for restoring the carry flag on non-P6 cores */
                   1952: static void bt_l_ri_noclobber(R4 r, IMM i)
                   1953: {
                   1954:     int size=4;
                   1955:     if (i<16)
                   1956:        size=2;
                   1957:     r=readreg(r,size);
                   1958:     raw_bt_l_ri(r,i);
                   1959:     unlock2(r);
                   1960: }
                   1961: 
                   1962: /********************************************************************
                   1963:  * FPU register status handling. EMIT TIME!                         *
                   1964:  ********************************************************************/
                   1965: 
                   1966: static  void f_tomem(int r)
                   1967: {
                   1968:     if (live.fate[r].status==DIRTY) {
                   1969: #if USE_LONG_DOUBLE
                   1970:        raw_fmov_ext_mr((uintptr)live.fate[r].mem,live.fate[r].realreg); 
                   1971: #else
                   1972:        raw_fmov_mr((uintptr)live.fate[r].mem,live.fate[r].realreg); 
                   1973: #endif
                   1974:        live.fate[r].status=CLEAN;
                   1975:     }
                   1976: }
                   1977: 
                   1978: static  void f_tomem_drop(int r)
                   1979: {
                   1980:     if (live.fate[r].status==DIRTY) {
                   1981: #if USE_LONG_DOUBLE
                   1982:        raw_fmov_ext_mr_drop((uintptr)live.fate[r].mem,live.fate[r].realreg); 
                   1983: #else
                   1984:        raw_fmov_mr_drop((uintptr)live.fate[r].mem,live.fate[r].realreg); 
                   1985: #endif
                   1986:        live.fate[r].status=INMEM;
                   1987:     }
                   1988: }
                   1989: 
                   1990: 
                   1991: static __inline__ int f_isinreg(int r)
                   1992: {
                   1993:     return live.fate[r].status==CLEAN || live.fate[r].status==DIRTY;
                   1994: }
                   1995: 
                   1996: static void f_evict(int r)
                   1997: {
                   1998:     int rr;
                   1999: 
                   2000:     if (!f_isinreg(r))
                   2001:        return;
                   2002:     rr=live.fate[r].realreg;
                   2003:     if (live.fat[rr].nholds==1)
                   2004:        f_tomem_drop(r);
                   2005:     else
                   2006:        f_tomem(r);
                   2007: 
                   2008:     Dif (live.fat[rr].locked &&
                   2009:        live.fat[rr].nholds==1) {
                   2010:        write_log("FPU register %d in nreg %d is locked!\n",r,live.fate[r].realreg);
                   2011:        abort();
                   2012:     }
                   2013: 
                   2014:     live.fat[rr].nholds--;
                   2015:     if (live.fat[rr].nholds!=live.fate[r].realind) { /* Was not last */
                   2016:        int topreg=live.fat[rr].holds[live.fat[rr].nholds];
                   2017:        int thisind=live.fate[r].realind;
                   2018:        live.fat[rr].holds[thisind]=topreg;
                   2019:        live.fate[topreg].realind=thisind;
                   2020:     }
                   2021:     live.fate[r].status=INMEM;
                   2022:     live.fate[r].realreg=-1;
                   2023: }
                   2024: 
                   2025: static __inline__ void f_free_nreg(int r)
                   2026: {
                   2027:     int i=live.fat[r].nholds;
                   2028: 
                   2029:     while (i) {
                   2030:        int vr;
                   2031: 
                   2032:        --i;
                   2033:        vr=live.fat[r].holds[i];
                   2034:        f_evict(vr);
                   2035:     }
                   2036:     Dif (live.fat[r].nholds!=0) {
                   2037:        write_log("Failed to free nreg %d, nholds is %d\n",r,live.fat[r].nholds);
                   2038:        abort();
                   2039:     }
                   2040: }
                   2041: 
                   2042: 
                   2043: /* Use with care! */
                   2044: static __inline__ void f_isclean(int r)
                   2045: {
                   2046:     if (!f_isinreg(r))
                   2047:        return;
                   2048:     live.fate[r].status=CLEAN;
                   2049: }
                   2050: 
                   2051: static __inline__ void f_disassociate(int r)
                   2052: {
                   2053:     f_isclean(r);
                   2054:     f_evict(r);
                   2055: }
                   2056: 
                   2057: 
                   2058: 
                   2059: static  int f_alloc_reg(int r, int willclobber)
                   2060: {
                   2061:     int bestreg;
                   2062:     uae_s32 when;
                   2063:     int i;
                   2064:     uae_s32 badness;
                   2065:     bestreg=-1;
                   2066:     when=2000000000;
                   2067:     for (i=N_FREGS;i--;) {
                   2068:        badness=live.fat[i].touched;
                   2069:        if (live.fat[i].nholds==0)
                   2070:            badness=0;
                   2071: 
                   2072:        if (!live.fat[i].locked && badness<when) {
                   2073:            bestreg=i;
                   2074:            when=badness;
                   2075:            if (live.fat[i].nholds==0)
                   2076:                break;
                   2077:        }
                   2078:     }
                   2079:     Dif (bestreg==-1)
                   2080:        abort();
                   2081: 
                   2082:     if (live.fat[bestreg].nholds>0) {
                   2083:        f_free_nreg(bestreg);
                   2084:     }
                   2085:     if (f_isinreg(r)) {
                   2086:        f_evict(r);
                   2087:     }
                   2088: 
                   2089:     if (!willclobber) {
                   2090:        if (live.fate[r].status!=UNDEF) {
                   2091: #if USE_LONG_DOUBLE
                   2092:            raw_fmov_ext_rm(bestreg,(uintptr)live.fate[r].mem);
                   2093: #else
                   2094:            raw_fmov_rm(bestreg,(uintptr)live.fate[r].mem);
                   2095: #endif
                   2096:        }
                   2097:        live.fate[r].status=CLEAN;
                   2098:     }
                   2099:     else { 
                   2100:        live.fate[r].status=DIRTY;
                   2101:     }
                   2102:     live.fate[r].realreg=bestreg;
                   2103:     live.fate[r].realind=live.fat[bestreg].nholds;
                   2104:     live.fat[bestreg].touched=touchcnt++;
                   2105:     live.fat[bestreg].holds[live.fat[bestreg].nholds]=r;
                   2106:     live.fat[bestreg].nholds++;
                   2107: 
                   2108:     return bestreg;
                   2109: }
                   2110: 
                   2111: static  void f_unlock(int r)
                   2112: {
                   2113:     Dif (!live.fat[r].locked)
                   2114:        abort();
                   2115:     live.fat[r].locked--;
                   2116: }
                   2117: 
                   2118: static  void f_setlock(int r)
                   2119: {
                   2120:     live.fat[r].locked++;
                   2121: }
                   2122: 
                   2123: static __inline__ int f_readreg(int r)
                   2124: {
                   2125:     int n;
                   2126:     int answer=-1;
                   2127: 
                   2128:     if (f_isinreg(r)) {
                   2129:        n=live.fate[r].realreg;
                   2130:        answer=n; 
                   2131:     }
                   2132:     /* either the value was in memory to start with, or it was evicted and 
                   2133:        is in memory now */
                   2134:     if (answer<0) 
                   2135:        answer=f_alloc_reg(r,0);
                   2136: 
                   2137:     live.fat[answer].locked++;
                   2138:     live.fat[answer].touched=touchcnt++;
                   2139:     return answer;
                   2140: }
                   2141: 
                   2142: static __inline__ void f_make_exclusive(int r, int clobber)
                   2143: {
                   2144:     freg_status oldstate;
                   2145:     int rr=live.fate[r].realreg;
                   2146:     int nr;
                   2147:     int nind;
                   2148:     int ndirt=0;
                   2149:     int i;
                   2150: 
                   2151:     if (!f_isinreg(r))
                   2152:        return;
                   2153:     if (live.fat[rr].nholds==1)
                   2154:        return;
                   2155:     for (i=0;i<live.fat[rr].nholds;i++) {
                   2156:        int vr=live.fat[rr].holds[i];
                   2157:        if (vr!=r && live.fate[vr].status==DIRTY)
                   2158:            ndirt++;
                   2159:     }
                   2160:     if (!ndirt && !live.fat[rr].locked) {
                   2161:                /* Everything else is clean, so let's keep this register */
                   2162:        for (i=0;i<live.fat[rr].nholds;i++) {
                   2163:            int vr=live.fat[rr].holds[i];
                   2164:            if (vr!=r) {
                   2165:                f_evict(vr);
                   2166:                i--; /* Try that index again! */
                   2167:            }
                   2168:        }
                   2169:        Dif (live.fat[rr].nholds!=1) {
                   2170:            write_log("realreg %d holds %d (",rr,live.fat[rr].nholds);
                   2171:            for (i=0;i<live.fat[rr].nholds;i++) {
                   2172:                write_log(" %d(%d,%d)",live.fat[rr].holds[i],
                   2173:                       live.fate[live.fat[rr].holds[i]].realreg,
                   2174:                       live.fate[live.fat[rr].holds[i]].realind);
                   2175:            }
                   2176:            write_log("\n");
                   2177:            abort();
                   2178:        }
                   2179:        return;
                   2180:     }
                   2181: 
                   2182:     /* We have to split the register */
                   2183:     oldstate=live.fate[r];
                   2184: 
                   2185:     f_setlock(rr); /* Make sure this doesn't go away */
                   2186:     /* Forget about r being in the register rr */
                   2187:     f_disassociate(r);
                   2188:     /* Get a new register, that we will clobber completely */
                   2189:     nr=f_alloc_reg(r,1);
                   2190:     nind=live.fate[r].realind;
                   2191:     if (!clobber)
                   2192:        raw_fmov_rr(nr,rr);  /* Make another copy */
                   2193:     live.fate[r]=oldstate;   /* Keep all the old state info */
                   2194:     live.fate[r].realreg=nr;
                   2195:     live.fate[r].realind=nind;
                   2196:     f_unlock(rr); 
                   2197: }
                   2198: 
                   2199: 
                   2200: static __inline__ int f_writereg(int r)
                   2201: {
                   2202:     int n;
                   2203:     int answer=-1;
                   2204: 
                   2205:     f_make_exclusive(r,1);
                   2206:     if (f_isinreg(r)) {
                   2207:        n=live.fate[r].realreg;
                   2208:        answer=n;
                   2209:     }
                   2210:     if (answer<0) {
                   2211:        answer=f_alloc_reg(r,1);
                   2212:     }
                   2213:     live.fate[r].status=DIRTY;
                   2214:     live.fat[answer].locked++;
                   2215:     live.fat[answer].touched=touchcnt++;
                   2216:     return answer;
                   2217: }
                   2218: 
                   2219: static int f_rmw(int r)
                   2220: {
                   2221:     int n;
                   2222: 
                   2223:     f_make_exclusive(r,0);
                   2224:     if (f_isinreg(r)) {
                   2225:        n=live.fate[r].realreg;
                   2226:     }
                   2227:     else 
                   2228:        n=f_alloc_reg(r,0);
                   2229:     live.fate[r].status=DIRTY;
                   2230:     live.fat[n].locked++;
                   2231:     live.fat[n].touched=touchcnt++;
                   2232:     return n;
                   2233: }
                   2234: 
                   2235: static void fflags_into_flags_internal(uae_u32 tmp)
                   2236: {
                   2237:     int r;
                   2238: 
                   2239:     clobber_flags();
                   2240:     r=f_readreg(FP_RESULT);
                   2241:        if (FFLAG_NREG_CLOBBER_CONDITION) {
                   2242:        int tmp2=tmp;
                   2243:        tmp=writereg_specific(tmp,4,FFLAG_NREG);
                   2244:        raw_fflags_into_flags(r);
                   2245:        unlock2(tmp);
                   2246:        forget_about(tmp2);
                   2247:        }
                   2248:        else
                   2249:     raw_fflags_into_flags(r);
                   2250:     f_unlock(r);
                   2251:     live_flags();
                   2252: }
                   2253: 
                   2254: 
                   2255: 
                   2256: 
                   2257: /********************************************************************
                   2258:  * CPU functions exposed to gencomp. Both CREATE and EMIT time      *
                   2259:  ********************************************************************/
                   2260: 
                   2261: /* 
                   2262:  *  RULES FOR HANDLING REGISTERS:
                   2263:  *
                   2264:  *  * In the function headers, order the parameters 
                   2265:  *     - 1st registers written to
                   2266:  *     - 2nd read/modify/write registers
                   2267:  *     - 3rd registers read from
                   2268:  *  * Before calling raw_*, you must call readreg, writereg or rmw for
                   2269:  *    each register
                   2270:  *  * The order for this is
                   2271:  *     - 1st call remove_offset for all registers written to with size<4
                   2272:  *     - 2nd call readreg for all registers read without offset
                   2273:  *     - 3rd call rmw for all rmw registers
                   2274:  *     - 4th call readreg_offset for all registers that can handle offsets
                   2275:  *     - 5th call get_offset for all the registers from the previous step
                   2276:  *     - 6th call writereg for all written-to registers
                   2277:  *     - 7th call raw_*
                   2278:  *     - 8th unlock2 all registers that were locked
                   2279:  */
                   2280: 
                   2281: MIDFUNC(0,live_flags,(void))
                   2282: {
                   2283:     live.flags_on_stack=TRASH;
                   2284:     live.flags_in_flags=VALID;
                   2285:     live.flags_are_important=1;
                   2286: }
                   2287: MENDFUNC(0,live_flags,(void))
                   2288: 
                   2289: MIDFUNC(0,dont_care_flags,(void))
                   2290: {
                   2291:     live.flags_are_important=0;
                   2292: }
                   2293: MENDFUNC(0,dont_care_flags,(void))
                   2294: 
                   2295: 
                   2296: MIDFUNC(0,duplicate_carry,(void))
                   2297: {
                   2298:     evict(FLAGX);
                   2299:     make_flags_live_internal();
                   2300:     COMPCALL(setcc_m)((uintptr)live.state[FLAGX].mem,2);
                   2301:        log_vwrite(FLAGX);
                   2302: }
                   2303: MENDFUNC(0,duplicate_carry,(void))
                   2304: 
                   2305: MIDFUNC(0,restore_carry,(void))
                   2306: {
                   2307:     if (!have_rat_stall) { /* Not a P6 core, i.e. no partial stalls */
                   2308:        bt_l_ri_noclobber(FLAGX,0);
                   2309:     }
                   2310:     else {  /* Avoid the stall the above creates.
                   2311:               This is slow on non-P6, though.
                   2312:            */
                   2313:        COMPCALL(rol_b_ri(FLAGX,8));
                   2314:        isclean(FLAGX);
                   2315:     }
                   2316: }
                   2317: MENDFUNC(0,restore_carry,(void))
                   2318: 
                   2319: MIDFUNC(0,start_needflags,(void))
                   2320: {
                   2321:     needflags=1;
                   2322: }
                   2323: MENDFUNC(0,start_needflags,(void))
                   2324: 
                   2325: MIDFUNC(0,end_needflags,(void))
                   2326: {
                   2327:     needflags=0;
                   2328: }
                   2329: MENDFUNC(0,end_needflags,(void))
                   2330: 
                   2331: MIDFUNC(0,make_flags_live,(void))
                   2332: {
                   2333:     make_flags_live_internal();
                   2334: }
                   2335: MENDFUNC(0,make_flags_live,(void))
                   2336: 
                   2337: MIDFUNC(1,fflags_into_flags,(W2 tmp))
                   2338: {
                   2339:     clobber_flags();
                   2340:     fflags_into_flags_internal(tmp);
                   2341: }
                   2342: MENDFUNC(1,fflags_into_flags,(W2 tmp))
                   2343: 
                   2344: 
                   2345: MIDFUNC(2,bt_l_ri,(R4 r, IMM i)) /* This is defined as only affecting C */
                   2346: {    
                   2347:     int size=4;
                   2348:     if (i<16)
                   2349:        size=2;
                   2350:     CLOBBER_BT;
                   2351:     r=readreg(r,size);
                   2352:     raw_bt_l_ri(r,i);
                   2353:     unlock2(r);
                   2354: }
                   2355: MENDFUNC(2,bt_l_ri,(R4 r, IMM i)) /* This is defined as only affecting C */
                   2356: 
                   2357: MIDFUNC(2,bt_l_rr,(R4 r, R4 b)) /* This is defined as only affecting C */
                   2358: {
                   2359:     CLOBBER_BT;
                   2360:     r=readreg(r,4);
                   2361:     b=readreg(b,4);
                   2362:     raw_bt_l_rr(r,b);
                   2363:     unlock2(r);
                   2364:     unlock2(b);
                   2365: }
                   2366: MENDFUNC(2,bt_l_rr,(R4 r, R4 b)) /* This is defined as only affecting C */
                   2367: 
                   2368: MIDFUNC(2,btc_l_ri,(RW4 r, IMM i)) 
                   2369: {    
                   2370:     int size=4;
                   2371:     if (i<16)
                   2372:        size=2;
                   2373:     CLOBBER_BT;
                   2374:     r=rmw(r,size,size);
                   2375:     raw_btc_l_ri(r,i);
                   2376:     unlock2(r);
                   2377: }
                   2378: MENDFUNC(2,btc_l_ri,(RW4 r, IMM i)) 
                   2379: 
                   2380: MIDFUNC(2,btc_l_rr,(RW4 r, R4 b)) 
                   2381: {
                   2382:     CLOBBER_BT;
                   2383:     b=readreg(b,4);
                   2384:     r=rmw(r,4,4);
                   2385:     raw_btc_l_rr(r,b);
                   2386:     unlock2(r);
                   2387:     unlock2(b);
                   2388: }
                   2389: MENDFUNC(2,btc_l_rr,(RW4 r, R4 b)) 
                   2390: 
                   2391: 
                   2392: MIDFUNC(2,btr_l_ri,(RW4 r, IMM i)) 
                   2393: {    
                   2394:     int size=4;
                   2395:     if (i<16)
                   2396:        size=2;
                   2397:     CLOBBER_BT;
                   2398:     r=rmw(r,size,size);
                   2399:     raw_btr_l_ri(r,i);
                   2400:     unlock2(r);
                   2401: }
                   2402: MENDFUNC(2,btr_l_ri,(RW4 r, IMM i)) 
                   2403: 
                   2404: MIDFUNC(2,btr_l_rr,(RW4 r, R4 b)) 
                   2405: {
                   2406:     CLOBBER_BT;
                   2407:     b=readreg(b,4);
                   2408:     r=rmw(r,4,4);
                   2409:     raw_btr_l_rr(r,b);
                   2410:     unlock2(r);
                   2411:     unlock2(b);
                   2412: }
                   2413: MENDFUNC(2,btr_l_rr,(RW4 r, R4 b)) 
                   2414: 
                   2415: 
                   2416: MIDFUNC(2,bts_l_ri,(RW4 r, IMM i)) 
                   2417: {    
                   2418:     int size=4;
                   2419:     if (i<16)
                   2420:        size=2;
                   2421:     CLOBBER_BT;
                   2422:     r=rmw(r,size,size);
                   2423:     raw_bts_l_ri(r,i);
                   2424:     unlock2(r);
                   2425: }
                   2426: MENDFUNC(2,bts_l_ri,(RW4 r, IMM i)) 
                   2427: 
                   2428: MIDFUNC(2,bts_l_rr,(RW4 r, R4 b)) 
                   2429: {
                   2430:     CLOBBER_BT;
                   2431:     b=readreg(b,4);
                   2432:     r=rmw(r,4,4);
                   2433:     raw_bts_l_rr(r,b);
                   2434:     unlock2(r);
                   2435:     unlock2(b);
                   2436: }
                   2437: MENDFUNC(2,bts_l_rr,(RW4 r, R4 b)) 
                   2438: 
                   2439: MIDFUNC(2,mov_l_rm,(W4 d, IMM s))
                   2440: {
                   2441:     CLOBBER_MOV;
                   2442:     d=writereg(d,4);
                   2443:     raw_mov_l_rm(d,s);
                   2444:     unlock2(d);
                   2445: }
                   2446: MENDFUNC(2,mov_l_rm,(W4 d, IMM s))
                   2447: 
                   2448: 
                   2449: MIDFUNC(1,call_r,(R4 r)) /* Clobbering is implicit */
                   2450: {
                   2451:     r=readreg(r,4);
                   2452:     raw_call_r(r);
                   2453:     unlock2(r);
                   2454: }
                   2455: MENDFUNC(1,call_r,(R4 r)) /* Clobbering is implicit */
                   2456: 
                   2457: MIDFUNC(2,sub_l_mi,(IMM d, IMM s)) 
                   2458: {
                   2459:     CLOBBER_SUB;
                   2460:     raw_sub_l_mi(d,s) ;
                   2461: }
                   2462: MENDFUNC(2,sub_l_mi,(IMM d, IMM s)) 
                   2463: 
                   2464: MIDFUNC(2,mov_l_mi,(IMM d, IMM s)) 
                   2465: {
                   2466:     CLOBBER_MOV;
                   2467:     raw_mov_l_mi(d,s) ;
                   2468: }
                   2469: MENDFUNC(2,mov_l_mi,(IMM d, IMM s)) 
                   2470: 
                   2471: MIDFUNC(2,mov_w_mi,(IMM d, IMM s)) 
                   2472: {
                   2473:     CLOBBER_MOV;
                   2474:     raw_mov_w_mi(d,s) ;
                   2475: }
                   2476: MENDFUNC(2,mov_w_mi,(IMM d, IMM s)) 
                   2477: 
                   2478: MIDFUNC(2,mov_b_mi,(IMM d, IMM s)) 
                   2479: {
                   2480:     CLOBBER_MOV;
                   2481:     raw_mov_b_mi(d,s) ;
                   2482: }
                   2483: MENDFUNC(2,mov_b_mi,(IMM d, IMM s)) 
                   2484: 
                   2485: MIDFUNC(2,rol_b_ri,(RW1 r, IMM i))
                   2486: {
                   2487:        if (!i && !needflags)
                   2488:                return;
                   2489:     CLOBBER_ROL;
                   2490:     r=rmw(r,1,1);
                   2491:     raw_rol_b_ri(r,i);
                   2492:     unlock2(r);
                   2493: }
                   2494: MENDFUNC(2,rol_b_ri,(RW1 r, IMM i))
                   2495: 
                   2496: MIDFUNC(2,rol_w_ri,(RW2 r, IMM i))
                   2497: {
                   2498:        if (!i && !needflags)
                   2499:                return;
                   2500:     CLOBBER_ROL;
                   2501:     r=rmw(r,2,2);
                   2502:     raw_rol_w_ri(r,i);
                   2503:     unlock2(r);
                   2504: }
                   2505: MENDFUNC(2,rol_w_ri,(RW2 r, IMM i))
                   2506: 
                   2507: MIDFUNC(2,rol_l_ri,(RW4 r, IMM i))
                   2508: {
                   2509:        if (!i && !needflags)
                   2510:                return;
                   2511:     CLOBBER_ROL;
                   2512:     r=rmw(r,4,4);
                   2513:     raw_rol_l_ri(r,i);
                   2514:     unlock2(r);
                   2515: }
                   2516: MENDFUNC(2,rol_l_ri,(RW4 r, IMM i))
                   2517: 
                   2518: MIDFUNC(2,rol_l_rr,(RW4 d, R1 r)) 
                   2519: { 
                   2520:     if (isconst(r)) {
                   2521:        COMPCALL(rol_l_ri)(d,(uae_u8)live.state[r].val);
                   2522:        return;
                   2523:     }
                   2524:     CLOBBER_ROL;
                   2525:     r=readreg_specific(r,1,SHIFTCOUNT_NREG);
                   2526:     d=rmw(d,4,4);
                   2527:     Dif (r!=1) {
                   2528:        write_log("Illegal register %d in raw_rol_b\n",r);
                   2529:        abort();
                   2530:     }
                   2531:     raw_rol_l_rr(d,r) ;
                   2532:     unlock2(r);
                   2533:     unlock2(d);
                   2534: }
                   2535: MENDFUNC(2,rol_l_rr,(RW4 d, R1 r)) 
                   2536: 
                   2537: MIDFUNC(2,rol_w_rr,(RW2 d, R1 r)) 
                   2538: { /* Can only do this with r==1, i.e. cl */
                   2539:   
                   2540:     if (isconst(r)) {
                   2541:        COMPCALL(rol_w_ri)(d,(uae_u8)live.state[r].val);
                   2542:        return;
                   2543:     }
                   2544:     CLOBBER_ROL;
                   2545:     r=readreg_specific(r,1,SHIFTCOUNT_NREG);
                   2546:     d=rmw(d,2,2);
                   2547:     Dif (r!=1) {
                   2548:        write_log("Illegal register %d in raw_rol_b\n",r);
                   2549:        abort();
                   2550:     }
                   2551:     raw_rol_w_rr(d,r) ;
                   2552:     unlock2(r);
                   2553:     unlock2(d);
                   2554: }
                   2555: MENDFUNC(2,rol_w_rr,(RW2 d, R1 r)) 
                   2556: 
                   2557: MIDFUNC(2,rol_b_rr,(RW1 d, R1 r)) 
                   2558: { /* Can only do this with r==1, i.e. cl */
                   2559:   
                   2560:     if (isconst(r)) {
                   2561:        COMPCALL(rol_b_ri)(d,(uae_u8)live.state[r].val);
                   2562:        return;
                   2563:     }
                   2564: 
                   2565:     CLOBBER_ROL;
                   2566:     r=readreg_specific(r,1,SHIFTCOUNT_NREG);
                   2567:     d=rmw(d,1,1);
                   2568:     Dif (r!=1) {
                   2569:        write_log("Illegal register %d in raw_rol_b\n",r);
                   2570:        abort();
                   2571:     }
                   2572:     raw_rol_b_rr(d,r) ;
                   2573:     unlock2(r);
                   2574:     unlock2(d);
                   2575: }
                   2576: MENDFUNC(2,rol_b_rr,(RW1 d, R1 r)) 
                   2577: 
                   2578: 
                   2579: MIDFUNC(2,shll_l_rr,(RW4 d, R1 r)) 
                   2580: { 
                   2581:     if (isconst(r)) {
                   2582:        COMPCALL(shll_l_ri)(d,(uae_u8)live.state[r].val);
                   2583:        return;
                   2584:     }
                   2585:     CLOBBER_SHLL;
                   2586:     r=readreg_specific(r,1,SHIFTCOUNT_NREG);
                   2587:     d=rmw(d,4,4);
                   2588:     Dif (r!=1) {
                   2589:        write_log("Illegal register %d in raw_rol_b\n",r);
                   2590:        abort();
                   2591:     }
                   2592:     raw_shll_l_rr(d,r) ;
                   2593:     unlock2(r);
                   2594:     unlock2(d);
                   2595: }
                   2596: MENDFUNC(2,shll_l_rr,(RW4 d, R1 r)) 
                   2597: 
                   2598: MIDFUNC(2,shll_w_rr,(RW2 d, R1 r)) 
                   2599: { /* Can only do this with r==1, i.e. cl */
                   2600:   
                   2601:     if (isconst(r)) {
                   2602:        COMPCALL(shll_w_ri)(d,(uae_u8)live.state[r].val);
                   2603:        return;
                   2604:     }
                   2605:     CLOBBER_SHLL;
                   2606:     r=readreg_specific(r,1,SHIFTCOUNT_NREG);
                   2607:     d=rmw(d,2,2);
                   2608:     Dif (r!=1) {
                   2609:        write_log("Illegal register %d in raw_shll_b\n",r);
                   2610:        abort();
                   2611:     }
                   2612:     raw_shll_w_rr(d,r) ;
                   2613:     unlock2(r);
                   2614:     unlock2(d);
                   2615: }
                   2616: MENDFUNC(2,shll_w_rr,(RW2 d, R1 r)) 
                   2617: 
                   2618: MIDFUNC(2,shll_b_rr,(RW1 d, R1 r)) 
                   2619: { /* Can only do this with r==1, i.e. cl */
                   2620:   
                   2621:     if (isconst(r)) {
                   2622:        COMPCALL(shll_b_ri)(d,(uae_u8)live.state[r].val);
                   2623:        return;
                   2624:     }
                   2625: 
                   2626:     CLOBBER_SHLL;
                   2627:     r=readreg_specific(r,1,SHIFTCOUNT_NREG);
                   2628:     d=rmw(d,1,1);
                   2629:     Dif (r!=1) {
                   2630:        write_log("Illegal register %d in raw_shll_b\n",r);
                   2631:        abort();
                   2632:     }
                   2633:     raw_shll_b_rr(d,r) ;
                   2634:     unlock2(r);
                   2635:     unlock2(d);
                   2636: }
                   2637: MENDFUNC(2,shll_b_rr,(RW1 d, R1 r)) 
                   2638: 
                   2639: 
                   2640: MIDFUNC(2,ror_b_ri,(R1 r, IMM i))
                   2641: {
                   2642:        if (!i && !needflags)
                   2643:                return;
                   2644:     CLOBBER_ROR;
                   2645:     r=rmw(r,1,1);
                   2646:     raw_ror_b_ri(r,i);
                   2647:     unlock2(r);
                   2648: }
                   2649: MENDFUNC(2,ror_b_ri,(R1 r, IMM i))
                   2650: 
                   2651: MIDFUNC(2,ror_w_ri,(R2 r, IMM i))
                   2652: {
                   2653:        if (!i && !needflags)
                   2654:                return;
                   2655:     CLOBBER_ROR;
                   2656:     r=rmw(r,2,2);
                   2657:     raw_ror_w_ri(r,i);
                   2658:     unlock2(r);
                   2659: }
                   2660: MENDFUNC(2,ror_w_ri,(R2 r, IMM i))
                   2661: 
                   2662: MIDFUNC(2,ror_l_ri,(R4 r, IMM i))
                   2663: {
                   2664:        if (!i && !needflags)
                   2665:                return;
                   2666:     CLOBBER_ROR;
                   2667:     r=rmw(r,4,4);
                   2668:     raw_ror_l_ri(r,i);
                   2669:     unlock2(r);
                   2670: }
                   2671: MENDFUNC(2,ror_l_ri,(R4 r, IMM i))
                   2672: 
                   2673: MIDFUNC(2,ror_l_rr,(R4 d, R1 r)) 
                   2674: { 
                   2675:     if (isconst(r)) {
                   2676:        COMPCALL(ror_l_ri)(d,(uae_u8)live.state[r].val);
                   2677:        return;
                   2678:     }
                   2679:     CLOBBER_ROR;
                   2680:     r=readreg_specific(r,1,SHIFTCOUNT_NREG);
                   2681:     d=rmw(d,4,4);
                   2682:     raw_ror_l_rr(d,r) ;
                   2683:     unlock2(r);
                   2684:     unlock2(d);
                   2685: }
                   2686: MENDFUNC(2,ror_l_rr,(R4 d, R1 r)) 
                   2687: 
                   2688: MIDFUNC(2,ror_w_rr,(R2 d, R1 r)) 
                   2689: { 
                   2690:     if (isconst(r)) {
                   2691:        COMPCALL(ror_w_ri)(d,(uae_u8)live.state[r].val);
                   2692:        return;
                   2693:     }
                   2694:     CLOBBER_ROR;
                   2695:     r=readreg_specific(r,1,SHIFTCOUNT_NREG);
                   2696:     d=rmw(d,2,2);
                   2697:     raw_ror_w_rr(d,r) ;
                   2698:     unlock2(r);
                   2699:     unlock2(d);
                   2700: }
                   2701: MENDFUNC(2,ror_w_rr,(R2 d, R1 r)) 
                   2702: 
                   2703: MIDFUNC(2,ror_b_rr,(R1 d, R1 r)) 
                   2704: {   
                   2705:     if (isconst(r)) {
                   2706:        COMPCALL(ror_b_ri)(d,(uae_u8)live.state[r].val);
                   2707:        return;
                   2708:     }
                   2709: 
                   2710:     CLOBBER_ROR;
                   2711:     r=readreg_specific(r,1,SHIFTCOUNT_NREG);
                   2712:     d=rmw(d,1,1);
                   2713:     raw_ror_b_rr(d,r) ;
                   2714:     unlock2(r);
                   2715:     unlock2(d);
                   2716: }
                   2717: MENDFUNC(2,ror_b_rr,(R1 d, R1 r)) 
                   2718: 
                   2719: MIDFUNC(2,shrl_l_rr,(RW4 d, R1 r)) 
                   2720: { 
                   2721:     if (isconst(r)) {
                   2722:        COMPCALL(shrl_l_ri)(d,(uae_u8)live.state[r].val);
                   2723:        return;
                   2724:     }
                   2725:     CLOBBER_SHRL;
                   2726:     r=readreg_specific(r,1,SHIFTCOUNT_NREG);
                   2727:     d=rmw(d,4,4);
                   2728:     Dif (r!=1) {
                   2729:        write_log("Illegal register %d in raw_rol_b\n",r);
                   2730:        abort();
                   2731:     }
                   2732:     raw_shrl_l_rr(d,r) ;
                   2733:     unlock2(r);
                   2734:     unlock2(d);
                   2735: }
                   2736: MENDFUNC(2,shrl_l_rr,(RW4 d, R1 r)) 
                   2737: 
                   2738: MIDFUNC(2,shrl_w_rr,(RW2 d, R1 r)) 
                   2739: { /* Can only do this with r==1, i.e. cl */
                   2740:   
                   2741:     if (isconst(r)) {
                   2742:        COMPCALL(shrl_w_ri)(d,(uae_u8)live.state[r].val);
                   2743:        return;
                   2744:     }
                   2745:     CLOBBER_SHRL;
                   2746:     r=readreg_specific(r,1,SHIFTCOUNT_NREG);
                   2747:     d=rmw(d,2,2);
                   2748:     Dif (r!=1) {
                   2749:        write_log("Illegal register %d in raw_shrl_b\n",r);
                   2750:        abort();
                   2751:     }
                   2752:     raw_shrl_w_rr(d,r) ;
                   2753:     unlock2(r);
                   2754:     unlock2(d);
                   2755: }
                   2756: MENDFUNC(2,shrl_w_rr,(RW2 d, R1 r)) 
                   2757: 
                   2758: MIDFUNC(2,shrl_b_rr,(RW1 d, R1 r)) 
                   2759: { /* Can only do this with r==1, i.e. cl */
                   2760:   
                   2761:     if (isconst(r)) {
                   2762:        COMPCALL(shrl_b_ri)(d,(uae_u8)live.state[r].val);
                   2763:        return;
                   2764:     }
                   2765: 
                   2766:     CLOBBER_SHRL;
                   2767:     r=readreg_specific(r,1,SHIFTCOUNT_NREG);
                   2768:     d=rmw(d,1,1);
                   2769:     Dif (r!=1) {
                   2770:        write_log("Illegal register %d in raw_shrl_b\n",r);
                   2771:        abort();
                   2772:     }
                   2773:     raw_shrl_b_rr(d,r) ;
                   2774:     unlock2(r);
                   2775:     unlock2(d);
                   2776: }
                   2777: MENDFUNC(2,shrl_b_rr,(RW1 d, R1 r)) 
                   2778: 
                   2779: 
                   2780: 
                   2781: MIDFUNC(2,shll_l_ri,(RW4 r, IMM i))
                   2782: {
                   2783:     if (!i && !needflags)
                   2784:        return;
                   2785:     if (isconst(r) && !needflags) {
                   2786:        live.state[r].val<<=i;
                   2787:        return;
                   2788:     }
                   2789:     CLOBBER_SHLL;
                   2790:     r=rmw(r,4,4);
                   2791:     raw_shll_l_ri(r,i);
                   2792:     unlock2(r);
                   2793: }
                   2794: MENDFUNC(2,shll_l_ri,(RW4 r, IMM i))
                   2795: 
                   2796: MIDFUNC(2,shll_w_ri,(RW2 r, IMM i))
                   2797: {
                   2798:     if (!i && !needflags)
                   2799:        return;
                   2800:     CLOBBER_SHLL;
                   2801:     r=rmw(r,2,2);
                   2802:     raw_shll_w_ri(r,i);
                   2803:     unlock2(r);
                   2804: }
                   2805: MENDFUNC(2,shll_w_ri,(RW2 r, IMM i))
                   2806: 
                   2807: MIDFUNC(2,shll_b_ri,(RW1 r, IMM i))
                   2808: {
                   2809:     if (!i && !needflags)
                   2810:        return;
                   2811:     CLOBBER_SHLL;
                   2812:     r=rmw(r,1,1);
                   2813:     raw_shll_b_ri(r,i);
                   2814:     unlock2(r);
                   2815: }
                   2816: MENDFUNC(2,shll_b_ri,(RW1 r, IMM i))
                   2817: 
                   2818: MIDFUNC(2,shrl_l_ri,(RW4 r, IMM i))
                   2819: {
                   2820:     if (!i && !needflags)
                   2821:        return;
                   2822:     if (isconst(r) && !needflags) {
                   2823:        live.state[r].val>>=i;
                   2824:        return;
                   2825:     }
                   2826:     CLOBBER_SHRL;
                   2827:     r=rmw(r,4,4);
                   2828:     raw_shrl_l_ri(r,i);
                   2829:     unlock2(r);
                   2830: }
                   2831: MENDFUNC(2,shrl_l_ri,(RW4 r, IMM i))
                   2832: 
                   2833: MIDFUNC(2,shrl_w_ri,(RW2 r, IMM i))
                   2834: {
                   2835:     if (!i && !needflags)
                   2836:        return;
                   2837:     CLOBBER_SHRL;
                   2838:     r=rmw(r,2,2);
                   2839:     raw_shrl_w_ri(r,i);
                   2840:     unlock2(r);
                   2841: }
                   2842: MENDFUNC(2,shrl_w_ri,(RW2 r, IMM i))
                   2843: 
                   2844: MIDFUNC(2,shrl_b_ri,(RW1 r, IMM i))
                   2845: {
                   2846:     if (!i && !needflags)
                   2847:        return;
                   2848:     CLOBBER_SHRL;
                   2849:     r=rmw(r,1,1);
                   2850:     raw_shrl_b_ri(r,i);
                   2851:     unlock2(r);
                   2852: }
                   2853: MENDFUNC(2,shrl_b_ri,(RW1 r, IMM i))
                   2854: 
                   2855: MIDFUNC(2,shra_l_ri,(RW4 r, IMM i))
                   2856: {
                   2857:     if (!i && !needflags)
                   2858:        return;
                   2859:     CLOBBER_SHRA;
                   2860:     r=rmw(r,4,4);
                   2861:     raw_shra_l_ri(r,i);
                   2862:     unlock2(r);
                   2863: }
                   2864: MENDFUNC(2,shra_l_ri,(RW4 r, IMM i))
                   2865: 
                   2866: MIDFUNC(2,shra_w_ri,(RW2 r, IMM i))
                   2867: {
                   2868:     if (!i && !needflags)
                   2869:        return;
                   2870:     CLOBBER_SHRA;
                   2871:     r=rmw(r,2,2);
                   2872:     raw_shra_w_ri(r,i);
                   2873:     unlock2(r);
                   2874: }
                   2875: MENDFUNC(2,shra_w_ri,(RW2 r, IMM i))
                   2876: 
                   2877: MIDFUNC(2,shra_b_ri,(RW1 r, IMM i))
                   2878: {
                   2879:     if (!i && !needflags)
                   2880:        return;
                   2881:     CLOBBER_SHRA;
                   2882:     r=rmw(r,1,1);
                   2883:     raw_shra_b_ri(r,i);
                   2884:     unlock2(r);
                   2885: }
                   2886: MENDFUNC(2,shra_b_ri,(RW1 r, IMM i))
                   2887: 
                   2888: MIDFUNC(2,shra_l_rr,(RW4 d, R1 r)) 
                   2889: { 
                   2890:     if (isconst(r)) {
                   2891:        COMPCALL(shra_l_ri)(d,(uae_u8)live.state[r].val);
                   2892:        return;
                   2893:     }
                   2894:     CLOBBER_SHRA;
                   2895:     r=readreg_specific(r,1,SHIFTCOUNT_NREG);
                   2896:     d=rmw(d,4,4);
                   2897:     Dif (r!=1) {
                   2898:        write_log("Illegal register %d in raw_rol_b\n",r);
                   2899:        abort();
                   2900:     }
                   2901:     raw_shra_l_rr(d,r) ;
                   2902:     unlock2(r);
                   2903:     unlock2(d);
                   2904: }
                   2905: MENDFUNC(2,shra_l_rr,(RW4 d, R1 r)) 
                   2906: 
                   2907: MIDFUNC(2,shra_w_rr,(RW2 d, R1 r)) 
                   2908: { /* Can only do this with r==1, i.e. cl */
                   2909:   
                   2910:     if (isconst(r)) {
                   2911:        COMPCALL(shra_w_ri)(d,(uae_u8)live.state[r].val);
                   2912:        return;
                   2913:     }
                   2914:     CLOBBER_SHRA;
                   2915:     r=readreg_specific(r,1,SHIFTCOUNT_NREG);
                   2916:     d=rmw(d,2,2);
                   2917:     Dif (r!=1) {
                   2918:        write_log("Illegal register %d in raw_shra_b\n",r);
                   2919:        abort();
                   2920:     }
                   2921:     raw_shra_w_rr(d,r) ;
                   2922:     unlock2(r);
                   2923:     unlock2(d);
                   2924: }
                   2925: MENDFUNC(2,shra_w_rr,(RW2 d, R1 r)) 
                   2926: 
                   2927: MIDFUNC(2,shra_b_rr,(RW1 d, R1 r)) 
                   2928: { /* Can only do this with r==1, i.e. cl */
                   2929:   
                   2930:     if (isconst(r)) {
                   2931:        COMPCALL(shra_b_ri)(d,(uae_u8)live.state[r].val);
                   2932:        return;
                   2933:     }
                   2934: 
                   2935:     CLOBBER_SHRA;
                   2936:     r=readreg_specific(r,1,SHIFTCOUNT_NREG);
                   2937:     d=rmw(d,1,1);
                   2938:     Dif (r!=1) {
                   2939:        write_log("Illegal register %d in raw_shra_b\n",r);
                   2940:        abort();
                   2941:     }
                   2942:     raw_shra_b_rr(d,r) ;
                   2943:     unlock2(r);
                   2944:     unlock2(d);
                   2945: }
                   2946: MENDFUNC(2,shra_b_rr,(RW1 d, R1 r)) 
                   2947: 
                   2948: 
                   2949: MIDFUNC(2,setcc,(W1 d, IMM cc))
                   2950: {
                   2951:     CLOBBER_SETCC;
                   2952:     d=writereg(d,1);
                   2953:     raw_setcc(d,cc);
                   2954:     unlock2(d);
                   2955: }
                   2956: MENDFUNC(2,setcc,(W1 d, IMM cc))
                   2957: 
                   2958: MIDFUNC(2,setcc_m,(IMM d, IMM cc))
                   2959: {
                   2960:     CLOBBER_SETCC;
                   2961:     raw_setcc_m(d,cc);
                   2962: }
                   2963: MENDFUNC(2,setcc_m,(IMM d, IMM cc))
                   2964: 
                   2965: MIDFUNC(3,cmov_b_rr,(RW1 d, R1 s, IMM cc))
                   2966: {
                   2967:     if (d==s)
                   2968:        return;
                   2969:     CLOBBER_CMOV;
                   2970:     s=readreg(s,1);
                   2971:     d=rmw(d,1,1);
                   2972:     raw_cmov_b_rr(d,s,cc);
                   2973:     unlock2(s);
                   2974:     unlock2(d);
                   2975: }
                   2976: MENDFUNC(3,cmov_b_rr,(RW1 d, R1 s, IMM cc))
                   2977: 
                   2978: MIDFUNC(3,cmov_w_rr,(RW2 d, R2 s, IMM cc))
                   2979: {
                   2980:     if (d==s)
                   2981:        return;
                   2982:     CLOBBER_CMOV;
                   2983:     s=readreg(s,2);
                   2984:     d=rmw(d,2,2);
                   2985:     raw_cmov_w_rr(d,s,cc);
                   2986:     unlock2(s);
                   2987:     unlock2(d);
                   2988: }
                   2989: MENDFUNC(3,cmov_w_rr,(RW2 d, R2 s, IMM cc))
                   2990: 
                   2991: MIDFUNC(3,cmov_l_rr,(RW4 d, R4 s, IMM cc))
                   2992: {
                   2993:     if (d==s)
                   2994:        return;
                   2995:     CLOBBER_CMOV;
                   2996:     s=readreg(s,4);
                   2997:     d=rmw(d,4,4);
                   2998:     raw_cmov_l_rr(d,s,cc);
                   2999:     unlock2(s);
                   3000:     unlock2(d);
                   3001: }
                   3002: MENDFUNC(3,cmov_l_rr,(RW4 d, R4 s, IMM cc))
                   3003: 
                   3004: MIDFUNC(3,cmov_l_rm,(RW4 d, IMM s, IMM cc))
                   3005: {
                   3006:     CLOBBER_CMOV;
                   3007:     d=rmw(d,4,4);
                   3008:     raw_cmov_l_rm(d,s,cc);
                   3009:     unlock2(d);
                   3010: }
                   3011: MENDFUNC(3,cmov_l_rm,(RW4 d, IMM s, IMM cc))
                   3012: 
                   3013: MIDFUNC(2,bsf_l_rr,(W4 d, W4 s))
                   3014: {
                   3015:     CLOBBER_BSF;
                   3016:     s = readreg(s, 4);
                   3017:     d = writereg(d, 4);
                   3018:     raw_bsf_l_rr(d, s);
                   3019:     unlock2(s);
                   3020:     unlock2(d);
                   3021: }
                   3022: MENDFUNC(2,bsf_l_rr,(W4 d, W4 s))
                   3023: 
                   3024: /* Set the Z flag depending on the value in s. Note that the
                   3025:    value has to be 0 or -1 (or, more precisely, for non-zero
                   3026:    values, bit 14 must be set)! */
                   3027: MIDFUNC(2,simulate_bsf,(W4 tmp, RW4 s))
                   3028: {
                   3029:     CLOBBER_BSF;
                   3030:     s=rmw_specific(s,4,4,FLAG_NREG3);
                   3031:     tmp=writereg(tmp,4);
                   3032:     raw_flags_set_zero(s, tmp);
                   3033:     unlock2(tmp);
                   3034:     unlock2(s);
                   3035: }
                   3036: MENDFUNC(2,simulate_bsf,(W4 tmp, RW4 s))
                   3037: 
                   3038: MIDFUNC(2,imul_32_32,(RW4 d, R4 s))
                   3039: {
                   3040:     CLOBBER_MUL;
                   3041:     s=readreg(s,4);
                   3042:     d=rmw(d,4,4);
                   3043:     raw_imul_32_32(d,s);
                   3044:     unlock2(s);
                   3045:     unlock2(d);
                   3046: }
                   3047: MENDFUNC(2,imul_32_32,(RW4 d, R4 s))
                   3048: 
                   3049: MIDFUNC(2,imul_64_32,(RW4 d, RW4 s))
                   3050: {
                   3051:     CLOBBER_MUL;
                   3052:     s=rmw_specific(s,4,4,MUL_NREG2);
                   3053:     d=rmw_specific(d,4,4,MUL_NREG1);
                   3054:     raw_imul_64_32(d,s);
                   3055:     unlock2(s);
                   3056:     unlock2(d);
                   3057: }
                   3058: MENDFUNC(2,imul_64_32,(RW4 d, RW4 s))
                   3059: 
                   3060: MIDFUNC(2,mul_64_32,(RW4 d, RW4 s))
                   3061: {
                   3062:     CLOBBER_MUL;
                   3063:     s=rmw_specific(s,4,4,MUL_NREG2);
                   3064:     d=rmw_specific(d,4,4,MUL_NREG1);
                   3065:     raw_mul_64_32(d,s);
                   3066:     unlock2(s);
                   3067:     unlock2(d);
                   3068: }
                   3069: MENDFUNC(2,mul_64_32,(RW4 d, RW4 s))
                   3070: 
                   3071: MIDFUNC(2,mul_32_32,(RW4 d, R4 s))
                   3072: {
                   3073:     CLOBBER_MUL;
                   3074:     s=readreg(s,4);
                   3075:     d=rmw(d,4,4);
                   3076:     raw_mul_32_32(d,s);
                   3077:     unlock2(s);
                   3078:     unlock2(d);
                   3079: }
                   3080: MENDFUNC(2,mul_32_32,(RW4 d, R4 s))
                   3081: 
                   3082: #if SIZEOF_VOID_P == 8
                   3083: MIDFUNC(2,sign_extend_32_rr,(W4 d, R2 s))
                   3084: {
                   3085:     int isrmw;
                   3086: 
                   3087:     if (isconst(s)) {
                   3088:        set_const(d,(uae_s32)live.state[s].val);
                   3089:        return;
                   3090:     }
                   3091: 
                   3092:     CLOBBER_SE32;
                   3093:     isrmw=(s==d);
                   3094:     if (!isrmw) {
                   3095:        s=readreg(s,4);
                   3096:        d=writereg(d,4);
                   3097:     }
                   3098:     else {  /* If we try to lock this twice, with different sizes, we
                   3099:               are int trouble! */
                   3100:        s=d=rmw(s,4,4);
                   3101:     }
                   3102:     raw_sign_extend_32_rr(d,s);
                   3103:     if (!isrmw) {
                   3104:        unlock2(d);
                   3105:        unlock2(s);
                   3106:     }
                   3107:     else {
                   3108:        unlock2(s);
                   3109:     }
                   3110: }
                   3111: MENDFUNC(2,sign_extend_32_rr,(W4 d, R2 s))
                   3112: #endif
                   3113: 
                   3114: MIDFUNC(2,sign_extend_16_rr,(W4 d, R2 s))
                   3115: {
                   3116:     int isrmw;
                   3117: 
                   3118:     if (isconst(s)) {
                   3119:        set_const(d,(uae_s32)(uae_s16)live.state[s].val);
                   3120:        return;
                   3121:     }
                   3122: 
                   3123:     CLOBBER_SE16;
                   3124:     isrmw=(s==d);
                   3125:     if (!isrmw) {
                   3126:        s=readreg(s,2);
                   3127:        d=writereg(d,4);
                   3128:     }
                   3129:     else {  /* If we try to lock this twice, with different sizes, we
                   3130:               are int trouble! */
                   3131:        s=d=rmw(s,4,2);
                   3132:     }
                   3133:     raw_sign_extend_16_rr(d,s);
                   3134:     if (!isrmw) {
                   3135:        unlock2(d);
                   3136:        unlock2(s);
                   3137:     }
                   3138:     else {
                   3139:        unlock2(s);
                   3140:     }
                   3141: }
                   3142: MENDFUNC(2,sign_extend_16_rr,(W4 d, R2 s))
                   3143: 
                   3144: MIDFUNC(2,sign_extend_8_rr,(W4 d, R1 s))
                   3145: {
                   3146:     int isrmw;
                   3147: 
                   3148:     if (isconst(s)) {
                   3149:        set_const(d,(uae_s32)(uae_s8)live.state[s].val);
                   3150:        return;
                   3151:     }
                   3152: 
                   3153:     isrmw=(s==d);
                   3154:     CLOBBER_SE8;
                   3155:     if (!isrmw) {
                   3156:        s=readreg(s,1);
                   3157:        d=writereg(d,4);
                   3158:     }
                   3159:     else {  /* If we try to lock this twice, with different sizes, we
                   3160:               are int trouble! */
                   3161:        s=d=rmw(s,4,1);
                   3162:     }
                   3163:   
                   3164:     raw_sign_extend_8_rr(d,s);
                   3165: 
                   3166:     if (!isrmw) {
                   3167:        unlock2(d);
                   3168:        unlock2(s);
                   3169:     }
                   3170:     else {
                   3171:        unlock2(s);
                   3172:     }
                   3173: }
                   3174: MENDFUNC(2,sign_extend_8_rr,(W4 d, R1 s))
                   3175: 
                   3176: 
                   3177: MIDFUNC(2,zero_extend_16_rr,(W4 d, R2 s))
                   3178: {
                   3179:     int isrmw;
                   3180: 
                   3181:     if (isconst(s)) {
                   3182:        set_const(d,(uae_u32)(uae_u16)live.state[s].val);
                   3183:        return;
                   3184:     }
                   3185: 
                   3186:     isrmw=(s==d);
                   3187:     CLOBBER_ZE16;
                   3188:     if (!isrmw) {
                   3189:        s=readreg(s,2);
                   3190:        d=writereg(d,4);
                   3191:     }
                   3192:     else {  /* If we try to lock this twice, with different sizes, we
                   3193:               are int trouble! */
                   3194:        s=d=rmw(s,4,2);
                   3195:     }
                   3196:     raw_zero_extend_16_rr(d,s);
                   3197:     if (!isrmw) {
                   3198:        unlock2(d);
                   3199:        unlock2(s);
                   3200:     }
                   3201:     else {
                   3202:        unlock2(s);
                   3203:     }
                   3204: }
                   3205: MENDFUNC(2,zero_extend_16_rr,(W4 d, R2 s))
                   3206: 
                   3207: MIDFUNC(2,zero_extend_8_rr,(W4 d, R1 s))
                   3208: {
                   3209:     int isrmw;
                   3210:     if (isconst(s)) {
                   3211:        set_const(d,(uae_u32)(uae_u8)live.state[s].val);
                   3212:        return;
                   3213:     }
                   3214: 
                   3215:     isrmw=(s==d);
                   3216:     CLOBBER_ZE8;
                   3217:     if (!isrmw) {
                   3218:        s=readreg(s,1);
                   3219:        d=writereg(d,4);
                   3220:     }
                   3221:     else {  /* If we try to lock this twice, with different sizes, we
                   3222:               are int trouble! */
                   3223:        s=d=rmw(s,4,1);
                   3224:     }
                   3225:   
                   3226:     raw_zero_extend_8_rr(d,s);
                   3227: 
                   3228:     if (!isrmw) {
                   3229:        unlock2(d);
                   3230:        unlock2(s);
                   3231:     }
                   3232:     else {
                   3233:        unlock2(s);
                   3234:     }
                   3235: }
                   3236: MENDFUNC(2,zero_extend_8_rr,(W4 d, R1 s))
                   3237: 
                   3238: MIDFUNC(2,mov_b_rr,(W1 d, R1 s))
                   3239: {
                   3240:     if (d==s)
                   3241:        return;
                   3242:     if (isconst(s)) {
                   3243:        COMPCALL(mov_b_ri)(d,(uae_u8)live.state[s].val);
                   3244:        return;
                   3245:     }
                   3246: 
                   3247:     CLOBBER_MOV;
                   3248:     s=readreg(s,1);
                   3249:     d=writereg(d,1);
                   3250:     raw_mov_b_rr(d,s);
                   3251:     unlock2(d);
                   3252:     unlock2(s);
                   3253: }
                   3254: MENDFUNC(2,mov_b_rr,(W1 d, R1 s))
                   3255: 
                   3256: MIDFUNC(2,mov_w_rr,(W2 d, R2 s))
                   3257: {
                   3258:     if (d==s)
                   3259:        return;
                   3260:     if (isconst(s)) {
                   3261:        COMPCALL(mov_w_ri)(d,(uae_u16)live.state[s].val);
                   3262:        return;
                   3263:     }
                   3264: 
                   3265:     CLOBBER_MOV;
                   3266:     s=readreg(s,2);
                   3267:     d=writereg(d,2);
                   3268:     raw_mov_w_rr(d,s);
                   3269:     unlock2(d);
                   3270:     unlock2(s);
                   3271: }
                   3272: MENDFUNC(2,mov_w_rr,(W2 d, R2 s))
                   3273: 
                   3274: 
                   3275: MIDFUNC(4,mov_l_rrm_indexed,(W4 d,R4 baser, R4 index, IMM factor))
                   3276: {
                   3277:     CLOBBER_MOV;
                   3278:     baser=readreg(baser,4);
                   3279:     index=readreg(index,4);
                   3280:     d=writereg(d,4);
                   3281: 
                   3282:     raw_mov_l_rrm_indexed(d,baser,index,factor);
                   3283:     unlock2(d);
                   3284:     unlock2(baser);
                   3285:     unlock2(index);
                   3286: }
                   3287: MENDFUNC(4,mov_l_rrm_indexed,(W4 d,R4 baser, R4 index, IMM factor))
                   3288: 
                   3289: MIDFUNC(4,mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor))
                   3290: {
                   3291:     CLOBBER_MOV;
                   3292:     baser=readreg(baser,4);
                   3293:     index=readreg(index,4);
                   3294:     d=writereg(d,2);
                   3295: 
                   3296:     raw_mov_w_rrm_indexed(d,baser,index,factor);
                   3297:     unlock2(d);
                   3298:     unlock2(baser);
                   3299:     unlock2(index);
                   3300: }
                   3301: MENDFUNC(4,mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor))
                   3302: 
                   3303: MIDFUNC(4,mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor))
                   3304: {
                   3305:     CLOBBER_MOV;
                   3306:     baser=readreg(baser,4);
                   3307:     index=readreg(index,4);
                   3308:     d=writereg(d,1);
                   3309: 
                   3310:     raw_mov_b_rrm_indexed(d,baser,index,factor);
                   3311: 
                   3312:     unlock2(d);
                   3313:     unlock2(baser);
                   3314:     unlock2(index);
                   3315: }
                   3316: MENDFUNC(4,mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor))
                   3317: 
                   3318: 
                   3319: MIDFUNC(4,mov_l_mrr_indexed,(R4 baser, R4 index, IMM factor, R4 s))
                   3320: {
                   3321:     CLOBBER_MOV;
                   3322:     baser=readreg(baser,4);
                   3323:     index=readreg(index,4);
                   3324:     s=readreg(s,4);
                   3325: 
                   3326:     Dif (baser==s || index==s) 
                   3327:        abort();
                   3328: 
                   3329: 
                   3330:     raw_mov_l_mrr_indexed(baser,index,factor,s);
                   3331:     unlock2(s);
                   3332:     unlock2(baser);
                   3333:     unlock2(index);
                   3334: }
                   3335: MENDFUNC(4,mov_l_mrr_indexed,(R4 baser, R4 index, IMM factor, R4 s))
                   3336: 
                   3337: MIDFUNC(4,mov_w_mrr_indexed,(R4 baser, R4 index, IMM factor, R2 s))
                   3338: {
                   3339:     CLOBBER_MOV;
                   3340:     baser=readreg(baser,4);
                   3341:     index=readreg(index,4);
                   3342:     s=readreg(s,2);
                   3343: 
                   3344:     raw_mov_w_mrr_indexed(baser,index,factor,s);
                   3345:     unlock2(s);
                   3346:     unlock2(baser);
                   3347:     unlock2(index);
                   3348: }
                   3349: MENDFUNC(4,mov_w_mrr_indexed,(R4 baser, R4 index, IMM factor, R2 s))
                   3350: 
                   3351: MIDFUNC(4,mov_b_mrr_indexed,(R4 baser, R4 index, IMM factor, R1 s))
                   3352: {
                   3353:     CLOBBER_MOV;
                   3354:     s=readreg(s,1);
                   3355:     baser=readreg(baser,4);
                   3356:     index=readreg(index,4);
                   3357: 
                   3358:     raw_mov_b_mrr_indexed(baser,index,factor,s);
                   3359:     unlock2(s);
                   3360:     unlock2(baser);
                   3361:     unlock2(index);
                   3362: }
                   3363: MENDFUNC(4,mov_b_mrr_indexed,(R4 baser, R4 index, IMM factor, R1 s))
                   3364: 
                   3365: 
                   3366: MIDFUNC(5,mov_l_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R4 s))
                   3367: {
                   3368:     int basereg=baser;
                   3369:     int indexreg=index;
                   3370: 
                   3371:     CLOBBER_MOV;
                   3372:     s=readreg(s,4);
                   3373:     baser=readreg_offset(baser,4);
                   3374:     index=readreg_offset(index,4);
                   3375: 
                   3376:     base+=get_offset(basereg);
                   3377:     base+=factor*get_offset(indexreg);
                   3378: 
                   3379:     raw_mov_l_bmrr_indexed(base,baser,index,factor,s);
                   3380:     unlock2(s);
                   3381:     unlock2(baser);
                   3382:     unlock2(index);
                   3383: }
                   3384: MENDFUNC(5,mov_l_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R4 s))
                   3385: 
                   3386: MIDFUNC(5,mov_w_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R2 s))
                   3387: {
                   3388:     int basereg=baser;
                   3389:     int indexreg=index;
                   3390: 
                   3391:     CLOBBER_MOV;
                   3392:     s=readreg(s,2);
                   3393:     baser=readreg_offset(baser,4);
                   3394:     index=readreg_offset(index,4);
                   3395: 
                   3396:     base+=get_offset(basereg);
                   3397:     base+=factor*get_offset(indexreg);
                   3398: 
                   3399:     raw_mov_w_bmrr_indexed(base,baser,index,factor,s);
                   3400:     unlock2(s);
                   3401:     unlock2(baser);
                   3402:     unlock2(index);
                   3403: }
                   3404: MENDFUNC(5,mov_w_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R2 s))
                   3405: 
                   3406: MIDFUNC(5,mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s))
                   3407: {
                   3408:     int basereg=baser;
                   3409:     int indexreg=index;
                   3410: 
                   3411:     CLOBBER_MOV;
                   3412:     s=readreg(s,1);
                   3413:     baser=readreg_offset(baser,4);
                   3414:     index=readreg_offset(index,4);
                   3415: 
                   3416:     base+=get_offset(basereg);
                   3417:     base+=factor*get_offset(indexreg);
                   3418: 
                   3419:     raw_mov_b_bmrr_indexed(base,baser,index,factor,s);
                   3420:     unlock2(s);
                   3421:     unlock2(baser);
                   3422:     unlock2(index);
                   3423: }
                   3424: MENDFUNC(5,mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s))
                   3425: 
                   3426: 
                   3427: 
                   3428: /* Read a long from base+baser+factor*index */
                   3429: MIDFUNC(5,mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor))
                   3430: {
                   3431:     int basereg=baser;
                   3432:     int indexreg=index;
                   3433: 
                   3434:     CLOBBER_MOV;
                   3435:     baser=readreg_offset(baser,4);
                   3436:     index=readreg_offset(index,4);
                   3437:     base+=get_offset(basereg);
                   3438:     base+=factor*get_offset(indexreg);    
                   3439:     d=writereg(d,4);
                   3440:     raw_mov_l_brrm_indexed(d,base,baser,index,factor);
                   3441:     unlock2(d);
                   3442:     unlock2(baser);
                   3443:     unlock2(index);
                   3444: }
                   3445: MENDFUNC(5,mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor))
                   3446: 
                   3447: 
                   3448: MIDFUNC(5,mov_w_brrm_indexed,(W2 d, IMM base, R4 baser, R4 index, IMM factor))
                   3449: {
                   3450:     int basereg=baser;
                   3451:     int indexreg=index;
                   3452: 
                   3453:     CLOBBER_MOV;
                   3454:     remove_offset(d,-1);
                   3455:     baser=readreg_offset(baser,4);
                   3456:     index=readreg_offset(index,4);
                   3457:     base+=get_offset(basereg);
                   3458:     base+=factor*get_offset(indexreg);    
                   3459:     d=writereg(d,2);
                   3460:     raw_mov_w_brrm_indexed(d,base,baser,index,factor);
                   3461:     unlock2(d);
                   3462:     unlock2(baser);
                   3463:     unlock2(index);
                   3464: }
                   3465: MENDFUNC(5,mov_w_brrm_indexed,(W2 d, IMM base, R4 baser, R4 index, IMM factor))
                   3466: 
                   3467: 
                   3468: MIDFUNC(5,mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index, IMM factor))
                   3469: {
                   3470:     int basereg=baser;
                   3471:     int indexreg=index;
                   3472: 
                   3473:     CLOBBER_MOV;
                   3474:     remove_offset(d,-1);
                   3475:     baser=readreg_offset(baser,4);
                   3476:     index=readreg_offset(index,4);
                   3477:     base+=get_offset(basereg);
                   3478:     base+=factor*get_offset(indexreg);    
                   3479:     d=writereg(d,1);
                   3480:     raw_mov_b_brrm_indexed(d,base,baser,index,factor);
                   3481:     unlock2(d);
                   3482:     unlock2(baser);
                   3483:     unlock2(index);
                   3484: }
                   3485: MENDFUNC(5,mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index, IMM factor))
                   3486: 
                   3487: /* Read a long from base+factor*index */
                   3488: MIDFUNC(4,mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor))
                   3489: {
                   3490:     int indexreg=index;
                   3491: 
                   3492:     if (isconst(index)) {
                   3493:        COMPCALL(mov_l_rm)(d,base+factor*live.state[index].val);
                   3494:        return;
                   3495:     }
                   3496: 
                   3497:     CLOBBER_MOV;
                   3498:     index=readreg_offset(index,4);
                   3499:     base+=get_offset(indexreg)*factor;
                   3500:     d=writereg(d,4);
                   3501: 
                   3502:     raw_mov_l_rm_indexed(d,base,index,factor);
                   3503:     unlock2(index);
                   3504:     unlock2(d);
                   3505: }
                   3506: MENDFUNC(4,mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor))
                   3507: 
                   3508: 
                   3509: /* read the long at the address contained in s+offset and store in d */
                   3510: MIDFUNC(3,mov_l_rR,(W4 d, R4 s, IMM offset))
                   3511: {
                   3512:     if (isconst(s)) {
                   3513:        COMPCALL(mov_l_rm)(d,live.state[s].val+offset);
                   3514:        return;
                   3515:     }
                   3516:     CLOBBER_MOV;
                   3517:     s=readreg(s,4);
                   3518:     d=writereg(d,4);
                   3519: 
                   3520:     raw_mov_l_rR(d,s,offset);
                   3521:     unlock2(d);
                   3522:     unlock2(s);
                   3523: }
                   3524: MENDFUNC(3,mov_l_rR,(W4 d, R4 s, IMM offset))
                   3525: 
                   3526: /* read the word at the address contained in s+offset and store in d */
                   3527: MIDFUNC(3,mov_w_rR,(W2 d, R4 s, IMM offset))
                   3528: {
                   3529:     if (isconst(s)) {
                   3530:        COMPCALL(mov_w_rm)(d,live.state[s].val+offset);
                   3531:        return;
                   3532:     }
                   3533:     CLOBBER_MOV;
                   3534:     s=readreg(s,4);
                   3535:     d=writereg(d,2);
                   3536: 
                   3537:     raw_mov_w_rR(d,s,offset);
                   3538:     unlock2(d);
                   3539:     unlock2(s);
                   3540: }
                   3541: MENDFUNC(3,mov_w_rR,(W2 d, R4 s, IMM offset))
                   3542: 
                   3543: /* read the word at the address contained in s+offset and store in d */
                   3544: MIDFUNC(3,mov_b_rR,(W1 d, R4 s, IMM offset))
                   3545: {
                   3546:     if (isconst(s)) {
                   3547:        COMPCALL(mov_b_rm)(d,live.state[s].val+offset);
                   3548:        return;
                   3549:     }
                   3550:     CLOBBER_MOV;
                   3551:     s=readreg(s,4);
                   3552:     d=writereg(d,1);
                   3553: 
                   3554:     raw_mov_b_rR(d,s,offset);
                   3555:     unlock2(d);
                   3556:     unlock2(s);
                   3557: }
                   3558: MENDFUNC(3,mov_b_rR,(W1 d, R4 s, IMM offset))
                   3559: 
                   3560: /* read the long at the address contained in s+offset and store in d */
                   3561: MIDFUNC(3,mov_l_brR,(W4 d, R4 s, IMM offset))
                   3562: {
                   3563:     int sreg=s;
                   3564:     if (isconst(s)) {
                   3565:        COMPCALL(mov_l_rm)(d,live.state[s].val+offset);
                   3566:        return;
                   3567:     }
                   3568:     CLOBBER_MOV;
                   3569:     s=readreg_offset(s,4);
                   3570:     offset+=get_offset(sreg);
                   3571:     d=writereg(d,4);
                   3572:     
                   3573:     raw_mov_l_brR(d,s,offset);
                   3574:     unlock2(d);
                   3575:     unlock2(s);
                   3576: }
                   3577: MENDFUNC(3,mov_l_brR,(W4 d, R4 s, IMM offset))
                   3578: 
                   3579: /* read the word at the address contained in s+offset and store in d */
                   3580: MIDFUNC(3,mov_w_brR,(W2 d, R4 s, IMM offset))
                   3581: {
                   3582:     int sreg=s;
                   3583:     if (isconst(s)) {
                   3584:        COMPCALL(mov_w_rm)(d,live.state[s].val+offset);
                   3585:        return;
                   3586:     }
                   3587:     CLOBBER_MOV;
                   3588:     remove_offset(d,-1);
                   3589:     s=readreg_offset(s,4);
                   3590:     offset+=get_offset(sreg);
                   3591:     d=writereg(d,2);
                   3592: 
                   3593:     raw_mov_w_brR(d,s,offset);
                   3594:     unlock2(d);
                   3595:     unlock2(s);
                   3596: }
                   3597: MENDFUNC(3,mov_w_brR,(W2 d, R4 s, IMM offset))
                   3598: 
                   3599: /* read the word at the address contained in s+offset and store in d */
                   3600: MIDFUNC(3,mov_b_brR,(W1 d, R4 s, IMM offset))
                   3601: {
                   3602:     int sreg=s;
                   3603:     if (isconst(s)) {
                   3604:        COMPCALL(mov_b_rm)(d,live.state[s].val+offset);
                   3605:        return;
                   3606:     }
                   3607:     CLOBBER_MOV;
                   3608:     remove_offset(d,-1);
                   3609:     s=readreg_offset(s,4);
                   3610:     offset+=get_offset(sreg);
                   3611:     d=writereg(d,1);
                   3612: 
                   3613:     raw_mov_b_brR(d,s,offset);
                   3614:     unlock2(d);
                   3615:     unlock2(s);
                   3616: }
                   3617: MENDFUNC(3,mov_b_brR,(W1 d, R4 s, IMM offset))
                   3618: 
                   3619: MIDFUNC(3,mov_l_Ri,(R4 d, IMM i, IMM offset))
                   3620: {
                   3621:     int dreg=d;
                   3622:     if (isconst(d)) {
                   3623:        COMPCALL(mov_l_mi)(live.state[d].val+offset,i);
                   3624:        return;
                   3625:     }
                   3626: 
                   3627:     CLOBBER_MOV;
                   3628:     d=readreg_offset(d,4);
                   3629:     offset+=get_offset(dreg);
                   3630:     raw_mov_l_Ri(d,i,offset);
                   3631:     unlock2(d);
                   3632: }
                   3633: MENDFUNC(3,mov_l_Ri,(R4 d, IMM i, IMM offset))
                   3634: 
                   3635: MIDFUNC(3,mov_w_Ri,(R4 d, IMM i, IMM offset))
                   3636: {
                   3637:     int dreg=d;
                   3638:     if (isconst(d)) {
                   3639:        COMPCALL(mov_w_mi)(live.state[d].val+offset,i);
                   3640:        return;
                   3641:     }
                   3642: 
                   3643:     CLOBBER_MOV;
                   3644:     d=readreg_offset(d,4);
                   3645:     offset+=get_offset(dreg);
                   3646:     raw_mov_w_Ri(d,i,offset);
                   3647:     unlock2(d);
                   3648: }
                   3649: MENDFUNC(3,mov_w_Ri,(R4 d, IMM i, IMM offset))
                   3650: 
                   3651: MIDFUNC(3,mov_b_Ri,(R4 d, IMM i, IMM offset))
                   3652: {
                   3653:     int dreg=d;
                   3654:     if (isconst(d)) {
                   3655:        COMPCALL(mov_b_mi)(live.state[d].val+offset,i);
                   3656:        return;
                   3657:     }
                   3658: 
                   3659:     CLOBBER_MOV;
                   3660:     d=readreg_offset(d,4);
                   3661:     offset+=get_offset(dreg);
                   3662:     raw_mov_b_Ri(d,i,offset);
                   3663:     unlock2(d);
                   3664: }
                   3665: MENDFUNC(3,mov_b_Ri,(R4 d, IMM i, IMM offset))
                   3666: 
                   3667:      /* Warning! OFFSET is byte sized only! */
                   3668: MIDFUNC(3,mov_l_Rr,(R4 d, R4 s, IMM offset))
                   3669: {
                   3670:     if (isconst(d)) {
                   3671:        COMPCALL(mov_l_mr)(live.state[d].val+offset,s);
                   3672:        return;
                   3673:     }
                   3674:     if (isconst(s)) {
                   3675:        COMPCALL(mov_l_Ri)(d,live.state[s].val,offset);
                   3676:        return;
                   3677:     }
                   3678: 
                   3679:     CLOBBER_MOV;
                   3680:     s=readreg(s,4);
                   3681:     d=readreg(d,4);
                   3682: 
                   3683:     raw_mov_l_Rr(d,s,offset);
                   3684:     unlock2(d);
                   3685:     unlock2(s);
                   3686: }
                   3687: MENDFUNC(3,mov_l_Rr,(R4 d, R4 s, IMM offset))
                   3688: 
                   3689: MIDFUNC(3,mov_w_Rr,(R4 d, R2 s, IMM offset))
                   3690: {
                   3691:     if (isconst(d)) {
                   3692:        COMPCALL(mov_w_mr)(live.state[d].val+offset,s);
                   3693:        return;
                   3694:     }
                   3695:     if (isconst(s)) {
                   3696:        COMPCALL(mov_w_Ri)(d,(uae_u16)live.state[s].val,offset);
                   3697:        return;
                   3698:     }
                   3699: 
                   3700:     CLOBBER_MOV;
                   3701:     s=readreg(s,2);
                   3702:     d=readreg(d,4);
                   3703:     raw_mov_w_Rr(d,s,offset);
                   3704:     unlock2(d);
                   3705:     unlock2(s);
                   3706: }
                   3707: MENDFUNC(3,mov_w_Rr,(R4 d, R2 s, IMM offset))
                   3708: 
                   3709: MIDFUNC(3,mov_b_Rr,(R4 d, R1 s, IMM offset))
                   3710: {
                   3711:     if (isconst(d)) {
                   3712:        COMPCALL(mov_b_mr)(live.state[d].val+offset,s);
                   3713:        return;
                   3714:     }
                   3715:     if (isconst(s)) {
                   3716:        COMPCALL(mov_b_Ri)(d,(uae_u8)live.state[s].val,offset);
                   3717:        return;
                   3718:     }
                   3719: 
                   3720:     CLOBBER_MOV;
                   3721:     s=readreg(s,1);
                   3722:     d=readreg(d,4);
                   3723:     raw_mov_b_Rr(d,s,offset);
                   3724:     unlock2(d);
                   3725:     unlock2(s);
                   3726: }
                   3727: MENDFUNC(3,mov_b_Rr,(R4 d, R1 s, IMM offset))
                   3728: 
                   3729: MIDFUNC(3,lea_l_brr,(W4 d, R4 s, IMM offset))
                   3730: {
                   3731:     if (isconst(s)) {
                   3732:        COMPCALL(mov_l_ri)(d,live.state[s].val+offset);
                   3733:        return;
                   3734:     }
                   3735: #if USE_OFFSET
                   3736:     if (d==s) {
                   3737:        add_offset(d,offset);
                   3738:        return;
                   3739:     }
                   3740: #endif
                   3741:     CLOBBER_LEA;
                   3742:     s=readreg(s,4);
                   3743:     d=writereg(d,4);
                   3744:     raw_lea_l_brr(d,s,offset);
                   3745:     unlock2(d);
                   3746:     unlock2(s);
                   3747: }
                   3748: MENDFUNC(3,lea_l_brr,(W4 d, R4 s, IMM offset))
                   3749: 
                   3750: MIDFUNC(5,lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset))
                   3751: {
                   3752:     if (!offset) {
                   3753:        COMPCALL(lea_l_rr_indexed)(d,s,index,factor);
                   3754:        return;
                   3755:     }
                   3756:     CLOBBER_LEA;
                   3757:     s=readreg(s,4);
                   3758:     index=readreg(index,4);
                   3759:     d=writereg(d,4);
                   3760: 
                   3761:     raw_lea_l_brr_indexed(d,s,index,factor,offset);
                   3762:     unlock2(d);
                   3763:     unlock2(index);
                   3764:     unlock2(s);
                   3765: }
                   3766: MENDFUNC(5,lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset))
                   3767: 
                   3768: MIDFUNC(4,lea_l_rr_indexed,(W4 d, R4 s, R4 index, IMM factor))
                   3769: {
                   3770:     CLOBBER_LEA;
                   3771:     s=readreg(s,4);
                   3772:     index=readreg(index,4);
                   3773:     d=writereg(d,4);
                   3774: 
                   3775:     raw_lea_l_rr_indexed(d,s,index,factor);
                   3776:     unlock2(d);
                   3777:     unlock2(index);
                   3778:     unlock2(s);
                   3779: }
                   3780: MENDFUNC(4,lea_l_rr_indexed,(W4 d, R4 s, R4 index, IMM factor))
                   3781: 
                   3782: /* write d to the long at the address contained in s+offset */
                   3783: MIDFUNC(3,mov_l_bRr,(R4 d, R4 s, IMM offset))
                   3784: {
                   3785:     int dreg=d;
                   3786:     if (isconst(d)) {
                   3787:        COMPCALL(mov_l_mr)(live.state[d].val+offset,s);
                   3788:        return;
                   3789:     }
                   3790: 
                   3791:     CLOBBER_MOV;
                   3792:     s=readreg(s,4);
                   3793:     d=readreg_offset(d,4);
                   3794:     offset+=get_offset(dreg);
                   3795: 
                   3796:     raw_mov_l_bRr(d,s,offset);
                   3797:     unlock2(d);
                   3798:     unlock2(s);
                   3799: }
                   3800: MENDFUNC(3,mov_l_bRr,(R4 d, R4 s, IMM offset))
                   3801: 
                   3802: /* write the word at the address contained in s+offset and store in d */
                   3803: MIDFUNC(3,mov_w_bRr,(R4 d, R2 s, IMM offset))
                   3804: {
                   3805:     int dreg=d;
                   3806: 
                   3807:     if (isconst(d)) {
                   3808:        COMPCALL(mov_w_mr)(live.state[d].val+offset,s);
                   3809:        return;
                   3810:     }
                   3811: 
                   3812:     CLOBBER_MOV;
                   3813:     s=readreg(s,2);
                   3814:     d=readreg_offset(d,4);
                   3815:     offset+=get_offset(dreg);
                   3816:     raw_mov_w_bRr(d,s,offset);
                   3817:     unlock2(d);
                   3818:     unlock2(s);
                   3819: }
                   3820: MENDFUNC(3,mov_w_bRr,(R4 d, R2 s, IMM offset))
                   3821: 
                   3822: MIDFUNC(3,mov_b_bRr,(R4 d, R1 s, IMM offset))
                   3823: {
                   3824:     int dreg=d;
                   3825:     if (isconst(d)) {
                   3826:        COMPCALL(mov_b_mr)(live.state[d].val+offset,s);
                   3827:        return;
                   3828:     }
                   3829: 
                   3830:     CLOBBER_MOV;
                   3831:     s=readreg(s,1);
                   3832:     d=readreg_offset(d,4);
                   3833:     offset+=get_offset(dreg);
                   3834:     raw_mov_b_bRr(d,s,offset);
                   3835:     unlock2(d);
                   3836:     unlock2(s);
                   3837: }
                   3838: MENDFUNC(3,mov_b_bRr,(R4 d, R1 s, IMM offset))
                   3839: 
                   3840: MIDFUNC(1,bswap_32,(RW4 r))
                   3841: {
                   3842:     int reg=r;
                   3843: 
                   3844:     if (isconst(r)) {
                   3845:        uae_u32 oldv=live.state[r].val;
                   3846:        live.state[r].val=reverse32(oldv);
                   3847:        return;
                   3848:     }
                   3849:     
                   3850:     CLOBBER_SW32;
                   3851:     r=rmw(r,4,4);  
                   3852:     raw_bswap_32(r);
                   3853:     unlock2(r);
                   3854: }
                   3855: MENDFUNC(1,bswap_32,(RW4 r))
                   3856: 
                   3857: MIDFUNC(1,bswap_16,(RW2 r))
                   3858: {
                   3859:     if (isconst(r)) {
                   3860:        uae_u32 oldv=live.state[r].val;
                   3861:        live.state[r].val=((oldv>>8)&0xff) | ((oldv<<8)&0xff00) |
                   3862:            (oldv&0xffff0000);
                   3863:        return;
                   3864:     }
                   3865: 
                   3866:     CLOBBER_SW16;
                   3867:     r=rmw(r,2,2);
                   3868:   
                   3869:     raw_bswap_16(r);
                   3870:     unlock2(r);
                   3871: }
                   3872: MENDFUNC(1,bswap_16,(RW2 r))
                   3873: 
                   3874: 
                   3875: 
                   3876: MIDFUNC(2,mov_l_rr,(W4 d, R4 s))
                   3877: {
                   3878:     int olds;
                   3879: 
                   3880:     if (d==s) { /* How pointless! */
                   3881:        return;
                   3882:     }
                   3883:     if (isconst(s)) {
                   3884:        COMPCALL(mov_l_ri)(d,live.state[s].val);
                   3885:        return;
                   3886:     }
                   3887:     olds=s;
                   3888:     disassociate(d);
                   3889:     s=readreg_offset(s,4);
                   3890:     live.state[d].realreg=s;
                   3891:     live.state[d].realind=live.nat[s].nholds;
                   3892:     live.state[d].val=live.state[olds].val;
                   3893:     live.state[d].validsize=4;
                   3894:     live.state[d].dirtysize=4;
                   3895:     set_status(d,DIRTY);
                   3896: 
                   3897:     live.nat[s].holds[live.nat[s].nholds]=d;
                   3898:     live.nat[s].nholds++;
                   3899:     log_clobberreg(d);
                   3900:     /* write_log("Added %d to nreg %d(%d), now holds %d regs\n",
                   3901:        d,s,live.state[d].realind,live.nat[s].nholds); */
                   3902:     unlock2(s);
                   3903: }
                   3904: MENDFUNC(2,mov_l_rr,(W4 d, R4 s))
                   3905: 
                   3906: MIDFUNC(2,mov_l_mr,(IMM d, R4 s))
                   3907: {
                   3908:     if (isconst(s)) {
                   3909:        COMPCALL(mov_l_mi)(d,live.state[s].val);
                   3910:        return;
                   3911:     }
                   3912:     CLOBBER_MOV;
                   3913:     s=readreg(s,4);
                   3914: 
                   3915:     raw_mov_l_mr(d,s);
                   3916:     unlock2(s);
                   3917: }
                   3918: MENDFUNC(2,mov_l_mr,(IMM d, R4 s))
                   3919: 
                   3920: 
                   3921: MIDFUNC(2,mov_w_mr,(IMM d, R2 s))
                   3922: {
                   3923:     if (isconst(s)) {
                   3924:        COMPCALL(mov_w_mi)(d,(uae_u16)live.state[s].val);
                   3925:        return;
                   3926:     }
                   3927:     CLOBBER_MOV;
                   3928:     s=readreg(s,2);
                   3929: 
                   3930:     raw_mov_w_mr(d,s);
                   3931:     unlock2(s);
                   3932: }
                   3933: MENDFUNC(2,mov_w_mr,(IMM d, R2 s))
                   3934: 
                   3935: MIDFUNC(2,mov_w_rm,(W2 d, IMM s))
                   3936: {
                   3937:     CLOBBER_MOV;
                   3938:     d=writereg(d,2);
                   3939: 
                   3940:     raw_mov_w_rm(d,s);
                   3941:     unlock2(d);
                   3942: }
                   3943: MENDFUNC(2,mov_w_rm,(W2 d, IMM s))
                   3944: 
                   3945: MIDFUNC(2,mov_b_mr,(IMM d, R1 s))
                   3946: {
                   3947:     if (isconst(s)) {
                   3948:        COMPCALL(mov_b_mi)(d,(uae_u8)live.state[s].val);
                   3949:        return;
                   3950:     }
                   3951: 
                   3952:     CLOBBER_MOV;
                   3953:     s=readreg(s,1);
                   3954: 
                   3955:     raw_mov_b_mr(d,s);
                   3956:     unlock2(s);
                   3957: }
                   3958: MENDFUNC(2,mov_b_mr,(IMM d, R1 s))
                   3959: 
                   3960: MIDFUNC(2,mov_b_rm,(W1 d, IMM s))
                   3961: {
                   3962:     CLOBBER_MOV;
                   3963:     d=writereg(d,1);
                   3964: 
                   3965:     raw_mov_b_rm(d,s);
                   3966:     unlock2(d);
                   3967: }
                   3968: MENDFUNC(2,mov_b_rm,(W1 d, IMM s))
                   3969: 
                   3970: MIDFUNC(2,mov_l_ri,(W4 d, IMM s))
                   3971: {
                   3972:     set_const(d,s);
                   3973:     return;
                   3974: }
                   3975: MENDFUNC(2,mov_l_ri,(W4 d, IMM s))
                   3976: 
                   3977: MIDFUNC(2,mov_w_ri,(W2 d, IMM s))
                   3978: {
                   3979:     CLOBBER_MOV;
                   3980:     d=writereg(d,2);
                   3981: 
                   3982:     raw_mov_w_ri(d,s);
                   3983:     unlock2(d);
                   3984: }
                   3985: MENDFUNC(2,mov_w_ri,(W2 d, IMM s))
                   3986: 
                   3987: MIDFUNC(2,mov_b_ri,(W1 d, IMM s))
                   3988: {
                   3989:     CLOBBER_MOV;
                   3990:     d=writereg(d,1);
                   3991: 
                   3992:     raw_mov_b_ri(d,s);
                   3993:     unlock2(d);
                   3994: }
                   3995: MENDFUNC(2,mov_b_ri,(W1 d, IMM s))
                   3996: 
                   3997: 
                   3998: MIDFUNC(2,add_l_mi,(IMM d, IMM s)) 
                   3999: {
                   4000:     CLOBBER_ADD;
                   4001:     raw_add_l_mi(d,s) ;
                   4002: }
                   4003: MENDFUNC(2,add_l_mi,(IMM d, IMM s)) 
                   4004: 
                   4005: MIDFUNC(2,add_w_mi,(IMM d, IMM s)) 
                   4006: {
                   4007:     CLOBBER_ADD;
                   4008:     raw_add_w_mi(d,s) ;
                   4009: }
                   4010: MENDFUNC(2,add_w_mi,(IMM d, IMM s)) 
                   4011: 
                   4012: MIDFUNC(2,add_b_mi,(IMM d, IMM s)) 
                   4013: {
                   4014:     CLOBBER_ADD;
                   4015:     raw_add_b_mi(d,s) ;
                   4016: }
                   4017: MENDFUNC(2,add_b_mi,(IMM d, IMM s)) 
                   4018: 
                   4019: 
                   4020: MIDFUNC(2,test_l_ri,(R4 d, IMM i))
                   4021: {
                   4022:     CLOBBER_TEST;
                   4023:     d=readreg(d,4);
                   4024: 
                   4025:     raw_test_l_ri(d,i);
                   4026:     unlock2(d);
                   4027: }
                   4028: MENDFUNC(2,test_l_ri,(R4 d, IMM i))
                   4029: 
                   4030: MIDFUNC(2,test_l_rr,(R4 d, R4 s))
                   4031: {
                   4032:     CLOBBER_TEST;
                   4033:     d=readreg(d,4);
                   4034:     s=readreg(s,4);
                   4035: 
                   4036:     raw_test_l_rr(d,s);;
                   4037:     unlock2(d);
                   4038:     unlock2(s);
                   4039: }
                   4040: MENDFUNC(2,test_l_rr,(R4 d, R4 s))
                   4041: 
                   4042: MIDFUNC(2,test_w_rr,(R2 d, R2 s))
                   4043: {
                   4044:     CLOBBER_TEST;
                   4045:     d=readreg(d,2);
                   4046:     s=readreg(s,2);
                   4047: 
                   4048:     raw_test_w_rr(d,s);
                   4049:     unlock2(d);
                   4050:     unlock2(s);
                   4051: }
                   4052: MENDFUNC(2,test_w_rr,(R2 d, R2 s))
                   4053: 
                   4054: MIDFUNC(2,test_b_rr,(R1 d, R1 s))
                   4055: {
                   4056:     CLOBBER_TEST;
                   4057:     d=readreg(d,1);
                   4058:     s=readreg(s,1);
                   4059: 
                   4060:     raw_test_b_rr(d,s);
                   4061:     unlock2(d);
                   4062:     unlock2(s);
                   4063: }
                   4064: MENDFUNC(2,test_b_rr,(R1 d, R1 s))
                   4065: 
                   4066: 
                   4067: MIDFUNC(2,and_l_ri,(RW4 d, IMM i))
                   4068: {
                   4069:        if (isconst(d) && !needflags) {
                   4070:                live.state[d].val &= i;
                   4071:                return;
                   4072:        }
                   4073: 
                   4074:     CLOBBER_AND;
                   4075:     d=rmw(d,4,4);
                   4076: 
                   4077:     raw_and_l_ri(d,i);
                   4078:     unlock2(d);
                   4079: }
                   4080: MENDFUNC(2,and_l_ri,(RW4 d, IMM i))
                   4081: 
                   4082: MIDFUNC(2,and_l,(RW4 d, R4 s))
                   4083: {
                   4084:     CLOBBER_AND;
                   4085:     s=readreg(s,4);
                   4086:     d=rmw(d,4,4);
                   4087: 
                   4088:     raw_and_l(d,s);
                   4089:     unlock2(d);
                   4090:     unlock2(s);
                   4091: }
                   4092: MENDFUNC(2,and_l,(RW4 d, R4 s))
                   4093: 
                   4094: MIDFUNC(2,and_w,(RW2 d, R2 s))
                   4095: {
                   4096:     CLOBBER_AND;
                   4097:     s=readreg(s,2);
                   4098:     d=rmw(d,2,2);
                   4099: 
                   4100:     raw_and_w(d,s);
                   4101:     unlock2(d);
                   4102:     unlock2(s);
                   4103: }
                   4104: MENDFUNC(2,and_w,(RW2 d, R2 s))
                   4105: 
                   4106: MIDFUNC(2,and_b,(RW1 d, R1 s))
                   4107: {
                   4108:     CLOBBER_AND;
                   4109:     s=readreg(s,1);
                   4110:     d=rmw(d,1,1);
                   4111: 
                   4112:     raw_and_b(d,s);
                   4113:     unlock2(d);
                   4114:     unlock2(s);
                   4115: }
                   4116: MENDFUNC(2,and_b,(RW1 d, R1 s))
                   4117: 
                   4118: // gb-- used for making an fpcr value in compemu_fpp.cpp
                   4119: MIDFUNC(2,or_l_rm,(RW4 d, IMM s))
                   4120: {
                   4121:     CLOBBER_OR;
                   4122:     d=rmw(d,4,4);
                   4123:        
                   4124:     raw_or_l_rm(d,s);
                   4125:     unlock2(d);
                   4126: }
                   4127: MENDFUNC(2,or_l_rm,(RW4 d, IMM s))
                   4128: 
                   4129: MIDFUNC(2,or_l_ri,(RW4 d, IMM i))
                   4130: {
                   4131:     if (isconst(d) && !needflags) {
                   4132:        live.state[d].val|=i;
                   4133:        return;
                   4134:     }
                   4135:     CLOBBER_OR;
                   4136:     d=rmw(d,4,4);
                   4137: 
                   4138:     raw_or_l_ri(d,i);
                   4139:     unlock2(d);
                   4140: }
                   4141: MENDFUNC(2,or_l_ri,(RW4 d, IMM i))
                   4142: 
                   4143: MIDFUNC(2,or_l,(RW4 d, R4 s))
                   4144: {
                   4145:     if (isconst(d) && isconst(s) && !needflags) {
                   4146:        live.state[d].val|=live.state[s].val;
                   4147:        return;
                   4148:     }
                   4149:     CLOBBER_OR;
                   4150:     s=readreg(s,4);
                   4151:     d=rmw(d,4,4);
                   4152: 
                   4153:     raw_or_l(d,s);
                   4154:     unlock2(d);
                   4155:     unlock2(s);
                   4156: }
                   4157: MENDFUNC(2,or_l,(RW4 d, R4 s))
                   4158: 
                   4159: MIDFUNC(2,or_w,(RW2 d, R2 s))
                   4160: {
                   4161:     CLOBBER_OR;
                   4162:     s=readreg(s,2);
                   4163:     d=rmw(d,2,2);
                   4164: 
                   4165:     raw_or_w(d,s);
                   4166:     unlock2(d);
                   4167:     unlock2(s);
                   4168: }
                   4169: MENDFUNC(2,or_w,(RW2 d, R2 s))
                   4170: 
                   4171: MIDFUNC(2,or_b,(RW1 d, R1 s))
                   4172: {
                   4173:     CLOBBER_OR;
                   4174:     s=readreg(s,1);
                   4175:     d=rmw(d,1,1);
                   4176: 
                   4177:     raw_or_b(d,s);
                   4178:     unlock2(d);
                   4179:     unlock2(s);
                   4180: }
                   4181: MENDFUNC(2,or_b,(RW1 d, R1 s))
                   4182: 
                   4183: MIDFUNC(2,adc_l,(RW4 d, R4 s))
                   4184: {
                   4185:     CLOBBER_ADC;
                   4186:     s=readreg(s,4);
                   4187:     d=rmw(d,4,4);
                   4188: 
                   4189:     raw_adc_l(d,s);
                   4190: 
                   4191:     unlock2(d);
                   4192:     unlock2(s);
                   4193: }
                   4194: MENDFUNC(2,adc_l,(RW4 d, R4 s))
                   4195: 
                   4196: MIDFUNC(2,adc_w,(RW2 d, R2 s))
                   4197: {
                   4198:     CLOBBER_ADC;
                   4199:     s=readreg(s,2);
                   4200:     d=rmw(d,2,2);
                   4201: 
                   4202:     raw_adc_w(d,s);
                   4203:     unlock2(d);
                   4204:     unlock2(s);
                   4205: }
                   4206: MENDFUNC(2,adc_w,(RW2 d, R2 s))
                   4207: 
                   4208: MIDFUNC(2,adc_b,(RW1 d, R1 s))
                   4209: {
                   4210:     CLOBBER_ADC;
                   4211:     s=readreg(s,1);
                   4212:     d=rmw(d,1,1);
                   4213: 
                   4214:     raw_adc_b(d,s);
                   4215:     unlock2(d);
                   4216:     unlock2(s);
                   4217: }
                   4218: MENDFUNC(2,adc_b,(RW1 d, R1 s))
                   4219: 
                   4220: MIDFUNC(2,add_l,(RW4 d, R4 s))
                   4221: {
                   4222:     if (isconst(s)) {
                   4223:        COMPCALL(add_l_ri)(d,live.state[s].val);
                   4224:        return;
                   4225:     }
                   4226: 
                   4227:     CLOBBER_ADD;
                   4228:     s=readreg(s,4);
                   4229:     d=rmw(d,4,4);
                   4230: 
                   4231:     raw_add_l(d,s);
                   4232: 
                   4233:     unlock2(d);
                   4234:     unlock2(s);
                   4235: }
                   4236: MENDFUNC(2,add_l,(RW4 d, R4 s))
                   4237: 
                   4238: MIDFUNC(2,add_w,(RW2 d, R2 s))
                   4239: {
                   4240:     if (isconst(s)) {
                   4241:        COMPCALL(add_w_ri)(d,(uae_u16)live.state[s].val);
                   4242:        return;
                   4243:     }
                   4244: 
                   4245:     CLOBBER_ADD;
                   4246:     s=readreg(s,2);
                   4247:     d=rmw(d,2,2);
                   4248: 
                   4249:     raw_add_w(d,s);
                   4250:     unlock2(d);
                   4251:     unlock2(s);
                   4252: }
                   4253: MENDFUNC(2,add_w,(RW2 d, R2 s))
                   4254: 
                   4255: MIDFUNC(2,add_b,(RW1 d, R1 s))
                   4256: {
                   4257:     if (isconst(s)) {
                   4258:        COMPCALL(add_b_ri)(d,(uae_u8)live.state[s].val);
                   4259:        return;
                   4260:     }
                   4261: 
                   4262:     CLOBBER_ADD;
                   4263:     s=readreg(s,1);
                   4264:     d=rmw(d,1,1);
                   4265: 
                   4266:     raw_add_b(d,s);
                   4267:     unlock2(d);
                   4268:     unlock2(s);
                   4269: }
                   4270: MENDFUNC(2,add_b,(RW1 d, R1 s))
                   4271: 
                   4272: MIDFUNC(2,sub_l_ri,(RW4 d, IMM i))
                   4273: {
                   4274:     if (!i && !needflags)
                   4275:        return;
                   4276:     if (isconst(d) && !needflags) {
                   4277:        live.state[d].val-=i;
                   4278:        return;
                   4279:     }
                   4280: #if USE_OFFSET 
                   4281:     if (!needflags) {
                   4282:        add_offset(d,-i);
                   4283:        return;
                   4284:     }
                   4285: #endif
                   4286: 
                   4287:     CLOBBER_SUB;
                   4288:     d=rmw(d,4,4);
                   4289: 
                   4290:     raw_sub_l_ri(d,i);
                   4291:     unlock2(d);
                   4292: }
                   4293: MENDFUNC(2,sub_l_ri,(RW4 d, IMM i))
                   4294: 
                   4295: MIDFUNC(2,sub_w_ri,(RW2 d, IMM i))
                   4296: {
                   4297:     if (!i && !needflags)
                   4298:        return;
                   4299: 
                   4300:     CLOBBER_SUB;
                   4301:     d=rmw(d,2,2);
                   4302: 
                   4303:     raw_sub_w_ri(d,i);
                   4304:     unlock2(d);
                   4305: }
                   4306: MENDFUNC(2,sub_w_ri,(RW2 d, IMM i))
                   4307: 
                   4308: MIDFUNC(2,sub_b_ri,(RW1 d, IMM i))
                   4309: {
                   4310:     if (!i && !needflags)
                   4311:        return;
                   4312: 
                   4313:     CLOBBER_SUB;
                   4314:     d=rmw(d,1,1);
                   4315: 
                   4316:     raw_sub_b_ri(d,i);
                   4317: 
                   4318:     unlock2(d);
                   4319: }
                   4320: MENDFUNC(2,sub_b_ri,(RW1 d, IMM i))
                   4321: 
                   4322: MIDFUNC(2,add_l_ri,(RW4 d, IMM i))
                   4323: {
                   4324:     if (!i && !needflags)
                   4325:        return;
                   4326:     if (isconst(d) && !needflags) {
                   4327:        live.state[d].val+=i;
                   4328:        return;
                   4329:     }
                   4330: #if USE_OFFSET 
                   4331:     if (!needflags) {
                   4332:        add_offset(d,i);
                   4333:        return;
                   4334:     }
                   4335: #endif
                   4336:     CLOBBER_ADD;
                   4337:     d=rmw(d,4,4);
                   4338:     raw_add_l_ri(d,i);
                   4339:     unlock2(d);
                   4340: }
                   4341: MENDFUNC(2,add_l_ri,(RW4 d, IMM i))
                   4342: 
                   4343: MIDFUNC(2,add_w_ri,(RW2 d, IMM i))
                   4344: {
                   4345:     if (!i && !needflags)
                   4346:        return;
                   4347: 
                   4348:     CLOBBER_ADD;
                   4349:     d=rmw(d,2,2);
                   4350: 
                   4351:     raw_add_w_ri(d,i);
                   4352:     unlock2(d);
                   4353: }
                   4354: MENDFUNC(2,add_w_ri,(RW2 d, IMM i))
                   4355: 
                   4356: MIDFUNC(2,add_b_ri,(RW1 d, IMM i))
                   4357: {
                   4358:     if (!i && !needflags)
                   4359:        return;
                   4360: 
                   4361:     CLOBBER_ADD;
                   4362:     d=rmw(d,1,1);
                   4363: 
                   4364:     raw_add_b_ri(d,i);
                   4365: 
                   4366:     unlock2(d);
                   4367: }
                   4368: MENDFUNC(2,add_b_ri,(RW1 d, IMM i))
                   4369: 
                   4370: MIDFUNC(2,sbb_l,(RW4 d, R4 s))
                   4371: {
                   4372:     CLOBBER_SBB;
                   4373:     s=readreg(s,4);
                   4374:     d=rmw(d,4,4);
                   4375: 
                   4376:     raw_sbb_l(d,s);
                   4377:     unlock2(d);
                   4378:     unlock2(s);
                   4379: }
                   4380: MENDFUNC(2,sbb_l,(RW4 d, R4 s))
                   4381: 
                   4382: MIDFUNC(2,sbb_w,(RW2 d, R2 s))
                   4383: {
                   4384:     CLOBBER_SBB;
                   4385:     s=readreg(s,2);
                   4386:     d=rmw(d,2,2);
                   4387: 
                   4388:     raw_sbb_w(d,s);
                   4389:     unlock2(d);
                   4390:     unlock2(s);
                   4391: }
                   4392: MENDFUNC(2,sbb_w,(RW2 d, R2 s))
                   4393: 
                   4394: MIDFUNC(2,sbb_b,(RW1 d, R1 s))
                   4395: {
                   4396:     CLOBBER_SBB;
                   4397:     s=readreg(s,1);
                   4398:     d=rmw(d,1,1);
                   4399: 
                   4400:     raw_sbb_b(d,s);
                   4401:     unlock2(d);
                   4402:     unlock2(s);
                   4403: }
                   4404: MENDFUNC(2,sbb_b,(RW1 d, R1 s))
                   4405: 
                   4406: MIDFUNC(2,sub_l,(RW4 d, R4 s))
                   4407: {
                   4408:     if (isconst(s)) {
                   4409:        COMPCALL(sub_l_ri)(d,live.state[s].val);
                   4410:        return;
                   4411:     }
                   4412: 
                   4413:     CLOBBER_SUB;
                   4414:     s=readreg(s,4);
                   4415:     d=rmw(d,4,4);
                   4416: 
                   4417:     raw_sub_l(d,s);
                   4418:     unlock2(d);
                   4419:     unlock2(s);
                   4420: }
                   4421: MENDFUNC(2,sub_l,(RW4 d, R4 s))
                   4422: 
                   4423: MIDFUNC(2,sub_w,(RW2 d, R2 s))
                   4424: {
                   4425:     if (isconst(s)) {
                   4426:        COMPCALL(sub_w_ri)(d,(uae_u16)live.state[s].val);
                   4427:        return;
                   4428:     }
                   4429: 
                   4430:     CLOBBER_SUB;
                   4431:     s=readreg(s,2);
                   4432:     d=rmw(d,2,2);
                   4433: 
                   4434:     raw_sub_w(d,s);
                   4435:     unlock2(d);
                   4436:     unlock2(s);
                   4437: }
                   4438: MENDFUNC(2,sub_w,(RW2 d, R2 s))
                   4439: 
                   4440: MIDFUNC(2,sub_b,(RW1 d, R1 s))
                   4441: {
                   4442:     if (isconst(s)) {
                   4443:        COMPCALL(sub_b_ri)(d,(uae_u8)live.state[s].val);
                   4444:        return;
                   4445:     }
                   4446: 
                   4447:     CLOBBER_SUB;
                   4448:     s=readreg(s,1);
                   4449:     d=rmw(d,1,1);
                   4450: 
                   4451:     raw_sub_b(d,s);
                   4452:     unlock2(d);
                   4453:     unlock2(s);
                   4454: }
                   4455: MENDFUNC(2,sub_b,(RW1 d, R1 s))
                   4456: 
                   4457: MIDFUNC(2,cmp_l,(R4 d, R4 s))
                   4458: {
                   4459:     CLOBBER_CMP;
                   4460:     s=readreg(s,4);
                   4461:     d=readreg(d,4);
                   4462: 
                   4463:     raw_cmp_l(d,s);
                   4464:     unlock2(d);
                   4465:     unlock2(s);
                   4466: }
                   4467: MENDFUNC(2,cmp_l,(R4 d, R4 s))
                   4468: 
                   4469: MIDFUNC(2,cmp_l_ri,(R4 r, IMM i))
                   4470: {
                   4471:     CLOBBER_CMP;
                   4472:     r=readreg(r,4);
                   4473: 
                   4474:     raw_cmp_l_ri(r,i);
                   4475:     unlock2(r);
                   4476: }
                   4477: MENDFUNC(2,cmp_l_ri,(R4 r, IMM i))
                   4478: 
                   4479: MIDFUNC(2,cmp_w,(R2 d, R2 s))
                   4480: {
                   4481:     CLOBBER_CMP;
                   4482:     s=readreg(s,2);
                   4483:     d=readreg(d,2);
                   4484: 
                   4485:     raw_cmp_w(d,s);
                   4486:     unlock2(d);
                   4487:     unlock2(s);
                   4488: }
                   4489: MENDFUNC(2,cmp_w,(R2 d, R2 s))
                   4490: 
                   4491: MIDFUNC(2,cmp_b,(R1 d, R1 s))
                   4492: {
                   4493:     CLOBBER_CMP;
                   4494:     s=readreg(s,1);
                   4495:     d=readreg(d,1);
                   4496: 
                   4497:     raw_cmp_b(d,s);
                   4498:     unlock2(d);
                   4499:     unlock2(s);
                   4500: }
                   4501: MENDFUNC(2,cmp_b,(R1 d, R1 s))
                   4502: 
                   4503: 
                   4504: MIDFUNC(2,xor_l,(RW4 d, R4 s))
                   4505: {
                   4506:     CLOBBER_XOR;
                   4507:     s=readreg(s,4);
                   4508:     d=rmw(d,4,4);
                   4509: 
                   4510:     raw_xor_l(d,s);
                   4511:     unlock2(d);
                   4512:     unlock2(s);
                   4513: }
                   4514: MENDFUNC(2,xor_l,(RW4 d, R4 s))
                   4515: 
                   4516: MIDFUNC(2,xor_w,(RW2 d, R2 s))
                   4517: {
                   4518:     CLOBBER_XOR;
                   4519:     s=readreg(s,2);
                   4520:     d=rmw(d,2,2);
                   4521: 
                   4522:     raw_xor_w(d,s);
                   4523:     unlock2(d);
                   4524:     unlock2(s);
                   4525: }
                   4526: MENDFUNC(2,xor_w,(RW2 d, R2 s))
                   4527: 
                   4528: MIDFUNC(2,xor_b,(RW1 d, R1 s))
                   4529: {
                   4530:     CLOBBER_XOR;
                   4531:     s=readreg(s,1);
                   4532:     d=rmw(d,1,1);
                   4533: 
                   4534:     raw_xor_b(d,s);
                   4535:     unlock2(d);
                   4536:     unlock2(s);
                   4537: }
                   4538: MENDFUNC(2,xor_b,(RW1 d, R1 s))
                   4539: 
                   4540: MIDFUNC(5,call_r_11,(W4 out1, R4 r, R4 in1, IMM osize, IMM isize))
                   4541: {
                   4542:     clobber_flags();
                   4543:     remove_all_offsets();
                   4544:     if (osize==4) {
                   4545:        if (out1!=in1 && out1!=r) {
                   4546:            COMPCALL(forget_about)(out1);
                   4547:        }
                   4548:     }
                   4549:     else {
                   4550:        tomem_c(out1);
                   4551:     }
                   4552: 
                   4553:     in1=readreg_specific(in1,isize,REG_PAR1);
                   4554:     r=readreg(r,4);
                   4555:     prepare_for_call_1();  /* This should ensure that there won't be
                   4556:                              any need for swapping nregs in prepare_for_call_2
                   4557:                           */
                   4558: #if USE_NORMAL_CALLING_CONVENTION
                   4559:     raw_push_l_r(in1);
                   4560: #endif
                   4561:     unlock2(in1);
                   4562:     unlock2(r);
                   4563: 
                   4564:     prepare_for_call_2();
                   4565:     raw_call_r(r);
                   4566: 
                   4567: #if USE_NORMAL_CALLING_CONVENTION
                   4568:     raw_inc_sp(4);
                   4569: #endif
                   4570: 
                   4571: 
                   4572:     live.nat[REG_RESULT].holds[0]=out1;
                   4573:     live.nat[REG_RESULT].nholds=1;
                   4574:     live.nat[REG_RESULT].touched=touchcnt++;
                   4575: 
                   4576:     live.state[out1].realreg=REG_RESULT;
                   4577:     live.state[out1].realind=0;
                   4578:     live.state[out1].val=0;
                   4579:     live.state[out1].validsize=osize;
                   4580:     live.state[out1].dirtysize=osize;
                   4581:     set_status(out1,DIRTY);
                   4582: }
                   4583: MENDFUNC(5,call_r_11,(W4 out1, R4 r, R4 in1, IMM osize, IMM isize))
                   4584: 
                   4585: MIDFUNC(5,call_r_02,(R4 r, R4 in1, R4 in2, IMM isize1, IMM isize2))
                   4586: {
                   4587:     clobber_flags();
                   4588:     remove_all_offsets();
                   4589:     in1=readreg_specific(in1,isize1,REG_PAR1);
                   4590:     in2=readreg_specific(in2,isize2,REG_PAR2);
                   4591:     r=readreg(r,4);
                   4592:     prepare_for_call_1();  /* This should ensure that there won't be
                   4593:                              any need for swapping nregs in prepare_for_call_2
                   4594:                           */
                   4595: #if USE_NORMAL_CALLING_CONVENTION
                   4596:     raw_push_l_r(in2);
                   4597:     raw_push_l_r(in1);
                   4598: #endif
                   4599:     unlock2(r);
                   4600:     unlock2(in1);
                   4601:     unlock2(in2);
                   4602:     prepare_for_call_2();
                   4603:     raw_call_r(r);
                   4604: #if USE_NORMAL_CALLING_CONVENTION
                   4605:     raw_inc_sp(8);
                   4606: #endif
                   4607: }
                   4608: MENDFUNC(5,call_r_02,(R4 r, R4 in1, R4 in2, IMM isize1, IMM isize2))
                   4609: 
                   4610: /* forget_about() takes a mid-layer register */
                   4611: MIDFUNC(1,forget_about,(W4 r))
                   4612: {
                   4613:     if (isinreg(r))
                   4614:        disassociate(r);
                   4615:     live.state[r].val=0;
                   4616:     set_status(r,UNDEF);
                   4617: }
                   4618: MENDFUNC(1,forget_about,(W4 r))
                   4619: 
                   4620: MIDFUNC(0,nop,(void))
                   4621: {
                   4622:     raw_nop();
                   4623: }
                   4624: MENDFUNC(0,nop,(void))
                   4625: 
                   4626: 
                   4627: MIDFUNC(1,f_forget_about,(FW r))
                   4628: {
                   4629:     if (f_isinreg(r))
                   4630:        f_disassociate(r);
                   4631:     live.fate[r].status=UNDEF;
                   4632: }
                   4633: MENDFUNC(1,f_forget_about,(FW r))
                   4634: 
                   4635: MIDFUNC(1,fmov_pi,(FW r))
                   4636: {
                   4637:     r=f_writereg(r);
                   4638:     raw_fmov_pi(r);
                   4639:     f_unlock(r);
                   4640: }
                   4641: MENDFUNC(1,fmov_pi,(FW r))
                   4642: 
                   4643: MIDFUNC(1,fmov_log10_2,(FW r))
                   4644: {
                   4645:     r=f_writereg(r);
                   4646:     raw_fmov_log10_2(r);
                   4647:     f_unlock(r);
                   4648: }
                   4649: MENDFUNC(1,fmov_log10_2,(FW r))
                   4650: 
                   4651: MIDFUNC(1,fmov_log2_e,(FW r))
                   4652: {
                   4653:     r=f_writereg(r);
                   4654:     raw_fmov_log2_e(r);
                   4655:     f_unlock(r);
                   4656: }
                   4657: MENDFUNC(1,fmov_log2_e,(FW r))
                   4658: 
                   4659: MIDFUNC(1,fmov_loge_2,(FW r))
                   4660: {
                   4661:     r=f_writereg(r);
                   4662:     raw_fmov_loge_2(r);
                   4663:     f_unlock(r);
                   4664: }
                   4665: MENDFUNC(1,fmov_loge_2,(FW r))
                   4666: 
                   4667: MIDFUNC(1,fmov_1,(FW r))
                   4668: {
                   4669:     r=f_writereg(r);
                   4670:     raw_fmov_1(r);
                   4671:     f_unlock(r);
                   4672: }
                   4673: MENDFUNC(1,fmov_1,(FW r))
                   4674: 
                   4675: MIDFUNC(1,fmov_0,(FW r))
                   4676: {
                   4677:     r=f_writereg(r);
                   4678:     raw_fmov_0(r);
                   4679:     f_unlock(r);
                   4680: }
                   4681: MENDFUNC(1,fmov_0,(FW r))
                   4682: 
                   4683: MIDFUNC(2,fmov_rm,(FW r, MEMR m))
                   4684: {
                   4685:     r=f_writereg(r);
                   4686:     raw_fmov_rm(r,m);
                   4687:     f_unlock(r);
                   4688: }
                   4689: MENDFUNC(2,fmov_rm,(FW r, MEMR m))
                   4690: 
                   4691: MIDFUNC(2,fmovi_rm,(FW r, MEMR m))
                   4692: {
                   4693:     r=f_writereg(r);
                   4694:     raw_fmovi_rm(r,m);
                   4695:     f_unlock(r);
                   4696: }
                   4697: MENDFUNC(2,fmovi_rm,(FW r, MEMR m))
                   4698: 
                   4699: MIDFUNC(2,fmovi_mr,(MEMW m, FR r))
                   4700: {
                   4701:     r=f_readreg(r);
                   4702:     raw_fmovi_mr(m,r);
                   4703:     f_unlock(r);
                   4704: }
                   4705: MENDFUNC(2,fmovi_mr,(MEMW m, FR r))
                   4706: 
                   4707: MIDFUNC(2,fmovs_rm,(FW r, MEMR m))
                   4708: {
                   4709:     r=f_writereg(r);
                   4710:     raw_fmovs_rm(r,m);
                   4711:     f_unlock(r);
                   4712: }
                   4713: MENDFUNC(2,fmovs_rm,(FW r, MEMR m))
                   4714: 
                   4715: MIDFUNC(2,fmovs_mr,(MEMW m, FR r))
                   4716: {
                   4717:     r=f_readreg(r);
                   4718:     raw_fmovs_mr(m,r);
                   4719:     f_unlock(r);
                   4720: }
                   4721: MENDFUNC(2,fmovs_mr,(MEMW m, FR r))
                   4722: 
                   4723: MIDFUNC(2,fmov_ext_mr,(MEMW m, FR r))
                   4724: {
                   4725:     r=f_readreg(r);
                   4726:     raw_fmov_ext_mr(m,r);
                   4727:     f_unlock(r);
                   4728: }
                   4729: MENDFUNC(2,fmov_ext_mr,(MEMW m, FR r))
                   4730: 
                   4731: MIDFUNC(2,fmov_mr,(MEMW m, FR r))
                   4732: {
                   4733:     r=f_readreg(r);
                   4734:     raw_fmov_mr(m,r);
                   4735:     f_unlock(r);
                   4736: }
                   4737: MENDFUNC(2,fmov_mr,(MEMW m, FR r))
                   4738: 
                   4739: MIDFUNC(2,fmov_ext_rm,(FW r, MEMR m))
                   4740: {
                   4741:     r=f_writereg(r);
                   4742:     raw_fmov_ext_rm(r,m);
                   4743:     f_unlock(r);
                   4744: }
                   4745: MENDFUNC(2,fmov_ext_rm,(FW r, MEMR m))
                   4746: 
                   4747: MIDFUNC(2,fmov_rr,(FW d, FR s))
                   4748: {
                   4749:     if (d==s) { /* How pointless! */
                   4750:        return;
                   4751:     }
                   4752: #if USE_F_ALIAS
                   4753:     f_disassociate(d);
                   4754:     s=f_readreg(s);
                   4755:     live.fate[d].realreg=s;
                   4756:     live.fate[d].realind=live.fat[s].nholds;
                   4757:     live.fate[d].status=DIRTY;
                   4758:     live.fat[s].holds[live.fat[s].nholds]=d;
                   4759:     live.fat[s].nholds++;
                   4760:     f_unlock(s);
                   4761: #else
                   4762:     s=f_readreg(s);
                   4763:     d=f_writereg(d);
                   4764:     raw_fmov_rr(d,s);
                   4765:     f_unlock(s);
                   4766:     f_unlock(d);
                   4767: #endif
                   4768: }
                   4769: MENDFUNC(2,fmov_rr,(FW d, FR s))
                   4770: 
                   4771: MIDFUNC(2,fldcw_m_indexed,(R4 index, IMM base))
                   4772: {
                   4773:     index=readreg(index,4);
                   4774: 
                   4775:     raw_fldcw_m_indexed(index,base);
                   4776:     unlock2(index);
                   4777: }
                   4778: MENDFUNC(2,fldcw_m_indexed,(R4 index, IMM base))
                   4779: 
                   4780: MIDFUNC(1,ftst_r,(FR r))
                   4781: {
                   4782:     r=f_readreg(r);
                   4783:     raw_ftst_r(r);
                   4784:     f_unlock(r);
                   4785: }
                   4786: MENDFUNC(1,ftst_r,(FR r))
                   4787: 
                   4788: MIDFUNC(0,dont_care_fflags,(void))
                   4789: {
                   4790:     f_disassociate(FP_RESULT);
                   4791: }
                   4792: MENDFUNC(0,dont_care_fflags,(void))
                   4793: 
                   4794: MIDFUNC(2,fsqrt_rr,(FW d, FR s))
                   4795: {
                   4796:     s=f_readreg(s);
                   4797:     d=f_writereg(d);
                   4798:     raw_fsqrt_rr(d,s);
                   4799:     f_unlock(s);
                   4800:     f_unlock(d);
                   4801: }
                   4802: MENDFUNC(2,fsqrt_rr,(FW d, FR s))
                   4803: 
                   4804: MIDFUNC(2,fabs_rr,(FW d, FR s))
                   4805: {
                   4806:     s=f_readreg(s);
                   4807:     d=f_writereg(d);
                   4808:     raw_fabs_rr(d,s);
                   4809:     f_unlock(s);
                   4810:     f_unlock(d);
                   4811: }
                   4812: MENDFUNC(2,fabs_rr,(FW d, FR s))
                   4813: 
                   4814: MIDFUNC(2,fsin_rr,(FW d, FR s))
                   4815: {
                   4816:     s=f_readreg(s);
                   4817:     d=f_writereg(d);
                   4818:     raw_fsin_rr(d,s);
                   4819:     f_unlock(s);
                   4820:     f_unlock(d);
                   4821: }
                   4822: MENDFUNC(2,fsin_rr,(FW d, FR s))
                   4823: 
                   4824: MIDFUNC(2,fcos_rr,(FW d, FR s))
                   4825: {
                   4826:     s=f_readreg(s);
                   4827:     d=f_writereg(d);
                   4828:     raw_fcos_rr(d,s);
                   4829:     f_unlock(s);
                   4830:     f_unlock(d);
                   4831: }
                   4832: MENDFUNC(2,fcos_rr,(FW d, FR s))
                   4833: 
                   4834: MIDFUNC(2,ftwotox_rr,(FW d, FR s))
                   4835: {
                   4836:     s=f_readreg(s);
                   4837:     d=f_writereg(d);
                   4838:     raw_ftwotox_rr(d,s);
                   4839:     f_unlock(s);
                   4840:     f_unlock(d);
                   4841: }
                   4842: MENDFUNC(2,ftwotox_rr,(FW d, FR s))
                   4843: 
                   4844: MIDFUNC(2,fetox_rr,(FW d, FR s))
                   4845: {
                   4846:     s=f_readreg(s);
                   4847:     d=f_writereg(d);
                   4848:     raw_fetox_rr(d,s);
                   4849:     f_unlock(s);
                   4850:     f_unlock(d);
                   4851: }
                   4852: MENDFUNC(2,fetox_rr,(FW d, FR s))
                   4853: 
                   4854: MIDFUNC(2,frndint_rr,(FW d, FR s))
                   4855: {
                   4856:     s=f_readreg(s);
                   4857:     d=f_writereg(d);
                   4858:     raw_frndint_rr(d,s);
                   4859:     f_unlock(s);
                   4860:     f_unlock(d);
                   4861: }
                   4862: MENDFUNC(2,frndint_rr,(FW d, FR s))
                   4863: 
                   4864: MIDFUNC(2,flog2_rr,(FW d, FR s))
                   4865: {
                   4866:     s=f_readreg(s);
                   4867:     d=f_writereg(d);
                   4868:     raw_flog2_rr(d,s);
                   4869:     f_unlock(s);
                   4870:     f_unlock(d);
                   4871: }
                   4872: MENDFUNC(2,flog2_rr,(FW d, FR s))
                   4873: 
                   4874: MIDFUNC(2,fneg_rr,(FW d, FR s))
                   4875: {
                   4876:     s=f_readreg(s);
                   4877:     d=f_writereg(d);
                   4878:     raw_fneg_rr(d,s);
                   4879:     f_unlock(s);
                   4880:     f_unlock(d);
                   4881: }
                   4882: MENDFUNC(2,fneg_rr,(FW d, FR s))
                   4883: 
                   4884: MIDFUNC(2,fadd_rr,(FRW d, FR s))
                   4885: {
                   4886:     s=f_readreg(s);
                   4887:     d=f_rmw(d);
                   4888:     raw_fadd_rr(d,s);
                   4889:     f_unlock(s);
                   4890:     f_unlock(d);
                   4891: }
                   4892: MENDFUNC(2,fadd_rr,(FRW d, FR s))
                   4893: 
                   4894: MIDFUNC(2,fsub_rr,(FRW d, FR s))
                   4895: {
                   4896:     s=f_readreg(s);
                   4897:     d=f_rmw(d);
                   4898:     raw_fsub_rr(d,s);
                   4899:     f_unlock(s);
                   4900:     f_unlock(d);
                   4901: }
                   4902: MENDFUNC(2,fsub_rr,(FRW d, FR s))
                   4903: 
                   4904: MIDFUNC(2,fcmp_rr,(FR d, FR s))
                   4905: {
                   4906:     d=f_readreg(d);
                   4907:     s=f_readreg(s);
                   4908:     raw_fcmp_rr(d,s);
                   4909:     f_unlock(s);
                   4910:     f_unlock(d);
                   4911: }
                   4912: MENDFUNC(2,fcmp_rr,(FR d, FR s))
                   4913: 
                   4914: MIDFUNC(2,fdiv_rr,(FRW d, FR s))
                   4915: {
                   4916:     s=f_readreg(s);
                   4917:     d=f_rmw(d);
                   4918:     raw_fdiv_rr(d,s);
                   4919:     f_unlock(s);
                   4920:     f_unlock(d);
                   4921: }
                   4922: MENDFUNC(2,fdiv_rr,(FRW d, FR s))
                   4923: 
                   4924: MIDFUNC(2,frem_rr,(FRW d, FR s))
                   4925: {
                   4926:     s=f_readreg(s);
                   4927:     d=f_rmw(d);
                   4928:     raw_frem_rr(d,s);
                   4929:     f_unlock(s);
                   4930:     f_unlock(d);
                   4931: }
                   4932: MENDFUNC(2,frem_rr,(FRW d, FR s))
                   4933: 
                   4934: MIDFUNC(2,frem1_rr,(FRW d, FR s))
                   4935: {
                   4936:     s=f_readreg(s);
                   4937:     d=f_rmw(d);
                   4938:     raw_frem1_rr(d,s);
                   4939:     f_unlock(s);
                   4940:     f_unlock(d);
                   4941: }
                   4942: MENDFUNC(2,frem1_rr,(FRW d, FR s))
                   4943: 
                   4944: MIDFUNC(2,fmul_rr,(FRW d, FR s))
                   4945: {
                   4946:     s=f_readreg(s);
                   4947:     d=f_rmw(d);
                   4948:     raw_fmul_rr(d,s);
                   4949:     f_unlock(s);
                   4950:     f_unlock(d);
                   4951: }
                   4952: MENDFUNC(2,fmul_rr,(FRW d, FR s))
                   4953: 
                   4954: /********************************************************************
                   4955:  * Support functions exposed to gencomp. CREATE time                *
                   4956:  ********************************************************************/
                   4957: 
                   4958: void set_zero(int r, int tmp)
                   4959: {
                   4960:     if (setzflg_uses_bsf)
                   4961:        bsf_l_rr(r,r);
                   4962:     else
                   4963:        simulate_bsf(tmp,r);
                   4964: }
                   4965: 
                   4966: int kill_rodent(int r)
                   4967: {
                   4968:     return KILLTHERAT && 
                   4969:                have_rat_stall &&
                   4970:        (live.state[r].status==INMEM || 
                   4971:         live.state[r].status==CLEAN || 
                   4972:         live.state[r].status==ISCONST || 
                   4973:         live.state[r].dirtysize==4);
                   4974: }
                   4975: 
                   4976: uae_u32 get_const(int r)
                   4977: {
                   4978:        Dif (!isconst(r)) {
                   4979:            write_log("Register %d should be constant, but isn't\n",r);
                   4980:            abort();
                   4981:        }
                   4982:     return live.state[r].val;
                   4983: }
                   4984: 
                   4985: void sync_m68k_pc(void)
                   4986: {
                   4987:     if (m68k_pc_offset) {
                   4988:        add_l_ri(PC_P,m68k_pc_offset);
                   4989:        comp_pc_p+=m68k_pc_offset;
                   4990:        m68k_pc_offset=0;
                   4991:     }
                   4992: }
                   4993:     
                   4994: /********************************************************************
                   4995:  * Scratch registers management                                     *
                   4996:  ********************************************************************/
                   4997: 
                   4998: struct scratch_t {
                   4999:        uae_u32         regs[VREGS];
                   5000:        fpu_register    fregs[VFREGS];
                   5001: };
                   5002: 
                   5003: static scratch_t scratch;
                   5004: 
                   5005: /********************************************************************
                   5006:  * Support functions exposed to newcpu                              *
                   5007:  ********************************************************************/
                   5008: 
                   5009: static inline const char *str_on_off(bool b)
                   5010: {
                   5011:        return b ? "on" : "off";
                   5012: }
                   5013: 
                   5014: void compiler_init(void)
                   5015: {
                   5016:        static bool initialized = false;
                   5017:        if (initialized)
                   5018:                return;
                   5019: 
                   5020: #if JIT_DEBUG
                   5021:        // JIT debug mode ?
                   5022:        JITDebug = PrefsFindBool("jitdebug");
                   5023: #endif
                   5024:        write_log("<JIT compiler> : enable runtime disassemblers : %s\n", JITDebug ? "yes" : "no");
                   5025:        
                   5026: #ifdef USE_JIT_FPU
                   5027:        // Use JIT compiler for FPU instructions ?
                   5028:        avoid_fpu = !PrefsFindBool("jitfpu");
                   5029: #else
                   5030:        // JIT FPU is always disabled
                   5031:        avoid_fpu = true;
                   5032: #endif
                   5033:        write_log("<JIT compiler> : compile FPU instructions : %s\n", !avoid_fpu ? "yes" : "no");
                   5034:        
                   5035:        // Get size of the translation cache (in KB)
                   5036:        cache_size = PrefsFindInt32("jitcachesize");
                   5037:        write_log("<JIT compiler> : requested translation cache size : %d KB\n", cache_size);
                   5038:        
                   5039:        // Initialize target CPU (check for features, e.g. CMOV, rat stalls)
                   5040:        raw_init_cpu();
                   5041:        setzflg_uses_bsf = target_check_bsf();
                   5042:        write_log("<JIT compiler> : target processor has CMOV instructions : %s\n", have_cmov ? "yes" : "no");
                   5043:        write_log("<JIT compiler> : target processor can suffer from partial register stalls : %s\n", have_rat_stall ? "yes" : "no");
                   5044:        write_log("<JIT compiler> : alignment for loops, jumps are %d, %d\n", align_loops, align_jumps);
                   5045:        
                   5046:        // Translation cache flush mechanism
                   5047:        lazy_flush = PrefsFindBool("jitlazyflush");
                   5048:        write_log("<JIT compiler> : lazy translation cache invalidation : %s\n", str_on_off(lazy_flush));
                   5049:        flush_icache = lazy_flush ? flush_icache_lazy : flush_icache_hard;
                   5050:        
                   5051:        // Compiler features
                   5052:        write_log("<JIT compiler> : register aliasing : %s\n", str_on_off(1));
                   5053:        write_log("<JIT compiler> : FP register aliasing : %s\n", str_on_off(USE_F_ALIAS));
                   5054:        write_log("<JIT compiler> : lazy constant offsetting : %s\n", str_on_off(USE_OFFSET));
                   5055: #if USE_INLINING
                   5056:        follow_const_jumps = PrefsFindBool("jitinline");
                   5057: #endif
                   5058:        write_log("<JIT compiler> : translate through constant jumps : %s\n", str_on_off(follow_const_jumps));
                   5059:        write_log("<JIT compiler> : separate blockinfo allocation : %s\n", str_on_off(USE_SEPARATE_BIA));
                   5060:        
                   5061:        // Build compiler tables
                   5062:        build_comp();
                   5063:        
                   5064:        initialized = true;
                   5065:        
                   5066: #if PROFILE_UNTRANSLATED_INSNS
                   5067:        write_log("<JIT compiler> : gather statistics on untranslated insns count\n");
                   5068: #endif
                   5069: 
                   5070: #if PROFILE_COMPILE_TIME
                   5071:        write_log("<JIT compiler> : gather statistics on translation time\n");
                   5072:        emul_start_time = clock();
                   5073: #endif
                   5074: }
                   5075: 
                   5076: void compiler_exit(void)
                   5077: {
                   5078: #if PROFILE_COMPILE_TIME
                   5079:        emul_end_time = clock();
                   5080: #endif
                   5081:        
                   5082:        // Deallocate translation cache
                   5083:        if (compiled_code) {
                   5084:                vm_release(compiled_code, cache_size * 1024);
                   5085:                compiled_code = 0;
                   5086:        }
                   5087: 
                   5088:        // Deallocate popallspace
                   5089:        if (popallspace) {
                   5090:                vm_release(popallspace, POPALLSPACE_SIZE);
                   5091:                popallspace = 0;
                   5092:        }
                   5093:        
                   5094: #if PROFILE_COMPILE_TIME
                   5095:        write_log("### Compile Block statistics\n");
                   5096:        write_log("Number of calls to compile_block : %d\n", compile_count);
                   5097:        uae_u32 emul_time = emul_end_time - emul_start_time;
                   5098:        write_log("Total emulation time   : %.1f sec\n", double(emul_time)/double(CLOCKS_PER_SEC));
                   5099:        write_log("Total compilation time : %.1f sec (%.1f%%)\n", double(compile_time)/double(CLOCKS_PER_SEC),
                   5100:                100.0*double(compile_time)/double(emul_time));
                   5101:        write_log("\n");
                   5102: #endif
                   5103: 
                   5104: #if PROFILE_UNTRANSLATED_INSNS
                   5105:        uae_u64 untranslated_count = 0;
                   5106:        for (int i = 0; i < 65536; i++) {
                   5107:                opcode_nums[i] = i;
                   5108:                untranslated_count += raw_cputbl_count[i];
                   5109:        }
                   5110:        write_log("Sorting out untranslated instructions count...\n");
                   5111:        qsort(opcode_nums, 65536, sizeof(uae_u16), untranslated_compfn);
                   5112:        write_log("\nRank  Opc      Count Name\n");
                   5113:        for (int i = 0; i < untranslated_top_ten; i++) {
                   5114:                uae_u32 count = raw_cputbl_count[opcode_nums[i]];
                   5115:                struct instr *dp;
                   5116:                struct mnemolookup *lookup;
                   5117:                if (!count)
                   5118:                        break;
                   5119:                dp = table68k + opcode_nums[i];
                   5120:                for (lookup = lookuptab; lookup->mnemo != dp->mnemo; lookup++)
                   5121:                        ;
                   5122:                write_log("%03d: %04x %10lu %s\n", i, opcode_nums[i], count, lookup->name);
                   5123:        }
                   5124: #endif
                   5125: 
                   5126: #if RECORD_REGISTER_USAGE
                   5127:        int reg_count_ids[16];
                   5128:        uint64 tot_reg_count = 0;
                   5129:        for (int i = 0; i < 16; i++) {
                   5130:            reg_count_ids[i] = i;
                   5131:            tot_reg_count += reg_count[i];
                   5132:        }
                   5133:        qsort(reg_count_ids, 16, sizeof(int), reg_count_compare);
                   5134:        uint64 cum_reg_count = 0;
                   5135:        for (int i = 0; i < 16; i++) {
                   5136:            int r = reg_count_ids[i];
                   5137:            cum_reg_count += reg_count[r];
                   5138:            printf("%c%d : %16ld %2.1f%% [%2.1f]\n", r < 8 ? 'D' : 'A', r % 8,
                   5139:                   reg_count[r],
                   5140:                   100.0*double(reg_count[r])/double(tot_reg_count),
                   5141:                   100.0*double(cum_reg_count)/double(tot_reg_count));
                   5142:        }
                   5143: #endif
                   5144: }
                   5145: 
                   5146: bool compiler_use_jit(void)
                   5147: {
                   5148:        // Check for the "jit" prefs item
                   5149:        if (!PrefsFindBool("jit"))
                   5150:                return false;
                   5151:        
                   5152:        // Don't use JIT if translation cache size is less then MIN_CACHE_SIZE KB
                   5153:        if (PrefsFindInt32("jitcachesize") < MIN_CACHE_SIZE) {
                   5154:                write_log("<JIT compiler> : translation cache size is less than %d KB. Disabling JIT.\n", MIN_CACHE_SIZE);
                   5155:                return false;
                   5156:        }
                   5157:        
                   5158:        // Enable JIT for 68020+ emulation only
                   5159:        if (CPUType < 2) {
                   5160:                write_log("<JIT compiler> : JIT is not supported in 680%d0 emulation mode, disabling.\n", CPUType);
                   5161:                return false;
                   5162:        }
                   5163: 
                   5164:        return true;
                   5165: }
                   5166: 
                   5167: void init_comp(void)
                   5168: {
                   5169:     int i;
                   5170:     uae_s8* cb=can_byte;
                   5171:     uae_s8* cw=can_word;
                   5172:     uae_s8* au=always_used;
                   5173: 
                   5174: #if RECORD_REGISTER_USAGE
                   5175:     for (i=0;i<16;i++)
                   5176:        reg_count_local[i] = 0;
                   5177: #endif
                   5178: 
                   5179:     for (i=0;i<VREGS;i++) {
                   5180:        live.state[i].realreg=-1;
                   5181:        live.state[i].needflush=NF_SCRATCH;
                   5182:        live.state[i].val=0;
                   5183:        set_status(i,UNDEF);
                   5184:     }
                   5185: 
                   5186:     for (i=0;i<VFREGS;i++) {
                   5187:        live.fate[i].status=UNDEF;
                   5188:        live.fate[i].realreg=-1;
                   5189:        live.fate[i].needflush=NF_SCRATCH;
                   5190:     }
                   5191: 
                   5192:     for (i=0;i<VREGS;i++) {
                   5193:        if (i<16) { /* First 16 registers map to 68k registers */
                   5194:            live.state[i].mem=((uae_u32*)&regs)+i;
                   5195:            live.state[i].needflush=NF_TOMEM;
                   5196:            set_status(i,INMEM);
                   5197:        }
                   5198:        else
                   5199:            live.state[i].mem=scratch.regs+i;
                   5200:     }
                   5201:     live.state[PC_P].mem=(uae_u32*)&(regs.pc_p);
                   5202:     live.state[PC_P].needflush=NF_TOMEM;
                   5203:     set_const(PC_P,(uintptr)comp_pc_p);
                   5204: 
                   5205:     live.state[FLAGX].mem=(uae_u32*)&(regflags.x);
                   5206:     live.state[FLAGX].needflush=NF_TOMEM;
                   5207:     set_status(FLAGX,INMEM);
                   5208:        
                   5209:     live.state[FLAGTMP].mem=(uae_u32*)&(regflags.cznv);
                   5210:     live.state[FLAGTMP].needflush=NF_TOMEM;
                   5211:     set_status(FLAGTMP,INMEM);
                   5212: 
                   5213:     live.state[NEXT_HANDLER].needflush=NF_HANDLER;
                   5214:     set_status(NEXT_HANDLER,UNDEF);
                   5215: 
                   5216:     for (i=0;i<VFREGS;i++) {
                   5217:        if (i<8) { /* First 8 registers map to 68k FPU registers */
                   5218:            live.fate[i].mem=(uae_u32*)fpu_register_address(i);
                   5219:            live.fate[i].needflush=NF_TOMEM;
                   5220:            live.fate[i].status=INMEM;
                   5221:        }
                   5222:        else if (i==FP_RESULT) {
                   5223:            live.fate[i].mem=(uae_u32*)(&fpu.result);
                   5224:            live.fate[i].needflush=NF_TOMEM;
                   5225:            live.fate[i].status=INMEM;
                   5226:        }
                   5227:        else
                   5228:            live.fate[i].mem=(uae_u32*)(&scratch.fregs[i]);
                   5229:     }
                   5230: 
                   5231: 
                   5232:     for (i=0;i<N_REGS;i++) {
                   5233:        live.nat[i].touched=0;
                   5234:        live.nat[i].nholds=0;
                   5235:        live.nat[i].locked=0;
                   5236:        if (*cb==i) {
                   5237:            live.nat[i].canbyte=1; cb++;
                   5238:        } else live.nat[i].canbyte=0;
                   5239:        if (*cw==i) {
                   5240:            live.nat[i].canword=1; cw++;
                   5241:        } else live.nat[i].canword=0;
                   5242:        if (*au==i) {
                   5243:            live.nat[i].locked=1; au++;
                   5244:        }
                   5245:     }
                   5246: 
                   5247:     for (i=0;i<N_FREGS;i++) {
                   5248:        live.fat[i].touched=0;
                   5249:        live.fat[i].nholds=0;
                   5250:        live.fat[i].locked=0;
                   5251:     }
                   5252:     
                   5253:     touchcnt=1;
                   5254:     m68k_pc_offset=0;
                   5255:     live.flags_in_flags=TRASH;
                   5256:     live.flags_on_stack=VALID;
                   5257:     live.flags_are_important=1;
                   5258: 
                   5259:     raw_fp_init();
                   5260: }
                   5261: 
                   5262: /* Only do this if you really mean it! The next call should be to init!*/
                   5263: void flush(int save_regs)
                   5264: {
                   5265:     int fi,i;
                   5266:     
                   5267:        log_flush();
                   5268:     flush_flags(); /* low level */
                   5269:     sync_m68k_pc(); /* mid level */
                   5270: 
                   5271:     if (save_regs) {
                   5272:        for (i=0;i<VFREGS;i++) {
                   5273:            if (live.fate[i].needflush==NF_SCRATCH || 
                   5274:                live.fate[i].status==CLEAN) {
                   5275:                f_disassociate(i);
                   5276:            }
                   5277:        }
                   5278:        for (i=0;i<VREGS;i++) {
                   5279:            if (live.state[i].needflush==NF_TOMEM) {
                   5280:                switch(live.state[i].status) {
                   5281:                 case INMEM:   
                   5282:                    if (live.state[i].val) {
                   5283:                        raw_add_l_mi((uintptr)live.state[i].mem,live.state[i].val);
                   5284:                        log_vwrite(i);
                   5285:                        live.state[i].val=0;
                   5286:                    }
                   5287:                    break;
                   5288:                 case CLEAN:   
                   5289:                 case DIRTY:   
                   5290:                    remove_offset(i,-1); tomem(i); break;
                   5291:                 case ISCONST: 
                   5292:                    if (i!=PC_P) 
                   5293:                        writeback_const(i); 
                   5294:                    break;
                   5295:                 default: break;
                   5296:                }
                   5297:                Dif (live.state[i].val && i!=PC_P) {
                   5298:                    write_log("Register %d still has val %x\n",
                   5299:                           i,live.state[i].val);
                   5300:                }
                   5301:            }
                   5302:        }
                   5303:        for (i=0;i<VFREGS;i++) {
                   5304:            if (live.fate[i].needflush==NF_TOMEM && 
                   5305:                live.fate[i].status==DIRTY) {
                   5306:                f_evict(i);
                   5307:            }
                   5308:        }
                   5309:        raw_fp_cleanup_drop();
                   5310:     }
                   5311:     if (needflags) {
                   5312:        write_log("Warning! flush with needflags=1!\n");
                   5313:     }
                   5314: }
                   5315: 
                   5316: static void flush_keepflags(void)
                   5317: {
                   5318:     int fi,i;
                   5319:     
                   5320:     for (i=0;i<VFREGS;i++) {
                   5321:        if (live.fate[i].needflush==NF_SCRATCH || 
                   5322:            live.fate[i].status==CLEAN) {
                   5323:            f_disassociate(i);
                   5324:        }
                   5325:     }
                   5326:     for (i=0;i<VREGS;i++) {
                   5327:        if (live.state[i].needflush==NF_TOMEM) {
                   5328:            switch(live.state[i].status) {
                   5329:             case INMEM:   
                   5330:                /* Can't adjust the offset here --- that needs "add" */
                   5331:                break;
                   5332:             case CLEAN:   
                   5333:             case DIRTY:   
                   5334:                remove_offset(i,-1); tomem(i); break;
                   5335:             case ISCONST: 
                   5336:                if (i!=PC_P) 
                   5337:                    writeback_const(i); 
                   5338:                break;
                   5339:             default: break;
                   5340:            }
                   5341:        }
                   5342:     }
                   5343:     for (i=0;i<VFREGS;i++) {
                   5344:        if (live.fate[i].needflush==NF_TOMEM && 
                   5345:            live.fate[i].status==DIRTY) {
                   5346:            f_evict(i);
                   5347:        }
                   5348:     }
                   5349:     raw_fp_cleanup_drop();
                   5350: }
                   5351: 
                   5352: void freescratch(void)
                   5353: {
                   5354:     int i;
                   5355:     for (i=0;i<N_REGS;i++)
                   5356:        if (live.nat[i].locked && i!=4)
                   5357:            write_log("Warning! %d is locked\n",i);
                   5358: 
                   5359:     for (i=0;i<VREGS;i++)
                   5360:        if (live.state[i].needflush==NF_SCRATCH) {
                   5361:            forget_about(i);
                   5362:        }
                   5363: 
                   5364:     for (i=0;i<VFREGS;i++)
                   5365:        if (live.fate[i].needflush==NF_SCRATCH) {
                   5366:            f_forget_about(i);
                   5367:        }
                   5368: }
                   5369: 
                   5370: /********************************************************************
                   5371:  * Support functions, internal                                      *
                   5372:  ********************************************************************/
                   5373: 
                   5374: 
                   5375: static void align_target(uae_u32 a)
                   5376: {
                   5377:        if (!a)
                   5378:                return;
                   5379: 
                   5380:        if (tune_nop_fillers)
                   5381:                raw_emit_nop_filler(a - (((uintptr)target) & (a - 1)));
                   5382:        else {
                   5383:                /* Fill with NOPs --- makes debugging with gdb easier */
                   5384:                while ((uintptr)target&(a-1)) 
                   5385:                        *target++=0x90;
                   5386:        }
                   5387: }
                   5388: 
                   5389: static __inline__ int isinrom(uintptr addr)
                   5390: {
                   5391:        return ((addr >= (uintptr)ROMBaseHost) && (addr < (uintptr)ROMBaseHost + ROMSize));
                   5392: }
                   5393: 
                   5394: static void flush_all(void)
                   5395: {
                   5396:     int i;
                   5397: 
                   5398:        log_flush();
                   5399:     for (i=0;i<VREGS;i++)
                   5400:        if (live.state[i].status==DIRTY) {
                   5401:            if (!call_saved[live.state[i].realreg]) {
                   5402:                tomem(i);
                   5403:            }
                   5404:        }
                   5405:     for (i=0;i<VFREGS;i++)
                   5406:        if (f_isinreg(i)) 
                   5407:            f_evict(i);
                   5408:     raw_fp_cleanup_drop();
                   5409: }
                   5410: 
                   5411: /* Make sure all registers that will get clobbered by a call are
                   5412:    save and sound in memory */
                   5413: static void prepare_for_call_1(void)
                   5414: {
                   5415:     flush_all();  /* If there are registers that don't get clobbered,
                   5416:                   * we should be a bit more selective here */
                   5417: }
                   5418: 
                   5419: /* We will call a C routine in a moment. That will clobber all registers,
                   5420:    so we need to disassociate everything */
                   5421: static void prepare_for_call_2(void)
                   5422: {
                   5423:     int i;
                   5424:     for (i=0;i<N_REGS;i++)   
                   5425:        if (!call_saved[i] && live.nat[i].nholds>0)
                   5426:            free_nreg(i);
                   5427: 
                   5428:     for (i=0;i<N_FREGS;i++)   
                   5429:        if (live.fat[i].nholds>0)
                   5430:            f_free_nreg(i);
                   5431: 
                   5432:     live.flags_in_flags=TRASH;  /* Note: We assume we already rescued the
                   5433:                                   flags at the very start of the call_r
                   5434:                                   functions! */
                   5435: }
                   5436: 
                   5437: /********************************************************************
                   5438:  * Memory access and related functions, CREATE time                 *
                   5439:  ********************************************************************/
                   5440: 
                   5441: void register_branch(uae_u32 not_taken, uae_u32 taken, uae_u8 cond)
                   5442: {
                   5443:     next_pc_p=not_taken;
                   5444:     taken_pc_p=taken;
                   5445:     branch_cc=cond;
                   5446: }
                   5447: 
                   5448: 
                   5449: static uae_u32 get_handler_address(uae_u32 addr)
                   5450: {
                   5451:     uae_u32 cl=cacheline(addr);
                   5452:     blockinfo* bi=get_blockinfo_addr_new((void*)(uintptr)addr,0);
                   5453:     return (uintptr)&(bi->direct_handler_to_use);
                   5454: }
                   5455: 
                   5456: static uae_u32 get_handler(uae_u32 addr)
                   5457: {
                   5458:     uae_u32 cl=cacheline(addr);
                   5459:     blockinfo* bi=get_blockinfo_addr_new((void*)(uintptr)addr,0);
                   5460:     return (uintptr)bi->direct_handler_to_use;
                   5461: }
                   5462: 
                   5463: static void load_handler(int reg, uae_u32 addr)
                   5464: {
                   5465:     mov_l_rm(reg,get_handler_address(addr));
                   5466: }
                   5467: 
                   5468: /* This version assumes that it is writing *real* memory, and *will* fail
                   5469:  *  if that assumption is wrong! No branches, no second chances, just
                   5470:  *  straight go-for-it attitude */
                   5471: 
                   5472: static void writemem_real(int address, int source, int size, int tmp, int clobber)
                   5473: {
                   5474:     int f=tmp;
                   5475: 
                   5476:        if (clobber)
                   5477:            f=source;
                   5478: 
                   5479:        switch(size) {
                   5480:         case 1: mov_b_bRr(address,source,MEMBaseDiff); break; 
                   5481:         case 2: mov_w_rr(f,source); bswap_16(f); mov_w_bRr(address,f,MEMBaseDiff); break;
                   5482:         case 4: mov_l_rr(f,source); bswap_32(f); mov_l_bRr(address,f,MEMBaseDiff); break;
                   5483:        }
                   5484:        forget_about(tmp);
                   5485:        forget_about(f);
                   5486: }
                   5487: 
                   5488: void writebyte(int address, int source, int tmp)
                   5489: {
                   5490:        writemem_real(address,source,1,tmp,0);
                   5491: }
                   5492: 
                   5493: static __inline__ void writeword_general(int address, int source, int tmp,
                   5494:                                         int clobber)
                   5495: {
                   5496:        writemem_real(address,source,2,tmp,clobber);
                   5497: }
                   5498: 
                   5499: void writeword_clobber(int address, int source, int tmp)
                   5500: {
                   5501:     writeword_general(address,source,tmp,1);
                   5502: }
                   5503: 
                   5504: void writeword(int address, int source, int tmp)
                   5505: {
                   5506:     writeword_general(address,source,tmp,0);
                   5507: }
                   5508: 
                   5509: static __inline__ void writelong_general(int address, int source, int tmp, 
                   5510:                                         int clobber)
                   5511: {
                   5512:        writemem_real(address,source,4,tmp,clobber);
                   5513: }
                   5514: 
                   5515: void writelong_clobber(int address, int source, int tmp)
                   5516: {
                   5517:     writelong_general(address,source,tmp,1);
                   5518: }
                   5519: 
                   5520: void writelong(int address, int source, int tmp)
                   5521: {
                   5522:     writelong_general(address,source,tmp,0);
                   5523: }
                   5524: 
                   5525: 
                   5526: 
                   5527: /* This version assumes that it is reading *real* memory, and *will* fail
                   5528:  *  if that assumption is wrong! No branches, no second chances, just
                   5529:  *  straight go-for-it attitude */
                   5530: 
                   5531: static void readmem_real(int address, int dest, int size, int tmp)
                   5532: {
                   5533:     int f=tmp; 
                   5534: 
                   5535:     if (size==4 && address!=dest)
                   5536:        f=dest;
                   5537: 
                   5538:        switch(size) {
                   5539:         case 1: mov_b_brR(dest,address,MEMBaseDiff); break; 
                   5540:         case 2: mov_w_brR(dest,address,MEMBaseDiff); bswap_16(dest); break;
                   5541:         case 4: mov_l_brR(dest,address,MEMBaseDiff); bswap_32(dest); break;
                   5542:        }
                   5543:        forget_about(tmp);
                   5544: }
                   5545: 
                   5546: void readbyte(int address, int dest, int tmp)
                   5547: {
                   5548:        readmem_real(address,dest,1,tmp);
                   5549: }
                   5550: 
                   5551: void readword(int address, int dest, int tmp)
                   5552: {
                   5553:        readmem_real(address,dest,2,tmp);
                   5554: }
                   5555: 
                   5556: void readlong(int address, int dest, int tmp)
                   5557: {
                   5558:        readmem_real(address,dest,4,tmp);
                   5559: }
                   5560: 
                   5561: void get_n_addr(int address, int dest, int tmp)
                   5562: {
                   5563:        // a is the register containing the virtual address
                   5564:        // after the offset had been fetched
                   5565:        int a=tmp;
                   5566:        
                   5567:        // f is the register that will contain the offset
                   5568:        int f=tmp;
                   5569:        
                   5570:        // a == f == tmp if (address == dest)
                   5571:        if (address!=dest) {
                   5572:        a=address;
                   5573:        f=dest;
                   5574:        }
                   5575: 
                   5576: #if REAL_ADDRESSING
                   5577:        mov_l_rr(dest, address);
                   5578: #elif DIRECT_ADDRESSING
                   5579:        lea_l_brr(dest,address,MEMBaseDiff);
                   5580: #endif
                   5581:        forget_about(tmp);
                   5582: }
                   5583: 
                   5584: void get_n_addr_jmp(int address, int dest, int tmp)
                   5585: {
                   5586:        /* For this, we need to get the same address as the rest of UAE
                   5587:         would --- otherwise we end up translating everything twice */
                   5588:     get_n_addr(address,dest,tmp);
                   5589: }
                   5590: 
                   5591: 
                   5592: /* base is a register, but dp is an actual value. 
                   5593:    target is a register, as is tmp */
                   5594: void calc_disp_ea_020(int base, uae_u32 dp, int target, int tmp)
                   5595: {
                   5596:     int reg = (dp >> 12) & 15;
                   5597:     int regd_shift=(dp >> 9) & 3;
                   5598: 
                   5599:     if (dp & 0x100) {
                   5600:        int ignorebase=(dp&0x80);
                   5601:        int ignorereg=(dp&0x40);
                   5602:        int addbase=0;
                   5603:        int outer=0;
                   5604:     
                   5605:        if ((dp & 0x30) == 0x20) addbase = (uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2);
                   5606:        if ((dp & 0x30) == 0x30) addbase = comp_get_ilong((m68k_pc_offset+=4)-4);
                   5607: 
                   5608:        if ((dp & 0x3) == 0x2) outer = (uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2);
                   5609:        if ((dp & 0x3) == 0x3) outer = comp_get_ilong((m68k_pc_offset+=4)-4);
                   5610: 
                   5611:        if ((dp & 0x4) == 0) {  /* add regd *before* the get_long */
                   5612:            if (!ignorereg) {
                   5613:                if ((dp & 0x800) == 0) 
                   5614:                    sign_extend_16_rr(target,reg);
                   5615:                else
                   5616:                    mov_l_rr(target,reg);
                   5617:                shll_l_ri(target,regd_shift);
                   5618:            }
                   5619:            else
                   5620:                mov_l_ri(target,0);
                   5621: 
                   5622:            /* target is now regd */
                   5623:            if (!ignorebase)
                   5624:                add_l(target,base);
                   5625:            add_l_ri(target,addbase);
                   5626:            if (dp&0x03) readlong(target,target,tmp);
                   5627:        } else { /* do the getlong first, then add regd */
                   5628:            if (!ignorebase) {
                   5629:                mov_l_rr(target,base);
                   5630:                add_l_ri(target,addbase);
                   5631:            }
                   5632:            else
                   5633:                mov_l_ri(target,addbase);
                   5634:            if (dp&0x03) readlong(target,target,tmp);
                   5635: 
                   5636:            if (!ignorereg) {
                   5637:                if ((dp & 0x800) == 0) 
                   5638:                    sign_extend_16_rr(tmp,reg);
                   5639:                else
                   5640:                    mov_l_rr(tmp,reg);
                   5641:                shll_l_ri(tmp,regd_shift);
                   5642:                /* tmp is now regd */
                   5643:                add_l(target,tmp);
                   5644:            }
                   5645:        }
                   5646:        add_l_ri(target,outer);
                   5647:     }
                   5648:     else { /* 68000 version */
                   5649:        if ((dp & 0x800) == 0) { /* Sign extend */
                   5650:            sign_extend_16_rr(target,reg);
                   5651:            lea_l_brr_indexed(target,base,target,1<<regd_shift,(uae_s32)((uae_s8)dp));
                   5652:        }
                   5653:        else {
                   5654:            lea_l_brr_indexed(target,base,reg,1<<regd_shift,(uae_s32)((uae_s8)dp));
                   5655:        }
                   5656:     }
                   5657:     forget_about(tmp);
                   5658: }
                   5659: 
                   5660: 
                   5661: 
                   5662: 
                   5663: 
                   5664: void set_cache_state(int enabled)
                   5665: {
                   5666:     if (enabled!=letit)
                   5667:        flush_icache_hard(77);
                   5668:     letit=enabled;
                   5669: }
                   5670: 
                   5671: int get_cache_state(void)
                   5672: {
                   5673:     return letit;
                   5674: }
                   5675: 
                   5676: uae_u32 get_jitted_size(void)
                   5677: {
                   5678:     if (compiled_code)
                   5679:        return current_compile_p-compiled_code;
                   5680:     return 0;
                   5681: }
                   5682: 
                   5683: const int CODE_ALLOC_MAX_ATTEMPTS = 10;
                   5684: const int CODE_ALLOC_BOUNDARIES   = 128 * 1024; // 128 KB
                   5685: 
                   5686: static uint8 *do_alloc_code(uint32 size, int depth)
                   5687: {
                   5688: #if defined(__linux__) && 0
                   5689:        /*
                   5690:          This is a really awful hack that is known to work on Linux at
                   5691:          least.
                   5692:          
                   5693:          The trick here is to make sure the allocated cache is nearby
                   5694:          code segment, and more precisely in the positive half of a
                   5695:          32-bit address space. i.e. addr < 0x80000000. Actually, it
                   5696:          turned out that a 32-bit binary run on AMD64 yields a cache
                   5697:          allocated around 0xa0000000, thus causing some troubles when
                   5698:          translating addresses from m68k to x86.
                   5699:        */
                   5700:        static uint8 * code_base = NULL;
                   5701:        if (code_base == NULL) {
                   5702:                uintptr page_size = getpagesize();
                   5703:                uintptr boundaries = CODE_ALLOC_BOUNDARIES;
                   5704:                if (boundaries < page_size)
                   5705:                        boundaries = page_size;
                   5706:                code_base = (uint8 *)sbrk(0);
                   5707:                for (int attempts = 0; attempts < CODE_ALLOC_MAX_ATTEMPTS; attempts++) {
                   5708:                        if (vm_acquire_fixed(code_base, size) == 0) {
                   5709:                                uint8 *code = code_base;
                   5710:                                code_base += size;
                   5711:                                return code;
                   5712:                        }
                   5713:                        code_base += boundaries;
                   5714:                }
                   5715:                return NULL;
                   5716:        }
                   5717: 
                   5718:        if (vm_acquire_fixed(code_base, size) == 0) {
                   5719:                uint8 *code = code_base;
                   5720:                code_base += size;
                   5721:                return code;
                   5722:        }
                   5723: 
                   5724:        if (depth >= CODE_ALLOC_MAX_ATTEMPTS)
                   5725:                return NULL;
                   5726: 
                   5727:        return do_alloc_code(size, depth + 1);
                   5728: #else
                   5729:        uint8 *code = (uint8 *)vm_acquire(size);
                   5730:        return code == VM_MAP_FAILED ? NULL : code;
                   5731: #endif
                   5732: }
                   5733: 
                   5734: static inline uint8 *alloc_code(uint32 size)
                   5735: {
                   5736:        uint8 *ptr = do_alloc_code(size, 0);
                   5737:        /* allocated code must fit in 32-bit boundaries */
                   5738:        assert((uintptr)ptr <= 0xffffffff);
                   5739:        return ptr;
                   5740: }
                   5741: 
                   5742: void alloc_cache(void)
                   5743: {
                   5744:        if (compiled_code) {
                   5745:                flush_icache_hard(6);
                   5746:                vm_release(compiled_code, cache_size * 1024);
                   5747:                compiled_code = 0;
                   5748:        }
                   5749:        
                   5750:        if (cache_size == 0)
                   5751:                return;
                   5752:        
                   5753:        while (!compiled_code && cache_size) {
                   5754:                if ((compiled_code = alloc_code(cache_size * 1024)) == NULL) {
                   5755:                        compiled_code = 0;
                   5756:                        cache_size /= 2;
                   5757:                }
                   5758:        }
                   5759:        vm_protect(compiled_code, cache_size * 1024, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE);
                   5760:        
                   5761:        if (compiled_code) {
                   5762:                write_log("<JIT compiler> : actual translation cache size : %d KB at 0x%08X\n", cache_size, compiled_code);
                   5763:                max_compile_start = compiled_code + cache_size*1024 - BYTES_PER_INST;
                   5764:                current_compile_p = compiled_code;
                   5765:                current_cache_size = 0;
                   5766:        }
                   5767: }
                   5768: 
                   5769: 
                   5770: 
1.1.1.2 ! root     5771: void op_illg_1 (uae_u32 opcode) REGPARAM;
1.1       root     5772: 
                   5773: static void calc_checksum(blockinfo* bi, uae_u32* c1, uae_u32* c2)
                   5774: {
                   5775:     uae_u32 k1 = 0;
                   5776:     uae_u32 k2 = 0;
                   5777: 
                   5778: #if USE_CHECKSUM_INFO
                   5779:     checksum_info *csi = bi->csi;
                   5780:        Dif(!csi) abort();
                   5781:        while (csi) {
                   5782:                uae_s32 len = csi->length;
                   5783:                uintptr tmp = (uintptr)csi->start_p;
                   5784: #else
                   5785:                uae_s32 len = bi->len;
                   5786:                uintptr tmp = (uintptr)bi->min_pcp;
                   5787: #endif
                   5788:                uae_u32*pos;
                   5789: 
                   5790:                len += (tmp & 3);
                   5791:                tmp &= ~((uintptr)3);
                   5792:                pos = (uae_u32 *)tmp;
                   5793: 
                   5794:                if (len >= 0 && len <= MAX_CHECKSUM_LEN) {
                   5795:                        while (len > 0) {
                   5796:                                k1 += *pos;
                   5797:                                k2 ^= *pos;
                   5798:                                pos++;
                   5799:                                len -= 4;
                   5800:                        }
                   5801:                }
                   5802: 
                   5803: #if USE_CHECKSUM_INFO
                   5804:                csi = csi->next;
                   5805:        }
                   5806: #endif
                   5807: 
                   5808:        *c1 = k1;
                   5809:        *c2 = k2;
                   5810: }
                   5811: 
                   5812: #if 0
                   5813: static void show_checksum(CSI_TYPE* csi)
                   5814: {
                   5815:     uae_u32 k1=0;
                   5816:     uae_u32 k2=0;
                   5817:     uae_s32 len=CSI_LENGTH(csi);
                   5818:     uae_u32 tmp=(uintptr)CSI_START_P(csi);
                   5819:     uae_u32* pos;
                   5820: 
                   5821:     len+=(tmp&3);
                   5822:     tmp&=(~3);
                   5823:     pos=(uae_u32*)tmp;
                   5824: 
                   5825:     if (len<0 || len>MAX_CHECKSUM_LEN) {
                   5826:        return;
                   5827:     }
                   5828:     else {
                   5829:        while (len>0) {
                   5830:            write_log("%08x ",*pos);
                   5831:            pos++;
                   5832:            len-=4;
                   5833:        }
                   5834:        write_log(" bla\n");
                   5835:     }
                   5836: }
                   5837: #endif
                   5838: 
                   5839: 
                   5840: int check_for_cache_miss(void)
                   5841: {
                   5842:     blockinfo* bi=get_blockinfo_addr(regs.pc_p);
                   5843:     
                   5844:     if (bi) {
                   5845:        int cl=cacheline(regs.pc_p);
                   5846:        if (bi!=cache_tags[cl+1].bi) {
                   5847:            raise_in_cl_list(bi);
                   5848:            return 1;
                   5849:        }
                   5850:     }
                   5851:     return 0;
                   5852: }
                   5853: 
                   5854:     
                   5855: static void recompile_block(void)
                   5856: {
                   5857:     /* An existing block's countdown code has expired. We need to make
                   5858:        sure that execute_normal doesn't refuse to recompile due to a
                   5859:        perceived cache miss... */
                   5860:     blockinfo*  bi=get_blockinfo_addr(regs.pc_p);
                   5861: 
                   5862:     Dif (!bi) 
                   5863:        abort();
                   5864:     raise_in_cl_list(bi);
                   5865:     execute_normal();
                   5866:     return;
                   5867: }
                   5868: static void cache_miss(void)
                   5869: {
                   5870:     blockinfo*  bi=get_blockinfo_addr(regs.pc_p);
                   5871:     uae_u32     cl=cacheline(regs.pc_p);
                   5872:     blockinfo*  bi2=get_blockinfo(cl);
                   5873: 
                   5874:     if (!bi) {
                   5875:        execute_normal(); /* Compile this block now */
                   5876:        return;
                   5877:     }
                   5878:     Dif (!bi2 || bi==bi2) {
                   5879:        write_log("Unexplained cache miss %p %p\n",bi,bi2);
                   5880:        abort();
                   5881:     }
                   5882:     raise_in_cl_list(bi);
                   5883:     return;
                   5884: }
                   5885: 
                   5886: static int called_check_checksum(blockinfo* bi);
                   5887: 
                   5888: static inline int block_check_checksum(blockinfo* bi) 
                   5889: {
                   5890:     uae_u32     c1,c2;
                   5891:     bool        isgood;
                   5892:     
                   5893:     if (bi->status!=BI_NEED_CHECK)
                   5894:        return 1;  /* This block is in a checked state */
                   5895:     
                   5896:     checksum_count++;
                   5897: 
                   5898:     if (bi->c1 || bi->c2)
                   5899:        calc_checksum(bi,&c1,&c2);
                   5900:     else {
                   5901:        c1=c2=1;  /* Make sure it doesn't match */
                   5902:        }
                   5903:     
                   5904:     isgood=(c1==bi->c1 && c2==bi->c2);
                   5905: 
                   5906:     if (isgood) { 
                   5907:        /* This block is still OK. So we reactivate. Of course, that
                   5908:           means we have to move it into the needs-to-be-flushed list */
                   5909:        bi->handler_to_use=bi->handler;
                   5910:        set_dhtu(bi,bi->direct_handler);
                   5911:        bi->status=BI_CHECKING;
                   5912:        isgood=called_check_checksum(bi);
                   5913:     }
                   5914:     if (isgood) {
                   5915:        /*      write_log("reactivate %p/%p (%x %x/%x %x)\n",bi,bi->pc_p,
                   5916:                c1,c2,bi->c1,bi->c2);*/
                   5917:        remove_from_list(bi);
                   5918:        add_to_active(bi);
                   5919:        raise_in_cl_list(bi);
                   5920:        bi->status=BI_ACTIVE;
                   5921:     }
                   5922:     else {
                   5923:        /* This block actually changed. We need to invalidate it,
                   5924:           and set it up to be recompiled */
                   5925:        /* write_log("discard %p/%p (%x %x/%x %x)\n",bi,bi->pc_p,
                   5926:           c1,c2,bi->c1,bi->c2); */
                   5927:        invalidate_block(bi);
                   5928:        raise_in_cl_list(bi);
                   5929:     }
                   5930:     return isgood;
                   5931: }
                   5932: 
                   5933: static int called_check_checksum(blockinfo* bi) 
                   5934: {
                   5935:     dependency* x=bi->deplist;
                   5936:     int isgood=1;
                   5937:     int i;
                   5938:     
                   5939:     for (i=0;i<2 && isgood;i++) {
                   5940:        if (bi->dep[i].jmp_off) {
                   5941:            isgood=block_check_checksum(bi->dep[i].target);
                   5942:        }
                   5943:     }
                   5944:     return isgood;
                   5945: }
                   5946: 
                   5947: static void check_checksum(void) 
                   5948: {
                   5949:     blockinfo*  bi=get_blockinfo_addr(regs.pc_p);
                   5950:     uae_u32     cl=cacheline(regs.pc_p);
                   5951:     blockinfo*  bi2=get_blockinfo(cl);
                   5952: 
                   5953:     /* These are not the droids you are looking for...  */
                   5954:     if (!bi) {
                   5955:        /* Whoever is the primary target is in a dormant state, but
                   5956:           calling it was accidental, and we should just compile this
                   5957:           new block */
                   5958:        execute_normal();
                   5959:        return;
                   5960:     }
                   5961:     if (bi!=bi2) {
                   5962:        /* The block was hit accidentally, but it does exist. Cache miss */
                   5963:        cache_miss();
                   5964:        return;
                   5965:     }
                   5966: 
                   5967:     if (!block_check_checksum(bi))
                   5968:        execute_normal();
                   5969: }
                   5970: 
                   5971: static __inline__ void match_states(blockinfo* bi)
                   5972: {
                   5973:     int i;
                   5974:     smallstate* s=&(bi->env);
                   5975:     
                   5976:     if (bi->status==BI_NEED_CHECK) {
                   5977:        block_check_checksum(bi);
                   5978:     }
                   5979:     if (bi->status==BI_ACTIVE || 
                   5980:        bi->status==BI_FINALIZING) {  /* Deal with the *promises* the 
                   5981:                                         block makes (about not using 
                   5982:                                         certain vregs) */
                   5983:        for (i=0;i<16;i++) {
                   5984:            if (s->virt[i]==L_UNNEEDED) {
                   5985:                // write_log("unneeded reg %d at %p\n",i,target);
                   5986:                COMPCALL(forget_about)(i); // FIXME
                   5987:            }
                   5988:        }
                   5989:     }
                   5990:     flush(1);
                   5991: 
                   5992:     /* And now deal with the *demands* the block makes */
                   5993:     for (i=0;i<N_REGS;i++) {
                   5994:        int v=s->nat[i];
                   5995:        if (v>=0) {
                   5996:            // printf("Loading reg %d into %d at %p\n",v,i,target);
                   5997:            readreg_specific(v,4,i);
                   5998:            // do_load_reg(i,v);
                   5999:            // setlock(i);
                   6000:        }
                   6001:     }
                   6002:     for (i=0;i<N_REGS;i++) {
                   6003:        int v=s->nat[i];
                   6004:        if (v>=0) {
                   6005:            unlock2(i);
                   6006:        }
                   6007:     }
                   6008: }
                   6009: 
                   6010: static __inline__ void create_popalls(void)
                   6011: {
                   6012:   int i,r;
                   6013: 
                   6014:   if ((popallspace = alloc_code(POPALLSPACE_SIZE)) == NULL) {
                   6015:          write_log("FATAL: Could not allocate popallspace!\n");
                   6016:          abort();
                   6017:   }
                   6018:   vm_protect(popallspace, POPALLSPACE_SIZE, VM_PAGE_READ | VM_PAGE_WRITE);
                   6019: 
                   6020:   int stack_space = STACK_OFFSET;
                   6021:   for (i=0;i<N_REGS;i++) {
                   6022:          if (need_to_preserve[i])
                   6023:                  stack_space += sizeof(void *);
                   6024:   }
                   6025:   stack_space %= STACK_ALIGN;
                   6026:   if (stack_space)
                   6027:          stack_space = STACK_ALIGN - stack_space;
                   6028: 
                   6029:   current_compile_p=popallspace;
                   6030:   set_target(current_compile_p);
                   6031: 
                   6032:   /* We need to guarantee 16-byte stack alignment on x86 at any point
                   6033:      within the JIT generated code. We have multiple exit points
                   6034:      possible but a single entry. A "jmp" is used so that we don't
                   6035:      have to generate stack alignment in generated code that has to
                   6036:      call external functions (e.g. a generic instruction handler).
                   6037: 
                   6038:      In summary, JIT generated code is not leaf so we have to deal
                   6039:      with it here to maintain correct stack alignment. */
                   6040:   align_target(align_jumps);
                   6041:   current_compile_p=get_target();
                   6042:   pushall_call_handler=get_target();
                   6043:   for (i=N_REGS;i--;) {
                   6044:       if (need_to_preserve[i])
                   6045:          raw_push_l_r(i);
                   6046:   }
                   6047:   raw_dec_sp(stack_space);
                   6048:   r=REG_PC_TMP;
                   6049:   raw_mov_l_rm(r,(uintptr)&regs.pc_p);
                   6050:   raw_and_l_ri(r,TAGMASK);
                   6051:   raw_jmp_m_indexed((uintptr)cache_tags,r,SIZEOF_VOID_P);
                   6052: 
                   6053:   /* now the exit points */
                   6054:   align_target(align_jumps);
                   6055:   popall_do_nothing=get_target();
                   6056:   raw_inc_sp(stack_space);
                   6057:   for (i=0;i<N_REGS;i++) {
                   6058:       if (need_to_preserve[i])
                   6059:          raw_pop_l_r(i);
                   6060:   }
                   6061:   raw_jmp((uintptr)do_nothing);
                   6062:   
                   6063:   align_target(align_jumps);
                   6064:   popall_execute_normal=get_target();
                   6065:   raw_inc_sp(stack_space);
                   6066:   for (i=0;i<N_REGS;i++) {
                   6067:       if (need_to_preserve[i])
                   6068:          raw_pop_l_r(i);
                   6069:   }
                   6070:   raw_jmp((uintptr)execute_normal);
                   6071: 
                   6072:   align_target(align_jumps);
                   6073:   popall_cache_miss=get_target();
                   6074:   raw_inc_sp(stack_space);
                   6075:   for (i=0;i<N_REGS;i++) {
                   6076:       if (need_to_preserve[i])
                   6077:          raw_pop_l_r(i);
                   6078:   }
                   6079:   raw_jmp((uintptr)cache_miss);
                   6080: 
                   6081:   align_target(align_jumps);
                   6082:   popall_recompile_block=get_target();
                   6083:   raw_inc_sp(stack_space);
                   6084:   for (i=0;i<N_REGS;i++) {
                   6085:       if (need_to_preserve[i])
                   6086:          raw_pop_l_r(i);
                   6087:   }
                   6088:   raw_jmp((uintptr)recompile_block);
                   6089: 
                   6090:   align_target(align_jumps);
                   6091:   popall_exec_nostats=get_target();
                   6092:   raw_inc_sp(stack_space);
                   6093:   for (i=0;i<N_REGS;i++) {
                   6094:       if (need_to_preserve[i])
                   6095:          raw_pop_l_r(i);
                   6096:   }
                   6097:   raw_jmp((uintptr)exec_nostats);
                   6098: 
                   6099:   align_target(align_jumps);
                   6100:   popall_check_checksum=get_target();
                   6101:   raw_inc_sp(stack_space);
                   6102:   for (i=0;i<N_REGS;i++) {
                   6103:       if (need_to_preserve[i])
                   6104:          raw_pop_l_r(i);
                   6105:   }
                   6106:   raw_jmp((uintptr)check_checksum);
                   6107: 
                   6108:   // no need to further write into popallspace
                   6109:   vm_protect(popallspace, POPALLSPACE_SIZE, VM_PAGE_READ | VM_PAGE_EXECUTE);
                   6110: }
                   6111: 
                   6112: static __inline__ void reset_lists(void)
                   6113: {
                   6114:     int i;
                   6115:     
                   6116:     for (i=0;i<MAX_HOLD_BI;i++)
                   6117:        hold_bi[i]=NULL;
                   6118:     active=NULL;
                   6119:     dormant=NULL;
                   6120: }
                   6121: 
                   6122: static void prepare_block(blockinfo* bi)
                   6123: {
                   6124:     int i;
                   6125: 
                   6126:     set_target(current_compile_p);
                   6127:     align_target(align_jumps);
                   6128:     bi->direct_pen=(cpuop_func *)get_target();
                   6129:     raw_mov_l_rm(0,(uintptr)&(bi->pc_p));
                   6130:     raw_mov_l_mr((uintptr)&regs.pc_p,0);
                   6131:     raw_jmp((uintptr)popall_execute_normal);
                   6132: 
                   6133:     align_target(align_jumps);
                   6134:     bi->direct_pcc=(cpuop_func *)get_target();
                   6135:     raw_mov_l_rm(0,(uintptr)&(bi->pc_p));
                   6136:     raw_mov_l_mr((uintptr)&regs.pc_p,0);
                   6137:     raw_jmp((uintptr)popall_check_checksum);
                   6138:     current_compile_p=get_target();
                   6139: 
                   6140:     bi->deplist=NULL;
                   6141:     for (i=0;i<2;i++) {
                   6142:        bi->dep[i].prev_p=NULL;
                   6143:        bi->dep[i].next=NULL;
                   6144:     }
                   6145:     bi->env=default_ss;
                   6146:     bi->status=BI_INVALID;
                   6147:     bi->havestate=0;
                   6148:     //bi->env=empty_ss;
                   6149: }
                   6150: 
                   6151: // OPCODE is in big endian format, use cft_map() beforehand, if needed.
                   6152: static inline void reset_compop(int opcode)
                   6153: {
                   6154:        compfunctbl[opcode] = NULL;
                   6155:        nfcompfunctbl[opcode] = NULL;
                   6156: }
                   6157: 
                   6158: static int read_opcode(const char *p)
                   6159: {
                   6160:        int opcode = 0;
                   6161:        for (int i = 0; i < 4; i++) {
                   6162:                int op = p[i];
                   6163:                switch (op) {
                   6164:                case '0': case '1': case '2': case '3': case '4':
                   6165:                case '5': case '6': case '7': case '8': case '9':
                   6166:                        opcode = (opcode << 4) | (op - '0');
                   6167:                        break;
                   6168:                case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
                   6169:                        opcode = (opcode << 4) | ((op - 'a') + 10);
                   6170:                        break;
                   6171:                case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
                   6172:                        opcode = (opcode << 4) | ((op - 'A') + 10);
                   6173:                        break;
                   6174:                default:
                   6175:                        return -1;
                   6176:                }
                   6177:        }
                   6178:        return opcode;
                   6179: }
                   6180: 
                   6181: static bool merge_blacklist()
                   6182: {
                   6183:        const char *blacklist = PrefsFindString("jitblacklist");
                   6184:        if (blacklist) {
                   6185:                const char *p = blacklist;
                   6186:                for (;;) {
                   6187:                        if (*p == 0)
                   6188:                                return true;
                   6189: 
                   6190:                        int opcode1 = read_opcode(p);
                   6191:                        if (opcode1 < 0)
                   6192:                                return false;
                   6193:                        p += 4;
                   6194: 
                   6195:                        int opcode2 = opcode1;
                   6196:                        if (*p == '-') {
                   6197:                                p++;
                   6198:                                opcode2 = read_opcode(p);
                   6199:                                if (opcode2 < 0)
                   6200:                                        return false;
                   6201:                                p += 4;
                   6202:                        }
                   6203: 
                   6204:                        if (*p == 0 || *p == ',' || *p == ';') {
                   6205:                                write_log("<JIT compiler> : blacklist opcodes : %04x-%04x\n", opcode1, opcode2);
                   6206:                                for (int opcode = opcode1; opcode <= opcode2; opcode++)
                   6207:                                        reset_compop(cft_map(opcode));
                   6208: 
                   6209:                                if (*p == ',' || *p++ == ';')
                   6210:                                        continue;
                   6211: 
                   6212:                                return true;
                   6213:                        }
                   6214: 
                   6215:                        return false;
                   6216:                }
                   6217:        }
                   6218:        return true;
                   6219: }
                   6220: 
                   6221: void build_comp(void) 
                   6222: {
                   6223:        int i;
                   6224:     int jumpcount=0;
                   6225:     unsigned long opcode;
                   6226:     struct comptbl* tbl=op_smalltbl_0_comp_ff;
                   6227:     struct comptbl* nftbl=op_smalltbl_0_comp_nf;
                   6228:     int count;
                   6229:        int cpu_level = 0;                      // 68000 (default)
                   6230:        if (CPUType == 4)
                   6231:                cpu_level = 4;                  // 68040 with FPU
                   6232:        else {
                   6233:                if (FPUType)
                   6234:                        cpu_level = 3;          // 68020 with FPU
                   6235:                else if (CPUType >= 2)
                   6236:                        cpu_level = 2;          // 68020
                   6237:                else if (CPUType == 1)
                   6238:                        cpu_level = 1;
                   6239:        }
                   6240:     struct cputbl *nfctbl = (
                   6241:                                   cpu_level == 4 ? op_smalltbl_0_nf
                   6242:                             : cpu_level == 3 ? op_smalltbl_1_nf
                   6243:                             : cpu_level == 2 ? op_smalltbl_2_nf
                   6244:                             : cpu_level == 1 ? op_smalltbl_3_nf
                   6245:                             : op_smalltbl_4_nf);
                   6246: 
                   6247:     write_log ("<JIT compiler> : building compiler function tables\n");
                   6248:        
                   6249:        for (opcode = 0; opcode < 65536; opcode++) {
                   6250:                reset_compop(opcode);
                   6251:                nfcpufunctbl[opcode] = op_illg_1;
                   6252:                prop[opcode].use_flags = 0x1f;
                   6253:                prop[opcode].set_flags = 0x1f;
                   6254:                prop[opcode].cflow = fl_trap; // ILLEGAL instructions do trap
                   6255:        }
                   6256:        
                   6257:        for (i = 0; tbl[i].opcode < 65536; i++) {
                   6258:                int cflow = table68k[tbl[i].opcode].cflow;
                   6259:                if (follow_const_jumps && (tbl[i].specific & 16))
                   6260:                        cflow = fl_const_jump;
                   6261:                else
                   6262:                        cflow &= ~fl_const_jump;
                   6263:                prop[cft_map(tbl[i].opcode)].cflow = cflow;
                   6264: 
                   6265:                int uses_fpu = tbl[i].specific & 32;
                   6266:                if (uses_fpu && avoid_fpu)
                   6267:                        compfunctbl[cft_map(tbl[i].opcode)] = NULL;
                   6268:                else
                   6269:                        compfunctbl[cft_map(tbl[i].opcode)] = tbl[i].handler;
                   6270:        }
                   6271: 
                   6272:     for (i = 0; nftbl[i].opcode < 65536; i++) {
                   6273:                int uses_fpu = tbl[i].specific & 32;
                   6274:                if (uses_fpu && avoid_fpu)
                   6275:                        nfcompfunctbl[cft_map(nftbl[i].opcode)] = NULL;
                   6276:                else
                   6277:                        nfcompfunctbl[cft_map(nftbl[i].opcode)] = nftbl[i].handler;
                   6278:                
                   6279:                nfcpufunctbl[cft_map(nftbl[i].opcode)] = nfctbl[i].handler;
                   6280:     }
                   6281: 
                   6282:        for (i = 0; nfctbl[i].handler; i++) {
                   6283:                nfcpufunctbl[cft_map(nfctbl[i].opcode)] = nfctbl[i].handler;
                   6284:        }
                   6285: 
                   6286:     for (opcode = 0; opcode < 65536; opcode++) {
                   6287:                compop_func *f;
                   6288:                compop_func *nff;
                   6289:                cpuop_func *nfcf;
                   6290:                int isaddx,cflow;
                   6291: 
                   6292:                if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > cpu_level)
                   6293:                        continue;
                   6294: 
                   6295:                if (table68k[opcode].handler != -1) {
                   6296:                        f = compfunctbl[cft_map(table68k[opcode].handler)];
                   6297:                        nff = nfcompfunctbl[cft_map(table68k[opcode].handler)];
                   6298:                        nfcf = nfcpufunctbl[cft_map(table68k[opcode].handler)];
                   6299:                        cflow = prop[cft_map(table68k[opcode].handler)].cflow;
                   6300:                        isaddx = prop[cft_map(table68k[opcode].handler)].is_addx;
                   6301:                        prop[cft_map(opcode)].cflow = cflow;
                   6302:                        prop[cft_map(opcode)].is_addx = isaddx;
                   6303:                        compfunctbl[cft_map(opcode)] = f;
                   6304:                        nfcompfunctbl[cft_map(opcode)] = nff;
                   6305:                        Dif (nfcf == op_illg_1)
                   6306:                        abort();
                   6307:                        nfcpufunctbl[cft_map(opcode)] = nfcf;
                   6308:                }
                   6309:                prop[cft_map(opcode)].set_flags = table68k[opcode].flagdead;
                   6310:                prop[cft_map(opcode)].use_flags = table68k[opcode].flaglive;
                   6311:                /* Unconditional jumps don't evaluate condition codes, so they
                   6312:                 * don't actually use any flags themselves */
                   6313:                if (prop[cft_map(opcode)].cflow & fl_const_jump)
                   6314:                        prop[cft_map(opcode)].use_flags = 0;
                   6315:     }
                   6316:        for (i = 0; nfctbl[i].handler != NULL; i++) {
                   6317:                if (nfctbl[i].specific)
                   6318:                        nfcpufunctbl[cft_map(tbl[i].opcode)] = nfctbl[i].handler;
                   6319:        }
                   6320: 
                   6321:        /* Merge in blacklist */
                   6322:        if (!merge_blacklist())
                   6323:                write_log("<JIT compiler> : blacklist merge failure!\n");
                   6324: 
                   6325:     count=0;
                   6326:     for (opcode = 0; opcode < 65536; opcode++) {
                   6327:        if (compfunctbl[cft_map(opcode)])
                   6328:            count++;
                   6329:     }
                   6330:        write_log("<JIT compiler> : supposedly %d compileable opcodes!\n",count);
                   6331: 
                   6332:     /* Initialise state */
                   6333:     create_popalls();
                   6334:     alloc_cache();
                   6335:     reset_lists();
                   6336: 
                   6337:     for (i=0;i<TAGSIZE;i+=2) {
                   6338:        cache_tags[i].handler=(cpuop_func *)popall_execute_normal;
                   6339:        cache_tags[i+1].bi=NULL;
                   6340:     }
                   6341:     
                   6342: #if 0
                   6343:     for (i=0;i<N_REGS;i++) {
                   6344:        empty_ss.nat[i].holds=-1;
                   6345:        empty_ss.nat[i].validsize=0;
                   6346:        empty_ss.nat[i].dirtysize=0;
                   6347:     }
                   6348: #endif
                   6349:     for (i=0;i<VREGS;i++) {
                   6350:        empty_ss.virt[i]=L_NEEDED;
                   6351:     }
                   6352:     for (i=0;i<N_REGS;i++) {
                   6353:        empty_ss.nat[i]=L_UNKNOWN;
                   6354:     }
                   6355:     default_ss=empty_ss;
                   6356: }
                   6357: 
                   6358: 
                   6359: static void flush_icache_none(int n)
                   6360: {
                   6361:        /* Nothing to do.  */
                   6362: }
                   6363:     
                   6364: static void flush_icache_hard(int n)
                   6365: {
                   6366:     uae_u32 i;
                   6367:     blockinfo* bi, *dbi;
                   6368: 
                   6369:     hard_flush_count++;
                   6370: #if 0
                   6371:     write_log("Flush Icache_hard(%d/%x/%p), %u KB\n",
                   6372:           n,regs.pc,regs.pc_p,current_cache_size/1024);
                   6373:        current_cache_size = 0;
                   6374: #endif
                   6375:     bi=active;
                   6376:     while(bi) {
                   6377:        cache_tags[cacheline(bi->pc_p)].handler=(cpuop_func *)popall_execute_normal;
                   6378:        cache_tags[cacheline(bi->pc_p)+1].bi=NULL;
                   6379:        dbi=bi; bi=bi->next;
                   6380:        free_blockinfo(dbi);
                   6381:     }
                   6382:     bi=dormant;
                   6383:     while(bi) {
                   6384:        cache_tags[cacheline(bi->pc_p)].handler=(cpuop_func *)popall_execute_normal;
                   6385:        cache_tags[cacheline(bi->pc_p)+1].bi=NULL;
                   6386:        dbi=bi; bi=bi->next;
                   6387:        free_blockinfo(dbi);
                   6388:     }
                   6389: 
                   6390:     reset_lists();
                   6391:     if (!compiled_code)
                   6392:        return;
                   6393:     current_compile_p=compiled_code;
                   6394:        SPCFLAGS_SET( SPCFLAG_JIT_EXEC_RETURN ); /* To get out of compiled code */
                   6395: }
                   6396: 
                   6397: 
                   6398: /* "Soft flushing" --- instead of actually throwing everything away,
                   6399:    we simply mark everything as "needs to be checked". 
                   6400: */
                   6401: 
                   6402: static inline void flush_icache_lazy(int n)
                   6403: {
                   6404:     uae_u32 i;
                   6405:     blockinfo* bi;
                   6406:     blockinfo* bi2;
                   6407: 
                   6408:         soft_flush_count++;
                   6409:        if (!active)
                   6410:            return;
                   6411: 
                   6412:        bi=active;
                   6413:        while (bi) {
                   6414:            uae_u32 cl=cacheline(bi->pc_p);
                   6415:                if (bi->status==BI_INVALID ||
                   6416:                        bi->status==BI_NEED_RECOMP) { 
                   6417:                if (bi==cache_tags[cl+1].bi) 
                   6418:                    cache_tags[cl].handler=(cpuop_func *)popall_execute_normal;
                   6419:                bi->handler_to_use=(cpuop_func *)popall_execute_normal;
                   6420:                set_dhtu(bi,bi->direct_pen);
                   6421:            bi->status=BI_INVALID;
                   6422:            }
                   6423:            else {
                   6424:                if (bi==cache_tags[cl+1].bi) 
                   6425:                    cache_tags[cl].handler=(cpuop_func *)popall_check_checksum;
                   6426:                bi->handler_to_use=(cpuop_func *)popall_check_checksum;
                   6427:                set_dhtu(bi,bi->direct_pcc);
                   6428:                bi->status=BI_NEED_CHECK;
                   6429:            }
                   6430:            bi2=bi;
                   6431:            bi=bi->next;
                   6432:        }
                   6433:        /* bi2 is now the last entry in the active list */
                   6434:        bi2->next=dormant;
                   6435:        if (dormant)
                   6436:            dormant->prev_p=&(bi2->next);
                   6437:     
                   6438:        dormant=active;
                   6439:        active->prev_p=&dormant;
                   6440:        active=NULL;
                   6441: }
                   6442: 
                   6443: void flush_icache_range(uae_u8 *start_p, uae_u32 length)
                   6444: {
                   6445:        if (!active)
                   6446:                return;
                   6447: 
                   6448: #if LAZY_FLUSH_ICACHE_RANGE
                   6449:        blockinfo *bi = active;
                   6450:        while (bi) {
                   6451: #if USE_CHECKSUM_INFO
                   6452:                bool candidate = false;
                   6453:                for (checksum_info *csi = bi->csi; csi; csi = csi->next) {
                   6454:                        if (((start_p - csi->start_p) < csi->length) ||
                   6455:                                ((csi->start_p - start_p) < length)) {
                   6456:                                candidate = true;
                   6457:                                break;
                   6458:                        }
                   6459:                }
                   6460: #else
                   6461:                // Assume system is consistent and would invalidate the right range
                   6462:                const bool candidate = (bi->pc_p - start_p) < length;
                   6463: #endif
                   6464:                blockinfo *dbi = bi;
                   6465:                bi = bi->next;
                   6466:                if (candidate) {
                   6467:                        uae_u32 cl = cacheline(dbi->pc_p);
                   6468:                        if (dbi->status == BI_INVALID || dbi->status == BI_NEED_RECOMP) {
                   6469:                                if (dbi == cache_tags[cl+1].bi) 
                   6470:                                        cache_tags[cl].handler = (cpuop_func *)popall_execute_normal;
                   6471:                                dbi->handler_to_use = (cpuop_func *)popall_execute_normal;
                   6472:                                set_dhtu(dbi, dbi->direct_pen);
                   6473:                                dbi->status = BI_INVALID;
                   6474:                        }
                   6475:                        else {
                   6476:                                if (dbi == cache_tags[cl+1].bi) 
                   6477:                                        cache_tags[cl].handler = (cpuop_func *)popall_check_checksum;
                   6478:                                dbi->handler_to_use = (cpuop_func *)popall_check_checksum;
                   6479:                                set_dhtu(dbi, dbi->direct_pcc);
                   6480:                                dbi->status = BI_NEED_CHECK;
                   6481:                        }
                   6482:                        remove_from_list(dbi);
                   6483:                        add_to_dormant(dbi);
                   6484:                }
                   6485:        }
                   6486:        return;
                   6487: #endif
                   6488:        flush_icache(-1);
                   6489: }
                   6490: 
                   6491: static void catastrophe(void)
                   6492: {
                   6493:     abort();
                   6494: }
                   6495: 
                   6496: int failure;
                   6497: 
                   6498: #define TARGET_M68K            0
                   6499: #define TARGET_POWERPC 1
                   6500: #define TARGET_X86             2
                   6501: #define TARGET_X86_64  3
                   6502: #if defined(i386) || defined(__i386__)
                   6503: #define TARGET_NATIVE  TARGET_X86
                   6504: #endif
                   6505: #if defined(powerpc) || defined(__powerpc__)
                   6506: #define TARGET_NATIVE  TARGET_POWERPC
                   6507: #endif
                   6508: #if defined(x86_64) || defined(__x86_64__)
                   6509: #define TARGET_NATIVE  TARGET_X86_64
                   6510: #endif
                   6511: 
                   6512: #ifdef ENABLE_MON
                   6513: static uae_u32 mon_read_byte_jit(uintptr addr)
                   6514: {
                   6515:        uae_u8 *m = (uae_u8 *)addr;
                   6516:        return (uintptr)(*m);
                   6517: }
                   6518:  
                   6519: static void mon_write_byte_jit(uintptr addr, uae_u32 b)
                   6520: {
                   6521:        uae_u8 *m = (uae_u8 *)addr;
                   6522:        *m = b;
                   6523: }
                   6524: #endif
                   6525: 
                   6526: void disasm_block(int target, uint8 * start, size_t length)
                   6527: {
                   6528:        if (!JITDebug)
                   6529:                return;
                   6530:        
                   6531: #if defined(JIT_DEBUG) && defined(ENABLE_MON)
                   6532:        char disasm_str[200];
                   6533:        sprintf(disasm_str, "%s $%x $%x",
                   6534:                        target == TARGET_M68K ? "d68" :
                   6535:                        target == TARGET_X86 ? "d86" :
                   6536:                        target == TARGET_X86_64 ? "d8664" :
                   6537:                        target == TARGET_POWERPC ? "d" : "x",
                   6538:                        start, start + length - 1);
                   6539:        
                   6540:        uae_u32 (*old_mon_read_byte)(uintptr) = mon_read_byte;
                   6541:        void (*old_mon_write_byte)(uintptr, uae_u32) = mon_write_byte;
                   6542:        
                   6543:        mon_read_byte = mon_read_byte_jit;
                   6544:        mon_write_byte = mon_write_byte_jit;
                   6545:        
                   6546:        char *arg[5] = {"mon", "-m", "-r", disasm_str, NULL};
                   6547:        mon(4, arg);
                   6548:        
                   6549:        mon_read_byte = old_mon_read_byte;
                   6550:        mon_write_byte = old_mon_write_byte;
                   6551: #endif
                   6552: }
                   6553: 
                   6554: static void disasm_native_block(uint8 *start, size_t length)
                   6555: {
                   6556:        disasm_block(TARGET_NATIVE, start, length);
                   6557: }
                   6558: 
                   6559: static void disasm_m68k_block(uint8 *start, size_t length)
                   6560: {
                   6561:        disasm_block(TARGET_M68K, start, length);
                   6562: }
                   6563: 
                   6564: #ifdef HAVE_GET_WORD_UNSWAPPED
                   6565: # define DO_GET_OPCODE(a) (do_get_mem_word_unswapped((uae_u16 *)(a)))
                   6566: #else
                   6567: # define DO_GET_OPCODE(a) (do_get_mem_word((uae_u16 *)(a)))
                   6568: #endif
                   6569: 
                   6570: #if JIT_DEBUG
                   6571: static uae_u8 *last_regs_pc_p = 0;
                   6572: static uae_u8 *last_compiled_block_addr = 0;
                   6573: 
                   6574: void compiler_dumpstate(void)
                   6575: {
                   6576:        if (!JITDebug)
                   6577:                return;
                   6578:        
                   6579:        write_log("### Host addresses\n");
                   6580:        write_log("MEM_BASE    : %x\n", MEMBaseDiff);
                   6581:        write_log("PC_P        : %p\n", &regs.pc_p);
                   6582:        write_log("SPCFLAGS    : %p\n", &regs.spcflags);
                   6583:        write_log("D0-D7       : %p-%p\n", &regs.regs[0], &regs.regs[7]);
                   6584:        write_log("A0-A7       : %p-%p\n", &regs.regs[8], &regs.regs[15]);
                   6585:        write_log("\n");
                   6586:        
                   6587:        write_log("### M68k processor state\n");
                   6588:        m68k_dumpstate(0);
                   6589:        write_log("\n");
                   6590:        
                   6591:        write_log("### Block in Mac address space\n");
                   6592:        write_log("M68K block   : %p\n",
                   6593:                          (void *)(uintptr)get_virtual_address(last_regs_pc_p));
                   6594:        write_log("Native block : %p (%d bytes)\n",
                   6595:                          (void *)(uintptr)get_virtual_address(last_compiled_block_addr),
                   6596:                          get_blockinfo_addr(last_regs_pc_p)->direct_handler_size);
                   6597:        write_log("\n");
                   6598: }
                   6599: #endif
                   6600: 
                   6601: static void compile_block(cpu_history* pc_hist, int blocklen)
                   6602: {
                   6603:     if (letit && compiled_code) {
                   6604: #if PROFILE_COMPILE_TIME
                   6605:        compile_count++;
                   6606:        clock_t start_time = clock();
                   6607: #endif
                   6608: #if JIT_DEBUG
                   6609:        bool disasm_block = false;
                   6610: #endif
                   6611:        
                   6612:        /* OK, here we need to 'compile' a block */
                   6613:        int i;
                   6614:        int r;
                   6615:        int was_comp=0;
                   6616:        uae_u8 liveflags[MAXRUN+1];
                   6617: #if USE_CHECKSUM_INFO
                   6618:        bool trace_in_rom = isinrom((uintptr)pc_hist[0].location);
                   6619:        uintptr max_pcp=(uintptr)pc_hist[blocklen - 1].location;
                   6620:        uintptr min_pcp=max_pcp;
                   6621: #else
                   6622:        uintptr max_pcp=(uintptr)pc_hist[0].location;
                   6623:        uintptr min_pcp=max_pcp;
                   6624: #endif
                   6625:        uae_u32 cl=cacheline(pc_hist[0].location);
                   6626:        void* specflags=(void*)&regs.spcflags;
                   6627:        blockinfo* bi=NULL;
                   6628:        blockinfo* bi2;
                   6629:        int extra_len=0;
                   6630: 
                   6631:        redo_current_block=0;
                   6632:        if (current_compile_p>=max_compile_start)
                   6633:            flush_icache_hard(7);
                   6634: 
                   6635:        alloc_blockinfos();
                   6636: 
                   6637:        bi=get_blockinfo_addr_new(pc_hist[0].location,0);
                   6638:        bi2=get_blockinfo(cl);
                   6639: 
                   6640:        optlev=bi->optlevel;
                   6641:        if (bi->status!=BI_INVALID) {
                   6642:            Dif (bi!=bi2) { 
                   6643:                /* I don't think it can happen anymore. Shouldn't, in 
                   6644:                   any case. So let's make sure... */
                   6645:                write_log("WOOOWOO count=%d, ol=%d %p %p\n",
                   6646:                       bi->count,bi->optlevel,bi->handler_to_use,
                   6647:                       cache_tags[cl].handler);
                   6648:                abort();
                   6649:            }
                   6650: 
                   6651:            Dif (bi->count!=-1 && bi->status!=BI_NEED_RECOMP) {
                   6652:                write_log("bi->count=%d, bi->status=%d\n",bi->count,bi->status);
                   6653:                /* What the heck? We are not supposed to be here! */
                   6654:                abort();
                   6655:            }
                   6656:        }       
                   6657:        if (bi->count==-1) {
                   6658:            optlev++;
                   6659:            while (!optcount[optlev])
                   6660:                optlev++;
                   6661:            bi->count=optcount[optlev]-1;
                   6662:        }
                   6663:        current_block_pc_p=(uintptr)pc_hist[0].location;
                   6664:        
                   6665:        remove_deps(bi); /* We are about to create new code */
                   6666:        bi->optlevel=optlev;
                   6667:        bi->pc_p=(uae_u8*)pc_hist[0].location;
                   6668: #if USE_CHECKSUM_INFO
                   6669:        free_checksum_info_chain(bi->csi);
                   6670:        bi->csi = NULL;
                   6671: #endif
                   6672:        
                   6673:        liveflags[blocklen]=0x1f; /* All flags needed afterwards */
                   6674:        i=blocklen;
                   6675:        while (i--) {
                   6676:            uae_u16* currpcp=pc_hist[i].location;
                   6677:            uae_u32 op=DO_GET_OPCODE(currpcp);
                   6678: 
                   6679: #if USE_CHECKSUM_INFO
                   6680:                trace_in_rom = trace_in_rom && isinrom((uintptr)currpcp);
                   6681:                if (follow_const_jumps && is_const_jump(op)) {
                   6682:                        checksum_info *csi = alloc_checksum_info();
                   6683:                        csi->start_p = (uae_u8 *)min_pcp;
                   6684:                        csi->length = max_pcp - min_pcp + LONGEST_68K_INST;
                   6685:                        csi->next = bi->csi;
                   6686:                        bi->csi = csi;
                   6687:                        max_pcp = (uintptr)currpcp;
                   6688:                }
                   6689:                min_pcp = (uintptr)currpcp;
                   6690: #else
                   6691:            if ((uintptr)currpcp<min_pcp)
                   6692:                min_pcp=(uintptr)currpcp;
                   6693:            if ((uintptr)currpcp>max_pcp)
                   6694:                max_pcp=(uintptr)currpcp;
                   6695: #endif
                   6696: 
                   6697:                liveflags[i]=((liveflags[i+1]&
                   6698:                               (~prop[op].set_flags))|
                   6699:                              prop[op].use_flags);
                   6700:                if (prop[op].is_addx && (liveflags[i+1]&FLAG_Z)==0)
                   6701:                    liveflags[i]&= ~FLAG_Z;
                   6702:        }
                   6703: 
                   6704: #if USE_CHECKSUM_INFO
                   6705:        checksum_info *csi = alloc_checksum_info();
                   6706:        csi->start_p = (uae_u8 *)min_pcp;
                   6707:        csi->length = max_pcp - min_pcp + LONGEST_68K_INST;
                   6708:        csi->next = bi->csi;
                   6709:        bi->csi = csi;
                   6710: #endif
                   6711: 
                   6712:        bi->needed_flags=liveflags[0];
                   6713: 
                   6714:        align_target(align_loops);
                   6715:        was_comp=0;
                   6716: 
                   6717:        bi->direct_handler=(cpuop_func *)get_target();
                   6718:        set_dhtu(bi,bi->direct_handler);
                   6719:        bi->status=BI_COMPILING;
                   6720:        current_block_start_target=(uintptr)get_target();
                   6721:        
                   6722:        log_startblock();
                   6723:        
                   6724:        if (bi->count>=0) { /* Need to generate countdown code */
                   6725:            raw_mov_l_mi((uintptr)&regs.pc_p,(uintptr)pc_hist[0].location);
                   6726:            raw_sub_l_mi((uintptr)&(bi->count),1);
                   6727:            raw_jl((uintptr)popall_recompile_block);
                   6728:        }
                   6729:        if (optlev==0) { /* No need to actually translate */
                   6730:            /* Execute normally without keeping stats */
                   6731:            raw_mov_l_mi((uintptr)&regs.pc_p,(uintptr)pc_hist[0].location);
                   6732:            raw_jmp((uintptr)popall_exec_nostats); 
                   6733:        }
                   6734:        else {
                   6735:            reg_alloc_run=0;
                   6736:            next_pc_p=0;
                   6737:            taken_pc_p=0;
                   6738:            branch_cc=0;
                   6739:                
                   6740:            comp_pc_p=(uae_u8*)pc_hist[0].location;
                   6741:            init_comp();
                   6742:            was_comp=1;
                   6743: 
                   6744: #ifdef USE_CPU_EMUL_SERVICES
                   6745:            raw_sub_l_mi((uintptr)&emulated_ticks,blocklen);
                   6746:            raw_jcc_b_oponly(NATIVE_CC_GT);
                   6747:            uae_s8 *branchadd=(uae_s8*)get_target();
                   6748:            emit_byte(0);
                   6749:            raw_call((uintptr)cpu_do_check_ticks);
                   6750:            *branchadd=(uintptr)get_target()-((uintptr)branchadd+1);
                   6751: #endif
                   6752: 
                   6753: #if JIT_DEBUG
                   6754:                if (JITDebug) {
                   6755:                        raw_mov_l_mi((uintptr)&last_regs_pc_p,(uintptr)pc_hist[0].location);
                   6756:                        raw_mov_l_mi((uintptr)&last_compiled_block_addr,current_block_start_target);
                   6757:                }
                   6758: #endif
                   6759:                
                   6760:            for (i=0;i<blocklen &&
                   6761:                     get_target_noopt()<max_compile_start;i++) {
                   6762:                cpuop_func **cputbl;
                   6763:                compop_func **comptbl;
                   6764:                uae_u32 opcode=DO_GET_OPCODE(pc_hist[i].location);
                   6765:                needed_flags=(liveflags[i+1] & prop[opcode].set_flags);
                   6766:                if (!needed_flags) {
                   6767:                    cputbl=nfcpufunctbl;
                   6768:                    comptbl=nfcompfunctbl;
                   6769:                }
                   6770:                else {
                   6771:                    cputbl=cpufunctbl;
                   6772:                    comptbl=compfunctbl;
                   6773:                }
                   6774: 
                   6775: #if FLIGHT_RECORDER
                   6776:                {
                   6777:                    mov_l_ri(S1, get_virtual_address((uae_u8 *)(pc_hist[i].location)) | 1);
                   6778:                    clobber_flags();
                   6779:                    remove_all_offsets();
                   6780:                    int arg = readreg_specific(S1,4,REG_PAR1);
                   6781:                    prepare_for_call_1();
                   6782:                    unlock2(arg);
                   6783:                    prepare_for_call_2();
                   6784:                    raw_call((uintptr)m68k_record_step);
                   6785:                }
                   6786: #endif
                   6787:                
                   6788:                failure = 1; // gb-- defaults to failure state
                   6789:                if (comptbl[opcode] && optlev>1) { 
                   6790:                    failure=0;
                   6791:                    if (!was_comp) {
                   6792:                        comp_pc_p=(uae_u8*)pc_hist[i].location;
                   6793:                        init_comp();
                   6794:                    }
                   6795:                    was_comp=1;
                   6796: 
                   6797:                    comptbl[opcode](opcode);
                   6798:                    freescratch();
                   6799:                    if (!(liveflags[i+1] & FLAG_CZNV)) { 
                   6800:                        /* We can forget about flags */
                   6801:                        dont_care_flags();
                   6802:                    }
                   6803: #if INDIVIDUAL_INST 
                   6804:                    flush(1);
                   6805:                    nop();
                   6806:                    flush(1);
                   6807:                    was_comp=0;
                   6808: #endif
                   6809:                }
                   6810:                
                   6811:                if (failure) {
                   6812:                    if (was_comp) {
                   6813:                        flush(1);
                   6814:                        was_comp=0;
                   6815:                    }
                   6816:                    raw_mov_l_ri(REG_PAR1,(uae_u32)opcode);
                   6817: #if USE_NORMAL_CALLING_CONVENTION
                   6818:                    raw_push_l_r(REG_PAR1);
                   6819: #endif
                   6820:                    raw_mov_l_mi((uintptr)&regs.pc_p,
                   6821:                                 (uintptr)pc_hist[i].location);
                   6822:                    raw_call((uintptr)cputbl[opcode]);
                   6823: #if PROFILE_UNTRANSLATED_INSNS
                   6824:                        // raw_cputbl_count[] is indexed with plain opcode (in m68k order)
                   6825:                        raw_add_l_mi((uintptr)&raw_cputbl_count[cft_map(opcode)],1);
                   6826: #endif
                   6827: #if USE_NORMAL_CALLING_CONVENTION
                   6828:                    raw_inc_sp(4);
                   6829: #endif
                   6830:                    
                   6831:                    if (i < blocklen - 1) {
                   6832:                        uae_s8* branchadd;
                   6833:                        
                   6834:                        raw_mov_l_rm(0,(uintptr)specflags);
                   6835:                        raw_test_l_rr(0,0);
                   6836:                        raw_jz_b_oponly();
                   6837:                        branchadd=(uae_s8 *)get_target();
                   6838:                        emit_byte(0);
                   6839:                        raw_jmp((uintptr)popall_do_nothing);
                   6840:                        *branchadd=(uintptr)get_target()-(uintptr)branchadd-1;
                   6841:                    }
                   6842:                }
                   6843:            }
                   6844: #if 1 /* This isn't completely kosher yet; It really needs to be
                   6845:         be integrated into a general inter-block-dependency scheme */
                   6846:            if (next_pc_p && taken_pc_p &&
                   6847:                was_comp && taken_pc_p==current_block_pc_p) {
                   6848:                blockinfo* bi1=get_blockinfo_addr_new((void*)next_pc_p,0);
                   6849:                blockinfo* bi2=get_blockinfo_addr_new((void*)taken_pc_p,0);
                   6850:                uae_u8 x=bi1->needed_flags;
                   6851:                
                   6852:                if (x==0xff || 1) {  /* To be on the safe side */
                   6853:                    uae_u16* next=(uae_u16*)next_pc_p;
                   6854:                    uae_u32 op=DO_GET_OPCODE(next);
                   6855: 
                   6856:                    x=0x1f;
                   6857:                    x&=(~prop[op].set_flags);
                   6858:                    x|=prop[op].use_flags;
                   6859:                }
                   6860:                
                   6861:                x|=bi2->needed_flags;
                   6862:                if (!(x & FLAG_CZNV)) { 
                   6863:                    /* We can forget about flags */
                   6864:                    dont_care_flags();
                   6865:                    extra_len+=2; /* The next instruction now is part of this
                   6866:                                     block */
                   6867:                }
                   6868:                    
                   6869:            }
                   6870: #endif
                   6871:                log_flush();
                   6872: 
                   6873:            if (next_pc_p) { /* A branch was registered */
                   6874:                uintptr t1=next_pc_p;
                   6875:                uintptr t2=taken_pc_p;
                   6876:                int     cc=branch_cc;
                   6877:                
                   6878:                uae_u32* branchadd;
                   6879:                uae_u32* tba;
                   6880:                bigstate tmp;
                   6881:                blockinfo* tbi;
                   6882: 
                   6883:                if (taken_pc_p<next_pc_p) {
                   6884:                    /* backward branch. Optimize for the "taken" case ---
                   6885:                       which means the raw_jcc should fall through when
                   6886:                       the 68k branch is taken. */
                   6887:                    t1=taken_pc_p;
                   6888:                    t2=next_pc_p;
                   6889:                    cc=branch_cc^1;
                   6890:                }
                   6891:                
                   6892:                tmp=live; /* ouch! This is big... */
                   6893:                raw_jcc_l_oponly(cc);
                   6894:                branchadd=(uae_u32*)get_target();
                   6895:                emit_long(0);
                   6896:                
                   6897:                /* predicted outcome */
                   6898:                tbi=get_blockinfo_addr_new((void*)t1,1);
                   6899:                match_states(tbi);
                   6900:                raw_cmp_l_mi((uintptr)specflags,0);
                   6901:                raw_jcc_l_oponly(4);
                   6902:                tba=(uae_u32*)get_target();
                   6903:                emit_long(get_handler(t1)-((uintptr)tba+4));
                   6904:                raw_mov_l_mi((uintptr)&regs.pc_p,t1);
                   6905:                flush_reg_count();
                   6906:                raw_jmp((uintptr)popall_do_nothing);
                   6907:                create_jmpdep(bi,0,tba,t1);
                   6908: 
                   6909:                align_target(align_jumps);
                   6910:                /* not-predicted outcome */
                   6911:                *branchadd=(uintptr)get_target()-((uintptr)branchadd+4);
                   6912:                live=tmp; /* Ouch again */
                   6913:                tbi=get_blockinfo_addr_new((void*)t2,1);
                   6914:                match_states(tbi);
                   6915: 
                   6916:                //flush(1); /* Can only get here if was_comp==1 */
                   6917:                raw_cmp_l_mi((uintptr)specflags,0);
                   6918:                raw_jcc_l_oponly(4);
                   6919:                tba=(uae_u32*)get_target();
                   6920:                emit_long(get_handler(t2)-((uintptr)tba+4));
                   6921:                raw_mov_l_mi((uintptr)&regs.pc_p,t2);
                   6922:                flush_reg_count();
                   6923:                raw_jmp((uintptr)popall_do_nothing);
                   6924:                create_jmpdep(bi,1,tba,t2);
                   6925:            }           
                   6926:            else 
                   6927:            {
                   6928:                if (was_comp) {
                   6929:                    flush(1);
                   6930:                }
                   6931:                flush_reg_count();
                   6932:                
                   6933:                /* Let's find out where next_handler is... */
                   6934:                if (was_comp && isinreg(PC_P)) { 
                   6935:                    r=live.state[PC_P].realreg;
                   6936:                        raw_and_l_ri(r,TAGMASK);
                   6937:                        int r2 = (r==0) ? 1 : 0;
                   6938:                        raw_mov_l_ri(r2,(uintptr)popall_do_nothing);
                   6939:                        raw_cmp_l_mi((uintptr)specflags,0);
                   6940:                        raw_cmov_l_rm_indexed(r2,(uintptr)cache_tags,r,SIZEOF_VOID_P,NATIVE_CC_EQ);
                   6941:                        raw_jmp_r(r2);
                   6942:                }
                   6943:                else if (was_comp && isconst(PC_P)) {
                   6944:                    uae_u32 v=live.state[PC_P].val;
                   6945:                    uae_u32* tba;
                   6946:                    blockinfo* tbi;
                   6947: 
                   6948:                    tbi=get_blockinfo_addr_new((void*)(uintptr)v,1);
                   6949:                    match_states(tbi);
                   6950: 
                   6951:                        raw_cmp_l_mi((uintptr)specflags,0);
                   6952:                        raw_jcc_l_oponly(4);
                   6953:                    tba=(uae_u32*)get_target();
                   6954:                    emit_long(get_handler(v)-((uintptr)tba+4));
                   6955:                    raw_mov_l_mi((uintptr)&regs.pc_p,v);
                   6956:                    raw_jmp((uintptr)popall_do_nothing);
                   6957:                    create_jmpdep(bi,0,tba,v);
                   6958:                }
                   6959:                else {
                   6960:                    r=REG_PC_TMP;
                   6961:                    raw_mov_l_rm(r,(uintptr)&regs.pc_p);
                   6962:                        raw_and_l_ri(r,TAGMASK);
                   6963:                        int r2 = (r==0) ? 1 : 0;
                   6964:                        raw_mov_l_ri(r2,(uintptr)popall_do_nothing);
                   6965:                        raw_cmp_l_mi((uintptr)specflags,0);
                   6966:                        raw_cmov_l_rm_indexed(r2,(uintptr)cache_tags,r,SIZEOF_VOID_P,NATIVE_CC_EQ);
                   6967:                        raw_jmp_r(r2);
                   6968:                }
                   6969:            }
                   6970:        }
                   6971: 
                   6972: #if USE_MATCH  
                   6973:        if (callers_need_recompile(&live,&(bi->env))) {
                   6974:            mark_callers_recompile(bi);
                   6975:        }
                   6976: 
                   6977:        big_to_small_state(&live,&(bi->env));
                   6978: #endif
                   6979: 
                   6980: #if USE_CHECKSUM_INFO
                   6981:        remove_from_list(bi);
                   6982:        if (trace_in_rom) {
                   6983:                // No need to checksum that block trace on cache invalidation
                   6984:                free_checksum_info_chain(bi->csi);
                   6985:                bi->csi = NULL;
                   6986:                add_to_dormant(bi);
                   6987:        }
                   6988:        else {
                   6989:            calc_checksum(bi,&(bi->c1),&(bi->c2));
                   6990:                add_to_active(bi);
                   6991:        }
                   6992: #else
                   6993:        if (next_pc_p+extra_len>=max_pcp && 
                   6994:            next_pc_p+extra_len<max_pcp+LONGEST_68K_INST) 
                   6995:            max_pcp=next_pc_p+extra_len;  /* extra_len covers flags magic */
                   6996:        else
                   6997:            max_pcp+=LONGEST_68K_INST;
                   6998: 
                   6999:        bi->len=max_pcp-min_pcp;
                   7000:        bi->min_pcp=min_pcp;
                   7001:        
                   7002:        remove_from_list(bi);
                   7003:        if (isinrom(min_pcp) && isinrom(max_pcp)) {
                   7004:            add_to_dormant(bi); /* No need to checksum it on cache flush.
                   7005:                                   Please don't start changing ROMs in
                   7006:                                   flight! */
                   7007:        }
                   7008:        else {
                   7009:            calc_checksum(bi,&(bi->c1),&(bi->c2));
                   7010:            add_to_active(bi);
                   7011:        }
                   7012: #endif
                   7013:        
                   7014:        current_cache_size += get_target() - (uae_u8 *)current_compile_p;
                   7015:        
                   7016: #if JIT_DEBUG
                   7017:        if (JITDebug)
                   7018:                bi->direct_handler_size = get_target() - (uae_u8 *)current_block_start_target;
                   7019:        
                   7020:        if (JITDebug && disasm_block) {
                   7021:                uaecptr block_addr = start_pc + ((char *)pc_hist[0].location - (char *)start_pc_p);
                   7022:                D(bug("M68K block @ 0x%08x (%d insns)\n", block_addr, blocklen));
                   7023:                uae_u32 block_size = ((uae_u8 *)pc_hist[blocklen - 1].location - (uae_u8 *)pc_hist[0].location) + 1;
                   7024:                disasm_m68k_block((uae_u8 *)pc_hist[0].location, block_size);
                   7025:                D(bug("Compiled block @ 0x%08x\n", pc_hist[0].location));
                   7026:                disasm_native_block((uae_u8 *)current_block_start_target, bi->direct_handler_size);
                   7027:                getchar();
                   7028:        }
                   7029: #endif
                   7030:        
                   7031:        log_dump();
                   7032:        align_target(align_jumps);
                   7033: 
                   7034:        /* This is the non-direct handler */
                   7035:        bi->handler=
                   7036:            bi->handler_to_use=(cpuop_func *)get_target();
                   7037:        raw_cmp_l_mi((uintptr)&regs.pc_p,(uintptr)pc_hist[0].location);
                   7038:        raw_jnz((uintptr)popall_cache_miss);
                   7039:        comp_pc_p=(uae_u8*)pc_hist[0].location;
                   7040: 
                   7041:        bi->status=BI_FINALIZING;
                   7042:        init_comp();
                   7043:        match_states(bi);
                   7044:        flush(1);
                   7045: 
                   7046:        raw_jmp((uintptr)bi->direct_handler);
                   7047: 
                   7048:        current_compile_p=get_target();
                   7049:        raise_in_cl_list(bi);
                   7050:        
                   7051:        /* We will flush soon, anyway, so let's do it now */
                   7052:        if (current_compile_p>=max_compile_start)
                   7053:                flush_icache_hard(7);
                   7054:        
                   7055:        bi->status=BI_ACTIVE;
                   7056:        if (redo_current_block)
                   7057:            block_need_recompile(bi);
                   7058:        
                   7059: #if PROFILE_COMPILE_TIME
                   7060:        compile_time += (clock() - start_time);
                   7061: #endif
                   7062:     }
                   7063: 
                   7064:     /* Account for compilation time */
                   7065:     cpu_do_check_ticks();
                   7066: }
                   7067: 
                   7068: void do_nothing(void)
                   7069: {
                   7070:     /* What did you expect this to do? */
                   7071: }
                   7072: 
                   7073: void exec_nostats(void)
                   7074: {
                   7075:        for (;;)  { 
                   7076:                uae_u32 opcode = GET_OPCODE;
                   7077: #if FLIGHT_RECORDER
                   7078:                m68k_record_step(m68k_getpc());
                   7079: #endif
                   7080:                (*cpufunctbl[opcode])(opcode);
                   7081:                cpu_check_ticks();
                   7082:                if (end_block(opcode) || SPCFLAGS_TEST(SPCFLAG_ALL)) {
                   7083:                        return; /* We will deal with the spcflags in the caller */
                   7084:                }
                   7085:        }
                   7086: }
                   7087: 
                   7088: void execute_normal(void)
                   7089: {
                   7090:        if (!check_for_cache_miss()) {
                   7091:                cpu_history pc_hist[MAXRUN];
                   7092:                int blocklen = 0;
                   7093: #if REAL_ADDRESSING || DIRECT_ADDRESSING
                   7094:                start_pc_p = regs.pc_p;
                   7095:                start_pc = get_virtual_address(regs.pc_p);
                   7096: #else
                   7097:                start_pc_p = regs.pc_oldp;  
                   7098:                start_pc = regs.pc; 
                   7099: #endif
                   7100:                for (;;)  { /* Take note: This is the do-it-normal loop */
                   7101:                        pc_hist[blocklen++].location = (uae_u16 *)regs.pc_p;
                   7102:                        uae_u32 opcode = GET_OPCODE;
                   7103: #if FLIGHT_RECORDER
                   7104:                        m68k_record_step(m68k_getpc());
                   7105: #endif
                   7106:                        (*cpufunctbl[opcode])(opcode);
                   7107:                        cpu_check_ticks();
                   7108:                        if (end_block(opcode) || SPCFLAGS_TEST(SPCFLAG_ALL) || blocklen>=MAXRUN) {
                   7109:                                compile_block(pc_hist, blocklen);
                   7110:                                return; /* We will deal with the spcflags in the caller */
                   7111:                        }
                   7112:                        /* No need to check regs.spcflags, because if they were set,
                   7113:                        we'd have ended up inside that "if" */
                   7114:                }
                   7115:        }
                   7116: }
                   7117: 
                   7118: typedef void (*compiled_handler)(void);
                   7119: 
                   7120: static void m68k_do_compile_execute(void)
                   7121: {
                   7122:        for (;;) {
                   7123:                ((compiled_handler)(pushall_call_handler))();
                   7124:                /* Whenever we return from that, we should check spcflags */
                   7125:                if (SPCFLAGS_TEST(SPCFLAG_ALL)) {
                   7126:                        if (m68k_do_specialties ())
                   7127:                                return;
                   7128:                }
                   7129:        }
                   7130: }
                   7131: 
                   7132: void m68k_compile_execute (void)
                   7133: {
                   7134:     for (;;) {
                   7135:          if (quit_program)
                   7136:                break;
                   7137:          m68k_do_compile_execute();
                   7138:     }
                   7139: }

unix.superglobalmegacorp.com

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