home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Emulation / BasiliskII / src / uae_cpu / compiler.cpp < prev    next >
C/C++ Source or Header  |  1999-11-03  |  135KB  |  4,550 lines

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