Annotation of uae/src/compiler.c, revision 1.1.1.3

1.1.1.3 ! root        1:  /*
1.1       root        2:   * UAE - The Un*x Amiga Emulator
1.1.1.3 ! root        3:   *
1.1       root        4:   * m68k emulation
                      5:   *
1.1.1.3 ! root        6:   * Copyright 1996 Bernd Schmidt
1.1       root        7:   */
                      8: 
                      9: #include "sysconfig.h"
                     10: #include "sysdeps.h"
                     11: 
                     12: #include "config.h"
                     13: #include "options.h"
1.1.1.3 ! root       14: #include "gensound.h"
        !            15: #include "sounddep/sound.h"
1.1       root       16: #include "events.h"
                     17: #include "gui.h"
                     18: #include "memory.h"
                     19: #include "custom.h"
1.1.1.2   root       20: #include "machdep/m68k.h"
                     21: #include "readcpu.h"
1.1       root       22: #include "newcpu.h"
                     23: #include "ersatz.h"
                     24: #include "blitter.h"
                     25: #include "debug.h"
                     26: #include "autoconf.h"
                     27: #include "compiler.h"
                     28: 
                     29: #ifdef USE_COMPILER
                     30: 
                     31: #include <sys/mman.h>
                     32: 
                     33: char *address_space, *good_address_map;
                     34: 
                     35: code_execfunc exec_me;
1.1.1.3 ! root       36: uae_u8 nr_bbs_to_run = 1;
1.1       root       37: int nr_bbs_start = 40;
                     38: 
                     39: static int compile_failure;
                     40: static int quiet_compile = 1;
                     41: int i_want_to_die = 1;
                     42: static int n_compiled = 0;
                     43: static int n_max_comp = 99999999;
1.1.1.3 ! root       44: static uaecptr call_only_me = 0;
1.1       root       45: 
                     46: int patched_syscalls = 0;
                     47: 
1.1.1.3 ! root       48: static int count_bits(uae_u16 v)
1.1       root       49: {
                     50:     int bits = 0;
                     51:     while (v != 0) {
                     52:        if (v & 1)
                     53:            bits++;
                     54:        v >>= 1;
                     55:     }
                     56:     return bits;
                     57: }
                     58: 
1.1.1.3 ! root       59: static uae_u16 bitswap(uae_u16 v)
1.1       root       60: {
1.1.1.3 ! root       61:     uae_u16 newv = 0;
        !            62:     uae_u16 m1 = 1, m2 = 0x8000;
1.1       root       63:     int i;
1.1.1.3 ! root       64: 
1.1       root       65:     for (i = 0; i < 16; i++) {
                     66:        if (v & m1)
                     67:            newv |= m2;
                     68:        m2 >>= 1;
                     69:        m1 <<= 1;
                     70:     }
                     71:     return newv;
                     72: }
                     73: 
                     74: static long long compiled_hits = 0;
                     75: 
                     76: /* 16K areas with 512 byte blocks */
                     77: #define SUBUNIT_ORDER 9
                     78: #define PAGE_SUBUNIT (1 << SUBUNIT_ORDER)
                     79: #define PAGE_ALLOC_UNIT (PAGE_SUBUNIT * 32)
                     80: 
                     81: static int zerofd;
                     82: static int zeroff;
                     83: static struct code_page *first_code_page;
                     84: 
                     85: static struct code_page *new_code_page(void)
                     86: {
                     87:     struct code_page *ncp;
1.1.1.3 ! root       88: 
        !            89:     ncp = (struct code_page *)mmap(NULL, PAGE_ALLOC_UNIT,
1.1       root       90:                                   PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE,
                     91:                                   zerofd, zeroff);
                     92:     zeroff += PAGE_ALLOC_UNIT;
                     93:     if (ncp) {
                     94:        ncp->next = first_code_page;
                     95:        first_code_page = ncp;
                     96:        ncp->allocmask = 1; /* what a waste */
                     97:     }
                     98:     return ncp;
                     99: }
                    100: 
1.1.1.2   root      101: #define NUM_HASH 32768 /* larger values cause some paging on my 16MB machine */
1.1       root      102: #define HASH_MASK (NUM_HASH-1)
1.1.1.2   root      103: #define MAX_UNUSED_HASH 512
1.1       root      104: 
1.1.1.2   root      105: static int SCAN_MARK = 1; /* Number of calls after which to scan a function */
                    106: static int COMPILE_MARK = 5; /* Number of calls after which to compile a function */
1.1       root      107: 
1.1.1.2   root      108: /* The main address -> function lookup hashtable. We use the lower bits of
                    109:  * the address as hash function. */
1.1       root      110: static struct hash_entry cpu_hash[NUM_HASH];
1.1.1.2   root      111: /* These aren't really LRU lists... They used to be, but keeping them in that
                    112:  * order is costly. The hash LRU list is now a two-part list: Functions that have
                    113:  * no code allocated for them are placed at the beginning. Such entries can be
                    114:  * recycled when we need a new hash entry. */
1.1       root      115: static struct hash_block lru_first_block;
                    116: static struct hash_entry lru_first_hash;
                    117: static struct hash_entry *freelist_hash;
                    118: static struct hash_block *freelist_block;
1.1.1.2   root      119: static int num_unused_hash;
1.1       root      120: 
                    121: static int m68k_scan_func(struct hash_entry *);
                    122: static int m68k_compile_block(struct hash_block *);
                    123: 
                    124: static char *alloc_code(struct hash_block *hb, int ninsns)
                    125: {
                    126:     struct code_page *cp;
                    127:     long int allocsize = (ninsns * 32 + PAGE_SUBUNIT-1) & ~(PAGE_SUBUNIT-1);
1.1.1.3 ! root      128:     uae_u32 allocmask;
1.1       root      129:     int allocbits;
                    130:     int j;
                    131:     int last_bit;
                    132: 
                    133:     if (allocsize >= (PAGE_ALLOC_UNIT - (1 << SUBUNIT_ORDER)))
                    134:        return NULL;
                    135:     allocbits = (allocsize >> SUBUNIT_ORDER);
                    136:     allocmask = (1 << allocbits) - 1;
1.1.1.3 ! root      137: 
1.1       root      138:     for (cp = first_code_page; cp != NULL; cp = cp->next) {
1.1.1.3 ! root      139:        uae_u32 thispage_alloc = cp->allocmask;
1.1       root      140:        for (j = 1; j < (33 - allocbits); j++) {
                    141:            if ((cp->allocmask & (allocmask << j)) == 0) {
                    142:                goto found_page;
                    143:            }
                    144:        }
                    145:     }
                    146: 
                    147:     /* Nothing large enough free: make a new page */
                    148:     cp = new_code_page();
                    149:     if (cp == NULL)
                    150:        return NULL;
                    151:     j = 1;
1.1.1.3 ! root      152: 
1.1       root      153: found_page:
                    154:     /* See whether there is in fact more space for us. If so, allocate all of
                    155:      * it. compile_block() will free everything it didn't need. */
                    156: 
                    157:     allocmask <<= j;
                    158:     last_bit = allocbits + j;
                    159:     while (last_bit < 32 && (cp->allocmask & (1 << last_bit)) == 0) {
                    160:        allocmask |= 1 << last_bit;
                    161:        allocsize += PAGE_SUBUNIT;
                    162:        last_bit++;
                    163:     }
                    164: 
                    165:     hb->page_allocmask = allocmask;
                    166:     hb->cpage = cp;
                    167:     cp->allocmask |= allocmask;
                    168:     hb->compile_start = ((char *)cp + (j << SUBUNIT_ORDER));
                    169:     hb->alloclen = allocsize;
                    170:     return hb->compile_start;
                    171: }
                    172: 
1.1.1.2   root      173: static void remove_hash_from_lists(struct hash_entry *h)
1.1       root      174: {
                    175:     h->lru_next->lru_prev = h->lru_prev;
                    176:     h->lru_prev->lru_next = h->lru_next;
1.1.1.3 ! root      177: 
1.1       root      178:     h->next->prev = h->prev;
                    179:     h->prev->next = h->next;
1.1.1.2   root      180: }
                    181: 
                    182: static void lru_touch(struct hash_entry *h)
                    183: {
                    184:     h->lru_next->lru_prev = h->lru_prev;
                    185:     h->lru_prev->lru_next = h->lru_next;
1.1.1.3 ! root      186: 
1.1.1.2   root      187:     h->lru_next = &lru_first_hash;
                    188:     h->lru_prev = lru_first_hash.lru_prev;
                    189:     h->lru_prev->lru_next = h;
                    190:     lru_first_hash.lru_prev = h;
                    191: }
                    192: 
                    193: static void lru_untouch(struct hash_entry *h)
                    194: {
                    195:     h->lru_next->lru_prev = h->lru_prev;
                    196:     h->lru_prev->lru_next = h->lru_next;
1.1.1.3 ! root      197: 
1.1.1.2   root      198:     h->lru_prev = &lru_first_hash;
                    199:     h->lru_next = lru_first_hash.lru_next;
                    200:     h->lru_next->lru_prev = h;
                    201:     lru_first_hash.lru_next = h;
1.1       root      202: }
                    203: 
                    204: static void forget_block(struct hash_block *hb)
                    205: {
                    206:     struct hash_entry *h = hb->he_first;
1.1.1.3 ! root      207: 
1.1       root      208:     hb->lru_next->lru_prev = hb->lru_prev;
                    209:     hb->lru_prev->lru_next = hb->lru_next;
                    210: 
                    211:     hb->lru_next = freelist_block;
                    212:     freelist_block = hb;
                    213: 
                    214:     if (hb->cpage != NULL)
                    215:        fprintf(stderr, "Discarding block with code. Tsk.\n");
                    216: 
                    217:     do {
                    218:        struct hash_entry *next = h->next_same_block;
                    219:        h->block = NULL;
                    220:        h->execute = NULL;
                    221:        h->next_same_block = NULL;
                    222:        h = next;
1.1.1.2   root      223:        num_unused_hash++;
                    224:        lru_untouch(h);
1.1       root      225:     } while (h != hb->he_first);
1.1.1.2   root      226:     compiler_flush_jsr_stack();
1.1       root      227: }
                    228: 
                    229: static void lru_touch_block(struct hash_block *h)
                    230: {
                    231:     h->lru_next->lru_prev = h->lru_prev;
                    232:     h->lru_prev->lru_next = h->lru_next;
1.1.1.3 ! root      233: 
1.1       root      234:     h->lru_next = &lru_first_block;
                    235:     h->lru_prev = lru_first_block.lru_prev;
                    236:     h->lru_prev->lru_next = h;
1.1.1.3 ! root      237:     lru_first_block.lru_prev = h;
1.1       root      238: }
                    239: 
1.1.1.2   root      240: static __inline__ int check_block(struct hash_block *hb)
1.1       root      241: {
                    242: #ifndef RELY_ON_LOADSEG_DETECTION
                    243:     struct hash_entry *h = hb->he_first;
1.1.1.3 ! root      244: 
1.1       root      245:     do {
                    246:        struct hash_entry *next = h->next_same_block;
1.1.1.3 ! root      247:        if (h->matchword != *(uae_u32 *)get_real_address(h->addr))
1.1       root      248:            return 0;
                    249:        h = next;
                    250:     } while (h != hb->he_first);
                    251: #endif
                    252:     return 1;
                    253: }
                    254: 
1.1.1.3 ! root      255: uae_u32 flush_icache(void)
1.1       root      256: {
                    257:     struct hash_block *hb = lru_first_block.lru_next;
1.1.1.3 ! root      258: 
1.1       root      259:     while (hb != &lru_first_block) {
                    260:        struct hash_block *next = hb->lru_next;
                    261:        if (hb->cpage != NULL) {
                    262:            /* Address in chipmem? Then forget about block*/
                    263:            if ((hb->he_first->addr & ~0xF80000) != 0xF80000) {
                    264:                hb->cpage->allocmask &= ~hb->page_allocmask;
                    265:                hb->cpage = NULL;
                    266:                forget_block(hb);
                    267:            }
                    268:        }
                    269:        hb = next;
                    270:     }
1.1.1.2   root      271:     return m68k_dreg(regs, 0);
1.1       root      272: }
                    273: 
                    274: void possible_loadseg(void)
                    275: {
                    276:     fprintf(stderr, "Possible LoadSeg() detected\n");
                    277:     flush_icache();
                    278: }
                    279: 
                    280: static struct hash_block *new_block(void)
                    281: {
                    282:     struct hash_block *b = freelist_block;
1.1.1.3 ! root      283: 
1.1       root      284:     if (b != NULL) {
                    285:        freelist_block = b->lru_next;
                    286:     } else
                    287:        b = (struct hash_block *)malloc(sizeof *b);
                    288:     b->nrefs = 0;
                    289:     b->cpage = NULL;
                    290:     b->he_first = NULL;
                    291:     b->translated = b->untranslatable = b->allocfailed = 0;
                    292:     return b;
                    293: }
                    294: 
                    295: static struct hash_entry *get_free_hash(void)
                    296: {
                    297:     struct hash_entry *h;
                    298: 
                    299:     for (;;) {
                    300:        h = freelist_hash;
                    301:        if (h != NULL) {
                    302:            freelist_hash = h->next_same_block;
                    303:            break;
1.1.1.2   root      304:        }
1.1       root      305:        h = lru_first_hash.lru_next;
1.1.1.2   root      306:        if (num_unused_hash >= MAX_UNUSED_HASH && h->block == NULL
1.1.1.3 ! root      307:            && !h->locked)
1.1.1.2   root      308:        {
1.1       root      309:            remove_hash_from_lists(h);
1.1.1.2   root      310:            num_unused_hash--;
1.1       root      311:            break;
                    312:        }
1.1.1.2   root      313:        h = (struct hash_entry *)malloc(sizeof(struct hash_entry));
                    314:        h->next_same_block = NULL;
                    315:        h->addr = -1;
                    316:        break;
1.1       root      317:     }
1.1.1.2   root      318:     num_unused_hash++;
1.1       root      319:     h->block = NULL;
                    320:     h->ncalls = 0;
                    321:     h->locked = h->cacheflush = 0;
                    322:     h->execute = NULL;
                    323:     return h;
                    324: }
                    325: 
1.1.1.3 ! root      326: static struct hash_entry *new_hash(uaecptr addr)
1.1       root      327: {
                    328:     struct hash_entry *h = get_free_hash();
1.1.1.3 ! root      329: 
1.1       root      330:     h->addr = addr;
                    331: 
                    332:     /* Chain the new node */
                    333:     h->prev = cpu_hash + ((addr >> 1) & HASH_MASK);
                    334:     h->next = h->prev->next;
                    335:     h->next->prev = h->prev->next = h;
                    336: 
                    337:     h->lru_next = &lru_first_hash;
                    338:     h->lru_prev = lru_first_hash.lru_prev;
                    339:     h->lru_prev->lru_next = h;
                    340:     lru_first_hash.lru_prev = h;
1.1.1.3 ! root      341: 
1.1       root      342:     h->next_same_block = NULL;
                    343: 
                    344:     return h;
                    345: }
1.1.1.3 ! root      346: static struct hash_entry *find_hash(uaecptr addr)
1.1       root      347: {
                    348:     struct hash_entry *h;
                    349:     struct hash_entry *h1 = cpu_hash + ((addr >> 1) & HASH_MASK);
                    350: 
                    351:     if (h1->next->addr == addr)
                    352:        return h1->next;
1.1.1.3 ! root      353: 
1.1       root      354:     for (h = h1->next; h != h1; h = h->next) {
                    355:        if (h->addr == addr) {
1.1.1.2   root      356:            /* Put it at the head of the list so that the above shortcut
                    357:             * works the next time we come here */
1.1       root      358:            h->next->prev = h->prev; h->prev->next = h->next;
                    359:            h->prev = h1;
                    360:            h->next = h1->next;
                    361:            h->next->prev = h->prev->next = h;
                    362:            return h;
                    363:        }
                    364:     }
                    365:     return NULL;
                    366: }
                    367: 
1.1.1.3 ! root      368: static struct hash_entry *get_hash_for_func(uaecptr addr, int mark_locked)
1.1       root      369: {
                    370:     struct hash_entry *h = find_hash(addr);
                    371:     if (h == NULL)
                    372:        h = new_hash (addr);
1.1.1.2   root      373: #if 0 /* Too expensive */
1.1       root      374:     else
                    375:        lru_touch(h);
1.1.1.2   root      376: #endif
                    377:     if (mark_locked)
                    378:        h->locked = 1;
1.1       root      379:     return h;
                    380: }
                    381: 
1.1.1.3 ! root      382: static struct hash_entry *get_hash(uaecptr addr)
1.1       root      383: {
1.1.1.2   root      384:     struct hash_entry *h = get_hash_for_func(addr, 0);
1.1       root      385: 
                    386:     if (h->block == NULL) {
                    387:        if (++h->ncalls == SCAN_MARK) {
                    388:            m68k_scan_func(h);
                    389:        }
                    390:     } else
                    391:        if (!h->block->untranslatable && h->block->nrefs++ == COMPILE_MARK) {
                    392:            lru_touch_block(h->block);
                    393:            if (m68k_compile_block(h->block)) {
                    394:                h->block->untranslatable = 1;
1.1.1.2   root      395:            } else {
1.1       root      396:                h->block->translated = 1;
1.1.1.2   root      397:            }
1.1       root      398:        }
                    399:     return h;
                    400: }
                    401: 
1.1.1.3 ! root      402: void special_flush_hash(uaecptr addr)
1.1       root      403: {
1.1.1.2   root      404:     struct hash_entry *h = get_hash_for_func(addr, 0);
1.1.1.3 ! root      405: 
1.1       root      406:     h->cacheflush = 1;
                    407: }
                    408: 
1.1.1.3 ! root      409: static __inline__ void m68k_setpc_hash(uaecptr newpc)
1.1       root      410: {
                    411:     struct hash_entry *h = get_hash(newpc);
1.1.1.3 ! root      412: 
1.1       root      413:     if (h->cacheflush)
                    414:        flush_icache();
                    415: 
                    416:     if (h->execute != NULL) {
                    417:        if ((h->addr & 0xF80000) == 0xF80000 || check_block(h->block)) {
                    418:            compiled_hits++;
                    419:            if (i_want_to_die && (call_only_me == 0 || call_only_me == newpc)) {
                    420:                exec_me = h->execute;
                    421:                nr_bbs_to_run = nr_bbs_start;
                    422:                regs.spcflags |= SPCFLAG_EXEC;
                    423:            }
1.1.1.3 ! root      424:        } else
1.1       root      425:            flush_icache();
                    426:     }
                    427:     regs.pc = newpc;
                    428:     regs.pc_p = regs.pc_oldp = get_real_address(newpc);
                    429: }
                    430: 
1.1.1.3 ! root      431: static __inline__ void m68k_setpc_nohash(uaecptr newpc)
1.1       root      432: {
                    433: #if 0
                    434:     /* This is probably not too good for efficiency... FIXME */
                    435:     struct hash_entry *h = find_hash(newpc);
                    436: 
                    437:     if (h != NULL && h->cacheflush)
                    438:        flush_icache();
                    439: #endif
                    440:     regs.pc = newpc;
                    441:     regs.pc_p = regs.pc_oldp = get_real_address(newpc);
                    442: }
                    443: 
1.1.1.3 ! root      444: void m68k_setpc(uaecptr newpc)
1.1       root      445: {
1.1.1.3 ! root      446:     m68k_setpc_hash(newpc);
1.1       root      447: }
                    448: 
1.1.1.3 ! root      449: void m68k_setpc_fast(uaecptr newpc)
1.1       root      450: {
1.1.1.3 ! root      451:     m68k_setpc_nohash(newpc);
1.1       root      452: }
                    453: 
1.1.1.3 ! root      454: void m68k_setpc_rte(uaecptr newpc)
1.1       root      455: {
                    456:     m68k_setpc_nohash(newpc);
                    457: }
                    458: 
1.1.1.3 ! root      459: void m68k_setpc_bcc(uaecptr newpc)
1.1       root      460: {
                    461:     m68k_setpc_hash(newpc);
                    462: }
                    463: 
                    464: static void hash_init(void)
                    465: {
                    466:     int i;
                    467:     struct hash_entry **hepp;
1.1.1.3 ! root      468: 
1.1.1.2   root      469:     freelist_block = NULL;
                    470:     freelist_hash = NULL;
                    471: 
1.1       root      472:     for(i = 0; i < NUM_HASH; i++) {
                    473:        cpu_hash[i].next = cpu_hash[i].prev = cpu_hash + i;
                    474:        cpu_hash[i].lru_next = cpu_hash[i].lru_prev = NULL;
                    475:        cpu_hash[i].block = NULL;
                    476:        cpu_hash[i].locked = 0; cpu_hash[i].cacheflush = 0;
                    477:        cpu_hash[i].addr = -1;
                    478:     }
1.1.1.2   root      479: 
1.1       root      480:     lru_first_hash.lru_next = lru_first_hash.lru_prev = &lru_first_hash;
                    481:     lru_first_block.lru_next = lru_first_block.lru_prev = &lru_first_block;
1.1.1.2   root      482: 
                    483:     num_unused_hash = 0;
1.1       root      484: }
                    485: 
                    486: static void code_init(void)
                    487: {
                    488:     first_code_page = NULL;
                    489:     zerofd = open("/dev/zero", O_RDWR);
                    490:     zeroff = 0;
                    491: }
                    492: 
1.1.1.2   root      493: #define CC68K_C 16
                    494: #define CC68K_V 8
                    495: #define CC68K_Z 4
                    496: #define CC68K_N 2
                    497: #define CC68K_X 1
1.1       root      498: 
1.1.1.2   root      499: static __inline__ int cc_flagmask_68k(const int cc)
1.1       root      500: {
                    501:     switch(cc){
                    502:      case 0: return 0;                       /* T */
                    503:      case 1: return 0;                       /* F */
1.1.1.2   root      504:      case 2: return CC68K_C|CC68K_Z;         /* HI */
                    505:      case 3: return CC68K_C|CC68K_Z;         /* LS */
                    506:      case 4: return CC68K_C;                 /* CC */
                    507:      case 5: return CC68K_C;                 /* CS */
                    508:      case 6: return CC68K_Z;                 /* NE */
                    509:      case 7: return CC68K_Z;                 /* EQ */
                    510:      case 8: return CC68K_V;                 /* VC */
                    511:      case 9: return CC68K_V;                 /* VS */
                    512:      case 10:return CC68K_N;                 /* PL */
                    513:      case 11:return CC68K_N;                 /* MI */
                    514:      case 12:return CC68K_N|CC68K_V;         /* GE */
                    515:      case 13:return CC68K_N|CC68K_V;         /* LT */
                    516:      case 14:return CC68K_N|CC68K_V|CC68K_Z; /* GT */
                    517:      case 15:return CC68K_N|CC68K_V|CC68K_Z; /* LE */
1.1       root      518:     }
                    519:     abort();
1.1.1.3 ! root      520:     return 0;
1.1       root      521: }
                    522: 
1.1.1.3 ! root      523: static __inline__ void translate_step_over_ea(uae_u8 **pcpp, amodes m,
1.1       root      524:                                              wordsizes size)
                    525: {
                    526:     switch (m) {
                    527:      case Areg:
                    528:      case Dreg:
                    529:      case Aind:
                    530:      case Aipi:
                    531:      case Apdi:
                    532:      case immi:
                    533:        break;
                    534: 
                    535:      case imm:
                    536:        if (size == sz_long)
                    537:            goto is_long;
                    538:        /* fall through */
                    539:      case Ad16:
                    540:      case PC16:
                    541:      case imm0:
                    542:      case imm1:
                    543:      case absw:
                    544:        (*pcpp)+=2;
                    545:        break;
                    546:      case Ad8r:
                    547:      case PC8r:
                    548:        {
1.1.1.3 ! root      549:            uae_u16 extra = *(*pcpp)++;
1.1       root      550:            extra <<= 8;
                    551:            extra |= *(*pcpp)++;
                    552:            /* @@@ handle 68020 stuff here */
                    553:        }
                    554:        break;
                    555:      case absl:
                    556:      case imm2:
                    557:        is_long:
                    558:        (*pcpp) += 4;
                    559:        break;
                    560:     }
                    561: }
                    562: 
1.1.1.3 ! root      563: static struct instr *translate_getnextinsn(uae_u8 **pcpp)
1.1       root      564: {
1.1.1.3 ! root      565:     uae_u16 opcode;
1.1       root      566:     struct instr *dp;
1.1.1.3 ! root      567: 
1.1       root      568:     opcode = *(*pcpp)++ << 8;
                    569:     opcode |= *(*pcpp)++;
1.1.1.3 ! root      570: 
1.1       root      571:     if (cpufunctbl[opcode] == op_illg) {
                    572:        opcode = 0x4AFC;
                    573:     }
                    574:     dp = table68k + opcode;
                    575:     if (dp->suse) {
                    576:        translate_step_over_ea(pcpp, dp->smode, dp->size);
                    577:     }
                    578:     if (dp->duse) {
                    579:        translate_step_over_ea(pcpp, dp->dmode, dp->size);
                    580:     }
                    581:     return dp;
                    582: }
                    583: 
                    584: #define CB_STACKSIZE 200
                    585: #define BB_STACKSIZE 200
                    586: 
1.1.1.3 ! root      587: static uae_u32 condbranch_stack[CB_STACKSIZE];
1.1       root      588: static int condbranch_src_stack[CB_STACKSIZE];
                    589: 
                    590: struct bb_info {
                    591:     struct hash_entry *h;
1.1.1.3 ! root      592:     uaecptr stopaddr;
1.1       root      593:     int can_compile_last;
                    594:     struct bb_info *bb_next1, *bb_next2;
                    595:     int flags_live_at_end;
                    596:     int flags_live_at_start;
                    597:     int first_iip, last_iip;
                    598: } bb_stack[BB_STACKSIZE];
                    599: 
                    600: static int top_bb;
                    601: 
1.1.1.3 ! root      602: static uaecptr bcc_target_stack[BB_STACKSIZE];
1.1       root      603: 
1.1.1.3 ! root      604: static int new_bcc_target(uaecptr addr)
1.1       root      605: {
                    606:     int i;
1.1.1.3 ! root      607: 
1.1       root      608:     for (i = 0; i < top_bb; i++)
                    609:        if (bcc_target_stack[i] == addr)
                    610:            return 1;
                    611: 
                    612:     if (top_bb == BB_STACKSIZE)
                    613:        return 0;
                    614:     bcc_target_stack[top_bb++] = addr;
                    615:     return 1;
                    616: }
                    617: 
                    618: static int bcc_compfn(const void *a, const void *b)
                    619: {
1.1.1.3 ! root      620:     uaecptr *a1 = (uaecptr *)a, *b1 = (uaecptr *)b;
        !           621: 
1.1       root      622:     if (*a1 == *b1)
                    623:        printf("BUG!!\n");
1.1.1.3 ! root      624: 
1.1       root      625:     if (*a1 < *b1)
                    626:        return 1;
                    627:     return -1;
                    628: }
                    629: 
                    630: static int bb_compfn(const void *a, const void *b)
                    631: {
                    632:     struct bb_info *a1 = (struct bb_info *)a, *b1 = (struct bb_info *)b;
1.1.1.3 ! root      633: 
1.1       root      634:     if (a1->h->addr == b1->h->addr)
                    635:        printf("BUG!!\n");
1.1.1.3 ! root      636: 
1.1       root      637:     if (a1->h->addr < b1->h->addr)
                    638:        return -1;
                    639:     return 1;
                    640: }
                    641: 
                    642: static int find_basic_blocks(struct hash_entry *h)
                    643: {
                    644:     int current_bb = 0;
                    645: 
                    646:     top_bb = 0;
                    647:     bcc_target_stack[0] = h->addr;
                    648:     new_bcc_target(h->addr);
                    649: 
                    650:     while (top_bb > current_bb) {
1.1.1.3 ! root      651:        uaecptr addr = bcc_target_stack[current_bb];
1.1       root      652:        int ninsns = 0;
1.1.1.3 ! root      653:        uae_u8 *realpc = get_real_address(addr);
        !           654:        uae_u8 *rpc_start = realpc;
        !           655: 
1.1       root      656:        for(;;) {
1.1.1.3 ! root      657:            uaecptr thisinsn_addr = (realpc - rpc_start) + addr;
        !           658:            uae_u8 *rpc_save = realpc;
1.1       root      659:            struct instr *dp = translate_getnextinsn(&realpc);
1.1.1.3 ! root      660:            uaecptr nextinsn_addr = (realpc - rpc_start) + addr;
1.1       root      661: 
1.1.1.3 ! root      662:            if (dp->mnemo == i_RTS || dp->mnemo == i_RTE
1.1       root      663:                || dp->mnemo == i_RTR || dp->mnemo == i_RTD
1.1.1.3 ! root      664:                || dp->mnemo == i_JMP || dp->mnemo == i_ILLG)
1.1       root      665:            {
                    666:                break;
                    667:            }
1.1.1.3 ! root      668: 
1.1       root      669:            if (dp->mnemo == i_BSR || dp->mnemo == i_JSR) {
                    670:                if (!new_bcc_target(nextinsn_addr))
                    671:                    return 0;
                    672:                break;
                    673:            }
                    674: 
                    675:            if (dp->mnemo == i_DBcc) {
1.1.1.3 ! root      676:                uaecptr newaddr = thisinsn_addr + 2 + (uae_s16)((*(rpc_save+2) << 8) | *(rpc_save+3));
1.1       root      677:                if (!new_bcc_target(nextinsn_addr))
                    678:                    return 0;
                    679:                if (!new_bcc_target(newaddr))
                    680:                    return 0;
                    681:                break;
                    682:            }
1.1.1.3 ! root      683: 
1.1       root      684:            if (dp->mnemo == i_Bcc) {
1.1.1.3 ! root      685:                uaecptr newaddr;
1.1       root      686:                if (dp->smode == imm1)
1.1.1.3 ! root      687:                    newaddr = thisinsn_addr + 2 + (uae_s16)((*(rpc_save+2) << 8) | *(rpc_save+3));
1.1       root      688:                else
1.1.1.3 ! root      689:                    newaddr = thisinsn_addr + 2 + (uae_s8)dp->sreg;
        !           690: 
1.1       root      691:                if (dp->cc != 0)
                    692:                    if (!new_bcc_target(nextinsn_addr))
                    693:                        return 0;
                    694:                if (!new_bcc_target(newaddr))
                    695:                    return 0;
                    696:                break;
                    697:            }
                    698:        }
                    699:        current_bb++;
                    700:     }
                    701: 
1.1.1.3 ! root      702:     qsort(bcc_target_stack, top_bb, sizeof (uaecptr), bcc_compfn);
1.1       root      703: 
                    704:     return 1;
                    705: }
                    706: 
                    707: static int m68k_scan_func(struct hash_entry *h)
                    708: {
                    709:     int i;
                    710:     struct hash_block *found_block;
                    711:     struct hash_entry **hepp;
1.1.1.3 ! root      712: 
1.1       root      713:     if (!find_basic_blocks(h))
                    714:        return 0;
                    715: 
                    716:     found_block = NULL;
1.1.1.3 ! root      717: 
1.1.1.2   root      718:     /* First, lock the hash entries we already have to prevent grief */
                    719:     for (i = 0; i < top_bb; i++) {
                    720:        struct hash_entry *h = find_hash(bcc_target_stack[i]);
                    721:        if (h != NULL)
                    722:            h->locked = 1;
                    723:     }
1.1.1.3 ! root      724: 
1.1.1.2   root      725:     /* Allocate new ones */
1.1       root      726:     for (i = 0; i < top_bb; i++) {
1.1.1.2   root      727:        struct hash_entry *h = get_hash_for_func(bcc_target_stack[i], 1);
1.1       root      728:        bb_stack[i].h = h;
1.1.1.2   root      729: #if 0 /* This doesn't work in all cases */
                    730:        if (h->block != NULL && h->block != found_block) {
1.1       root      731:            if (found_block == NULL) {
                    732:                if (h->block->cpage != NULL)
                    733:                    fprintf(stderr, "Found compiled code\n");
                    734:                else
                    735:                    found_block = h->block;
                    736:            } else {
                    737:                fprintf(stderr, "Multiple blocks found.\n");
                    738:                if (h->block->cpage == NULL)
                    739:                    forget_block(h->block);
                    740:                else if (found_block->cpage == NULL) {
                    741:                    forget_block(found_block);
                    742:                    found_block = h->block;
                    743:                } else
                    744:                    fprintf(stderr, "Bad case.\n");
                    745:            }
1.1.1.2   root      746:        }
                    747: #endif
1.1       root      748:     }
                    749:     if (found_block == NULL) {
                    750:        found_block = new_block();
                    751: 
                    752:        found_block->lru_next = &lru_first_block;
                    753:        found_block->lru_prev = lru_first_block.lru_prev;
                    754:        found_block->lru_prev->lru_next = found_block;
                    755:        lru_first_block.lru_prev = found_block;
                    756:     }
                    757: 
                    758:     hepp = &found_block->he_first;
                    759:     found_block->he_first = NULL;
                    760:     for (i = 0; i < top_bb; i++) {
                    761:        struct bb_info *bb = bb_stack + i;
                    762: 
                    763:        if (bb->h->block == NULL) {
1.1.1.2   root      764:            num_unused_hash--;
                    765:            lru_touch(bb->h);
1.1       root      766:            bb->h->block = found_block;
                    767:            *hepp = bb->h;
                    768:            hepp = &bb->h->next_same_block;
                    769:        }
                    770:     }
                    771:     *hepp = found_block->he_first;
                    772:     return 1;
                    773: }
                    774: 
                    775: struct ea_reg_info {
                    776:     enum { eat_reg, eat_imem, eat_amem, eat_const } ea_type;
                    777:     int regs_set:16;
                    778:     int regs_used:16;
                    779:     int nr_scratch;
1.1.1.3 ! root      780:     uae_u32 temp1, temp2;
1.1       root      781: };
                    782: 
                    783: #define MAX_TRANSLATE 2048
                    784: struct insn_info_struct {
1.1.1.3 ! root      785:     uaecptr address;
1.1       root      786:     struct instr *dp;
                    787:     int flags_set;
                    788:     int flags_used;
                    789:     int flags_live_at_end;
                    790:     int jump_target;
                    791:     int jumps_to;
                    792:     char *compiled_jumpaddr; /* Address to use for jumps to this insn */
                    793:     char *compiled_fillin;   /* Address where to put offset if this is a Bcc */
                    794:     int regs_set:16;
                    795:     int regs_used:16;
1.1.1.2   root      796:     int stop_translation:2;
1.1       root      797:     int sync_cache:1;
                    798:     int sync_flags:1;
                    799:     int ccuser_follows:1;
                    800: } insn_info [MAX_TRANSLATE];
                    801: 
1.1.1.2   root      802: #define EA_NONE 0
1.1       root      803: #define EA_LOAD 1
                    804: #define EA_STORE 2
1.1.1.2   root      805: #define EA_MODIFY 4
                    806: 
1.1       root      807: #if 0
                    808: static void analyze_ea_for_insn(amodes mode, int reg, wordsizes size,
                    809:                                struct ea_reg_info *eai,
1.1.1.3 ! root      810:                                uae_u8 **pcpp, uaecptr pca,
1.1       root      811:                                int ea_purpose)
                    812: {
1.1.1.3 ! root      813:     uae_u8 *p = *pcpp;
1.1       root      814: 
                    815:     switch(mode) {
                    816:      case Dreg:
                    817:        eai->ea_type = eat_reg;
                    818:        if (size != sz_long && (ea_purpose & EA_STORE))
                    819:            ea_purpose |= EA_LOAD;
                    820:        if (ea_purpose & EA_LOAD)
                    821:            eai->regs_used |= 1 << reg;
                    822:        if (ea_purpose & EA_STORE)
                    823:            eai->regs_set |= 1 << reg;
                    824:        break;
1.1.1.3 ! root      825: 
1.1       root      826:      case Areg:
                    827:        eai->ea_type = eat_reg;
                    828:        if (size != sz_long && (ea_purpose & EA_STORE))
                    829:            printf("Areg != long\n");
                    830:        if (ea_purpose & EA_LOAD)
                    831:            eai->regs_used |= 1 << (8+reg);
                    832:        if (ea_purpose & EA_STORE)
                    833:            eai->regs_set |= 1 << (8+reg);
                    834:        break;
1.1.1.3 ! root      835: 
1.1       root      836:      case Ad16:
                    837:      case Aind:
                    838:      case Apdi:
                    839:      case Aipi:
                    840:        eai->ea_type = eat_imem;
                    841:        eai->regs_used |= 1 << (8+reg);
                    842:        break;
                    843: 
                    844:      case Ad8r:
                    845:        eai->ea_type = eat_imem;
                    846:        pii->regs_used |= 1 << (8+reg);
                    847: 
1.1.1.3 ! root      848:        eai->temp = (uae_u16)((*p << 8) | *(p+1));
1.1       root      849:        r = (eai->temp & 0x7000) >> 12;
1.1.1.3 ! root      850:        (*pcpp) += 2; p += 2;
        !           851: 
1.1       root      852:        if (eai->temp1 & 0x8000)
                    853:            pii->regs_used |= 1 << (8+r);
                    854:        else
                    855:            pii->regs_used |= 1 << r;
                    856:        break;
                    857: 
                    858:      case PC8r:
                    859:        eai->ea_type = eat_imem;
1.1.1.3 ! root      860:        eai->temp1 = (uae_u16)do_get_mem_word((uae_u16 *)p);
        !           861:        eai->temp2 = pca + (uae_s8)eai->temp1;
1.1       root      862:        (*pcpp) += 2; p += 2;
                    863:        r = (eai->temp1 & 0x7000) >> 12;
                    864: 
                    865:        if (eai->temp1 & 0x8000)
                    866:            pii->regs_used |= 1 << (8+r);
                    867:        else
                    868:            pii->regs_used |= 1 << r;
                    869:        break;
1.1.1.3 ! root      870: 
        !           871:      case PC16:
1.1       root      872:        eai->ea_type = eat_amem;
1.1.1.3 ! root      873:        eai->temp1 = pca + (uae_s16)do_get_mem_word((uae_u16 *)p);
1.1       root      874:        (*pcpp) += 2;
                    875:        break;
1.1.1.3 ! root      876: 
1.1       root      877:      case absw:
                    878:        eai->ea_type = eat_amem;
1.1.1.3 ! root      879:        eai->temp1 = (uae_s16)do_get_mem_word((uae_u16 *)p);
1.1       root      880:        (*pcpp) += 2;
                    881:        break;
                    882: 
                    883:      case absl:
                    884:        eai->ea_type = eat_amem;
1.1.1.3 ! root      885:        eai->temp1 = (uae_s32)do_get_mem_long((uae_u32 *)p);
1.1       root      886:        (*pcpp) += 4;
                    887:        break;
                    888: 
                    889:      case imm:
                    890:        if (size == sz_long)
                    891:            goto imm2_const;
                    892:        if (size == sz_word)
                    893:            goto imm1_const;
1.1.1.3 ! root      894: 
1.1       root      895:        /* fall through */
                    896:      case imm0:
                    897:        eai->ea_type = eat_imm;
1.1.1.3 ! root      898:        eai->temp1 = (uae_s8)*(p+1);
1.1       root      899:        (*pcpp) += 2;
                    900:        break;
                    901: 
                    902:      case imm1:
                    903:        imm1_const:
                    904:        eai->ea_type = eat_imm;
1.1.1.3 ! root      905:        eai->temp1 = (uae_s16)do_get_mem_word((uae_u16 *)p);
1.1       root      906:        (*pcpp) += 2;
                    907:        break;
                    908: 
                    909:      case imm2:
                    910:        imm2_const:
                    911:        eai->ea_type = eat_imm;
1.1.1.3 ! root      912:        eai->temp1 = (uae_s32)do_get_mem_long((uae_u32 *)p);
1.1       root      913:        (*pcpp) += 4;
                    914:        break;
                    915: 
                    916:      case immi:
                    917:        eai->ea_type = eat_imm;
1.1.1.3 ! root      918:        eai->temp1 = (uae_s8)reg;
1.1       root      919:        break;
                    920: 
                    921:      default:
                    922:        break;
                    923:     }
                    924: }
                    925: #endif
                    926: static struct bb_info *find_bb(struct hash_entry *h)
                    927: {
                    928:     int i;
1.1.1.3 ! root      929: 
1.1.1.2   root      930:     if (h == NULL)
                    931:        printf("Bug...\n");
1.1.1.3 ! root      932: 
1.1       root      933:     for (i = 0; i < top_bb; i++)
                    934:        if (bb_stack[i].h == h)
                    935:            return bb_stack + i;
                    936:     if (!quiet_compile)
                    937:        fprintf(stderr, "BB not found!\n");
                    938:     return NULL;
                    939: }
                    940: 
                    941: static int m68k_scan_block(struct hash_block *hb, int *movem_count)
                    942: {
                    943:     struct hash_entry *h = hb->he_first;
                    944:     int i, iip, last_iip;
1.1.1.2   root      945:     int changed, round;
                    946: 
1.1       root      947:     top_bb = 0;
1.1.1.3 ! root      948: 
1.1       root      949:     do {
                    950:        struct bb_info *bb = bb_stack + top_bb;
                    951:        bb->h = h;
                    952:        bb->bb_next1 = NULL;
                    953:        bb->bb_next2 = NULL;
                    954:        h = h->next_same_block;
                    955:        top_bb++;
                    956:     } while (h != hb->he_first);
1.1.1.3 ! root      957: 
1.1       root      958:     qsort(bb_stack, top_bb, sizeof (struct bb_info), bb_compfn);
                    959: 
                    960:     *movem_count = 0;
                    961: 
                    962:     iip = 0;
                    963:     for (i = 0; i < top_bb; i++) {
                    964:        struct bb_info *bb = bb_stack + i;
1.1.1.3 ! root      965:        uae_u8 *realpc = get_real_address(bb->h->addr);
        !           966:        uae_u8 *rpc_start = realpc;
        !           967:        uaecptr stop_addr = 0;
1.1       root      968:        int live_at_start = 31, may_clear_las = 31;
                    969:        struct insn_info_struct *prev_ii = NULL;
                    970: 
                    971:        if (i < top_bb - 1)
                    972:            stop_addr = (bb+1)->h->addr;
                    973:        bb->first_iip = iip;
                    974: 
                    975:        for (;;) {
                    976:            struct insn_info_struct *thisii = insn_info + iip;
1.1.1.3 ! root      977:            uaecptr thisinsn_addr = (realpc - rpc_start) + bb->h->addr;
        !           978:            uae_u8 *rpc_save = realpc;
1.1       root      979:            struct instr *dp = translate_getnextinsn(&realpc);
1.1.1.3 ! root      980:            uaecptr nextinsn_addr = (realpc - rpc_start) + bb->h->addr;
        !           981: 
1.1       root      982:            int fset = dp->flagdead == -1 ? 31 : dp->flagdead;
                    983:            int fuse = dp->flaglive == -1 ? 31 : dp->flaglive;
1.1.1.3 ! root      984: 
1.1       root      985:            if (thisinsn_addr == stop_addr) {
                    986:                bb->bb_next1 = find_bb (find_hash (thisinsn_addr));
                    987:                break;
                    988:            }
1.1.1.3 ! root      989: 
1.1       root      990:            if (dp->mnemo == i_Scc || dp->mnemo == i_Bcc || dp->mnemo == i_DBcc) {
1.1.1.2   root      991:                fset = 0, fuse = cc_flagmask_68k(dp->cc);
1.1       root      992:                if (prev_ii && dp->mnemo != i_Scc) /* Don't use Scc here: ea can cause an exit */
                    993:                    prev_ii->ccuser_follows = 1;
                    994:            }
                    995: 
                    996:            may_clear_las &= ~fuse;
                    997:            live_at_start &= ~(fset & may_clear_las);
1.1.1.3 ! root      998: 
1.1       root      999:            thisii->dp = dp;
                   1000:            thisii->address = thisinsn_addr;
                   1001:            thisii->stop_translation = 0;
                   1002:            thisii->ccuser_follows = 0;
                   1003: /*         thisii->have_reginfo = 0;*/
                   1004:            thisii->jump_target = 0;
                   1005:            thisii->sync_cache = thisii->sync_flags = 0;
                   1006:            thisii->flags_set = fset;
                   1007:            thisii->flags_used = fuse;
                   1008:            thisii->regs_set = 0;
                   1009:            thisii->regs_used = 0;
                   1010:            iip++;
                   1011:            if (iip == MAX_TRANSLATE)
                   1012:                return 0;
                   1013: 
1.1.1.3 ! root     1014:            if (dp->mnemo == i_RTS || dp->mnemo == i_RTE
1.1       root     1015:                || dp->mnemo == i_RTR || dp->mnemo == i_RTD
1.1.1.2   root     1016:                || dp->mnemo == i_JMP || dp->mnemo == i_ILLG)
1.1       root     1017:            {
                   1018:                thisii->flags_used = 31;
                   1019:                thisii->regs_used = 65535;
1.1.1.2   root     1020:                thisii->stop_translation = dp->mnemo == i_RTS || dp->mnemo == i_JMP ? 2 : 1;
1.1       root     1021:                break;
                   1022:            }
1.1.1.2   root     1023:            if (dp->mnemo == i_BSR || dp->mnemo == i_JSR)
                   1024:            {
                   1025:                thisii->flags_used = 31;
                   1026:                thisii->regs_used = 65535;
                   1027:                bb->can_compile_last = 1;
                   1028:                bb->bb_next1 = find_bb (get_hash_for_func (nextinsn_addr, 1));
                   1029:                if (bb->bb_next1 == NULL)
                   1030:                    thisii->stop_translation = 1;
                   1031:                break;
                   1032:            }
                   1033: 
1.1       root     1034:            if (dp->mnemo == i_DBcc) {
1.1.1.3 ! root     1035:                uaecptr newaddr = thisinsn_addr + 2 + (uae_s16)((*(rpc_save+2) << 8) | *(rpc_save+3));
1.1       root     1036:                bb->can_compile_last = 1;
1.1.1.2   root     1037:                bb->bb_next1 = find_bb (get_hash_for_func (newaddr, 1));
1.1       root     1038:                if (bb->bb_next1 == NULL)
                   1039:                    thisii->stop_translation = 1;
1.1.1.2   root     1040:                bb->bb_next2 = find_bb (get_hash_for_func (nextinsn_addr, 1));
1.1       root     1041:                if (bb->bb_next2 == NULL)
                   1042:                    thisii->stop_translation = 1;
                   1043:                thisii->regs_used = 65535;
                   1044:                break;
                   1045:            }
1.1.1.3 ! root     1046: 
1.1       root     1047:            if (dp->mnemo == i_Bcc) {
1.1.1.3 ! root     1048:                uaecptr newaddr;
1.1       root     1049:                if (dp->smode == imm1)
1.1.1.3 ! root     1050:                    newaddr = thisinsn_addr + 2 + (uae_s16)((*(rpc_save+2) << 8) | *(rpc_save+3));
1.1       root     1051:                else
1.1.1.3 ! root     1052:                    newaddr = thisinsn_addr + 2 + (uae_s8)dp->sreg;
1.1       root     1053:                bb->can_compile_last = 1;
1.1.1.2   root     1054:                bb->bb_next1 = find_bb(get_hash_for_func(newaddr, 1));
1.1       root     1055:                if (bb->bb_next1 == NULL)
                   1056:                    thisii->stop_translation = 1;
                   1057:                if (dp->cc != 0) {
1.1.1.2   root     1058:                    bb->bb_next2 = find_bb(get_hash_for_func(nextinsn_addr, 1));
1.1       root     1059:                    if (bb->bb_next2 == NULL)
                   1060:                        thisii->stop_translation = 1;
                   1061:                }
                   1062:                thisii->regs_used = 65535;
                   1063:                break;
                   1064:            }
                   1065: 
                   1066:            if (dp->mnemo == i_MVMLE || dp->mnemo == i_MVMEL) {
1.1.1.3 ! root     1067:                uae_u16 regmask = (*(rpc_save + 2) << 8) | (*(rpc_save + 3));
1.1       root     1068:                *movem_count += count_bits(regmask);
                   1069:                if (dp->dmode == Apdi)
                   1070:                    regmask = bitswap(regmask);
                   1071:                if (dp->mnemo == i_MVMLE)
                   1072:                    thisii->regs_used = regmask;
                   1073:                else
                   1074:                    thisii->regs_set = regmask;
                   1075:            }
                   1076: 
                   1077:            prev_ii = thisii;
                   1078:        }
                   1079:        bb->last_iip = iip - 1;
                   1080:        bb->flags_live_at_start = live_at_start;
                   1081:     }
                   1082:     last_iip = iip;
1.1.1.2   root     1083:     round = 0;
                   1084:     do {
                   1085:        changed = 0;
                   1086:        for (i = 0; i < top_bb; i++) {
                   1087:            struct bb_info *bb = bb_stack + i;
                   1088:            int mnemo;
                   1089:            int current_live;
                   1090:            struct instr *dp;
1.1.1.3 ! root     1091: 
1.1.1.2   root     1092:            iip = bb->last_iip;
                   1093:            mnemo = insn_info[iip].dp->mnemo;
1.1       root     1094: 
1.1.1.2   root     1095:            /* Fix up branches */
                   1096:            if (round == 0 && (mnemo == i_DBcc || mnemo == i_Bcc)) {
                   1097:                if (bb->bb_next1 != NULL) {
                   1098:                    insn_info[bb->last_iip].jumps_to = bb->bb_next1->first_iip;
                   1099:                    insn_info[bb->bb_next1->first_iip].jump_target = 1;
                   1100:                }
                   1101:            }
1.1.1.3 ! root     1102: 
1.1.1.2   root     1103:            /* And take care of flag life information */
                   1104:            dp = insn_info[iip].dp;
                   1105:            if (insn_info[iip].stop_translation)
                   1106:                current_live = 31;
                   1107:            else if (dp->mnemo == i_DBcc || dp->mnemo == i_Bcc) {
                   1108:                current_live = 0;
                   1109:                if (bb->bb_next1 != NULL)
                   1110:                    current_live |= bb->bb_next1->flags_live_at_start;
                   1111:                if (bb->bb_next2 != NULL)
                   1112:                    current_live |= bb->bb_next2->flags_live_at_start;
                   1113:            } else {
                   1114:                if (bb->bb_next1 == NULL && bb->bb_next2 == NULL)
                   1115:                    fprintf(stderr, "Can't happen\n");
                   1116:                current_live = 0;
                   1117:                if (bb->bb_next1 != NULL)
                   1118:                    current_live |= bb->bb_next1->flags_live_at_start;
                   1119:                if (bb->bb_next2 != NULL)
                   1120:                    current_live |= bb->bb_next2->flags_live_at_start;
                   1121:            }
                   1122: 
                   1123:            do {
                   1124:                insn_info[iip].flags_live_at_end = current_live;
                   1125:                current_live &= ~insn_info[iip].flags_set;
                   1126:                current_live |= insn_info[iip].flags_used;
                   1127:            } while (iip-- != bb->first_iip);
                   1128: 
                   1129:            if (bb->flags_live_at_start != current_live && !quiet_compile)
                   1130:                fprintf(stderr, "Fascinating %d!\n", round), changed = 1;
                   1131:            bb->flags_live_at_start = current_live;
1.1       root     1132:        }
1.1.1.2   root     1133:        round++;
                   1134:     } while (changed);
                   1135:     return last_iip;
                   1136: }
1.1       root     1137: 
1.1.1.2   root     1138: #define MAX_JSRS 4096 /* must be a power of two */
                   1139: 
1.1.1.3 ! root     1140: static uaecptr jsr_rets[MAX_JSRS];
1.1.1.2   root     1141: static struct hash_entry *jsr_hash[MAX_JSRS];
                   1142: static int jsr_num;
                   1143: static struct hash_entry dummy_hash; /* This is for safety purposes only */
                   1144: 
                   1145: 
                   1146: static void jsr_stack_init(void)
                   1147: {
                   1148:     jsr_num = 0;
                   1149:     dummy_hash.execute = NULL;
                   1150: }
                   1151: 
                   1152: void compiler_flush_jsr_stack(void)
                   1153: {
                   1154:     jsr_num = 0;
                   1155: }
                   1156: 
                   1157: void m68k_do_rts(void)
                   1158: {
                   1159:     m68k_setpc(get_long(m68k_areg(regs, 7)));
                   1160:     m68k_areg(regs, 7) += 4;
                   1161:     if (jsr_num > 0)
                   1162:        jsr_num--;
                   1163: }
                   1164: 
1.1.1.3 ! root     1165: __inline__ void m68k_do_jsr(uaecptr oldpc, uaecptr dest)
1.1.1.2   root     1166: {
                   1167:     struct hash_entry *h = find_hash(oldpc);
                   1168: 
                   1169:     if (jsr_num == MAX_JSRS)
                   1170:        compiler_flush_jsr_stack();
                   1171:     if (h == NULL) {
                   1172:        jsr_hash[jsr_num] = &dummy_hash;
                   1173:        jsr_rets[jsr_num++] = 0xC0DEDBAD;
                   1174:     } else {
                   1175:        jsr_hash[jsr_num] = h;
                   1176:        jsr_rets[jsr_num++] = oldpc;
1.1       root     1177:     }
1.1.1.2   root     1178:     m68k_areg(regs, 7) -= 4;
                   1179:     put_long(m68k_areg(regs, 7), oldpc);
                   1180:     m68k_setpc(dest);
1.1       root     1181: }
                   1182: 
1.1.1.3 ! root     1183: void m68k_do_bsr(uaecptr oldpc, uae_s32 offset)
1.1.1.2   root     1184: {
1.1.1.3 ! root     1185:     m68k_do_jsr(oldpc, m68k_getpc() + offset);
1.1.1.2   root     1186: }
                   1187: 
                   1188: /* Here starts the actual compiling part */
                   1189: 
1.1       root     1190: static char *compile_current_addr;
                   1191: static char *compile_last_addr;
                   1192: 
1.1.1.3 ! root     1193: static __inline__ void assemble(uae_u8 a)
1.1       root     1194: {
                   1195:     if (compile_current_addr < compile_last_addr) {
                   1196:        *compile_current_addr++ = a;
                   1197:     } else {
                   1198:        compile_failure = 1;
                   1199:     }
                   1200: }
                   1201: 
1.1.1.3 ! root     1202: static __inline__ void assemble_ulong(uae_u32 a)
1.1       root     1203: {
                   1204:     assemble(a);
                   1205:     assemble(a >> 8);
                   1206:     assemble(a >> 16);
                   1207:     assemble(a >> 24);
                   1208: }
                   1209: 
1.1.1.3 ! root     1210: static __inline__ void assemble_ulong_68k(uae_u32 a)
1.1.1.2   root     1211: {
                   1212:     assemble(a >> 24);
                   1213:     assemble(a >> 16);
                   1214:     assemble(a >> 8);
                   1215:     assemble(a);
                   1216: }
                   1217: 
1.1.1.3 ! root     1218: static __inline__ void assemble_uword(uae_u16 a)
1.1       root     1219: {
                   1220:     assemble(a);
                   1221:     assemble(a >> 8);
                   1222: }
                   1223: 
                   1224: static __inline__ void assemble_long(void *a)
                   1225: {
1.1.1.3 ! root     1226:     assemble_ulong((uae_u32)a);
1.1       root     1227: }
                   1228: 
                   1229: static __inline__ void compile_org(char *addr)
                   1230: {
                   1231:     compile_current_addr = addr;
                   1232: }
                   1233: 
                   1234: static __inline__ char *compile_here(void)
                   1235: {
                   1236:     return compile_current_addr;
                   1237: }
                   1238: 
                   1239: #define r_EAX 0
                   1240: #define r_ECX 1
                   1241: #define r_EDX 2
                   1242: #define r_EBX 3
                   1243: #define r_ESP 4
                   1244: #define r_EBP 5
                   1245: #define r_ESI 6
                   1246: #define r_EDI 7
                   1247: 
                   1248: #define r_AH 0x84
                   1249: #define r_CH 0x85
                   1250: #define r_DH 0x86
                   1251: #define r_BH 0x87
                   1252: 
                   1253: #define ALL_X86_REGS 255
                   1254: #define ADDRESS_X86_REGS ((1 << r_EBP) | (1 << r_ESI) | (1 << r_EDI))
                   1255: #define DATA_X86_REGS ((1 << r_EAX) | (1 << r_EDX) | (1 << r_EBX) | (1 << r_ECX))
                   1256: 
                   1257: #define BO_NORMAL 0
                   1258: #define BO_SWAPPED_LONG 1
                   1259: #define BO_SWAPPED_WORD 2
                   1260: 
                   1261: struct register_mapping {
                   1262:     int dreg_map[8], areg_map[8]; /* 68000 register cache */
                   1263:     int x86_const_offset[8];
                   1264:     int x86_dirty[8];
                   1265:     int x86_cache_reg[8]; /* Regs used for the 68000 register cache */
                   1266:     int x86_cr_type[8]; /* Caching data or address register? */
                   1267:     int x86_locked[8]; /* Regs used for some purpose */
1.1.1.2   root     1268:     int x86_users[8];
1.1       root     1269:     int x86_byteorder[8];
                   1270:     int x86_verified[8];
                   1271: };
                   1272: 
                   1273: /*
                   1274:  * First, code to compile some primitive x86 instructions
                   1275:  */
                   1276: 
1.1.1.3 ! root     1277: static void compile_lea_reg_with_offset(int dstreg, int srcreg, uae_u32 srcoffs)
1.1       root     1278: {
                   1279:     assemble(0x8D);
                   1280:     if (srcreg == -2) {
                   1281:        assemble(0x05 + 8*dstreg);
                   1282:        assemble_ulong(srcoffs);
1.1.1.3 ! root     1283:     } else if ((uae_s32)srcoffs >= -128 && (uae_s32)srcoffs <= 127) {
1.1       root     1284:        assemble(0x40 + 8*dstreg + srcreg);
                   1285:        assemble(srcoffs);
                   1286:     } else {
                   1287:        assemble(0x80 + 8*dstreg + srcreg);
                   1288:        assemble_ulong(srcoffs);
                   1289:     }
                   1290: }
                   1291: 
                   1292: static void compile_move_reg_reg(int dstreg, int srcreg, wordsizes size)
                   1293: {
                   1294:     if (size == sz_byte
                   1295:        && (((1 << dstreg) & DATA_X86_REGS) == 0
                   1296:            || ((1 << srcreg) & DATA_X86_REGS) == 0))
                   1297:     {
                   1298:        fprintf(stderr, "Moving wrong register types!\n");
                   1299:     }
                   1300:     if (size == sz_word)
                   1301:        assemble(0x66);
                   1302:     if (size == sz_byte)
                   1303:        assemble(0x88);
                   1304:     else
                   1305:        assemble(0x89);
                   1306:     assemble(0xC0 + dstreg + 8*srcreg);
                   1307: }
                   1308: 
                   1309: static void compile_move_between_reg_mem_regoffs(int dstreg, int srcreg,
1.1.1.3 ! root     1310:                                                 uae_u32 srcoffs, wordsizes size,
1.1       root     1311:                                                 int code)
                   1312: {
                   1313:     if (size == sz_byte && (dstreg & 0x80) != 0)
                   1314:        dstreg &= ~0x80;
                   1315:     else if ((size == sz_byte
                   1316:              && ((1 << dstreg) & DATA_X86_REGS) == 0)
                   1317:             || (size != sz_byte && (dstreg & 0x80) != 0))
                   1318:     {
                   1319:        fprintf(stderr, "Moving wrong register types!\n");
                   1320:     }
                   1321:     if (size == sz_word)
                   1322:        assemble(0x66);
                   1323:     if (size == sz_byte)
                   1324:        assemble(code);
                   1325:     else
                   1326:        assemble(code + 1);
1.1.1.3 ! root     1327: 
1.1       root     1328:     if (srcreg == -2) {
                   1329:        assemble(0x05 + 8*dstreg);
                   1330:        assemble_ulong(srcoffs);
1.1.1.3 ! root     1331:     } else if ((uae_s32)srcoffs >= -128 && (uae_s32)srcoffs <= 127) {
1.1       root     1332:        assemble(0x40 + 8*dstreg + srcreg);
                   1333:        assemble(srcoffs);
                   1334:     } else {
                   1335:        assemble(0x80 + 8*dstreg + srcreg);
                   1336:        assemble_ulong(srcoffs);
                   1337:     }
                   1338: }
                   1339: 
1.1.1.3 ! root     1340: static void compile_move_reg_from_mem_regoffs(int dstreg, int srcreg,
        !          1341:                                              uae_u32 srcoffs, wordsizes size)
1.1       root     1342: {
                   1343:     compile_move_between_reg_mem_regoffs(dstreg, srcreg, srcoffs, size, 0x8A);
                   1344: }
                   1345: 
1.1.1.3 ! root     1346: static void compile_move_reg_to_mem_regoffs(int dstreg, uae_u32 dstoffs,
1.1       root     1347:                                            int srcreg, wordsizes size)
                   1348: {
                   1349:     compile_move_between_reg_mem_regoffs(srcreg, dstreg, dstoffs, size, 0x88);
                   1350: }
                   1351: 
                   1352: static void compile_byteswap(int x86r, wordsizes size, int save_flags)
                   1353: {
                   1354:     switch(size) {
                   1355:      case sz_word:
                   1356:        if (save_flags)
                   1357:            assemble(0x9C);
                   1358:        assemble(0x66); /* rolw $8,x86r */
                   1359:        assemble(0xC1);
                   1360:        assemble(0xC0 + x86r);
                   1361:        assemble(8);
                   1362:        if (save_flags)
                   1363:            assemble(0x9D);
                   1364:        break;
                   1365:      case sz_long:
                   1366:        assemble(0x0F); /* bswapl x86r */
                   1367:        assemble(0xC8+x86r);
                   1368:        break;
                   1369:      default:
                   1370:        break;
                   1371:     }
                   1372: }
                   1373: 
                   1374: static void compile_force_byteorder(struct register_mapping *map, int x86r,
                   1375:                                    int desired_bo, int save_flags)
                   1376: {
1.1.1.2   root     1377:     if (x86r < 0 || map->x86_byteorder[x86r] == desired_bo)
1.1       root     1378:        return;
1.1.1.3 ! root     1379: 
1.1       root     1380:     if (map->x86_byteorder[x86r] == BO_SWAPPED_LONG)
                   1381:        compile_byteswap(x86r, sz_long, save_flags);
                   1382:     else if (map->x86_byteorder[x86r] == BO_SWAPPED_WORD)
                   1383:        compile_byteswap(x86r, sz_word, save_flags);
1.1.1.3 ! root     1384: 
1.1       root     1385:     if (desired_bo == BO_SWAPPED_LONG)
                   1386:        compile_byteswap(x86r, sz_long, save_flags);
                   1387:     else if (desired_bo == BO_SWAPPED_WORD)
                   1388:        compile_byteswap(x86r, sz_word, save_flags);
                   1389:     map->x86_byteorder[x86r] = desired_bo;
                   1390: }
                   1391: 
                   1392: /* Add a constant offset to a x86 register. If it's in the cache, make sure
                   1393:  * we update the const_offset value. The flags are unaffected by this */
                   1394: 
1.1.1.3 ! root     1395: static void compile_offset_reg(struct register_mapping *map, int x86r,
        !          1396:                               uae_u32 offset)
1.1       root     1397: {
                   1398:     int cached_68k;
1.1.1.3 ! root     1399: 
1.1       root     1400:     if (offset == 0 || x86r == -1 || x86r == -2)
                   1401:        return;
                   1402: 
                   1403:     compile_force_byteorder(map, x86r, BO_NORMAL, 1);
                   1404:     cached_68k = map->x86_cache_reg[x86r];
                   1405:     if (cached_68k != -1) {
                   1406:        map->x86_const_offset[x86r] -= offset;
                   1407:        map->x86_dirty[x86r] = 1;
                   1408:     }
                   1409:     compile_lea_reg_with_offset(x86r, x86r, offset);
                   1410: }
                   1411: 
                   1412: static int get_unused_x86_register(struct register_mapping *map)
                   1413: {
                   1414:     int x86r;
                   1415:     for (x86r = 0; x86r < 24; x86r++) {
                   1416:        if (map->x86_cache_reg[x86r] != -1)
                   1417:            continue;
1.1.1.2   root     1418:        if (map->x86_users[x86r] > 0)
1.1       root     1419:            continue;
1.1.1.3 ! root     1420: 
1.1       root     1421:        map->x86_verified[x86r] = 0;
                   1422:        map->x86_byteorder[x86r] = BO_NORMAL;
                   1423:        return x86r;
                   1424:     }
                   1425:     return -1;
                   1426: }
                   1427: 
                   1428: /*
                   1429:  * sync_reg() may not touch the flags
                   1430:  * If may_clobber is 1 and the reg had an offset, the reg will be offsetted
                   1431:  * by this function
                   1432:  */
1.1.1.3 ! root     1433: static void sync_reg(struct register_mapping *map, int x86r, void *m68kr,
        !          1434:                     uae_u32 offset, int dirty, int may_clobber)
1.1       root     1435: {
1.1.1.2   root     1436:     if (dirty || offset != 0)
                   1437:        compile_force_byteorder(map, x86r, BO_NORMAL, 1);
1.1       root     1438:     if (offset != 0) {
                   1439:        if (may_clobber) {
                   1440:            compile_lea_reg_with_offset(x86r, x86r, offset);
                   1441:            dirty = 1;
                   1442:        } else {
                   1443:            int tmpr = get_unused_x86_register(map);
1.1.1.3 ! root     1444:            if (tmpr != -1) {
1.1       root     1445:                compile_lea_reg_with_offset(tmpr, x86r, offset);
                   1446:                x86r = tmpr;
                   1447:                dirty = 1;
                   1448:            } else {
                   1449:                compile_lea_reg_with_offset(x86r, x86r, offset);
                   1450:                assemble(0x89);          /* movl x86r,m68kr */
1.1.1.3 ! root     1451:                assemble(0x05 + (x86r << 3));
1.1       root     1452:                assemble_long(m68kr);
                   1453:                compile_lea_reg_with_offset(x86r, x86r, -offset);
                   1454:                return;
                   1455:            }
                   1456:        }
                   1457:     }
                   1458:     if (dirty) {
                   1459:        assemble(0x89);          /* movl x86r,m68kr */
1.1.1.3 ! root     1460:        assemble(0x05 + (x86r << 3));
1.1       root     1461:        assemble_long(m68kr);
                   1462:     }
                   1463: }
                   1464: 
                   1465: static void sync_reg_cache(struct register_mapping *map, int flush)
                   1466: {
                   1467:     int i;
                   1468: 
                   1469:     for (i = 0; i < 8; i++) {
                   1470:        int cr68k = map->x86_cache_reg[i];
                   1471:        if (cr68k != -1) {
                   1472:            if (map->x86_cr_type[i] == 1) {
1.1.1.2   root     1473:                sync_reg(map, i, regs.regs + cr68k, map->x86_const_offset[i], map->x86_dirty[i], 1);
1.1       root     1474:                if (flush)
                   1475:                    map->dreg_map[cr68k] = -1;
                   1476:            } else {
1.1.1.2   root     1477:                sync_reg(map, i, regs.regs + 8 + cr68k, map->x86_const_offset[i], map->x86_dirty[i], 1);
1.1       root     1478:                if (flush)
                   1479:                    map->areg_map[cr68k] = -1;
                   1480:            }
                   1481:            if (flush)
                   1482:                map->x86_cache_reg[i] = -1;
                   1483:            map->x86_const_offset[i] = 0;
                   1484:        }
                   1485:     }
                   1486:     memset(map->x86_dirty, 0, sizeof map->x86_dirty);
                   1487: }
                   1488: 
1.1.1.3 ! root     1489: static void remove_x86r_from_cache(struct register_mapping *map, int x86r,
1.1       root     1490:                                   int may_clobber)
                   1491: {
                   1492:     int j;
                   1493:     int reg_68k;
1.1.1.3 ! root     1494: 
1.1       root     1495:     if (x86r == -1)
                   1496:        return;
                   1497: 
                   1498:     reg_68k = map->x86_cache_reg[x86r];
1.1.1.3 ! root     1499: 
1.1.1.2   root     1500:     if (reg_68k == -1)
                   1501:        return;
1.1.1.3 ! root     1502: 
1.1.1.2   root     1503:     if (map->x86_cr_type[x86r] == 1) {
                   1504:        map->dreg_map[reg_68k] = -1;
                   1505:        sync_reg(map, x86r, regs.regs + reg_68k, map->x86_const_offset[x86r],
                   1506:                 map->x86_dirty[x86r], may_clobber);
                   1507:     } else {
                   1508:        map->areg_map[reg_68k] = -1;
                   1509:        sync_reg(map, x86r, regs.regs + 8 + reg_68k,  map->x86_const_offset[x86r],
                   1510:                 map->x86_dirty[x86r], may_clobber);
1.1       root     1511:     }
                   1512:     map->x86_dirty[x86r] = 0;
                   1513:     map->x86_cache_reg[x86r] = -1;
                   1514:     map->x86_const_offset[x86r] = 0;
                   1515:     map->x86_verified[x86r] = 0;
                   1516:     map->x86_byteorder[x86r] = BO_NORMAL;
                   1517: }
                   1518: 
                   1519: static int get_free_x86_register(struct register_mapping *map,
                   1520:                                 int preferred_mask)
                   1521: {
                   1522:     int cnt;
                   1523:     for (cnt = 0; cnt < 24; cnt++) {
                   1524:        int x86r = cnt & 7;
                   1525:        /* In the first two passes, try to get one of the preferred regs */
                   1526:        if (cnt < 16 && ((1 << x86r) & preferred_mask) == 0)
                   1527:            continue;
                   1528:        /* In the first pass, don't discard any registers from the cache */
                   1529:        if (cnt < 8 && map->x86_cache_reg[x86r] != -1)
                   1530:            continue;
                   1531:        /* Never use locked registers */
1.1.1.2   root     1532:        if (map->x86_users[x86r] > 0)
1.1       root     1533:            continue;
                   1534: 
                   1535:        remove_x86r_from_cache(map, x86r, 1);
1.1.1.2   root     1536:        map->x86_dirty[x86r] = 0;
                   1537:        map->x86_cache_reg[x86r] = -1;
                   1538:        map->x86_const_offset[x86r] = 0;
                   1539:        map->x86_verified[x86r] = 0;
                   1540:        map->x86_byteorder[x86r] = BO_NORMAL;
1.1       root     1541:        return x86r;
                   1542:     }
                   1543:     printf("Out of registers!\n");
                   1544:     return -1;
                   1545: }
                   1546: 
                   1547: static int get_typed_x86_register(struct register_mapping *map,
                   1548:                                  int preferred_mask)
                   1549: {
                   1550:     int cnt;
                   1551:     for (cnt = 0; cnt < 16; cnt++) {
                   1552:        int x86r = cnt & 7;
                   1553:        /* Get one of the preferred regs */
                   1554:        if (((1 << x86r) & preferred_mask) == 0)
                   1555:            continue;
                   1556:        /* In the first pass, don't discard any registers from the cache */
                   1557:        if (cnt < 8 && map->x86_cache_reg[x86r] != -1)
                   1558:            continue;
                   1559:        /* Never use locked registers */
1.1.1.2   root     1560:        if (map->x86_users[x86r] > 0)
1.1       root     1561:            continue;
                   1562: 
                   1563:        remove_x86r_from_cache(map, x86r, 1);
1.1.1.2   root     1564:        map->x86_dirty[x86r] = 0;
                   1565:        map->x86_cache_reg[x86r] = -1;
                   1566:        map->x86_const_offset[x86r] = 0;
                   1567:        map->x86_verified[x86r] = 0;
                   1568:        map->x86_byteorder[x86r] = BO_NORMAL;
1.1       root     1569:        return x86r;
                   1570:     }
                   1571:     printf("Out of type registers!\n");
                   1572:     return -1;
                   1573: }
                   1574: 
                   1575: static void compile_unlock_reg(struct register_mapping *map, int reg)
                   1576: {
                   1577:     if (reg >= 0) {
1.1.1.2   root     1578:        if (--map->x86_users[reg] == 0)
                   1579:            map->x86_locked[reg] = 0;
                   1580: 
                   1581:     }
                   1582: }
                   1583: 
                   1584: static void lock_reg(struct register_mapping *map, int x86r, int lock_type)
                   1585: {
                   1586: #if 1
                   1587:     switch (map->x86_locked[x86r]) {
                   1588:      case 0:
                   1589:        if (map->x86_users[x86r] != 0)
                   1590:            printf("Users for an unlocked reg!\n");
                   1591:        break;
                   1592:      case 1:
                   1593:        if (lock_type == 2)
                   1594:            printf("Locking shared reg for exclusive use!\n");
                   1595:        break;
                   1596:      case 2:
                   1597:        printf("Locking exclusive reg!\n");
                   1598:        break;
                   1599:      default:
                   1600:        printf("Unknown lock?\n");
                   1601:        break;
1.1       root     1602:     }
1.1.1.2   root     1603: #endif
                   1604:     map->x86_locked[x86r] = lock_type;
                   1605:     map->x86_users[x86r]++;
1.1       root     1606: }
                   1607: 
                   1608: static int get_and_lock_68k_reg(struct register_mapping *map, int reg, int is_dreg,
1.1.1.2   root     1609:                                int preferred, int no_offset, int lock_type)
1.1       root     1610: {
                   1611:     int x86r;
                   1612:     int *regmap;
1.1.1.3 ! root     1613:     uae_u32 *reghome;
        !          1614:     uae_u32 const_off = 0;
        !          1615: 
1.1.1.2   root     1616:     if (reg < 0 || reg > 7) {
                   1617:        printf("Mad compiler disease\n");
                   1618:        return 0;
                   1619:     }
                   1620: 
1.1       root     1621:     if (is_dreg)
1.1.1.2   root     1622:        regmap = map->dreg_map, reghome = regs.regs;
1.1       root     1623:     else
1.1.1.2   root     1624:        regmap = map->areg_map, reghome = regs.regs + 8;
1.1.1.3 ! root     1625: 
1.1       root     1626:     if (preferred == 0)
                   1627:        preferred = ALL_X86_REGS;
1.1.1.3 ! root     1628: 
1.1       root     1629:     x86r = regmap[reg];
                   1630:     if (x86r == -1) {
                   1631:        x86r = get_free_x86_register(map, preferred);
                   1632:        assemble(0x8B); assemble(0x05 + (x86r << 3)); /* movl regs.d[reg],x86r */
                   1633:        assemble_long(reghome + reg);
                   1634:        map->x86_cache_reg[x86r] = reg;
                   1635:        map->x86_cr_type[x86r] = is_dreg;
                   1636:        map->x86_const_offset[x86r] = 0;
                   1637:        map->x86_dirty[x86r] = 0;
                   1638:        map->x86_verified[x86r] = 0;
                   1639:        map->x86_byteorder[x86r] = BO_NORMAL;
                   1640:        regmap[reg] = x86r;
1.1.1.2   root     1641:     } else {
                   1642:        const_off = map->x86_const_offset[x86r];
1.1.1.3 ! root     1643: 
1.1.1.2   root     1644:        if (map->x86_locked[x86r] == 2
                   1645:            || (map->x86_locked[x86r] == 1 && (lock_type == 2 || (const_off != 0 && no_offset))))
                   1646:        {
                   1647:            int newr;
                   1648:            int old_dirty = 0;
                   1649:            int old_verified;
                   1650:            int old_bo;
1.1.1.3 ! root     1651: 
1.1.1.2   root     1652:            newr = get_free_x86_register(map, preferred);
                   1653:            if (const_off == 0) {
                   1654:                compile_move_reg_reg(newr, x86r, sz_long);
                   1655:            } else {
                   1656:                compile_force_byteorder(map, x86r, BO_NORMAL, 1);
                   1657:                compile_lea_reg_with_offset(newr, x86r, const_off);
                   1658:                old_dirty = 1;
                   1659:                const_off = 0;
                   1660:            }
                   1661:            /* Remove old reg from cache... */
                   1662:            map->x86_cache_reg[x86r] = -1;
                   1663:            map->x86_cr_type[x86r] = is_dreg;
                   1664:            map->x86_const_offset[x86r] = 0;
                   1665:            old_dirty |= map->x86_dirty[x86r];
                   1666:            old_verified = map->x86_verified[x86r];
                   1667:            old_bo = map->x86_byteorder[x86r];
                   1668:            map->x86_verified[x86r] = 0;
                   1669:            map->x86_dirty[x86r] = 0;
                   1670:            x86r = newr;
                   1671:            /* ... and make the new one the cache register */
                   1672:            map->x86_cache_reg[x86r] = reg;
                   1673:            map->x86_cr_type[x86r] = is_dreg;
                   1674:            map->x86_const_offset[x86r] = 0;
                   1675:            map->x86_dirty[x86r] = old_dirty;
                   1676:            map->x86_verified[x86r] = old_verified;
                   1677:            map->x86_byteorder[x86r] = old_bo;
                   1678:            regmap[reg] = x86r;
1.1       root     1679:        }
                   1680:     }
1.1.1.2   root     1681:     if (no_offset && const_off != 0) {
                   1682:        if (map->x86_locked[x86r] != 0)
                   1683:            printf("modifying locked reg\n");
1.1       root     1684:        compile_force_byteorder(map, x86r, BO_NORMAL, 1);
                   1685:        compile_lea_reg_with_offset(x86r, x86r, map->x86_const_offset[x86r]);
                   1686:        map->x86_const_offset[x86r] = 0;
                   1687:        map->x86_dirty[x86r] = 1;
                   1688:     }
1.1.1.2   root     1689:     lock_reg(map, x86r, lock_type);
1.1       root     1690:     return x86r;
                   1691: }
                   1692: 
                   1693: /*
1.1.1.2   root     1694:  * Move a constant to a register. Don't do anything if we already have a
1.1       root     1695:  * register, even if it is offset by a constant
                   1696:  */
                   1697: 
                   1698: static int compile_force_const_reg(struct register_mapping *map, int x86r,
1.1.1.3 ! root     1699:                                   uae_u32 *offs, int desired)
1.1       root     1700: {
                   1701:     int newr = x86r;
                   1702: 
                   1703:     if (newr == -2) {
                   1704:        if (desired == 0)
                   1705:            newr = get_free_x86_register(map, ALL_X86_REGS);
                   1706:        else
                   1707:            newr = get_typed_x86_register(map, desired);
                   1708: 
                   1709:        assemble(0xB8 + newr);
                   1710:        assemble_ulong(*offs);
                   1711:        *offs = 0;
                   1712:     }
1.1.1.2   root     1713:     map->x86_users[newr]++;
1.1       root     1714:     return newr;
                   1715: }
                   1716: 
1.1.1.2   root     1717: static void compile_extend_long(struct register_mapping *map, int x86r,
                   1718:                                wordsizes size)
1.1       root     1719: {
1.1.1.2   root     1720:     if (x86r < 0) {
                   1721:        printf("Bad reg in extend_long\n");
                   1722:        return;
                   1723:     }
1.1.1.3 ! root     1724: 
1.1       root     1725:     compile_force_byteorder(map, x86r, BO_NORMAL, 1);
1.1.1.2   root     1726: 
1.1       root     1727:     if (size != sz_long) {
                   1728:        if (x86r == r_EAX && size == sz_word) {
                   1729:            assemble(0x98); /* cwtl */
                   1730:        } else {
                   1731:            assemble(0x0F);
                   1732:            if (size == sz_byte) {
                   1733:                assemble(0xBE);
                   1734:            } else {
                   1735:                assemble(0xBF);
                   1736:            }
                   1737:            assemble(0xC0 + x86r*9);
                   1738:        }
                   1739:     }
                   1740: }
                   1741: 
1.1.1.2   root     1742: struct ea_info {
                   1743:     int reg;
                   1744:     amodes mode;
                   1745:     wordsizes size;
                   1746:     int address_reg;    /* The x86 reg holding the address, or -1 if ea doesn't refer to memory
                   1747:                         * -2 if it refers to memory, but only with a constant address */
1.1.1.3 ! root     1748:     uae_u32 addr_const_off; /* Constant offset to the address */
        !          1749:     int data_reg;         /* The x86 reg that holds the data. -1 if data is not present yet.
1.1.1.2   root     1750:                           * -2 if data is constant */
1.1.1.3 ! root     1751:     uae_u32 data_const_off;
1.1.1.2   root     1752:     int flags;            /* Extra info. Contains the dp field of d8r modes */
                   1753:     int purpose;
                   1754: };
1.1       root     1755: 
1.1.1.2   root     1756: static void init_eainfo(struct ea_info *eai)
1.1       root     1757: {
1.1.1.2   root     1758:     eai->address_reg = -1;
                   1759:     eai->addr_const_off = 0;
                   1760:     eai->data_reg = -1;
                   1761:     eai->data_const_off = 0;
1.1       root     1762: }
                   1763: 
1.1.1.2   root     1764: struct insn_reg_needs {
                   1765:     int checkpoint_no;
                   1766:     int dreg_needed[8], areg_needed[8];
                   1767:     int dreg_mask[8], areg_mask[8];
                   1768: };
1.1       root     1769: 
                   1770: /*
                   1771:  * This structure holds information about predec/postinc addressing modes.
                   1772:  */
                   1773: 
                   1774: struct pid_undo {
                   1775:     int used;
                   1776:     int x86r[2];
                   1777:     int m68kr[2];
                   1778:     int dirty[2];
1.1.1.2   root     1779:     int offs[2];
1.1       root     1780: };
                   1781: 
1.1.1.2   root     1782: static void add_undo(struct pid_undo *pud, int x86r, int m68kr, int offs,
1.1       root     1783:                     int dirty)
                   1784: {
                   1785:     int i;
                   1786:     for (i = 0; i < pud->used; i++)
                   1787:        if (pud->m68kr[i] == m68kr)
                   1788:            return;
                   1789:     pud->m68kr[i] = m68kr;
                   1790:     pud->x86r[i] = x86r;
                   1791:     pud->offs[i] = offs;
                   1792:     pud->dirty[i] = dirty;
                   1793:     pud->used++;
                   1794: }
                   1795: 
1.1.1.2   root     1796: /*
                   1797:  * Lock previous contents of address registers used in predec/postinc modes
                   1798:  * for generate_possible_exit().
                   1799:  */
1.1       root     1800: 
1.1.1.2   root     1801: static void compile_prepare_undo(struct register_mapping *map, amodes mode,
                   1802:                              int reg, struct pid_undo *pud)
1.1       root     1803: {
1.1.1.2   root     1804:     int x86r;
                   1805: 
                   1806:     switch(mode){
                   1807:      default:
                   1808:        break;
1.1.1.3 ! root     1809: 
1.1.1.2   root     1810:      case Apdi:
                   1811:        x86r = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
                   1812:        /* This saves recording the byteorder in the pud structure, and we'll
                   1813:         * need it in normal byteorder anyway */
                   1814:        compile_force_byteorder(map, x86r, BO_NORMAL, 0);
1.1.1.3 ! root     1815:        /*
1.1.1.2   root     1816:         * Add this reg with its current offset to the undo buffer.
                   1817:         * Since we have locked it, we are certain that it will not be
                   1818:         * modified.
                   1819:         */
                   1820:        add_undo(pud, x86r, reg, map->x86_const_offset[x86r], map->x86_dirty[x86r]);
                   1821:        break;
1.1.1.3 ! root     1822: 
1.1.1.2   root     1823:      case Aipi:
                   1824:        x86r = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
                   1825:        compile_force_byteorder(map, x86r, BO_NORMAL, 0);
                   1826:        add_undo(pud, x86r, reg, map->x86_const_offset[x86r], map->x86_dirty[x86r]);
                   1827:        break;
                   1828:     }
1.1       root     1829: }
                   1830: 
                   1831: /*
                   1832:  * Load all the registers absolutely needed to calculate and verify thea
                   1833:  * address. Load other registers if convenient.
                   1834:  * This contains a fair amount of magic to get the register cache working right.
                   1835:  */
                   1836: 
                   1837: static void compile_prepareea(struct register_mapping *map, amodes mode,
1.1.1.3 ! root     1838:                              int reg, wordsizes size, uae_u8 **pcpp, uaecptr pca,
1.1.1.2   root     1839:                              struct ea_info *eainf, int eaino, int ea_purpose,
                   1840:                              int pidmult)
1.1       root     1841: {
1.1.1.2   root     1842:     struct ea_info *eai = eainf + eaino;
1.1       root     1843:     int pdival = size == sz_byte && reg != 7 ? 1 : size == sz_long ? 4 : 2;
1.1.1.3 ! root     1844:     uae_u8 *p = *pcpp;
        !          1845:     uae_u16 dp;
1.1       root     1846:     int r;
                   1847:     int x86r, tmpr;
                   1848: 
                   1849:     pdival *= pidmult;
1.1.1.3 ! root     1850: 
1.1       root     1851:     init_eainfo(eai);
                   1852:     eai->mode = mode;
                   1853:     eai->size = size;
                   1854:     eai->reg = reg;
1.1.1.3 ! root     1855: 
1.1       root     1856:     switch(mode){
                   1857:      case Dreg:
                   1858:      case Areg:
                   1859:        break;
1.1.1.3 ! root     1860: 
1.1       root     1861:      case Ad16:
1.1.1.3 ! root     1862:        eai->addr_const_off = (uae_s16)do_get_mem_word((uae_u16 *)p);
1.1       root     1863:        (*pcpp) += 2; p += 2;
1.1.1.2   root     1864:        x86r = eai->address_reg = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
1.1       root     1865:        compile_force_byteorder(map, x86r, BO_NORMAL, 0);
                   1866:        eai->addr_const_off += map->x86_const_offset[x86r];
                   1867:        break;
                   1868: 
                   1869:      case Aind:
1.1.1.2   root     1870:        x86r = eai->address_reg = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
1.1       root     1871:        compile_force_byteorder(map, x86r, BO_NORMAL, 0);
                   1872:        eai->addr_const_off = map->x86_const_offset[x86r];
                   1873:        break;
1.1.1.3 ! root     1874: 
1.1       root     1875:      case Apdi:
1.1.1.2   root     1876:        x86r = eai->address_reg = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
1.1       root     1877:        compile_force_byteorder(map, x86r, BO_NORMAL, 0);
                   1878:        map->x86_const_offset[x86r] -= pdival;
                   1879:        eai->addr_const_off = map->x86_const_offset[x86r];
                   1880:        break;
1.1.1.3 ! root     1881: 
1.1       root     1882:      case Aipi:
1.1.1.2   root     1883:        x86r = eai->address_reg = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
1.1       root     1884:        compile_force_byteorder(map, x86r, BO_NORMAL, 0);
                   1885:        eai->addr_const_off = map->x86_const_offset[x86r];
                   1886:        map->x86_const_offset[x86r] += pdival;
                   1887:        break;
                   1888: 
                   1889:      case Ad8r:
1.1.1.3 ! root     1890:        dp = (uae_s16)do_get_mem_word((uae_u16 *)p);
1.1       root     1891:        r = (dp & 0x7000) >> 12;
1.1.1.3 ! root     1892:        (*pcpp) += 2; p += 2;
        !          1893: 
1.1.1.2   root     1894:        tmpr = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
1.1       root     1895:        compile_force_byteorder(map, tmpr, BO_NORMAL, 0);
1.1.1.3 ! root     1896:        eai->addr_const_off = map->x86_const_offset[tmpr] + (uae_s8)dp;
1.1.1.2   root     1897: 
                   1898:        if (dp & 0x800) {
                   1899:            x86r = get_and_lock_68k_reg(map, r, dp & 0x8000 ? 0 : 1, ADDRESS_X86_REGS, 0, 2);
                   1900:            remove_x86r_from_cache(map, x86r, 0);
                   1901:            compile_force_byteorder(map, x86r, BO_NORMAL, 0);
                   1902:            eai->addr_const_off += map->x86_const_offset[x86r];
                   1903:        } else {
                   1904:            x86r = get_and_lock_68k_reg(map, r, dp & 0x8000 ? 0 : 1, ADDRESS_X86_REGS, 1, 2);
                   1905:            remove_x86r_from_cache(map, x86r, 0);
                   1906:            compile_force_byteorder(map, x86r, BO_NORMAL, 0);
                   1907:        }
                   1908:        eai->address_reg = x86r;
1.1.1.3 ! root     1909: 
1.1       root     1910:        r = (dp & 0x7000) >> 12;
                   1911: 
                   1912:        if (dp & 0x800) {
1.1.1.2   root     1913:            if (eai->addr_const_off == 0) {
                   1914:                assemble(0x03); assemble(0xC0 + tmpr + x86r*8); /* addl basereg,addrreg */
1.1.1.3 ! root     1915:            } else if ((uae_s32)eai->addr_const_off >= -128 && (uae_s32)eai->addr_const_off <= 127) {
        !          1916:                assemble(0x8D);
1.1.1.2   root     1917:                assemble(0x44 + x86r*8); /* leal disp8(dispreg,basereg),dispreg */
1.1       root     1918:                assemble(x86r*8 + tmpr);
                   1919:                assemble(eai->addr_const_off);
                   1920:            } else {
                   1921:                assemble(0x8D);
1.1.1.2   root     1922:                assemble(0x84 + x86r*8); /* leal disp32(dispreg,basereg),dispreg */
1.1       root     1923:                assemble(x86r*8 + tmpr);
                   1924:                assemble_ulong(eai->addr_const_off);
                   1925:            }
                   1926:            eai->addr_const_off = 0;
                   1927:        } else {
                   1928:            assemble(0x0F); assemble(0xBF);
1.1.1.2   root     1929:            assemble(0xC0 + x86r*9); /* movswl dispreg,addrreg */
                   1930:            assemble(0x03); assemble(0xC0 + tmpr + x86r*8); /* addl basereg,addrreg */
1.1       root     1931:        }
                   1932:        compile_unlock_reg(map, tmpr);
                   1933:        break;
                   1934: 
                   1935:      case PC8r:
1.1.1.3 ! root     1936:        dp = (uae_s16)do_get_mem_word((uae_u16 *)p);
1.1       root     1937:        (*pcpp) += 2; p += 2;
                   1938:        r = (dp & 0x7000) >> 12;
1.1.1.3 ! root     1939:        eai->addr_const_off = pca + (uae_s8)dp;
1.1       root     1940:        if (dp & 0x800) {
1.1.1.2   root     1941:            x86r = get_and_lock_68k_reg(map, r, dp & 0x8000 ? 0 : 1, ADDRESS_X86_REGS, 0, 1);
                   1942:            remove_x86r_from_cache(map, x86r, 0);
                   1943:            compile_force_byteorder(map, x86r, BO_NORMAL, 0);
                   1944:            eai->addr_const_off += map->x86_const_offset[x86r];
1.1       root     1945:        } else {
1.1.1.2   root     1946:            x86r = get_and_lock_68k_reg(map, r, dp & 0x8000 ? 0 : 1, ADDRESS_X86_REGS, 1, 2);
                   1947:            remove_x86r_from_cache(map, x86r, 0);
                   1948:            compile_force_byteorder(map, x86r, BO_NORMAL, 0);
1.1       root     1949: 
                   1950:            assemble(0x0F); assemble(0xBF);
1.1.1.2   root     1951:            assemble(0xC0 + x86r*9); /* movswl dispreg,addrreg */
1.1       root     1952:        }
1.1.1.2   root     1953:        eai->address_reg = x86r;
1.1       root     1954:        break;
1.1.1.3 ! root     1955: 
1.1       root     1956:      case PC16:
1.1.1.3 ! root     1957:        eai->addr_const_off = pca + (uae_s16)do_get_mem_word((uae_u16 *)p);
1.1       root     1958:        eai->address_reg = -2;
                   1959:        (*pcpp) += 2; p += 2;
                   1960:        break;
1.1.1.3 ! root     1961: 
1.1       root     1962:      case absw:
1.1.1.3 ! root     1963:        eai->addr_const_off = (uae_s16)do_get_mem_word((uae_u16 *)p);
1.1       root     1964:        eai->address_reg = -2;
                   1965:        (*pcpp) += 2; p += 2;
                   1966:        break;
                   1967: 
                   1968:      case absl:
1.1.1.3 ! root     1969:        eai->addr_const_off = (uae_s32)do_get_mem_long((uae_u32 *)p);
1.1       root     1970:        eai->address_reg = -2;
                   1971:        (*pcpp) += 4; p += 4;
                   1972:        break;
                   1973: 
                   1974:      case imm:
                   1975:        if (size == sz_long)
                   1976:            goto imm2_const;
                   1977:        if (size == sz_word)
                   1978:            goto imm1_const;
1.1.1.3 ! root     1979: 
1.1       root     1980:        /* fall through */
                   1981:      case imm0:
1.1.1.3 ! root     1982:        eai->data_const_off = (uae_s8)*(p+1);
1.1       root     1983:        eai->data_reg = -2;
                   1984:        (*pcpp) += 2; p += 2;
                   1985:        break;
                   1986: 
                   1987:      case imm1:
                   1988:        imm1_const:
1.1.1.3 ! root     1989:        eai->data_const_off = (uae_s16)do_get_mem_word((uae_u16 *)p);
1.1       root     1990:        eai->data_reg = -2;
                   1991:        (*pcpp) += 2; p += 2;
                   1992:        break;
                   1993: 
                   1994:      case imm2:
                   1995:        imm2_const:
1.1.1.3 ! root     1996:        eai->data_const_off = (uae_s32)do_get_mem_long((uae_u32 *)p);
1.1       root     1997:        eai->data_reg = -2;
                   1998:        (*pcpp) += 4; p += 4;
                   1999:        break;
                   2000: 
                   2001:      case immi:
1.1.1.3 ! root     2002:        eai->data_const_off = (uae_s8)reg;
1.1       root     2003:        eai->data_reg = -2;
                   2004:        break;
                   2005: 
                   2006:      default:
                   2007:        break;
                   2008:     }
                   2009:     eai->purpose = ea_purpose;
                   2010: }
                   2011: 
1.1.1.2   root     2012: static void compile_get_excl_lock(struct register_mapping *map, struct ea_info *eai)
1.1       root     2013: {
1.1.1.2   root     2014:     int x86r = eai->data_reg;
1.1.1.3 ! root     2015: 
1.1.1.2   root     2016:     if (x86r >= 0 && map->x86_locked[x86r] == 1) {
                   2017:        int newr;
                   2018:        if (eai->size == sz_byte)
                   2019:            newr = get_typed_x86_register(map, DATA_X86_REGS);
                   2020:        else
                   2021:            newr = get_free_x86_register(map, ALL_X86_REGS);
1.1.1.3 ! root     2022: 
1.1.1.2   root     2023:        compile_move_reg_reg(newr, x86r, sz_long);
                   2024:        eai->data_reg = newr;
                   2025:        lock_reg(map, eai->data_reg, 2);
1.1       root     2026:     }
1.1.1.2   root     2027: }
                   2028: 
                   2029: /*
                   2030:  * Some functions to assemble some 386 opcodes which have a similar
                   2031:  * structure (ADD, AND, OR, etc.). These take source and destination
                   2032:  * addressing modes, check their validity and assemble a complete
                   2033:  * 386 instruction.
                   2034:  */
1.1       root     2035: 
1.1.1.2   root     2036: static __inline__ int rmop_long(struct ea_info *eai)
                   2037: {
                   2038:     if (eai->data_reg == -2)
                   2039:        printf("rmop for const\n");
                   2040:     else if (eai->data_reg == -1) {
                   2041:        if (eai->address_reg == -2)
                   2042:            return 5;
                   2043:        if (eai->address_reg == -1) {
                   2044:            /* This must be a 68k register in its home location */
                   2045:            return 5;
                   2046:        }
                   2047: #if 0 /* We need to add address_space... */
                   2048:        if (eai->addr_const_off == 0 && eai->address_reg != r_EBP) {
                   2049:            return eai->address_reg;
                   2050:        }
1.1.1.3 ! root     2051:        else if ((uae_s32)eai->addr_const_off >= -128 && (uae_s32)eai->addr_const_off <= 127) {
1.1.1.2   root     2052:            return eai->address_reg | 0x40;
                   2053:        }
                   2054: #endif
                   2055:        return eai->address_reg | 0x80;
                   2056:     } else {
                   2057:        if (eai->size == sz_byte && ((1 << eai->data_reg) & DATA_X86_REGS) == 0)
                   2058:            printf("wrong type reg in rmop\n");
                   2059:        if (eai->data_const_off != 0)
                   2060:            printf("data_const_off in rmop\n");
                   2061:        return 0xC0 + eai->data_reg;
                   2062:     }
                   2063:     return 0;
                   2064: }
                   2065: 
                   2066: static __inline__ int rmop_short(struct ea_info *eai)
                   2067: {
                   2068:     if (eai->data_reg == -2)
                   2069:        printf("rmop_short for const\n");
                   2070:     else if (eai->data_reg == -1) {
                   2071:        printf("rmop_short for mem\n");
                   2072:     } else {
                   2073:        if (eai->size == sz_byte && ((1 << eai->data_reg) & DATA_X86_REGS) == 0)
                   2074:            printf("wrong type reg in rmop_short\n");
                   2075:        if (eai->data_const_off != 0)
                   2076:            printf("data_const_off in rmop_short\n");
                   2077:        return eai->data_reg*8;
                   2078:     }
                   2079:     return 0;
                   2080: }
                   2081: 
1.1.1.3 ! root     2082: static __inline__ void rmop_finalize(struct ea_info *eai)
1.1.1.2   root     2083: {
                   2084:     if (eai->data_reg == -2)
                   2085:        assemble_ulong(eai->data_const_off);
                   2086:     else if (eai->data_reg == -1) {
                   2087:        if (eai->address_reg == -2)
                   2088:            /* Constant address */
1.1.1.3 ! root     2089:            assemble_long(address_space + (uae_s32)eai->addr_const_off);
1.1.1.2   root     2090:        else if (eai->address_reg == -1) {
                   2091:            /* Register in its home location */
                   2092:            if (eai->mode == Areg)
                   2093:                assemble_long(regs.regs + 8  + eai->reg);
                   2094:            else
                   2095:                assemble_long(regs.regs + eai->reg);
                   2096:        } else {
                   2097: #if 0
                   2098:            /* Indirect address with offset */
1.1.1.3 ! root     2099:            if ((uae_s32)eai->addr_const_off >= -128 && (uae_s32)eai->addr_const_off <= 127) {
1.1.1.2   root     2100:            }
                   2101: #endif
1.1.1.3 ! root     2102:            assemble_long(address_space + (uae_s32)eai->addr_const_off);
1.1.1.2   root     2103:        }
                   2104:     }
                   2105: }
                   2106: 
1.1.1.3 ! root     2107: static void compile_eas(struct register_mapping *map, struct ea_info *eainf, int eaino_s, int eaino_d,
1.1.1.2   root     2108:                        int optype)
                   2109: {
                   2110:     struct ea_info *eais = eainf + eaino_s;
                   2111:     struct ea_info *eaid = eainf + eaino_d;
                   2112:     int szflag = eais->size == sz_byte ? 0 : 1;
                   2113:     int swapflag = 0;
                   2114:     int opcode;
                   2115: 
                   2116:     if (eais->data_reg == -1) {
                   2117:        compile_force_byteorder(map, eais->address_reg, BO_NORMAL, 0);
                   2118:        eais = eainf + eaino_d;
                   2119:        eaid = eainf + eaino_s;
                   2120:        swapflag = 1;
                   2121:     }
                   2122:     if (eais->data_reg == -1) {
                   2123:        compile_force_byteorder(map, eais->address_reg, BO_NORMAL, 0);
                   2124:     }
                   2125: 
                   2126:     if (eais->size == sz_word)
                   2127:        assemble(0x66);
                   2128: 
                   2129:     if (eais->data_reg == -2) {
                   2130:        assemble(0x80+szflag);
                   2131:        assemble(8*optype | rmop_long(eaid));
                   2132:        rmop_finalize(eaid);
                   2133:        switch(eais->size) {
                   2134:         case sz_byte: assemble(eais->data_const_off); break;
                   2135:         case sz_word: assemble_uword(eais->data_const_off); break;
                   2136:         case sz_long: assemble_ulong(eais->data_const_off); break;
                   2137:        }
                   2138:     } else {
                   2139:        assemble(8*optype | szflag | 2*swapflag);
                   2140:        assemble(rmop_long(eaid) | rmop_short(eais));
                   2141:        rmop_finalize(eaid);
                   2142:     }
                   2143: }
                   2144: 
                   2145: static void compile_fetchmem(struct register_mapping *map, struct ea_info *eai)
                   2146: {
                   2147:     int x86r;
1.1       root     2148:     if (eai->size == sz_byte)
                   2149:        x86r = get_typed_x86_register(map, DATA_X86_REGS);
                   2150:     else
                   2151:        x86r = get_free_x86_register(map, ALL_X86_REGS);
                   2152: 
1.1.1.2   root     2153:     lock_reg(map, x86r, 2);
1.1       root     2154:     compile_force_byteorder(map, eai->address_reg, BO_NORMAL, 0);
1.1.1.3 ! root     2155:     compile_move_reg_from_mem_regoffs(x86r, eai->address_reg,
        !          2156:                                      (uae_u32)(eai->addr_const_off + address_space),
1.1       root     2157:                                      eai->size);
1.1.1.2   root     2158:     map->x86_verified[x86r] = 0;
1.1       root     2159:     switch (eai->size) {
                   2160:      case sz_byte: map->x86_byteorder[x86r] = BO_NORMAL; break;
                   2161:      case sz_word: map->x86_byteorder[x86r] = BO_SWAPPED_WORD; break;
                   2162:      case sz_long: map->x86_byteorder[x86r] = BO_SWAPPED_LONG; break;
                   2163:     }
1.1.1.2   root     2164:     eai->data_reg = x86r;
                   2165:     eai->data_const_off = 0;
1.1       root     2166: }
                   2167: 
1.1.1.2   root     2168: static void compile_fetchimm(struct register_mapping *map, struct ea_info *eai, int byteorder)
1.1       root     2169: {
1.1.1.2   root     2170:     int x86r;
                   2171:     if (eai->size == sz_byte)
                   2172:        x86r = get_typed_x86_register(map, DATA_X86_REGS);
                   2173:     else
                   2174:        x86r = get_free_x86_register(map, ALL_X86_REGS);
                   2175: 
                   2176:     switch (byteorder) {
                   2177:      case BO_SWAPPED_LONG:
                   2178:        eai->data_const_off = (((eai->data_const_off & 0xFF000000) >> 24)
                   2179:                               | ((eai->data_const_off & 0xFF0000) >> 8)
                   2180:                               | ((eai->data_const_off & 0xFF00) << 8)
                   2181:                               | ((eai->data_const_off & 0xFF) << 24));
                   2182:        break;
                   2183:      case BO_SWAPPED_WORD:
                   2184:        eai->data_const_off = (((eai->data_const_off & 0xFF00) >> 8)
                   2185:                               | ((eai->data_const_off & 0xFF) << 8)
                   2186:                               | (eai->data_const_off & 0xFFFF0000));
                   2187:        break;
                   2188:      case BO_NORMAL:
                   2189:        break;
                   2190:     }
                   2191:     lock_reg(map, x86r, 2);
                   2192:     map->x86_byteorder[x86r] = byteorder; map->x86_verified[x86r] = 0;
                   2193: 
                   2194:     switch (eai->size) {
                   2195:      case sz_byte: assemble(0xC6); assemble(0xC0 + x86r); assemble(eai->data_const_off); break;
                   2196:      case sz_word: assemble(0x66); assemble(0xC7); assemble(0xC0 + x86r); assemble_uword(eai->data_const_off); break;
                   2197:      case sz_long: assemble(0xC7); assemble(0xC0 + x86r); assemble_ulong(eai->data_const_off); break;
                   2198:     }
                   2199:     eai->data_reg = x86r;
                   2200:     eai->data_const_off = 0;
                   2201: }
                   2202: 
                   2203: /*
                   2204:  * 1: reg
                   2205:  * 2: mem
                   2206:  * 4: imm
                   2207:  */
                   2208: 
                   2209: static int binop_alternatives[] = {
                   2210:     7, 1,
                   2211:     5, 3,
                   2212:     0, 0
1.1.1.3 ! root     2213: };
1.1.1.2   root     2214: 
                   2215: static int binop_worda_alternatives[] = {
                   2216:     1, 3,
                   2217:     0, 0
1.1.1.3 ! root     2218: };
1.1.1.2   root     2219: 
                   2220: static int regonly_alternatives[] = {
                   2221:     1, 1,
                   2222:     0, 0
1.1.1.3 ! root     2223: };
1.1.1.2   root     2224: 
                   2225: static void compile_loadeas(struct register_mapping *map, struct ea_info *eainf,
                   2226:                           int eaino_s, int eaino_d, int *alternatives,
                   2227:                           int scramble_poss, int load_dest)
                   2228: {
                   2229:     struct ea_info *eais = eainf + eaino_s;
                   2230:     struct ea_info *eaid = eainf + eaino_d;
                   2231:     int scrambled_bo = eaid->size == sz_long ? BO_SWAPPED_LONG : eaid->size == sz_word ? BO_SWAPPED_WORD : BO_NORMAL;
                   2232:     int i, scrambled = 0;
                   2233:     int best = 0;
                   2234:     int bestcost = -1;
                   2235:     int *ap;
1.1.1.3 ! root     2236:     uae_u32 *sregp = NULL, *dregp = NULL;
1.1.1.2   root     2237:     int screg = -1, dcreg = -1;
                   2238:     int stype = -1, dtype = -1;
                   2239:     int asrc, adst;
                   2240:     int regprefs = eais->size == sz_byte ? DATA_X86_REGS : 0;
                   2241: 
                   2242:     if (eais->mode == Dreg) {
                   2243:        stype = 0;
                   2244:        screg = map->dreg_map[eais->reg];
                   2245:        if (screg == -1)
                   2246:            sregp = regs.regs + eais->reg;
                   2247:     } else if (eais->mode == Areg) {
                   2248:        stype = 0;
                   2249:        screg = map->areg_map[eais->reg];
                   2250:        if (screg == -1)
                   2251:            sregp = regs.regs + 8 + eais->reg;
                   2252:     } else if (eais->data_reg == -2) {
                   2253:        stype = -2;
                   2254:     }
                   2255: 
                   2256:     if (eaid->mode == Dreg) {
                   2257:        dtype = 0;
                   2258:        dcreg = map->dreg_map[eaid->reg];
                   2259:        if (dcreg == -1)
                   2260:            dregp = regs.regs + eaid->reg;
                   2261:     } else if (eaid->mode == Areg) {
                   2262:        dtype = 0;
                   2263:        dcreg = map->areg_map[eaid->reg];
                   2264:        if (dcreg == -1)
                   2265:            dregp = regs.regs + 8 + eaid->reg;
                   2266:     } else if (eaid->data_reg == -2) {
                   2267:        dtype = -2;
                   2268:     }
                   2269: 
                   2270:     ap = alternatives;
1.1.1.3 ! root     2271: 
1.1.1.2   root     2272:     for (i = 0;; i++) {
                   2273:        int cost = 0;
                   2274: 
                   2275:        asrc = *ap++;
                   2276:        if (asrc == 0)
                   2277:            break;
                   2278:        adst = *ap++;
1.1.1.3 ! root     2279: 
1.1.1.2   root     2280:        if (stype == -2 && (asrc & 4) == 0)
                   2281:            cost++;
                   2282:        else if (stype == -1 && ((asrc & 2) == 0 || (eais->size != sz_byte && !scramble_poss)))
                   2283:            cost++;
                   2284:        else if (stype == 0 && screg == -1 && (asrc & 2) == 0)
                   2285:            cost++;
1.1.1.3 ! root     2286: 
1.1.1.2   root     2287:        if (dtype == -1 && ((adst & 2) == 0 || (eaid->size != sz_byte && !scramble_poss)))
                   2288:            /* The !load_dest case isn't handled by the current code,
                   2289:             * and it isn't desirable anyway. Use a different alternative
1.1       root     2290:             */
1.1.1.2   root     2291:            cost += load_dest ? 1 : 100;
                   2292:        else if (dtype == 0 && dcreg == -1 && (adst & 2) == 0)
                   2293:            cost++;
1.1.1.3 ! root     2294: 
1.1.1.2   root     2295:        if (bestcost == -1 || cost < bestcost) {
                   2296:            bestcost = cost;
                   2297:            best = i;
                   2298:        }
                   2299:     }
1.1.1.3 ! root     2300: 
1.1.1.2   root     2301:     asrc = alternatives[2*best];
                   2302:     adst = alternatives[2*best+1];
1.1.1.3 ! root     2303: 
1.1.1.2   root     2304:     if (dtype == -1) {
                   2305:        if (load_dest) {
                   2306:            if ((adst & 2) == 0 || (eaid->size != sz_byte && !scramble_poss))
                   2307:                compile_fetchmem(map, eaid);
                   2308:        } else {
                   2309:            if ((adst & 2) == 0) {
                   2310:                printf("Not loading memory operand. Prepare to die.\n");
                   2311:                if (eaid->size == sz_byte)
                   2312:                    eaid->data_reg = get_typed_x86_register(map, DATA_X86_REGS);
                   2313:                else
                   2314:                    eaid->data_reg = get_free_x86_register(map, ALL_X86_REGS);
1.1       root     2315:            }
                   2316:        }
1.1.1.2   root     2317:        /* Scrambled in both mem and reg cases */
                   2318:        if (eaid->size != sz_byte && scramble_poss)
                   2319:            scrambled = 1;
                   2320:     } else {
                   2321:        if (dcreg == -1 && !load_dest && (adst & 2) == 0 && eaid->size == sz_long) {
                   2322:            /* We need a register, but we don't need to fetch the old data.
                   2323:             * See storeea for some more code handling this case. This first
                   2324:             * if statement could be eliminated, we would generate some
                   2325:             * superfluous moves. This is an optimization. If it were not
                   2326:             * done, the mem-mem-move warning could be commented in in
                   2327:             * storeea. */
                   2328:            if (eaid->size == sz_byte)
                   2329:                eaid->data_reg = get_typed_x86_register(map, DATA_X86_REGS);
                   2330:            else
                   2331:                eaid->data_reg = get_free_x86_register(map, ALL_X86_REGS);
                   2332:            eaid->data_const_off = 0;
                   2333:        } else if ((dcreg == -1 && (adst & 2) == 0) || dcreg != -1) {
                   2334:            int reg_bo;
                   2335:            eaid->data_reg = get_and_lock_68k_reg(map, eaid->reg, eaid->mode == Dreg, regprefs, 1, 2);
                   2336:            eaid->data_const_off = 0;
1.1.1.3 ! root     2337: 
1.1.1.2   root     2338:            reg_bo = map->x86_byteorder[eaid->data_reg];
1.1.1.3 ! root     2339: 
1.1.1.2   root     2340:            if (reg_bo != BO_NORMAL) {
                   2341:                if (reg_bo != scrambled_bo)
                   2342:                    compile_force_byteorder(map, eaid->data_reg, BO_NORMAL, 0);
                   2343:                else if (scramble_poss)
                   2344:                    scrambled = 1;
                   2345:            }
                   2346:        }
                   2347:     }
1.1.1.3 ! root     2348: 
1.1.1.2   root     2349:     if (stype == -2) {
                   2350:        /* @@@ may need to scramble imm, this is a workaround */
                   2351:        if ((asrc & 4) == 0 || scrambled)
                   2352:            compile_fetchimm(map, eais, scrambled ? scrambled_bo : BO_NORMAL);
                   2353:     } else if (stype == -1) {
                   2354:        if ((asrc & 2) == 0 || (eais->size != sz_byte && !scrambled))
                   2355:            compile_fetchmem(map, eais);
                   2356:     } else {
                   2357:        if ((screg == -1 && (asrc & 2) == 0) || screg != -1) {
                   2358:            eais->data_reg = get_and_lock_68k_reg(map, eais->reg, eais->mode == Dreg, regprefs, 1, 2);
                   2359:            eais->data_const_off = 0;
                   2360:        }
                   2361:     }
1.1.1.3 ! root     2362: 
1.1.1.2   root     2363:     /* Optimization */
                   2364:     if (scrambled && eais->data_reg >= 0 && !load_dest
                   2365:        && map->x86_byteorder[eais->data_reg] == BO_NORMAL
                   2366:        && eaid->size == sz_long && dtype == 0)
                   2367:        scrambled = 0;
1.1.1.3 ! root     2368: 
1.1.1.2   root     2369:     if (regprefs != 0 && eais->data_reg >= 0 && ((1 << eais->data_reg) & regprefs) == 0) {
                   2370:        int tmpr = get_typed_x86_register(map, regprefs);
                   2371:        compile_move_reg_reg(tmpr, eais->data_reg, sz_long);
                   2372:        eais->data_reg = tmpr;
                   2373:     }
1.1.1.3 ! root     2374: 
1.1.1.2   root     2375:     if (regprefs != 0 && eaid->data_reg >= 0 && ((1 << eaid->data_reg) & regprefs) == 0) {
                   2376:        int tmpr = get_typed_x86_register(map, regprefs);
                   2377:        compile_move_reg_reg(tmpr, eaid->data_reg, sz_long);
                   2378:        eaid->data_reg = tmpr;
                   2379:     }
1.1.1.3 ! root     2380: 
1.1.1.2   root     2381:     /* Now set the byteorder once and for all (should already be correct for
                   2382:      * most cases) */
                   2383:     if (scrambled) {
                   2384:        if (eaid->data_reg >= 0)
                   2385:            compile_force_byteorder(map, eaid->data_reg, scrambled_bo, 0);
                   2386:        if (eais->data_reg >= 0)
1.1.1.3 ! root     2387:            compile_force_byteorder(map, eais->data_reg, scrambled_bo, 0);
1.1.1.2   root     2388:     } else {
                   2389:        if (eaid->data_reg >= 0)
                   2390:            compile_force_byteorder(map, eaid->data_reg, BO_NORMAL, 0);
                   2391:        if (eais->data_reg >= 0)
                   2392:            compile_force_byteorder(map, eais->data_reg, BO_NORMAL, 0);
                   2393:     }
                   2394: }
1.1       root     2395: 
1.1.1.2   root     2396: static void compile_fetchea(struct register_mapping *map, struct ea_info *eainf,
                   2397:                            int eaino, int asrc)
                   2398: {
                   2399:     struct ea_info *eais = eainf + eaino;
                   2400:     int scrambled_bo = eais->size == sz_long ? BO_SWAPPED_LONG : eais->size == sz_word ? BO_SWAPPED_WORD : BO_NORMAL;
                   2401:     int i, scrambled = 0;
                   2402:     int best = 0;
                   2403:     int bestcost = -1;
                   2404:     int *ap;
1.1.1.3 ! root     2405:     uae_u32 *sregp = NULL;
1.1.1.2   root     2406:     int screg = -1, stype = -1;
                   2407:     int regprefs = eais->size == sz_byte ? DATA_X86_REGS : 0;
                   2408: 
                   2409:     if (eais->mode == Dreg) {
                   2410:        stype = 0;
                   2411:        screg = map->dreg_map[eais->reg];
                   2412:        if (screg == -1)
                   2413:            sregp = regs.regs + eais->reg;
                   2414:     } else if (eais->mode == Areg) {
                   2415:        stype = 0;
                   2416:        screg = map->areg_map[eais->reg];
                   2417:        if (screg == -1)
                   2418:            sregp = regs.regs + 8 + eais->reg;
                   2419:     } else if (eais->data_reg == -2) {
                   2420:        stype = -2;
                   2421:     }
                   2422: 
                   2423:     if (stype == -2) {
                   2424:        if ((asrc & 4) == 0)
                   2425:            compile_fetchimm(map, eais, scrambled ? scrambled_bo : BO_NORMAL);
                   2426:     } else if (stype == -1) {
                   2427:        if ((asrc & 2) == 0 || eais->size != sz_byte)
                   2428:            compile_fetchmem(map, eais);
                   2429:     } else {
                   2430:        if ((screg == -1 && (asrc & 2) == 0) || screg != -1) {
                   2431:            eais->data_reg = get_and_lock_68k_reg(map, eais->reg, eais->mode == Dreg, regprefs, 1, 2);
                   2432:            eais->data_const_off = 0;
                   2433:        }
                   2434:     }
1.1.1.3 ! root     2435: 
1.1.1.2   root     2436:     if (eais->data_reg >= 0)
                   2437:        compile_force_byteorder(map, eais->data_reg, BO_NORMAL, 0);
                   2438: }
                   2439: 
                   2440: /*
                   2441:  * compile_note_modify() should be called on destination EAs obtained from
                   2442:  * compile_loadeas(), if their value was modified (e.g. by the compile_eas()
                   2443:  * function)
                   2444:  */
                   2445: 
                   2446: static void compile_note_modify(struct register_mapping *map, struct ea_info *eainf,
                   2447:                                int eaino)
                   2448: {
                   2449:     struct ea_info *eai = eainf + eaino;
                   2450:     int newr;
                   2451:     int szflag = eai->size == sz_byte ? 0 : 1;
                   2452: 
                   2453:     if (eai->mode == Dreg) {
                   2454:        /* We only need to do something if we have the value in a register,
                   2455:         * otherwise, the home location was modified already */
                   2456:        if (eai->data_reg >= 0) {
                   2457:            if (eai->data_reg != map->dreg_map[eai->reg]) {
                   2458:                remove_x86r_from_cache(map, eai->data_reg, 0);
                   2459:                if (map->dreg_map[eai->reg] >= 0)
                   2460:                    remove_x86r_from_cache(map, map->dreg_map[eai->reg], 0);
                   2461:                map->x86_cache_reg[eai->data_reg] = eai->reg;
                   2462:                map->x86_cr_type[eai->data_reg] = 1;
                   2463:                map->dreg_map[eai->reg] = eai->data_reg;
1.1       root     2464:            }
1.1.1.3 ! root     2465:            map->x86_verified[eai->data_reg] = 0;
1.1.1.2   root     2466:            map->x86_const_offset[eai->data_reg] = eai->data_const_off;
                   2467:            map->x86_dirty[eai->data_reg] = 1;
1.1       root     2468:        }
                   2469:        return;
                   2470:     } else if (eai->mode == Areg) {
                   2471:        if (eai->size != sz_long)
                   2472:            printf("Areg put != long\n");
                   2473: 
1.1.1.2   root     2474:        /* We only need to do something if we have the value in a register,
                   2475:         * otherwise, the home location was modified already */
                   2476:        if (eai->data_reg >= 0) {
                   2477:            if (eai->data_reg != map->areg_map[eai->reg]) {
                   2478:                remove_x86r_from_cache(map, eai->data_reg, 0);
                   2479:                if (map->areg_map[eai->reg] >= 0)
                   2480:                    remove_x86r_from_cache(map, map->areg_map[eai->reg], 0);
                   2481:                map->x86_cache_reg[eai->data_reg] = eai->reg;
                   2482:                map->x86_cr_type[eai->data_reg] = 0;
                   2483:                map->areg_map[eai->reg] = eai->data_reg;
                   2484:            }
1.1.1.3 ! root     2485:            map->x86_verified[eai->data_reg] = 0;
1.1.1.2   root     2486:            map->x86_const_offset[eai->data_reg] = eai->data_const_off;
                   2487:            map->x86_dirty[eai->data_reg] = 1;
                   2488:        }
                   2489:        return;
                   2490:     } else {
                   2491:        /* Storing to memory from reg? */
                   2492:        if (eai->data_reg >= 0) {
                   2493:            compile_offset_reg(map, eai->data_reg, eai->data_const_off);
1.1.1.3 ! root     2494: 
1.1.1.2   root     2495:            switch (eai->size) {
                   2496:             case sz_byte: compile_force_byteorder(map, eai->data_reg, BO_NORMAL, 1); break;
                   2497:             case sz_word: compile_force_byteorder(map, eai->data_reg, BO_SWAPPED_WORD, 1); break;
                   2498:             case sz_long: compile_force_byteorder(map, eai->data_reg, BO_SWAPPED_LONG, 1); break;
                   2499:            }
                   2500:            compile_force_byteorder(map, eai->address_reg, BO_NORMAL, 0);
                   2501:            compile_move_reg_to_mem_regoffs(eai->address_reg,
1.1.1.3 ! root     2502:                                            (uae_u32)(eai->addr_const_off + address_space),
1.1.1.2   root     2503:                                            eai->data_reg, eai->size);
                   2504:        }
                   2505:     }
                   2506: }
1.1       root     2507: 
1.1.1.2   root     2508: static void compile_storeea(struct register_mapping *map, struct ea_info *eainf,
                   2509:                            int eaino_s, int eaino_d)
                   2510: {
                   2511:     struct ea_info *eais = eainf + eaino_s;
                   2512:     struct ea_info *eaid = eainf + eaino_d;
                   2513:     int newr, cacher;
                   2514:     int szflag = eaid->size == sz_byte ? 0 : 1;
                   2515: 
                   2516:     if (eaid->mode == Dreg) {
                   2517:        /* Is the reg to move from already the register cache reg for the
                   2518:         * destination? */
                   2519:        if (eais->data_reg >= 0 && eais->data_reg == map->dreg_map[eaid->reg]) {
                   2520:            map->x86_dirty[eais->data_reg] = 1; map->x86_verified[eais->data_reg] = 0;
                   2521:            map->x86_const_offset[eais->data_reg] = eais->data_const_off;
                   2522:            return;
1.1       root     2523:        }
1.1.1.2   root     2524:        /* Is the destination register in its home location? */
                   2525:        if (map->dreg_map[eaid->reg] < 0) {
                   2526:            if (eais->data_reg == -2) {
                   2527:                /* Move immediate to regs.regs */
                   2528:                if (eaid->size == sz_word) assemble(0x66);
                   2529:                assemble(0xC6 + szflag); assemble(0x05); assemble_long(regs.regs + eaid->reg);
                   2530:                switch (eaid->size) {
                   2531:                 case sz_byte: assemble(eais->data_const_off); break;
                   2532:                 case sz_word: assemble_uword(eais->data_const_off); break;
                   2533:                 case sz_long: assemble_ulong(eais->data_const_off); break;
                   2534:                }
                   2535:            } else if (eais->data_reg == -1) {
                   2536: #if 0
                   2537:                printf("Shouldn't happen (mem-mem-move)\n");
                   2538: #endif
                   2539:                /* This _can_ happen: move.l $4,d0, if d0 isn't in the
                   2540:                 * cache, will come here. But a reg will be allocated for
                   2541:                 * dest. We use this. This _really_ shouldn't happen if
                   2542:                 * the size isn't long. */
                   2543:                if (eaid->size != sz_long)
                   2544:                    printf("_Really_ shouldn't happen (Dreg case)\n");
                   2545:                map->x86_cache_reg[eaid->data_reg] = eaid->reg;
                   2546:                map->x86_cr_type[eaid->data_reg] = 1;
                   2547:                map->x86_const_offset[eaid->data_reg] = eaid->data_const_off;
                   2548:                map->dreg_map[eaid->reg] = eaid->data_reg;
                   2549:                map->x86_verified[eaid->data_reg] = 0;
                   2550:                goto have_cache_reg_d;
                   2551:            } else {
                   2552:                if (eais->size == sz_long) {
                   2553:                    /* Make this the new register cache reg */
                   2554:                    remove_x86r_from_cache(map, eais->data_reg, 0);
                   2555:                    map->x86_cache_reg[eais->data_reg] = eaid->reg;
                   2556:                    map->x86_cr_type[eais->data_reg] = 1;
                   2557:                    map->x86_const_offset[eais->data_reg] = eais->data_const_off;
                   2558:                    map->dreg_map[eaid->reg] = eais->data_reg;
                   2559:                    map->x86_verified[eais->data_reg] = 0;
                   2560:                } else {
                   2561:                    /* Move from reg to regs.regs */
                   2562:                    compile_force_byteorder(map, eais->data_reg, BO_NORMAL, 1);
                   2563:                    compile_offset_reg (map, eais->data_reg, eais->data_const_off);
                   2564:                    if (eaid->size == sz_word) assemble(0x66);
                   2565:                    assemble(0x88 + szflag); assemble(0x05 + 8*eais->data_reg);
                   2566:                    assemble_long(regs.regs + eaid->reg);
                   2567:                }
                   2568:            }
                   2569:        } else {
                   2570:            int destr;
1.1.1.3 ! root     2571: 
1.1.1.2   root     2572:            have_cache_reg_d:
                   2573: 
                   2574:            destr = map->dreg_map[eaid->reg];
                   2575:            if (eaid->size != sz_long)
                   2576:                compile_force_byteorder(map, destr, BO_NORMAL, 1);
                   2577: 
                   2578:            if (eais->data_reg == -2) {
                   2579:                /* Move immediate to reg */
                   2580:                if (eaid->size == sz_word) assemble(0x66);
                   2581:                assemble(0xC6 + szflag); assemble(0xC0 + destr);
                   2582:                switch (eaid->size) {
                   2583:                 case sz_byte: assemble(eais->data_const_off); break;
                   2584:                 case sz_word: assemble_uword(eais->data_const_off); break;
                   2585:                 case sz_long: assemble_ulong(eais->data_const_off); break;
                   2586:                }
                   2587:                /* normal byteorder comes either from force above or from long
                   2588:                 * const move */
                   2589:                map->x86_byteorder[destr] = BO_NORMAL;
                   2590:            } else if (eais->data_reg == -1) {
                   2591:                if (eais->mode == Dreg) {
1.1.1.3 ! root     2592:                    compile_move_reg_from_mem_regoffs(destr, -2, (uae_u32)(regs.regs + eais->reg),
1.1.1.2   root     2593:                                                      eais->size);
                   2594:                    map->x86_byteorder[destr] = BO_NORMAL;
                   2595:                } else if (eais->mode == Areg) {
1.1.1.3 ! root     2596:                    compile_move_reg_from_mem_regoffs(destr, -2, (uae_u32)(regs.regs + 8 + eais->reg),
1.1.1.2   root     2597:                                                      eais->size);
                   2598:                    map->x86_byteorder[destr] = BO_NORMAL;
                   2599:                } else {
                   2600:                    /* Move mem to reg */
                   2601:                    compile_force_byteorder(map, eais->address_reg, BO_NORMAL, 0);
                   2602:                    compile_move_reg_from_mem_regoffs(destr, eais->address_reg,
1.1.1.3 ! root     2603:                                                      (uae_u32)(eais->addr_const_off + address_space),
1.1.1.2   root     2604:                                                      eais->size);
                   2605: 
                   2606:                    switch (eais->size) {
                   2607:                     case sz_byte: map->x86_byteorder[destr] = BO_NORMAL; break;
                   2608:                     case sz_word: map->x86_byteorder[destr] = BO_SWAPPED_WORD; break;
                   2609:                     case sz_long: map->x86_byteorder[destr] = BO_SWAPPED_LONG; break;
                   2610:                    }
                   2611:                }
                   2612:            } else {
                   2613:                if (eais->size == sz_long) {
                   2614:                    /* Make this the new register cache reg */
                   2615:                    remove_x86r_from_cache(map, eais->data_reg, 0);
                   2616:                    remove_x86r_from_cache(map, destr, 0);
                   2617:                    map->x86_cache_reg[eais->data_reg] = eaid->reg;
                   2618:                    map->x86_cr_type[eais->data_reg] = 1;
                   2619:                    map->x86_const_offset[eais->data_reg] = eais->data_const_off;
                   2620:                    map->dreg_map[eaid->reg] = eais->data_reg;
                   2621:                    map->x86_verified[eais->data_reg] = 0;
                   2622:                } else {
                   2623:                    /* Move from reg to reg */
                   2624:                    compile_force_byteorder(map, eais->data_reg, BO_NORMAL, 1);
                   2625:                    compile_offset_reg (map, eais->data_reg, eais->data_const_off);
                   2626:                    if (eaid->size == sz_word) assemble(0x66);
                   2627:                    assemble(0x88 + szflag); assemble(0xC0 + destr + 8*eais->data_reg);
                   2628:                }
                   2629:            }
                   2630:        }
1.1.1.3 ! root     2631: 
1.1.1.2   root     2632:        if (map->dreg_map[eaid->reg] >= 0)
                   2633:            map->x86_dirty[map->dreg_map[eaid->reg]] = 1;
                   2634:        return;
                   2635:     } else if (eaid->mode == Areg) {
                   2636:        if (eaid->size != sz_long)
                   2637:            printf("Areg put != long\n");
                   2638: 
                   2639:        /* Is the reg to move from already the register cache reg for the
                   2640:         * destination? */
                   2641:        if (eais->data_reg >= 0 && eais->data_reg == map->areg_map[eaid->reg]) {
                   2642:            map->x86_dirty[eais->data_reg] = 1; map->x86_verified[eais->data_reg] = 0;
                   2643:            map->x86_const_offset[eais->data_reg] = eais->data_const_off;
                   2644:            return;
1.1.1.3 ! root     2645:        }
1.1.1.2   root     2646:        /* Is the destination register in its home location? */
                   2647:        if (map->areg_map[eaid->reg] < 0) {
                   2648:            if (eais->data_reg == -2) {
                   2649:                /* Move immediate to regs.regs */
                   2650:                assemble(0xC7); assemble(0x05); assemble_long(regs.regs + 8 + eaid->reg);
                   2651:                assemble_ulong(eais->data_const_off);
                   2652:            } else if (eais->data_reg == -1) {
                   2653: #if 0 /* see above... */
                   2654:                printf("Shouldn't happen (mem-mem-move)\n");
                   2655: #endif
                   2656:                map->x86_cache_reg[eaid->data_reg] = eaid->reg;
                   2657:                map->x86_cr_type[eaid->data_reg] = 0;
                   2658:                map->x86_const_offset[eaid->data_reg] = eaid->data_const_off;
                   2659:                map->areg_map[eaid->reg] = eaid->data_reg;
                   2660:                map->x86_verified[eaid->data_reg] = 0;
                   2661:                goto have_cache_reg_a;
                   2662:            } else {
                   2663:                /* Make this the new register cache reg */
                   2664:                remove_x86r_from_cache(map, eais->data_reg, 0);
                   2665:                map->x86_cache_reg[eais->data_reg] = eaid->reg;
                   2666:                map->x86_cr_type[eais->data_reg] = 0;
                   2667:                map->x86_const_offset[eais->data_reg] = eais->data_const_off;
                   2668:                map->areg_map[eaid->reg] = eais->data_reg;
                   2669:                map->x86_verified[eais->data_reg] = 0;
                   2670:            }
                   2671:        } else {
                   2672:            int destr;
1.1.1.3 ! root     2673: 
1.1.1.2   root     2674:            have_cache_reg_a:
                   2675: 
                   2676:            destr = map->areg_map[eaid->reg];
                   2677:            if (eaid->size != sz_long)
                   2678:                compile_force_byteorder(map, destr, BO_NORMAL, 1);
                   2679: 
                   2680:            if (eais->data_reg == -2) {
                   2681:                /* Move immediate to reg */
                   2682:                assemble(0xC7); assemble(0xC0 + destr);
                   2683:                assemble_ulong(eais->data_const_off);
                   2684: 
                   2685:                /* normal byteorder comes either from force above or from long
                   2686:                 * const move */
                   2687:                map->x86_byteorder[destr] = BO_NORMAL;
                   2688:            } else if (eais->data_reg == -1) {
                   2689:                if (eais->mode == Dreg) {
1.1.1.3 ! root     2690:                    compile_move_reg_from_mem_regoffs(destr, -2, (uae_u32)(regs.regs + eais->reg),
1.1.1.2   root     2691:                                                      eais->size);
                   2692:                    map->x86_byteorder[destr] = BO_NORMAL;
                   2693:                } else if (eais->mode == Areg) {
1.1.1.3 ! root     2694:                    compile_move_reg_from_mem_regoffs(destr, -2, (uae_u32)(regs.regs + 8 + eais->reg),
1.1.1.2   root     2695:                                                      eais->size);
                   2696:                    map->x86_byteorder[destr] = BO_NORMAL;
                   2697:                } else {
                   2698:                    /* Move mem to reg */
                   2699:                    compile_force_byteorder(map, eais->address_reg, BO_NORMAL, 0);
1.1.1.3 ! root     2700:                    compile_move_reg_from_mem_regoffs(destr, eais->address_reg,
        !          2701:                                                      (uae_u32)(eais->addr_const_off + address_space),
1.1.1.2   root     2702:                                                      eais->size);
1.1.1.3 ! root     2703: 
1.1.1.2   root     2704:                    map->x86_byteorder[destr] = BO_SWAPPED_LONG;
                   2705:                }
                   2706:            } else {
                   2707:                /* Make this the new register cache reg */
                   2708:                remove_x86r_from_cache(map, eais->data_reg, 0);
                   2709:                remove_x86r_from_cache(map, destr, 0);
                   2710:                map->x86_cache_reg[eais->data_reg] = eaid->reg;
                   2711:                map->x86_cr_type[eais->data_reg] = 0;
                   2712:                map->x86_const_offset[eais->data_reg] = eais->data_const_off;
                   2713:                map->areg_map[eaid->reg] = eais->data_reg;
                   2714:                map->x86_verified[eais->data_reg] = 0;
                   2715:            }
1.1       root     2716:        }
1.1.1.3 ! root     2717: 
1.1.1.2   root     2718:        if (map->areg_map[eaid->reg] >= 0)
                   2719:            map->x86_dirty[map->areg_map[eaid->reg]] = 1;
1.1       root     2720:        return;
                   2721:     }
                   2722: 
1.1.1.2   root     2723:     if (eais->data_reg == -1)
                   2724:        printf("Storing to mem, but not from reg\n");
1.1       root     2725:     /* Correct the byteorder */
1.1.1.2   root     2726:     if (eais->data_reg != -2) {
                   2727:        compile_offset_reg(map, eais->data_reg, eais->data_const_off);
1.1.1.3 ! root     2728: 
1.1.1.2   root     2729:        switch (eaid->size) {
                   2730:         case sz_byte: compile_force_byteorder(map, eais->data_reg, BO_NORMAL, 1); break;
                   2731:         case sz_word: compile_force_byteorder(map, eais->data_reg, BO_SWAPPED_WORD, 1); break;
                   2732:         case sz_long: compile_force_byteorder(map, eais->data_reg, BO_SWAPPED_LONG, 1); break;
                   2733:        }
                   2734:        compile_force_byteorder(map, eaid->address_reg, BO_NORMAL, 0);
                   2735:        compile_move_reg_to_mem_regoffs(eaid->address_reg,
1.1.1.3 ! root     2736:                                        (uae_u32)(eaid->addr_const_off + address_space),
1.1.1.2   root     2737:                                        eais->data_reg, eaid->size);
1.1       root     2738:     } else {
1.1.1.2   root     2739:        switch (eaid->size) {
1.1       root     2740:         case sz_long:
1.1.1.2   root     2741:            eais->data_const_off = (((eais->data_const_off & 0xFF000000) >> 24)
                   2742:                                 | ((eais->data_const_off & 0xFF0000) >> 8)
                   2743:                                 | ((eais->data_const_off & 0xFF00) << 8)
                   2744:                                 | ((eais->data_const_off & 0xFF) << 24));
1.1       root     2745:            break;
                   2746:         case sz_word:
1.1.1.2   root     2747:            eais->data_const_off = (((eais->data_const_off & 0xFF00) >> 8)
                   2748:                                 | ((eais->data_const_off & 0xFF) << 8));
1.1       root     2749:            break;
                   2750:        }
1.1.1.2   root     2751:        compile_force_byteorder(map, eaid->address_reg, BO_NORMAL, 0);
1.1       root     2752:        /* generate code to move valueoffset,eaoffset(eareg) */
1.1.1.3 ! root     2753:        switch(eaid->size) {
1.1       root     2754:         case sz_byte: assemble(0xC6); break;
                   2755:         case sz_word: assemble(0x66); /* fall through */
                   2756:         case sz_long: assemble(0xC7); break;
                   2757:        }
1.1.1.2   root     2758:        if (eaid->address_reg == -2) { /* absolute or PC-relative */
1.1       root     2759:            assemble(0x05);
1.1.1.2   root     2760:            assemble_long(eaid->addr_const_off + address_space);
1.1       root     2761:        } else {
1.1.1.2   root     2762:            assemble(0x80 + eaid->address_reg);
                   2763:            assemble_long(eaid->addr_const_off + address_space);
1.1       root     2764:        }
1.1.1.2   root     2765:        switch(eaid->size) {
                   2766:         case sz_byte: assemble(eais->data_const_off); break;
                   2767:         case sz_word: assemble_uword(eais->data_const_off); break;
                   2768:         case sz_long: assemble_ulong(eais->data_const_off); break;
1.1       root     2769:        }
                   2770:     }
                   2771: }
                   2772: 
                   2773: #define CE_STACK_SIZE 1000
                   2774: 
                   2775: static struct {
                   2776:     struct register_mapping map;
                   2777:     char *jmpoffs;
1.1.1.3 ! root     2778:     uae_u32 address;
1.1       root     2779:     int noflush:1;
                   2780: } compile_exit_stack[CE_STACK_SIZE];
                   2781: 
                   2782: static int cesp;
                   2783: 
                   2784: static struct register_mapping current_exit_regmap;
                   2785: 
                   2786: static void generate_exit(struct register_mapping *map, int address)
                   2787: {
                   2788:     int i;
1.1.1.3 ! root     2789: 
1.1       root     2790:     if (map != NULL)
                   2791:        sync_reg_cache (map, 1);
                   2792:     assemble(0xB8); /* movl $new_pc,%eax */
                   2793:     assemble_ulong(address);
                   2794:     assemble(0xC3); /* RET */
                   2795: }
                   2796: 
1.1.1.3 ! root     2797: static void copy_map_with_undo(struct register_mapping *dst,
1.1       root     2798:                               struct register_mapping *src,
                   2799:                               struct pid_undo *pud)
                   2800: {
                   2801:     int i;
                   2802:     *dst = *src;
                   2803:     for (i = 0; i < pud->used; i++) {
                   2804:        int m68kr = pud->m68kr[i];
                   2805:        int x86r = pud->x86r[i];
                   2806:        int old_cr = dst->areg_map[m68kr];
                   2807:        if (old_cr != -1) {
                   2808:            dst->x86_cache_reg[old_cr] = -1;
                   2809:        }
                   2810:        dst->x86_cache_reg[x86r] = m68kr;
                   2811:        dst->areg_map[m68kr] = x86r;
                   2812:        dst->x86_cr_type[x86r] = 0;
                   2813:        dst->x86_const_offset[x86r] = pud->offs[i];
                   2814:        dst->x86_dirty[x86r] = pud->dirty[i];
                   2815:     }
                   2816: }
                   2817: 
1.1.1.2   root     2818: static void unlock_pud(struct register_mapping *map, struct pid_undo *pud)
                   2819: {
                   2820:     int i;
                   2821:     for (i = 0; i < pud->used; i++) {
                   2822:        compile_unlock_reg(map, pud->x86r[i]);
                   2823:     }
                   2824: }
                   2825: 
                   2826: static int exits_necessary;
                   2827: 
1.1       root     2828: static void generate_possible_exit(struct register_mapping *map,
                   2829:                                   struct ea_info *eai, int iip,
                   2830:                                   struct pid_undo *pud)
                   2831: {
                   2832:     struct register_mapping exit_regmap;
1.1.1.3 ! root     2833: 
1.1.1.2   root     2834:     if (!exits_necessary) {
                   2835:        unlock_pud(map, pud);
                   2836:        return;
                   2837:     }
                   2838: 
                   2839:     compile_force_byteorder(map, eai->address_reg, BO_NORMAL, 0);
1.1       root     2840:     switch (eai->address_reg) {
                   2841:      case -1:
                   2842:        /* EA doesn't refer to memory */
                   2843:        break;
                   2844:      case -2:
                   2845:        /* Only a constant offset */
                   2846:        eai->addr_const_off &= (1<<24)-1;
                   2847:        if (!good_address_map[eai->addr_const_off]) {
                   2848:            copy_map_with_undo(&exit_regmap, map, pud);
                   2849:            generate_exit(&exit_regmap, insn_info[iip].address);
                   2850:        }
                   2851:        break;
                   2852:      default:
                   2853:        if (map->x86_verified[eai->address_reg])
                   2854:            break;
                   2855:        map->x86_verified[eai->address_reg] = 1;
                   2856:        if (cesp == CE_STACK_SIZE) {
                   2857:            copy_map_with_undo(&exit_regmap, map, pud);
                   2858:            generate_exit(&exit_regmap, insn_info[iip].address);
                   2859:            break;
                   2860:        }
                   2861:        copy_map_with_undo(&compile_exit_stack[cesp].map, map, pud);
                   2862:        compile_exit_stack[cesp].address = insn_info[iip].address;
                   2863:        assemble(0x80); assemble(0xB8 + eai->address_reg); /* cmpb $0, good_address_map(x86r) */
                   2864:        assemble_long(good_address_map + eai->addr_const_off);
                   2865:        assemble(0);
                   2866:        assemble(0x0F); assemble(0x84); /* JE finish */
                   2867:        compile_exit_stack[cesp].jmpoffs = compile_here();
                   2868:        compile_exit_stack[cesp].noflush = 0;
                   2869:        assemble_ulong(0);
                   2870:        cesp++;
                   2871:        break;
                   2872:     }
1.1.1.2   root     2873:     unlock_pud(map, pud);
1.1       root     2874: }
                   2875: 
                   2876: static void finish_exits(void)
                   2877: {
                   2878:     int i;
                   2879:     for (i = 0; i < cesp; i++) {
                   2880:        char *exitpoint = compile_here();
                   2881:        char *nextpoint;
                   2882: 
                   2883:        if (compile_exit_stack[i].noflush)
                   2884:            generate_exit(NULL, compile_exit_stack[i].address);
                   2885:        else
                   2886:            generate_exit(&compile_exit_stack[i].map, compile_exit_stack[i].address);
                   2887:        nextpoint = compile_here();
                   2888:        compile_org(compile_exit_stack[i].jmpoffs);
                   2889:        assemble_ulong(exitpoint - (compile_exit_stack[i].jmpoffs + 4));
                   2890:        compile_org(nextpoint);
                   2891:     }
                   2892: }
                   2893: 
                   2894: static void finish_condjumps(int lastiip)
                   2895: {
                   2896:     int iip;
                   2897:     char *lastptr = compile_here();
                   2898:     for (iip = 0; iip < lastiip; iip++) {
                   2899:        char *fillin = insn_info[iip].compiled_fillin;
                   2900:        if (fillin != NULL) {
                   2901:            compile_org(insn_info[iip].compiled_fillin);
                   2902:            assemble_ulong(insn_info[insn_info[iip].jumps_to].compiled_jumpaddr - (fillin + 4));
                   2903:        }
                   2904:     }
                   2905:     compile_org(lastptr);
                   2906: }
                   2907: 
                   2908: #define CC_X_FROM_86C 1
                   2909: #define CC_C_FROM_86C 2
                   2910: #define CC_Z_FROM_86Z 4
1.1.1.3 ! root     2911: #define CC_V_FROM_86V 8
1.1       root     2912: #define CC_N_FROM_86N 16
                   2913: #define CC_TEST_REG   32
                   2914: #define CC_Z_FROM_86C 64
                   2915: #define CC_SAHF       128
                   2916: #define CC_TEST_CONST 256
                   2917: #define CC_AFTER_RO   512
                   2918: #define CC_AFTER_ROX  1024
                   2919: 
                   2920: static unsigned int cc_status;
                   2921: static int cc_reg;
1.1.1.3 ! root     2922: static uae_u32 cc_offset;
1.1       root     2923: static wordsizes cc_size;
                   2924: 
                   2925: static void compile_do_cc_test_reg(struct register_mapping *map)
                   2926: {
                   2927:     compile_force_byteorder(map, cc_reg, BO_NORMAL, 1);
                   2928:     if (cc_offset != 0)
                   2929:        printf("Pull my finger\n");
                   2930:     if (cc_size == sz_word) /* test ccreg */
                   2931:        assemble(0x66);
                   2932:     if (cc_size == sz_byte)
                   2933:        assemble(0x84);
                   2934:     else
                   2935:        assemble(0x85);
                   2936:     assemble(0xC0 + 9*cc_reg);
                   2937: }
                   2938: 
1.1.1.3 ! root     2939: static int compile_flush_cc_cache(struct register_mapping *map, int status,
1.1       root     2940:                                  int live_at_end, int user_follows,
                   2941:                                  int user_live_at_end, int user_ccval)
                   2942: {
                   2943:     int status_for_user = 0;
                   2944: 
                   2945:     if (user_follows) {
                   2946:        int need_for_user = 0;
1.1.1.2   root     2947:        int user_flagmask = cc_flagmask_68k(user_ccval);
1.1       root     2948: 
                   2949:        if (user_flagmask & CC68K_C)
                   2950:            need_for_user |= CC_C_FROM_86C;
                   2951:        if (user_flagmask & CC68K_Z)
                   2952:            need_for_user |= CC_Z_FROM_86Z;
                   2953:        if (user_flagmask & CC68K_N)
                   2954:            need_for_user |= CC_N_FROM_86N;
                   2955:        if (user_flagmask & CC68K_V)
                   2956:            need_for_user |= CC_V_FROM_86V;
                   2957: 
                   2958:        /* Check whether we can satisfy the user's needs in a simple way. */
                   2959:        if ((need_for_user & status) == need_for_user)
                   2960:            status_for_user = status;
                   2961:        else if (user_flagmask == CC68K_Z && status == CC_Z_FROM_86C)
                   2962:            status_for_user = status;
                   2963:        else if (status == CC_TEST_REG && (user_flagmask & (CC68K_C|CC68K_V|CC68K_Z|CC68K_N)) != 0) {
                   2964:            if (cc_reg == -2) {
                   2965:                status_for_user = CC_TEST_CONST;
                   2966:            } else {
                   2967:                compile_do_cc_test_reg(map);
                   2968:                status_for_user = status = (CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V);
                   2969:            }
                   2970:        } else if (status == CC_AFTER_RO) {
                   2971:            /* We fake some information here... */
                   2972:            if (user_flagmask == CC68K_C && (user_live_at_end & ~CC68K_C) == 0)
                   2973:                status = status_for_user = CC_C_FROM_86C;
1.1.1.2   root     2974:            else if (((user_flagmask | user_live_at_end) & (CC68K_C|CC68K_V)) == 0) {
1.1       root     2975:                status = CC_TEST_REG; user_live_at_end = CC68K_Z|CC68K_N|CC68K_V;
                   2976:                status_for_user = (CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V);
                   2977:            } else
                   2978:                status_for_user = CC_SAHF;
                   2979:        } else if (status == CC_AFTER_ROX) {
                   2980:            if (user_flagmask == CC68K_C && (user_live_at_end & ~(CC68K_C|CC68K_X)) == 0)
                   2981:                status = status_for_user = CC_C_FROM_86C;
1.1.1.2   root     2982:            else if (((user_flagmask | user_live_at_end) & (CC68K_C|CC68K_X|CC68K_V)) == 0) {
1.1       root     2983:                status = CC_TEST_REG; user_live_at_end = CC68K_Z|CC68K_N|CC68K_V;
                   2984:                status_for_user = (CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V);
                   2985:            } else
                   2986:                status_for_user = CC_SAHF;
                   2987:        } else if (need_for_user != 0) {
                   2988:            /* No way to handle it easily */
                   2989:            status_for_user = CC_SAHF;
                   2990:        }
                   2991:        if (status_for_user != CC_SAHF)
                   2992:            live_at_end = user_live_at_end;
                   2993:     }
                   2994: 
                   2995:     /*
1.1.1.3 ! root     2996:      * Now store the flags which are live at the end of this insn and set by
        !          2997:      * us into their home locations
1.1       root     2998:      */
                   2999:     if (status == CC_TEST_REG) {
                   3000:        if ((live_at_end & (CC68K_C|CC68K_V|CC68K_Z|CC68K_N)) == 0)
                   3001:            goto all_ok;
                   3002: 
                   3003:        if (cc_reg == -2) {
1.1.1.3 ! root     3004:            uae_u8 f = 0;
1.1       root     3005:            if (cc_size == sz_byte) {
                   3006:                f |= (cc_offset & 0x80) ? 0x80 : 0;
                   3007:                f |= (cc_offset & 0xFF) == 0 ? 0x40 : 0;
                   3008:            } else if (cc_size == sz_byte) {
                   3009:                f |= (cc_offset & 0x8000) ? 0x80 : 0;
                   3010:                f |= (cc_offset & 0xFFFF) == 0 ? 0x40 : 0;
                   3011:            } else {
                   3012:                f |= (cc_offset & 0x80000000) ? 0x80 : 0;
                   3013:                f |= (cc_offset & 0xFFFFFFFF) == 0 ? 0x40 : 0;
                   3014:            }
1.1.1.3 ! root     3015:            assemble(0xC7); assemble(0x05);
1.1       root     3016:            assemble_long((char*)&regflags);
                   3017:            assemble_uword(f);
                   3018:        } else {
                   3019:            int tmpr = get_free_x86_register(map, ALL_X86_REGS);
                   3020:            compile_do_cc_test_reg(map);
                   3021: 
                   3022:            /* pushfl; popl tmpr; movl tempr, regflags */
                   3023:            assemble(0x9C); assemble(0x58+tmpr);
1.1.1.3 ! root     3024:            compile_move_reg_to_mem_regoffs(-2, (uae_u32)&regflags, tmpr, sz_long);
1.1       root     3025:        }
                   3026:     } else if (status == CC_Z_FROM_86C) {
                   3027:        if ((live_at_end & CC68K_Z) != 0) {
                   3028:            int tmpr = get_typed_x86_register(map, DATA_X86_REGS);
                   3029:            assemble(0x9C);
                   3030:            /* setnc tmpr; shl $6, tmpr; andb $~0x40, regflags; orb tmpr, regflags */
                   3031:            assemble(0x0F); assemble(0x93); assemble(0xC0 + tmpr);
                   3032:            assemble(0xC0); assemble(4*8 + 0xC0 + tmpr); assemble(6);
1.1.1.3 ! root     3033:            assemble(0x80); assemble(0x05+0x20); assemble_long(&regflags); assemble((uae_u8)~0x40);
1.1       root     3034:            assemble(0x08); assemble(0x05+ tmpr*8); assemble_long(&regflags);
                   3035:            assemble(0x9D);
                   3036:        }
                   3037:     } else if (status == CC_AFTER_RO || status == CC_AFTER_ROX) {
                   3038:        int tmpr = get_typed_x86_register(map, DATA_X86_REGS);
                   3039:        assemble(0x9C);
                   3040:        compile_do_cc_test_reg(map);
1.1.1.2   root     3041:        /* pushfl; popl tmpr; andl $0xff,tmpr (mask out V flag which is cleared after rotates) */
                   3042:        assemble(0x9C); assemble(0x58 + tmpr);
                   3043:        assemble(0x81); assemble(0xC0 + tmpr + 8*4); assemble_ulong(0xFF);
1.1       root     3044:        assemble(0x9D);
                   3045:        /* adc $0, tmpr */
                   3046:        assemble(0x80); assemble(0xC0 + tmpr + 8*2); assemble(0);
1.1.1.3 ! root     3047:        compile_move_reg_to_mem_regoffs(-2, (uae_u32)&regflags, tmpr, sz_long);
1.1       root     3048:        if (status == CC_AFTER_ROX)
1.1.1.3 ! root     3049:            compile_move_reg_to_mem_regoffs(-2, 4 + (uae_u32)&regflags, tmpr, sz_long);
1.1       root     3050:     } else if (status != 0) {
                   3051:        assert((status & CC_TEST_REG) == 0);
                   3052:        assert (status == (CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_X_FROM_86C | CC_V_FROM_86V)
                   3053:                || status == (CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V)
                   3054:                || status == CC_C_FROM_86C);
1.1.1.3 ! root     3055: 
1.1       root     3056:        if ((status & CC_X_FROM_86C) == 0)
                   3057:            live_at_end &= ~CC68K_X;
1.1.1.3 ! root     3058: 
        !          3059:        if (status == CC_C_FROM_86C && (live_at_end & CC68K_C) != 0)
1.1       root     3060:            fprintf(stderr, "Shouldn't be needing C here!\n");
                   3061:        else if (live_at_end) {
                   3062:            if ((live_at_end & CC68K_X) == 0)
                   3063:                status &= ~CC_X_FROM_86C;
                   3064: 
                   3065:            if (live_at_end) {
1.1.1.2   root     3066:                if ((status & CC_X_FROM_86C) != 0 && live_at_end == CC68K_X) {
                   3067:                    /* SETC regflags + 4 */
                   3068:                    assemble(0x0F); assemble(0x92);
1.1.1.3 ! root     3069:                    assemble(0x05); assemble_long(4 + (uae_u32)&regflags);
1.1.1.2   root     3070:                } else {
                   3071:                    int tmpr = get_free_x86_register(map, ALL_X86_REGS);
                   3072:                    /* pushfl; popl tmpr; movl tempr, regflags */
                   3073:                    assemble(0x9C); assemble(0x58+tmpr);
1.1.1.3 ! root     3074:                    compile_move_reg_to_mem_regoffs(-2, (uae_u32)&regflags, tmpr, sz_long);
        !          3075: 
1.1.1.2   root     3076:                    if (status & CC_X_FROM_86C) {
1.1.1.3 ! root     3077:                        compile_move_reg_to_mem_regoffs(-2, 4 + (uae_u32)&regflags, tmpr, sz_word);
1.1.1.2   root     3078:                    }
1.1       root     3079:                }
                   3080:            }
                   3081:        }
                   3082:     }
                   3083: 
                   3084:     all_ok:
                   3085:     return status_for_user;
                   3086: }
1.1.1.2   root     3087: 
1.1       root     3088: static char *compile_condbranch(struct register_mapping *map, int iip,
                   3089:                                int new_cc_status)
                   3090: {
                   3091:     int cc = insn_info[iip].dp->cc;
1.1.1.2   root     3092:     int flagsused = cc_flagmask_68k(cc);
1.1       root     3093:     int flagsneeded = 0;
                   3094:     char *undo_pointer = compile_here();
                   3095: 
                   3096:     if (flagsused & CC68K_C)
                   3097:        flagsneeded |= CC_C_FROM_86C;
                   3098:     if (flagsused & CC68K_Z)
                   3099:        flagsneeded |= CC_Z_FROM_86Z;
                   3100:     if (flagsused & CC68K_N)
                   3101:        flagsneeded |= CC_N_FROM_86N;
                   3102:     if (flagsused & CC68K_V)
                   3103:        flagsneeded |= CC_V_FROM_86V;
                   3104: 
1.1.1.2   root     3105:     if (flagsneeded == 0)
                   3106:        /* Fine */;
                   3107:     else if (new_cc_status == CC_SAHF) {
1.1       root     3108:        int tmpr = get_free_x86_register(map, ALL_X86_REGS);
1.1.1.3 ! root     3109:        compile_move_reg_from_mem_regoffs(tmpr, -2, (uae_u32)&regflags, sz_long);
1.1       root     3110:        assemble(0x66); assemble(0x50+tmpr); assemble(0x66); assemble(0x9D);
                   3111:        new_cc_status = CC_C_FROM_86C|CC_Z_FROM_86Z|CC_N_FROM_86N|CC_V_FROM_86V;
                   3112:     } else if (new_cc_status == CC_TEST_CONST) {
                   3113:        int n,z;
                   3114:        switch(cc_size) {
1.1.1.3 ! root     3115:         case sz_byte: n = ((uae_s8)cc_offset) < 0; z = ((uae_s8)cc_offset) == 0; break;
        !          3116:         case sz_word: n = ((uae_s16)cc_offset) < 0; z = ((uae_s16)cc_offset) == 0; break;
        !          3117:         case sz_long: n = ((uae_s32)cc_offset) < 0; z = ((uae_s32)cc_offset) == 0; break;
1.1       root     3118:        }
                   3119: #define Bcc_TRUE 0
                   3120: #define Bcc_FALSE 1
                   3121:        flagsneeded = 0;
                   3122:        new_cc_status = 0;
                   3123:        switch (cc) {
                   3124:         case 2: cc = !z ? Bcc_TRUE : Bcc_FALSE; break; /* !CFLG && !ZFLG */
                   3125:         case 3: cc = z ? Bcc_TRUE : Bcc_FALSE; break; /* CFLG || ZFLG */
                   3126:         case 4: cc = Bcc_TRUE; break; /* !CFLG */
                   3127:         case 5: cc = Bcc_FALSE; break; /* CFLG */
                   3128:         case 6: cc = !z ? Bcc_TRUE : Bcc_FALSE; break; /* !ZFLG */
                   3129:         case 7: cc = z ? Bcc_TRUE : Bcc_FALSE; break; /* ZFLG */
                   3130:         case 8: cc = Bcc_TRUE; break; /* !VFLG */
                   3131:         case 9: cc = Bcc_FALSE; break; /* VFLG */
                   3132:         case 10:cc = !n ? Bcc_TRUE : Bcc_FALSE; break; /* !NFLG */
                   3133:         case 11:cc = n ? Bcc_TRUE : Bcc_FALSE; break; /* NFLG */
                   3134:         case 12:cc = !n ? Bcc_TRUE : Bcc_FALSE; break; /* NFLG == VFLG */
                   3135:         case 13:cc = n ? Bcc_TRUE : Bcc_FALSE; break; /* NFLG != VFLG */
                   3136:         case 14:cc = !n && !z ? Bcc_TRUE : Bcc_FALSE; break; /* !ZFLG && (NFLG == VFLG) */
                   3137:         case 15:cc = n || z ? Bcc_TRUE : Bcc_FALSE; break; /* ZFLG || (NFLG != VFLG) */
                   3138:        }
                   3139:     } else if (new_cc_status == CC_Z_FROM_86C) {
                   3140:        if (cc == 6 || cc == 7) {
                   3141:            cc = (cc - 2) ^ 1;
                   3142:            /* Fake... */
                   3143:            flagsneeded = new_cc_status = CC_C_FROM_86C;
                   3144:        } else if (cc != 0 && cc != 1)
                   3145:            printf("Groan!\n");
                   3146:     }
1.1.1.3 ! root     3147: 
1.1       root     3148:     if (cc == 1)
                   3149:        return NULL;
1.1.1.3 ! root     3150: 
1.1       root     3151:     if ((flagsneeded & new_cc_status) == flagsneeded) {
                   3152:        char *result;
                   3153:        /* We can generate a simple branch */
                   3154:        if (cc == 0)
                   3155:            assemble(0xE9);
                   3156:        else
                   3157:            assemble(0x0F);
                   3158:        switch(cc) {
                   3159:         case 2: assemble(0x87); break;          /* HI */
                   3160:         case 3: assemble(0x86); break;          /* LS */
                   3161:         case 4: assemble(0x83); break;          /* CC */
                   3162:         case 5: assemble(0x82); break;          /* CS */
                   3163:         case 6: assemble(0x85); break;          /* NE */
                   3164:         case 7: assemble(0x84); break;          /* EQ */
                   3165:         case 8: assemble(0x81); break;          /* VC */
                   3166:         case 9: assemble(0x80); break;          /* VS */
                   3167:         case 10:assemble(0x89); break;          /* PL */
                   3168:         case 11:assemble(0x88); break;          /* MI */
                   3169:         case 12:assemble(0x8D); break;          /* GE */
                   3170:         case 13:assemble(0x8C); break;          /* LT */
                   3171:         case 14:assemble(0x8F); break;          /* GT */
                   3172:         case 15:assemble(0x8E); break;          /* LE */
                   3173:        }
                   3174:        result = compile_here();
                   3175:        assemble_ulong(0);
                   3176:        return result;
                   3177:     }
                   3178:     printf("Uhhuh.\n");
                   3179:     return NULL;
                   3180: }
                   3181: 
1.1.1.3 ! root     3182: static void compile_handle_bcc(struct register_mapping *map, int iip,
1.1       root     3183:                               int new_cc_status)
                   3184: {
                   3185:     insn_info[iip].compiled_fillin = compile_condbranch(map, iip, new_cc_status);
                   3186: }
                   3187: 
1.1.1.3 ! root     3188: static void compile_handle_dbcc(struct register_mapping *map, int iip,
1.1       root     3189:                                int new_cc_status, int dreg)
                   3190: {
                   3191:     char *fillin1 = compile_condbranch(map, iip, new_cc_status);
1.1.1.3 ! root     3192: 
1.1       root     3193:     /* subw $1,dreg; jnc ... */
                   3194:     assemble(0x66); assemble(0x83); assemble(0x05 + 5*8);
1.1.1.2   root     3195:     assemble_long(regs.regs + dreg);
1.1       root     3196:     assemble(1);
                   3197:     assemble(0x0F); assemble(0x83);
                   3198:     insn_info[iip].compiled_fillin = compile_here();
                   3199:     assemble_ulong(0);
                   3200:     if (fillin1 != NULL) {
                   3201:        char *oldp = compile_here();
                   3202:        compile_org(fillin1);
                   3203:        assemble_ulong(oldp - (fillin1+4));
                   3204:        compile_org(oldp);
                   3205:     }
                   3206: }
                   3207: 
1.1.1.2   root     3208: static void handle_bit_insns(struct register_mapping *map, struct ea_info *eainf,
                   3209:                             int eaino_s, int eaino_d, instrmnem optype)
1.1       root     3210: {
1.1.1.3 ! root     3211:     struct ea_info *srcea = eainf + eaino_s, *dstea = eainf + eaino_d;
1.1       root     3212:     int code = (optype == i_BTST ? 0
                   3213:                : optype == i_BSET ? 1
                   3214:                : optype == i_BCLR ? 2
                   3215:                : /* optype == i_BCHG */ 3);
                   3216: 
1.1.1.2   root     3217:     compile_fetchea(map, eainf, eaino_s, 5);
                   3218:     compile_fetchea(map, eainf, eaino_d, 3);
                   3219: 
                   3220:     if (srcea->data_reg != -2) {
                   3221:        compile_force_byteorder(map, srcea->data_reg, BO_NORMAL, 0);
                   3222:        remove_x86r_from_cache(map, srcea->data_reg, 0);
1.1       root     3223:        /* andl $something,srcreg */
1.1.1.2   root     3224:        assemble(0x83); assemble(0xC0 + 4*8 + srcea->data_reg);
1.1       root     3225:        if (dstea->size == sz_byte)
                   3226:            assemble(7);
                   3227:        else
                   3228:            assemble(31);
                   3229:     } else
                   3230:        if (dstea->size == sz_byte)
1.1.1.2   root     3231:            srcea->data_const_off &= 7;
1.1       root     3232:        else
1.1.1.2   root     3233:            srcea->data_const_off &= 31;
1.1       root     3234: 
                   3235:     /* Areg isn't possible here */
                   3236:     if (dstea->mode == Dreg && dstea->data_reg == -1) {
1.1.1.2   root     3237:        if (srcea->data_reg == -2) {
1.1       root     3238:            assemble(0x0F); assemble(0xBA); assemble(5 + 8*(4 + code));
1.1.1.2   root     3239:            assemble_long(regs.regs + dstea->reg);
                   3240:            assemble(srcea->data_const_off);
1.1       root     3241:        } else {
                   3242:            assemble(0x0F); assemble(0xA3 + 8*code);
1.1.1.2   root     3243:            assemble(5 + srcea->data_reg*8);
                   3244:            assemble_long(regs.regs + dstea->reg);
1.1       root     3245:        }
                   3246:     } else if (dstea->data_reg >= 0) {
                   3247:        compile_force_byteorder(map, dstea->data_reg, BO_NORMAL, 0);
1.1.1.2   root     3248:        if (srcea->data_reg == -2) {
1.1       root     3249:            assemble(0x0F); assemble(0xBA); assemble(0xC0 + dstea->data_reg + 8*(4 + code));
1.1.1.2   root     3250:            assemble(srcea->data_const_off);
1.1       root     3251:        } else {
                   3252:            assemble(0x0F); assemble(0xA3 + 8*code);
1.1.1.2   root     3253:            assemble(0xC0 + dstea->data_reg + srcea->data_reg*8);
1.1       root     3254:        }
                   3255:        if (optype != i_BTST)
                   3256:            map->x86_dirty[dstea->data_reg] = 1;
                   3257:     } else {
                   3258:        int addr_code = dstea->address_reg == -2 ? 5 : dstea->address_reg + 0x80;
1.1.1.2   root     3259:        compile_force_byteorder(map, dstea->address_reg, BO_NORMAL, 0);
1.1       root     3260:        /* We have an address in memory */
                   3261:        if (dstea->data_reg != -1)
                   3262:            printf("Things don't look good in handle_bit_insns\n");
1.1.1.2   root     3263:        if (srcea->data_reg == -2) {
1.1.1.3 ! root     3264:            assemble(0x0F); assemble(0xBA);
1.1       root     3265:            assemble(addr_code + 8*(4 + code));
                   3266:            assemble_long(address_space + dstea->addr_const_off);
1.1.1.2   root     3267:            assemble(srcea->data_const_off);
1.1       root     3268:        } else {
                   3269:            assemble(0x0F); assemble(0xA3 + 8*code);
1.1.1.2   root     3270:            assemble(addr_code + srcea->data_reg*8);
1.1       root     3271:            assemble_long(address_space + dstea->addr_const_off);
                   3272:        }
1.1.1.3 ! root     3273: 
1.1       root     3274:     }
                   3275:     cc_status = CC_Z_FROM_86C;
                   3276: }
                   3277: 
                   3278: static int do_rotshi = 1;
                   3279: 
1.1.1.3 ! root     3280: static void handle_rotshi(struct register_mapping *map, int iip,
        !          3281:                          uae_u8 *realpc, uaecptr current_addr, struct pid_undo *pud)
1.1       root     3282: {
                   3283:     struct ea_info eai;
                   3284:     int amode_reg = insn_info[iip].dp->sreg;
                   3285:     int amode_mode = insn_info[iip].dp->smode;
                   3286:     wordsizes size = insn_info[iip].dp->size;
                   3287:     int shiftcount;
                   3288:     int mnemo = insn_info[iip].dp->mnemo;
                   3289:     int shiftcode;
1.1.1.2   root     3290:     int locked_eax_for_sahf = 0;
1.1.1.3 ! root     3291: 
1.1       root     3292:     switch(mnemo) {
                   3293:      case i_ASLW: shiftcount = 1; mnemo = i_ASL; break;
                   3294:      case i_ASRW: shiftcount = 1; mnemo = i_ASR; break;
                   3295:      case i_LSLW: shiftcount = 1; mnemo = i_LSL; break;
                   3296:      case i_LSRW: shiftcount = 1; mnemo = i_LSR; break;
                   3297:      case i_ROLW: shiftcount = 1; mnemo = i_ROL; break;
                   3298:      case i_RORW: shiftcount = 1; mnemo = i_ROR; break;
                   3299:      case i_ROXLW:shiftcount = 1; mnemo = i_ROXL;break;
                   3300:      case i_ROXRW:shiftcount = 1; mnemo = i_ROXR;break;
                   3301:      default:
                   3302:        amode_reg = insn_info[iip].dp->dreg;
                   3303:        amode_mode = insn_info[iip].dp->dmode;
                   3304:        shiftcount = insn_info[iip].dp->sreg;
                   3305:        break;
                   3306:     }
1.1.1.2   root     3307:     if ((insn_info[iip].flags_live_at_end & CC68K_V) != 0) {
                   3308:        if (mnemo == i_ASL) {
1.1       root     3309:            generate_exit(map, insn_info[iip].address);
1.1.1.2   root     3310:            printf("Can't handle this shift\n");
1.1       root     3311:            return;
1.1.1.2   root     3312:        } else if (mnemo == i_ASR || mnemo == i_LSR || mnemo == i_LSL) {
                   3313:            remove_x86r_from_cache(map, r_EAX, 1);
                   3314:            locked_eax_for_sahf = 1;
1.1.1.3 ! root     3315:            lock_reg(map, r_EAX, 2);
1.1       root     3316:        }
1.1.1.3 ! root     3317: 
1.1       root     3318:     }
                   3319:     if (mnemo == i_ROXR || mnemo == i_ROXL) {
                   3320:        remove_x86r_from_cache(map, r_EAX, 1);
1.1.1.2   root     3321:        lock_reg(map, r_EAX, 2);
1.1.1.3 ! root     3322:        compile_move_reg_from_mem_regoffs(r_AH, -2, 4 + (uae_u32)&regflags, sz_byte);
1.1       root     3323:     }
1.1.1.2   root     3324:     compile_prepare_undo(map, amode_mode, amode_reg, pud);
1.1       root     3325:     compile_prepareea(map, amode_mode, amode_reg, size,
                   3326:                      &realpc, current_addr,
1.1.1.2   root     3327:                      &eai, 0, EA_LOAD|EA_STORE|EA_MODIFY, 1);
1.1.1.3 ! root     3328: 
1.1.1.2   root     3329:     generate_possible_exit(map, &eai, iip, pud);
1.1.1.3 ! root     3330: 
1.1.1.2   root     3331:     compile_fetchea(map, &eai, 0, 1);
                   3332:     compile_force_byteorder(map, eai.data_reg, BO_NORMAL, 0);
1.1       root     3333: 
                   3334:     switch (mnemo) {
                   3335:      case i_ASL:
                   3336:        shiftcode = 4; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
                   3337:        break;
                   3338:      case i_LSL:
                   3339:        shiftcode = 4; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
1.1.1.3 ! root     3340:        break;
1.1       root     3341:      case i_LSR:
                   3342:        shiftcode = 5; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
                   3343:        break;
                   3344:      case i_ASR:
                   3345:        shiftcode = 7; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
                   3346:        break;
                   3347:      case i_ROR:
                   3348:        shiftcode = 1; cc_status = CC_AFTER_RO;
                   3349:        break;
                   3350:      case i_ROL:
                   3351:        shiftcode = 0; cc_status = CC_AFTER_RO;
                   3352:        break;
                   3353:      case i_ROXL:
1.1.1.2   root     3354:        shiftcode = 2; assemble(0x9E); /* SAHF */ cc_status = CC_AFTER_ROX; compile_unlock_reg(map, r_EAX);
1.1       root     3355:        break;
                   3356:      case i_ROXR:
1.1.1.2   root     3357:        shiftcode = 3; assemble(0x9E); /* SAHF */ cc_status = CC_AFTER_ROX; compile_unlock_reg(map, r_EAX);
1.1       root     3358:        break;
                   3359:     }
                   3360: 
                   3361:     if (size == sz_word)
                   3362:        assemble(0x66);
                   3363:     assemble((shiftcount == 1 ? 0xD0 : 0xC0) + (size == sz_byte ? 0 : 1));
1.1.1.2   root     3364:     assemble(shiftcode*8+0xC0 + eai.data_reg);
1.1       root     3365:     if (shiftcount != 1) assemble(shiftcount);
1.1.1.2   root     3366:     cc_offset = 0; cc_size = size; cc_reg = eai.data_reg;
                   3367: 
                   3368:     if (locked_eax_for_sahf) {
                   3369:        /* The trick here is that the overflow flag isn't put into AH in SAHF */
                   3370:        assemble(0x9E);
                   3371:        assemble(0x0B); assemble(9*1 + 0xC0);
                   3372:        assemble(0x9F);
                   3373:        compile_unlock_reg(map, r_EAX);
                   3374:     }
                   3375:     compile_note_modify(map, &eai, 0);
                   3376: }
                   3377: 
1.1.1.3 ! root     3378: static void handle_rotshi_variable(struct register_mapping *map, int iip,
        !          3379:                                   uae_u8 *realpc, uaecptr current_addr,
1.1.1.2   root     3380:                                   struct pid_undo *pud)
                   3381: {
                   3382:     struct ea_info eais, eaid;
                   3383:     int mnemo = insn_info[iip].dp->mnemo;
                   3384:     int shiftcode;
                   3385:     char *tmp1, *tmp2;
                   3386:     int locked_eax_for_sahf = 0;
                   3387: 
                   3388:     remove_x86r_from_cache(map, r_ECX, 1);
                   3389:     lock_reg(map, r_ECX, 2);
                   3390: 
                   3391:     if ((insn_info[iip].flags_live_at_end & CC68K_V) != 0) {
                   3392:        if (mnemo == i_ASL) {
                   3393:            generate_exit(map, insn_info[iip].address);
                   3394:            printf("Can't handle this shift (var)\n");
                   3395:            return;
                   3396:        } else if (mnemo == i_ASR || mnemo == i_LSR || mnemo == i_LSL) {
                   3397:            remove_x86r_from_cache(map, r_EAX, 1);
                   3398:            locked_eax_for_sahf = 1;
1.1.1.3 ! root     3399:            lock_reg(map, r_EAX, 2);
1.1.1.2   root     3400:        }
1.1.1.3 ! root     3401: 
1.1.1.2   root     3402:     }
                   3403:     if (mnemo == i_ROXR || mnemo == i_ROXL) {
                   3404:        remove_x86r_from_cache(map, r_EAX, 1);
                   3405:        lock_reg(map, r_EAX, 2);
1.1.1.3 ! root     3406:        compile_move_reg_from_mem_regoffs(r_AH, -2, 4 + (uae_u32)&regflags,
1.1.1.2   root     3407:                                          sz_byte);
                   3408:     }
                   3409:     /* Both src and dest are Dreg modes */
                   3410:     compile_prepareea(map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg,
                   3411:                      sz_long, &realpc, current_addr,
                   3412:                      &eais, 0, EA_LOAD, 1);
                   3413:     compile_prepareea(map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg,
                   3414:                      insn_info[iip].dp->size, &realpc, current_addr,
                   3415:                      &eaid, 0, EA_LOAD|EA_STORE|EA_MODIFY, 1);
1.1.1.3 ! root     3416: 
1.1.1.2   root     3417:     compile_fetchea(map, &eais, 0, 1);
                   3418:     compile_fetchea(map, &eaid, 1, 1);
                   3419:     compile_force_byteorder(map, eais.data_reg, BO_NORMAL, 0);
                   3420:     compile_force_byteorder(map, eaid.data_reg, BO_NORMAL, 0);
                   3421:     compile_move_reg_reg(r_ECX, eais.data_reg, sz_long);
                   3422:     /* Test against zero, and test bit 6. If 1 <= count <= 31, we can do the
                   3423:      * operation, otherwise, we have to exit */
                   3424:     assemble(0xF6); assemble(0xC0 + r_ECX); assemble(0x1F);
                   3425:     assemble(0x74); assemble(9);
                   3426:     assemble(0xF6); assemble(0xC0 + r_ECX); assemble(0x20);
                   3427: 
                   3428:     assemble(0x0F); assemble(0x85); tmp1 = compile_here(); assemble_ulong(0);
                   3429:     generate_exit(map, insn_info[iip].address);
                   3430:     tmp2 = compile_here(); compile_org (tmp1); assemble_ulong((tmp2-tmp1) + 4); compile_org(tmp2);
                   3431: 
                   3432:     switch (mnemo) {
                   3433:      case i_ASL:
                   3434:        shiftcode = 4; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
                   3435:        break;
                   3436:      case i_LSL:
                   3437:        shiftcode = 4; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
1.1.1.3 ! root     3438:        break;
1.1.1.2   root     3439:      case i_LSR:
                   3440:        shiftcode = 5; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
                   3441:        break;
                   3442:      case i_ASR:
                   3443:        shiftcode = 7; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
                   3444:        break;
                   3445:      case i_ROR:
                   3446:        shiftcode = 1; cc_status = CC_AFTER_RO;
                   3447:        break;
                   3448:      case i_ROL:
                   3449:        shiftcode = 0; cc_status = CC_AFTER_RO;
                   3450:        break;
                   3451:      case i_ROXL:
                   3452:        shiftcode = 2; assemble(0x9E); /* SAHF */ cc_status = CC_AFTER_ROX; compile_unlock_reg(map, r_EAX);
                   3453:        break;
                   3454:      case i_ROXR:
                   3455:        shiftcode = 3; assemble(0x9E); /* SAHF */ cc_status = CC_AFTER_ROX; compile_unlock_reg(map, r_EAX);
                   3456:        break;
                   3457:     }
                   3458: 
                   3459:     if (insn_info[iip].dp->size == sz_word)
                   3460:        assemble(0x66);
                   3461:     assemble(0xD2 + (insn_info[iip].dp->size == sz_byte ? 0 : 1));
                   3462:     assemble(shiftcode*8+0xC0 + eaid.data_reg);
                   3463:     cc_offset = 0; cc_size = insn_info[iip].dp->size; cc_reg = eaid.data_reg;
                   3464: 
                   3465:     if (locked_eax_for_sahf) {
                   3466:        /* The trick here is that the overflow flag isn't put into AH in SAHF */
                   3467:        assemble(0x9E);
                   3468:        assemble(0x0B); assemble(9*1 + 0xC0);
                   3469:        assemble(0x9F);
                   3470:        compile_unlock_reg(map, r_EAX);
                   3471:     }
                   3472:     compile_note_modify(map, &eaid, 0);
                   3473:     compile_unlock_reg(map, r_ECX);
1.1       root     3474: }
                   3475: 
1.1.1.3 ! root     3476: static uae_u32 testmask = 0xF80000, testval = 0xF80000;
1.1       root     3477: 
                   3478: static int m68k_compile_block(struct hash_block *hb)
                   3479: {
                   3480:     int movem_extra = 0;
                   3481:     int last_iip = m68k_scan_block(hb, &movem_extra);
                   3482:     struct register_mapping map;
                   3483:     int i, iip, szflag;
1.1.1.3 ! root     3484:     uae_u8 *realpc_start = NULL;
1.1       root     3485:     struct bb_info *current_bb;
                   3486:     int cc_status_for_bcc = CC_SAHF;
1.1.1.2   root     3487:     struct insn_reg_needs reg_needs_init;
1.1.1.3 ! root     3488: 
1.1       root     3489:     cesp = 0;
                   3490: 
                   3491:     if (n_compiled > n_max_comp)
                   3492:        return 1;
                   3493:     else if (n_compiled++ == n_max_comp)
                   3494:        printf("X\n");
                   3495: 
                   3496:     cc_status = 0; compile_failure = 0;
                   3497: 
                   3498:     /* Kickstart ROM address? */
                   3499:     if ((hb->he_first->addr & 0xF80000) != 0xF80000
                   3500:        && 0 && !patched_syscalls)
                   3501:        return 1;
                   3502: 
1.1.1.2   root     3503:     exits_necessary = ((hb->he_first->addr & 0xF80000) == 0xF80000 || !USER_PROGRAMS_BEHAVE);
1.1.1.3 ! root     3504: 
1.1       root     3505:     if (alloc_code (hb, last_iip + movem_extra) == NULL) {
                   3506:        hb->allocfailed = 1;
                   3507:        return 0;
                   3508:     }
                   3509:     compile_org(hb->compile_start);
                   3510:     compile_last_addr = (char *)hb->compile_start + hb->alloclen;
1.1.1.3 ! root     3511: 
1.1       root     3512:     /* m68k_scan_block() will leave this all set up */
                   3513:     current_bb = bb_stack;
1.1.1.3 ! root     3514: 
1.1       root     3515:     for (i = 0; i < 8; i++) {
                   3516:        map.dreg_map[i] = map.areg_map[i] = -1;
                   3517:        map.x86_dirty[i] = 0;
                   3518:        map.x86_cache_reg[i] = -1;
                   3519:        map.x86_cr_type[i] = 0;
                   3520:        map.x86_const_offset[i] = 0;
                   3521:        map.x86_verified[i] = 0;
                   3522:        map.x86_byteorder[i] = BO_NORMAL;
                   3523:     }
1.1.1.3 ! root     3524: 
1.1.1.2   root     3525:     reg_needs_init.checkpoint_no = 0;
                   3526:     for (i = 0; i < 8; i++) {
                   3527:        reg_needs_init.dreg_needed[i] = reg_needs_init.areg_needed[i] = -1;
                   3528:        reg_needs_init.dreg_mask[i] = reg_needs_init.areg_mask[i] = ALL_X86_REGS;
                   3529:     }
1.1.1.3 ! root     3530: 
1.1       root     3531:     for (iip = 0; iip < last_iip && !compile_failure; iip++) {
1.1.1.3 ! root     3532:        uae_u8 *realpc;
1.1.1.2   root     3533:        struct ea_info eainfo[8];
1.1.1.3 ! root     3534:        uaecptr current_addr;
1.1       root     3535:        struct pid_undo pub;
1.1.1.2   root     3536:        struct insn_reg_needs this_reg_needs = reg_needs_init;
                   3537: 
1.1       root     3538:        /* Set up locks for a new insn. We don't bother to clear this
                   3539:         * properly after compiling one insn. */
1.1.1.2   root     3540:        for (i = 0; i < 8; i++) {
                   3541:            map.x86_users[i] = i == r_ESP ? 1 : 0;
                   3542:            map.x86_locked[i] = i == r_ESP ? 2 : 0;
                   3543:        }
1.1       root     3544: 
                   3545:        pub.used = 0;
                   3546:        current_addr = insn_info[iip].address + 2;
                   3547: 
                   3548:        if (iip == current_bb->first_iip) {
                   3549:            sync_reg_cache(&map, 1);
                   3550:            if (!quiet_compile)
                   3551:                printf("Compiling %08lx\n", current_bb->h->addr);
1.1.1.2   root     3552: 
1.1       root     3553:            realpc_start = get_real_address(current_bb->h->addr);
                   3554:            current_bb->h->execute = (code_execfunc)compile_here();
1.1.1.3 ! root     3555:            current_bb->h->matchword = *(uae_u32 *)realpc_start;
1.1       root     3556:            cc_status_for_bcc = CC_SAHF;
                   3557:        }
                   3558: 
1.1.1.3 ! root     3559:        realpc = realpc_start + (current_addr - current_bb->h->addr);
1.1       root     3560: 
1.1.1.3 ! root     3561:        insn_info[iip].compiled_jumpaddr = compile_here();
1.1       root     3562:        insn_info[iip].compiled_fillin = NULL;
1.1.1.3 ! root     3563: 
1.1       root     3564:        if (insn_info[iip].jump_target) {
                   3565:            if (cesp == CE_STACK_SIZE) {
                   3566:                generate_exit(NULL, insn_info[iip].address);
                   3567:                compile_failure = 1;
                   3568:            } else {
                   3569:                assemble(0xFE); assemble(0x05 + 8*1); assemble_long(&nr_bbs_to_run);
                   3570:                assemble(0x0F); assemble(0x84); /* JE finish */
                   3571:                compile_exit_stack[cesp].noflush = 1;
                   3572:                compile_exit_stack[cesp].address = current_bb->h;
                   3573:                compile_exit_stack[cesp].jmpoffs = compile_here();
                   3574:                assemble_ulong(0);
                   3575:                cesp++;
                   3576:            }
                   3577:        }
                   3578:        /*
                   3579:         * This will sort out all insns we can't compile, including
1.1.1.2   root     3580:         * jumps out of this block */
1.1       root     3581:        if (insn_info[iip].stop_translation == 1) {
                   3582:            generate_exit(&map, insn_info[iip].address);
                   3583:            cc_status = 0;
                   3584:        } else switch (insn_info[iip].dp->mnemo) {
1.1.1.2   root     3585:         case i_NOP:
                   3586:            cc_status = 0;
                   3587:            if (!quiet_compile)
                   3588:                printf("Compiling a NOP\n");
                   3589:            break;
                   3590: 
                   3591:         case i_RTS:
                   3592:            sync_reg_cache(&map, 1);
                   3593:            lock_reg(&map, r_ECX, 2);
                   3594:            lock_reg(&map, r_EBX, 2);
                   3595:            {
                   3596:                char *tmp1, *tmp2, *tmp3;
                   3597: 
                   3598:                /* fetch (A7) */
                   3599:                assemble(0x8B); assemble(0x5 + r_EBX*8); assemble_long(regs.regs + 15);
                   3600:                assemble(0x8B); assemble(0x80 + 9*r_EBX); assemble_long(address_space);
                   3601:                assemble(0x0F); /* bswapl x86r */
                   3602:                assemble(0xC8 + r_EBX);
                   3603:                /* fetch jsr_num */
                   3604:                assemble(0x8B); assemble(0x5 + r_ECX*8); assemble_long(&jsr_num);
                   3605:                assemble(0x09); assemble(0xC0 + 9*r_ECX);
                   3606:                assemble(0x0F); assemble(0x84); tmp1 = compile_here(); assemble_ulong(0);
                   3607:                assemble(0xFF); assemble(1*8 + 0xC0 + r_ECX);
                   3608:                /* cmpl %ebx,disp32(,%ecx,4) */
                   3609:                assemble(0x39); assemble(0x04 + 8*r_EBX); assemble(0x8d);
                   3610:                assemble_long(jsr_rets);
                   3611:                assemble(0x0F); assemble(0x85); tmp2 = compile_here(); assemble_ulong(0);
                   3612:                /* movl disp32(,%ecx,4),%ebx */
                   3613:                assemble(0x8B); assemble(0x04 + 8*r_EBX); assemble(0x8d);
                   3614:                assemble_long(jsr_hash);
                   3615:                /* movl execute(%ebx), %ebx */
                   3616:                assemble(0x8B); assemble(0x040 + 9*r_EBX); assemble((int)&((struct hash_entry *)0)->execute);
                   3617:                assemble(0x09); assemble(0xC0 + 9*r_EBX);
                   3618:                assemble(0x0F); assemble(0x85); tmp3 = compile_here(); assemble_ulong(0);
                   3619:                compile_org(tmp1); assemble_ulong(tmp3 - tmp1);
                   3620:                compile_org(tmp2); assemble_ulong(tmp3 - tmp2);
                   3621:                compile_org(tmp3 + 4);
                   3622:                generate_exit(&map, insn_info[iip].address);
                   3623:                tmp1 = compile_here();
                   3624:                compile_org(tmp3); assemble_ulong((tmp1-tmp3)-4);
                   3625:                compile_org(tmp1);
                   3626:                assemble(0x89); assemble(0x5 + r_ECX*8); assemble_long(&jsr_num);
                   3627:                assemble(0x83); assemble(0x05 + 5*8); assemble_long(regs.regs + 15); assemble(-4);
                   3628:                /* Off we go */
1.1.1.3 ! root     3629:                assemble(0xFF); assemble(4*8 + 0xC0 + r_EBX);
1.1.1.2   root     3630:            }
                   3631:            break;
1.1.1.3 ! root     3632: 
1.1.1.2   root     3633:         case i_JMP:
                   3634:            sync_reg_cache(&map, 1);
                   3635:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     3636:                              insn_info[iip].dp->sreg,
1.1.1.2   root     3637:                              insn_info[iip].dp->size, &realpc, current_addr,
                   3638:                              eainfo, 0, EA_LOAD, 1);
                   3639:            {
                   3640:                char *tmp1, *tmp2, *tmp3;
                   3641: 
                   3642:                struct hash_entry *tmph;
                   3643:                if (eainfo[0].address_reg != -2 || (tmph = get_hash_for_func(eainfo[0].addr_const_off, 1)) == 0) {
                   3644:                    if (eainfo[0].address_reg != -2 && !quiet_compile)
                   3645:                        printf("Can't compile indirect JMP\n");
                   3646:                    generate_exit(&map, insn_info[iip].address);
                   3647:                    break;
                   3648:                }
                   3649:                /* check whether the destination has compiled code */
                   3650:                assemble(0x8B); assemble(r_EBX*8 + 0x05); assemble_long(&(tmph->execute));
                   3651:                assemble(0x09); assemble(0xC0 + 9*r_EBX);
                   3652:                assemble(0x0F); assemble(0x85); tmp1 = compile_here(); assemble_ulong(0);
                   3653:                generate_exit(&map, insn_info[iip].address);
1.1.1.3 ! root     3654:                tmp2 = compile_here(); compile_org(tmp1);
1.1.1.2   root     3655:                assemble_ulong((tmp2 - tmp1) - 4);
                   3656:                compile_org(tmp2);
                   3657:                /* Off we go */
                   3658:                assemble(0xFF); assemble(4*8 + 0xC0 + r_EBX);
                   3659:            }
                   3660:            cc_status = 0;
                   3661:            break;
                   3662: 
                   3663:         case i_JSR:
                   3664:            sync_reg_cache(&map, 1);
                   3665:            lock_reg(&map, r_ECX, 2);
                   3666:            lock_reg(&map, r_EBX, 2);
                   3667:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     3668:                              insn_info[iip].dp->sreg,
1.1.1.2   root     3669:                              insn_info[iip].dp->size, &realpc, current_addr,
                   3670:                              eainfo, 0, EA_LOAD, 1);
                   3671:            {
                   3672:                char *tmp1, *tmp2, *tmp3;
                   3673: 
                   3674:                struct hash_entry *tmph;
                   3675:                if (eainfo[0].address_reg != -2 || (tmph = get_hash_for_func(eainfo[0].addr_const_off, 1)) == 0) {
                   3676:                    if (eainfo[0].address_reg != -2 && !quiet_compile)
                   3677:                        printf("Can't compile indirect JSR\n");
                   3678:                    generate_exit(&map, insn_info[iip].address);
                   3679:                    break;
                   3680:                }
                   3681:                assert(iip + 1 < last_iip);
                   3682:                assert(iip == current_bb->last_iip);
                   3683:                /* check whether the destination has compiled code */
                   3684:                assemble(0x8B); assemble(r_EBX*8 + 0x05); assemble_long(&(tmph->execute));
                   3685:                assemble(0x09); assemble(0xC0 + 9*r_EBX);
                   3686:                assemble(0x0F); assemble(0x84); tmp3 = compile_here(); assemble_ulong(0);
                   3687:                /* check for stack overflow */
                   3688:                assemble(0x8B); assemble(r_ECX*8 + 0x05); assemble_long(&jsr_num);
                   3689:                assemble(0xF7); assemble(0xC0+r_ECX); assemble_ulong(MAX_JSRS);
                   3690:                assemble(0x0F); assemble(0x84); tmp1 = compile_here(); assemble_ulong(0);
                   3691:                generate_exit(&map, insn_info[iip].address);
                   3692:                tmp2 = compile_here(); compile_org(tmp1); assemble_ulong((tmp2 - tmp1) - 4);
                   3693:                compile_org(tmp3); assemble_ulong(tmp1-tmp3);
                   3694:                compile_org(tmp2);
                   3695:                /* movl $something,disp32(,%ecx,4) */
1.1.1.3 ! root     3696:                assemble(0xC7); assemble(0x04); assemble(0x8d);
1.1.1.2   root     3697:                assemble_long(jsr_rets); assemble_ulong(insn_info[iip+1].address);
1.1.1.3 ! root     3698:                assemble(0xC7); assemble(0x04); assemble(0x8d);
1.1.1.2   root     3699:                assemble_long(jsr_hash); assemble_long((current_bb + 1)->h);
                   3700:                /* incl jsr_num */
                   3701:                assemble(0xFF); assemble(0x05); assemble_long(&jsr_num);
                   3702:                /* Put things on the 68k stack */
                   3703:                assemble(0x83); assemble(0x05 + 5*8); assemble_long(regs.regs + 15); assemble(4);
                   3704:                assemble(0x8B); assemble(r_ECX*8+ 0x05); assemble_long(regs.regs + 15);
1.1.1.3 ! root     3705:                assemble(0xC7); assemble(0x80 + r_ECX); assemble_long(address_space);
1.1.1.2   root     3706:                assemble_ulong_68k(insn_info[iip+1].address);
                   3707:                /* Off we go */
                   3708:                assemble(0xFF); assemble(4*8 + 0xC0 + r_EBX);
                   3709:            }
                   3710:            break;
                   3711: 
                   3712:         case i_BSR:
                   3713:            sync_reg_cache(&map, 1);
                   3714:            lock_reg(&map, r_ECX, 2);
                   3715:            lock_reg(&map, r_EBX, 2);
                   3716:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     3717:                              insn_info[iip].dp->sreg,
1.1.1.2   root     3718:                              insn_info[iip].dp->size, &realpc, current_addr,
                   3719:                              eainfo, 0, EA_LOAD, 1);
                   3720:            {
                   3721:                char *tmp1, *tmp2, *tmp3;
1.1.1.3 ! root     3722:                uaecptr dest = insn_info[iip].address + 2 + (uae_s32)eainfo[0].data_const_off;
1.1.1.2   root     3723:                struct hash_entry *tmph;
                   3724:                if ((tmph = get_hash_for_func(dest, 1)) == 0) {
                   3725:                    generate_exit(&map, insn_info[iip].address);
                   3726:                    break;
                   3727:                }
                   3728:                assert(iip + 1 < last_iip);
                   3729:                assert(iip == current_bb->last_iip);
                   3730: 
                   3731:                /* check whether the destination has compiled code */
                   3732:                assemble(0x8B); assemble(r_EBX*8 + 0x05); assemble_long(&(tmph->execute));
                   3733:                assemble(0x09); assemble(0xC0 + 9*r_EBX);
                   3734:                assemble(0x0F); assemble(0x84); tmp3 = compile_here(); assemble_ulong(0);
                   3735:                /* check for stack overflow */
                   3736:                assemble(0x8B); assemble(r_ECX*8 + 0x05); assemble_long(&jsr_num);
                   3737:                assemble(0xF7); assemble(0xC0+r_ECX); assemble_ulong(MAX_JSRS);
                   3738:                assemble(0x0F); assemble(0x84); tmp1 = compile_here(); assemble_ulong(0);
                   3739:                generate_exit(&map, insn_info[iip].address);
                   3740:                tmp2 = compile_here(); compile_org(tmp1); assemble_ulong((tmp2 - tmp1) - 4);
                   3741:                compile_org(tmp3); assemble_ulong(tmp1-tmp3);
                   3742:                compile_org(tmp2);
                   3743:                /* movl $something,disp32(,%ecx,4) */
1.1.1.3 ! root     3744:                assemble(0xC7); assemble(0x04); assemble(0x8d);
1.1.1.2   root     3745:                assemble_long(jsr_rets); assemble_ulong(insn_info[iip+1].address);
1.1.1.3 ! root     3746:                assemble(0xC7); assemble(0x04); assemble(0x8d);
1.1.1.2   root     3747:                assemble_long(jsr_hash); assemble_long((current_bb + 1)->h);
                   3748:                /* incl jsr_num */
                   3749:                assemble(0xFF); assemble(0x05); assemble_long(&jsr_num);
                   3750:                /* Put things on the 68k stack */
                   3751:                assemble(0x83); assemble(0x05 + 5*8); assemble_long(regs.regs + 15); assemble(4);
                   3752:                assemble(0x8B); assemble(r_ECX*8+ 0x05); assemble_long(regs.regs + 15);
1.1.1.3 ! root     3753:                assemble(0xC7); assemble(0x80 + r_ECX); assemble_long(address_space);
1.1.1.2   root     3754:                assemble_ulong_68k(insn_info[iip+1].address);
                   3755:                /* Off we go */
                   3756:                assemble(0xFF); assemble(4*8 + 0xC0 + r_EBX);
                   3757:            }
                   3758:            break;
1.1.1.3 ! root     3759: 
1.1       root     3760:         case i_Bcc:
                   3761:            sync_reg_cache(&map, 0);
                   3762:            compile_handle_bcc(&map, iip, cc_status_for_bcc);
                   3763:            cc_status = 0;
                   3764:            break;
                   3765: 
                   3766:         case i_DBcc:
                   3767:            sync_reg_cache(&map, 0);
                   3768:            remove_x86r_from_cache(&map, map.dreg_map[insn_info[iip].dp->sreg], 1);
                   3769:            compile_handle_dbcc(&map, iip, cc_status_for_bcc,
                   3770:                                insn_info[iip].dp->sreg);
                   3771:            cc_status = 0;
                   3772:            break;
                   3773: #if 0
                   3774:         case i_Scc:
1.1.1.2   root     3775:            compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
1.1       root     3776:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     3777:                              insn_info[iip].dp->sreg,
1.1       root     3778:                              insn_info[iip].dp->size, &realpc, current_addr,
1.1.1.2   root     3779:                              eainfo, 0, EA_STORE, 1);
1.1       root     3780: 
                   3781:            generate_possible_exit(&map, eainfo, iip, &pub);
                   3782:            srcreg2 = get_;
1.1.1.2   root     3783:            compile_note_modify(&map, eainfo, 0);
1.1       root     3784: 
                   3785:            cc_status = 0;
                   3786:            break;
                   3787: #endif
                   3788:         case i_ADD:
                   3789:         case i_SUB:
                   3790:         case i_CMP:
                   3791:         case i_CMPM:
1.1.1.2   root     3792:            compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
                   3793:            compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
1.1       root     3794:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     3795:                              insn_info[iip].dp->sreg,
1.1       root     3796:                              insn_info[iip].dp->size, &realpc, current_addr,
1.1.1.2   root     3797:                              eainfo, 0, EA_LOAD, 1);
1.1       root     3798:            compile_prepareea(&map, insn_info[iip].dp->dmode,
1.1.1.3 ! root     3799:                              insn_info[iip].dp->dreg,
1.1       root     3800:                              insn_info[iip].dp->size, &realpc, current_addr,
1.1.1.3 ! root     3801:                              eainfo, 1,
        !          3802:                              (insn_info[iip].dp->mnemo == i_ADD || insn_info[iip].dp->mnemo == i_SUB
1.1.1.2   root     3803:                               ? EA_MODIFY | EA_LOAD | EA_STORE
                   3804:                               : EA_LOAD | EA_STORE), 1);
1.1       root     3805: 
                   3806:            generate_possible_exit(&map, eainfo, iip, &pub);
                   3807:            generate_possible_exit(&map, eainfo+1, iip, &pub);
1.1.1.3 ! root     3808: 
1.1.1.2   root     3809:            compile_loadeas(&map, eainfo, 0, 1, binop_alternatives, 0, 1);
1.1       root     3810: 
                   3811:            switch (insn_info[iip].dp->mnemo) {
1.1.1.2   root     3812:             case i_ADD: compile_eas(&map, eainfo, 0, 1, 0); break;
                   3813:             case i_SUB: compile_eas(&map, eainfo, 0, 1, 5); break;
                   3814:             case i_CMP: case i_CMPM: compile_eas(&map, eainfo, 0, 1, 7); break;
                   3815:            }
1.1.1.3 ! root     3816: 
1.1.1.2   root     3817:            if (insn_info[iip].dp->mnemo != i_CMP && insn_info[iip].dp->mnemo != i_CMPM)
                   3818:                compile_note_modify(&map, eainfo, 1);
1.1       root     3819:            switch (insn_info[iip].dp->mnemo) {
                   3820:             case i_ADD:
                   3821:             case i_SUB:
1.1.1.2   root     3822:                cc_status = CC_X_FROM_86C | CC_Z_FROM_86Z | CC_C_FROM_86C | CC_V_FROM_86V | CC_N_FROM_86N;
1.1       root     3823:                break;
                   3824:             case i_CMP:
                   3825:             case i_CMPM:
1.1.1.2   root     3826:                cc_status = CC_Z_FROM_86Z | CC_C_FROM_86C | CC_V_FROM_86V | CC_N_FROM_86N;
1.1       root     3827:                break;
                   3828:            }
                   3829:            break;
                   3830: 
                   3831:         case i_ADDX:
                   3832:         case i_SUBX:
1.1.1.2   root     3833:            compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
                   3834:            compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
1.1       root     3835:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     3836:                              insn_info[iip].dp->sreg,
1.1       root     3837:                              insn_info[iip].dp->size, &realpc, current_addr,
1.1.1.2   root     3838:                              eainfo, 0, EA_LOAD, 1);
1.1       root     3839:            compile_prepareea(&map, insn_info[iip].dp->dmode,
1.1.1.3 ! root     3840:                              insn_info[iip].dp->dreg,
1.1       root     3841:                              insn_info[iip].dp->size, &realpc, current_addr,
1.1.1.2   root     3842:                              eainfo, 1, EA_MODIFY | EA_LOAD | EA_STORE, 1);
1.1       root     3843: 
                   3844:            generate_possible_exit(&map, eainfo, iip, &pub);
                   3845:            generate_possible_exit(&map, eainfo+1, iip, &pub);
                   3846: 
1.1.1.2   root     3847:            compile_loadeas(&map, eainfo, 0, 1, binop_alternatives, 0, 1);
1.1       root     3848: 
1.1.1.2   root     3849:            /* bt $0, regflags+4 ; get carry */
1.1.1.3 ! root     3850:            assemble(0x0F); assemble(0xBA); assemble(0x5+4*8);
        !          3851:            assemble_ulong(4 + (uae_u32)&regflags); assemble(0);
1.1.1.2   root     3852: 
1.1       root     3853:            switch (insn_info[iip].dp->mnemo) {
1.1.1.2   root     3854:             case i_ADDX: compile_eas(&map, eainfo, 0, 1, 2); break;
                   3855:             case i_SUBX: compile_eas(&map, eainfo, 0, 1, 3); break;
1.1.1.3 ! root     3856:            }
1.1.1.2   root     3857:            compile_note_modify(&map, eainfo, 1);
                   3858: 
1.1       root     3859:            if (insn_info[iip].flags_live_at_end & CC68K_Z) {
                   3860:                /* Darn. */
                   3861:                int tmpr = get_free_x86_register(&map, ALL_X86_REGS);
                   3862:                /* pushfl; popl tmpr */
                   3863:                assemble(0x9C); assemble(0x58+tmpr);
                   3864:                /* Magic! */
                   3865:                /* andl tmpr, regflags; andl $~0x40,tmpr; orl tmpr, regflags */
                   3866:                assemble(0x21); assemble(0x05 + 8*tmpr); assemble_long(&regflags);
                   3867:                assemble(0x81); assemble(0xC0 + 8*4 + tmpr); assemble_ulong(~0x40);
                   3868:                assemble(0x09); assemble(0x05 + 8*tmpr); assemble_long(&regflags);
1.1.1.3 ! root     3869:                compile_move_reg_to_mem_regoffs(-2, 4 + (uae_u32)&regflags, tmpr, sz_long);
1.1       root     3870:                cc_status = 0;
                   3871:            } else {
                   3872:                /* Lies! */
                   3873:                cc_status = CC_X_FROM_86C | CC_Z_FROM_86Z |CC_C_FROM_86C |CC_V_FROM_86V |CC_N_FROM_86N;
                   3874:            }
                   3875:            break;
                   3876: 
                   3877:         case i_MULU:
                   3878:         case i_MULS:
1.1.1.2   root     3879:            compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
                   3880:            compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
1.1       root     3881:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     3882:                              insn_info[iip].dp->sreg,
1.1       root     3883:                              insn_info[iip].dp->size, &realpc, current_addr,
1.1.1.2   root     3884:                              eainfo, 0, EA_LOAD, 1);
1.1       root     3885:            compile_prepareea(&map, insn_info[iip].dp->dmode,
1.1.1.3 ! root     3886:                              insn_info[iip].dp->dreg,
1.1       root     3887:                              insn_info[iip].dp->size, &realpc, current_addr,
1.1.1.2   root     3888:                              eainfo, 1, EA_MODIFY | EA_LOAD | EA_STORE, 1);
1.1       root     3889: 
                   3890:            generate_possible_exit(&map, eainfo, iip, &pub);
                   3891:            generate_possible_exit(&map, eainfo+1, iip, &pub);
1.1.1.3 ! root     3892: 
1.1.1.2   root     3893:            compile_loadeas(&map, eainfo, 0, 1, regonly_alternatives, 0, 1);
1.1       root     3894: 
                   3895:            /* Extend the regs properly */
1.1.1.2   root     3896:            remove_x86r_from_cache(&map, eainfo[0].data_reg, 0);
1.1       root     3897:            switch (insn_info[iip].dp->mnemo) {
                   3898:             case i_MULU:
1.1.1.2   root     3899:                assemble(0x81); assemble(0xC0+4*8 + eainfo[0].data_reg); assemble_ulong(0xFFFF);
                   3900:                assemble(0x81); assemble(0xC0+4*8 + eainfo[1].data_reg); assemble_ulong(0xFFFF);
1.1       root     3901:                break;
                   3902:             case i_MULS:
1.1.1.2   root     3903:                assemble(0x0F); assemble(0xBF); assemble(0xC0 + 9*eainfo[0].data_reg);
                   3904:                assemble(0x0F); assemble(0xBF); assemble(0xC0 + 9*eainfo[1].data_reg);
1.1       root     3905:                break;
                   3906:            }
                   3907:            /* and multiply */
1.1.1.2   root     3908:            assemble(0x0F); assemble(0xAF); assemble(0xC0 + 8*eainfo[1].data_reg + eainfo[0].data_reg);
                   3909:            compile_note_modify(&map, eainfo, 1);
1.1       root     3910:            cc_status = CC_TEST_REG;
1.1.1.2   root     3911:            cc_reg = eainfo[1].data_reg;
1.1       root     3912:            cc_offset = 0;
                   3913:            cc_size = sz_long;
                   3914:            break;
                   3915: 
                   3916:         case i_ADDA:
                   3917:         case i_SUBA:
                   3918:         case i_CMPA:
1.1.1.2   root     3919:            compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
                   3920:            compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
1.1       root     3921:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     3922:                              insn_info[iip].dp->sreg,
1.1       root     3923:                              insn_info[iip].dp->size, &realpc, current_addr,
1.1.1.2   root     3924:                              eainfo, 0, EA_LOAD, 1);
1.1       root     3925:            compile_prepareea(&map, insn_info[iip].dp->dmode,
1.1.1.3 ! root     3926:                              insn_info[iip].dp->dreg,
1.1       root     3927:                              sz_long, &realpc, current_addr,
1.1.1.3 ! root     3928:                              eainfo, 1,
1.1.1.2   root     3929:                              (insn_info[iip].dp->mnemo == i_ADDA || insn_info[iip].dp->mnemo == i_SUBA
                   3930:                               ? EA_MODIFY | EA_LOAD | EA_STORE
1.1.1.3 ! root     3931:                               : EA_LOAD | EA_STORE),
1.1.1.2   root     3932:                              1);
1.1       root     3933: 
                   3934:            generate_possible_exit(&map, eainfo, iip, &pub);
                   3935: 
1.1.1.2   root     3936:            compile_loadeas(&map, eainfo, 0, 1,
                   3937:                            insn_info[iip].dp->size == sz_word ? binop_worda_alternatives : binop_alternatives,
                   3938:                            0, 1);
                   3939: 
                   3940:            if (insn_info[iip].dp->size == sz_word) {
                   3941:                remove_x86r_from_cache(&map, eainfo[0].data_reg, 0);
                   3942:                compile_extend_long(&map, eainfo[0].data_reg, sz_word);
                   3943:            }
                   3944:            eainfo[0].size = sz_long;
1.1       root     3945: 
                   3946:            switch (insn_info[iip].dp->mnemo) {
1.1.1.2   root     3947:             case i_ADDA: compile_eas(&map, eainfo, 0, 1, 0); break;
                   3948:             case i_SUBA: compile_eas(&map, eainfo, 0, 1, 5); break;
                   3949:             case i_CMPA: compile_eas(&map, eainfo, 0, 1, 7); break;
1.1       root     3950:            }
                   3951: 
                   3952:            if (insn_info[iip].dp->mnemo == i_CMPA) {
                   3953:                cc_status = CC_Z_FROM_86Z |CC_C_FROM_86C |CC_V_FROM_86V |CC_N_FROM_86N;
                   3954:            } else {
1.1.1.2   root     3955:                compile_note_modify(&map, eainfo, 1);
1.1       root     3956:                cc_status = 0;
                   3957:            }
                   3958:            break;
                   3959: 
                   3960:         case i_MOVE:
1.1.1.2   root     3961:            compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
                   3962:            compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
1.1       root     3963:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     3964:                              insn_info[iip].dp->sreg,
1.1       root     3965:                              insn_info[iip].dp->size, &realpc, current_addr,
1.1.1.2   root     3966:                              eainfo, 0, EA_LOAD, 1);
1.1       root     3967:            compile_prepareea(&map, insn_info[iip].dp->dmode,
1.1.1.3 ! root     3968:                              insn_info[iip].dp->dreg,
1.1       root     3969:                              insn_info[iip].dp->size, &realpc, current_addr,
1.1.1.2   root     3970:                              eainfo, 1, EA_STORE, 1);
1.1       root     3971: 
                   3972:            generate_possible_exit(&map, eainfo, iip, &pub);
                   3973:            generate_possible_exit(&map, eainfo + 1, iip, &pub);
1.1.1.3 ! root     3974: 
1.1.1.2   root     3975:            compile_loadeas(&map, eainfo, 0, 1, binop_alternatives, 1, 0);
                   3976:            compile_storeea(&map, eainfo, 0, 1);
1.1.1.3 ! root     3977: 
1.1.1.2   root     3978:            if (eainfo[0].data_reg == -2) {
                   3979:                cc_status = CC_TEST_REG;
                   3980:                cc_reg = -2;
                   3981:                cc_offset = eainfo[0].data_const_off;
                   3982:            } else if (eainfo[0].data_reg == -1) {
                   3983:                if (eainfo[1].data_reg == -1)
                   3984:                    printf("Don't know where to get flags from\n");
                   3985:                cc_status = CC_TEST_REG;
                   3986:                cc_offset = 0;
                   3987:                cc_reg = eainfo[1].data_reg;
                   3988:            } else {
                   3989:                cc_status = CC_TEST_REG;
                   3990:                cc_reg = eainfo[0].data_reg;
                   3991:                cc_offset = 0;
                   3992:            }
1.1       root     3993:            cc_size = eainfo[0].size;
1.1.1.3 ! root     3994: 
1.1       root     3995:            break;
                   3996: 
                   3997:         case i_MOVEA:
1.1.1.2   root     3998:            compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
                   3999:            compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
1.1       root     4000:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     4001:                              insn_info[iip].dp->sreg,
1.1       root     4002:                              insn_info[iip].dp->size, &realpc, current_addr,
1.1.1.2   root     4003:                              eainfo, 0, EA_LOAD, 1);
1.1       root     4004:            compile_prepareea(&map, insn_info[iip].dp->dmode,
                   4005:                              insn_info[iip].dp->dreg,
                   4006:                              sz_long, &realpc, current_addr,
1.1.1.2   root     4007:                              eainfo, 1, EA_STORE, 1);
1.1       root     4008: 
                   4009:            generate_possible_exit(&map, eainfo, iip, &pub);
1.1.1.3 ! root     4010: 
1.1.1.2   root     4011:            compile_loadeas(&map, eainfo, 0, 1,
                   4012:                            insn_info[iip].dp->size == sz_word ? binop_worda_alternatives : binop_alternatives,
                   4013:                            0, 0);
                   4014: 
                   4015:            if (insn_info[iip].dp->size == sz_word) {
                   4016:                remove_x86r_from_cache(&map, eainfo[0].data_reg, 0);
                   4017:                compile_extend_long(&map, eainfo[0].data_reg, sz_word);
                   4018:            }
                   4019:            eainfo[0].size = sz_long;
                   4020: 
                   4021:            compile_storeea(&map, eainfo, 0, 1);
1.1       root     4022: 
                   4023:            cc_status = 0;
                   4024:            break;
                   4025: 
                   4026:         case i_EXG:
1.1.1.2   root     4027:            if (insn_info[iip].dp->smode != insn_info[iip].dp->dmode
1.1.1.3 ! root     4028:                || insn_info[iip].dp->sreg != insn_info[iip].dp->dreg)
1.1.1.2   root     4029:            {
                   4030:                compile_prepareea(&map, insn_info[iip].dp->smode,
                   4031:                                  insn_info[iip].dp->sreg,
                   4032:                                  sz_long, &realpc, current_addr,
                   4033:                                  eainfo, 0, EA_LOAD|EA_STORE, 1);
                   4034:                compile_prepareea(&map, insn_info[iip].dp->dmode,
                   4035:                                  insn_info[iip].dp->dreg,
                   4036:                                  sz_long, &realpc, current_addr,
                   4037:                                  eainfo, 1, EA_LOAD|EA_STORE, 1);
1.1       root     4038: 
1.1.1.2   root     4039:                compile_loadeas(&map, eainfo, 0, 1, regonly_alternatives, 0, 1);
                   4040:                compile_storeea(&map, eainfo, 1, 0);
                   4041:                compile_storeea(&map, eainfo, 0, 1);
                   4042:            }
1.1       root     4043: 
                   4044:            cc_status = 0;
                   4045:            break;
1.1.1.3 ! root     4046: 
1.1       root     4047:         case i_LINK:
1.1.1.2   root     4048:            compile_prepare_undo(&map, Apdi, 7, &pub);
1.1       root     4049:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     4050:                              insn_info[iip].dp->sreg,
1.1       root     4051:                              sz_long, &realpc, current_addr,
1.1.1.2   root     4052:                              eainfo, 0, EA_LOAD|EA_STORE, 1);
1.1       root     4053:            compile_prepareea(&map, insn_info[iip].dp->dmode,
                   4054:                              insn_info[iip].dp->dreg,
                   4055:                              sz_long, &realpc, current_addr,
1.1.1.2   root     4056:                              eainfo, 1, EA_LOAD, 1);
1.1       root     4057:            compile_prepareea(&map, Apdi, 7, sz_long, &realpc, current_addr,
1.1.1.2   root     4058:                              eainfo, 2, EA_STORE, 1);
1.1       root     4059: 
                   4060:            generate_possible_exit(&map, eainfo+2, iip, &pub);
                   4061: 
1.1.1.2   root     4062:            compile_fetchea(&map, eainfo, 0, 1);
                   4063:            /* we know this is a constant - no need to fetch it*/
                   4064:            /* compile_fetchea(&map, eainfo, 1); */
                   4065:            compile_storeea(&map, eainfo, 0, 2); /* An -> -(A7) */
1.1       root     4066: 
                   4067:            compile_prepareea(&map, Areg, 7, sz_long, &realpc, current_addr,
1.1.1.2   root     4068:                              eainfo, 3, EA_STORE, 1);
                   4069:            compile_fetchea(&map, eainfo, 3, 1);
                   4070:            compile_storeea(&map, eainfo, 3, 0); /* A7 -> An */
                   4071: 
1.1       root     4072:            /* @@@ 020 */
1.1.1.2   root     4073:            compile_prepareea(&map, Areg, 7, sz_long, &realpc, current_addr,
                   4074:                              eainfo, 4, EA_LOAD, 1);
                   4075:            compile_prepareea(&map, Areg, 7, sz_long, &realpc, current_addr,
                   4076:                              eainfo, 5, EA_STORE, 1);
                   4077:            compile_fetchea(&map, eainfo, 4, 1);
1.1.1.3 ! root     4078:            eainfo[4].data_const_off += (uae_s16)eainfo[1].data_const_off;
1.1.1.2   root     4079:            compile_storeea(&map, eainfo, 4, 5); /* A7+off -> A7 */
1.1       root     4080:            cc_status = 0;
                   4081:            break;
1.1.1.3 ! root     4082: 
1.1       root     4083:         case i_UNLK:
1.1.1.2   root     4084:            compile_prepareea(&map, Areg,
1.1.1.3 ! root     4085:                              insn_info[iip].dp->sreg,
1.1       root     4086:                              sz_long, &realpc, current_addr,
1.1.1.2   root     4087:                              eainfo, 0, EA_LOAD, 1);
                   4088:            compile_prepareea(&map, Areg, 7, sz_long, &realpc, current_addr,
                   4089:                              eainfo, 1, EA_STORE, 1);
1.1.1.3 ! root     4090: 
1.1.1.2   root     4091:            generate_possible_exit(&map, eainfo + 0, iip, &pub);
                   4092: 
                   4093:            compile_fetchea(&map, eainfo, 0, 1);
                   4094:            compile_storeea(&map, eainfo, 0, 1);
                   4095: 
                   4096:            /* The Apdi could of course point to a non-memory area, but undos
                   4097:             * are difficult here, and anyway: which program does evil hacks
                   4098:             * with UNLK? */
                   4099:            compile_prepareea(&map, Aipi, 7, sz_long, &realpc, current_addr,
                   4100:                              eainfo, 2, EA_LOAD, 1);
                   4101:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     4102:                              insn_info[iip].dp->sreg,
1.1       root     4103:                              sz_long, &realpc, current_addr,
1.1.1.2   root     4104:                              eainfo, 3, EA_STORE, 1);
                   4105:            compile_fetchea(&map, eainfo, 2, 1);
                   4106:            compile_storeea(&map, eainfo, 2, 3);
1.1       root     4107: 
1.1.1.3 ! root     4108:            cc_status = 0;
1.1       root     4109:            break;
                   4110: 
                   4111:         case i_OR:
                   4112:         case i_AND:
                   4113:         case i_EOR:
1.1.1.2   root     4114:            compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
                   4115:            compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
1.1       root     4116:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     4117:                              insn_info[iip].dp->sreg,
1.1       root     4118:                              insn_info[iip].dp->size, &realpc, current_addr,
1.1.1.2   root     4119:                              eainfo, 0, EA_LOAD, 1);
1.1       root     4120:            compile_prepareea(&map, insn_info[iip].dp->dmode,
1.1.1.3 ! root     4121:                              insn_info[iip].dp->dreg,
1.1       root     4122:                              insn_info[iip].dp->size, &realpc, current_addr,
1.1.1.2   root     4123:                              eainfo, 1, EA_MODIFY | EA_LOAD | EA_STORE, 1);
1.1       root     4124: 
                   4125:            generate_possible_exit(&map, eainfo, iip, &pub);
                   4126:            generate_possible_exit(&map, eainfo + 1, iip, &pub);
1.1.1.3 ! root     4127: 
1.1.1.2   root     4128:            compile_loadeas(&map, eainfo, 0, 1, binop_alternatives, 0, 1);
1.1       root     4129: 
                   4130:            switch (insn_info[iip].dp->mnemo) {
1.1.1.2   root     4131:             case i_AND: compile_eas(&map, eainfo, 0, 1, 4); break;
                   4132:             case i_EOR: compile_eas(&map, eainfo, 0, 1, 6); break;
                   4133:             case i_OR:  compile_eas(&map, eainfo, 0, 1, 1); break;
                   4134:            }
1.1.1.3 ! root     4135: 
1.1.1.2   root     4136:            compile_note_modify(&map, eainfo, 1);
                   4137:            cc_status = CC_Z_FROM_86Z | CC_C_FROM_86C | CC_V_FROM_86V | CC_N_FROM_86N;
1.1       root     4138:            break;
1.1.1.2   root     4139: 
1.1       root     4140:         case i_TST:
1.1.1.2   root     4141:            compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
1.1       root     4142:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     4143:                              insn_info[iip].dp->sreg,
1.1       root     4144:                              insn_info[iip].dp->size, &realpc, current_addr,
1.1.1.2   root     4145:                              eainfo, 0, EA_LOAD, 1);
1.1       root     4146: 
                   4147:            generate_possible_exit(&map, eainfo, iip, &pub);
1.1.1.3 ! root     4148: 
1.1.1.2   root     4149:            compile_fetchea(&map, eainfo, 0, 1);
1.1       root     4150:            cc_status = CC_TEST_REG;
1.1.1.2   root     4151:            cc_reg = eainfo[0].data_reg;
                   4152:            cc_offset = 0;
1.1       root     4153:            cc_size = eainfo[0].size;
                   4154:            break;
1.1.1.3 ! root     4155: 
1.1       root     4156:         case i_CLR:
1.1.1.2   root     4157:            compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
1.1       root     4158:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     4159:                              insn_info[iip].dp->sreg,
1.1       root     4160:                              insn_info[iip].dp->size, &realpc, current_addr,
1.1.1.2   root     4161:                              eainfo, 0, EA_STORE, 1);
                   4162:            compile_prepareea(&map, immi, 0, sz_long, &realpc, current_addr,
                   4163:                              eainfo, 1, EA_LOAD, 1);
                   4164:            generate_possible_exit(&map, eainfo + 0, iip, &pub);
                   4165:            compile_loadeas(&map, eainfo, 1, 0, binop_alternatives, 1, 0);
                   4166:            compile_storeea(&map, eainfo, 1, 0);
1.1       root     4167: 
                   4168:            cc_status = CC_TEST_REG;
                   4169:            cc_reg = -2;
                   4170:            cc_offset = 0;
                   4171:            cc_size = eainfo[0].size;
                   4172:            break;
                   4173: 
                   4174:         case i_EXT:
1.1.1.2   root     4175:            /* No exits, no undo - this is always a Dreg; fetchea will get it in a reg
                   4176:             * without offset */
1.1       root     4177:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     4178:                              insn_info[iip].dp->sreg,
1.1       root     4179:                              insn_info[iip].dp->size == sz_long ? sz_word : sz_byte,
                   4180:                              &realpc, current_addr,
1.1.1.2   root     4181:                              eainfo, 0, EA_LOAD|EA_STORE, 1);
                   4182:            compile_fetchea(&map, eainfo, 0, 1);
                   4183:            compile_force_byteorder(&map, eainfo[0].data_reg, BO_NORMAL, 0);
1.1       root     4184: 
                   4185:            if (insn_info[iip].dp->size == sz_word)
                   4186:                assemble(0x66);
                   4187:            assemble(0x0F);
                   4188:            if (insn_info[iip].dp->size == sz_long)
                   4189:                assemble(0xBF);
                   4190:            else
                   4191:                assemble(0xBE);
1.1.1.3 ! root     4192: 
1.1.1.2   root     4193:            assemble(0xC0 + 9*eainfo[0].data_reg);
                   4194:            map.x86_dirty[eainfo[0].data_reg] = 1;
1.1       root     4195: 
                   4196:            cc_status = CC_TEST_REG;
1.1.1.2   root     4197:            cc_reg = eainfo[0].data_reg;
                   4198:            cc_offset = 0;
1.1.1.3 ! root     4199:            cc_size = eainfo[0].size;
1.1       root     4200:            break;
                   4201: 
                   4202:         case i_NOT:
                   4203:         case i_NEG:
                   4204:            szflag = insn_info[iip].dp->size == sz_byte ? 0 : 1;
                   4205: 
1.1.1.2   root     4206:            compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
1.1       root     4207:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     4208:                              insn_info[iip].dp->sreg,
1.1       root     4209:                              insn_info[iip].dp->size,
                   4210:                              &realpc, current_addr,
1.1.1.2   root     4211:                              eainfo, 0, EA_LOAD|EA_STORE, 1);
1.1       root     4212: 
                   4213:            generate_possible_exit(&map, eainfo, iip, &pub);
1.1.1.3 ! root     4214: 
1.1.1.2   root     4215:            compile_fetchea(&map, eainfo, 0, 1);
                   4216:            compile_force_byteorder(&map, eainfo[0].data_reg, BO_NORMAL, 0);
1.1       root     4217: 
                   4218:            if (insn_info[iip].dp->size == sz_word)
                   4219:                assemble(0x66);
                   4220:            assemble(0xF6 + szflag);
1.1.1.3 ! root     4221: 
1.1.1.2   root     4222:            assemble(0xC0 + eainfo[0].data_reg + 8*(insn_info[iip].dp->mnemo == i_NOT ? 2 : 3));
                   4223:            compile_note_modify(&map, eainfo, 0);
1.1       root     4224: 
1.1.1.2   root     4225:            if (insn_info[iip].dp->mnemo == i_NEG)
                   4226:                cc_status = CC_Z_FROM_86Z | CC_C_FROM_86C | CC_V_FROM_86V | CC_N_FROM_86N | CC_X_FROM_86C;
                   4227:            else {
                   4228:                cc_status = CC_TEST_REG;
                   4229:                cc_reg = eainfo[0].data_reg;
                   4230:                cc_offset = 0;
                   4231:                cc_size = eainfo[0].size;
                   4232:            }
1.1       root     4233:            break;
                   4234: 
                   4235:         case i_SWAP:
1.1.1.2   root     4236:            /* No exits, no undo - this is always a Dreg; fetchea will get it in a reg
                   4237:             * without offset */
1.1       root     4238:            compile_prepareea(&map, insn_info[iip].dp->smode,
                   4239:                              insn_info[iip].dp->sreg, sz_long,
                   4240:                              &realpc, current_addr,
1.1.1.2   root     4241:                              eainfo, 0, EA_LOAD|EA_STORE, 1);
                   4242: 
                   4243:            compile_fetchea(&map, eainfo, 0, 1);
                   4244:            compile_force_byteorder(&map, eainfo[0].data_reg, BO_NORMAL, 0);
1.1       root     4245: 
                   4246:            /* roll $16, srcreg */
1.1.1.2   root     4247:            assemble(0xC1); assemble(0xC0 + eainfo[0].data_reg); assemble(16);
1.1       root     4248: 
1.1.1.2   root     4249:            /* @@@ un-shortcut */
                   4250:            map.x86_dirty[eainfo[0].data_reg] = 1;
1.1       root     4251: 
                   4252:            cc_status = CC_TEST_REG;
1.1.1.2   root     4253:            cc_reg = eainfo[0].data_reg;
                   4254:            cc_offset = 0;
1.1.1.3 ! root     4255:            cc_size = eainfo[0].size;
1.1       root     4256:            break;
1.1.1.3 ! root     4257: 
1.1       root     4258:         case i_LEA:
1.1.1.2   root     4259:            /* No exits necessary here: never touches memory */
1.1       root     4260:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     4261:                              insn_info[iip].dp->sreg,
1.1       root     4262:                              insn_info[iip].dp->size, &realpc, current_addr,
1.1.1.2   root     4263:                              eainfo, 0, 0, 1);
                   4264:            eainfo[0].data_reg = eainfo[0].address_reg;
                   4265:            eainfo[0].data_const_off = eainfo[0].addr_const_off;
                   4266:            eainfo[0].address_reg = -1;
                   4267:            compile_get_excl_lock(&map, eainfo + 0);
1.1       root     4268:            compile_prepareea(&map, insn_info[iip].dp->dmode,
                   4269:                              insn_info[iip].dp->dreg,
                   4270:                              sz_long, &realpc, current_addr,
1.1.1.2   root     4271:                              eainfo, 1, EA_STORE, 1);
                   4272:            compile_storeea(&map, eainfo, 0, 1);
1.1       root     4273:            cc_status = 0;
                   4274:            break;
                   4275: 
                   4276:         case i_PEA:
1.1.1.2   root     4277:            compile_prepare_undo(&map, Apdi, 7, &pub);
1.1       root     4278:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     4279:                              insn_info[iip].dp->sreg,
1.1       root     4280:                              insn_info[iip].dp->size, &realpc, current_addr,
1.1.1.2   root     4281:                              eainfo, 0, 0, 1);
                   4282:            eainfo[0].data_reg = eainfo[0].address_reg;
                   4283:            eainfo[0].data_const_off = eainfo[0].addr_const_off;
                   4284:            eainfo[0].address_reg = -1;
                   4285:            compile_get_excl_lock(&map, eainfo + 0);
1.1       root     4286:            compile_prepareea(&map, Apdi, 7, sz_long, &realpc, current_addr,
1.1.1.2   root     4287:                              eainfo, 1, EA_STORE, 1);
1.1       root     4288: 
                   4289:            generate_possible_exit(&map, eainfo+1, iip, &pub);
1.1.1.2   root     4290:            compile_storeea(&map, eainfo, 0, 1);
1.1       root     4291: 
                   4292:            cc_status = 0;
                   4293:            break;
                   4294: 
                   4295:         case i_MVMEL:
                   4296:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     4297:                              insn_info[iip].dp->sreg,
1.1       root     4298:                              sz_word, &realpc, current_addr,
1.1.1.2   root     4299:                              eainfo, 0, EA_LOAD, 1);
1.1       root     4300:            sync_reg_cache(&map, 0);
                   4301:            {
                   4302:                /* Scratch 0 holds the registers while they are being moved
                   4303:                 * from/to memory. Scratch 1 points at regs.d. Scratch 2
                   4304:                 * points at the base addr in memory where to fetch data
1.1.1.2   root     4305:                 * from.
1.1       root     4306:                 */
                   4307:                int scratch0, scratch1, scratch2;
1.1.1.3 ! root     4308:                uae_u16 mask = eainfo[0].data_const_off;
1.1       root     4309:                int bits = count_bits(mask);
                   4310:                int size = insn_info[iip].dp->size == sz_long ? 4 : 2;
                   4311:                int i;
1.1.1.3 ! root     4312:                uae_u8 x86amode;
        !          4313:                uae_u32 current_offs = 0;
        !          4314: 
1.1.1.2   root     4315:                compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
1.1       root     4316:                /* !!! Note current_addr + 2 here! */
                   4317:                compile_prepareea(&map, insn_info[iip].dp->dmode,
                   4318:                                  insn_info[iip].dp->dreg,
                   4319:                                  insn_info[iip].dp->size, &realpc, current_addr + 2,
1.1.1.2   root     4320:                                  eainfo, 1, EA_LOAD, bits);
1.1.1.3 ! root     4321: 
1.1       root     4322:                generate_possible_exit(&map, eainfo + 1, iip, &pub);
                   4323: 
                   4324:                scratch0 = get_free_x86_register(&map, ADDRESS_X86_REGS);
1.1.1.2   root     4325:                lock_reg(&map, scratch0, 2);
1.1       root     4326:                scratch1 = get_free_x86_register(&map, ADDRESS_X86_REGS);
1.1.1.2   root     4327:                lock_reg(&map, scratch1, 2);
1.1       root     4328:                scratch2 = get_free_x86_register(&map, ADDRESS_X86_REGS);
1.1.1.2   root     4329:                lock_reg(&map, scratch2, 2);
1.1       root     4330:                compile_force_byteorder(&map, eainfo[1].address_reg, BO_NORMAL, 0);
1.1.1.3 ! root     4331: 
        !          4332:                compile_lea_reg_with_offset(scratch1, -2, (uae_u32)regs.regs);
1.1       root     4333:                compile_lea_reg_with_offset(scratch2, eainfo[1].address_reg,
1.1.1.3 ! root     4334:                                            (uae_u32)(address_space + eainfo[1].addr_const_off));
1.1       root     4335: 
                   4336:                for (i = 0; i < 16; i++) {
1.1.1.2   root     4337:                    int r68k = i;
1.1       root     4338:                    int *cache68k = i < 8 ? map.dreg_map : map.areg_map;
1.1.1.3 ! root     4339:                    if (mask & 1
        !          4340:                        && (i < 8
1.1       root     4341:                            || insn_info[iip].dp->dmode != Aipi
1.1.1.2   root     4342:                            || (r68k & 7) != insn_info[iip].dp->dreg)) {
                   4343:                        int tmpr = cache68k[r68k & 7];
1.1.1.3 ! root     4344: 
1.1       root     4345:                        if (tmpr != -1) {
1.1.1.2   root     4346:                            cache68k[r68k & 7] = -1;
1.1       root     4347:                            map.x86_cache_reg[tmpr] = -1;
                   4348:                        }
                   4349:                        compile_move_reg_from_mem_regoffs(scratch0, scratch2,
                   4350:                                                          current_offs, insn_info[iip].dp->size);
                   4351:                        if (size == 2) {
                   4352:                            assemble(0x66); /* rolw $8,scratch0 */
                   4353:                            assemble(0xC1);
                   4354:                            assemble(0xC0 + scratch0);
                   4355:                            assemble(8);
                   4356:                            assemble(0x0F); assemble(0xBF); /* extend */
                   4357:                            assemble(0xC0 + 9*scratch0);
                   4358:                        } else {
                   4359:                            assemble(0x0F); /* bswapl scratch0 */
                   4360:                            assemble(0xC8 + scratch0);
                   4361:                        }
1.1.1.2   root     4362:                        compile_move_reg_to_mem_regoffs(scratch1, (char *)(regs.regs + r68k) - (char *)regs.regs,
1.1       root     4363:                                                        scratch0, sz_long);
                   4364:                    }
                   4365:                    if (mask & 1)
                   4366:                        current_offs += size;
                   4367:                    mask >>= 1;
                   4368:                }
                   4369:            }
                   4370:            cc_status = 0;
                   4371:            break;
                   4372: 
                   4373:         case i_MVMLE:
                   4374:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     4375:                              insn_info[iip].dp->sreg,
1.1       root     4376:                              sz_word, &realpc, current_addr,
1.1.1.2   root     4377:                              eainfo, 0, EA_LOAD, 1);
1.1       root     4378:            sync_reg_cache(&map, 0);
                   4379:            {
                   4380:                int scratch0,scratch1,scratch2;
1.1.1.3 ! root     4381:                uae_u16 mask = eainfo[0].data_const_off;
1.1       root     4382:                int bits = count_bits(mask);
                   4383:                int size = insn_info[iip].dp->size == sz_long ? 4 : 2;
                   4384:                int i;
1.1.1.3 ! root     4385:                uae_u8 x86amode;
        !          4386:                uae_u32 current_offs = 0;
1.1.1.2   root     4387:                int addrareg = -1;
                   4388:                if (insn_info[iip].dp->dmode == Aind
                   4389:                    || insn_info[iip].dp->dmode == Apdi
                   4390:                    || insn_info[iip].dp->dmode == Aipi
                   4391:                    || insn_info[iip].dp->dmode == Ad16
                   4392:                    || insn_info[iip].dp->dmode == Ad8r)
                   4393:                {
                   4394:                    addrareg = get_and_lock_68k_reg(&map, insn_info[iip].dp->dreg, 0, ADDRESS_X86_REGS, 1, 2);
                   4395:                    compile_force_byteorder(&map, addrareg, BO_NORMAL, 0);
                   4396:                }
1.1       root     4397:                if (insn_info[iip].dp->dmode == Apdi)
                   4398:                    mask = bitswap(mask);
                   4399:                /* !!! Note current_addr + 2 here! */
1.1.1.2   root     4400:                compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
1.1       root     4401:                compile_prepareea(&map, insn_info[iip].dp->dmode,
                   4402:                                  insn_info[iip].dp->dreg,
                   4403:                                  insn_info[iip].dp->size, &realpc, current_addr + 2,
1.1.1.2   root     4404:                                  eainfo, 1, EA_STORE, bits);
1.1.1.3 ! root     4405: 
1.1       root     4406:                generate_possible_exit(&map, eainfo + 1, iip, &pub);
                   4407: 
                   4408:                scratch0 = get_free_x86_register(&map, ADDRESS_X86_REGS);
1.1.1.2   root     4409:                lock_reg(&map, scratch0, 2);
1.1       root     4410:                scratch1 = get_free_x86_register(&map, ADDRESS_X86_REGS);
1.1.1.2   root     4411:                lock_reg(&map, scratch1, 2);
1.1       root     4412:                scratch2 = get_free_x86_register(&map, ADDRESS_X86_REGS);
1.1.1.2   root     4413:                lock_reg(&map, scratch2, 2);
1.1       root     4414: 
                   4415:                compile_force_byteorder(&map, eainfo[1].address_reg, BO_NORMAL, 0);
                   4416: 
1.1.1.3 ! root     4417:                compile_lea_reg_with_offset(scratch1, -2, (uae_u32)regs.regs);
1.1       root     4418:                compile_lea_reg_with_offset(scratch2, eainfo[1].address_reg,
1.1.1.3 ! root     4419:                                            (uae_u32)(address_space + eainfo[1].addr_const_off));
1.1       root     4420: 
                   4421:                for (i = 0; i < 16; i++) {
1.1.1.2   root     4422:                    int r68k = i;
1.1       root     4423:                    if (mask & 1) {
                   4424:                        /* move from 68k reg */
1.1.1.2   root     4425:                        if (i < 8 || (i & 7) != insn_info[iip].dp->dreg || addrareg == -1) {
                   4426:                            compile_move_reg_from_mem_regoffs(scratch0, scratch1, (char *)(regs.regs + r68k) - (char *)regs.regs,
1.1       root     4427:                                                              sz_long);
                   4428:                        } else {
                   4429:                            assemble(0x8B); assemble(0xC0 + 8*scratch0 + addrareg);
                   4430:                        }
                   4431: 
                   4432:                        if (size == 2) {
                   4433:                            assemble(0x66); /* rolw $8,scratch0 */
                   4434:                            assemble(0xC1);
                   4435:                            assemble(0xC0 + scratch0); assemble(8);
                   4436:                        } else {
                   4437:                            assemble(0x0F); /* bswapl scratch0 */
                   4438:                            assemble(0xC8 + scratch0);
                   4439:                        }
                   4440:                        compile_move_reg_to_mem_regoffs(scratch2, current_offs,
                   4441:                                                        scratch0, insn_info[iip].dp->size);
                   4442:                    }
                   4443:                    if (mask & 1)
                   4444:                        current_offs += size;
                   4445:                    mask >>= 1;
                   4446:                }
                   4447:            }
                   4448:            cc_status = 0;
                   4449:            break;
1.1.1.2   root     4450: #if 1
                   4451:         case i_BTST:
                   4452:         case i_BSET:
                   4453:         case i_BCLR:
                   4454:         case i_BCHG:
                   4455:            compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
                   4456:            compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
                   4457:            compile_prepareea(&map, insn_info[iip].dp->smode,
1.1.1.3 ! root     4458:                              insn_info[iip].dp->sreg,
1.1.1.2   root     4459:                              insn_info[iip].dp->size, &realpc, current_addr,
                   4460:                              eainfo, 0, EA_LOAD, 1);
                   4461:            compile_prepareea(&map, insn_info[iip].dp->dmode,
1.1.1.3 ! root     4462:                              insn_info[iip].dp->dreg,
1.1.1.2   root     4463:                              insn_info[iip].dp->size, &realpc, current_addr,
                   4464:                              eainfo, 1, 0, 1);
1.1       root     4465: 
1.1.1.2   root     4466:            generate_possible_exit(&map, eainfo, iip, &pub);
                   4467:            generate_possible_exit(&map, eainfo + 1, iip, &pub);
                   4468: 
                   4469:            handle_bit_insns(&map, eainfo, 0, 1, insn_info[iip].dp->mnemo);
                   4470:            break;
1.1.1.3 ! root     4471: 
        !          4472:         case i_ASL: case i_ASR: case i_LSL: case i_LSR:
1.1       root     4473:         case i_ROL: case i_ROR: case i_ROXL:case i_ROXR:
1.1.1.2   root     4474:            if (insn_info[iip].dp->smode == Dreg && do_rotshi) {
                   4475:                handle_rotshi_variable(&map, iip, realpc, current_addr, &pub);
                   4476:                break;
                   4477:            }
                   4478:            /* fall through */
1.1.1.3 ! root     4479:         case i_ASLW: case i_ASRW: case i_LSLW: case i_LSRW:
1.1       root     4480:         case i_ROLW: case i_RORW: case i_ROXLW:case i_ROXRW:
                   4481:            if (do_rotshi) {
1.1.1.2   root     4482:                handle_rotshi(&map, iip, realpc, current_addr, &pub);
1.1       root     4483:                break;
                   4484:            }
1.1.1.2   root     4485: #endif
1.1       root     4486:         default:
                   4487:            generate_exit(&map, insn_info[iip].address); cc_status = 0;
                   4488:            break;
                   4489:        }
                   4490:        if (insn_info[iip].ccuser_follows)
1.1.1.3 ! root     4491:            cc_status_for_bcc = compile_flush_cc_cache(&map, cc_status,
1.1       root     4492:                                   insn_info[iip].flags_live_at_end,
                   4493:                                   1, insn_info[iip+1].flags_live_at_end,
                   4494:                                   insn_info[iip+1].dp->cc);
                   4495:        else
1.1.1.3 ! root     4496:            cc_status_for_bcc = compile_flush_cc_cache(&map, cc_status,
1.1       root     4497:                                   insn_info[iip].flags_live_at_end,
                   4498:                                   0, 0, 0);
                   4499: 
                   4500:        if (iip == current_bb->last_iip) {
                   4501:            current_bb++;
                   4502:        }
                   4503:     }
                   4504:     if (compile_failure)
                   4505:        goto oops;
                   4506: 
                   4507:     /* Compile all exits that we prepared earlier */
                   4508:     finish_exits();
                   4509:     if (compile_failure)
                   4510:        goto oops;
                   4511:     finish_condjumps(last_iip);
                   4512:     {
                   4513:        int needed_len = compile_here() - hb->compile_start;
                   4514:        int allocsize = (needed_len + PAGE_SUBUNIT - 1) & ~(PAGE_SUBUNIT-1);
1.1.1.3 ! root     4515:        uae_u32 allocmask;
1.1       root     4516:        int allocbits;
1.1.1.3 ! root     4517: 
1.1       root     4518:        allocbits = (allocsize >> SUBUNIT_ORDER);
                   4519:        allocmask = (1 << allocbits) - 1;
                   4520:        while ((allocmask & hb->page_allocmask) != allocmask)
                   4521:            allocmask <<= 1;
                   4522:        if ((hb->page_allocmask & ~allocmask) != 0 && !quiet_compile)
                   4523:            fprintf(stderr, "Gaining some bits: %08lx\n", hb->page_allocmask & ~allocmask);
                   4524:        hb->cpage->allocmask &= ~hb->page_allocmask;
                   4525:        hb->page_allocmask = allocmask;
                   4526:        hb->cpage->allocmask |= allocmask;
                   4527:     }
                   4528:     return 0;
1.1.1.3 ! root     4529: 
1.1       root     4530:     oops:
                   4531:     if (1 || !quiet_compile)
                   4532:        fprintf(stderr, "Compile failed!\n");
                   4533:     hb->cpage->allocmask &= ~hb->page_allocmask;
                   4534:     hb->cpage = NULL;
                   4535:     hb->untranslatable = 1;
                   4536:     {
                   4537:        struct hash_entry *h = hb->he_first;
1.1.1.3 ! root     4538: 
1.1       root     4539:        do {
                   4540:            h->execute = NULL;
                   4541:            h = h->next_same_block;
                   4542:        } while (h != hb->he_first);
                   4543:     }
                   4544:     return 1;
                   4545: }
                   4546: 
1.1.1.2   root     4547: void compiler_init(void)
                   4548: {
                   4549:     code_init();
                   4550:     hash_init();
                   4551:     jsr_stack_init();
                   4552: }
                   4553: 
1.1       root     4554: /*
                   4555:  * Why do compilers always have to be so complicated? And I thought GCC was
                   4556:  * a mess...
                   4557:  */
                   4558: 
                   4559: #endif /* USE_COMPILER */

unix.superglobalmegacorp.com

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