ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp
Revision: 1.12
Committed: 2002-10-12T16:27:13Z (21 years, 11 months ago) by gbeauche
Branch: MAIN
Changes since 1.11: +15 -4 lines
Log Message:
Add raw_emit_nop_filler() with more efficient no-op fillers stolen from
GNU binutils 2.12.90.0.15. Speed bump is marginal (less than 6%). Make it
default though, that's conditionalized by tune_nop_fillers constant.

File Contents

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