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