}
return 0;
}
+void genimm_checked(u_int imm,u_int *encoded)
+{
+ u_int ret=genimm(imm,encoded);
+ assert(ret);
+}
u_int genjmp(u_int addr)
{
int offset=addr-(int)out-8;
{
u_int armval;
assem_debug("tst %s,$%d\n",regname[rs],imm);
- assert(genimm(imm,&armval));
+ genimm_checked(imm,&armval);
output_w32(0xe3100000|rd_rn_rm(0,rs,0)|armval);
}
{
u_int armval;
assem_debug("tsteq %s,$%d\n",regname[rs],imm);
- assert(genimm(imm,&armval));
+ genimm_checked(imm,&armval);
output_w32(0x03100000|rd_rn_rm(0,rs,0)|armval);
}
output_w32(0xe1900000|rd_rn_rm(rt,rs1,rs2));
}
+void emit_orrshr_imm(u_int rs,u_int imm,u_int rt)
+{
+ assert(rs<16);
+ assert(rt<16);
+ assert(imm<32);
+ assem_debug("orr %s,%s,%s,lsr #%d\n",regname[rt],regname[rt],regname[rs],imm);
+ output_w32(0xe1800020|rd_rn_rm(rt,rt,rs)|(imm<<7));
+}
+
void emit_xor(u_int rs1,u_int rs2,u_int rt)
{
assem_debug("eor %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
void emit_adcimm(u_int rs,int imm,u_int rt)
{
u_int armval;
- assert(genimm(imm,&armval));
+ genimm_checked(imm,&armval);
assem_debug("adc %s,%s,#%d\n",regname[rt],regname[rs],imm);
output_w32(0xe2a00000|rd_rn_rm(rt,rs,0)|armval);
}
/*void emit_sbcimm(int imm,u_int rt)
{
u_int armval;
- assert(genimm(imm,&armval));
+ genimm_checked(imm,&armval);
assem_debug("sbc %s,%s,#%d\n",regname[rt],regname[rt],imm);
output_w32(0xe2c00000|rd_rn_rm(rt,rt,0)|armval);
}*/
{
assert(0);
u_int armval;
- assert(genimm(imm,&armval));
+ genimm_checked(imm,&armval);
assem_debug("rsc %s,%s,#%d\n",regname[rt],regname[rs],imm);
output_w32(0xe2e00000|rd_rn_rm(rt,rs,0)|armval);
}
{
assem_debug("movne %s,#%d\n",regname[rt],imm);
u_int armval;
- assert(genimm(imm,&armval));
+ genimm_checked(imm,&armval);
output_w32(0x13a00000|rd_rn_rm(rt,0,0)|armval);
}
void emit_cmovl_imm(int imm,int rt)
{
assem_debug("movlt %s,#%d\n",regname[rt],imm);
u_int armval;
- assert(genimm(imm,&armval));
+ genimm_checked(imm,&armval);
output_w32(0xb3a00000|rd_rn_rm(rt,0,0)|armval);
}
void emit_cmovb_imm(int imm,int rt)
{
assem_debug("movcc %s,#%d\n",regname[rt],imm);
u_int armval;
- assert(genimm(imm,&armval));
+ genimm_checked(imm,&armval);
output_w32(0x33a00000|rd_rn_rm(rt,0,0)|armval);
}
void emit_cmovs_imm(int imm,int rt)
{
assem_debug("movmi %s,#%d\n",regname[rt],imm);
u_int armval;
- assert(genimm(imm,&armval));
+ genimm_checked(imm,&armval);
output_w32(0x43a00000|rd_rn_rm(rt,0,0)|armval);
}
void emit_cmove_reg(int rs,int rt)
{
u_int offset = addr-(u_int)&dynarec_local;
assert(offset<4096);
- assem_debug("str %s,fp+%d\n",regname[rt],offset);
+ assem_debug("strb %s,fp+%d\n",regname[rt],offset);
output_w32(0xe5c00000|rd_rn_rm(rt,FP,0)|offset);
}
void emit_writeword_imm(int imm, int addr)
void emit_rsbimm(int rs, int imm, int rt)
{
u_int armval;
- assert(genimm(imm,&armval));
+ genimm_checked(imm,&armval);
assem_debug("rsb %s,%s,#%d\n",regname[rt],regname[rs],imm);
output_w32(0xe2600000|rd_rn_rm(rt,rs,0)|armval);
}
void emit_bicne_imm(int rs,int imm,int rt)
{
u_int armval;
- assert(genimm(imm,&armval));
+ genimm_checked(imm,&armval);
assem_debug("bicne %s,%s,#%d\n",regname[rt],regname[rs],imm);
output_w32(0x13c00000|rd_rn_rm(rt,rs,0)|armval);
}
void emit_biccs_imm(int rs,int imm,int rt)
{
u_int armval;
- assert(genimm(imm,&armval));
+ genimm_checked(imm,&armval);
assem_debug("biccs %s,%s,#%d\n",regname[rt],regname[rs],imm);
output_w32(0x23c00000|rd_rn_rm(rt,rs,0)|armval);
}
void emit_bicvc_imm(int rs,int imm,int rt)
{
u_int armval;
- assert(genimm(imm,&armval));
+ genimm_checked(imm,&armval);
assem_debug("bicvc %s,%s,#%d\n",regname[rt],regname[rs],imm);
output_w32(0x73c00000|rd_rn_rm(rt,rs,0)|armval);
}
void emit_bichi_imm(int rs,int imm,int rt)
{
u_int armval;
- assert(genimm(imm,&armval));
+ genimm_checked(imm,&armval);
assem_debug("bichi %s,%s,#%d\n",regname[rt],regname[rs],imm);
output_w32(0x83c00000|rd_rn_rm(rt,rs,0)|armval);
}
void emit_orrvs_imm(int rs,int imm,int rt)
{
u_int armval;
- assert(genimm(imm,&armval));
+ genimm_checked(imm,&armval);
assem_debug("orrvs %s,%s,#%d\n",regname[rt],regname[rs],imm);
output_w32(0x63800000|rd_rn_rm(rt,rs,0)|armval);
}
void emit_orrne_imm(int rs,int imm,int rt)
{
u_int armval;
- assert(genimm(imm,&armval));
+ genimm_checked(imm,&armval);
assem_debug("orrne %s,%s,#%d\n",regname[rt],regname[rs],imm);
output_w32(0x13800000|rd_rn_rm(rt,rs,0)|armval);
}
void emit_andne_imm(int rs,int imm,int rt)
{
u_int armval;
- assert(genimm(imm,&armval));
+ genimm_checked(imm,&armval);
assem_debug("andne %s,%s,#%d\n",regname[rt],regname[rs],imm);
output_w32(0x12000000|rd_rn_rm(rt,rs,0)|armval);
}
rth=get_reg(i_regmap,rt1[i]|64);
rt=get_reg(i_regmap,rt1[i]);
}
-#ifdef PCSX
- if(rt<0)
- // assume forced dummy read
- rt=get_reg(i_regmap,-1);
-#endif
assert(rs>=0);
- assert(rt>=0);
if(addr<0) addr=rt;
+ if(addr<0)
+ // assume dummy read, no alloced reg
+ addr=get_reg(i_regmap,-1);
assert(addr>=0);
int ftable=0;
if(type==LOADB_STUB||type==LOADBU_STUB)
//if((cc=get_reg(regmap,CCREG))>=0) {
// emit_loadreg(CCREG,cc);
//}
- if(type==LOADB_STUB)
- emit_movsbl((int)&readmem_dword,rt);
- if(type==LOADBU_STUB)
- emit_movzbl((int)&readmem_dword,rt);
- if(type==LOADH_STUB)
- emit_movswl((int)&readmem_dword,rt);
- if(type==LOADHU_STUB)
- emit_movzwl((int)&readmem_dword,rt);
- if(type==LOADW_STUB)
- emit_readword((int)&readmem_dword,rt);
- if(type==LOADD_STUB) {
- emit_readword((int)&readmem_dword,rt);
- if(rth>=0) emit_readword(((int)&readmem_dword)+4,rth);
+ if(itype[i]==C1LS||itype[i]==C2LS||(rt>=0&&rt1[i]!=0)) {
+ assert(rt>=0);
+ if(type==LOADB_STUB)
+ emit_movsbl((int)&readmem_dword,rt);
+ if(type==LOADBU_STUB)
+ emit_movzbl((int)&readmem_dword,rt);
+ if(type==LOADH_STUB)
+ emit_movswl((int)&readmem_dword,rt);
+ if(type==LOADHU_STUB)
+ emit_movzwl((int)&readmem_dword,rt);
+ if(type==LOADW_STUB)
+ emit_readword((int)&readmem_dword,rt);
+ if(type==LOADD_STUB) {
+ emit_readword((int)&readmem_dword,rt);
+ if(rth>=0) emit_readword(((int)&readmem_dword)+4,rth);
+ }
}
emit_jmp(stubs[n][2]); // return address
}
#endif
emit_xorimm(temp,24,temp);
emit_movimm(-1,HOST_TEMPREG);
- if (opcode[i]==0x2e) { // SWR
+ if (opcode[i]==0x2a) { // SWL
emit_bic_lsr(temp2,HOST_TEMPREG,temp,temp2);
emit_orrshr(rt,temp,temp2);
}else{
signed char t=get_reg(i_regs->regmap,rt1[i]);
char copr=(source[i]>>11)&0x1f;
//assert(t>=0); // Why does this happen? OOT is weird
- if(t>=0) {
+ if(t>=0&&rt1[i]!=0) {
#ifdef MUPEN64
emit_addimm(FP,(int)&fake_pc-(int)&dynarec_local,0);
emit_movimm((source[i]>>11)&0x1f,1);
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
+#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_writebyte(1,(int)&(fake_pc.f.r.nrd));
-#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);
// The interrupt must be taken immediately, because a subsequent
// instruction might disable interrupts again.
if(copr==12||copr==13) {
+#ifdef PCSX
+ if (is_delayslot) {
+ // burn cycles to cause cc_interrupt, which will
+ // reschedule next_interupt. Relies on CCREG from above.
+ assem_debug("MTC0 DS %d\n", copr);
+ emit_writeword(HOST_CCREG,(int)&last_count);
+ emit_movimm(0,HOST_CCREG);
+ emit_storereg(CCREG,HOST_CCREG);
+ emit_movimm(copr,0);
+ emit_call((int)pcsx_mtc0_ds);
+ return;
+ }
+#endif
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
+#ifdef PCSX
+ emit_movimm(copr,0);
+ emit_call((int)pcsx_mtc0);
+#else
emit_call((int)MTC0);
+#endif
if(copr==9||copr==11||copr==12||copr==13) {
emit_readword((int)&Count,HOST_CCREG);
emit_readword((int)&next_interupt,ECX);
if((source[i]&0x3f)==0x08) // TLBP
emit_call((int)TLBP);
#endif
+#ifdef PCSX
+ if((source[i]&0x3f)==0x10) // RFE
+ {
+ emit_readword((int)&Status,0);
+ emit_andimm(0,0x3c,1);
+ emit_andimm(0,~0xf,0);
+ emit_orrshr_imm(1,2,0);
+ emit_writeword(0,(int)&Status);
+ }
+#else
if((source[i]&0x3f)==0x18) // ERET
{
int count=ccadj[i];
emit_addimm(HOST_CCREG,CLOCK_DIVIDER*count,HOST_CCREG); // TODO: Should there be an extra cycle here?
emit_jmp((int)jump_eret);
}
+#endif
}
}
signed char temp=get_reg(i_regs->regmap,-1);
if (opcode2[i]==0) { // MFC2
signed char tl=get_reg(i_regs->regmap,rt1[i]);
- if(tl>=0)
+ if(tl>=0&&rt1[i]!=0)
cop2_get_dreg(copr,tl,temp);
}
else if (opcode2[i]==4) { // MTC2
else if (opcode2[i]==2) // CFC2
{
signed char tl=get_reg(i_regs->regmap,rt1[i]);
- if(tl>=0)
+ if(tl>=0&&rt1[i]!=0)
emit_readword((int)®_cop2c[copr],tl);
}
else if (opcode2[i]==6) // CTC2