ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp
(Generate patch)

Comparing BasiliskII/src/uae_cpu/compiler/compemu_support.cpp (file contents):
Revision 1.3 by gbeauche, 2002-09-18T09:55:37Z vs.
Revision 1.26 by gbeauche, 2004-11-08T21:10:46Z

# Line 1 | Line 1
1 + /*
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-2004
7 + *    Gwenole Beauchesne
8 + *
9 + *  Basilisk II (C) 1997-2004 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   #if !REAL_ADDRESSING && !DIRECT_ADDRESSING
27   #error "Only Real or Direct Addressing is supported with the JIT Compiler"
28   #endif
29  
30 + #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 + /* NOTE: support for AMD64 assumes translation cache and other code
35 + * buffers are allocated into a 32-bit address space because (i) B2/JIT
36 + * code is not 64-bit clean and (ii) it's faster to resolve branches
37 + * that way.
38 + */
39 + #if !defined(__i386__) && !defined(__x86_64__)
40 + #error "Only IA-32 and X86-64 targets are supported with the JIT Compiler"
41 + #endif
42 +
43   #define USE_MATCH 0
44  
45   /* kludge for Brian, so he can compile under MSVC++ */
46   #define USE_NORMAL_CALLING_CONVENTION 0
47  
48   #ifndef WIN32
49 + #include <unistd.h>
50   #include <sys/types.h>
51   #include <sys/mman.h>
52   #endif
# Line 40 | Line 79
79   #endif
80  
81   #ifndef WIN32
82 < #define PROFILE_COMPILE_TIME    1
82 > #define PROFILE_COMPILE_TIME            1
83 > #define PROFILE_UNTRANSLATED_INSNS      1
84   #endif
85  
86   #ifdef WIN32
# Line 65 | Line 105 | static clock_t emul_start_time = 0;
105   static clock_t emul_end_time    = 0;
106   #endif
107  
108 < compop_func *compfunctbl[65536];
109 < compop_func *nfcompfunctbl[65536];
110 < cpuop_func *nfcpufunctbl[65536];
108 > #if PROFILE_UNTRANSLATED_INSNS
109 > const int untranslated_top_ten = 20;
110 > static uae_u32 raw_cputbl_count[65536] = { 0, };
111 > static uae_u16 opcode_nums[65536];
112 >
113 > static int untranslated_compfn(const void *e1, const void *e2)
114 > {
115 >        return raw_cputbl_count[*(const uae_u16 *)e1] < raw_cputbl_count[*(const uae_u16 *)e2];
116 > }
117 > #endif
118 >
119 > static compop_func *compfunctbl[65536];
120 > static compop_func *nfcompfunctbl[65536];
121 > static cpuop_func *nfcpufunctbl[65536];
122   uae_u8* comp_pc_p;
123  
124 + // From main_unix.cpp
125 + extern bool ThirtyThreeBitAddressing;
126 +
127 + // From newcpu.cpp
128 + extern bool quit_program;
129 +
130   // gb-- Extra data for Basilisk II/JIT
131   #if JIT_DEBUG
132   static bool             JITDebug                        = false;        // Enable runtime disassemblers through mon?
# Line 77 | Line 134 | static bool            JITDebug                        = false;        // Enab
134   const bool              JITDebug                        = false;        // Don't use JIT debug mode at all
135   #endif
136  
137 < const uae_u32   MIN_CACHE_SIZE          = 2048;         // Minimal translation cache size (2048 KB)
137 > const uae_u32   MIN_CACHE_SIZE          = 1024;         // Minimal translation cache size (1 MB)
138   static uae_u32  cache_size                      = 0;            // Size of total cache allocated for compiled blocks
139   static uae_u32  current_cache_size      = 0;            // Cache grows upwards: how much has been consumed already
140   static bool             lazy_flush                      = true;         // Flag: lazy translation cache invalidation
141   static bool             avoid_fpu                       = true;         // Flag: compile FPU instructions ?
142   static bool             have_cmov                       = false;        // target has CMOV instructions ?
143   static bool             have_rat_stall          = true;         // target has partial register stalls ?
144 < static int              zero_fd                         = -1;
144 > const bool              tune_alignment          = true;         // Tune code alignments for running CPU ?
145 > const bool              tune_nop_fillers        = true;         // Tune no-op fillers for architecture
146 > static bool             setzflg_uses_bsf        = false;        // setzflg virtual instruction can use native BSF instruction correctly?
147 > static int              align_loops                     = 32;           // Align the start of loops
148 > static int              align_jumps                     = 32;           // Align the start of jumps
149   static int              optcount[10]            = {
150          10,             // How often a block has to be executed before it is translated
151          0,              // How often to use naive translation
# Line 100 | Line 161 | struct op_properties {
161   };
162   static op_properties prop[65536];
163  
103 // gb-- Control Flow Predicates
104
164   static inline int end_block(uae_u32 opcode)
165   {
166          return (prop[opcode].cflow & fl_end_block);
167   }
168  
169 + static inline bool is_const_jump(uae_u32 opcode)
170 + {
171 +        return (prop[opcode].cflow == fl_const_jump);
172 + }
173 +
174   static inline bool may_trap(uae_u32 opcode)
175   {
176          return (prop[opcode].cflow & fl_trap);
177   }
178  
179 + static inline unsigned int cft_map (unsigned int f)
180 + {
181 + #ifndef HAVE_GET_WORD_UNSWAPPED
182 +    return f;
183 + #else
184 +    return ((f >> 8) & 255) | ((f & 255) << 8);
185 + #endif
186 + }
187 +
188   uae_u8* start_pc_p;
189   uae_u32 start_pc;
190   uae_u32 current_block_pc_p;
191 < uae_u32 current_block_start_target;
191 > static uintptr current_block_start_target;
192   uae_u32 needed_flags;
193 < static uae_u32 next_pc_p;
194 < static uae_u32 taken_pc_p;
193 > static uintptr next_pc_p;
194 > static uintptr taken_pc_p;
195   static int branch_cc;
196   static int redo_current_block;
197  
# Line 130 | Line 203 | static uae_u8* current_compile_p=NULL;
203   static uae_u8* max_compile_start;
204   static uae_u8* compiled_code=NULL;
205   static uae_s32 reg_alloc_run;
206 + const int POPALLSPACE_SIZE = 1024; /* That should be enough space */
207 + static uae_u8* popallspace=NULL;
208  
209   void* pushall_call_handler=NULL;
210   static void* popall_do_nothing=NULL;
# Line 139 | Line 214 | static void* popall_cache_miss=NULL;
214   static void* popall_recompile_block=NULL;
215   static void* popall_check_checksum=NULL;
216  
142 extern uae_u32 oink;
143 extern unsigned long foink3;
144 extern unsigned long foink;
145
217   /* The 68k only ever executes from even addresses. So right now, we
218   * waste half the entries in this array
219   * UPDATE: We now use those entries to store the start of the linked
# Line 389 | Line 460 | static __inline__ void invalidate_block(
460  
461   static __inline__ void create_jmpdep(blockinfo* bi, int i, uae_u32* jmpaddr, uae_u32 target)
462   {
463 <    blockinfo*  tbi=get_blockinfo_addr((void*)target);
463 >    blockinfo*  tbi=get_blockinfo_addr((void*)(uintptr)target);
464      
465      Dif(!tbi) {
466          write_log("Could not create jmpdep!\n");
# Line 487 | Line 558 | static void prepare_block(blockinfo* bi)
558     compiled. If the list of free blockinfos is empty, we allocate a new
559     pool of blockinfos and link the newly created blockinfos altogether
560     into the list of free blockinfos. Otherwise, we simply pop a structure
561 <   of the free list.
561 >   off the free list.
562  
563     Blockinfo are lazily deallocated, i.e. chained altogether in the
564     list of free blockinfos whenvever a translation cache flush (hard or
565     soft) request occurs.
566   */
567  
568 < #if USE_SEPARATE_BIA
569 < const int BLOCKINFO_POOL_SIZE = 128;
570 < struct blockinfo_pool {
571 <        blockinfo bi[BLOCKINFO_POOL_SIZE];
572 <        blockinfo_pool *next;
568 > template< class T >
569 > class LazyBlockAllocator
570 > {
571 >        enum {
572 >                kPoolSize = 1 + 4096 / sizeof(T)
573 >        };
574 >        struct Pool {
575 >                T chunk[kPoolSize];
576 >                Pool * next;
577 >        };
578 >        Pool * mPools;
579 >        T * mChunks;
580 > public:
581 >        LazyBlockAllocator() : mPools(0), mChunks(0) { }
582 >        ~LazyBlockAllocator();
583 >        T * acquire();
584 >        void release(T * const);
585   };
503 static blockinfo_pool * blockinfo_pools = 0;
504 static blockinfo *              free_blockinfos = 0;
505 #endif
586  
587 < static __inline__ blockinfo *alloc_blockinfo(void)
587 > template< class T >
588 > LazyBlockAllocator<T>::~LazyBlockAllocator()
589   {
590 < #if USE_SEPARATE_BIA
591 <        if (!free_blockinfos) {
592 <                // There is no blockinfo struct left, allocate a new
593 <                // pool and link the chunks into the free list
594 <                blockinfo_pool *bi_pool = (blockinfo_pool *)malloc(sizeof(blockinfo_pool));
595 <                for (blockinfo *bi = &bi_pool->bi[0]; bi < &bi_pool->bi[BLOCKINFO_POOL_SIZE]; bi++) {
596 <                        bi->next = free_blockinfos;
597 <                        free_blockinfos = bi;
590 >        Pool * currentPool = mPools;
591 >        while (currentPool) {
592 >                Pool * deadPool = currentPool;
593 >                currentPool = currentPool->next;
594 >                free(deadPool);
595 >        }
596 > }
597 >
598 > template< class T >
599 > T * LazyBlockAllocator<T>::acquire()
600 > {
601 >        if (!mChunks) {
602 >                // There is no chunk left, allocate a new pool and link the
603 >                // chunks into the free list
604 >                Pool * newPool = (Pool *)malloc(sizeof(Pool));
605 >                for (T * chunk = &newPool->chunk[0]; chunk < &newPool->chunk[kPoolSize]; chunk++) {
606 >                        chunk->next = mChunks;
607 >                        mChunks = chunk;
608                  }
609 <                bi_pool->next = blockinfo_pools;
610 <                blockinfo_pools = bi_pool;
609 >                newPool->next = mPools;
610 >                mPools = newPool;
611          }
612 <        blockinfo *bi = free_blockinfos;
613 <        free_blockinfos = bi->next;
614 < #else
524 <        blockinfo *bi = (blockinfo*)current_compile_p;
525 <        current_compile_p += sizeof(blockinfo);
526 < #endif
527 <        return bi;
612 >        T * chunk = mChunks;
613 >        mChunks = chunk->next;
614 >        return chunk;
615   }
616  
617 < static __inline__ void free_blockinfo(blockinfo *bi)
617 > template< class T >
618 > void LazyBlockAllocator<T>::release(T * const chunk)
619 > {
620 >        chunk->next = mChunks;
621 >        mChunks = chunk;
622 > }
623 >
624 > template< class T >
625 > class HardBlockAllocator
626   {
627 + public:
628 +        T * acquire() {
629 +                T * data = (T *)current_compile_p;
630 +                current_compile_p += sizeof(T);
631 +                return data;
632 +        }
633 +
634 +        void release(T * const chunk) {
635 +                // Deallocated on invalidation
636 +        }
637 + };
638 +
639   #if USE_SEPARATE_BIA
640 <        bi->next = free_blockinfos;
641 <        free_blockinfos = bi;
640 > static LazyBlockAllocator<blockinfo> BlockInfoAllocator;
641 > static LazyBlockAllocator<checksum_info> ChecksumInfoAllocator;
642 > #else
643 > static HardBlockAllocator<blockinfo> BlockInfoAllocator;
644 > static HardBlockAllocator<checksum_info> ChecksumInfoAllocator;
645   #endif
646 +
647 + static __inline__ checksum_info *alloc_checksum_info(void)
648 + {
649 +        checksum_info *csi = ChecksumInfoAllocator.acquire();
650 +        csi->next = NULL;
651 +        return csi;
652   }
653  
654 < static void free_blockinfo_pools(void)
654 > static __inline__ void free_checksum_info(checksum_info *csi)
655   {
656 < #if USE_SEPARATE_BIA
657 <        int blockinfo_pool_count = 0;
658 <        blockinfo_pool *curr_pool = blockinfo_pools;
659 <        while (curr_pool) {
660 <                blockinfo_pool_count++;
661 <                blockinfo_pool *dead_pool = curr_pool;
662 <                curr_pool = curr_pool->next;
663 <                free(dead_pool);
656 >        csi->next = NULL;
657 >        ChecksumInfoAllocator.release(csi);
658 > }
659 >
660 > static __inline__ void free_checksum_info_chain(checksum_info *csi)
661 > {
662 >        while (csi != NULL) {
663 >                checksum_info *csi2 = csi->next;
664 >                free_checksum_info(csi);
665 >                csi = csi2;
666          }
667 <        
668 <        uae_u32 blockinfo_pools_size = blockinfo_pool_count * BLOCKINFO_POOL_SIZE * sizeof(blockinfo);
669 <        write_log("### Blockinfo allocation statistics\n");
670 <        write_log("Number of blockinfo pools  : %d\n", blockinfo_pool_count);
671 <        write_log("Total number of blockinfos : %d (%d KB)\n",
672 <                          blockinfo_pool_count * BLOCKINFO_POOL_SIZE,
673 <                          blockinfo_pools_size / 1024);
556 <        write_log("\n");
667 > }
668 >
669 > static __inline__ blockinfo *alloc_blockinfo(void)
670 > {
671 >        blockinfo *bi = BlockInfoAllocator.acquire();
672 > #if USE_CHECKSUM_INFO
673 >        bi->csi = NULL;
674   #endif
675 +        return bi;
676 + }
677 +
678 + static __inline__ void free_blockinfo(blockinfo *bi)
679 + {
680 + #if USE_CHECKSUM_INFO
681 +        free_checksum_info_chain(bi->csi);
682 +        bi->csi = NULL;
683 + #endif
684 +        BlockInfoAllocator.release(bi);
685   }
686  
687   static __inline__ void alloc_blockinfos(void)
# Line 597 | Line 724 | static __inline__ void emit_long(uae_u32
724      target+=4;
725   }
726  
727 + static __inline__ void emit_quad(uae_u64 x)
728 + {
729 +    *((uae_u64*)target)=x;
730 +    target+=8;
731 + }
732 +
733 + static __inline__ void emit_block(const uae_u8 *block, uae_u32 blocklen)
734 + {
735 +        memcpy((uae_u8 *)target,block,blocklen);
736 +        target+=blocklen;
737 + }
738 +
739   static __inline__ uae_u32 reverse32(uae_u32 v)
740   {
741   #if 1
# Line 693 | Line 832 | static __inline__ void flush_flags(void)
832   int touchcnt;
833  
834   /********************************************************************
835 + * Partial register flushing for optimized calls                    *
836 + ********************************************************************/
837 +
838 + struct regusage {
839 +        uae_u16 rmask;
840 +        uae_u16 wmask;
841 + };
842 +
843 + static inline void ru_set(uae_u16 *mask, int reg)
844 + {
845 + #if USE_OPTIMIZED_CALLS
846 +        *mask |= 1 << reg;
847 + #endif
848 + }
849 +
850 + static inline bool ru_get(const uae_u16 *mask, int reg)
851 + {
852 + #if USE_OPTIMIZED_CALLS
853 +        return (*mask & (1 << reg));
854 + #else
855 +        /* Default: instruction reads & write to register */
856 +        return true;
857 + #endif
858 + }
859 +
860 + static inline void ru_set_read(regusage *ru, int reg)
861 + {
862 +        ru_set(&ru->rmask, reg);
863 + }
864 +
865 + static inline void ru_set_write(regusage *ru, int reg)
866 + {
867 +        ru_set(&ru->wmask, reg);
868 + }
869 +
870 + static inline bool ru_read_p(const regusage *ru, int reg)
871 + {
872 +        return ru_get(&ru->rmask, reg);
873 + }
874 +
875 + static inline bool ru_write_p(const regusage *ru, int reg)
876 + {
877 +        return ru_get(&ru->wmask, reg);
878 + }
879 +
880 + static void ru_fill_ea(regusage *ru, int reg, amodes mode,
881 +                                           wordsizes size, int write_mode)
882 + {
883 +        switch (mode) {
884 +        case Areg:
885 +                reg += 8;
886 +                /* fall through */
887 +        case Dreg:
888 +                ru_set(write_mode ? &ru->wmask : &ru->rmask, reg);
889 +                break;
890 +        case Ad16:
891 +                /* skip displacment */
892 +                m68k_pc_offset += 2;
893 +        case Aind:
894 +        case Aipi:
895 +        case Apdi:
896 +                ru_set_read(ru, reg+8);
897 +                break;
898 +        case Ad8r:
899 +                ru_set_read(ru, reg+8);
900 +                /* fall through */
901 +        case PC8r: {
902 +                uae_u16 dp = comp_get_iword((m68k_pc_offset+=2)-2);
903 +                reg = (dp >> 12) & 15;
904 +                ru_set_read(ru, reg);
905 +                if (dp & 0x100)
906 +                        m68k_pc_offset += (((dp & 0x30) >> 3) & 7) + ((dp & 3) * 2);
907 +                break;
908 +        }
909 +        case PC16:
910 +        case absw:
911 +        case imm0:
912 +        case imm1:
913 +                m68k_pc_offset += 2;
914 +                break;
915 +        case absl:
916 +        case imm2:
917 +                m68k_pc_offset += 4;
918 +                break;
919 +        case immi:
920 +                m68k_pc_offset += (size == sz_long) ? 4 : 2;
921 +                break;
922 +        }
923 + }
924 +
925 + /* TODO: split into a static initialization part and a dynamic one
926 +   (instructions depending on extension words) */
927 + static void ru_fill(regusage *ru, uae_u32 opcode)
928 + {
929 +        m68k_pc_offset += 2;
930 +
931 +        /* Default: no register is used or written to */
932 +        ru->rmask = 0;
933 +        ru->wmask = 0;
934 +
935 +        uae_u32 real_opcode = cft_map(opcode);
936 +        struct instr *dp = &table68k[real_opcode];
937 +
938 +        bool rw_dest = true;
939 +        bool handled = false;
940 +
941 +        /* Handle some instructions specifically */
942 +        uae_u16 reg, ext;
943 +        switch (dp->mnemo) {
944 +        case i_BFCHG:
945 +        case i_BFCLR:
946 +        case i_BFEXTS:
947 +        case i_BFEXTU:
948 +        case i_BFFFO:
949 +        case i_BFINS:
950 +        case i_BFSET:
951 +        case i_BFTST:
952 +                ext = comp_get_iword((m68k_pc_offset+=2)-2);
953 +                if (ext & 0x800) ru_set_read(ru, (ext >> 6) & 7);
954 +                if (ext & 0x020) ru_set_read(ru, ext & 7);
955 +                ru_fill_ea(ru, dp->dreg, (amodes)dp->dmode, (wordsizes)dp->size, 1);
956 +                if (dp->dmode == Dreg)
957 +                        ru_set_read(ru, dp->dreg);
958 +                switch (dp->mnemo) {
959 +                case i_BFEXTS:
960 +                case i_BFEXTU:
961 +                case i_BFFFO:
962 +                        ru_set_write(ru, (ext >> 12) & 7);
963 +                        break;
964 +                case i_BFINS:
965 +                        ru_set_read(ru, (ext >> 12) & 7);
966 +                        /* fall through */
967 +                case i_BFCHG:
968 +                case i_BFCLR:
969 +                case i_BSET:
970 +                        if (dp->dmode == Dreg)
971 +                                ru_set_write(ru, dp->dreg);
972 +                        break;
973 +                }
974 +                handled = true;
975 +                rw_dest = false;
976 +                break;
977 +
978 +        case i_BTST:
979 +                rw_dest = false;
980 +                break;
981 +
982 +        case i_CAS:
983 +        {
984 +                ext = comp_get_iword((m68k_pc_offset+=2)-2);
985 +                int Du = ext & 7;
986 +                ru_set_read(ru, Du);
987 +                int Dc = (ext >> 6) & 7;
988 +                ru_set_read(ru, Dc);
989 +                ru_set_write(ru, Dc);
990 +                break;
991 +        }
992 +        case i_CAS2:
993 +        {
994 +                int Dc1, Dc2, Du1, Du2, Rn1, Rn2;
995 +                ext = comp_get_iword((m68k_pc_offset+=2)-2);
996 +                Rn1 = (ext >> 12) & 15;
997 +                Du1 = (ext >> 6) & 7;
998 +                Dc1 = ext & 7;
999 +                ru_set_read(ru, Rn1);
1000 +                ru_set_read(ru, Du1);
1001 +                ru_set_read(ru, Dc1);
1002 +                ru_set_write(ru, Dc1);
1003 +                ext = comp_get_iword((m68k_pc_offset+=2)-2);
1004 +                Rn2 = (ext >> 12) & 15;
1005 +                Du2 = (ext >> 6) & 7;
1006 +                Dc2 = ext & 7;
1007 +                ru_set_read(ru, Rn2);
1008 +                ru_set_read(ru, Du2);
1009 +                ru_set_write(ru, Dc2);
1010 +                break;
1011 +        }
1012 +        case i_DIVL: case i_MULL:
1013 +                m68k_pc_offset += 2;
1014 +                break;
1015 +        case i_LEA:
1016 +        case i_MOVE: case i_MOVEA: case i_MOVE16:
1017 +                rw_dest = false;
1018 +                break;
1019 +        case i_PACK: case i_UNPK:
1020 +                rw_dest = false;
1021 +                m68k_pc_offset += 2;
1022 +                break;
1023 +        case i_TRAPcc:
1024 +                m68k_pc_offset += (dp->size == sz_long) ? 4 : 2;
1025 +                break;
1026 +        case i_RTR:
1027 +                /* do nothing, just for coverage debugging */
1028 +                break;
1029 +        /* TODO: handle EXG instruction */
1030 +        }
1031 +
1032 +        /* Handle A-Traps better */
1033 +        if ((real_opcode & 0xf000) == 0xa000) {
1034 +                handled = true;
1035 +        }
1036 +
1037 +        /* Handle EmulOps better */
1038 +        if ((real_opcode & 0xff00) == 0x7100) {
1039 +                handled = true;
1040 +                ru->rmask = 0xffff;
1041 +                ru->wmask = 0;
1042 +        }
1043 +
1044 +        if (dp->suse && !handled)
1045 +                ru_fill_ea(ru, dp->sreg, (amodes)dp->smode, (wordsizes)dp->size, 0);
1046 +
1047 +        if (dp->duse && !handled)
1048 +                ru_fill_ea(ru, dp->dreg, (amodes)dp->dmode, (wordsizes)dp->size, 1);
1049 +
1050 +        if (rw_dest)
1051 +                ru->rmask |= ru->wmask;
1052 +
1053 +        handled = handled || dp->suse || dp->duse;
1054 +
1055 +        /* Mark all registers as used/written if the instruction may trap */
1056 +        if (may_trap(opcode)) {
1057 +                handled = true;
1058 +                ru->rmask = 0xffff;
1059 +                ru->wmask = 0xffff;
1060 +        }
1061 +
1062 +        if (!handled) {
1063 +                write_log("ru_fill: %04x = { %04x, %04x }\n",
1064 +                                  real_opcode, ru->rmask, ru->wmask);
1065 +                abort();
1066 +        }
1067 + }
1068 +
1069 + /********************************************************************
1070   * register allocation per block logging                            *
1071   ********************************************************************/
1072  
# Line 770 | Line 1144 | static __inline__ void do_load_reg(int n
1144    else if (r == FLAGX)
1145          raw_load_flagx(n, r);
1146    else
1147 <        raw_mov_l_rm(n, (uae_u32) live.state[r].mem);
1147 >        raw_mov_l_rm(n, (uintptr) live.state[r].mem);
1148   }
1149  
1150   static __inline__ void check_load_reg(int n, int r)
1151   {
1152 <  raw_mov_l_rm(n, (uae_u32) live.state[r].mem);
1152 >  raw_mov_l_rm(n, (uintptr) live.state[r].mem);
1153   }
1154  
1155   static __inline__ void log_vwrite(int r)
# Line 886 | Line 1260 | static  void tomem(int r)
1260  
1261      if (live.state[r].status==DIRTY) {
1262          switch (live.state[r].dirtysize) {
1263 <         case 1: raw_mov_b_mr((uae_u32)live.state[r].mem,rr); break;
1264 <         case 2: raw_mov_w_mr((uae_u32)live.state[r].mem,rr); break;
1265 <         case 4: raw_mov_l_mr((uae_u32)live.state[r].mem,rr); break;
1263 >         case 1: raw_mov_b_mr((uintptr)live.state[r].mem,rr); break;
1264 >         case 2: raw_mov_w_mr((uintptr)live.state[r].mem,rr); break;
1265 >         case 4: raw_mov_l_mr((uintptr)live.state[r].mem,rr); break;
1266           default: abort();
1267          }
1268          log_vwrite(r);
# Line 916 | Line 1290 | static __inline__ void writeback_const(i
1290          abort();
1291      }
1292  
1293 <    raw_mov_l_mi((uae_u32)live.state[r].mem,live.state[r].val);
1293 >    raw_mov_l_mi((uintptr)live.state[r].mem,live.state[r].val);
1294          log_vwrite(r);
1295      live.state[r].val=0;
1296      set_status(r,INMEM);
# Line 1049 | Line 1423 | static  int alloc_reg_hinted(int r, int
1423          if (size==4 && live.state[r].validsize==2) {
1424                  log_isused(bestreg);
1425                  log_visused(r);
1426 <            raw_mov_l_rm(bestreg,(uae_u32)live.state[r].mem);
1426 >            raw_mov_l_rm(bestreg,(uintptr)live.state[r].mem);
1427              raw_bswap_32(bestreg);
1428              raw_zero_extend_16_rr(rr,rr);
1429              raw_zero_extend_16_rr(bestreg,bestreg);
# Line 1546 | Line 1920 | static  void f_tomem(int r)
1920   {
1921      if (live.fate[r].status==DIRTY) {
1922   #if USE_LONG_DOUBLE
1923 <        raw_fmov_ext_mr((uae_u32)live.fate[r].mem,live.fate[r].realreg);
1923 >        raw_fmov_ext_mr((uintptr)live.fate[r].mem,live.fate[r].realreg);
1924   #else
1925 <        raw_fmov_mr((uae_u32)live.fate[r].mem,live.fate[r].realreg);
1925 >        raw_fmov_mr((uintptr)live.fate[r].mem,live.fate[r].realreg);
1926   #endif
1927          live.fate[r].status=CLEAN;
1928      }
# Line 1558 | Line 1932 | static  void f_tomem_drop(int r)
1932   {
1933      if (live.fate[r].status==DIRTY) {
1934   #if USE_LONG_DOUBLE
1935 <        raw_fmov_ext_mr_drop((uae_u32)live.fate[r].mem,live.fate[r].realreg);
1935 >        raw_fmov_ext_mr_drop((uintptr)live.fate[r].mem,live.fate[r].realreg);
1936   #else
1937 <        raw_fmov_mr_drop((uae_u32)live.fate[r].mem,live.fate[r].realreg);
1937 >        raw_fmov_mr_drop((uintptr)live.fate[r].mem,live.fate[r].realreg);
1938   #endif
1939          live.fate[r].status=INMEM;
1940      }
# Line 1668 | Line 2042 | static  int f_alloc_reg(int r, int willc
2042      if (!willclobber) {
2043          if (live.fate[r].status!=UNDEF) {
2044   #if USE_LONG_DOUBLE
2045 <            raw_fmov_ext_rm(bestreg,(uae_u32)live.fate[r].mem);
2045 >            raw_fmov_ext_rm(bestreg,(uintptr)live.fate[r].mem);
2046   #else
2047 <            raw_fmov_rm(bestreg,(uae_u32)live.fate[r].mem);
2047 >            raw_fmov_rm(bestreg,(uintptr)live.fate[r].mem);
2048   #endif
2049          }
2050          live.fate[r].status=CLEAN;
# Line 1827 | Line 2201 | static void fflags_into_flags_internal(u
2201          else
2202      raw_fflags_into_flags(r);
2203      f_unlock(r);
2204 +    live_flags();
2205   }
2206  
2207  
# Line 1875 | Line 2250 | MIDFUNC(0,duplicate_carry,(void))
2250   {
2251      evict(FLAGX);
2252      make_flags_live_internal();
2253 <    COMPCALL(setcc_m)((uae_u32)live.state[FLAGX].mem,2);
2253 >    COMPCALL(setcc_m)((uintptr)live.state[FLAGX].mem,2);
2254          log_vwrite(FLAGX);
2255   }
2256   MENDFUNC(0,duplicate_carry,(void))
# Line 2562 | Line 2937 | MIDFUNC(3,cmov_l_rm,(RW4 d, IMM s, IMM c
2937   }
2938   MENDFUNC(3,cmov_l_rm,(RW4 d, IMM s, IMM cc))
2939  
2940 < MIDFUNC(2,bsf_l_rr,(W4 d, R4 s))
2940 > MIDFUNC(2,bsf_l_rr,(W4 d, W4 s))
2941   {
2942      CLOBBER_BSF;
2943 <    s=readreg(s,4);
2944 <    d=writereg(d,4);
2945 <    raw_bsf_l_rr(d,s);
2943 >    s = readreg(s, 4);
2944 >    d = writereg(d, 4);
2945 >    raw_bsf_l_rr(d, s);
2946      unlock2(s);
2947      unlock2(d);
2948   }
2949 < MENDFUNC(2,bsf_l_rr,(W4 d, R4 s))
2949 > MENDFUNC(2,bsf_l_rr,(W4 d, W4 s))
2950 >
2951 > /* Set the Z flag depending on the value in s. Note that the
2952 >   value has to be 0 or -1 (or, more precisely, for non-zero
2953 >   values, bit 14 must be set)! */
2954 > MIDFUNC(2,simulate_bsf,(W4 tmp, RW4 s))
2955 > {
2956 >    CLOBBER_BSF;
2957 >    s=rmw_specific(s,4,4,FLAG_NREG3);
2958 >    tmp=writereg(tmp,4);
2959 >    raw_flags_set_zero(s, tmp);
2960 >    unlock2(tmp);
2961 >    unlock2(s);
2962 > }
2963 > MENDFUNC(2,simulate_bsf,(W4 tmp, RW4 s))
2964  
2965   MIDFUNC(2,imul_32_32,(RW4 d, R4 s))
2966   {
# Line 2617 | Line 3006 | MIDFUNC(2,mul_32_32,(RW4 d, R4 s))
3006   }
3007   MENDFUNC(2,mul_32_32,(RW4 d, R4 s))
3008  
3009 + #if SIZEOF_VOID_P == 8
3010 + MIDFUNC(2,sign_extend_32_rr,(W4 d, R2 s))
3011 + {
3012 +    int isrmw;
3013 +
3014 +    if (isconst(s)) {
3015 +        set_const(d,(uae_s32)live.state[s].val);
3016 +        return;
3017 +    }
3018 +
3019 +    CLOBBER_SE32;
3020 +    isrmw=(s==d);
3021 +    if (!isrmw) {
3022 +        s=readreg(s,4);
3023 +        d=writereg(d,4);
3024 +    }
3025 +    else {  /* If we try to lock this twice, with different sizes, we
3026 +               are int trouble! */
3027 +        s=d=rmw(s,4,4);
3028 +    }
3029 +    raw_sign_extend_32_rr(d,s);
3030 +    if (!isrmw) {
3031 +        unlock2(d);
3032 +        unlock2(s);
3033 +    }
3034 +    else {
3035 +        unlock2(s);
3036 +    }
3037 + }
3038 + MENDFUNC(2,sign_extend_32_rr,(W4 d, R2 s))
3039 + #endif
3040 +
3041   MIDFUNC(2,sign_extend_16_rr,(W4 d, R2 s))
3042   {
3043      int isrmw;
# Line 4461 | Line 4882 | MENDFUNC(2,fmul_rr,(FRW d, FR s))
4882   * Support functions exposed to gencomp. CREATE time                *
4883   ********************************************************************/
4884  
4885 + void set_zero(int r, int tmp)
4886 + {
4887 +    if (setzflg_uses_bsf)
4888 +        bsf_l_rr(r,r);
4889 +    else
4890 +        simulate_bsf(tmp,r);
4891 + }
4892 +
4893   int kill_rodent(int r)
4894   {
4895      return KILLTHERAT &&
# Line 4509 | Line 4938 | static inline const char *str_on_off(boo
4938          return b ? "on" : "off";
4939   }
4940  
4512 static __inline__ unsigned int cft_map (unsigned int f)
4513 {
4514 #ifndef HAVE_GET_WORD_UNSWAPPED
4515    return f;
4516 #else
4517    return ((f >> 8) & 255) | ((f & 255) << 8);
4518 #endif
4519 }
4520
4941   void compiler_init(void)
4942   {
4943          static bool initialized = false;
4944          if (initialized)
4945                  return;
4946 <        
4527 < #ifndef WIN32
4528 <        // Open /dev/zero
4529 <        zero_fd = open("/dev/zero", O_RDWR);
4530 <        if (zero_fd < 0) {
4531 <                char str[200];
4532 <                sprintf(str, GetString(STR_NO_DEV_ZERO_ERR), strerror(errno));
4533 <                ErrorAlert(str);
4534 <                QuitEmulator();
4535 <        }
4536 < #endif
4537 <        
4946 >
4947   #if JIT_DEBUG
4948          // JIT debug mode ?
4949          JITDebug = PrefsFindBool("jitdebug");
# Line 4556 | Line 4965 | void compiler_init(void)
4965          
4966          // Initialize target CPU (check for features, e.g. CMOV, rat stalls)
4967          raw_init_cpu();
4968 +        setzflg_uses_bsf = target_check_bsf();
4969          write_log("<JIT compiler> : target processor has CMOV instructions : %s\n", have_cmov ? "yes" : "no");
4970          write_log("<JIT compiler> : target processor can suffer from partial register stalls : %s\n", have_rat_stall ? "yes" : "no");
4971 +        write_log("<JIT compiler> : alignment for loops, jumps are %d, %d\n", align_loops, align_jumps);
4972          
4973          // Translation cache flush mechanism
4974          lazy_flush = PrefsFindBool("jitlazyflush");
# Line 4568 | Line 4979 | void compiler_init(void)
4979          write_log("<JIT compiler> : register aliasing : %s\n", str_on_off(1));
4980          write_log("<JIT compiler> : FP register aliasing : %s\n", str_on_off(USE_F_ALIAS));
4981          write_log("<JIT compiler> : lazy constant offsetting : %s\n", str_on_off(USE_OFFSET));
4982 +        write_log("<JIT compiler> : block inlining : %s\n", str_on_off(USE_INLINING));
4983          write_log("<JIT compiler> : separate blockinfo allocation : %s\n", str_on_off(USE_SEPARATE_BIA));
4984          
4985          // Build compiler tables
# Line 4575 | Line 4987 | void compiler_init(void)
4987          
4988          initialized = true;
4989          
4990 + #if PROFILE_UNTRANSLATED_INSNS
4991 +        write_log("<JIT compiler> : gather statistics on untranslated insns count\n");
4992 + #endif
4993 +
4994   #if PROFILE_COMPILE_TIME
4995          write_log("<JIT compiler> : gather statistics on translation time\n");
4996          emul_start_time = clock();
# Line 4592 | Line 5008 | void compiler_exit(void)
5008                  vm_release(compiled_code, cache_size * 1024);
5009                  compiled_code = 0;
5010          }
5011 <        
5012 <        // Deallocate blockinfo pools
5013 <        free_blockinfo_pools();
5014 <        
5015 < #ifndef WIN32
5016 <        // Close /dev/zero
4601 <        if (zero_fd > 0)
4602 <                close(zero_fd);
4603 < #endif
5011 >
5012 >        // Deallocate popallspace
5013 >        if (popallspace) {
5014 >                vm_release(popallspace, POPALLSPACE_SIZE);
5015 >                popallspace = 0;
5016 >        }
5017          
5018   #if PROFILE_COMPILE_TIME
5019          write_log("### Compile Block statistics\n");
# Line 4611 | Line 5024 | void compiler_exit(void)
5024                  100.0*double(compile_time)/double(emul_time));
5025          write_log("\n");
5026   #endif
5027 +
5028 + #if PROFILE_UNTRANSLATED_INSNS
5029 +        uae_u64 untranslated_count = 0;
5030 +        for (int i = 0; i < 65536; i++) {
5031 +                opcode_nums[i] = i;
5032 +                untranslated_count += raw_cputbl_count[i];
5033 +        }
5034 +        write_log("Sorting out untranslated instructions count...\n");
5035 +        qsort(opcode_nums, 65536, sizeof(uae_u16), untranslated_compfn);
5036 +        write_log("\nRank  Opc      Count Name\n");
5037 +        for (int i = 0; i < untranslated_top_ten; i++) {
5038 +                uae_u32 count = raw_cputbl_count[opcode_nums[i]];
5039 +                struct instr *dp;
5040 +                struct mnemolookup *lookup;
5041 +                if (!count)
5042 +                        break;
5043 +                dp = table68k + opcode_nums[i];
5044 +                for (lookup = lookuptab; lookup->mnemo != dp->mnemo; lookup++)
5045 +                        ;
5046 +                write_log("%03d: %04x %10lu %s\n", i, opcode_nums[i], count, lookup->name);
5047 +        }
5048 + #endif
5049   }
5050  
5051   bool compiler_use_jit(void)
# Line 4665 | Line 5100 | void init_comp(void)
5100      }
5101      live.state[PC_P].mem=(uae_u32*)&(regs.pc_p);
5102      live.state[PC_P].needflush=NF_TOMEM;
5103 <    set_const(PC_P,(uae_u32)comp_pc_p);
5103 >    set_const(PC_P,(uintptr)comp_pc_p);
5104  
5105 <    live.state[FLAGX].mem=&(regflags.x);
5105 >    live.state[FLAGX].mem=(uae_u32*)&(regflags.x);
5106      live.state[FLAGX].needflush=NF_TOMEM;
5107      set_status(FLAGX,INMEM);
5108          
5109 <    live.state[FLAGTMP].mem=&(regflags.cznv);
5109 >    live.state[FLAGTMP].mem=(uae_u32*)&(regflags.cznv);
5110      live.state[FLAGTMP].needflush=NF_TOMEM;
5111      set_status(FLAGTMP,INMEM);
5112  
# Line 4690 | Line 5125 | void init_comp(void)
5125              live.fate[i].status=INMEM;
5126          }
5127          else
5128 <            live.fate[i].mem=(uae_u32*)(scratch.fregs+i);
5128 >            live.fate[i].mem=(uae_u32*)(&scratch.fregs[i]);
5129      }
5130  
5131  
# Line 4745 | Line 5180 | void flush(int save_regs)
5180                  switch(live.state[i].status) {
5181                   case INMEM:  
5182                      if (live.state[i].val) {
5183 <                        raw_add_l_mi((uae_u32)live.state[i].mem,live.state[i].val);
5183 >                        raw_add_l_mi((uintptr)live.state[i].mem,live.state[i].val);
5184                          log_vwrite(i);
5185                          live.state[i].val=0;
5186                      }
# Line 4839 | Line 5274 | void freescratch(void)
5274  
5275   static void align_target(uae_u32 a)
5276   {
5277 <    /* Fill with NOPs --- makes debugging with gdb easier */
5278 <    while ((uae_u32)target&(a-1))
5279 <        *target++=0x90;
5277 >        if (!a)
5278 >                return;
5279 >
5280 >        if (tune_nop_fillers)
5281 >                raw_emit_nop_filler(a - (((uintptr)target) & (a - 1)));
5282 >        else {
5283 >                /* Fill with NOPs --- makes debugging with gdb easier */
5284 >                while ((uintptr)target&(a-1))
5285 >                        *target++=0x90;
5286 >        }
5287   }
5288  
5289   static __inline__ int isinrom(uintptr addr)
# Line 4907 | Line 5349 | void register_branch(uae_u32 not_taken,
5349   static uae_u32 get_handler_address(uae_u32 addr)
5350   {
5351      uae_u32 cl=cacheline(addr);
5352 <    blockinfo* bi=get_blockinfo_addr_new((void*)addr,0);
5353 <    return (uae_u32)&(bi->direct_handler_to_use);
5352 >    blockinfo* bi=get_blockinfo_addr_new((void*)(uintptr)addr,0);
5353 >    return (uintptr)&(bi->direct_handler_to_use);
5354   }
5355  
5356   static uae_u32 get_handler(uae_u32 addr)
5357   {
5358      uae_u32 cl=cacheline(addr);
5359 <    blockinfo* bi=get_blockinfo_addr_new((void*)addr,0);
5360 <    return (uae_u32)bi->direct_handler_to_use;
5359 >    blockinfo* bi=get_blockinfo_addr_new((void*)(uintptr)addr,0);
5360 >    return (uintptr)bi->direct_handler_to_use;
5361   }
5362  
5363   static void load_handler(int reg, uae_u32 addr)
# Line 4927 | Line 5369 | static void load_handler(int reg, uae_u3
5369   *  if that assumption is wrong! No branches, no second chances, just
5370   *  straight go-for-it attitude */
5371  
5372 < static void writemem_real(int address, int source, int offset, int size, int tmp, int clobber)
5372 > static void writemem_real(int address, int source, int size, int tmp, int clobber)
5373   {
5374      int f=tmp;
5375  
5376          if (clobber)
5377              f=source;
5378 +
5379 + #if SIZEOF_VOID_P == 8
5380 +        if (!ThirtyThreeBitAddressing)
5381 +                sign_extend_32_rr(address, address);
5382 + #endif
5383 +
5384          switch(size) {
5385           case 1: mov_b_bRr(address,source,MEMBaseDiff); break;
5386           case 2: mov_w_rr(f,source); bswap_16(f); mov_w_bRr(address,f,MEMBaseDiff); break;
# Line 4944 | Line 5392 | static void writemem_real(int address, i
5392  
5393   void writebyte(int address, int source, int tmp)
5394   {
5395 <        writemem_real(address,source,20,1,tmp,0);
5395 >        writemem_real(address,source,1,tmp,0);
5396   }
5397  
5398   static __inline__ void writeword_general(int address, int source, int tmp,
5399                                           int clobber)
5400   {
5401 <        writemem_real(address,source,16,2,tmp,clobber);
5401 >        writemem_real(address,source,2,tmp,clobber);
5402   }
5403  
5404   void writeword_clobber(int address, int source, int tmp)
# Line 4966 | Line 5414 | void writeword(int address, int source,
5414   static __inline__ void writelong_general(int address, int source, int tmp,
5415                                           int clobber)
5416   {
5417 <        writemem_real(address,source,12,4,tmp,clobber);
5417 >        writemem_real(address,source,4,tmp,clobber);
5418   }
5419  
5420   void writelong_clobber(int address, int source, int tmp)
# Line 4985 | Line 5433 | void writelong(int address, int source,
5433   *  if that assumption is wrong! No branches, no second chances, just
5434   *  straight go-for-it attitude */
5435  
5436 < static void readmem_real(int address, int dest, int offset, int size, int tmp)
5436 > static void readmem_real(int address, int dest, int size, int tmp)
5437   {
5438      int f=tmp;
5439  
5440      if (size==4 && address!=dest)
5441          f=dest;
5442  
5443 + #if SIZEOF_VOID_P == 8
5444 +        if (!ThirtyThreeBitAddressing)
5445 +                sign_extend_32_rr(address, address);
5446 + #endif
5447 +
5448          switch(size) {
5449           case 1: mov_b_brR(dest,address,MEMBaseDiff); break;
5450           case 2: mov_w_brR(dest,address,MEMBaseDiff); bswap_16(dest); break;
# Line 5002 | Line 5455 | static void readmem_real(int address, in
5455  
5456   void readbyte(int address, int dest, int tmp)
5457   {
5458 <        readmem_real(address,dest,8,1,tmp);
5458 >        readmem_real(address,dest,1,tmp);
5459   }
5460  
5461   void readword(int address, int dest, int tmp)
5462   {
5463 <        readmem_real(address,dest,4,2,tmp);
5463 >        readmem_real(address,dest,2,tmp);
5464   }
5465  
5466   void readlong(int address, int dest, int tmp)
5467   {
5468 <        readmem_real(address,dest,0,4,tmp);
5468 >        readmem_real(address,dest,4,tmp);
5469   }
5470  
5471   void get_n_addr(int address, int dest, int tmp)
# Line 5137 | Line 5590 | uae_u32 get_jitted_size(void)
5590      return 0;
5591   }
5592  
5593 + const int CODE_ALLOC_MAX_ATTEMPTS = 10;
5594 + const int CODE_ALLOC_BOUNDARIES   = 128 * 1024; // 128 KB
5595 +
5596 + static uint8 *do_alloc_code(uint32 size, int depth)
5597 + {
5598 + #if defined(__linux__) && 0
5599 +        /*
5600 +          This is a really awful hack that is known to work on Linux at
5601 +          least.
5602 +          
5603 +          The trick here is to make sure the allocated cache is nearby
5604 +          code segment, and more precisely in the positive half of a
5605 +          32-bit address space. i.e. addr < 0x80000000. Actually, it
5606 +          turned out that a 32-bit binary run on AMD64 yields a cache
5607 +          allocated around 0xa0000000, thus causing some troubles when
5608 +          translating addresses from m68k to x86.
5609 +        */
5610 +        static uint8 * code_base = NULL;
5611 +        if (code_base == NULL) {
5612 +                uintptr page_size = getpagesize();
5613 +                uintptr boundaries = CODE_ALLOC_BOUNDARIES;
5614 +                if (boundaries < page_size)
5615 +                        boundaries = page_size;
5616 +                code_base = (uint8 *)sbrk(0);
5617 +                for (int attempts = 0; attempts < CODE_ALLOC_MAX_ATTEMPTS; attempts++) {
5618 +                        if (vm_acquire_fixed(code_base, size) == 0) {
5619 +                                uint8 *code = code_base;
5620 +                                code_base += size;
5621 +                                return code;
5622 +                        }
5623 +                        code_base += boundaries;
5624 +                }
5625 +                return NULL;
5626 +        }
5627 +
5628 +        if (vm_acquire_fixed(code_base, size) == 0) {
5629 +                uint8 *code = code_base;
5630 +                code_base += size;
5631 +                return code;
5632 +        }
5633 +
5634 +        if (depth >= CODE_ALLOC_MAX_ATTEMPTS)
5635 +                return NULL;
5636 +
5637 +        return do_alloc_code(size, depth + 1);
5638 + #else
5639 +        uint8 *code = (uint8 *)vm_acquire(size);
5640 +        return code == VM_MAP_FAILED ? NULL : code;
5641 + #endif
5642 + }
5643 +
5644 + static inline uint8 *alloc_code(uint32 size)
5645 + {
5646 +        return do_alloc_code(size, 0);
5647 + }
5648 +
5649   void alloc_cache(void)
5650   {
5651          if (compiled_code) {
# Line 5149 | Line 5658 | void alloc_cache(void)
5658                  return;
5659          
5660          while (!compiled_code && cache_size) {
5661 <                if ((compiled_code = (uae_u8 *)vm_acquire(cache_size * 1024)) == VM_MAP_FAILED) {
5661 >                if ((compiled_code = alloc_code(cache_size * 1024)) == NULL) {
5662                          compiled_code = 0;
5663                          cache_size /= 2;
5664                  }
5665          }
5666 <        vm_protect(compiled_code, cache_size, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE);
5666 >        vm_protect(compiled_code, cache_size * 1024, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE);
5667          
5668          if (compiled_code) {
5669                  write_log("<JIT compiler> : actual translation cache size : %d KB at 0x%08X\n", cache_size, compiled_code);
# Line 5166 | Line 5675 | void alloc_cache(void)
5675  
5676  
5677  
5678 < extern cpuop_rettype op_illg_1 (uae_u32 opcode) REGPARAM;
5678 > extern void op_illg_1 (uae_u32 opcode) REGPARAM;
5679  
5680   static void calc_checksum(blockinfo* bi, uae_u32* c1, uae_u32* c2)
5681   {
5682 <    uae_u32 k1=0;
5683 <    uae_u32 k2=0;
5175 <    uae_s32 len=bi->len;
5176 <    uae_u32 tmp=bi->min_pcp;
5177 <    uae_u32* pos;
5682 >    uae_u32 k1 = 0;
5683 >    uae_u32 k2 = 0;
5684  
5685 <    len+=(tmp&3);
5686 <    tmp&=(~3);
5687 <    pos=(uae_u32*)tmp;
5685 > #if USE_CHECKSUM_INFO
5686 >    checksum_info *csi = bi->csi;
5687 >        Dif(!csi) abort();
5688 >        while (csi) {
5689 >                uae_s32 len = csi->length;
5690 >                uintptr tmp = (uintptr)csi->start_p;
5691 > #else
5692 >                uae_s32 len = bi->len;
5693 >                uintptr tmp = (uintptr)bi->min_pcp;
5694 > #endif
5695 >                uae_u32*pos;
5696  
5697 <    if (len<0 || len>MAX_CHECKSUM_LEN) {
5698 <        *c1=0;
5699 <        *c2=0;
5700 <    }
5701 <    else {
5702 <        while (len>0) {
5703 <            k1+=*pos;
5704 <            k2^=*pos;
5705 <            pos++;
5706 <            len-=4;
5697 >                len += (tmp & 3);
5698 >                tmp &= ~((uintptr)3);
5699 >                pos = (uae_u32 *)tmp;
5700 >
5701 >                if (len >= 0 && len <= MAX_CHECKSUM_LEN) {
5702 >                        while (len > 0) {
5703 >                                k1 += *pos;
5704 >                                k2 ^= *pos;
5705 >                                pos++;
5706 >                                len -= 4;
5707 >                        }
5708 >                }
5709 >
5710 > #if USE_CHECKSUM_INFO
5711 >                csi = csi->next;
5712          }
5713 <        *c1=k1;
5714 <        *c2=k2;
5715 <    }
5713 > #endif
5714 >
5715 >        *c1 = k1;
5716 >        *c2 = k2;
5717   }
5718  
5719 < static void show_checksum(blockinfo* bi)
5719 > #if 0
5720 > static void show_checksum(CSI_TYPE* csi)
5721   {
5722      uae_u32 k1=0;
5723      uae_u32 k2=0;
5724 <    uae_s32 len=bi->len;
5725 <    uae_u32 tmp=(uae_u32)bi->pc_p;
5724 >    uae_s32 len=CSI_LENGTH(csi);
5725 >    uae_u32 tmp=(uintptr)CSI_START_P(csi);
5726      uae_u32* pos;
5727  
5728      len+=(tmp&3);
# Line 5220 | Line 5741 | static void show_checksum(blockinfo* bi)
5741          write_log(" bla\n");
5742      }
5743   }
5744 + #endif
5745  
5746  
5747   int check_for_cache_miss(void)
# Line 5273 | Line 5795 | static int called_check_checksum(blockin
5795   static inline int block_check_checksum(blockinfo* bi)
5796   {
5797      uae_u32     c1,c2;
5798 <    int         isgood;
5798 >    bool        isgood;
5799      
5800      if (bi->status!=BI_NEED_CHECK)
5801          return 1;  /* This block is in a checked state */
5802      
5803      checksum_count++;
5804 +
5805      if (bi->c1 || bi->c2)
5806          calc_checksum(bi,&c1,&c2);
5807      else {
5808          c1=c2=1;  /* Make sure it doesn't match */
5809 <    }
5809 >        }
5810      
5811      isgood=(c1==bi->c1 && c2==bi->c2);
5812 +
5813      if (isgood) {
5814          /* This block is still OK. So we reactivate. Of course, that
5815             means we have to move it into the needs-to-be-flushed list */
# Line 5390 | Line 5914 | static __inline__ void match_states(bloc
5914      }
5915   }
5916  
5393 static uae_u8 popallspace[1024]; /* That should be enough space */
5394
5917   static __inline__ void create_popalls(void)
5918   {
5919    int i,r;
5920  
5921 +  if ((popallspace = alloc_code(POPALLSPACE_SIZE)) == NULL) {
5922 +          write_log("FATAL: Could not allocate popallspace!\n");
5923 +          abort();
5924 +  }
5925 +  vm_protect(popallspace, POPALLSPACE_SIZE, VM_PAGE_READ | VM_PAGE_WRITE);
5926 +
5927    current_compile_p=popallspace;
5928    set_target(current_compile_p);
5929   #if USE_PUSH_POP
# Line 5403 | Line 5931 | static __inline__ void create_popalls(vo
5931       registers before jumping back to the various get-out routines.
5932       This generates the code for it.
5933    */
5934 <  popall_do_nothing=current_compile_p;
5934 >  align_target(align_jumps);
5935 >  popall_do_nothing=get_target();
5936    for (i=0;i<N_REGS;i++) {
5937        if (need_to_preserve[i])
5938            raw_pop_l_r(i);
5939    }
5940 <  raw_jmp((uae_u32)do_nothing);
5412 <  align_target(32);
5940 >  raw_jmp((uintptr)do_nothing);
5941    
5942 +  align_target(align_jumps);
5943    popall_execute_normal=get_target();
5944    for (i=0;i<N_REGS;i++) {
5945        if (need_to_preserve[i])
5946            raw_pop_l_r(i);
5947    }
5948 <  raw_jmp((uae_u32)execute_normal);
5420 <  align_target(32);
5948 >  raw_jmp((uintptr)execute_normal);
5949  
5950 +  align_target(align_jumps);
5951    popall_cache_miss=get_target();
5952    for (i=0;i<N_REGS;i++) {
5953        if (need_to_preserve[i])
5954            raw_pop_l_r(i);
5955    }
5956 <  raw_jmp((uae_u32)cache_miss);
5428 <  align_target(32);
5956 >  raw_jmp((uintptr)cache_miss);
5957  
5958 +  align_target(align_jumps);
5959    popall_recompile_block=get_target();
5960    for (i=0;i<N_REGS;i++) {
5961        if (need_to_preserve[i])
5962            raw_pop_l_r(i);
5963    }
5964 <  raw_jmp((uae_u32)recompile_block);
5965 <  align_target(32);
5966 <  
5964 >  raw_jmp((uintptr)recompile_block);
5965 >
5966 >  align_target(align_jumps);
5967    popall_exec_nostats=get_target();
5968    for (i=0;i<N_REGS;i++) {
5969        if (need_to_preserve[i])
5970            raw_pop_l_r(i);
5971    }
5972 <  raw_jmp((uae_u32)exec_nostats);
5973 <  align_target(32);
5974 <  
5972 >  raw_jmp((uintptr)exec_nostats);
5973 >
5974 >  align_target(align_jumps);
5975    popall_check_checksum=get_target();
5976    for (i=0;i<N_REGS;i++) {
5977        if (need_to_preserve[i])
5978            raw_pop_l_r(i);
5979    }
5980 <  raw_jmp((uae_u32)check_checksum);
5981 <  align_target(32);
5982 <  
5980 >  raw_jmp((uintptr)check_checksum);
5981 >
5982 >  align_target(align_jumps);
5983    current_compile_p=get_target();
5984   #else
5985    popall_exec_nostats=(void *)exec_nostats;
# Line 5459 | Line 5988 | static __inline__ void create_popalls(vo
5988    popall_recompile_block=(void *)recompile_block;
5989    popall_do_nothing=(void *)do_nothing;
5990    popall_check_checksum=(void *)check_checksum;
5462  pushall_call_handler=get_target();  
5991   #endif
5992  
5993    /* And now, the code to do the matching pushes and then jump
# Line 5472 | Line 6000 | static __inline__ void create_popalls(vo
6000    }
6001   #endif
6002    r=REG_PC_TMP;
6003 <  raw_mov_l_rm(r,(uae_u32)&regs.pc_p);
6003 >  raw_mov_l_rm(r,(uintptr)&regs.pc_p);
6004 >  raw_and_l_ri(r,TAGMASK);
6005 >  raw_jmp_m_indexed((uintptr)cache_tags,r,SIZEOF_VOID_P);
6006 >
6007 > #if defined(X86_ASSEMBLY) || defined(X86_64_ASSEMBLY)
6008 >  align_target(align_jumps);
6009 >  m68k_compile_execute = (void (*)(void))get_target();
6010 >  for (i=N_REGS;i--;) {
6011 >          if (need_to_preserve[i])
6012 >                  raw_push_l_r(i);
6013 >  }
6014 >  align_target(align_loops);
6015 >  uae_u32 dispatch_loop = (uintptr)get_target();
6016 >  r=REG_PC_TMP;
6017 >  raw_mov_l_rm(r,(uintptr)&regs.pc_p);
6018    raw_and_l_ri(r,TAGMASK);
6019 <  raw_jmp_m_indexed((uae_u32)cache_tags,r,4);
6019 >  raw_call_m_indexed((uintptr)cache_tags,r,SIZEOF_VOID_P);
6020 >  raw_cmp_l_mi((uintptr)&regs.spcflags,0);
6021 >  raw_jcc_b_oponly(NATIVE_CC_EQ);
6022 >  emit_byte(dispatch_loop-((uintptr)get_target()+1));
6023 >  raw_call((uintptr)m68k_do_specialties);
6024 >  raw_test_l_rr(REG_RESULT,REG_RESULT);
6025 >  raw_jcc_b_oponly(NATIVE_CC_EQ);
6026 >  emit_byte(dispatch_loop-((uintptr)get_target()+1));
6027 >  raw_cmp_b_mi((uintptr)&quit_program,0);
6028 >  raw_jcc_b_oponly(NATIVE_CC_EQ);
6029 >  emit_byte(dispatch_loop-((uintptr)get_target()+1));
6030 >  for (i=0;i<N_REGS;i++) {
6031 >          if (need_to_preserve[i])
6032 >                  raw_pop_l_r(i);
6033 >  }
6034 >  raw_ret();
6035 > #endif
6036 >
6037 >  // no need to further write into popallspace
6038 >  vm_protect(popallspace, POPALLSPACE_SIZE, VM_PAGE_READ | VM_PAGE_EXECUTE);
6039   }
6040  
6041   static __inline__ void reset_lists(void)
# Line 5492 | Line 6053 | static void prepare_block(blockinfo* bi)
6053      int i;
6054  
6055      set_target(current_compile_p);
6056 <    align_target(32);
6056 >    align_target(align_jumps);
6057      bi->direct_pen=(cpuop_func *)get_target();
6058 <    raw_mov_l_rm(0,(uae_u32)&(bi->pc_p));
6059 <    raw_mov_l_mr((uae_u32)&regs.pc_p,0);
6060 <    raw_jmp((uae_u32)popall_execute_normal);
6058 >    raw_mov_l_rm(0,(uintptr)&(bi->pc_p));
6059 >    raw_mov_l_mr((uintptr)&regs.pc_p,0);
6060 >    raw_jmp((uintptr)popall_execute_normal);
6061  
6062 <    align_target(32);
6062 >    align_target(align_jumps);
6063      bi->direct_pcc=(cpuop_func *)get_target();
6064 <    raw_mov_l_rm(0,(uae_u32)&(bi->pc_p));
6065 <    raw_mov_l_mr((uae_u32)&regs.pc_p,0);
6066 <    raw_jmp((uae_u32)popall_check_checksum);
5506 <
5507 <    align_target(32);
6064 >    raw_mov_l_rm(0,(uintptr)&(bi->pc_p));
6065 >    raw_mov_l_mr((uintptr)&regs.pc_p,0);
6066 >    raw_jmp((uintptr)popall_check_checksum);
6067      current_compile_p=get_target();
6068  
6069      bi->deplist=NULL;
# Line 5518 | Line 6077 | static void prepare_block(blockinfo* bi)
6077      //bi->env=empty_ss;
6078   }
6079  
6080 + // OPCODE is in big endian format, use cft_map() beforehand, if needed.
6081 + static inline void reset_compop(int opcode)
6082 + {
6083 +        compfunctbl[opcode] = NULL;
6084 +        nfcompfunctbl[opcode] = NULL;
6085 + }
6086 +
6087 + static int read_opcode(const char *p)
6088 + {
6089 +        int opcode = 0;
6090 +        for (int i = 0; i < 4; i++) {
6091 +                int op = p[i];
6092 +                switch (op) {
6093 +                case '0': case '1': case '2': case '3': case '4':
6094 +                case '5': case '6': case '7': case '8': case '9':
6095 +                        opcode = (opcode << 4) | (op - '0');
6096 +                        break;
6097 +                case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
6098 +                        opcode = (opcode << 4) | ((op - 'a') + 10);
6099 +                        break;
6100 +                case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
6101 +                        opcode = (opcode << 4) | ((op - 'A') + 10);
6102 +                        break;
6103 +                default:
6104 +                        return -1;
6105 +                }
6106 +        }
6107 +        return opcode;
6108 + }
6109 +
6110 + static bool merge_blacklist()
6111 + {
6112 +        const char *blacklist = PrefsFindString("jitblacklist");
6113 +        if (blacklist) {
6114 +                const char *p = blacklist;
6115 +                for (;;) {
6116 +                        if (*p == 0)
6117 +                                return true;
6118 +
6119 +                        int opcode1 = read_opcode(p);
6120 +                        if (opcode1 < 0)
6121 +                                return false;
6122 +                        p += 4;
6123 +
6124 +                        int opcode2 = opcode1;
6125 +                        if (*p == '-') {
6126 +                                p++;
6127 +                                opcode2 = read_opcode(p);
6128 +                                if (opcode2 < 0)
6129 +                                        return false;
6130 +                                p += 4;
6131 +                        }
6132 +
6133 +                        if (*p == 0 || *p == ';') {
6134 +                                write_log("<JIT compiler> : blacklist opcodes : %04x-%04x\n", opcode1, opcode2);
6135 +                                for (int opcode = opcode1; opcode <= opcode2; opcode++)
6136 +                                        reset_compop(cft_map(opcode));
6137 +
6138 +                                if (*p++ == ';')
6139 +                                        continue;
6140 +
6141 +                                return true;
6142 +                        }
6143 +
6144 +                        return false;
6145 +                }
6146 +        }
6147 +        return true;
6148 + }
6149 +
6150   void build_comp(void)
6151   {
6152          int i;
# Line 5547 | Line 6176 | void build_comp(void)
6176      write_log ("<JIT compiler> : building compiler function tables\n");
6177          
6178          for (opcode = 0; opcode < 65536; opcode++) {
6179 +                reset_compop(opcode);
6180                  nfcpufunctbl[opcode] = op_illg_1;
5551                compfunctbl[opcode] = NULL;
5552                nfcompfunctbl[opcode] = NULL;
6181                  prop[opcode].use_flags = 0x1f;
6182                  prop[opcode].set_flags = 0x1f;
6183                  prop[opcode].cflow = fl_trap; // ILLEGAL instructions do trap
# Line 5557 | Line 6185 | void build_comp(void)
6185          
6186          for (i = 0; tbl[i].opcode < 65536; i++) {
6187                  int cflow = table68k[tbl[i].opcode].cflow;
6188 +                if (USE_INLINING && ((cflow & fl_const_jump) != 0))
6189 +                        cflow = fl_const_jump;
6190 +                else
6191 +                        cflow &= ~fl_const_jump;
6192                  prop[cft_map(tbl[i].opcode)].cflow = cflow;
6193  
6194                  int uses_fpu = tbl[i].specific & 32;
# Line 5611 | Line 6243 | void build_comp(void)
6243                          nfcpufunctbl[cft_map(tbl[i].opcode)] = nfctbl[i].handler;
6244          }
6245  
6246 +        /* Merge in blacklist */
6247 +        if (!merge_blacklist())
6248 +                write_log("<JIT compiler> : blacklist merge failure!\n");
6249 +
6250      count=0;
6251      for (opcode = 0; opcode < 65536; opcode++) {
6252          if (compfunctbl[cft_map(opcode)])
# Line 5729 | Line 6365 | static inline void flush_icache_lazy(int
6365          active=NULL;
6366   }
6367  
6368 + void flush_icache_range(uae_u32 start, uae_u32 length)
6369 + {
6370 +        if (!active)
6371 +                return;
6372 +
6373 + #if LAZY_FLUSH_ICACHE_RANGE
6374 +        uae_u8 *start_p = get_real_address(start);
6375 +        blockinfo *bi = active;
6376 +        while (bi) {
6377 + #if USE_CHECKSUM_INFO
6378 +                bool invalidate = false;
6379 +                for (checksum_info *csi = bi->csi; csi && !invalidate; csi = csi->next)
6380 +                        invalidate = (((start_p - csi->start_p) < csi->length) ||
6381 +                                                  ((csi->start_p - start_p) < length));
6382 + #else
6383 +                // Assume system is consistent and would invalidate the right range
6384 +                const bool invalidate = (bi->pc_p - start_p) < length;
6385 + #endif
6386 +                if (invalidate) {
6387 +                        uae_u32 cl = cacheline(bi->pc_p);
6388 +                        if (bi == cache_tags[cl + 1].bi)
6389 +                                        cache_tags[cl].handler = (cpuop_func *)popall_execute_normal;
6390 +                        bi->handler_to_use = (cpuop_func *)popall_execute_normal;
6391 +                        set_dhtu(bi, bi->direct_pen);
6392 +                        bi->status = BI_NEED_RECOMP;
6393 +                }
6394 +                bi = bi->next;
6395 +        }
6396 +        return;
6397 + #endif
6398 +        flush_icache(-1);
6399 + }
6400 +
6401   static void catastrophe(void)
6402   {
6403      abort();
# Line 5739 | Line 6408 | int failure;
6408   #define TARGET_M68K             0
6409   #define TARGET_POWERPC  1
6410   #define TARGET_X86              2
6411 + #define TARGET_X86_64   3
6412   #if defined(i386) || defined(__i386__)
6413   #define TARGET_NATIVE   TARGET_X86
6414   #endif
6415   #if defined(powerpc) || defined(__powerpc__)
6416   #define TARGET_NATIVE   TARGET_POWERPC
6417   #endif
6418 + #if defined(x86_64) || defined(__x86_64__)
6419 + #define TARGET_NATIVE   TARGET_X86_64
6420 + #endif
6421  
6422   #ifdef ENABLE_MON
6423 < static uae_u32 mon_read_byte_jit(uae_u32 addr)
6423 > static uae_u32 mon_read_byte_jit(uintptr addr)
6424   {
6425          uae_u8 *m = (uae_u8 *)addr;
6426 <        return (uae_u32)(*m);
6426 >        return (uintptr)(*m);
6427   }
6428  
6429 < static void mon_write_byte_jit(uae_u32 addr, uae_u32 b)
6429 > static void mon_write_byte_jit(uintptr addr, uae_u32 b)
6430   {
6431          uae_u8 *m = (uae_u8 *)addr;
6432          *m = b;
# Line 5770 | Line 6443 | void disasm_block(int target, uint8 * st
6443          sprintf(disasm_str, "%s $%x $%x",
6444                          target == TARGET_M68K ? "d68" :
6445                          target == TARGET_X86 ? "d86" :
6446 +                        target == TARGET_X86_64 ? "d8664" :
6447                          target == TARGET_POWERPC ? "d" : "x",
6448                          start, start + length - 1);
6449          
6450 <        uae_u32 (*old_mon_read_byte)(uae_u32) = mon_read_byte;
6451 <        void (*old_mon_write_byte)(uae_u32, uae_u32) = mon_write_byte;
6450 >        uae_u32 (*old_mon_read_byte)(uintptr) = mon_read_byte;
6451 >        void (*old_mon_write_byte)(uintptr, uae_u32) = mon_write_byte;
6452          
6453          mon_read_byte = mon_read_byte_jit;
6454          mon_write_byte = mon_write_byte_jit;
# Line 5787 | Line 6461 | void disasm_block(int target, uint8 * st
6461   #endif
6462   }
6463  
6464 < static inline void disasm_native_block(uint8 *start, size_t length)
6464 > static void disasm_native_block(uint8 *start, size_t length)
6465   {
6466          disasm_block(TARGET_NATIVE, start, length);
6467   }
6468  
6469 < static inline void disasm_m68k_block(uint8 *start, size_t length)
6469 > static void disasm_m68k_block(uint8 *start, size_t length)
6470   {
6471          disasm_block(TARGET_M68K, start, length);
6472   }
# Line 5826 | Line 6500 | void compiler_dumpstate(void)
6500          
6501          write_log("### Block in Mac address space\n");
6502          write_log("M68K block   : %p\n",
6503 <                          (void *)get_virtual_address(last_regs_pc_p));
6503 >                          (void *)(uintptr)get_virtual_address(last_regs_pc_p));
6504          write_log("Native block : %p (%d bytes)\n",
6505 <                          (void *)get_virtual_address(last_compiled_block_addr),
6505 >                          (void *)(uintptr)get_virtual_address(last_compiled_block_addr),
6506                            get_blockinfo_addr(last_regs_pc_p)->direct_handler_size);
6507          write_log("\n");
6508   }
# Line 5850 | Line 6524 | static void compile_block(cpu_history* p
6524          int r;
6525          int was_comp=0;
6526          uae_u8 liveflags[MAXRUN+1];
6527 <        uae_u32 max_pcp=(uae_u32)pc_hist[0].location;
6528 <        uae_u32 min_pcp=max_pcp;
6527 > #if USE_CHECKSUM_INFO
6528 >        bool trace_in_rom = isinrom((uintptr)pc_hist[0].location);
6529 >        uintptr max_pcp=(uintptr)pc_hist[blocklen - 1].location;
6530 >        uintptr min_pcp=max_pcp;
6531 > #else
6532 >        uintptr max_pcp=(uintptr)pc_hist[0].location;
6533 >        uintptr min_pcp=max_pcp;
6534 > #endif
6535          uae_u32 cl=cacheline(pc_hist[0].location);
6536          void* specflags=(void*)&regs.spcflags;
6537          blockinfo* bi=NULL;
# Line 5890 | Line 6570 | static void compile_block(cpu_history* p
6570                  optlev++;
6571              bi->count=optcount[optlev]-1;
6572          }
6573 <        current_block_pc_p=(uae_u32)pc_hist[0].location;
6573 >        current_block_pc_p=(uintptr)pc_hist[0].location;
6574          
6575          remove_deps(bi); /* We are about to create new code */
6576          bi->optlevel=optlev;
6577          bi->pc_p=(uae_u8*)pc_hist[0].location;
6578 + #if USE_CHECKSUM_INFO
6579 +        free_checksum_info_chain(bi->csi);
6580 +        bi->csi = NULL;
6581 + #endif
6582          
6583          liveflags[blocklen]=0x1f; /* All flags needed afterwards */
6584          i=blocklen;
# Line 5902 | Line 6586 | static void compile_block(cpu_history* p
6586              uae_u16* currpcp=pc_hist[i].location;
6587              uae_u32 op=DO_GET_OPCODE(currpcp);
6588  
6589 <            if ((uae_u32)currpcp<min_pcp)
6590 <                min_pcp=(uae_u32)currpcp;
6591 <            if ((uae_u32)currpcp>max_pcp)
6592 <                max_pcp=(uae_u32)currpcp;
6589 > #if USE_CHECKSUM_INFO
6590 >                trace_in_rom = trace_in_rom && isinrom((uintptr)currpcp);
6591 > #if USE_INLINING
6592 >                if (is_const_jump(op)) {
6593 >                        checksum_info *csi = alloc_checksum_info();
6594 >                        csi->start_p = (uae_u8 *)min_pcp;
6595 >                        csi->length = max_pcp - min_pcp + LONGEST_68K_INST;
6596 >                        csi->next = bi->csi;
6597 >                        bi->csi = csi;
6598 >                        max_pcp = (uintptr)currpcp;
6599 >                }
6600 > #endif
6601 >                min_pcp = (uintptr)currpcp;
6602 > #else
6603 >            if ((uintptr)currpcp<min_pcp)
6604 >                min_pcp=(uintptr)currpcp;
6605 >            if ((uintptr)currpcp>max_pcp)
6606 >                max_pcp=(uintptr)currpcp;
6607 > #endif
6608  
6609                  liveflags[i]=((liveflags[i+1]&
6610                                 (~prop[op].set_flags))|
# Line 5914 | Line 6613 | static void compile_block(cpu_history* p
6613                      liveflags[i]&= ~FLAG_Z;
6614          }
6615  
6616 + #if USE_CHECKSUM_INFO
6617 +        checksum_info *csi = alloc_checksum_info();
6618 +        csi->start_p = (uae_u8 *)min_pcp;
6619 +        csi->length = max_pcp - min_pcp + LONGEST_68K_INST;
6620 +        csi->next = bi->csi;
6621 +        bi->csi = csi;
6622 + #endif
6623 +
6624          bi->needed_flags=liveflags[0];
6625  
6626 <        align_target(32);
6626 >        align_target(align_loops);
6627          was_comp=0;
6628  
6629          bi->direct_handler=(cpuop_func *)get_target();
6630          set_dhtu(bi,bi->direct_handler);
6631          bi->status=BI_COMPILING;
6632 <        current_block_start_target=(uae_u32)get_target();
6632 >        current_block_start_target=(uintptr)get_target();
6633          
6634          log_startblock();
6635          
6636          if (bi->count>=0) { /* Need to generate countdown code */
6637 <            raw_mov_l_mi((uae_u32)&regs.pc_p,(uae_u32)pc_hist[0].location);
6638 <            raw_sub_l_mi((uae_u32)&(bi->count),1);
6639 <            raw_jl((uae_u32)popall_recompile_block);
6637 >            raw_mov_l_mi((uintptr)&regs.pc_p,(uintptr)pc_hist[0].location);
6638 >            raw_sub_l_mi((uintptr)&(bi->count),1);
6639 >            raw_jl((uintptr)popall_recompile_block);
6640          }
6641          if (optlev==0) { /* No need to actually translate */
6642              /* Execute normally without keeping stats */
6643 <            raw_mov_l_mi((uae_u32)&regs.pc_p,(uae_u32)pc_hist[0].location);
6644 <            raw_jmp((uae_u32)popall_exec_nostats);
6643 >            raw_mov_l_mi((uintptr)&regs.pc_p,(uintptr)pc_hist[0].location);
6644 >            raw_jmp((uintptr)popall_exec_nostats);
6645          }
6646          else {
6647              reg_alloc_run=0;
# Line 5948 | Line 6655 | static void compile_block(cpu_history* p
6655  
6656   #if JIT_DEBUG
6657                  if (JITDebug) {
6658 <                        raw_mov_l_mi((uae_u32)&last_regs_pc_p,(uae_u32)pc_hist[0].location);
6659 <                        raw_mov_l_mi((uae_u32)&last_compiled_block_addr,(uae_u32)current_block_start_target);
6658 >                        raw_mov_l_mi((uintptr)&last_regs_pc_p,(uintptr)pc_hist[0].location);
6659 >                        raw_mov_l_mi((uintptr)&last_compiled_block_addr,current_block_start_target);
6660                  }
6661   #endif
6662                  
# Line 5975 | Line 6682 | static void compile_block(cpu_history* p
6682                          comp_pc_p=(uae_u8*)pc_hist[i].location;
6683                          init_comp();
6684                      }
6685 <                    was_comp++;
6685 >                    was_comp=1;
6686  
6687                      comptbl[opcode](opcode);
6688                      freescratch();
# Line 6000 | Line 6707 | static void compile_block(cpu_history* p
6707   #if USE_NORMAL_CALLING_CONVENTION
6708                      raw_push_l_r(REG_PAR1);
6709   #endif
6710 <                    raw_mov_l_mi((uae_u32)&regs.pc_p,
6711 <                                 (uae_u32)pc_hist[i].location);
6712 <                    raw_call((uae_u32)cputbl[opcode]);
6713 <                    //raw_add_l_mi((uae_u32)&oink,1); // FIXME
6710 >                    raw_mov_l_mi((uintptr)&regs.pc_p,
6711 >                                 (uintptr)pc_hist[i].location);
6712 >                    raw_call((uintptr)cputbl[opcode]);
6713 > #if PROFILE_UNTRANSLATED_INSNS
6714 >                        // raw_cputbl_count[] is indexed with plain opcode (in m68k order)
6715 >                        raw_add_l_mi((uintptr)&raw_cputbl_count[cft_map(opcode)],1);
6716 > #endif
6717   #if USE_NORMAL_CALLING_CONVENTION
6718                      raw_inc_sp(4);
6719   #endif
6010                    if (needed_flags) {
6011                        //raw_mov_l_mi((uae_u32)&foink3,(uae_u32)opcode+65536);
6012                    }
6013                    else {
6014                        //raw_mov_l_mi((uae_u32)&foink3,(uae_u32)opcode);
6015                    }
6720                      
6721                      if (i < blocklen - 1) {
6722                          uae_s8* branchadd;
6723                          
6724 <                        raw_mov_l_rm(0,(uae_u32)specflags);
6724 >                        raw_mov_l_rm(0,(uintptr)specflags);
6725                          raw_test_l_rr(0,0);
6726                          raw_jz_b_oponly();
6727                          branchadd=(uae_s8 *)get_target();
6728                          emit_byte(0);
6729 <                        raw_jmp((uae_u32)popall_do_nothing);
6730 <                        *branchadd=(uae_u32)get_target()-(uae_u32)branchadd-1;
6729 >                        raw_jmp((uintptr)popall_do_nothing);
6730 >                        *branchadd=(uintptr)get_target()-(uintptr)branchadd-1;
6731                      }
6732                  }
6733              }
# Line 6057 | Line 6761 | static void compile_block(cpu_history* p
6761                  log_flush();
6762  
6763              if (next_pc_p) { /* A branch was registered */
6764 <                uae_u32 t1=next_pc_p;
6765 <                uae_u32 t2=taken_pc_p;
6764 >                uintptr t1=next_pc_p;
6765 >                uintptr t2=taken_pc_p;
6766                  int     cc=branch_cc;
6767                  
6768                  uae_u32* branchadd;
# Line 6083 | Line 6787 | static void compile_block(cpu_history* p
6787                  /* predicted outcome */
6788                  tbi=get_blockinfo_addr_new((void*)t1,1);
6789                  match_states(tbi);
6790 <                raw_cmp_l_mi((uae_u32)specflags,0);
6790 >                raw_cmp_l_mi((uintptr)specflags,0);
6791                  raw_jcc_l_oponly(4);
6792                  tba=(uae_u32*)get_target();
6793 <                emit_long(get_handler(t1)-((uae_u32)tba+4));
6794 <                raw_mov_l_mi((uae_u32)&regs.pc_p,t1);
6795 <                raw_jmp((uae_u32)popall_do_nothing);
6793 >                emit_long(get_handler(t1)-((uintptr)tba+4));
6794 >                raw_mov_l_mi((uintptr)&regs.pc_p,t1);
6795 >                raw_jmp((uintptr)popall_do_nothing);
6796                  create_jmpdep(bi,0,tba,t1);
6797  
6798 <                align_target(16);
6798 >                align_target(align_jumps);
6799                  /* not-predicted outcome */
6800 <                *branchadd=(uae_u32)get_target()-((uae_u32)branchadd+4);
6800 >                *branchadd=(uintptr)get_target()-((uintptr)branchadd+4);
6801                  live=tmp; /* Ouch again */
6802                  tbi=get_blockinfo_addr_new((void*)t2,1);
6803                  match_states(tbi);
6804  
6805                  //flush(1); /* Can only get here if was_comp==1 */
6806 <                raw_cmp_l_mi((uae_u32)specflags,0);
6806 >                raw_cmp_l_mi((uintptr)specflags,0);
6807                  raw_jcc_l_oponly(4);
6808                  tba=(uae_u32*)get_target();
6809 <                emit_long(get_handler(t2)-((uae_u32)tba+4));
6810 <                raw_mov_l_mi((uae_u32)&regs.pc_p,t2);
6811 <                raw_jmp((uae_u32)popall_do_nothing);
6809 >                emit_long(get_handler(t2)-((uintptr)tba+4));
6810 >                raw_mov_l_mi((uintptr)&regs.pc_p,t2);
6811 >                raw_jmp((uintptr)popall_do_nothing);
6812                  create_jmpdep(bi,1,tba,t2);
6813              }          
6814              else
# Line 6118 | Line 6822 | static void compile_block(cpu_history* p
6822                      r=live.state[PC_P].realreg;
6823                          raw_and_l_ri(r,TAGMASK);
6824                          int r2 = (r==0) ? 1 : 0;
6825 <                        raw_mov_l_ri(r2,(uae_u32)popall_do_nothing);
6826 <                        raw_cmp_l_mi((uae_u32)specflags,0);
6827 <                        raw_cmov_l_rm_indexed(r2,(uae_u32)cache_tags,r,4,4);
6825 >                        raw_mov_l_ri(r2,(uintptr)popall_do_nothing);
6826 >                        raw_cmp_l_mi((uintptr)specflags,0);
6827 >                        raw_cmov_l_rm_indexed(r2,(uintptr)cache_tags,r,SIZEOF_VOID_P,SIZEOF_VOID_P);
6828                          raw_jmp_r(r2);
6829                  }
6830                  else if (was_comp && isconst(PC_P)) {
# Line 6128 | Line 6832 | static void compile_block(cpu_history* p
6832                      uae_u32* tba;
6833                      blockinfo* tbi;
6834  
6835 <                    tbi=get_blockinfo_addr_new((void*)v,1);
6835 >                    tbi=get_blockinfo_addr_new((void*)(uintptr)v,1);
6836                      match_states(tbi);
6837  
6838 <                        raw_cmp_l_mi((uae_u32)specflags,0);
6838 >                        raw_cmp_l_mi((uintptr)specflags,0);
6839                          raw_jcc_l_oponly(4);
6840                      tba=(uae_u32*)get_target();
6841 <                    emit_long(get_handler(v)-((uae_u32)tba+4));
6842 <                    raw_mov_l_mi((uae_u32)&regs.pc_p,v);
6843 <                    raw_jmp((uae_u32)popall_do_nothing);
6841 >                    emit_long(get_handler(v)-((uintptr)tba+4));
6842 >                    raw_mov_l_mi((uintptr)&regs.pc_p,v);
6843 >                    raw_jmp((uintptr)popall_do_nothing);
6844                      create_jmpdep(bi,0,tba,v);
6845                  }
6846                  else {
6847                      r=REG_PC_TMP;
6848 <                    raw_mov_l_rm(r,(uae_u32)&regs.pc_p);
6848 >                    raw_mov_l_rm(r,(uintptr)&regs.pc_p);
6849                          raw_and_l_ri(r,TAGMASK);
6850                          int r2 = (r==0) ? 1 : 0;
6851 <                        raw_mov_l_ri(r2,(uae_u32)popall_do_nothing);
6852 <                        raw_cmp_l_mi((uae_u32)specflags,0);
6853 <                        raw_cmov_l_rm_indexed(r2,(uae_u32)cache_tags,r,4,4);
6851 >                        raw_mov_l_ri(r2,(uintptr)popall_do_nothing);
6852 >                        raw_cmp_l_mi((uintptr)specflags,0);
6853 >                        raw_cmov_l_rm_indexed(r2,(uintptr)cache_tags,r,SIZEOF_VOID_P,SIZEOF_VOID_P);
6854                          raw_jmp_r(r2);
6855                  }
6856              }
# Line 6160 | Line 6864 | static void compile_block(cpu_history* p
6864          big_to_small_state(&live,&(bi->env));
6865   #endif
6866  
6867 + #if USE_CHECKSUM_INFO
6868 +        remove_from_list(bi);
6869 +        if (trace_in_rom) {
6870 +                // No need to checksum that block trace on cache invalidation
6871 +                free_checksum_info_chain(bi->csi);
6872 +                bi->csi = NULL;
6873 +                add_to_dormant(bi);
6874 +        }
6875 +        else {
6876 +            calc_checksum(bi,&(bi->c1),&(bi->c2));
6877 +                add_to_active(bi);
6878 +        }
6879 + #else
6880          if (next_pc_p+extra_len>=max_pcp &&
6881              next_pc_p+extra_len<max_pcp+LONGEST_68K_INST)
6882              max_pcp=next_pc_p+extra_len;  /* extra_len covers flags magic */
6883          else
6884              max_pcp+=LONGEST_68K_INST;
6885 +
6886          bi->len=max_pcp-min_pcp;
6887          bi->min_pcp=min_pcp;
6888 <                    
6888 >        
6889          remove_from_list(bi);
6890          if (isinrom(min_pcp) && isinrom(max_pcp)) {
6891              add_to_dormant(bi); /* No need to checksum it on cache flush.
# Line 6178 | Line 6896 | static void compile_block(cpu_history* p
6896              calc_checksum(bi,&(bi->c1),&(bi->c2));
6897              add_to_active(bi);
6898          }
6899 + #endif
6900          
6901          current_cache_size += get_target() - (uae_u8 *)current_compile_p;
6902          
# Line 6197 | Line 6916 | static void compile_block(cpu_history* p
6916   #endif
6917          
6918          log_dump();
6919 <        align_target(32);
6919 >        align_target(align_jumps);
6920  
6921          /* This is the non-direct handler */
6922          bi->handler=
6923              bi->handler_to_use=(cpuop_func *)get_target();
6924 <        raw_cmp_l_mi((uae_u32)&regs.pc_p,(uae_u32)pc_hist[0].location);
6925 <        raw_jnz((uae_u32)popall_cache_miss);
6924 >        raw_cmp_l_mi((uintptr)&regs.pc_p,(uintptr)pc_hist[0].location);
6925 >        raw_jnz((uintptr)popall_cache_miss);
6926          comp_pc_p=(uae_u8*)pc_hist[0].location;
6927  
6928          bi->status=BI_FINALIZING;
# Line 6211 | Line 6930 | static void compile_block(cpu_history* p
6930          match_states(bi);
6931          flush(1);
6932  
6933 <        raw_jmp((uae_u32)bi->direct_handler);
6933 >        raw_jmp((uintptr)bi->direct_handler);
6934  
6216        align_target(32);
6935          current_compile_p=get_target();
6218
6936          raise_in_cl_list(bi);
6937          
6938          /* We will flush soon, anyway, so let's do it now */
# Line 6241 | Line 6958 | void exec_nostats(void)
6958   {
6959          for (;;)  {
6960                  uae_u32 opcode = GET_OPCODE;
6244 #ifdef X86_ASSEMBLY__disable
6245                __asm__ __volatile__("\tpushl %%ebp\n\tcall *%%ebx\n\tpopl %%ebp" /* FIXME */
6246                                                         : : "b" (cpufunctbl[opcode]), "a" (opcode)
6247                                                         : "%edx", "%ecx", "%esi", "%edi",  "%ebp", "memory", "cc");
6248 #else
6961                  (*cpufunctbl[opcode])(opcode);
6250 #endif
6962                  if (end_block(opcode) || SPCFLAGS_TEST(SPCFLAG_ALL)) {
6963                          return; /* We will deal with the spcflags in the caller */
6964                  }
# Line 6272 | Line 6983 | void execute_normal(void)
6983   #if FLIGHT_RECORDER
6984                          m68k_record_step(m68k_getpc());
6985   #endif
6275 #ifdef X86_ASSEMBLY__disable
6276                        __asm__ __volatile__("\tpushl %%ebp\n\tcall *%%ebx\n\tpopl %%ebp" /* FIXME */
6277                                                                 : : "b" (cpufunctbl[opcode]), "a" (opcode)
6278                                                                 : "%edx", "%ecx", "%esi", "%edi", "%ebp", "memory", "cc");
6279 #else
6986                          (*cpufunctbl[opcode])(opcode);
6281 #endif
6987                          if (end_block(opcode) || SPCFLAGS_TEST(SPCFLAG_ALL) || blocklen>=MAXRUN) {
6988                                  compile_block(pc_hist, blocklen);
6989                                  return; /* We will deal with the spcflags in the caller */
# Line 6291 | Line 6996 | void execute_normal(void)
6996  
6997   typedef void (*compiled_handler)(void);
6998  
6999 + #if defined(X86_ASSEMBLY) || defined(X86_64_ASSEMBLY)
7000 + void (*m68k_compile_execute)(void) = NULL;
7001 + #else
7002   void m68k_do_compile_execute(void)
7003   {
7004          for (;;) {
6297 #ifdef X86_ASSEMBLY
6298                __asm__ __volatile__("\tpushl %%ebp\n\tcall *%%ebx\n\tpopl %%ebp" /* FIXME */
6299                                                         : : "b" (cache_tags[cacheline(regs.pc_p)].handler)
6300                                                         : "%edx", "%ecx", "%eax", "%esi", "%edi", "%ebp", "memory", "cc");
6301 #else
7005                  ((compiled_handler)(pushall_call_handler))();
6303 #endif
7006                  /* Whenever we return from that, we should check spcflags */
7007                  if (SPCFLAGS_TEST(SPCFLAG_ALL)) {
7008                          if (m68k_do_specialties ())
# Line 6308 | Line 7010 | void m68k_do_compile_execute(void)
7010                  }
7011          }
7012   }
7013 + #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines