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