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

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