extern int pending_exception;
extern int branch_target;
extern uint64_t readmem_dword;
+#ifdef MUPEN64
extern precomp_instr fake_pc;
+#endif
extern void *dynarec_local;
extern u_int memory_map[1048576];
extern u_int mini_ht[32][2];
#endif
if((*ptr&0xFF000000)!=0xeb000000) ptr++;
assert((*ptr&0xFF000000)==0xeb000000); // bl instruction
- u_int verifier=(int)ptr+((*ptr<<8)>>6)+8; // get target of bl
+ u_int verifier=(int)ptr+((signed int)(*ptr<<8)>>6)+8; // get target of bl
if(verifier==(u_int)verify_code_vm||verifier==(u_int)verify_code_ds) {
unsigned int page=source>>12;
unsigned int map_value=memory_map[page];
#endif
if((*ptr&0xFF000000)!=0xeb000000) ptr++;
assert((*ptr&0xFF000000)==0xeb000000); // bl instruction
- u_int verifier=(int)ptr+((*ptr<<8)>>6)+8; // get target of bl
+ u_int verifier=(int)ptr+((signed int)(*ptr<<8)>>6)+8; // get target of bl
if(verifier==(u_int)verify_code_vm||verifier==(u_int)verify_code_ds) {
if(memory_map[source>>12]>=0x80000000) source = 0;
else source = source+(memory_map[source>>12]<<2);
u_int genjmp(u_int addr)
{
int offset=addr-(int)out-8;
- if(offset<-33554432||offset>=33554432) return 0;
+ if(offset<-33554432||offset>=33554432) {
+ if (addr>2) {
+ printf("genjmp: out of range: %08x\n", offset);
+ exit(1);
+ }
+ return 0;
+ }
return ((u_int)offset>>2)&0xffffff;
}
void emit_loadreg(int r, int hr)
{
+#ifdef FORCE32
+ if(r&64) {
+ printf("64bit load in 32bit mode!\n");
+ exit(1);
+ }
+#endif
if((r&63)==0)
emit_zeroreg(hr);
else {
- int addr=((int)reg)+((r&63)<<3)+((r&64)>>4);
+ int addr=((int)reg)+((r&63)<<REG_SHIFT)+((r&64)>>4);
if((r&63)==HIREG) addr=(int)&hi+((r&64)>>4);
if((r&63)==LOREG) addr=(int)&lo+((r&64)>>4);
if(r==CCREG) addr=(int)&cycle_count;
}
void emit_storereg(int r, int hr)
{
- int addr=((int)reg)+((r&63)<<3)+((r&64)>>4);
+#ifdef FORCE32
+ if(r&64) {
+ printf("64bit store in 32bit mode!\n");
+ exit(1);
+ }
+#endif
+ int addr=((int)reg)+((r&63)<<REG_SHIFT)+((r&64)>>4);
if((r&63)==HIREG) addr=(int)&hi+((r&64)>>4);
if((r&63)==LOREG) addr=(int)&lo+((r&64)>>4);
if(r==CCREG) addr=(int)&cycle_count;
emit_movimm(value,HOST_TEMPREG);
}
emit_storereg(i_regmap[hr],HOST_TEMPREG);
+#ifndef FORCE32
if((i_is32>>i_regmap[hr])&1) {
if(value!=-1&&value!=0) emit_sarimm(HOST_TEMPREG,31,HOST_TEMPREG);
emit_storereg(i_regmap[hr]|64,HOST_TEMPREG);
}
+#endif
}
}
}
assert((ptr[3]&0x0e)==0xa);
emit_loadlp(target,0);
emit_loadlp(addr,1);
- assert(addr>=0x7000000&&addr<0x7FFFFFF);
+ assert(addr>=BASE_ADDR&&addr<(BASE_ADDR+(1<<TARGET_SIZE_2)));
//assert((target>=0x80000000&&target<0x80800000)||(target>0xA4000000&&target<0xA4001000));
//DEBUG >
#ifdef DEBUG_CYCLE_COUNT
ftable=(int)readmemh;
if(type==LOADW_STUB)
ftable=(int)readmem;
+#ifndef FORCE32
if(type==LOADD_STUB)
ftable=(int)readmemd;
+#endif
+ assert(ftable!=0);
emit_writeword(rs,(int)&address);
//emit_pusha();
save_regs(reglist);
ftable=(int)readmemh;
if(type==LOADW_STUB)
ftable=(int)readmem;
+#ifndef FORCE32
if(type==LOADD_STUB)
ftable=(int)readmemd;
+#endif
+ assert(ftable!=0);
emit_writeword(rs,(int)&address);
//emit_pusha();
save_regs(reglist);
ftable=(int)writememh;
if(type==STOREW_STUB)
ftable=(int)writemem;
+#ifndef FORCE32
if(type==STORED_STUB)
ftable=(int)writememd;
+#endif
+ assert(ftable!=0);
emit_writeword(rs,(int)&address);
//emit_shrimm(rs,16,rs);
//emit_movmem_indexedx4(ftable,rs,rs);
if(type==STOREW_STUB)
emit_writeword(rt,(int)&word);
if(type==STORED_STUB) {
+#ifndef FORCE32
emit_writeword(rt,(int)&dword);
emit_writeword(r?rth:rt,(int)&dword+4);
+#else
+ printf("STORED_STUB\n");
+#endif
}
//emit_pusha();
save_regs(reglist);
ftable=(int)writememh;
if(type==STOREW_STUB)
ftable=(int)writemem;
+#ifndef FORCE32
if(type==STORED_STUB)
ftable=(int)writememd;
+#endif
+ assert(ftable!=0);
emit_writeword(rs,(int)&address);
//emit_shrimm(rs,16,rs);
//emit_movmem_indexedx4(ftable,rs,rs);
if(type==STOREW_STUB)
emit_writeword(rt,(int)&word);
if(type==STORED_STUB) {
+#ifndef FORCE32
emit_writeword(rt,(int)&dword);
emit_writeword(target?rth:rt,(int)&dword+4);
+#else
+ printf("STORED_STUB\n");
+#endif
}
//emit_pusha();
save_regs(reglist);
assem_debug("do_cop1stub %x\n",start+stubs[n][3]*4);
set_jump_target(stubs[n][1],(int)out);
int i=stubs[n][3];
- int rs=stubs[n][4];
+// int rs=stubs[n][4];
struct regstat *i_regs=(struct regstat *)stubs[n][5];
int ds=stubs[n][6];
if(!ds) {
else
inline_readstub(LOADW_STUB,i,(constmap[i][s]+offset)&0xFFFFFFFC,i_regs->regmap,FTEMP,ccadj[i],reglist);
emit_andimm(temp,24,temp);
- if (opcode[i]==0x26) emit_xorimm(temp,24,temp); // LWR
+#ifdef BIG_ENDIAN_MIPS
+ if (opcode[i]==0x26) // LWR
+#else
+ if (opcode[i]==0x22) // LWL
+#endif
+ emit_xorimm(temp,24,temp);
emit_movimm(-1,HOST_TEMPREG);
if (opcode[i]==0x26) {
emit_shr(temp2,temp,temp2);
//emit_storereg(rt1[i],tl); // DEBUG
}
if (opcode[i]==0x1A||opcode[i]==0x1B) { // LDL/LDR
+ // FIXME: little endian
int temp2h=get_reg(i_regs->regmap,FTEMP|64);
if(!c||memtarget) {
//if(th>=0) emit_readword_indexed((int)rdram-0x80000000,temp2,temp2h);
char copr=(source[i]>>11)&0x1f;
//assert(t>=0); // Why does this happen? OOT is weird
if(t>=0) {
+#ifdef MUPEN64
emit_addimm(FP,(int)&fake_pc-(int)&dynarec_local,0);
emit_movimm((source[i]>>11)&0x1f,1);
emit_writeword(0,(int)&PC);
}
emit_call((int)MFC0);
emit_readword((int)&readmem_dword,t);
+#else
+ emit_readword((int)®_cop0+copr*4,t);
+#endif
}
}
else if(opcode2[i]==4) // MTC0
assert(s>=0);
emit_writeword(s,(int)&readmem_dword);
wb_register(rs1[i],i_regs->regmap,i_regs->dirty,i_regs->is32);
+#ifdef MUPEN64 /// FIXME
emit_addimm(FP,(int)&fake_pc-(int)&dynarec_local,0);
emit_movimm((source[i]>>11)&0x1f,1);
emit_writeword(0,(int)&PC);
emit_writebyte(1,(int)&(fake_pc.f.r.nrd));
- if(copr==9||copr==11||copr==12) {
+#endif
+#ifdef PCSX
+ emit_movimm(source[i],0);
+ emit_writeword(0,(int)&psxRegs.code);
+#endif
+ if(copr==9||copr==11||copr==12||copr==13) {
emit_readword((int)&last_count,ECX);
emit_loadreg(CCREG,HOST_CCREG); // TODO: do proper reg alloc
emit_add(HOST_CCREG,ECX,HOST_CCREG);
// so needs a special case to handle a pending interrupt.
// The interrupt must be taken immediately, because a subsequent
// instruction might disable interrupts again.
- if(copr==12&&!is_delayslot) {
+ if(copr==12||copr==13) {
emit_movimm(start+i*4+4,0);
emit_movimm(0,1);
emit_writeword(0,(int)&pcaddr);
//else if(copr==12&&is_delayslot) emit_call((int)MTC0_R12);
//else
emit_call((int)MTC0);
- if(copr==9||copr==11||copr==12) {
+ if(copr==9||copr==11||copr==12||copr==13) {
emit_readword((int)&Count,HOST_CCREG);
emit_readword((int)&next_interupt,ECX);
emit_addimm(HOST_CCREG,-CLOCK_DIVIDER*ccadj[i],HOST_CCREG);
emit_writeword(ECX,(int)&last_count);
emit_storereg(CCREG,HOST_CCREG);
}
- if(copr==12) {
+ if(copr==12||copr==13) {
assert(!is_delayslot);
emit_readword((int)&pending_exception,14);
}
emit_loadreg(rs1[i],s);
if(get_reg(i_regs->regmap,rs1[i]|64)>=0)
emit_loadreg(rs1[i]|64,get_reg(i_regs->regmap,rs1[i]|64));
- if(copr==12) {
+ if(copr==12||copr==13) {
emit_test(14,14);
emit_jne((int)&do_interrupt);
}
else
{
assert(opcode2[i]==0x10);
+#ifndef DISABLE_TLB
if((source[i]&0x3f)==0x01) // TLBR
emit_call((int)TLBR);
if((source[i]&0x3f)==0x02) // TLBWI
}
if((source[i]&0x3f)==0x08) // TLBP
emit_call((int)TLBP);
+#endif
if((source[i]&0x3f)==0x18) // ERET
{
int count=ccadj[i];
}
}
+void cop1_unusable(int i, struct regstat *i_regs)
+{
+ // XXX: should just just do the exception instead
+ if(!cop1_usable) {
+ int jaddr=(int)out;
+ emit_jmp(0);
+ add_stub(FP_STUB,jaddr,(int)out,i,0,(int)i_regs,is_delayslot,0);
+ cop1_usable=1;
+ }
+}
+
void cop1_assemble(int i,struct regstat *i_regs)
{
+#ifndef DISABLE_COP1
// Check cop1 unusable
if(!cop1_usable) {
signed char rs=get_reg(i_regs->regmap,CSREG);
//emit_fldcw_indexed((int)&rounding_modes,temp);
}
}
+#else
+ cop1_unusable(i, i_regs);
+#endif
}
void fconv_assemble_arm(int i,struct regstat *i_regs)
{
+#ifndef DISABLE_COP1
signed char temp=get_reg(i_regs->regmap,-1);
assert(temp>=0);
// Check cop1 unusable
}
restore_regs(reglist);
+#else
+ cop1_unusable(i, i_regs);
+#endif
}
#define fconv_assemble fconv_assemble_arm
void fcomp_assemble(int i,struct regstat *i_regs)
{
+#ifndef DISABLE_COP1
signed char fs=get_reg(i_regs->regmap,FSREG);
signed char temp=get_reg(i_regs->regmap,-1);
assert(temp>=0);
}
restore_regs(reglist);
emit_loadreg(FSREG,fs);
+#else
+ cop1_unusable(i, i_regs);
+#endif
}
void float_assemble(int i,struct regstat *i_regs)
{
+#ifndef DISABLE_COP1
signed char temp=get_reg(i_regs->regmap,-1);
assert(temp>=0);
// Check cop1 unusable
}
restore_regs(reglist);
}
+#else
+ cop1_unusable(i, i_regs);
+#endif
}
void multdiv_assemble_arm(int i,struct regstat *i_regs)
// as a 64-bit value later.
void wb_sx(signed char pre[],signed char entry[],uint64_t dirty,uint64_t is32_pre,uint64_t is32,uint64_t u,uint64_t uu)
{
+#ifndef FORCE32
if(is32_pre==is32) return;
int hr,reg;
for(hr=0;hr<HOST_REGS;hr++) {
//}
}
}
+#endif
}
void wb_valid(signed char pre[],signed char entry[],u_int dirty_pre,u_int dirty,uint64_t is32_pre,uint64_t u,uint64_t uu)
// CPU-architecture-specific initialization
void arch_init() {
+#ifndef DISABLE_COP1
rounding_modes[0]=0x0<<22; // round
rounding_modes[1]=0x3<<22; // trunc
rounding_modes[2]=0x1<<22; // ceil
rounding_modes[3]=0x2<<22; // floor
+#endif
}