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