ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp
Revision: 1.8
Committed: 2002-10-02T15:55:10Z (21 years, 11 months ago) by gbeauche
Branch: MAIN
Changes since 1.7: +122 -54 lines
Log Message:
- Remove dead code in readcpu.cpp concerning CONST_JUMP control flow.
- Replace unused fl_compiled with fl_const_jump
- Implement block inlining enabled with USE_INLINING && USE_CHECKSUM_INFO.
  However, this is currently disabled as it doesn't give much and exhibits
  even more a cache/code generation problem with FPU JIT compiled code.
- Actual checksum values are now integral part of a blockinfo regardless
  of USE_CHECKSUM_INFO is set or not. Reduce number of elements in that
  structure and speeds up a little calculation of checksum of chained blocks.
- Don't care about show_checksum() for now.

File Contents

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