<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">sh4trans.h</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+5</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">4f02196f68eb -> 2dc47c67bb93</td></tr>
<tr class="alt" style=";" ><td><tt> /<a href="#file2">sh4x86.in</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+87</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-24</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">4f02196f68eb -> 2dc47c67bb93</td></tr>
<tr><td><tt>xlat/x86/<a href="#file3">x86op.h</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">4f02196f68eb -> 2dc47c67bb93</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">+15</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-9</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">4f02196f68eb -> 2dc47c67bb93</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">+1</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">4f02196f68eb -> 2dc47c67bb93</td></tr>
<tr><td></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+111</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-33</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 support for block linking when the block target is fixed. Only a small
(~3% improvement) so far.
</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>sh4trans.h</b></big> <small id="info" style="color: #888888;" >4f02196f68eb -> 2dc47c67bb93</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/sh4/sh4trans.h
+++ lxdream/src/sh4/sh4trans.h
@@ -154,6 +154,11 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > gboolean sh4_translate_flush_cache( void );
/**
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ * Given a block's use_list, remove all direct links to the block.
+ */
+void sh4_translate_unlink_block( void *use_list );
+
+/**
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > * Support function called from the translator when a breakpoint is hit.
* Either returns immediately (to skip the breakpoint), or aborts the current
* cycle and never returns.
</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>sh4x86.in</b></big> <small id="info" style="color: #888888;" >4f02196f68eb -> 2dc47c67bb93</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/sh4/sh4x86.in
+++ lxdream/src/sh4/sh4x86.in
@@ -489,9 +489,9 @@
</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;
/** Offset of xlat_sh4_mode field relative to the code pointer */
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-#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="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#define XLAT_SH4_MODE_CODE_OFFSET (int32_t)(offsetof(struct xlat_cache_block, xlat_sh4_mode) - offsetof(struct xlat_cache_block,code) )
+#define XLAT_CHAIN_CODE_OFFSET (int32_t)(offsetof(struct xlat_cache_block, chain) - offsetof(struct xlat_cache_block,code) )
+#define XLAT_ACTIVE_CODE_OFFSET (int32_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 )
{
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -511,7 +511,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > CALL_ptr( sh4_x86.begin_callback );
}
if( sh4_x86.profile_blocks ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >- MOVP_immptr_rptr( <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >((uintptr_t)sh4_x86.code)</span> + XLAT_ACTIVE_CODE_OFFSET, REG_EAX );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ MOVP_immptr_rptr( <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >sh4_x86.code</span> + XLAT_ACTIVE_CODE_OFFSET, REG_EAX );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > ADDL_imms_r32disp( 1, REG_EAX, 0 );
}
}
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -575,6 +575,86 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > JMP_TARGET(nocode);
}
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+/**
+ *
+ */
+static void FASTCALL sh4_translate_get_code_and_backpatch( uint32_t pc )
+{
+ uint8_t *target = (uint8_t *)xlat_get_code_by_vma(pc);
+ while( target != NULL && sh4r.xlat_sh4_mode != XLAT_BLOCK_MODE(target) ) {
+ target = XLAT_BLOCK_CHAIN(target);
+ }
+ if( target == NULL ) {
+ target = sh4_translate_basic_block( pc );
+ }
+ uint8_t *backpatch = ((uint8_t *)__builtin_return_address(0)) - (CALL1_PTR_MIN_SIZE);
+ *backpatch = 0xE9;
+ *(uint32_t *)(backpatch+1) = (uint32_t)(target-backpatch)+PROLOGUE_SIZE-5;
+ *(void **)(backpatch+5) = XLAT_BLOCK_FOR_CODE(target)->use_list;
+ XLAT_BLOCK_FOR_CODE(target)->use_list = backpatch;
+
+ uint8_t **retptr = ((uint8_t **)__builtin_frame_address(0))+1;
+ assert( *retptr == ((uint8_t *)__builtin_return_address(0)) );
+ *retptr = backpatch;
+}
+
+static void emit_translate_and_backpatch()
+{
+ /* NB: this is either 7 bytes (i386) or 12 bytes (x86-64) */
+ CALL1_ptr_r32(sh4_translate_get_code_and_backpatch, REG_ARG1);
+
+ /* When patched, the jmp instruction will be 5 bytes (either platform) -
+ * we need to reserve sizeof(void*) bytes for the use-list
+ * pointer
+ */
+ if( sizeof(void*) == 8 ) {
+ NOP();
+ } else {
+ NOP2();
+ }
+}
+
+/**
+ * If we're jumping to a fixed address (or at least fixed relative to the
+ * current PC, then we can do a direct branch. REG_ARG1 should contain
+ * the PC at this point.
+ */
+static void jump_next_block_fixed_pc( sh4addr_t pc )
+{
+ if( IS_IN_ICACHE(pc) ) {
+ if( sh4_x86.sh4_mode != SH4_MODE_UNKNOWN ) {
+ /* Fixed address, in cache, and fixed SH4 mode - generate a call to the
+ * fetch-and-backpatch routine, which will replace the call with a branch */
+ emit_translate_and_backpatch();
+ return;
+ } else {
+ MOVP_moffptr_rax( xlat_get_lut_entry(GET_ICACHE_PHYS(pc)) );
+ ANDP_imms_rptr( -4, REG_EAX );
+ }
+ } else if( sh4_x86.tlb_on ) {
+ CALL1_ptr_r32(xlat_get_code_by_vma, REG_ARG1);
+ } else {
+ CALL1_ptr_r32(xlat_get_code, REG_ARG1);
+ }
+ jump_next_block();
+
+
+}
+
+void sh4_translate_unlink_block( void *use_list )
+{
+ uint8_t *tmp = xlat_output; /* In case something is active, which should never happen */
+ void *next = use_list;
+ while( next != NULL ) {
+ xlat_output = (uint8_t *)next;
+ next = *(void **)(xlat_output+5);
+ emit_translate_and_backpatch();
+ }
+ xlat_output = tmp;
+}
+
+
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > static void exit_block()
{
emit_epilogue();
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -645,16 +725,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > MOVL_r32_rbpdisp( REG_ARG1, R_PC );
CMPL_r32_rbpdisp( REG_ECX, REG_OFFSET(event_pending) );
JBE_label(exitloop);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-
- if( IS_IN_ICACHE(pc) ) {
- MOVP_moffptr_rax( xlat_get_lut_entry(GET_ICACHE_PHYS(pc)) );
- ANDP_imms_rptr( -4, REG_EAX );
- } else if( sh4_x86.tlb_on ) {
- CALL1_ptr_r32(xlat_get_code_by_vma, REG_ARG1);
- } else {
- CALL1_ptr_r32(xlat_get_code, REG_ARG1);
- }
- jump_next_block();
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ jump_next_block_fixed_pc(pc);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > JMP_TARGET(exitloop);
exit_block();
}
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -682,16 +753,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > MOVL_r32_rbpdisp( REG_ARG1, R_PC );
CMPL_r32_rbpdisp( REG_ECX, REG_OFFSET(event_pending) );
JBE_label(exitloop2);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-
- if( IS_IN_ICACHE(pc) ) {
- MOVP_moffptr_rax( xlat_get_lut_entry(GET_ICACHE_PHYS(pc)) );
- ANDP_imms_rptr( -4, REG_EAX );
- } else if( sh4_x86.tlb_on ) {
- CALL1_ptr_r32(xlat_get_code_by_vma, REG_ARG1);
- } else {
- CALL1_ptr_r32(xlat_get_code, REG_ARG1);
- }
- jump_next_block();
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+
+ jump_next_block_fixed_pc(pc);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > JMP_TARGET(exitloop2);
}
exit_block();
</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/xlat/x86</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>x86op.h</b></big> <small id="info" style="color: #888888;" >4f02196f68eb -> 2dc47c67bb93</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/xlat/x86/x86op.h
+++ lxdream/src/xlat/x86/x86op.h
@@ -482,6 +482,9 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #define NEGL_rbpdisp(r1) x86_encode_r32_rbspdisp32(0xF7, 3, disp)
#define NEGQ_r64(r1) x86_encode_r64_rm64(0xF7, 3, r1)
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#define NOP() OP(0x90)
+#define NOP2() OP(0x66); OP(0x90)
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #define NOTB_r8(r1) x86_encode_r32_rm32(0xF6, 2, r1)
#define NOTL_r32(r1) x86_encode_r32_rm32(0xF7, 2, r1)
#define NOTL_rbpdisp(r1) x86_encode_r32_rbspdisp32(0xF7, 2, disp)
</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;" >4f02196f68eb -> 2dc47c67bb93</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/xlat/xltcache.c
+++ lxdream/src/xlat/xltcache.c
@@ -22,6 +22,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >
#include "dreamcast.h"
#include "sh4/sh4core.h"
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#include "sh4/sh4trans.h"
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #include "xlat/xltcache.h"
#include "x86dasm/x86dasm.h"
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -121,6 +122,13 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
}
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+void xlat_delete_block( xlat_cache_block_t block )
+{
+ block->active = 0;
+ *block->lut_entry = block->chain;
+ sh4_translate_unlink_block( block->use_list );
+}
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > static void xlat_flush_page_by_lut( void **page )
{
int i;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -129,7 +137,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > void *p = page[i];
do {
xlat_cache_block_t block = XLAT_BLOCK_FOR_CODE(p);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >- block->active = 0;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ xlat_delete_block(block);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > p = block->chain;
} while( p != NULL );
}
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -377,7 +385,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #else
void xlat_promote_to_temp_space( xlat_cache_block_t block )
{
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >- *block->lut_entry = <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >0</span>;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ *block->lut_entry = <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >block->chain</span>;
+ xlat_delete_block(block);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
#endif
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -414,6 +423,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > } else {
xlat_new_create_ptr->chain = NULL;
}
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ xlat_new_create_ptr->use_list = NULL;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >
xlat_lut[XLAT_LUT_PAGE(address)][XLAT_LUT_ENTRY(address)] =
&xlat_new_create_ptr->code;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -424,6 +434,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >
xlat_cache_block_t xlat_extend_block( uint32_t newSize )
{
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ assert( xlat_new_create_ptr->use_list == NULL );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > while( xlat_new_create_ptr->size < newSize ) {
if( xlat_new_cache_ptr->size == 0 ) {
/* Migrate to the front of the cache to keep it contiguous */
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -447,6 +458,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > xlat_new_create_ptr->size = allocation;
xlat_new_create_ptr->lut_entry = lut_entry;
xlat_new_create_ptr->chain = chain;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ xlat_new_create_ptr->use_list = NULL;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > *lut_entry = &xlat_new_create_ptr->code;
memmove( xlat_new_create_ptr->code, olddata, oldsize );
} else {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -475,12 +487,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > xlat_new_cache_ptr = xlat_cut_block( xlat_new_create_ptr, destsize );
}
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-void xlat_delete_block( xlat_cache_block_t block )
-{
- block->active = 0;
- *block->lut_entry = NULL;
-}
-
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > void xlat_check_cache_integrity( xlat_cache_block_t cache, xlat_cache_block_t ptr, int size )
{
int foundptr = 0;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -517,7 +523,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > if( page != NULL ) {
for( j=0; j<XLAT_LUT_PAGE_ENTRIES; j++ ) {
void *entry = page[j];
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >- if( ((uintptr_t)entry) > XLAT_LUT_ENTRY_USED ) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ if( ((uintptr_t)entry) > <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >(uintptr_t)</span>XLAT_LUT_ENTRY_USED ) {
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > xlat_cache_block_t block = XLAT_BLOCK_FOR_CODE(entry);
if( ptr >= block->code && ptr < block->code + block->size) {
/* Found it */
</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;" >4f02196f68eb -> 2dc47c67bb93</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/xlat/xltcache.h
+++ lxdream/src/xlat/xltcache.h
@@ -42,6 +42,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > uint32_t size;
void **lut_entry; /* For deletion */
void *chain;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ void *use_list;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > uint32_t xlat_sh4_mode; /* comparison with sh4r.xlat_sh4_mode */
uint32_t recover_table_offset; // Offset from code[0] of the recovery table;
uint32_t recover_table_size;
</pre></div>
<center><small>Chaos Theory</small></center>
</div></body></html>