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