ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp
Revision: 1.16
Committed: 2003-03-13T20:34:34Z (21 years, 6 months ago) by gbeauche
Branch: MAIN
Changes since 1.15: +14 -9 lines
Log Message:
Implement a generic setzflg_l() for P4, thus permitting to re-enable
translation of ADDX/SUBX/BCLR/BTST/BSET/BCHG instructions. i.e. make
it faster. ;-)

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