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*)&regs)+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*)(&regs.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)&regs.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)&regs.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)&regs.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*)&regs.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)&regs.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)&regs.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)&regs.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)&regs);
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)&regs.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)&regs.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)&regs.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)&regs.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)&regs.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