ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp
Revision: 1.11
Committed: 2002-10-03T16:13:46Z (21 years, 11 months ago) by gbeauche
Branch: MAIN
Changes since 1.10: +25 -0 lines
Log Message:
JIT add copyright notices just to notify people that's real derivative
work from GPL code (UAE-JIT). Additions and improvements are from B2
developers.

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