if((*ptr&0xFF000000)!=0xeb000000) ptr++;
if((*ptr&0xFF000000)!=0xeb000000) return 1; // bl instruction
if((int)ptr+((*ptr<<8)>>6)+8==(int)verify_code) return 0;
- if((int)ptr+((*ptr<<8)>>6)+8==(int)verify_code_vm) return 0;
if((int)ptr+((*ptr<<8)>>6)+8==(int)verify_code_ds) return 0;
return 1;
}
static u_int genjmp(u_int addr)
{
- int offset=addr-(int)out-8;
- if(offset<-33554432||offset>=33554432) {
- if (addr>2) {
- SysPrintf("genjmp: out of range: %08x\n", offset);
- exit(1);
- }
+ if (addr < 3) return 0; // a branch that will be patched later
+ int offset = addr-(int)out-8;
+ if (offset < -33554432 || offset >= 33554432) {
+ SysPrintf("genjmp: out of range: %08x\n", offset);
+ abort();
return 0;
}
return ((u_int)offset>>2)&0xffffff;
output_w32(0xe0800000|rd_rn_rm(rt,rs1,rs2));
}
-static void emit_adds(int rs1,int rs2,int rt)
-{
- assem_debug("adds %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
- output_w32(0xe0900000|rd_rn_rm(rt,rs1,rs2));
-}
-
static void emit_adcs(int rs1,int rs2,int rt)
{
assem_debug("adcs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
if((r&63)==0)
emit_zeroreg(hr);
else {
- 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;
- if(r==CSREG) addr=(int)&Status;
- if(r==INVCP) addr=(int)&invc_ptr;
+ int addr = (int)&psxRegs.GPR.r[r];
+ switch (r) {
+ //case HIREG: addr = &hi; break;
+ //case LOREG: addr = &lo; break;
+ case CCREG: addr = (int)&cycle_count; break;
+ case CSREG: addr = (int)&Status; break;
+ case INVCP: addr = (int)&invc_ptr; break;
+ default: assert(r < 34); break;
+ }
u_int offset = addr-(u_int)&dynarec_local;
assert(offset<4096);
assem_debug("ldr %s,fp+%d\n",regname[hr],offset);
assert(0);
return;
}
- 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;
+ int addr = (int)&psxRegs.GPR.r[r];
+ switch (r) {
+ //case HIREG: addr = &hi; break;
+ //case LOREG: addr = &lo; break;
+ case CCREG: addr = (int)&cycle_count; break;
+ default: assert(r < 34); break;
+ }
u_int offset = addr-(u_int)&dynarec_local;
assert(offset<4096);
assem_debug("str %s,fp+%d\n",regname[hr],offset);
output_w32(0xe2800000|rd_rn_rm(r,r,0));
}
-static void emit_adcimm(u_int rs,int imm,u_int rt)
-{
- u_int 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);
-}
-
-static void emit_addimm64_32(int rsh,int rsl,int imm,int rth,int rtl)
-{
- // TODO: if(genimm(imm,&armval)) ...
- // else
- emit_movimm(imm,HOST_TEMPREG);
- emit_adds(HOST_TEMPREG,rsl,rtl);
- emit_adcimm(rsh,0,rth);
-}
-
static void emit_andimm(int rs,int imm,int rt)
{
u_int armval;
output_w32(0x1a000000|offset);
}
-static void emit_jeq(int a)
+static void emit_jeq(const void *a_)
{
+ int a = (int)a_;
assem_debug("beq %x\n",a);
u_int offset=genjmp(a);
output_w32(0x0a000000|offset);
}
-static void emit_js(int a)
+static void emit_js(const void *a_)
{
+ int a = (int)a_;
assem_debug("bmi %x\n",a);
u_int offset=genjmp(a);
output_w32(0x4a000000|offset);
}
-static void emit_jns(int a)
+static void emit_jns(const void *a_)
{
+ int a = (int)a_;
assem_debug("bpl %x\n",a);
u_int offset=genjmp(a);
output_w32(0x5a000000|offset);
}
-static void emit_jl(int a)
+static void emit_jl(const void *a_)
{
+ int a = (int)a_;
assem_debug("blt %x\n",a);
u_int offset=genjmp(a);
output_w32(0xba000000|offset);
}
-static void emit_jge(int a)
+static void emit_jge(const void *a_)
{
+ int a = (int)a_;
assem_debug("bge %x\n",a);
u_int offset=genjmp(a);
output_w32(0xaa000000|offset);
}
-static void emit_jno(int a)
+static void emit_jno(const void *a_)
{
+ int a = (int)a_;
assem_debug("bvc %x\n",a);
u_int offset=genjmp(a);
output_w32(0x7a000000|offset);
}
-static void emit_jc(int a)
+static void emit_jc(const void *a_)
{
+ int a = (int)a_;
assem_debug("bcs %x\n",a);
u_int offset=genjmp(a);
output_w32(0x2a000000|offset);
}
-static void emit_jcc(void *a_)
+static void emit_jcc(const void *a_)
{
int a = (int)a_;
assem_debug("bcc %x\n",a);
set_jump_target(jaddr, out);
}
-static void emit_extjump2(u_char *addr, int target, void *linker)
+// parsed by get_pointer, find_extjump_insn
+static void emit_extjump2(u_char *addr, u_int target, void *linker)
{
u_char *ptr=(u_char *)addr;
assert((ptr[3]&0x0e)==0xa);
emit_jmp(linker);
}
-static void emit_extjump(void *addr, int target)
-{
- emit_extjump2(addr, target, dyna_linker);
-}
-
-static void emit_extjump_ds(void *addr, int target)
-{
- emit_extjump2(addr, target, dyna_linker_ds);
-}
-
// put rt_val into rt, potentially making use of rs with value rs_val
static void emit_movimm_from(u_int rs_val,int rs,u_int rt_val,int rt)
{
emit_jmp(stubs[n].retaddr); // return address
}
-void *do_dirty_stub(int i)
+// this output is parsed by verify_dirty, get_bounds
+static void do_dirty_stub_emit_args(u_int arg0)
{
- assem_debug("do_dirty_stub %x\n",start+i*4);
- u_int addr=(u_int)source;
- // Careful about the code output here, verify_dirty needs to parse it.
#ifndef HAVE_ARMV7
- emit_loadlp(addr,1);
- emit_loadlp((int)copy,2);
- emit_loadlp(slen*4,3);
+ emit_loadlp((int)source, 1);
+ emit_loadlp((int)copy, 2);
+ emit_loadlp(slen*4, 3);
#else
- emit_movw(addr&0x0000FFFF,1);
- emit_movw(((u_int)copy)&0x0000FFFF,2);
- emit_movt(addr&0xFFFF0000,1);
- emit_movt(((u_int)copy)&0xFFFF0000,2);
- emit_movw(slen*4,3);
+ emit_movw(((u_int)source)&0x0000FFFF, 1);
+ emit_movw(((u_int)copy)&0x0000FFFF, 2);
+ emit_movt(((u_int)source)&0xFFFF0000, 1);
+ emit_movt(((u_int)copy)&0xFFFF0000, 2);
+ emit_movw(slen*4, 3);
#endif
- emit_movimm(start+i*4,0);
- emit_call((int)start<(int)0xC0000000?&verify_code:&verify_code_vm);
+ emit_movimm(arg0, 0);
+}
+
+static void *do_dirty_stub(int i)
+{
+ assem_debug("do_dirty_stub %x\n",start+i*4);
+ do_dirty_stub_emit_args(start + i*4);
+ emit_call(verify_code);
void *entry = out;
load_regs_entry(i);
if (entry == out)
static void do_dirty_stub_ds()
{
- // Careful about the code output here, verify_dirty needs to parse it.
- #ifndef HAVE_ARMV7
- emit_loadlp((int)start<(int)0xC0000000?(int)source:(int)start,1);
- emit_loadlp((int)copy,2);
- emit_loadlp(slen*4,3);
- #else
- emit_movw(((int)start<(int)0xC0000000?(u_int)source:(u_int)start)&0x0000FFFF,1);
- emit_movw(((u_int)copy)&0x0000FFFF,2);
- emit_movt(((int)start<(int)0xC0000000?(u_int)source:(u_int)start)&0xFFFF0000,1);
- emit_movt(((u_int)copy)&0xFFFF0000,2);
- emit_movw(slen*4,3);
- #endif
- emit_movimm(start+1,0);
- emit_call(&verify_code_ds);
+ do_dirty_stub_emit_args(start + 1);
+ emit_call(verify_code_ds);
}
/* Special assem */
emit_negmi(quotient,quotient); // .. quotient and ..
emit_negmi(remainder,remainder); // .. remainder for div0 case (will be negated back after jump)
emit_movs(d2,HOST_TEMPREG);
- emit_jeq((int)out+52); // Division by zero
+ emit_jeq(out+52); // Division by zero
emit_negsmi(HOST_TEMPREG,HOST_TEMPREG);
#ifdef HAVE_ARMV5
emit_clz(HOST_TEMPREG,quotient);
emit_movimm(0,quotient);
emit_addpl_imm(quotient,1,quotient);
emit_lslpls_imm(HOST_TEMPREG,1,HOST_TEMPREG);
- emit_jns((int)out-2*4);
+ emit_jns(out-2*4);
#endif
emit_orimm(quotient,1<<31,quotient);
emit_shr(quotient,quotient,quotient);
emit_mov(d1,remainder);
emit_movimm(0xffffffff,quotient); // div0 case
emit_test(d2,d2);
- emit_jeq((int)out+40); // Division by zero
+ emit_jeq(out+40); // Division by zero
#ifdef HAVE_ARMV5
emit_clz(d2,HOST_TEMPREG);
emit_movimm(1<<31,quotient);
emit_movimm(0,HOST_TEMPREG);
emit_addpl_imm(HOST_TEMPREG,1,HOST_TEMPREG);
emit_lslpls_imm(d2,1,d2);
- emit_jns((int)out-2*4);
+ emit_jns(out-2*4);
emit_movimm(1<<31,quotient);
#endif
emit_shr(quotient,HOST_TEMPREG,quotient);
static u_char rs2[MAXBLOCK];
static u_char rt1[MAXBLOCK];
static u_char rt2[MAXBLOCK];
- static u_char us1[MAXBLOCK];
- static u_char us2[MAXBLOCK];
static u_char dep1[MAXBLOCK];
static u_char dep2[MAXBLOCK];
static u_char lt1[MAXBLOCK];
/* registers that may be allocated */
/* 1-31 gpr */
-#define HIREG 32 // hi
-#define LOREG 33 // lo
+#define LOREG 32 // lo
+#define HIREG 33 // hi
//#define FSREG 34 // FPU status (FCSR)
#define CSREG 35 // Coprocessor status
#define CCREG 36 // Cycle count
#define NOTTAKEN 2
#define NULLDS 3
+#define DJT_1 (void *)1l // no function, just a label in assem_debug log
+#define DJT_2 (void *)2l
+
// asm linkage
int new_recompile_block(int addr);
void *get_addr_ht(u_int vaddr);
void dyna_linker();
void dyna_linker_ds();
void verify_code();
-void verify_code_vm();
void verify_code_ds();
void cc_interrupt();
void fp_exception();
cur->isconst|=1<<hr;
current_constmap[hr]=value;
}
- else if((cur->regmap[hr]^64)==reg) {
- cur->isconst|=1<<hr;
- current_constmap[hr]=value>>32;
- }
}
}
}
}
SysPrintf("Unknown constant in r%d\n",reg);
- exit(1);
+ abort();
}
// Least soon needed registers
FUNCNAME(jump_handler_write16),
FUNCNAME(jump_handler_write32),
FUNCNAME(invalidate_addr),
- FUNCNAME(verify_code_vm),
FUNCNAME(verify_code),
FUNCNAME(jump_hlecall),
FUNCNAME(jump_syscall_hle),
for(r=1;r<=MAXREG;r++)
{
if(hsn[r]==j&&r!=rs1[i-1]&&r!=rs2[i-1]&&r!=rt1[i-1]&&r!=rt2[i-1]) {
- for(hr=0;hr<HOST_REGS;hr++) {
- if(hr!=HOST_CCREG||j<hsn[CCREG]) {
- if(cur->regmap[hr]==r+64) {
- cur->regmap[hr]=reg;
- cur->dirty&=~(1<<hr);
- cur->isconst&=~(1<<hr);
- return;
- }
- }
- }
for(hr=0;hr<HOST_REGS;hr++) {
if(hr!=HOST_CCREG||j<hsn[CCREG]) {
if(cur->regmap[hr]==r) {
for(r=1;r<=MAXREG;r++)
{
if(hsn[r]==j) {
- for(hr=0;hr<HOST_REGS;hr++) {
- if(cur->regmap[hr]==r+64) {
- cur->regmap[hr]=reg;
- cur->dirty&=~(1<<hr);
- cur->isconst&=~(1<<hr);
- return;
- }
- }
for(hr=0;hr<HOST_REGS;hr++) {
if(cur->regmap[hr]==r) {
cur->regmap[hr]=reg;
}
}
}
- SysPrintf("This shouldn't happen (alloc_reg)");exit(1);
+ SysPrintf("This shouldn't happen (alloc_reg)");abort();
}
// Allocate a temporary register. This is done without regard to
for(r=1;r<=MAXREG;r++)
{
if(hsn[r]==j&&r!=rs1[i-1]&&r!=rs2[i-1]&&r!=rt1[i-1]&&r!=rt2[i-1]) {
- for(hr=0;hr<HOST_REGS;hr++) {
- if(hr!=HOST_CCREG||hsn[CCREG]>2) {
- if(cur->regmap[hr]==r+64) {
- cur->regmap[hr]=reg;
- cur->dirty&=~(1<<hr);
- cur->isconst&=~(1<<hr);
- return;
- }
- }
- }
for(hr=0;hr<HOST_REGS;hr++) {
if(hr!=HOST_CCREG||hsn[CCREG]>2) {
if(cur->regmap[hr]==r) {
for(r=1;r<=MAXREG;r++)
{
if(hsn[r]==j) {
- for(hr=0;hr<HOST_REGS;hr++) {
- if(cur->regmap[hr]==r+64) {
- cur->regmap[hr]=reg;
- cur->dirty&=~(1<<hr);
- cur->isconst&=~(1<<hr);
- return;
- }
- }
for(hr=0;hr<HOST_REGS;hr++) {
if(cur->regmap[hr]==r) {
cur->regmap[hr]=reg;
}
}
}
- SysPrintf("This shouldn't happen");exit(1);
+ SysPrintf("This shouldn't happen");abort();
}
static void mov_alloc(struct regstat *current,int i)
case SYSCALL:
case HLECALL:
case SPAN:
- assem_debug("jump in the delay slot. this shouldn't happen.\n");//exit(1);
+ assem_debug("jump in the delay slot. this shouldn't happen.\n");//abort();
SysPrintf("Disabled speculative precompilation\n");
stop_after_jal=1;
break;
}
}
-void rlist()
-{
- int i;
- printf("TRACE: ");
- for(i=0;i<32;i++)
- printf("r%d:%8x%8x ",i,((int *)(reg+i))[1],((int *)(reg+i))[0]);
- printf("\n");
-}
-
// trashes r2
static void pass_args(int a0, int a1)
{
}
if(opcode[i]==0x18||opcode[i]==0x19) { // DADDI/DADDIU
if(rt1[i]) {
- signed char sh,sl,th,tl;
- th=get_reg(i_regs->regmap,rt1[i]|64);
+ signed char sl,tl;
tl=get_reg(i_regs->regmap,rt1[i]);
- sh=get_reg(i_regs->regmap,rs1[i]|64);
sl=get_reg(i_regs->regmap,rs1[i]);
if(tl>=0) {
if(rs1[i]) {
- assert(sh>=0);
assert(sl>=0);
- if(th>=0) {
- emit_addimm64_32(sh,sl,imm[i],th,tl);
- }
- else {
- emit_addimm(sl,imm[i],tl);
- }
+ emit_addimm(sl,imm[i],tl);
} else {
emit_movimm(imm[i],tl);
- if(th>=0) emit_movimm(((signed int)imm[i])>>31,th);
}
}
}
}
else if(opcode[i]>=0x0c&&opcode[i]<=0x0e) { // ANDI/ORI/XORI
if(rt1[i]) {
- signed char sh,sl,th,tl;
- th=get_reg(i_regs->regmap,rt1[i]|64);
+ signed char sl,tl;
tl=get_reg(i_regs->regmap,rt1[i]);
- sh=get_reg(i_regs->regmap,rs1[i]|64);
sl=get_reg(i_regs->regmap,rs1[i]);
if(tl>=0 && !((i_regs->isconst>>tl)&1)) {
if(opcode[i]==0x0c) //ANDI
}
else
emit_zeroreg(tl);
- if(th>=0) emit_zeroreg(th);
}
else
{
if(sl<0) {
if(i_regs->regmap_entry[tl]!=rs1[i]) emit_loadreg(rs1[i],tl);
}
- if(th>=0) {
- if(sh<0) {
- emit_loadreg(rs1[i]|64,th);
- }else{
- emit_mov(sh,th);
- }
- }
if(opcode[i]==0x0d) { // ORI
if(sl<0) {
emit_orimm(tl,imm[i],tl);
}
else {
emit_movimm(imm[i],tl);
- if(th>=0) emit_zeroreg(th);
}
}
}
void shift_assemble(int i,struct regstat *i_regs)
{
printf("Need shift_assemble for this architecture.\n");
- exit(1);
+ abort();
}
#endif
static void load_assemble(int i,struct regstat *i_regs)
{
- int s,th,tl,addr;
+ int s,tl,addr;
int offset;
void *jaddr=0;
int memtarget=0,c=0;
int fastload_reg_override=0;
u_int hr,reglist=0;
- th=get_reg(i_regs->regmap,rt1[i]|64);
tl=get_reg(i_regs->regmap,rt1[i]);
s=get_reg(i_regs->regmap,rs1[i]);
offset=imm[i];
//if(c) printf("load_assemble: const=%lx\n",(long)constmap[i][s]+offset);
assert(tl>=0); // Even if the load is a NOP, we must check for pagefaults and I/O
reglist&=~(1<<tl);
- if(th>=0) reglist&=~(1<<th);
if(!c) {
#ifdef R29_HACK
// Strmnnrmn's speed hack
inline_readstub(LOADHU_STUB,i,constmap[i][s]+offset,i_regs->regmap,rt1[i],ccadj[i],reglist);
}
if (opcode[i]==0x27) { // LWU
- assert(th>=0);
- if(!c||memtarget) {
- if(!dummy) {
- int a=addr;
- if(fastload_reg_override) a=fastload_reg_override;
- emit_readword_indexed(0,a,tl);
- }
- if(jaddr)
- add_stub_r(LOADW_STUB,jaddr,out,i,addr,i_regs,ccadj[i],reglist);
- }
- else {
- inline_readstub(LOADW_STUB,i,constmap[i][s]+offset,i_regs->regmap,rt1[i],ccadj[i],reglist);
- }
- emit_zeroreg(th);
+ assert(0);
}
if (opcode[i]==0x37) { // LD
assert(0);
void loadlr_assemble(int i,struct regstat *i_regs)
{
printf("Need loadlr_assemble for this architecture.\n");
- exit(1);
+ abort();
}
#endif
emit_jne(&do_interrupt);
}
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));
}
else
{
void multdiv_assemble(int i,struct regstat *i_regs)
{
printf("Need multdiv_assemble for this architecture.\n");
- exit(1);
+ abort();
}
#endif
-void mov_assemble(int i,struct regstat *i_regs)
+static void mov_assemble(int i,struct regstat *i_regs)
{
//if(opcode2[i]==0x10||opcode2[i]==0x12) { // MFHI/MFLO
//if(opcode2[i]==0x11||opcode2[i]==0x13) { // MTHI/MTLO
if(rt1[i]) {
- signed char sh,sl,th,tl;
- th=get_reg(i_regs->regmap,rt1[i]|64);
+ signed char sl,tl;
tl=get_reg(i_regs->regmap,rt1[i]);
//assert(tl>=0);
if(tl>=0) {
- sh=get_reg(i_regs->regmap,rs1[i]|64);
sl=get_reg(i_regs->regmap,rs1[i]);
if(sl>=0) emit_mov(sl,tl);
else emit_loadreg(rs1[i],tl);
- if(th>=0) {
- if(sh>=0) emit_mov(sh,th);
- else emit_loadreg(rs1[i]|64,th);
- }
}
}
}
-void syscall_assemble(int i,struct regstat *i_regs)
+static void syscall_assemble(int i,struct regstat *i_regs)
{
signed char ccreg=get_reg(i_regs->regmap,CCREG);
assert(ccreg==HOST_CCREG);
emit_jmp(jump_syscall_hle); // XXX
}
-void hlecall_assemble(int i,struct regstat *i_regs)
+static void hlecall_assemble(int i,struct regstat *i_regs)
{
extern void psxNULL();
signed char ccreg=get_reg(i_regs->regmap,CCREG);
emit_jmp(jump_hlecall);
}
-void intcall_assemble(int i,struct regstat *i_regs)
+static void intcall_assemble(int i,struct regstat *i_regs)
{
signed char ccreg=get_reg(i_regs->regmap,CCREG);
assert(ccreg==HOST_CCREG);
#endif
}
-void ds_assemble(int i,struct regstat *i_regs)
+static void ds_assemble(int i,struct regstat *i_regs)
{
speculate_register_values(i);
is_delayslot=1;
#endif
// Used when a branch jumps into the delay slot of another branch
-void ds_assemble_entry(int i)
+static void ds_assemble_entry(int i)
{
int t=(ba[i]-start)>>2;
if (!instr_addr[t])
emit_jmp(0);
}
+static void emit_extjump(void *addr, u_int target)
+{
+ emit_extjump2(addr, target, dyna_linker);
+}
+
+static void emit_extjump_ds(void *addr, u_int target)
+{
+ emit_extjump2(addr, target, dyna_linker_ds);
+}
+
void do_cc(int i,signed char i_regmap[],int *adj,int addr,int taken,int invert)
{
int count;
}
emit_writeword(r,&pcaddr);
}
- else {SysPrintf("Unknown branch type in do_ccstub\n");exit(1);}
+ else {SysPrintf("Unknown branch type in do_ccstub\n");abort();}
}
// Update cycle count
assert(branch_regs[i].regmap[HOST_CCREG]==CCREG||branch_regs[i].regmap[HOST_CCREG]==-1);
}
}
-void ujump_assemble(int i,struct regstat *i_regs)
+static void ujump_assemble(int i,struct regstat *i_regs)
{
int ra_done=0;
if(i==(ba[i]-start)>>2) assem_debug("idle loop\n");
#endif
}
-void rjump_assemble(int i,struct regstat *i_regs)
+static void rjump_assemble(int i,struct regstat *i_regs)
{
int temp;
int rs,cc;
#endif
}
-void cjump_assemble(int i,struct regstat *i_regs)
+static void cjump_assemble(int i,struct regstat *i_regs)
{
signed char *i_regmap=i_regs->regmap;
int cc;
else emit_test(s1l,s1l);
if(invert){
nottaken=out;
- emit_jne((void *)1l);
+ emit_jne(DJT_1);
}else{
add_to_linker(out,ba[i],internal);
emit_jeq(0);
else emit_test(s1l,s1l);
if(invert){
nottaken=out;
- emit_jeq(1);
+ emit_jeq(DJT_1);
}else{
add_to_linker(out,ba[i],internal);
emit_jne(0);
emit_cmpimm(s1l,1);
if(invert){
nottaken=out;
- emit_jge(1);
+ emit_jge(DJT_1);
}else{
add_to_linker(out,ba[i],internal);
emit_jl(0);
emit_cmpimm(s1l,1);
if(invert){
nottaken=out;
- emit_jl(1);
+ emit_jl(DJT_1);
}else{
add_to_linker(out,ba[i],internal);
emit_jge(0);
if(s2l>=0) emit_cmp(s1l,s2l);
else emit_test(s1l,s1l);
nottaken=out;
- emit_jne((void *)2l);
+ emit_jne(DJT_2);
}
if((opcode[i]&0x2f)==5) // BNE
{
if(s2l>=0) emit_cmp(s1l,s2l);
else emit_test(s1l,s1l);
nottaken=out;
- emit_jeq(2);
+ emit_jeq(DJT_2);
}
if((opcode[i]&0x2f)==6) // BLEZ
{
emit_cmpimm(s1l,1);
nottaken=out;
- emit_jge(2);
+ emit_jge(DJT_2);
}
if((opcode[i]&0x2f)==7) // BGTZ
{
emit_cmpimm(s1l,1);
nottaken=out;
- emit_jl(2);
+ emit_jl(DJT_2);
}
} // if(!unconditional)
int adj;
}
}
-void sjump_assemble(int i,struct regstat *i_regs)
+static void sjump_assemble(int i,struct regstat *i_regs)
{
signed char *i_regmap=i_regs->regmap;
int cc;
emit_test(s1l,s1l);
if(invert){
nottaken=out;
- emit_jns(1);
+ emit_jns(DJT_1);
}else{
add_to_linker(out,ba[i],internal);
emit_js(0);
emit_test(s1l,s1l);
if(invert){
nottaken=out;
- emit_js(1);
+ emit_js(DJT_1);
}else{
add_to_linker(out,ba[i],internal);
emit_jns(0);
{
emit_test(s1l,s1l);
nottaken=out;
- emit_jns(1);
+ emit_jns(DJT_1);
}
if((opcode2[i]&0x0d)==1) // BGEZ/BGEZL/BGEZAL/BGEZALL
{
emit_test(s1l,s1l);
nottaken=out;
- emit_js(1);
+ emit_js(DJT_1);
}
} // if(!unconditional)
int adj;
size_t i;
// check structure linkage
- if ((void *)reg != (void *)&psxRegs
- || (u_char *)rcnts - (u_char *)reg != sizeof(psxRegs))
+ if ((u_char *)rcnts - (u_char *)&psxRegs != sizeof(psxRegs))
{
- SysPrintf("linkage_arm miscompilation/breakage detected.\n");
+ SysPrintf("linkage_arm* miscompilation/breakage detected.\n");
}
SysPrintf("testing if we can run recompiled code...\n");
}
start = (u_int)addr&~3;
- //assert(((u_int)addr&1)==0);
+ //assert(((u_int)addr&1)==0); // start-in-delay-slot flag
new_dynarec_did_compile=1;
if (Config.HLE && start == 0x80001000) // hlecall
{
source = get_source_start(start, &pagelimit);
if (source == NULL) {
SysPrintf("Compile at bogus memory address: %08x\n", addr);
- exit(1);
+ abort();
}
/* Pass 1: disassemble */
opcode2[i]=op2;
/* Get registers/immediates */
lt1[i]=0;
- us1[i]=0;
- us2[i]=0;
dep1[i]=0;
dep2[i]=0;
gte_rs[i]=gte_rt[i]=0;
rt1[i]=0;
rt2[i]=0;
imm[i]=(short)source[i];
- if(op==0x2c||op==0x2d||op==0x3f) us1[i]=rs2[i]; // 64-bit SDL/SDR/SD
break;
case LOADLR:
// LWL/LWR only load part of the register,
rt1[i]=(source[i]>>16)&0x1f;
rt2[i]=0;
imm[i]=(short)source[i];
- if(op==0x1a||op==0x1b) us1[i]=rs2[i]; // LDR/LDL
if(op==0x26) dep1[i]=rt1[i]; // LWR
break;
case IMM16:
}else{
imm[i]=(short)source[i];
}
- if(op==0x18||op==0x19) us1[i]=rs1[i]; // DADDI/DADDIU
- if(op==0x0a||op==0x0b) us1[i]=rs1[i]; // SLTI/SLTIU
if(op==0x0d||op==0x0e) dep1[i]=rs1[i]; // ORI/XORI
break;
case UJUMP:
if(op&2) { // BGTZ/BLEZ
rs2[i]=0;
}
- us1[i]=rs1[i];
- us2[i]=rs2[i];
likely[i]=op>>4;
break;
case SJUMP:
rs2[i]=CCREG;
rt1[i]=0;
rt2[i]=0;
- us1[i]=rs1[i];
if(op2&0x10) { // BxxAL
rt1[i]=31;
// NOTE: If the branch is not taken, r31 is still overwritten
rs2[i]=(source[i]>>16)&0x1f; // subtract amount
rt1[i]=(source[i]>>11)&0x1f; // destination
rt2[i]=0;
- if(op2==0x2a||op2==0x2b) { // SLT/SLTU
- us1[i]=rs1[i];us2[i]=rs2[i];
- }
- else if(op2>=0x24&&op2<=0x27) { // AND/OR/XOR/NOR
+ if(op2>=0x24&&op2<=0x27) { // AND/OR/XOR/NOR
dep1[i]=rs1[i];dep2[i]=rs2[i];
}
else if(op2>=0x2c&&op2<=0x2f) { // DADD/DSUB
rs2[i]=(source[i]>>16)&0x1f; // divisor
rt1[i]=HIREG;
rt2[i]=LOREG;
- if (op2>=0x1c&&op2<=0x1f) { // DMULT/DMULTU/DDIV/DDIVU
- us1[i]=rs1[i];us2[i]=rs2[i];
- }
break;
case MOV:
rs1[i]=0;
rs2[i]=(source[i]>>21)&0x1f; // shift amount
rt1[i]=(source[i]>>11)&0x1f; // destination
rt2[i]=0;
- // DSLLV/DSRLV/DSRAV are 64-bit
- if(op2>=0x14&&op2<=0x17) us1[i]=rs1[i];
break;
case SHIFTIMM:
rs1[i]=(source[i]>>16)&0x1f;
imm[i]=(source[i]>>6)&0x1f;
// DSxx32 instructions
if(op2>=0x3c) imm[i]|=0x20;
- // DSLL/DSRL/DSRA/DSRA32/DSRL32 but not DSLL32 require 64-bit source
- if(op2>=0x38&&op2!=0x3c) us1[i]=rs1[i];
break;
case COP0:
rs1[i]=0;
rt2[i]=0;
if(op2<3) rt1[i]=(source[i]>>16)&0x1F; // MFC1/DMFC1/CFC1
if(op2>3) rs1[i]=(source[i]>>16)&0x1F; // MTC1/DMTC1/CTC1
- if(op2==5) us1[i]=rs1[i]; // DMTC1
rs2[i]=CSREG;
break;
case COP2:
current.isconst=0;
current.waswritten=0;
}
- if(i>1)
- {
- if((opcode[i-2]&0x2f)==0x05) // BNE/BNEL
- {
- if(rs1[i-2]==0||rs2[i-2]==0)
- {
- if(rs1[i-2]) {
- int hr=get_reg(current.regmap,rs1[i-2]|64);
- if(hr>=0) current.regmap[hr]=-1;
- }
- if(rs2[i-2]) {
- int hr=get_reg(current.regmap,rs2[i-2]|64);
- if(hr>=0) current.regmap[hr]=-1;
- }
- }
- }
- }
memcpy(regmap_pre[i],current.regmap,sizeof(current.regmap));
regs[i].wasconst=current.isconst;
current.u=branch_unneeded_reg[i]&~((1LL<<rs1[i+1])|(1LL<<rs2[i+1]));
current.u&=~((1LL<<rs1[i])|(1LL<<rs2[i]));
current.u|=1;
- } else { SysPrintf("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");abort(); }
}
is_ds[i]=ds;
if(ds) {
}
else
{
- if(r<64){
+ assert(r < 64);
if((current.u>>r)&1) {
regs[i].regmap_entry[hr]=-1;
regs[i].regmap[hr]=-1;
//current.regmap[hr]=-1;
}else
regs[i].regmap_entry[hr]=r;
- }
- else {
- assert(0);
- }
}
} else {
// First instruction expects CCREG to be allocated
regs[i].regmap_entry[hr]=0;
}
else
- if(r<64){
+ {
+ assert(r<64);
if((current.u>>r)&1) {
regs[i].regmap_entry[hr]=-1;
//regs[i].regmap[hr]=-1;
}else
regs[i].regmap_entry[hr]=r;
}
- else {
- assert(0);
- }
}
} else {
// Branches expect CCREG to be allocated at the target
if(rt1[i+1]&&rt1[i+1]==(regs[i].regmap[hr]&63)) nr&=~(1<<hr);
if(rt2[i+1]&&rt2[i+1]==(regs[i].regmap[hr]&63)) nr&=~(1<<hr);
}
- if(us1[i+1]==(regmap_pre[i][hr]&63)) nr|=1<<hr;
- if(us2[i+1]==(regmap_pre[i][hr]&63)) nr|=1<<hr;
if(rs1[i+1]==regmap_pre[i][hr]) nr|=1<<hr;
if(rs2[i+1]==regmap_pre[i][hr]) nr|=1<<hr;
- if(us1[i+1]==(regs[i].regmap_entry[hr]&63)) nr|=1<<hr;
- if(us2[i+1]==(regs[i].regmap_entry[hr]&63)) nr|=1<<hr;
if(rs1[i+1]==regs[i].regmap_entry[hr]) nr|=1<<hr;
if(rs2[i+1]==regs[i].regmap_entry[hr]) nr|=1<<hr;
if(itype[i+1]==STORE || itype[i+1]==STORELR || (opcode[i+1]&0x3b)==0x39 || (opcode[i+1]&0x3b)==0x3a) {
if(rt2[i]&&rt2[i]==(regs[i].regmap[hr]&63)) nr&=~(1<<hr);
if(FTEMP==(regs[i].regmap[hr]&63)) nr&=~(1<<hr);
// Source registers are needed
- if(us1[i]==(regmap_pre[i][hr]&63)) nr|=1<<hr;
- if(us2[i]==(regmap_pre[i][hr]&63)) nr|=1<<hr;
if(rs1[i]==regmap_pre[i][hr]) nr|=1<<hr;
if(rs2[i]==regmap_pre[i][hr]) nr|=1<<hr;
- if(us1[i]==(regs[i].regmap_entry[hr]&63)) nr|=1<<hr;
- if(us2[i]==(regs[i].regmap_entry[hr]&63)) nr|=1<<hr;
if(rs1[i]==regs[i].regmap_entry[hr]) nr|=1<<hr;
if(rs2[i]==regs[i].regmap_entry[hr]) nr|=1<<hr;
if(itype[i]==STORE || itype[i]==STORELR || (opcode[i]&0x3b)==0x39 || (opcode[i]&0x3b)==0x3a) {
// But do so if this is a branch target, otherwise we
// might have to load the register before the branch.
if(i>0&&!bt[i]&&((regs[i].wasdirty>>hr)&1)) {
- if((regmap_pre[i][hr]>0&®map_pre[i][hr]<64&&!((unneeded_reg[i]>>regmap_pre[i][hr])&1))) {
+ if((regmap_pre[i][hr]>0&&!((unneeded_reg[i]>>regmap_pre[i][hr])&1))) {
if(rt1[i-1]==(regmap_pre[i][hr]&63)) nr|=1<<hr;
if(rt2[i-1]==(regmap_pre[i][hr]&63)) nr|=1<<hr;
}
- if((regs[i].regmap_entry[hr]>0&®s[i].regmap_entry[hr]<64&&!((unneeded_reg[i]>>regs[i].regmap_entry[hr])&1))) {
+ if((regs[i].regmap_entry[hr]>0&&!((unneeded_reg[i]>>regs[i].regmap_entry[hr])&1))) {
if(rt1[i-1]==(regs[i].regmap_entry[hr]&63)) nr|=1<<hr;
if(rt2[i-1]==(regs[i].regmap_entry[hr]&63)) nr|=1<<hr;
}
}
if(itype[i]==RJUMP||itype[i]==UJUMP||itype[i]==CJUMP||itype[i]==SJUMP)
{
- int d1=0,d2=0,map=0,temp=0;
- if(get_reg(regs[i].regmap,rt1[i+1]|64)>=0||get_reg(branch_regs[i].regmap,rt1[i+1]|64)>=0)
- {
- d1=dep1[i+1];
- d2=dep2[i+1];
- }
+ int map=0,temp=0;
if(itype[i+1]==STORE || itype[i+1]==STORELR ||
(opcode[i+1]&0x3b)==0x39 || (opcode[i+1]&0x3b)==0x3a) { // SWC1/SDC1 || SWC2/SDC2
map=INVCP;
if((regs[i].regmap[hr]&63)!=rs1[i] && (regs[i].regmap[hr]&63)!=rs2[i] &&
(regs[i].regmap[hr]&63)!=rt1[i] && (regs[i].regmap[hr]&63)!=rt2[i] &&
(regs[i].regmap[hr]&63)!=rt1[i+1] && (regs[i].regmap[hr]&63)!=rt2[i+1] &&
- (regs[i].regmap[hr]^64)!=us1[i+1] && (regs[i].regmap[hr]^64)!=us2[i+1] &&
- (regs[i].regmap[hr]^64)!=d1 && (regs[i].regmap[hr]^64)!=d2 &&
regs[i].regmap[hr]!=rs1[i+1] && regs[i].regmap[hr]!=rs2[i+1] &&
(regs[i].regmap[hr]&63)!=temp && regs[i].regmap[hr]!=PTEMP &&
regs[i].regmap[hr]!=RHASH && regs[i].regmap[hr]!=RHTBL &&
if((branch_regs[i].regmap[hr]&63)!=rs1[i] && (branch_regs[i].regmap[hr]&63)!=rs2[i] &&
(branch_regs[i].regmap[hr]&63)!=rt1[i] && (branch_regs[i].regmap[hr]&63)!=rt2[i] &&
(branch_regs[i].regmap[hr]&63)!=rt1[i+1] && (branch_regs[i].regmap[hr]&63)!=rt2[i+1] &&
- (branch_regs[i].regmap[hr]^64)!=us1[i+1] && (branch_regs[i].regmap[hr]^64)!=us2[i+1] &&
- (branch_regs[i].regmap[hr]^64)!=d1 && (branch_regs[i].regmap[hr]^64)!=d2 &&
branch_regs[i].regmap[hr]!=rs1[i+1] && branch_regs[i].regmap[hr]!=rs2[i+1] &&
(branch_regs[i].regmap[hr]&63)!=temp && branch_regs[i].regmap[hr]!=PTEMP &&
branch_regs[i].regmap[hr]!=RHASH && branch_regs[i].regmap[hr]!=RHTBL &&
// Non-branch
if(i>0)
{
- int d1=0,d2=0,map=-1,temp=-1;
- if(get_reg(regs[i].regmap,rt1[i]|64)>=0)
- {
- d1=dep1[i];
- d2=dep2[i];
- }
+ int map=-1,temp=-1;
if(itype[i]==STORE || itype[i]==STORELR ||
(opcode[i]&0x3b)==0x39 || (opcode[i]&0x3b)==0x3a) { // SWC1/SDC1 || SWC2/SDC2
map=INVCP;
itype[i]==C1LS || itype[i]==C2LS)
temp=FTEMP;
if((regs[i].regmap[hr]&63)!=rt1[i] && (regs[i].regmap[hr]&63)!=rt2[i] &&
- (regs[i].regmap[hr]^64)!=us1[i] && (regs[i].regmap[hr]^64)!=us2[i] &&
- (regs[i].regmap[hr]^64)!=d1 && (regs[i].regmap[hr]^64)!=d2 &&
regs[i].regmap[hr]!=rs1[i] && regs[i].regmap[hr]!=rs2[i] &&
(regs[i].regmap[hr]&63)!=temp && regs[i].regmap[hr]!=map &&
(itype[i]!=SPAN||regs[i].regmap[hr]!=CCREG))
if(t<2||(itype[t-2]!=UJUMP&&itype[t-2]!=RJUMP)||rt1[t-2]!=31) // call/ret assumes no registers allocated
for(hr=0;hr<HOST_REGS;hr++)
{
- if(regs[i].regmap[hr]>64) {
- if(!((regs[i].dirty>>hr)&1))
- f_regmap[hr]=regs[i].regmap[hr];
- else f_regmap[hr]=-1;
- }
- else if(regs[i].regmap[hr]>=0) {
+ if(regs[i].regmap[hr]>=0) {
if(f_regmap[hr]!=regs[i].regmap[hr]) {
// dealloc old register
int n;
f_regmap[hr]=regs[i].regmap[hr];
}
}
- if(branch_regs[i].regmap[hr]>64) {
- if(!((branch_regs[i].dirty>>hr)&1))
- f_regmap[hr]=branch_regs[i].regmap[hr];
- else f_regmap[hr]=-1;
- }
- else if(branch_regs[i].regmap[hr]>=0) {
+ if(branch_regs[i].regmap[hr]>=0) {
if(f_regmap[hr]!=branch_regs[i].regmap[hr]) {
// dealloc old register
int n;
for(hr=0;hr<HOST_REGS;hr++)
{
if(hr!=EXCLUDE_REG) {
- if(regs[i].regmap[hr]>64) {
- if(!((regs[i].dirty>>hr)&1))
- f_regmap[hr]=regs[i].regmap[hr];
- }
- else if(regs[i].regmap[hr]>=0) {
+ if(regs[i].regmap[hr]>=0) {
if(f_regmap[hr]!=regs[i].regmap[hr]) {
// dealloc old register
int n;
#ifdef __arm__
printf("pre: r0=%d r1=%d r2=%d r3=%d r4=%d r5=%d r6=%d r7=%d r8=%d r9=%d r10=%d r12=%d\n",regmap_pre[i][0],regmap_pre[i][1],regmap_pre[i][2],regmap_pre[i][3],regmap_pre[i][4],regmap_pre[i][5],regmap_pre[i][6],regmap_pre[i][7],regmap_pre[i][8],regmap_pre[i][9],regmap_pre[i][10],regmap_pre[i][12]);
#endif
+ #if defined(__i386__) || defined(__x86_64__)
printf("needs: ");
if(needed_reg[i]&1) printf("eax ");
if((needed_reg[i]>>1)&1) printf("ecx ");
if((needed_reg[i]>>6)&1) printf("esi ");
if((needed_reg[i]>>7)&1) printf("edi ");
printf("\n");
- #if defined(__i386__) || defined(__x86_64__)
printf("entry: eax=%d ecx=%d edx=%d ebx=%d ebp=%d esi=%d edi=%d\n",regs[i].regmap_entry[0],regs[i].regmap_entry[1],regs[i].regmap_entry[2],regs[i].regmap_entry[3],regs[i].regmap_entry[5],regs[i].regmap_entry[6],regs[i].regmap_entry[7]);
printf("dirty: ");
if(regs[i].wasdirty&1) printf("eax ");
if((regs[i].isconst>>6)&1) printf("esi=%x ",(u_int)constmap[i][6]);
if((regs[i].isconst>>7)&1) printf("edi=%x ",(u_int)constmap[i][7]);
#endif
- #ifdef __arm__
+ #if defined(__arm__) || defined(__aarch64__)
int r;
for (r = 0; r < ARRAY_SIZE(constmap[i]); r++)
if ((regs[i].isconst >> r) & 1)