#define OTHER 23 // Other
#define SPAN 24 // Branch/delay slot spans 2 pages
#define NI 25 // Not implemented
+#define HLECALL 26// PCSX fake opcodes for HLE
/* stubs */
#define CC_STUB 1
void fp_exception();
void fp_exception_ds();
void jump_syscall();
+void jump_syscall_hle();
void jump_eret();
+void jump_hlecall();
+void new_dyna_leave();
// TLB
void TLBWI_new();
void *get_addr_32(u_int vaddr,u_int flags)
{
+#ifdef FORCE32
+ return get_addr(vaddr);
+#endif
//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];
j++;
break;
}
- if(itype[i+j]==SYSCALL||((source[i+j]&0xfc00003f)==0x0d))
+ if(itype[i+j]==SYSCALL||itype[i+j]==HLECALL||((source[i+j]&0xfc00003f)==0x0d))
{
break;
}
// Add virtual address mapping for 32-bit compiled block
void ll_add_32(struct ll_entry **head,int vaddr,u_int reg32,void *addr)
{
- struct ll_entry *new_entry;
- new_entry=malloc(sizeof(struct ll_entry));
- assert(new_entry!=NULL);
- new_entry->vaddr=vaddr;
- new_entry->reg32=reg32;
- new_entry->addr=addr;
- new_entry->next=*head;
- *head=new_entry;
+ ll_add(head,vaddr,addr);
+#ifndef FORCE32
+ (*head)->reg32=reg32;
+#endif
}
// Check if an address is already compiled
if((((end-1-(u_int)rdram)>>12)&2047)>last) last=((end-1-(u_int)rdram)>>12)&2047;
}
}
+#ifndef DISABLE_TLB
if(page<2048&&(signed int)start>=(signed int)0xC0000000&&(signed int)end>=(signed int)0xC0000000) {
if(((start+memory_map[start>>12]-(u_int)rdram)>>12)<=page&&((end-1+memory_map[(end-1)>>12]-(u_int)rdram)>>12)>=page) {
if((((start+memory_map[start>>12]-(u_int)rdram)>>12)&2047)<first) first=((start+memory_map[start>>12]-(u_int)rdram)>>12)&2047;
if((((end-1+memory_map[(end-1)>>12]-(u_int)rdram)>>12)&2047)>last) last=((end-1+memory_map[(end-1)>>12]-(u_int)rdram)>>12)&2047;
}
}
+#endif
}
head=head->next;
}
case RJUMP:
case FJUMP:
case SYSCALL:
+ case HLECALL:
case SPAN:
assem_debug("jump in the delay slot. this shouldn't happen.\n");//exit(1);
printf("Disabled speculative precompilation\n");
if((dirty>>hr)&1) {
if(regmap[hr]<64) {
emit_storereg(r,hr);
+#ifndef FORCE32
if((is32>>regmap[hr])&1) {
emit_sarimm(hr,31,hr);
emit_storereg(r|64,hr);
}
+#endif
}else{
emit_storereg(r|64,hr);
}
//gen_tlb_addr_r(tl,map);
//emit_movsbl_indexed((int)rdram-0x80000000,tl,tl);
int x=0;
+#ifdef BIG_ENDIAN_MIPS
if(!c) emit_xorimm(addr,3,tl);
else x=((constmap[i][s]+offset)^3)-(constmap[i][s]+offset);
+#else
+ if(c) x=(constmap[i][s]+offset)-(constmap[i][s]+offset);
+ else if (tl!=addr) emit_mov(addr,tl);
+#endif
emit_movsbl_indexed_tlb(x,tl,map,tl);
}
if(jaddr)
#endif
{
int x=0;
+#ifdef BIG_ENDIAN_MIPS
if(!c) emit_xorimm(addr,2,tl);
else x=((constmap[i][s]+offset)^2)-(constmap[i][s]+offset);
+#else
+ if(c) x=(constmap[i][s]+offset)-(constmap[i][s]+offset);
+ else if (tl!=addr) emit_mov(addr,tl);
+#endif
//#ifdef
//emit_movswl_indexed_tlb(x,tl,map,tl);
//else
//gen_tlb_addr_r(tl,map);
//emit_movzbl_indexed((int)rdram-0x80000000,tl,tl);
int x=0;
+#ifdef BIG_ENDIAN_MIPS
if(!c) emit_xorimm(addr,3,tl);
else x=((constmap[i][s]+offset)^3)-(constmap[i][s]+offset);
+#else
+ if(c) x=(constmap[i][s]+offset)-(constmap[i][s]+offset);
+ else if (tl!=addr) emit_mov(addr,tl);
+#endif
emit_movzbl_indexed_tlb(x,tl,map,tl);
}
if(jaddr)
#endif
{
int x=0;
+#ifdef BIG_ENDIAN_MIPS
if(!c) emit_xorimm(addr,2,tl);
else x=((constmap[i][s]+offset)^2)-(constmap[i][s]+offset);
+#else
+ if(c) x=(constmap[i][s]+offset)-(constmap[i][s]+offset);
+ else if (tl!=addr) emit_mov(addr,tl);
+#endif
//#ifdef
//emit_movzwl_indexed_tlb(x,tl,map,tl);
//#else
int addr,temp;
int offset;
int jaddr=0,jaddr2,type;
- int memtarget,c=0;
+ int memtarget=0,c=0;
int agr=AGEN1+(i&1);
u_int hr,reglist=0;
th=get_reg(i_regs->regmap,rs2[i]|64);
if (opcode[i]==0x28) { // SB
if(!c||memtarget) {
int x=0;
+#ifdef BIG_ENDIAN_MIPS
if(!c) emit_xorimm(addr,3,temp);
else x=((constmap[i][s]+offset)^3)-(constmap[i][s]+offset);
+#else
+ if(c) x=(constmap[i][s]+offset)-(constmap[i][s]+offset);
+ else if (addr!=temp) emit_mov(addr,temp);
+#endif
//gen_tlb_addr_w(temp,map);
//emit_writebyte_indexed(tl,(int)rdram-0x80000000,temp);
emit_writebyte_indexed_tlb(tl,x,temp,map,temp);
if (opcode[i]==0x29) { // SH
if(!c||memtarget) {
int x=0;
+#ifdef BIG_ENDIAN_MIPS
if(!c) emit_xorimm(addr,2,temp);
else x=((constmap[i][s]+offset)^2)-(constmap[i][s]+offset);
+#else
+ if(c) x=(constmap[i][s]+offset)-(constmap[i][s]+offset);
+ else if (addr!=temp) emit_mov(addr,temp);
+#endif
//#ifdef
//emit_writehword_indexed_tlb(tl,x,temp,map,temp);
//#else
}
type=STORED_STUB;
}
+ if(!using_tlb&&(!c||memtarget))
+ // addr could be a temp, make sure it survives STORE*_STUB
+ reglist|=1<<addr;
if(jaddr) {
add_stub(type,jaddr,(int)out,i,addr,(int)i_regs,ccadj[i],reglist);
} else if(!memtarget) {
if(!rs2[i]) temp2=th=tl;
}
+#ifndef BIG_ENDIAN_MIPS
+ emit_xorimm(temp,3,temp);
+#endif
emit_testimm(temp,2);
case2=(int)out;
emit_jne(0);
assert(!is_delayslot);
emit_movimm(start+i*4,EAX); // Get PC
emit_addimm(HOST_CCREG,CLOCK_DIVIDER*ccadj[i],HOST_CCREG); // CHECK: is this right? There should probably be an extra cycle...
- emit_jmp((int)jump_syscall);
+ emit_jmp((int)jump_syscall_hle); // XXX
+}
+
+void hlecall_assemble(int i,struct regstat *i_regs)
+{
+ signed char ccreg=get_reg(i_regs->regmap,CCREG);
+ assert(ccreg==HOST_CCREG);
+ assert(!is_delayslot);
+ emit_movimm(start+i*4+4,0); // Get PC
+ emit_movimm(source[i],1); // opcode
+ emit_addimm(HOST_CCREG,CLOCK_DIVIDER*ccadj[i],HOST_CCREG); // XXX
+ emit_jmp((int)jump_hlecall); // XXX
}
void ds_assemble(int i,struct regstat *i_regs)
case MOV:
mov_assemble(i,i_regs);break;
case SYSCALL:
+ case HLECALL:
case SPAN:
case UJUMP:
case RJUMP:
if((i_dirty>>hr)&1) {
if(i_regmap[hr]<64) {
emit_storereg(i_regmap[hr],hr);
+#ifndef FORCE32
if( ((i_is32>>i_regmap[hr])&1) ) {
#ifdef DESTRUCTIVE_WRITEBACK
emit_sarimm(hr,31,hr);
emit_storereg(i_regmap[hr]|64,HOST_TEMPREG);
#endif
}
+#endif
}else{
if( !((i_is32>>(i_regmap[hr]&63))&1) ) {
emit_storereg(i_regmap[hr],hr);
if((i_dirty>>hr)&1) {
if(i_regmap[hr]<64) {
emit_storereg(i_regmap[hr],hr);
+#ifndef FORCE32
if( ((i_is32>>i_regmap[hr])&1) ) {
#ifdef DESTRUCTIVE_WRITEBACK
emit_sarimm(hr,31,hr);
emit_storereg(i_regmap[hr]|64,HOST_TEMPREG);
#endif
}
+#endif
}else{
if( !((i_is32>>(i_regmap[hr]&63))&1) ) {
emit_storereg(i_regmap[hr],hr);
case MOV:
mov_assemble(t,®s[t]);break;
case SYSCALL:
+ case HLECALL:
case SPAN:
case UJUMP:
case RJUMP:
case MOV:
mov_assemble(0,®s[0]);break;
case SYSCALL:
+ case HLECALL:
case SPAN:
case UJUMP:
case RJUMP:
}
}
}
- else if(itype[i]==SYSCALL)
+ else if(itype[i]==SYSCALL||itype[i]==HLECALL)
{
// SYSCALL instruction (software interrupt)
u=1;
// Save it
unneeded_reg[i]=u;
unneeded_reg_upper[i]=uu;
+#ifdef FORCE32
+ unneeded_reg_upper[i]=-1LL;
+#endif
/*
printf("ur (%d,%d) %x: ",istart,iend,start+i*4);
printf("U:");
case FCOMP:
break;
case SYSCALL:
+ case HLECALL:
break;
default:
break;
if((regs[i].was32>>dep2[i+1])&1) r32|=1LL<<dep2[i+1];
}
}
- else if(itype[i]==SYSCALL)
+ else if(itype[i]==SYSCALL||itype[i]==HLECALL)
{
// SYSCALL instruction (software interrupt)
r32=0;
}
}
}
- else if(itype[i]==SYSCALL)
+ else if(itype[i]==SYSCALL||itype[i]==HLECALL)
{
// SYSCALL instruction (software interrupt)
will_dirty_i=0;
memory_map[n]=((u_int)rdram-0x80000000)>>2;
for(n=526336;n<1048576;n++) // 0x80800000 .. 0xFFFFFFFF
memory_map[n]=-1;
+#ifdef MUPEN64
for(n=0;n<0x8000;n++) { // 0 .. 0x7FFFFFFF
writemem[n] = write_nomem_new;
writememb[n] = write_nomemb_new;
writememh[n] = write_nomemh_new;
+#ifndef FORCE32
writememd[n] = write_nomemd_new;
+#endif
readmem[n] = read_nomem_new;
readmemb[n] = read_nomemb_new;
readmemh[n] = read_nomemh_new;
+#ifndef FORCE32
readmemd[n] = read_nomemd_new;
+#endif
}
for(n=0x8000;n<0x8080;n++) { // 0x80000000 .. 0x807FFFFF
writemem[n] = write_rdram_new;
writememb[n] = write_rdramb_new;
writememh[n] = write_rdramh_new;
+#ifndef FORCE32
writememd[n] = write_rdramd_new;
+#endif
}
for(n=0xC000;n<0x10000;n++) { // 0xC0000000 .. 0xFFFFFFFF
writemem[n] = write_nomem_new;
writememb[n] = write_nomemb_new;
writememh[n] = write_nomemh_new;
+#ifndef FORCE32
writememd[n] = write_nomemd_new;
+#endif
readmem[n] = read_nomem_new;
readmemb[n] = read_nomemb_new;
readmemh[n] = read_nomemh_new;
+#ifndef FORCE32
readmemd[n] = read_nomemd_new;
+#endif
}
+#endif
tlb_hacks();
arch_init();
}
//rlist();
start = (u_int)addr&~3;
//assert(((u_int)addr&1)==0);
+#ifdef PCSX
+ if (Config.HLE && start == 0x80001000) {
+ // XXX: is this enough? Maybe check hleSoftCall?
+ u_int page=get_page(start);
+ ll_add(jump_in+page,start,out);
+ invalid_code[start>>12]=0;
+ emit_movimm(start,0);
+ emit_writeword(0,(int)&pcaddr);
+ emit_jmp((int)new_dyna_leave); // enough??
+ return 0;
+ }
+ else if ((u_int)addr < 0x00200000) {
+ // used for BIOS calls mostly?
+ source = (u_int *)((u_int)rdram+start-0);
+ pagelimit = 0x00200000;
+ }
+ else
+#endif
#ifdef MUPEN64
if ((int)addr >= 0xa4000000 && (int)addr < 0xa4001000) {
source = (u_int *)((u_int)SP_DMEM+start-0xa4000000);
source = (u_int *)((u_int)rdram+start-0x80000000);
pagelimit = 0x80800000;
}
+#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])
}
//printf("source= %x\n",(int)source);
}
+#endif
else {
printf("Compile at bogus memory address: %x \n", (int)addr);
exit(1);
case 0x37: strcpy(insn[i],"LD"); type=LOAD; break;
case 0x38: strcpy(insn[i],"SC"); type=NI; break;
case 0x39: strcpy(insn[i],"SWC1"); type=C1LS; break;
+#ifdef PCSX
+ case 0x3B: strcpy(insn[i],"HLECALL"); type=HLECALL; break;
+#endif
case 0x3C: strcpy(insn[i],"SCD"); type=NI; break;
case 0x3D: strcpy(insn[i],"SDC1"); type=C1LS; break;
case 0x3F: strcpy(insn[i],"SD"); type=STORE; break;
- default: strcpy(insn[i],"???"); type=NI; break;
+ default: strcpy(insn[i],"???"); type=NI;
+ printf("NI %08x @%08x\n", source[i], addr + i*4);
+ break;
}
itype[i]=type;
opcode2[i]=op2;
rt2[i]=0;
break;
case SYSCALL:
+ case HLECALL:
rs1[i]=CCREG;
rs2[i]=0;
rt1[i]=0;
if(i>MAXBLOCK/2) done=1;
}
if(i>0&&itype[i-1]==SYSCALL&&stop_after_jal) done=1;
+ if(itype[i-1]==HLECALL) done=1;
assert(i<MAXBLOCK-1);
if(start+i*4==pagelimit-4) done=1;
assert(start+i*4<pagelimit);
current.is32=temp_is32;
}
}
+#ifdef FORCE32
+ memset(p32, 0xff, sizeof(p32));
+ current.is32=-1LL;
+#endif
+
memcpy(regmap_pre[i],current.regmap,sizeof(current.regmap));
regs[i].wasconst=current.isconst;
regs[i].was32=current.is32;
fcomp_alloc(¤t,i);
break;
case SYSCALL:
+ case HLECALL:
syscall_alloc(¤t,i);
break;
case SPAN:
// Count cycles in between branches
ccadj[i]=cc;
- if(i>0&&(itype[i-1]==RJUMP||itype[i-1]==UJUMP||itype[i-1]==CJUMP||itype[i-1]==SJUMP||itype[i-1]==FJUMP||itype[i]==SYSCALL))
+ if(i>0&&(itype[i-1]==RJUMP||itype[i-1]==UJUMP||itype[i-1]==CJUMP||itype[i-1]==SJUMP||itype[i-1]==FJUMP||itype[i]==SYSCALL||itype[i]==HLECALL))
{
cc=0;
}
}
}
}
- else if(itype[i]==SYSCALL)
+ else if(itype[i]==SYSCALL||itype[i]==HLECALL)
{
// SYSCALL instruction (software interrupt)
nr=0;
if((regs[i].was32>>dep2[i+1])&1) r32|=1LL<<dep2[i+1];
}
}
- else if(itype[i]==SYSCALL)
+ else if(itype[i]==SYSCALL||itype[i]==HLECALL)
{
// SYSCALL instruction (software interrupt)
r32=0;
else printf(" r%d",r);
}
}
+#ifndef FORCE32
printf(" UU:");
for(r=1;r<=CCREG;r++) {
if(((unneeded_reg_upper[i]&~unneeded_reg[i])>>r)&1) {
else printf(" r%d",r);
}
}
+#endif
printf("\n");
#if defined(__i386__) || defined(__x86_64__)
printf("pre: eax=%d ecx=%d edx=%d ebx=%d ebp=%d esi=%d edi=%d\n",regmap_pre[i][0],regmap_pre[i][1],regmap_pre[i][2],regmap_pre[i][3],regmap_pre[i][5],regmap_pre[i][6],regmap_pre[i][7]);
#endif
printf("\n");
}
+#ifndef FORCE32
printf(" 32:");
for(r=0;r<=CCREG;r++) {
if((regs[i].is32>>r)&1) {
}
}
printf("\n");
+#endif
/*printf(" p32:");
for(r=0;r<=CCREG;r++) {
if((p32[i]>>r)&1) {
if((branch_regs[i].dirty>>10)&1) printf("r10 ");
if((branch_regs[i].dirty>>12)&1) printf("r12 ");
#endif
+#ifndef FORCE32
printf(" 32:");
for(r=0;r<=CCREG;r++) {
if((branch_regs[i].is32>>r)&1) {
}
}
printf("\n");
+#endif
}
}
mov_assemble(i,®s[i]);break;
case SYSCALL:
syscall_assemble(i,®s[i]);break;
+ case HLECALL:
+ hlecall_assemble(i,®s[i]);break;
case UJUMP:
ujump_assemble(i,®s[i]);ds=1;break;
case RJUMP:
// Trap writes to any of the pages we compiled
for(i=start>>12;i<=(start+slen*4)>>12;i++) {
invalid_code[i]=0;
+#ifndef DISABLE_TLB
memory_map[i]|=0x40000000;
if((signed int)start>=(signed int)0xC0000000) {
assert(using_tlb);
memory_map[j]|=0x40000000;
//printf("write protect physical page: %x (virtual %x)\n",j<<12,start);
}
+#endif
}
/* Pass 10 - Free memory by expiring oldest blocks */