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