diff options
Diffstat (limited to 'libpcsxcore/new_dynarec/new_dynarec.c')
-rw-r--r-- | libpcsxcore/new_dynarec/new_dynarec.c | 250 |
1 files changed, 153 insertions, 97 deletions
diff --git a/libpcsxcore/new_dynarec/new_dynarec.c b/libpcsxcore/new_dynarec/new_dynarec.c index cd63d2b..dfa17a7 100644 --- a/libpcsxcore/new_dynarec/new_dynarec.c +++ b/libpcsxcore/new_dynarec/new_dynarec.c @@ -32,10 +32,11 @@ #ifdef VITA #include <psp2/kernel/sysmem.h> static int sceBlock; +int getVMBlock(); #endif #include "new_dynarec_config.h" -#include "emu_if.h" //emulator interface +#include "backends/psx/emu_if.h" //emulator interface //#define DISASM //#define assem_debug printf @@ -44,13 +45,17 @@ static int sceBlock; #define inv_debug(...) #ifdef __i386__ -#include "assem_x86.h" +#include "x86/assem_x86.h" #endif #ifdef __x86_64__ -#include "assem_x64.h" +#include "x64/assem_x64.h" #endif #ifdef __arm__ -#include "assem_arm.h" +#include "arm/assem_arm.h" +#endif + +#ifdef VITA +int _newlib_vm_size_user = 1 << TARGET_SIZE_2; #endif #define MAXBLOCK 4096 @@ -361,14 +366,16 @@ static u_int get_vpage(u_int vaddr) // This is called from the recompiled JR/JALR instructions void *get_addr(u_int vaddr) { - u_int page=get_page(vaddr); - u_int vpage=get_vpage(vaddr); - struct ll_entry *head; + struct ll_entry *head = NULL; + u_int page = get_page(vaddr); + u_int vpage = get_vpage(vaddr); //printf("TRACE: count=%d next=%d (get_addr %x,page %d)\n",Count,next_interupt,vaddr,page); head=jump_in[page]; - while(head!=NULL) { - if(head->vaddr==vaddr) { - //printf("TRACE: count=%d next=%d (get_addr match %x: %x)\n",Count,next_interupt,vaddr,(int)head->addr); + while(head!=NULL) + { + if(head->vaddr==vaddr) + { + //printf("TRACE: count=%d next=%d (get_addr match %x: %x)\n",Count,next_interupt,vaddr,(int)head->addr); u_int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF]; ht_bin[3]=ht_bin[1]; ht_bin[2]=ht_bin[0]; @@ -379,39 +386,47 @@ void *get_addr(u_int vaddr) head=head->next; } head=jump_dirty[vpage]; - while(head!=NULL) { - if(head->vaddr==vaddr) { + while(head!=NULL) + { + if(head->vaddr==vaddr) + { //printf("TRACE: count=%d next=%d (get_addr match dirty %x: %x)\n",Count,next_interupt,vaddr,(int)head->addr); // Don't restore blocks which are about to expire from the cache if((((u_int)head->addr-(u_int)out)<<(32-TARGET_SIZE_2))>0x60000000+(MAX_OUTPUT_BLOCK_SIZE<<(32-TARGET_SIZE_2))) - if(verify_dirty(head->addr)) { - //printf("restore candidate: %x (%d) d=%d\n",vaddr,page,invalid_code[vaddr>>12]); - invalid_code[vaddr>>12]=0; - inv_code_start=inv_code_end=~0; - if(vpage<2048) { - restore_candidate[vpage>>3]|=1<<(vpage&7); - } - else restore_candidate[page>>3]|=1<<(page&7); - u_int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF]; - if(ht_bin[0]==vaddr) { - ht_bin[1]=(u_int)head->addr; // Replace existing entry - } - else + if(verify_dirty(head->addr)) { - ht_bin[3]=ht_bin[1]; - ht_bin[2]=ht_bin[0]; - ht_bin[1]=(int)head->addr; - ht_bin[0]=vaddr; + //printf("restore candidate: %x (%d) d=%d\n",vaddr,page,invalid_code[vaddr>>12]); + invalid_code[vaddr>>12]=0; + inv_code_start=inv_code_end=~0; + if(vpage<2048) + { + restore_candidate[vpage>>3]|=1<<(vpage&7); + } + else + { + restore_candidate[page>>3]|=1<<(page&7); + } + u_int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF]; + + if(ht_bin[0]==vaddr) + ht_bin[1]=(u_int)head->addr; // Replace existing entry + else + { + 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; } - return head->addr; - } } head=head->next; } //printf("TRACE: count=%d next=%d (get_addr no-match %x)\n",Count,next_interupt,vaddr); int r=new_recompile_block(vaddr); - if(r==0) return get_addr(vaddr); - // Execute in unmapped page, generate pagefault execption + if(r==0) + return get_addr(vaddr); + // Execute in unmapped page, generate pagefault exception Status|=2; Cause=(vaddr<<31)|0x8; EPC=(vaddr&1)?vaddr-5:vaddr; @@ -420,6 +435,7 @@ void *get_addr(u_int vaddr) EntryHi=BadVAddr&0xFFFFE000; return get_addr_ht(0x80000000); } + // Look up address in hash table first void *get_addr_ht(u_int vaddr) { @@ -763,13 +779,13 @@ void alloc_all(struct regstat *cur,int i) } #ifdef __i386__ -#include "assem_x86.c" +#include "x86/assem_x86.c" #endif #ifdef __x86_64__ -#include "assem_x64.c" +#include "x64/assem_x64.c" #endif #ifdef __arm__ -#include "assem_arm.c" +#include "arm/assem_arm.c" #endif // Add virtual address mapping to linked list @@ -943,23 +959,26 @@ static void invalidate_block_range(u_int block, u_int first, u_int last) assert(first+5>page); // NB: this assumes MAXBLOCK<=4096 (4 pages) assert(last<page+5); // Invalidate the adjacent pages if a block crosses a 4K boundary - while(first<page) { + while(first<page) + { invalidate_page(first); first++; } - for(first=page+1;first<last;first++) { + for(first=page+1;first<last;first++) + { invalidate_page(first); } - #ifdef __arm__ - do_clear_cache(); - #endif + +#ifdef __arm__ + do_clear_cache(); +#endif // Don't trap writes invalid_code[block]=1; - #ifdef USE_MINI_HT +#ifdef USE_MINI_HT memset(mini_ht,-1,sizeof(mini_ht)); - #endif +#endif } void invalidate_block(u_int block) @@ -967,19 +986,22 @@ void invalidate_block(u_int block) u_int page=get_page(block<<12); u_int vpage=get_vpage(block<<12); inv_debug("INVALIDATE: %x (%d)\n",block<<12,page); - //inv_debug("invalid_code[block]=%d\n",invalid_code[block]); u_int first,last; first=last=page; struct ll_entry *head; head=jump_dirty[vpage]; //printf("page=%d vpage=%d\n",page,vpage); - while(head!=NULL) { + while(head!=NULL) + { u_int start,end; - if(vpage>2047||(head->vaddr>>12)==block) { // Ignore vaddr hash collision + if(vpage>2047||(head->vaddr>>12)==block) + { // Ignore vaddr hash collision get_bounds((int)head->addr,&start,&end); //printf("start: %x end: %x\n",start,end); - if(page<2048&&start>=(u_int)rdram&&end<(u_int)rdram+RAM_SIZE) { - if(((start-(u_int)rdram)>>12)<=page&&((end-1-(u_int)rdram)>>12)>=page) { + if(page<2048&&start>=(u_int)rdram&&end<(u_int)rdram+RAM_SIZE) + { + if(((start-(u_int)rdram)>>12)<=page&&((end-1-(u_int)rdram)>>12)>=page) + { if((((start-(u_int)rdram)>>12)&2047)<first) first=((start-(u_int)rdram)>>12)&2047; if((((end-1-(u_int)rdram)>>12)&2047)>last) last=((end-1-(u_int)rdram)>>12)&2047; } @@ -1050,19 +1072,23 @@ void invalidate_addr(u_int addr) // This is called when loading a save state. // Anything could have changed, so invalidate everything. -void invalidate_all_pages() +void invalidate_all_pages(void) { u_int page; for(page=0;page<4096;page++) invalidate_page(page); for(page=0;page<1048576;page++) - if(!invalid_code[page]) { + { + if(!invalid_code[page]) + { restore_candidate[(page&2047)>>3]|=1<<(page&7); restore_candidate[((page&2047)>>3)+256]|=1<<(page&7); } - #ifdef USE_MINI_HT + } + +#ifdef USE_MINI_HT memset(mini_ht,-1,sizeof(mini_ht)); - #endif +#endif } // Add an entry to jump_out after making a link @@ -1087,37 +1113,48 @@ void clean_blocks(u_int page) struct ll_entry *head; inv_debug("INV: clean_blocks page=%d\n",page); head=jump_dirty[page]; - while(head!=NULL) { - if(!invalid_code[head->vaddr>>12]) { + while(head!=NULL) + { + if(!invalid_code[head->vaddr>>12]) + { // Don't restore blocks which are about to expire from the cache - if((((u_int)head->addr-(u_int)out)<<(32-TARGET_SIZE_2))>0x60000000+(MAX_OUTPUT_BLOCK_SIZE<<(32-TARGET_SIZE_2))) { + if((((u_int)head->addr-(u_int)out)<<(32-TARGET_SIZE_2))>0x60000000+(MAX_OUTPUT_BLOCK_SIZE<<(32-TARGET_SIZE_2))) + { u_int start,end; - if(verify_dirty(head->addr)) { + if(verify_dirty(head->addr)) + { //printf("Possibly Restore %x (%x)\n",head->vaddr, (int)head->addr); u_int i; u_int inv=0; get_bounds((int)head->addr,&start,&end); - if(start-(u_int)rdram<RAM_SIZE) { - for(i=(start-(u_int)rdram+0x80000000)>>12;i<=(end-1-(u_int)rdram+0x80000000)>>12;i++) { + if(start-(u_int)rdram<RAM_SIZE) + { + for(i=(start-(u_int)rdram+0x80000000)>>12;i<=(end-1-(u_int)rdram+0x80000000)>>12;i++) + { inv|=invalid_code[i]; } } - else if((signed int)head->vaddr>=(signed int)0x80000000+RAM_SIZE) { + else if((signed int)head->vaddr>=(signed int)0x80000000+RAM_SIZE) + { inv=1; } - if(!inv) { + if(!inv) + { void * clean_addr=(void *)get_clean_addr((int)head->addr); - if((((u_int)clean_addr-(u_int)out)<<(32-TARGET_SIZE_2))>0x60000000+(MAX_OUTPUT_BLOCK_SIZE<<(32-TARGET_SIZE_2))) { + if((((u_int)clean_addr-(u_int)out)<<(32-TARGET_SIZE_2))>0x60000000+(MAX_OUTPUT_BLOCK_SIZE<<(32-TARGET_SIZE_2))) + { u_int ppage=page; inv_debug("INV: Restored %x (%x/%x)\n",head->vaddr, (int)head->addr, (int)clean_addr); //printf("page=%x, addr=%x\n",page,head->vaddr); //assert(head->vaddr>>12==(page|0x80000)); ll_add_flags(jump_in+ppage,head->vaddr,head->reg_sv_flags,clean_addr); u_int *ht_bin=hash_table[((head->vaddr>>16)^head->vaddr)&0xFFFF]; - if(ht_bin[0]==head->vaddr) { + if(ht_bin[0]==head->vaddr) + { ht_bin[1]=(u_int)clean_addr; // Replace existing entry } - if(ht_bin[2]==head->vaddr) { + if(ht_bin[2]==head->vaddr) + { ht_bin[3]=(u_int)clean_addr; // Replace existing entry } } @@ -1129,15 +1166,17 @@ void clean_blocks(u_int page) } } - -void mov_alloc(struct regstat *current,int i) +static void mov_alloc(struct regstat *current,int i) { // Note: Don't need to actually alloc the source registers - if((~current->is32>>rs1[i])&1) { + if((~current->is32>>rs1[i])&1) + { //alloc_reg64(current,i,rs1[i]); alloc_reg64(current,i,rt1[i]); current->is32&=~(1LL<<rt1[i]); - } else { + } + else + { //alloc_reg(current,i,rs1[i]); alloc_reg(current,i,rt1[i]); current->is32|=(1LL<<rt1[i]); @@ -1695,7 +1734,8 @@ void syscall_alloc(struct regstat *current,int i) void delayslot_alloc(struct regstat *current,int i) { - switch(itype[i]) { + switch(itype[i]) + { case UJUMP: case CJUMP: case SJUMP: @@ -1845,7 +1885,8 @@ void wb_register(signed char r,signed char regmap[],uint64_t dirty,uint64_t is32 } } -int mchecksum() +#if 0 +static int mchecksum(void) { //if(!tracedebug) return 0; int i; @@ -1858,7 +1899,8 @@ int mchecksum() } return sum; } -int rchecksum() + +static int rchecksum(void) { int i; int sum=0; @@ -1866,7 +1908,8 @@ int rchecksum() sum^=((u_int *)reg)[i]; return sum; } -void rlist() + +static void rlist(void) { int i; printf("TRACE: "); @@ -1875,12 +1918,12 @@ void rlist() printf("\n"); } -void enabletrace() +static void enabletrace(void) { tracedebug=1; } -void memdebug(int i) +static void memdebug(int i) { //printf("TRACE: count=%d next=%d (checksum %x) lo=%8x%8x\n",Count,next_interupt,mchecksum(),(int)(reg[LOREG]>>32),(int)reg[LOREG]); //printf("TRACE: count=%d next=%d (rchecksum %x)\n",Count,next_interupt,rchecksum()); @@ -1905,6 +1948,7 @@ void memdebug(int i) } //printf("TRACE: %x\n",(&i)[-1]); } +#endif void alu_assemble(int i,struct regstat *i_regs) { @@ -7016,7 +7060,7 @@ static int new_dynarec_test(void) // clear the state completely, instead of just marking // things invalid like invalidate_all_pages() does -void new_dynarec_clear_full() +void new_dynarec_clear_full(void) { int n; out=(u_char *)BASE_ADDR; @@ -7037,7 +7081,7 @@ void new_dynarec_clear_full() for(n=0;n<4096;n++) ll_clear(jump_dirty+n); } -void new_dynarec_init() +void new_dynarec_init(void) { SysPrintf("Init new dynarec\n"); @@ -7045,37 +7089,45 @@ void new_dynarec_init() // see assem_arm.h for some explanation #if defined(BASE_ADDR_FIXED) if (mmap (translation_cache, 1 << TARGET_SIZE_2, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, - -1, 0) != translation_cache) { + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0) != translation_cache) + { SysPrintf("mmap() failed: %s\n", strerror(errno)); SysPrintf("disable BASE_ADDR_FIXED and recompile\n"); abort(); } #elif defined(BASE_ADDR_DYNAMIC) - #ifdef VITA - sceBlock = sceKernelAllocMemBlockForVM("code", 1 << TARGET_SIZE_2); +#ifdef VITA + sceBlock = getVMBlock();//sceKernelAllocMemBlockForVM("code", 1 << TARGET_SIZE_2); if (sceBlock < 0) SysPrintf("sceKernelAllocMemBlockForVM failed\n"); int ret = sceKernelGetMemBlockBase(sceBlock, (void **)&translation_cache); if (ret < 0) SysPrintf("sceKernelGetMemBlockBase failed\n"); - #else + + sceKernelOpenVMDomain(); + sceClibPrintf("translation_cache = 0x%08X \n ", translation_cache); +#elif defined(_MSC_VER) + base_addr = VirtualAlloc(NULL, 1<<TARGET_SIZE_2, MEM_COMMIT | MEM_RESERVE, + PAGE_EXECUTE_READWRITE); +#else translation_cache = mmap (NULL, 1 << TARGET_SIZE_2, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (translation_cache == MAP_FAILED) { SysPrintf("mmap() failed: %s\n", strerror(errno)); abort(); } - #endif +#endif #else - #ifndef NO_WRITE_EXEC +#ifndef NO_WRITE_EXEC // not all systems allow execute in data segment by default if (mprotect((void *)BASE_ADDR, 1<<TARGET_SIZE_2, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) SysPrintf("mprotect() failed: %s\n", strerror(errno)); - #endif #endif +#endif + out=(u_char *)BASE_ADDR; cycle_multiplier=200; new_dynarec_clear_full(); @@ -7092,24 +7144,28 @@ void new_dynarec_init() SysPrintf("warning: RAM is not directly mapped, performance will suffer\n"); } -void new_dynarec_cleanup() +void new_dynarec_cleanup(void) { int n; #if defined(BASE_ADDR_FIXED) || defined(BASE_ADDR_DYNAMIC) - #ifdef VITA - sceKernelFreeMemBlock(sceBlock); - sceBlock = -1; - #else +#ifndef VITA +#if defined(_MSC_VER) + VirtualFree(base_addr, 0, MEM_RELEASE); +#else if (munmap ((void *)BASE_ADDR, 1<<TARGET_SIZE_2) < 0) SysPrintf("munmap() failed\n"); - #endif #endif - for(n=0;n<4096;n++) ll_clear(jump_in+n); - for(n=0;n<4096;n++) ll_clear(jump_out+n); - for(n=0;n<4096;n++) ll_clear(jump_dirty+n); - #ifdef ROM_COPY +#endif +#endif + for(n=0;n<4096;n++) + ll_clear(jump_in+n); + for(n=0;n<4096;n++) + ll_clear(jump_out+n); + for(n=0;n<4096;n++) + ll_clear(jump_dirty+n); +#ifdef ROM_COPY if (munmap (ROM_COPY, 67108864) < 0) {SysPrintf("munmap() failed\n");} - #endif +#endif } static u_int *get_source_start(u_int addr, u_int *limit) |