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.4 by gbeauche, 2002-09-18T11:41:56Z vs.
Revision 1.11 by gbeauche, 2002-10-03T16:13: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-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   #if !REAL_ADDRESSING && !DIRECT_ADDRESSING
27   #error "Only Real or Direct Addressing is supported with the JIT Compiler"
28   #endif
# Line 44 | Line 69
69   #endif
70  
71   #ifndef WIN32
72 < #define PROFILE_COMPILE_TIME    1
72 > #define PROFILE_COMPILE_TIME            1
73 > #define PROFILE_UNTRANSLATED_INSNS      1
74   #endif
75  
76   #ifdef WIN32
# Line 69 | Line 95 | static clock_t emul_start_time = 0;
95   static clock_t emul_end_time    = 0;
96   #endif
97  
98 + #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   compop_func *compfunctbl[65536];
110   compop_func *nfcompfunctbl[65536];
111   cpuop_func *nfcpufunctbl[65536];
112   uae_u8* comp_pc_p;
113  
114 + // From newcpu.cpp
115 + extern bool quit_program;
116 +
117   // gb-- Extra data for Basilisk II/JIT
118   #if JIT_DEBUG
119   static bool             JITDebug                        = false;        // Enable runtime disassemblers through mon?
# Line 88 | Line 128 | static bool            lazy_flush                      = true;         // Fl
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 + static bool             tune_alignment          = true;         // Tune code alignments for running CPU ?
132 + static int              align_loops                     = 32;           // Align the start of loops
133 + static int              align_jumps                     = 32;           // Align the start of jumps
134   static int              zero_fd                         = -1;
135   static int              optcount[10]            = {
136          10,             // How often a block has to be executed before it is translated
# Line 104 | Line 147 | struct op_properties {
147   };
148   static op_properties prop[65536];
149  
107 // gb-- Control Flow Predicates
108
150   static inline int end_block(uae_u32 opcode)
151   {
152          return (prop[opcode].cflow & fl_end_block);
153   }
154  
155 < static inline bool may_trap(uae_u32 opcode)
155 > static inline bool is_const_jump(uae_u32 opcode)
156   {
157 <        return (prop[opcode].cflow & fl_trap);
157 >        return (prop[opcode].cflow == fl_const_jump);
158   }
159  
160   uae_u8* start_pc_p;
# Line 491 | Line 532 | static void prepare_block(blockinfo* bi)
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 <   of the free list.
535 >   off the free list.
536  
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 < #if USE_SEPARATE_BIA
543 < const int BLOCKINFO_POOL_SIZE = 128;
544 < struct blockinfo_pool {
545 <        blockinfo bi[BLOCKINFO_POOL_SIZE];
546 <        blockinfo_pool *next;
542 > 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   };
507 static blockinfo_pool * blockinfo_pools = 0;
508 static blockinfo *              free_blockinfos = 0;
509 #endif
560  
561 < static __inline__ blockinfo *alloc_blockinfo(void)
561 > template< class T >
562 > LazyBlockAllocator<T>::~LazyBlockAllocator()
563   {
564 < #if USE_SEPARATE_BIA
565 <        if (!free_blockinfos) {
566 <                // There is no blockinfo struct left, allocate a new
567 <                // pool and link the chunks into the free list
568 <                blockinfo_pool *bi_pool = (blockinfo_pool *)malloc(sizeof(blockinfo_pool));
569 <                for (blockinfo *bi = &bi_pool->bi[0]; bi < &bi_pool->bi[BLOCKINFO_POOL_SIZE]; bi++) {
570 <                        bi->next = free_blockinfos;
571 <                        free_blockinfos = bi;
564 >        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                  }
583 <                bi_pool->next = blockinfo_pools;
584 <                blockinfo_pools = bi_pool;
583 >                newPool->next = mPools;
584 >                mPools = newPool;
585          }
586 <        blockinfo *bi = free_blockinfos;
587 <        free_blockinfos = bi->next;
588 < #else
528 <        blockinfo *bi = (blockinfo*)current_compile_p;
529 <        current_compile_p += sizeof(blockinfo);
530 < #endif
531 <        return bi;
586 >        T * chunk = mChunks;
587 >        mChunks = chunk->next;
588 >        return chunk;
589   }
590  
591 < static __inline__ void free_blockinfo(blockinfo *bi)
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 +        }
607 +
608 +        void release(T * const chunk) {
609 +                // Deallocated on invalidation
610 +        }
611 + };
612 +
613   #if USE_SEPARATE_BIA
614 <        bi->next = free_blockinfos;
615 <        free_blockinfos = bi;
614 > static LazyBlockAllocator<blockinfo> BlockInfoAllocator;
615 > static LazyBlockAllocator<checksum_info> ChecksumInfoAllocator;
616 > #else
617 > static HardBlockAllocator<blockinfo> BlockInfoAllocator;
618 > static HardBlockAllocator<checksum_info> ChecksumInfoAllocator;
619   #endif
620 +
621 + 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 void free_blockinfo_pools(void)
628 > static __inline__ void free_checksum_info(checksum_info *csi)
629   {
630 < #if USE_SEPARATE_BIA
631 <        int blockinfo_pool_count = 0;
632 <        blockinfo_pool *curr_pool = blockinfo_pools;
633 <        while (curr_pool) {
634 <                blockinfo_pool_count++;
635 <                blockinfo_pool *dead_pool = curr_pool;
636 <                curr_pool = curr_pool->next;
637 <                free(dead_pool);
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 <        uae_u32 blockinfo_pools_size = blockinfo_pool_count * BLOCKINFO_POOL_SIZE * sizeof(blockinfo);
643 <        write_log("### Blockinfo allocation statistics\n");
644 <        write_log("Number of blockinfo pools  : %d\n", blockinfo_pool_count);
645 <        write_log("Total number of blockinfos : %d (%d KB)\n",
646 <                          blockinfo_pool_count * BLOCKINFO_POOL_SIZE,
647 <                          blockinfo_pools_size / 1024);
648 <        write_log("\n");
641 > }
642 >
643 > static __inline__ blockinfo *alloc_blockinfo(void)
644 > {
645 >        blockinfo *bi = BlockInfoAllocator.acquire();
646 > #if USE_CHECKSUM_INFO
647 >        bi->csi = NULL;
648 > #endif
649 >        return bi;
650 > }
651 >
652 > static __inline__ void free_blockinfo(blockinfo *bi)
653 > {
654 > #if USE_CHECKSUM_INFO
655 >        free_checksum_info_chain(bi->csi);
656 >        bi->csi = NULL;
657   #endif
658 +        BlockInfoAllocator.release(bi);
659   }
660  
661   static __inline__ void alloc_blockinfos(void)
# Line 4562 | Line 4659 | void compiler_init(void)
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 +        write_log("<JIT compiler> : alignment for loops, jumps are %d, %d\n", align_loops, align_jumps);
4663          
4664          // Translation cache flush mechanism
4665          lazy_flush = PrefsFindBool("jitlazyflush");
# Line 4572 | Line 4670 | void compiler_init(void)
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 +        write_log("<JIT compiler> : block inlining : %s\n", str_on_off(USE_INLINING));
4674          write_log("<JIT compiler> : separate blockinfo allocation : %s\n", str_on_off(USE_SEPARATE_BIA));
4675          
4676          // Build compiler tables
# Line 4579 | Line 4678 | void compiler_init(void)
4678          
4679          initialized = true;
4680          
4681 + #if PROFILE_UNTRANSLATED_INSNS
4682 +        write_log("<JIT compiler> : gather statistics on untranslated insns count\n");
4683 + #endif
4684 +
4685   #if PROFILE_COMPILE_TIME
4686          write_log("<JIT compiler> : gather statistics on translation time\n");
4687          emul_start_time = clock();
# Line 4597 | Line 4700 | void compiler_exit(void)
4700                  compiled_code = 0;
4701          }
4702          
4600        // Deallocate blockinfo pools
4601        free_blockinfo_pools();
4602        
4703   #ifndef WIN32
4704          // Close /dev/zero
4705          if (zero_fd > 0)
# Line 4615 | Line 4715 | void compiler_exit(void)
4715                  100.0*double(compile_time)/double(emul_time));
4716          write_log("\n");
4717   #endif
4718 +
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   }
4741  
4742   bool compiler_use_jit(void)
# Line 5174 | Line 5296 | extern cpuop_rettype op_illg_1 (uae_u32
5296  
5297   static void calc_checksum(blockinfo* bi, uae_u32* c1, uae_u32* c2)
5298   {
5299 <    uae_u32 k1=0;
5300 <    uae_u32 k2=0;
5179 <    uae_s32 len=bi->len;
5180 <    uae_u32 tmp=bi->min_pcp;
5181 <    uae_u32* pos;
5299 >    uae_u32 k1 = 0;
5300 >    uae_u32 k2 = 0;
5301  
5302 <    len+=(tmp&3);
5303 <    tmp&=(~3);
5304 <    pos=(uae_u32*)tmp;
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  
5314 <    if (len<0 || len>MAX_CHECKSUM_LEN) {
5315 <        *c1=0;
5316 <        *c2=0;
5317 <    }
5318 <    else {
5319 <        while (len>0) {
5320 <            k1+=*pos;
5321 <            k2^=*pos;
5322 <            pos++;
5323 <            len-=4;
5314 >                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 >
5327 > #if USE_CHECKSUM_INFO
5328 >                csi = csi->next;
5329          }
5330 <        *c1=k1;
5331 <        *c2=k2;
5332 <    }
5330 > #endif
5331 >
5332 >        *c1 = k1;
5333 >        *c2 = k2;
5334   }
5335  
5336 < static void show_checksum(blockinfo* bi)
5336 > #if 0
5337 > static void show_checksum(CSI_TYPE* csi)
5338   {
5339      uae_u32 k1=0;
5340      uae_u32 k2=0;
5341 <    uae_s32 len=bi->len;
5342 <    uae_u32 tmp=(uae_u32)bi->pc_p;
5341 >    uae_s32 len=CSI_LENGTH(csi);
5342 >    uae_u32 tmp=(uae_u32)CSI_START_P(csi);
5343      uae_u32* pos;
5344  
5345      len+=(tmp&3);
# Line 5224 | Line 5358 | static void show_checksum(blockinfo* bi)
5358          write_log(" bla\n");
5359      }
5360   }
5361 + #endif
5362  
5363  
5364   int check_for_cache_miss(void)
# Line 5277 | Line 5412 | static int called_check_checksum(blockin
5412   static inline int block_check_checksum(blockinfo* bi)
5413   {
5414      uae_u32     c1,c2;
5415 <    int         isgood;
5415 >    bool        isgood;
5416      
5417      if (bi->status!=BI_NEED_CHECK)
5418          return 1;  /* This block is in a checked state */
5419      
5420      checksum_count++;
5421 +
5422      if (bi->c1 || bi->c2)
5423          calc_checksum(bi,&c1,&c2);
5424      else {
5425          c1=c2=1;  /* Make sure it doesn't match */
5426 <    }
5426 >        }
5427      
5428      isgood=(c1==bi->c1 && c2==bi->c2);
5429 +
5430      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 */
# Line 5407 | Line 5544 | static __inline__ void create_popalls(vo
5544       registers before jumping back to the various get-out routines.
5545       This generates the code for it.
5546    */
5547 <  popall_do_nothing=current_compile_p;
5547 >  align_target(align_jumps);
5548 >  popall_do_nothing=get_target();
5549    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);
5416  align_target(32);
5554    
5555 +  align_target(align_jumps);
5556    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);
5424  align_target(32);
5562  
5563 +  align_target(align_jumps);
5564    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);
5432  align_target(32);
5570  
5571 +  align_target(align_jumps);
5572    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 <  align_target(32);
5579 <  
5578 >
5579 >  align_target(align_jumps);
5580    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 <  align_target(32);
5587 <  
5586 >
5587 >  align_target(align_jumps);
5588    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 <  align_target(32);
5595 <  
5594 >
5595 >  align_target(align_jumps);
5596    current_compile_p=get_target();
5597   #else
5598    popall_exec_nostats=(void *)exec_nostats;
# Line 5463 | Line 5601 | static __inline__ void create_popalls(vo
5601    popall_recompile_block=(void *)recompile_block;
5602    popall_do_nothing=(void *)do_nothing;
5603    popall_check_checksum=(void *)check_checksum;
5466  pushall_call_handler=get_target();  
5604   #endif
5605  
5606    /* And now, the code to do the matching pushes and then jump
# Line 5479 | Line 5616 | static __inline__ void create_popalls(vo
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 +
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   }
5650  
5651   static __inline__ void reset_lists(void)
# Line 5496 | Line 5663 | static void prepare_block(blockinfo* bi)
5663      int i;
5664  
5665      set_target(current_compile_p);
5666 <    align_target(32);
5666 >    align_target(align_jumps);
5667      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 <    align_target(32);
5672 >    align_target(align_jumps);
5673      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);
5510
5511    align_target(32);
5677      current_compile_p=get_target();
5678  
5679      bi->deplist=NULL;
# Line 5561 | Line 5726 | void build_comp(void)
5726          
5727          for (i = 0; tbl[i].opcode < 65536; i++) {
5728                  int cflow = table68k[tbl[i].opcode].cflow;
5729 +                if (USE_INLINING && ((cflow & fl_const_jump) != 0))
5730 +                        cflow = fl_const_jump;
5731 +                else
5732 +                        cflow &= ~fl_const_jump;
5733                  prop[cft_map(tbl[i].opcode)].cflow = cflow;
5734  
5735                  int uses_fpu = tbl[i].specific & 32;
# Line 5854 | Line 6023 | static void compile_block(cpu_history* p
6023          int r;
6024          int was_comp=0;
6025          uae_u8 liveflags[MAXRUN+1];
6026 + #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          uae_u32 max_pcp=(uae_u32)pc_hist[0].location;
6032          uae_u32 min_pcp=max_pcp;
6033 + #endif
6034          uae_u32 cl=cacheline(pc_hist[0].location);
6035          void* specflags=(void*)&regs.spcflags;
6036          blockinfo* bi=NULL;
# Line 5899 | Line 6074 | static void compile_block(cpu_history* p
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 + #if USE_CHECKSUM_INFO
6078 +        free_checksum_info_chain(bi->csi);
6079 +        bi->csi = NULL;
6080 + #endif
6081          
6082          liveflags[blocklen]=0x1f; /* All flags needed afterwards */
6083          i=blocklen;
# Line 5906 | Line 6085 | static void compile_block(cpu_history* p
6085              uae_u16* currpcp=pc_hist[i].location;
6086              uae_u32 op=DO_GET_OPCODE(currpcp);
6087  
6088 + #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              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 + #endif
6107  
6108                  liveflags[i]=((liveflags[i+1]&
6109                                 (~prop[op].set_flags))|
# Line 5918 | Line 6112 | static void compile_block(cpu_history* p
6112                      liveflags[i]&= ~FLAG_Z;
6113          }
6114  
6115 + #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          bi->needed_flags=liveflags[0];
6124  
6125 <        align_target(32);
6125 >        align_target(align_loops);
6126          was_comp=0;
6127  
6128          bi->direct_handler=(cpuop_func *)get_target();
# Line 6007 | Line 6209 | static void compile_block(cpu_history* p
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 + #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                      //raw_add_l_mi((uae_u32)&oink,1); // FIXME
6217   #if USE_NORMAL_CALLING_CONVENTION
6218                      raw_inc_sp(4);
# Line 6095 | Line 6301 | static void compile_block(cpu_history* p
6301                  raw_jmp((uae_u32)popall_do_nothing);
6302                  create_jmpdep(bi,0,tba,t1);
6303  
6304 <                align_target(16);
6304 >                align_target(align_jumps);
6305                  /* not-predicted outcome */
6306                  *branchadd=(uae_u32)get_target()-((uae_u32)branchadd+4);
6307                  live=tmp; /* Ouch again */
# Line 6164 | Line 6370 | static void compile_block(cpu_history* p
6370          big_to_small_state(&live,&(bi->env));
6371   #endif
6372  
6373 + #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          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 +
6392          bi->len=max_pcp-min_pcp;
6393          bi->min_pcp=min_pcp;
6394 <                    
6394 >        
6395          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.
# Line 6182 | Line 6402 | static void compile_block(cpu_history* p
6402              calc_checksum(bi,&(bi->c1),&(bi->c2));
6403              add_to_active(bi);
6404          }
6405 + #endif
6406          
6407          current_cache_size += get_target() - (uae_u8 *)current_compile_p;
6408          
# Line 6201 | Line 6422 | static void compile_block(cpu_history* p
6422   #endif
6423          
6424          log_dump();
6425 <        align_target(32);
6425 >        align_target(align_jumps);
6426  
6427          /* This is the non-direct handler */
6428          bi->handler=
# Line 6217 | Line 6438 | static void compile_block(cpu_history* p
6438  
6439          raw_jmp((uae_u32)bi->direct_handler);
6440  
6220        align_target(32);
6441          current_compile_p=get_target();
6222
6442          raise_in_cl_list(bi);
6443          
6444          /* We will flush soon, anyway, so let's do it now */
# Line 6245 | Line 6464 | void exec_nostats(void)
6464   {
6465          for (;;)  {
6466                  uae_u32 opcode = GET_OPCODE;
6248 #ifdef X86_ASSEMBLY__disable
6249                __asm__ __volatile__("\tpushl %%ebp\n\tcall *%%ebx\n\tpopl %%ebp" /* FIXME */
6250                                                         : : "b" (cpufunctbl[opcode]), "a" (opcode)
6251                                                         : "%edx", "%ecx", "%esi", "%edi",  "%ebp", "memory", "cc");
6252 #else
6467                  (*cpufunctbl[opcode])(opcode);
6254 #endif
6468                  if (end_block(opcode) || SPCFLAGS_TEST(SPCFLAG_ALL)) {
6469                          return; /* We will deal with the spcflags in the caller */
6470                  }
# Line 6276 | Line 6489 | void execute_normal(void)
6489   #if FLIGHT_RECORDER
6490                          m68k_record_step(m68k_getpc());
6491   #endif
6279 #ifdef X86_ASSEMBLY__disable
6280                        __asm__ __volatile__("\tpushl %%ebp\n\tcall *%%ebx\n\tpopl %%ebp" /* FIXME */
6281                                                                 : : "b" (cpufunctbl[opcode]), "a" (opcode)
6282                                                                 : "%edx", "%ecx", "%esi", "%edi", "%ebp", "memory", "cc");
6283 #else
6492                          (*cpufunctbl[opcode])(opcode);
6285 #endif
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 */
# Line 6295 | Line 6502 | void execute_normal(void)
6502  
6503   typedef void (*compiled_handler)(void);
6504  
6505 + #ifdef X86_ASSEMBLY
6506 + void (*m68k_compile_execute)(void) = NULL;
6507 + #else
6508   void m68k_do_compile_execute(void)
6509   {
6510          for (;;) {
6301 #ifdef X86_ASSEMBLY
6302                __asm__ __volatile__("\tpushl %%ebp\n\tcall *%%ebx\n\tpopl %%ebp" /* FIXME */
6303                                                         : : "b" (cache_tags[cacheline(regs.pc_p)].handler)
6304                                                         : "%edx", "%ecx", "%eax", "%esi", "%edi", "%ebp", "memory", "cc");
6305 #else
6511                  ((compiled_handler)(pushall_call_handler))();
6307 #endif
6512                  /* Whenever we return from that, we should check spcflags */
6513                  if (SPCFLAGS_TEST(SPCFLAG_ALL)) {
6514                          if (m68k_do_specialties ())
# Line 6312 | Line 6516 | void m68k_do_compile_execute(void)
6516                  }
6517          }
6518   }
6519 + #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines