<html>
<body>
  <div id="body" style="background-color:#ffffff;" >
<table cellspacing="0" cellpadding="0" border="0" rules="cols">
<tr class="head" style="border-bottom-width:1px;border-bottom-style:solid;" ><td class="headtd" style="padding:0;padding-top:.2em;" colspan="4">Commit in <b><tt>lxdream/src</tt></b></td></tr>
<tr><td><tt>sh4/<a href="#file1">sh4.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+3</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">3dc028106b08 -> b38a327ad8fa</td></tr>
<tr class="alt" style=";" ><td><tt>   /<a href="#file2">sh4trans.h</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+10</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">3dc028106b08 -> b38a327ad8fa</td></tr>
<tr><td><tt>   /<a href="#file3">sh4x86.in</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+21</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-4</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">3dc028106b08 -> b38a327ad8fa</td></tr>
<tr class="alt" style=";" ><td><tt>xlat/<a href="#file4">xltcache.c</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+91</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">3dc028106b08 -> b38a327ad8fa</td></tr>
<tr><td><tt>    /<a href="#file5">xltcache.h</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+7</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">3dc028106b08 -> b38a327ad8fa</td></tr>
<tr><td></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+132</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-4</td><td></td></tr>
</table>
<small id="info" style="color: #888888;" >5 modified files</small><br />
<pre class="comment" style="white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;padding:4px;border:1px dashed #000000;background-color:#ffffdd;" >
Add block profiling option to count the number of executions of each block,
and dump them out from most-to-least used.
</pre>
<hr /><a name="file1" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/sh4</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>sh4.c</b></big> <small id="info" style="color: #888888;" >3dc028106b08 -> b38a327ad8fa</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/sh4/sh4.c
+++ lxdream/src/sh4/sh4.c
@@ -235,6 +235,9 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         /* If we were running with the translator, update new_pc and in_delay_slot */
         sh4r.new_pc = sh4r.pc+2;
         sh4r.in_delay_slot = FALSE;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        if( sh4_translate_get_profile_blocks() ) {
+            xlat_dump_cache_by_activity(30);
+        }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 
 }
</pre></div>
<hr /><a name="file2" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/sh4</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>sh4trans.h</b></big> <small id="info" style="color: #888888;" >3dc028106b08 -> b38a327ad8fa</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/sh4/sh4trans.h
+++ lxdream/src/sh4/sh4trans.h
@@ -103,6 +103,16 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > void sh4_translate_set_fastmem( gboolean flag );
 
 /**
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ * Enable/disable basic block profiling
+ */
+void sh4_translate_set_profile_blocks( gboolean flag );
+
+/**
+ * Get the boolean flag indicating whether block profiling is on.
+ */
+gboolean sh4_translate_get_profile_blocks();
+
+/**
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  * Set the address spaces for the translated code.
  */
 void sh4_translate_set_address_space( struct mem_region_fn **priv, struct mem_region_fn **user );
</pre></div>
<hr /><a name="file3" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/sh4</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>sh4x86.in</b></big> <small id="info" style="color: #888888;" >3dc028106b08 -> b38a327ad8fa</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/sh4/sh4x86.in
+++ lxdream/src/sh4/sh4x86.in
@@ -106,6 +106,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     xlat_block_begin_callback_t begin_callback;
     xlat_block_end_callback_t end_callback;
     gboolean fastmem;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    gboolean profile_blocks;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     
     /* Allocated memory for the (block-wide) back-patch list */
     struct backpatch_record *backpatch_list;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -166,6 +167,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     sh4_x86.end_callback = NULL;
     sh4_translate_set_address_space( sh4_address_space, sh4_user_address_space );
     sh4_x86.fastmem = TRUE;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    sh4_x86.profile_blocks = FALSE;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     sh4_x86.sse3_enabled = is_sse3_supported();
     x86_disasm_init();
     x86_set_symtab( x86_symbol_table, sizeof(x86_symbol_table)/sizeof(struct x86_symbol) );
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -182,6 +184,16 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     sh4_x86.fastmem = flag;
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+void sh4_translate_set_profile_blocks( gboolean flag )
+{
+    sh4_x86.profile_blocks = flag;
+}
+
+gboolean sh4_translate_get_profile_blocks()
+{
+    return sh4_x86.profile_blocks;
+}
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > /**
  * Disassemble the given translated code block, and it's source SH4 code block
  * side-by-side. The current native pc will be marked if non-null.
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -476,6 +488,11 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 #define SLOTILLEGAL() exit_block_exc(EXC_SLOT_ILLEGAL, pc-2); sh4_x86.in_delay_slot = DELAY_NONE; return 2;
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+/** Offset of xlat_sh4_mode field relative to the code pointer */ 
+#define XLAT_SH4_MODE_CODE_OFFSET  (uint32_t)(offsetof(struct xlat_cache_block, xlat_sh4_mode) - offsetof(struct xlat_cache_block,code) )
+#define XLAT_CHAIN_CODE_OFFSET (uint32_t)(offsetof(struct xlat_cache_block, chain) - offsetof(struct xlat_cache_block,code) )
+#define XLAT_ACTIVE_CODE_OFFSET (uint32_t)(offsetof(struct xlat_cache_block, active) - offsetof(struct xlat_cache_block,code) )
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > void sh4_translate_begin_block( sh4addr_t pc ) 
 {
        sh4_x86.code = xlat_output;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -493,6 +510,10 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     if( sh4_x86.begin_callback ) {
         CALL_ptr( sh4_x86.begin_callback );
     }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( sh4_x86.profile_blocks ) {
+       MOVP_immptr_rptr( ((uintptr_t)sh4_x86.code) + XLAT_ACTIVE_CODE_OFFSET, REG_EAX );
+       ADDL_imms_r32disp( 1, REG_EAX, 0 );
+    }  
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -519,10 +540,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 #define UNTRANSLATABLE(pc) !IS_IN_ICACHE(pc)
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-/** Offset of xlat_sh4_mode field relative to the code pointer */ 
-#define XLAT_SH4_MODE_CODE_OFFSET  (uint32_t)(offsetof(struct xlat_cache_block, xlat_sh4_mode) - offsetof(struct xlat_cache_block,code) )
-#define XLAT_CHAIN_CODE_OFFSET (uint32_t)(offsetof(struct xlat_cache_block, chain) - offsetof(struct xlat_cache_block,code) )
-
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > /**
  * Test if the loaded target code pointer in %eax is valid, and if so jump
  * directly into it, bypassing the normal exit.
</pre></div>
<hr /><a name="file4" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/xlat</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>xltcache.c</b></big> <small id="info" style="color: #888888;" >3dc028106b08 -> b38a327ad8fa</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/xlat/xltcache.c
+++ lxdream/src/xlat/xltcache.c
@@ -37,6 +37,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #define XLAT_LUT_ENTRY_EMPTY (void *)0
 #define XLAT_LUT_ENTRY_USED  (void *)1
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#define XLAT_ADDR_FROM_ENTRY(pagenum,entrynum) ((((pagenum)&0xFFFF)<<13)|(((entrynum)<<1)&0x1FFE))
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #define NEXT(block) ( (xlat_cache_block_t)&((block)->code[(block)->size]))
 #define IS_ENTRY_POINT(ent) (ent > XLAT_LUT_ENTRY_USED)
 #define IS_ENTRY_USED(ent) (ent != XLAT_LUT_ENTRY_EMPTY)
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -575,3 +577,92 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #endif
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+typedef struct {
+    xlat_cache_block_t block;
+    sh4addr_t sh4_pc;
+} block_sh4_entry;
+
+unsigned int xlat_get_active_block_count()
+{
+    unsigned int count = 0;
+    xlat_cache_block_t ptr = xlat_new_cache;
+    while( ptr->size != 0 ) {
+        if( ptr->active != 0 ) {
+            count++;
+        }
+        ptr = NEXT(ptr);
+    }
+    return count;
+}
+
+unsigned int xlat_get_active_blocks( block_sh4_entry *blocks, unsigned int size )
+{
+    unsigned int count = 0;
+    xlat_cache_block_t ptr = xlat_new_cache;
+    while( ptr->size != 0 ) {
+        if( ptr->active != 0 ) {
+            blocks[count].block = ptr;
+            blocks[count].sh4_pc = 0;
+            count++;
+        }
+        if( count >= size )
+            break;
+        ptr = NEXT(ptr);
+    }
+    return count;
+}
+
+void xlat_get_block_sh4addrs( block_sh4_entry *blocks, unsigned int size )
+{
+    unsigned i;
+    for( i=0; i<XLAT_LUT_PAGES;i ++ ) {
+        void **page = xlat_lut[i];
+        if( page != NULL ) {
+            for( unsigned j=0; j < XLAT_LUT_PAGE_ENTRIES; j++ ) {
+                void *code = (void *)(((uintptr_t)(page[j])) & (~((uintptr_t)0x03)));
+                if( code != NULL ) {
+                    xlat_cache_block_t ptr = XLAT_BLOCK_FOR_CODE(code);
+                    sh4addr_t pc = XLAT_ADDR_FROM_ENTRY(i,j);
+                    for( unsigned k=0; k<size; k++ ) {
+                        if( blocks[k].block == ptr ) {
+                            blocks[k].sh4_pc = pc;
+                            ptr = ptr->chain;
+                            if( ptr == NULL )
+                                break;
+                            else {
+                                ptr = XLAT_BLOCK_FOR_CODE(ptr);
+                                k = 0;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+static int xlat_compare_active_field( const void *a, const void *b )
+{
+    const block_sh4_entry *ptra = (const block_sh4_entry *)a;
+    const block_sh4_entry *ptrb = (const block_sh4_entry *)b;
+    return ptrb->block->active - ptra->block->active;
+}
+
+void xlat_dump_cache_by_activity( unsigned int topN )
+{
+    int i=0;
+    int count = xlat_get_active_block_count();
+
+    block_sh4_entry blocks[count];
+    xlat_get_active_blocks(blocks, count);
+    xlat_get_block_sh4addrs(blocks,count);
+    qsort(blocks, count, sizeof(block_sh4_entry), xlat_compare_active_field);
+
+    if( topN == 0 || topN > count )
+        topN = count;
+    for( unsigned int i=0; i<topN; i++ ) {
+        fprintf(stderr, "0x%08X (%p): %d\n", blocks[i].sh4_pc, blocks[i].block->code, blocks[i].block->active);
+        sh4_translate_disasm_block( stderr, blocks[i].block->code, blocks[i].sh4_pc, NULL );
+        fprintf(stderr, "\n");
+    }
+}
</pre></div>
<hr /><a name="file5" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/xlat</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>xltcache.h</b></big> <small id="info" style="color: #888888;" >3dc028106b08 -> b38a327ad8fa</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/xlat/xltcache.h
+++ lxdream/src/xlat/xltcache.h
@@ -181,4 +181,11 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  */
 void xlat_check_integrity();
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+/**
+ * Dump out the top N translated blocks by number of executions (requires block
+ * profiling to be turned on in order to give meaningful results).
+ * @param topN Number of blocks to print. If 0, print all blocks in the cache
+ */
+void xlat_dump_cache_by_activity( unsigned int topN );
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #endif /* lxdream_xltcache_H */
</pre></div>
<center><small>Chaos Theory</small></center>
</div></body></html>