Permalink
Browse files

core: Update to commit d975b22.

Gillou68310/mupen64plus-core@d975b22

* d975b22 new_dynarec: Ported the dynamic linker to C
*   bf68e6a Merge pull request #128 from mupen64plus/rename-dynarec-wiki
|\
| * 2530742 Rename new_dynarec.txt to new_dynarec.mediawiki
|/
* f50009c Merge branch 'master' of https://github.com/mupen64plus/mupen64plus-core
* 1b98885 wiki updates
  • Loading branch information...
Gillou68310 committed Aug 28, 2015
1 parent 24af50d commit 9825b2fa8b3e5e9c12f691475669d47a479b7cce
@@ -1,5 +1,16 @@
-= Mupen64Plus v2.0 API =
+=User Documentation=
+== Configuration Parameters ==
+=== [[Mupen64Plus Core Parameters|Core Parameters]] ===
-The interface between Mupen64Plus and its compatible plugins is (slightly) different from other N64 emulators. The new API is described in detail in the documentation here
+This section lists the names and descriptions of all of the configuration parameters used by the Core library.
+
+=== [[Mupen64Plus Plugin Parameters|Plugin Parameters]] ===
+
+This section lists the names and descriptions of all of the configuration parameters used by the Plugin libraries.
+
+=Developer Documentation=
+
+== [[Mupen64Plus v2.0 Core API v1.0|Mupen64Plus v2.0 API]] ==
+
+The interface between Mupen64Plus and its compatible plugins is (slightly) different from other N64 emulators. The new API is described in detail in the documentation here.
-[[Mupen64Plus v2.0 Core API v1.0|Mupen64Plus v2.0 API]]
@@ -29,58 +29,32 @@ The expected sequence of operations which will be taken by the front-end applica
#* When emulation is finished, call <tt>CoreDetachPlugin</tt> on all plugins, then close the ROM
== Versioning ==
-=== API Versioning Scheme ===
-Since the !Mupen64Plus emulator comprises 6 different software modules which can be mixed and matched (the front-end app, the core library, and 4 plugins), and the interfaces between these modules change over time, there are many hard-to-diagnose bugs which could show up due to incompatibilities between these different modules. For this reason, we use a comprehensive versioning scheme which allows any 2 components to determine whether or not they are compatible, and to support forward and backward compatibility as necessary. This scheme is described in detail in this document.
-
-Details can be found in [[Mupen64Plus v2.0 API Versioning]]
+=== [[Mupen64Plus v2.0 API Versioning|API Versioning Scheme]] ===
+Since the Mupen64Plus emulator comprises 6 different software modules which can be mixed and matched (the front-end app, the core library, and 4 plugins), and the interfaces between these modules change over time, there are many hard-to-diagnose bugs which could show up due to incompatibilities between these different modules. For this reason, we use a comprehensive versioning scheme which allows any 2 components to determine whether or not they are compatible, and to support forward and backward compatibility as necessary. This scheme is described in detail in this document.
== Core API ==
-=== Basic Core Functions ===
+=== [[Mupen64Plus v2.0 Core Basic|Basic Core Functions]] ===
These two functions (<tt>PluginGetVersion</tt> and <tt>CoreErrorMessage</tt>) are utility functions and may be called at any time (even before core startup). These functions are used by both the front-end and the plugins.
-Details can be found in [[Mupen64Plus v2.0 Core Basic]]
-
-=== Front-End Functions ===
+=== [[Mupen64Plus v2.0 Core Front-End|Front-End Functions]] ===
There are several types of functions here, which are exported from the Core library to be used by the front-end. There are 'housekeeping' functions, for startup and shutdown, and attaching and detaching plugins. There is also a Command API which is used for many simple functions such as loading, executing, or stopping a ROM. Finally the Cheat API is here, for adding and removing cheat functions.
-Details can be found in [[Mupen64Plus v2.0 Core Front-End]]
-
-=== Video Extension API ===
+=== [[Mupen64Plus v2.0 Core Video Extension|Video Extension API]] ===
These functions are exported from the Core library for use by the video plugin. These functions are used for high-level video setup tasks such as enumerating available screen resolutions, setting the video mode, window caption, OpenGL attributes, and fullscreen mode. The video extension API allows for the abstraction of these functions away from the hard-coded SDL function calls currently in the video plugins, so that a front-end may override these functions and provide its own video API.
-Details can be found in [[Mupen64Plus v2.0 Core Video Extension]]
-
-=== Debugger Functions ===
+=== [[Mupen64Plus v2.0 Core Debugger|Debugger Functions]] ===
These are the debugger functions, which are also called only from the front-end. Most of these functions will return with an error if the core library was not compiled with the debugger enabled. A front-end may examine the <tt>Capabilities</tt> value returned by the <tt>CoreGetVersion</tt> function to determine if the core library was built with the debugger enabled.
-Details can be found in [[Mupen64Plus v2.0 Core Debugger]]
-
-=== Configuration API ===
+=== [[Mupen64Plus v2.0 Core Config|Configuration API]] ===
These configuration functions are exported from the core library and are used by the core and the plugins to store all of their persistent configuration parameters. The front-end application may also use these functions to store its configuration options, or it may use a different mechanism. This section also contains two Operating System Abstraction functions. These functions are used by the core, plugins, and the front-end to find full filepaths to shared data files and user-specific data files.
-Details can be found in [[Mupen64Plus v2.0 Core Config]]
-
== Plugin API ==
-=== Plugin API ===
+=== [[Mupen64Plus v2.0 Plugin API|Plugin API]] ===
This section lists all of the functions which are exported by the plugins. The front-end application should only use the <tt>PluginStartup</tt>, <tt>PluginShutdown</tt>, and <tt>PluginGetVersion</tt> functions. All other functions will only be called from the core.
-Details can be found in [[Mupen64Plus v2.0 Plugin API]]
-
-== Configuration Parameters ==
-=== Core Parameters ===
-
-This section lists the names and descriptions of all of the configuration parameters used by the Core library.
-
-Details can be found in [[Mupen64Plus Core Parameters]]
-
-=== Plugin Parameters ===
-
-This section lists the names and descriptions of all of the configuration parameters used by the Plugin libraries.
-
-Details can be found in [[Mupen64Plus Plugin Parameters]]
@@ -21,6 +21,9 @@
#include "../../cp0_private.h"
#include "main/main.h"
+void *dynamic_linker(void * src, int vaddr);
+void *dynamic_linker_ds(void * src, int vaddr);
+
extern int cycle_count;
extern int last_count;
extern int pcaddr;
@@ -107,8 +110,8 @@ const u_int invalidate_addr_reg[16] = {
static u_int jump_table_symbols[] = {
(int)invalidate_addr,
(int)jump_vaddr,
- (int)dyna_linker,
- (int)dyna_linker_ds,
+ (int)dynamic_linker,
+ (int)dynamic_linker_ds,
(int)verify_code,
(int)verify_code_vm,
(int)verify_code_ds,
@@ -302,6 +305,141 @@ static void set_jump_target_fillslot(int addr,u_int target,int copy)
}
*/
+
+void *dynamic_linker(void * src, int vaddr)
+{
+ u_int page=(vaddr^0x80000000)>>12;
+ u_int vpage=page;
+ if(page>262143&&tlb_LUT_r[vaddr>>12]) page=(tlb_LUT_r[vaddr>>12]^0x80000000)>>12;
+ if(page>2048) page=2048+(page&2047);
+ if(vpage>262143&&tlb_LUT_r[vaddr>>12]) vpage&=2047; // jump_dirty uses a hash of the virtual address instead
+ if(vpage>2048) vpage=2048+(vpage&2047);
+ struct ll_entry *head;
+ head=jump_in[page];
+
+ while(head!=NULL) {
+ if(head->vaddr==vaddr&&head->reg32==0) {
+ int *ptr=(int*)src;
+ assert((*ptr&0x0f000000)==0x0a000000); //jmp
+ int offset=(int)(((u_int)*ptr+2)<<8)>>6;
+ void *ptr2=(void*)((u_int)ptr+(u_int)offset);
+#ifdef ARMv5_ONLY
+ assert((*(int*)((u_int)ptr2)&0x0ff00000)==0x05900000); //ldr
+ assert((*(int*)((u_int)ptr2+4)&0x0ff00000)==0x05900000); //ldr
+ assert((*(int*)((u_int)ptr2+8)&0x0f000000)==0x0b000000); //bl
+ assert((*(int*)((u_int)ptr2+12)&0x0ff00000)==0x01a00000); //mov
+#else
+ assert((*(int*)((u_int)ptr2)&0x0ff00000)==0x03000000); //movw
+ assert((*(int*)((u_int)ptr2+4)&0x0ff00000)==0x03400000); //movt
+ assert((*(int*)((u_int)ptr2+8)&0x0ff00000)==0x03000000); //movw
+ assert((*(int*)((u_int)ptr2+12)&0x0ff00000)==0x03400000); //movt
+ assert((*(int*)((u_int)ptr2+16)&0x0f000000)==0x0b000000); //bl
+ assert((*(int*)((u_int)ptr2+20)&0x0ff00000)==0x01a00000); //mov
+#endif
+ add_link(vaddr, ptr2);
+ *ptr=(*ptr&0xFF000000)|((((u_int)head->addr-(u_int)ptr-8)<<6)>>8);
+ __clear_cache((void*)ptr, (void*)((u_int)ptr+4));
+ return head->addr;
+ }
+ head=head->next;
+ }
+
+ u_int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF];
+ if(ht_bin[0]==vaddr) return (void *)ht_bin[1];
+ if(ht_bin[2]==vaddr) return (void *)ht_bin[3];
+
+ head=jump_dirty[vpage];
+ while(head!=NULL) {
+ if(head->vaddr==vaddr&&head->reg32==0) {
+ u_int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF];
+ ht_bin[3]=ht_bin[1];
+ ht_bin[2]=ht_bin[0];
+ ht_bin[1]=(int)head->addr;
+ ht_bin[0]=vaddr;
+ return head->addr;
+ }
+ head=head->next;
+ }
+
+ int r=new_recompile_block(vaddr);
+ if(r==0) return dynamic_linker(src, vaddr);
+ // Execute in unmapped page, generate pagefault exception
+ g_cp0_regs[CP0_STATUS_REG]|=2;
+ g_cp0_regs[CP0_CAUSE_REG]=0x8;
+ g_cp0_regs[CP0_EPC_REG]=vaddr;
+ g_cp0_regs[CP0_BADVADDR_REG]=vaddr;
+ g_cp0_regs[CP0_CONTEXT_REG]=(g_cp0_regs[CP0_CONTEXT_REG]&0xFF80000F)|((g_cp0_regs[CP0_BADVADDR_REG]>>9)&0x007FFFF0);
+ g_cp0_regs[CP0_ENTRYHI_REG]=g_cp0_regs[CP0_BADVADDR_REG]&0xFFFFE000;
+ return get_addr_ht(0x80000000);
+}
+
+void *dynamic_linker_ds(void * src, int vaddr)
+{
+ u_int page=(vaddr^0x80000000)>>12;
+ u_int vpage=page;
+ if(page>262143&&tlb_LUT_r[vaddr>>12]) page=(tlb_LUT_r[vaddr>>12]^0x80000000)>>12;
+ if(page>2048) page=2048+(page&2047);
+ if(vpage>262143&&tlb_LUT_r[vaddr>>12]) vpage&=2047; // jump_dirty uses a hash of the virtual address instead
+ if(vpage>2048) vpage=2048+(vpage&2047);
+ struct ll_entry *head;
+ head=jump_in[page];
+
+ while(head!=NULL) {
+ if(head->vaddr==vaddr&&head->reg32==0) {
+ int *ptr=(int*)src;
+ assert((*ptr&0x0f000000)==0x0a000000); //jmp
+ int offset=(int)(((u_int)*ptr+2)<<8)>>6;
+ void *ptr2=(void*)((u_int)ptr+(u_int)offset);
+#ifdef ARMv5_ONLY
+ assert((*(int*)((u_int)ptr2)&0x0ff00000)==0x05900000); //ldr
+ assert((*(int*)((u_int)ptr2+4)&0x0ff00000)==0x05900000); //ldr
+ assert((*(int*)((u_int)ptr2+8)&0x0f000000)==0x0b000000); //bl
+ assert((*(int*)((u_int)ptr2+12)&0x0ff00000)==0x01a00000); //mov
+#else
+ assert((*(int*)((u_int)ptr2)&0x0ff00000)==0x03000000); //movw
+ assert((*(int*)((u_int)ptr2+4)&0x0ff00000)==0x03400000); //movt
+ assert((*(int*)((u_int)ptr2+8)&0x0ff00000)==0x03000000); //movw
+ assert((*(int*)((u_int)ptr2+12)&0x0ff00000)==0x03400000); //movt
+ assert((*(int*)((u_int)ptr2+16)&0x0f000000)==0x0b000000); //bl
+ assert((*(int*)((u_int)ptr2+20)&0x0ff00000)==0x01a00000); //mov
+#endif
+ add_link(vaddr, ptr2);
+ *ptr=(*ptr&0xFF000000)|((((u_int)head->addr-(u_int)ptr-8)<<6)>>8);
+ __clear_cache((void*)ptr, (void*)((u_int)ptr+4));
+ return head->addr;
+ }
+ head=head->next;
+ }
+
+ u_int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF];
+ if(ht_bin[0]==vaddr) return (void *)ht_bin[1];
+ if(ht_bin[2]==vaddr) return (void *)ht_bin[3];
+
+ head=jump_dirty[vpage];
+ while(head!=NULL) {
+ if(head->vaddr==vaddr&&head->reg32==0) {
+ u_int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF];
+ ht_bin[3]=ht_bin[1];
+ ht_bin[2]=ht_bin[0];
+ ht_bin[1]=(int)head->addr;
+ ht_bin[0]=vaddr;
+ return head->addr;
+ }
+ head=head->next;
+ }
+
+ int r=new_recompile_block((vaddr&0xFFFFFFF8)+1);
+ if(r==0) return dynamic_linker_ds(src, vaddr);
+ // Execute in unmapped page, generate pagefault exception
+ g_cp0_regs[CP0_STATUS_REG]|=2;
+ g_cp0_regs[CP0_CAUSE_REG]=0x80000008;
+ g_cp0_regs[CP0_EPC_REG]=(vaddr&0xFFFFFFF8)-4;
+ g_cp0_regs[CP0_BADVADDR_REG]=vaddr&0xFFFFFFF8;
+ g_cp0_regs[CP0_CONTEXT_REG]=(g_cp0_regs[CP0_CONTEXT_REG]&0xFF80000F)|((g_cp0_regs[CP0_BADVADDR_REG]>>9)&0x007FFFF0);
+ g_cp0_regs[CP0_ENTRYHI_REG]=g_cp0_regs[CP0_BADVADDR_REG]&0xFFFFE000;
+ return get_addr_ht(0x80000000);
+}
+
/* Literal pool */
static void add_literal(int addr,int val)
{
@@ -312,24 +450,40 @@ static void add_literal(int addr,int val)
static void *kill_pointer(void *stub)
{
+#ifdef ARMv5_ONLY
int *ptr=(int *)(stub+4);
- assert((*ptr&0x0ff00000)==0x05900000);
+ assert((*ptr&0x0ff00000)==0x05900000); //ldr
u_int offset=*ptr&0xfff;
int **l_ptr=(void *)ptr+offset+8;
int *i_ptr=*l_ptr;
+#else
+ int *ptr=(int *)(stub+8);
+ int *ptr2=(int *)(stub+12);
+ assert((*ptr&0x0ff00000)==0x03000000); //movw
+ assert((*ptr2&0x0ff00000)==0x03400000); //movt
+ int *i_ptr=(int*)((*ptr&0xfff)|((*ptr>>4)&0xf000)|((*ptr2&0xfff)<<16)|((*ptr2&0xf0000)<<12));
+#endif
+ assert((*i_ptr&0x0f000000)==0x0a000000); //jmp
set_jump_target((int)i_ptr,(int)stub);
return i_ptr;
}
static int get_pointer(void *stub)
{
- //DebugMessage(M64MSG_VERBOSE, "get_pointer(%x)",(int)stub);
+#ifdef ARMv5_ONLY
int *ptr=(int *)(stub+4);
- assert((*ptr&0x0ff00000)==0x05900000);
+ assert((*ptr&0x0ff00000)==0x05900000); //ldr
u_int offset=*ptr&0xfff;
int **l_ptr=(void *)ptr+offset+8;
int *i_ptr=*l_ptr;
- assert((*i_ptr&0x0f000000)==0x0a000000);
+#else
+ int *ptr=(int *)(stub+8);
+ int *ptr2=(int *)(stub+12);
+ assert((*ptr&0x0ff00000)==0x03000000); //movw
+ assert((*ptr2&0x0ff00000)==0x03400000); //movt
+ int *i_ptr=(int*)((*ptr&0xfff)|((*ptr>>4)&0xf000)|((*ptr2&0xfff)<<16)|((*ptr2&0xf0000)<<12));
+#endif
+ assert((*i_ptr&0x0f000000)==0x0a000000); //jmp
return (int)i_ptr+((*i_ptr<<8)>>6)+8;
}
@@ -1796,13 +1950,12 @@ static void emit_callreg(u_int r)
{
assem_debug("call *%%%s",regname[r]);
assert(0);
-}
+}*/
static void emit_jmpreg(u_int r)
{
assem_debug("mov pc,%s",regname[r]);
output_w32(0xe1a00000|rd_rn_rm(15,0,r));
}
-*/
static void emit_readword_indexed(int offset, int rs, int rt)
{
assert(offset>-4096&&offset<4096);
@@ -2614,8 +2767,15 @@ static void emit_extjump2(int addr, int target, int linker)
{
u_char *ptr=(u_char *)addr;
assert((ptr[3]&0x0e)==0xa);
- emit_loadlp(target,0);
- emit_loadlp(addr,1);
+#ifdef ARMv5_ONLY
+ emit_loadlp(target,1);
+ emit_loadlp(addr,0);
+#else
+ emit_movw(target&0x0000FFFF,1);
+ emit_movt(target&0xFFFF0000,1);
+ emit_movw(addr&0x0000FFFF,0);
+ emit_movt(addr&0xFFFF0000,0);
+#endif
//assert(addr>=0x7000000&&addr<0x7FFFFFF);
//assert((target>=0x80000000&&target<0x80800000)||(target>0xA4000000&&target<0xA4001000));
//DEBUG >
@@ -2628,16 +2788,17 @@ static void emit_extjump2(int addr, int target, int linker)
emit_writeword(ECX,(int)&last_count);
#endif
//DEBUG <
- emit_jmp(linker);
+ emit_call(linker);
+ emit_jmpreg(0);
}
static void emit_extjump(int addr, int target)
{
- emit_extjump2(addr, target, (int)dyna_linker);
+ emit_extjump2(addr, target, (int)dynamic_linker);
}
static void emit_extjump_ds(int addr, int target)
{
- emit_extjump2(addr, target, (int)dyna_linker_ds);
+ emit_extjump2(addr, target, (int)dynamic_linker_ds);
}
static void do_readstub(int n)
@@ -4603,9 +4764,9 @@ static void arch_init() {
// Jumping thru the trampolines created above slows things down by about 1%.
// If part of the cache is beyond the 32M limit, avoid using this area
// initially. It will be used later if the cache gets full.
- if((u_int)dyna_linker-33554432>(u_int)BASE_ADDR) {
- if((u_int)dyna_linker-33554432<(u_int)BASE_ADDR+(1<<(TARGET_SIZE_2-1))) {
- out=(u_char *)(((u_int)dyna_linker-33554432)&~4095);
+ if((u_int)dynamic_linker-33554432>(u_int)BASE_ADDR) {
+ if((u_int)dynamic_linker-33554432<(u_int)BASE_ADDR+(1<<(TARGET_SIZE_2-1))) {
+ out=(u_char *)(((u_int)dynamic_linker-33554432)&~4095);
expirep=((((int)out-BASE_ADDR)>>(TARGET_SIZE_2-16))+16384)&65535;
}
}
Oops, something went wrong.

0 comments on commit 9825b2f

Please sign in to comment.