diff -Nur a/core/hw/sh4/dyna/blockmanager.cpp b/core/hw/sh4/dyna/blockmanager.cpp --- a/core/hw/sh4/dyna/blockmanager.cpp 2015-10-06 21:43:53.030336315 -0300 +++ b/core/hw/sh4/dyna/blockmanager.cpp 2015-10-06 21:58:25.685653822 -0300 @@ -122,7 +122,11 @@ } else { - printf("bm_GetBlock(%08X) failed ..\n",dynarec_code); + for (iter = blkmap.begin(); iter != blkmap.end(); iter++) { + if ((*iter)->contains_code((u8*)dynarec_code)) + return *iter; + } + //printf("bm_GetBlock(%p, %p) failed ..\n",dynarec_code, ngen_FailedToFindBlock); return 0; } } @@ -158,6 +162,8 @@ verify((void*)bm_GetCode(blk->addr)==(void*)ngen_FailedToFindBlock); FPCA(blk->addr)=blk->code; + verify(bm_GetBlock(blk->addr) == blk); + #ifdef DYNA_OPROF if (oprofHandle) { diff -Nur a/core/hw/sh4/dyna/blockmanager.h b/core/hw/sh4/dyna/blockmanager.h --- a/core/hw/sh4/dyna/blockmanager.h 2015-10-06 21:43:53.030336315 -0300 +++ b/core/hw/sh4/dyna/blockmanager.h 2015-10-06 21:58:25.685653822 -0300 @@ -71,6 +71,7 @@ u32 memops; u32 linkedmemops; + bool entry_block; }; struct CachedBlockInfo: RuntimeBlockInfo_Core diff -Nur a/core/hw/sh4/dyna/decoder.cpp b/core/hw/sh4/dyna/decoder.cpp --- a/core/hw/sh4/dyna/decoder.cpp 2015-10-06 21:43:53.030336315 -0300 +++ b/core/hw/sh4/dyna/decoder.cpp 2015-10-06 21:58:25.685653822 -0300 @@ -14,6 +14,7 @@ #include "hw/sh4/sh4_core.h" #include "hw/sh4/sh4_mem.h" #include "decoder_opcodes.h" +#include "../interpr/sh4_opcodes.h" #define BLOCK_MAX_SH_OPS_SOFT 500 #define BLOCK_MAX_SH_OPS_HARD 511 @@ -1098,6 +1099,13 @@ else blk->guest_cycles+=CPU_RATIO; + if ((state.cpu.is_delayslot && OpDesc[op]->SetPC()) || + OpDesc[op]->oph == iNotImplemented) { + blk->addr = -1; + return; + } + + verify(!(state.cpu.is_delayslot && OpDesc[op]->SetPC())); if (state.ngen.OnlyDynamicEnds || !OpDesc[op]->rec_oph) { @@ -1168,6 +1176,8 @@ if (settings.dynarec.idleskip) { //Experimental hash-id based idle skip + if (blk->addr == 0x8C0B926A) + blk->guest_cycles *= 100; if (strstr(idle_hash,blk->hash(false,true))) { //printf("IDLESKIP: %08X reloc match %s\n",blk->addr,blk->hash(false,true)); diff -Nur a/core/hw/sh4/dyna/driver.cpp b/core/hw/sh4/dyna/driver.cpp --- a/core/hw/sh4/dyna/driver.cpp 2015-10-06 21:43:53.030336315 -0300 +++ b/core/hw/sh4/dyna/driver.cpp 2015-10-06 21:58:25.685653822 -0300 @@ -72,11 +72,24 @@ LastAddr=LastAddr_min; memset(emit_GetCCPtr(),0xCC,emit_FreeSpace()); } + +#include +#include +#include + +typedef map BlockGraph; + +vector graphs; +map blockgraphs; + void recSh4_ClearCache() { LastAddr=LastAddr_min; bm_Reset(); + graphs.clear(); + blockgraphs.clear(); + printf("recSh4:Dynarec Cache clear at %08X\n",curr_pc); } @@ -212,9 +225,145 @@ AnalyseBlock(this); } +void merge_graphs(BlockGraph* one, BlockGraph* two) { + for (BlockGraph::iterator it = two->begin(); it != two->end(); it++) { + blockgraphs[it->second->addr] = one; + (*one)[it->second->addr] = it->second; + } + graphs.erase(find(graphs.begin(), graphs.end(), two)); +} + +void discover_graph(u32 bootstrap) { + BlockGraph* graph; + set resolved; + vector unresolved; + + if (blockgraphs.count(bootstrap)) { + graph = blockgraphs[bootstrap]; + (*graph)[bootstrap]->entry_block = true; + return; + } else { + graph = new BlockGraph(); + + graphs.push_back(graph); + } + + unresolved.push_back(bootstrap); + + while (unresolved.size()) { + u32 pc = unresolved[unresolved.size()-1]; + unresolved.pop_back(); + + if (resolved.count(pc)) + continue; + + if (graph->count(pc)) + continue; + + if (blockgraphs.count(pc)) { + verify(blockgraphs[pc] != graph); + merge_graphs(blockgraphs[pc], graph); + graph = blockgraphs[pc]; + resolved.clear(); + continue; + } + + resolved.insert(pc); + //printf("resolving %08X\n", pc); + + RuntimeBlockInfo* rbi = ngen_AllocateBlock(); + rbi->Setup(pc,fpscr); + rbi->entry_block = pc == bootstrap; + + if (rbi->addr == -1) + continue; + + (*graph)[pc] = rbi; + blockgraphs[pc] = graph; + + if (rbi->BranchBlock !=-1 && rbi->BlockType != BET_StaticCall) + unresolved.push_back(rbi->BranchBlock); + + if (rbi->NextBlock != -1) + unresolved.push_back(rbi->NextBlock); + } + + int entrypoints = 0; + + for (BlockGraph::iterator it = graph->begin(); it != graph->end(); it++) { + entrypoints += it->second->entry_block; + } + + //printf("Graph: %d blocks w/ %d entrypoints, %d graphs\n", graph->size(), entrypoints, graphs.size()); +} + +void print_graphs() { + int top_runs = 0; + int total_runs = 0; + map graph_runs; + + for (size_t i = 0; i < graphs.size(); i++) { + BlockGraph* graph = graphs[i]; + for (BlockGraph::iterator it = graphs[i]->begin(); it != graphs[i]->end(); it++) { + + RuntimeBlockInfo* natblock = bm_GetBlock(it->first); + if (!natblock || natblock->runs == 0) + continue; + + if (natblock->runs > top_runs) + top_runs = natblock->runs; + + total_runs += natblock->runs; + + graph_runs[graph] += natblock->runs; + } + } + + int baseline = top_runs / 100; + + printf("begin(); it != graphs[i]->end(); it++) { + + RuntimeBlockInfo* natblock = bm_GetBlock(it->first); + if (!natblock || natblock->runs == 0 || natblock->runs < baseline) { + if (natblock) { + cnt2++; + natblock->runs = 0; + } else { + cnt++; + } + continue; + } + printf("\t\tBlock %08X, compiled: %d, entrypoint: %d, type: %d, len: %d, cycles: %d, runs %d, loop %d\n", + it->first, natblock != 0, it->second->entry_block, it->second->BlockType, it->second->oplist.size(), + it->second->guest_cycles, natblock ? natblock->runs : 0, + (it->second->BlockType == BET_Cond_0 || it->second->BlockType == BET_Cond_1) && graph->count(it->second->BranchBlock) ); + + if (natblock) + natblock->runs = 0; + } + if (cnt2) { + printf("\t\t and %d more not worth mentioning\n", cnt2); + } + if (cnt) { + printf("\t\t and %d more that never run\n", cnt); + } + } + printf("Graphdump>\n"); +} + DynarecCodeEntryPtr rdv_CompilePC() { u32 pc=next_pc; + discover_graph(pc); if (emit_FreeSpace()<16*1024 || pc==0x8c0000e0 || pc==0xac010000 || pc==0xac008300) recSh4_ClearCache(); @@ -232,6 +381,7 @@ rbi->staging_runs=do_opts?100:-100; ngen_Compile(rbi,DoCheck(rbi->addr),(pc&0xFFFFFF)==0x08300 || (pc&0xFFFFFF)==0x10000,false,do_opts); verify(rbi->code!=0); + verify(rbi->host_code_size!=0); bm_AddBlock(rbi); diff -Nur a/core/linux-dist/main.cpp b/core/linux-dist/main.cpp --- a/core/linux-dist/main.cpp 2015-10-06 21:43:53.042336401 -0300 +++ b/core/linux-dist/main.cpp 2015-10-06 21:58:25.685653822 -0300 @@ -189,6 +189,18 @@ #if defined(USE_SDL) input_sdl_handle(port); #endif + + //Whatever happened to these? +#if FEAT_SHREC != DYNAREC_NONE + /* + void print_graphs(); + if ('b' == key) emit_WriteCodeCache(); + if ('n' == key) bm_Reset(); + if ('m' == key) bm_Sort(); + if (',' == key) { emit_WriteCodeCache(); bm_Sort(); } + if ('q' == key) print_graphs(); + */ +#endif } void os_DoEvents() diff -Nur a/core/rec-x64/rec_x64.cpp b/core/rec-x64/rec_x64.cpp --- a/core/rec-x64/rec_x64.cpp 2015-10-06 21:43:53.045336422 -0300 +++ b/core/rec-x64/rec_x64.cpp 2015-10-06 21:58:25.685653822 -0300 @@ -162,6 +162,10 @@ sub(dword[rax], block->guest_cycles); + mov(rax, (size_t)&block->runs); + add(dword[rax], 1); + + sub(rsp, 0x28); for (size_t i = 0; i < block->oplist.size(); i++) { @@ -355,6 +359,7 @@ block->code = (DynarecCodeEntryPtr)getCode(); + block->host_code_size = getSize(); emit_Skip(getSize()); }