<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>