#include <stdlib.h>
#include <stdint.h> //include for uint64_t
#include <assert.h>
+#include <errno.h>
#include <sys/mman.h>
#include "emu_if.h" //emulator interface
#include "assem_arm.h"
#endif
+#ifdef __BLACKBERRY_QNX__
+#undef __clear_cache
+#define __clear_cache(start,end) msync(start, (size_t)((void*)end - (void*)start), MS_SYNC | MS_CACHE_ONLY | MS_INVALIDATE_ICACHE);
+#elif defined(__MACH__)
+#include <libkern/OSCacheControl.h>
+#define __clear_cache mach_clear_cache
+static void __clear_cache(void *start, void *end) {
+ size_t len = (char *)end - (char *)start;
+ sys_dcache_flush(start, len);
+ sys_icache_invalidate(start, len);
+}
+#endif
+
#define MAXBLOCK 4096
#define MAX_OUTPUT_BLOCK_SIZE 262144
u_int waswritten; // MIPS regs that were used as store base before
};
+// note: asm depends on this layout
struct ll_entry
{
u_int vaddr;
- u_int reg32;
+ u_int reg_sv_flags;
void *addr;
struct ll_entry *next;
};
u_int start;
u_int *source;
- u_int pagelimit;
char insn[MAXBLOCK][10];
u_char itype[MAXBLOCK];
u_char opcode[MAXBLOCK];
int is_delayslot;
int cop1_usable;
u_char *out;
- struct ll_entry *jump_in[4096];
+ struct ll_entry *jump_in[4096] __attribute__((aligned(16)));
struct ll_entry *jump_out[4096];
struct ll_entry *jump_dirty[4096];
u_int hash_table[65536][4] __attribute__((aligned(16)));
//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&&head->reg32==0) {
+ if(head->vaddr==vaddr) {
//printf("TRACE: count=%d next=%d (get_addr match %x: %x)\n",Count,next_interupt,vaddr,(int)head->addr);
int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF];
ht_bin[3]=ht_bin[1];
}
head=jump_dirty[vpage];
while(head!=NULL) {
- if(head->vaddr==vaddr&&head->reg32==0) {
+ 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)))
return get_addr(vaddr);
}
-void *get_addr_32(u_int vaddr,u_int flags)
-{
-#ifdef FORCE32
- return get_addr(vaddr);
-#else
- //printf("TRACE: count=%d next=%d (get_addr_32 %x,flags %x)\n",Count,next_interupt,vaddr,flags);
- 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];
- u_int page=get_page(vaddr);
- u_int vpage=get_vpage(vaddr);
- struct ll_entry *head;
- head=jump_in[page];
- while(head!=NULL) {
- if(head->vaddr==vaddr&&(head->reg32&flags)==0) {
- //printf("TRACE: count=%d next=%d (get_addr_32 match %x: %x)\n",Count,next_interupt,vaddr,(int)head->addr);
- if(head->reg32==0) {
- int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF];
- if(ht_bin[0]==-1) {
- ht_bin[1]=(int)head->addr;
- ht_bin[0]=vaddr;
- }else if(ht_bin[2]==-1) {
- ht_bin[3]=(int)head->addr;
- ht_bin[2]=vaddr;
- }
- //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;
- }
- head=jump_dirty[vpage];
- while(head!=NULL) {
- if(head->vaddr==vaddr&&(head->reg32&flags)==0) {
- //printf("TRACE: count=%d next=%d (get_addr_32 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;
- memory_map[vaddr>>12]|=0x40000000;
- if(vpage<2048) {
-#ifndef DISABLE_TLB
- if(tlb_LUT_r[vaddr>>12]) {
- invalid_code[tlb_LUT_r[vaddr>>12]>>12]=0;
- memory_map[tlb_LUT_r[vaddr>>12]>>12]|=0x40000000;
- }
-#endif
- restore_candidate[vpage>>3]|=1<<(vpage&7);
- }
- else restore_candidate[page>>3]|=1<<(page&7);
- if(head->reg32==0) {
- int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF];
- if(ht_bin[0]==-1) {
- ht_bin[1]=(int)head->addr;
- ht_bin[0]=vaddr;
- }else if(ht_bin[2]==-1) {
- ht_bin[3]=(int)head->addr;
- ht_bin[2]=vaddr;
- }
- //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;
- }
- //printf("TRACE: count=%d next=%d (get_addr_32 no-match %x,flags %x)\n",Count,next_interupt,vaddr,flags);
- int r=new_recompile_block(vaddr);
- if(r==0) return get_addr(vaddr);
- // Execute in unmapped page, generate pagefault execption
- Status|=2;
- Cause=(vaddr<<31)|0x8;
- EPC=(vaddr&1)?vaddr-5:vaddr;
- BadVAddr=(vaddr&~1);
- Context=(Context&0xFF80000F)|((BadVAddr>>9)&0x007FFFF0);
- EntryHi=BadVAddr&0xFFFFE000;
- return get_addr_ht(0x80000000);
-#endif
-}
-
void clear_all_regs(signed char regmap[])
{
int hr;
return current_constmap[hr];
}
}
- printf("Unknown constant in r%d\n",reg);
+ SysPrintf("Unknown constant in r%d\n",reg);
exit(1);
}
new_entry=malloc(sizeof(struct ll_entry));
assert(new_entry!=NULL);
new_entry->vaddr=vaddr;
- new_entry->reg32=0;
+ new_entry->reg_sv_flags=0;
new_entry->addr=addr;
new_entry->next=*head;
*head=new_entry;
}
-// Add virtual address mapping for 32-bit compiled block
-void ll_add_32(struct ll_entry **head,int vaddr,u_int reg32,void *addr)
+void ll_add_flags(struct ll_entry **head,int vaddr,u_int reg_sv_flags,void *addr)
{
ll_add(head,vaddr,addr);
-#ifndef FORCE32
- (*head)->reg32=reg32;
-#endif
+ (*head)->reg_sv_flags=reg_sv_flags;
}
// Check if an address is already compiled
struct ll_entry *head;
head=jump_in[page];
while(head!=NULL) {
- if(head->vaddr==vaddr&&head->reg32==0) {
+ if(head->vaddr==vaddr) {
if((((u_int)head->addr-(u_int)out)<<(32-TARGET_SIZE_2))>0x60000000+(MAX_OUTPUT_BLOCK_SIZE<<(32-TARGET_SIZE_2))) {
// Update existing entry with current address
if(ht_bin[0]==vaddr) {
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_32(jump_in+ppage,head->vaddr,head->reg32,clean_addr);
+ ll_add_flags(jump_in+ppage,head->vaddr,head->reg_sv_flags,clean_addr);
int *ht_bin=hash_table[((head->vaddr>>16)^head->vaddr)&0xFFFF];
- if(!head->reg32) {
- if(ht_bin[0]==head->vaddr) {
- ht_bin[1]=(int)clean_addr; // Replace existing entry
- }
- if(ht_bin[2]==head->vaddr) {
- ht_bin[3]=(int)clean_addr; // Replace existing entry
- }
+ if(ht_bin[0]==head->vaddr) {
+ ht_bin[1]=(int)clean_addr; // Replace existing entry
+ }
+ if(ht_bin[2]==head->vaddr) {
+ ht_bin[3]=(int)clean_addr; // Replace existing entry
}
}
}
case HLECALL:
case SPAN:
assem_debug("jump in the delay slot. this shouldn't happen.\n");//exit(1);
- printf("Disabled speculative precompilation\n");
+ SysPrintf("Disabled speculative precompilation\n");
stop_after_jal=1;
break;
case IMM16:
// basic current block modification detection..
// not looking back as that should be in mips cache already
if(c&&start+i*4<addr_val&&addr_val<start+slen*4) {
- printf("write to %08x hits block %08x, pc=%08x\n",addr_val,start,start+i*4);
+ SysPrintf("write to %08x hits block %08x, pc=%08x\n",addr_val,start,start+i*4);
assert(i_regs->regmap==regs[i].regmap); // not delay slot
if(i_regs->regmap==regs[i].regmap) {
load_all_consts(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty,i);
case CJUMP:
case SJUMP:
case FJUMP:
- printf("Jump in the delay slot. This is probably a bug.\n");
+ SysPrintf("Jump in the delay slot. This is probably a bug.\n");
}
is_delayslot=0;
}
case CJUMP:
case SJUMP:
case FJUMP:
- printf("Jump in the delay slot. This is probably a bug.\n");
+ SysPrintf("Jump in the delay slot. This is probably a bug.\n");
}
store_regs_bt(regs[t].regmap,regs[t].is32,regs[t].dirty,ba[i]+4);
load_regs_bt(regs[t].regmap,regs[t].is32,regs[t].dirty,ba[i]+4);
}
emit_writeword(r,(int)&pcaddr);
}
- else {printf("Unknown branch type in do_ccstub\n");exit(1);}
+ else {SysPrintf("Unknown branch type in do_ccstub\n");exit(1);}
}
// Update cycle count
assert(branch_regs[i].regmap[HOST_CCREG]==CCREG||branch_regs[i].regmap[HOST_CCREG]==-1);
case CJUMP:
case SJUMP:
case FJUMP:
- printf("Jump in the delay slot. This is probably a bug.\n");
+ SysPrintf("Jump in the delay slot. This is probably a bug.\n");
}
int btaddr=get_reg(regs[0].regmap,BTREG);
if(btaddr<0) {
static void disassemble_inst(int i) {}
#endif // DISASM
+#define DRC_TEST_VAL 0x74657374
+
+static int new_dynarec_test(void)
+{
+ int (*testfunc)(void) = (void *)out;
+ int ret;
+ emit_movimm(DRC_TEST_VAL,0); // test
+ emit_jmpreg(14);
+ literal_pool(0);
+#ifdef __arm__
+ __clear_cache((void *)testfunc, out);
+#endif
+ SysPrintf("testing if we can run recompiled code..\n");
+ ret = testfunc();
+ if (ret == DRC_TEST_VAL)
+ SysPrintf("test passed.\n");
+ else
+ SysPrintf("test failed: %08x\n", ret);
+ out=(u_char *)BASE_ADDR;
+ return ret == DRC_TEST_VAL;
+}
+
// clear the state completely, instead of just marking
// things invalid like invalidate_all_pages() does
void new_dynarec_clear_full()
void new_dynarec_init()
{
- printf("Init new dynarec\n");
+ SysPrintf("Init new dynarec\n");
out=(u_char *)BASE_ADDR;
#if BASE_ADDR_FIXED
if (mmap (out, 1<<TARGET_SIZE_2,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
- -1, 0) <= 0) {printf("mmap() failed\n");}
+ -1, 0) <= 0) {
+ SysPrintf("mmap() failed: %s\n", strerror(errno));
+ }
#else
// not all systems allow execute in data segment by default
if (mprotect(out, 1<<TARGET_SIZE_2, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
- printf("mprotect() failed\n");
+ SysPrintf("mprotect() failed: %s\n", strerror(errno));
#endif
#ifdef MUPEN64
rdword=&readmem_dword;
#endif
tlb_hacks();
arch_init();
+ new_dynarec_test();
#ifndef RAM_FIXED
ram_offset=(u_int)rdram-0x80000000;
#endif
if (ram_offset!=0)
- printf("warning: RAM is not directly mapped, performance will suffer\n");
+ SysPrintf("warning: RAM is not directly mapped, performance will suffer\n");
}
void new_dynarec_cleanup()
{
int n;
#if BASE_ADDR_FIXED
- if (munmap ((void *)BASE_ADDR, 1<<TARGET_SIZE_2) < 0) {printf("munmap() failed\n");}
+ if (munmap ((void *)BASE_ADDR, 1<<TARGET_SIZE_2) < 0) {SysPrintf("munmap() failed\n");}
#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) {printf("munmap() failed\n");}
+ if (munmap (ROM_COPY, 67108864) < 0) {SysPrintf("munmap() failed\n");}
#endif
}
-int new_recompile_block(int addr)
+static u_int *get_source_start(u_int addr, u_int *limit)
{
-/*
- if(addr==0x800cd050) {
- int block;
- for(block=0x80000;block<0x80800;block++) invalidate_block(block);
- int n;
- for(n=0;n<=2048;n++) ll_clear(jump_dirty+n);
+ if (addr < 0x00200000 ||
+ (0xa0000000 <= addr && addr < 0xa0200000)) {
+ // used for BIOS calls mostly?
+ *limit = (addr&0xa0000000)|0x00200000;
+ return (u_int *)((u_int)rdram + (addr&0x1fffff));
}
-*/
- //if(Count==365117028) tracedebug=1;
+ else if (!Config.HLE && (
+ /* (0x9fc00000 <= addr && addr < 0x9fc80000) ||*/
+ (0xbfc00000 <= addr && addr < 0xbfc80000))) {
+ // BIOS
+ *limit = (addr & 0xfff00000) | 0x80000;
+ return (u_int *)((u_int)psxR + (addr&0x7ffff));
+ }
+ else if (addr >= 0x80000000 && addr < 0x80000000+RAM_SIZE) {
+ *limit = (addr & 0x80600000) + 0x00200000;
+ return (u_int *)((u_int)rdram + (addr&0x1fffff));
+ }
+}
+
+static u_int scan_for_ret(u_int addr)
+{
+ u_int limit = 0;
+ u_int *mem;
+
+ mem = get_source_start(addr, &limit);
+ if (mem == NULL)
+ return addr;
+
+ if (limit > addr + 0x1000)
+ limit = addr + 0x1000;
+ for (; addr < limit; addr += 4, mem++) {
+ if (*mem == 0x03e00008) // jr $ra
+ return addr + 8;
+ }
+}
+
+struct savestate_block {
+ uint32_t addr;
+ uint32_t regflags;
+};
+
+static int addr_cmp(const void *p1_, const void *p2_)
+{
+ const struct savestate_block *p1 = p1_, *p2 = p2_;
+ return p1->addr - p2->addr;
+}
+
+int new_dynarec_save_blocks(void *save, int size)
+{
+ struct savestate_block *blocks = save;
+ int maxcount = size / sizeof(blocks[0]);
+ struct savestate_block tmp_blocks[1024];
+ struct ll_entry *head;
+ int p, s, d, o, bcnt;
+ u_int addr;
+
+ o = 0;
+ for (p = 0; p < sizeof(jump_in) / sizeof(jump_in[0]); p++) {
+ bcnt = 0;
+ for (head = jump_in[p]; head != NULL; head = head->next) {
+ tmp_blocks[bcnt].addr = head->vaddr;
+ tmp_blocks[bcnt].regflags = head->reg_sv_flags;
+ bcnt++;
+ }
+ if (bcnt < 1)
+ continue;
+ qsort(tmp_blocks, bcnt, sizeof(tmp_blocks[0]), addr_cmp);
+
+ addr = tmp_blocks[0].addr;
+ for (s = d = 0; s < bcnt; s++) {
+ if (tmp_blocks[s].addr < addr)
+ continue;
+ if (d == 0 || tmp_blocks[d-1].addr != tmp_blocks[s].addr)
+ tmp_blocks[d++] = tmp_blocks[s];
+ addr = scan_for_ret(tmp_blocks[s].addr);
+ }
+
+ if (o + d > maxcount)
+ d = maxcount - o;
+ memcpy(&blocks[o], tmp_blocks, d * sizeof(blocks[0]));
+ o += d;
+ }
+
+ return o * sizeof(blocks[0]);
+}
+
+void new_dynarec_load_blocks(const void *save, int size)
+{
+ const struct savestate_block *blocks = save;
+ int count = size / sizeof(blocks[0]);
+ u_int regs_save[32];
+ uint32_t f;
+ int i, b;
+
+ get_addr(psxRegs.pc);
+
+ // change GPRs for speculation to at least partially work..
+ memcpy(regs_save, &psxRegs.GPR, sizeof(regs_save));
+ for (i = 1; i < 32; i++)
+ psxRegs.GPR.r[i] = 0x80000000;
+
+ for (b = 0; b < count; b++) {
+ for (f = blocks[b].regflags, i = 0; f; f >>= 1, i++) {
+ if (f & 1)
+ psxRegs.GPR.r[i] = 0x1f800000;
+ }
+
+ get_addr(blocks[b].addr);
+
+ for (f = blocks[b].regflags, i = 0; f; f >>= 1, i++) {
+ if (f & 1)
+ psxRegs.GPR.r[i] = 0x80000000;
+ }
+ }
+
+ memcpy(&psxRegs.GPR, regs_save, sizeof(regs_save));
+}
+
+int new_recompile_block(int addr)
+{
+ u_int pagelimit = 0;
+ u_int state_rflags = 0;
+ int i;
+
assem_debug("NOTCOMPILED: addr = %x -> %x\n", (int)addr, (int)out);
//printf("NOTCOMPILED: addr = %x -> %x\n", (int)addr, (int)out);
//printf("TRACE: count=%d next=%d (compile %x)\n",Count,next_interupt,addr);
rlist();
}*/
//rlist();
+
+ // this is just for speculation
+ for (i = 1; i < 32; i++) {
+ if ((psxRegs.GPR.r[i] & 0xffff0000) == 0x1f800000)
+ state_rflags |= 1 << i;
+ }
+
start = (u_int)addr&~3;
//assert(((u_int)addr&1)==0);
new_dynarec_did_compile=1;
-#ifdef PCSX
if (Config.HLE && start == 0x80001000) // hlecall
{
// XXX: is this enough? Maybe check hleSoftCall?
#ifdef __arm__
__clear_cache((void *)beginning,out);
#endif
- ll_add(jump_in+page,start,(void *)beginning);
+ ll_add_flags(jump_in+page,start,state_rflags,(void *)beginning);
return 0;
}
- else if ((u_int)addr < 0x00200000 ||
- (0xa0000000 <= addr && addr < 0xa0200000)) {
- // used for BIOS calls mostly?
- source = (u_int *)((u_int)rdram+(start&0x1fffff));
- pagelimit = (addr&0xa0000000)|0x00200000;
- }
- else if (!Config.HLE && (
-/* (0x9fc00000 <= addr && addr < 0x9fc80000) ||*/
- (0xbfc00000 <= addr && addr < 0xbfc80000))) {
- // BIOS
- source = (u_int *)((u_int)psxR+(start&0x7ffff));
- pagelimit = (addr&0xfff00000)|0x80000;
- }
- else
-#endif
-#ifdef MUPEN64
- if ((int)addr >= 0xa4000000 && (int)addr < 0xa4001000) {
- source = (u_int *)((u_int)SP_DMEM+start-0xa4000000);
- pagelimit = 0xa4001000;
- }
- else
-#endif
- if ((int)addr >= 0x80000000 && (int)addr < 0x80000000+RAM_SIZE) {
- source = (u_int *)((u_int)rdram+start-0x80000000);
- pagelimit = 0x80000000+RAM_SIZE;
- }
-#ifndef DISABLE_TLB
- else if ((signed int)addr >= (signed int)0xC0000000) {
- //printf("addr=%x mm=%x\n",(u_int)addr,(memory_map[start>>12]<<2));
- //if(tlb_LUT_r[start>>12])
- //source = (u_int *)(((int)rdram)+(tlb_LUT_r[start>>12]&0xFFFFF000)+(((int)addr)&0xFFF)-0x80000000);
- if((signed int)memory_map[start>>12]>=0) {
- source = (u_int *)((u_int)(start+(memory_map[start>>12]<<2)));
- pagelimit=(start+4096)&0xFFFFF000;
- int map=memory_map[start>>12];
- int i;
- for(i=0;i<5;i++) {
- //printf("start: %x next: %x\n",map,memory_map[pagelimit>>12]);
- if((map&0xBFFFFFFF)==(memory_map[pagelimit>>12]&0xBFFFFFFF)) pagelimit+=4096;
- }
- assem_debug("pagelimit=%x\n",pagelimit);
- assem_debug("mapping=%x (%x)\n",memory_map[start>>12],(memory_map[start>>12]<<2)+start);
- }
- else {
- assem_debug("Compile at unmapped memory address: %x \n", (int)addr);
- //assem_debug("start: %x next: %x\n",memory_map[start>>12],memory_map[(start+4096)>>12]);
- return -1; // Caller will invoke exception handler
- }
- //printf("source= %x\n",(int)source);
- }
-#endif
- else {
- printf("Compile at bogus memory address: %x \n", (int)addr);
+
+ source = get_source_start(start, &pagelimit);
+ if (source == NULL) {
+ SysPrintf("Compile at bogus memory address: %08x\n", addr);
exit(1);
}
/* Pass 9: linker */
/* Pass 10: garbage collection / free memory */
- int i,j;
+ int j;
int done=0;
unsigned int type,op,op2;
case 0x3B: strcpy(insn[i],"HLECALL"); type=HLECALL; break;
#endif
default: strcpy(insn[i],"???"); type=NI;
- printf("NI %08x @%08x (%08x)\n", source[i], addr + i*4, addr);
+ SysPrintf("NI %08x @%08x (%08x)\n", source[i], addr + i*4, addr);
break;
}
itype[i]=type;
// branch in delay slot?
if(type==RJUMP||type==UJUMP||type==CJUMP||type==SJUMP||type==FJUMP) {
// don't handle first branch and call interpreter if it's hit
- printf("branch in delay slot @%08x (%08x)\n", addr + i*4, addr);
+ SysPrintf("branch in delay slot @%08x (%08x)\n", addr + i*4, addr);
do_in_intrp=1;
}
// basic load delay detection
int t=(ba[i-1]-start)/4;
if(0 <= t && t < i &&(rt1[i]==rs1[t]||rt1[i]==rs2[t])&&itype[t]!=CJUMP&&itype[t]!=SJUMP) {
// jump target wants DS result - potential load delay effect
- printf("load delay @%08x (%08x)\n", addr + i*4, addr);
+ SysPrintf("load delay @%08x (%08x)\n", addr + i*4, addr);
do_in_intrp=1;
bt[t+1]=1; // expected return from interpreter
}
else if(i>=2&&rt1[i-2]==2&&rt1[i]==2&&rs1[i]!=2&&rs2[i]!=2&&rs1[i-1]!=2&&rs2[i-1]!=2&&
!(i>=3&&(itype[i-3]==RJUMP||itype[i-3]==UJUMP||itype[i-3]==CJUMP||itype[i-3]==SJUMP))) {
// v0 overwrite like this is a sign of trouble, bail out
- printf("v0 overwrite @%08x (%08x)\n", addr + i*4, addr);
+ SysPrintf("v0 overwrite @%08x (%08x)\n", addr + i*4, addr);
do_in_intrp=1;
}
}
// Stop if we're compiling junk
if(itype[i]==NI&&opcode[i]==0x11) {
done=stop_after_jal=1;
- printf("Disabled speculative precompilation\n");
+ SysPrintf("Disabled speculative precompilation\n");
}
}
slen=i;
current.uu&=~((1LL<<us1[i])|(1LL<<us2[i]));
current.u|=1;
current.uu|=1;
- } else { printf("oops, branch at end of block with no delay slot\n");exit(1); }
+ } else { SysPrintf("oops, branch at end of block with no delay slot\n");exit(1); }
}
is_ds[i]=ds;
if(ds) {
{
cc+=2; // 2 cycle penalty (after CLOCK_DIVIDER)
}
+ else if(i>1&&itype[i]==STORE&&itype[i-1]==STORE&&itype[i-2]==STORE&&!bt[i])
+ {
+ cc+=4;
+ }
else if(itype[i]==C2LS)
{
cc+=4;
if(regmap_pre[i+1][hr]!=regs[i].regmap[hr])
if(regs[i].regmap[hr]<64||!((regs[i].was32>>(regs[i].regmap[hr]&63))&1))
{
- printf("fail: %x (%d %d!=%d)\n",start+i*4,hr,regmap_pre[i+1][hr],regs[i].regmap[hr]);
+ SysPrintf("fail: %x (%d %d!=%d)\n",start+i*4,hr,regmap_pre[i+1][hr],regs[i].regmap[hr]);
assert(regmap_pre[i+1][hr]==regs[i].regmap[hr]);
}
regmap_pre[i+1][hr]=-1;
u_int page=get_page(vaddr);
u_int vpage=get_vpage(vaddr);
literal_pool(256);
- //if(!(is32[i]&(~unneeded_reg_upper[i])&~(1LL<<CCREG)))
-#ifndef FORCE32
- if(!requires_32bit[i])
-#else
- if(1)
-#endif
{
assem_debug("%8x (%d) <- %8x\n",instr_addr[i],i,start+i*4);
assem_debug("jump_in: %x\n",start+i*4);
ll_add(jump_dirty+vpage,vaddr,(void *)out);
int entry_point=do_dirty_stub(i);
- ll_add(jump_in+page,vaddr,(void *)entry_point);
+ ll_add_flags(jump_in+page,vaddr,state_rflags,(void *)entry_point);
// If there was an existing entry in the hash table,
// replace it with the new address.
// Don't add new entries. We'll insert the
ht_bin[3]=entry_point;
}
}
- else
- {
- u_int r=requires_32bit[i]|!!(requires_32bit[i]>>32);
- assem_debug("%8x (%d) <- %8x\n",instr_addr[i],i,start+i*4);
- assem_debug("jump_in: %x (restricted - %x)\n",start+i*4,r);
- //int entry_point=(int)out;
- ////assem_debug("entry_point: %x\n",entry_point);
- //load_regs_entry(i);
- //if(entry_point==(int)out)
- // entry_point=instr_addr[i];
- //else
- // emit_jmp(instr_addr[i]);
- //ll_add_32(jump_in+page,vaddr,r,(void *)entry_point);
- ll_add_32(jump_dirty+vpage,vaddr,r,(void *)out);
- int entry_point=do_dirty_stub(i);
- ll_add_32(jump_in+page,vaddr,r,(void *)entry_point);
- }
}
}
}