#define unused __attribute__((unused))
+#ifdef DRC_DBG
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#endif
+
extern int cycle_count;
extern int last_count;
extern int pcaddr;
void jump_vaddr_r10();
void jump_vaddr_r12();
-const u_int jump_vaddr_reg[16] = {
- (int)jump_vaddr_r0,
- (int)jump_vaddr_r1,
- (int)jump_vaddr_r2,
- (int)jump_vaddr_r3,
- (int)jump_vaddr_r4,
- (int)jump_vaddr_r5,
- (int)jump_vaddr_r6,
- (int)jump_vaddr_r7,
- (int)jump_vaddr_r8,
- (int)jump_vaddr_r9,
- (int)jump_vaddr_r10,
+void * const jump_vaddr_reg[16] = {
+ jump_vaddr_r0,
+ jump_vaddr_r1,
+ jump_vaddr_r2,
+ jump_vaddr_r3,
+ jump_vaddr_r4,
+ jump_vaddr_r5,
+ jump_vaddr_r6,
+ jump_vaddr_r7,
+ jump_vaddr_r8,
+ jump_vaddr_r9,
+ jump_vaddr_r10,
0,
- (int)jump_vaddr_r12,
+ jump_vaddr_r12,
0,
0,
- 0};
+ 0
+};
void invalidate_addr_r0();
void invalidate_addr_r1();
/* Linker */
-static void set_jump_target(int addr,u_int target)
+static void set_jump_target(void *addr, void *target_)
{
- u_char *ptr=(u_char *)addr;
+ u_int target = (u_int)target_;
+ u_char *ptr = addr;
u_int *ptr2=(u_int *)ptr;
if(ptr[3]==0xe2) {
assert((target-(u_int)ptr2-8)<1024);
- assert((addr&3)==0);
+ assert(((uintptr_t)addr&3)==0);
assert((target&3)==0);
*ptr2=(*ptr2&0xFFFFF000)|((target-(u_int)ptr2-8)>>2)|0xF00;
- //printf("target=%x addr=%x insn=%x\n",target,addr,*ptr2);
+ //printf("target=%x addr=%p insn=%x\n",target,addr,*ptr2);
}
else if(ptr[3]==0x72) {
// generated by emit_jno_unlikely
if((target-(u_int)ptr2-8)<1024) {
- assert((addr&3)==0);
+ assert(((uintptr_t)addr&3)==0);
assert((target&3)==0);
*ptr2=(*ptr2&0xFFFFF000)|((target-(u_int)ptr2-8)>>2)|0xF00;
}
else if((target-(u_int)ptr2-8)<4096&&!((target-(u_int)ptr2-8)&15)) {
- assert((addr&3)==0);
+ assert(((uintptr_t)addr&3)==0);
assert((target&3)==0);
*ptr2=(*ptr2&0xFFFFF000)|((target-(u_int)ptr2-8)>>4)|0xE00;
}
// Find the "clean" entry point from a "dirty" entry point
// by skipping past the call to verify_code
-static u_int get_clean_addr(int addr)
+static void *get_clean_addr(void *addr)
{
- int *ptr=(int *)addr;
+ signed int *ptr = addr;
#ifndef HAVE_ARMV7
ptr+=4;
#else
assert((*ptr&0xFF000000)==0xeb000000); // bl instruction
ptr++;
if((*ptr&0xFF000000)==0xea000000) {
- return (int)ptr+((*ptr<<8)>>6)+8; // follow jump
+ return (char *)ptr+((*ptr<<8)>>6)+8; // follow jump
}
- return (u_int)ptr;
+ return ptr;
}
static int verify_dirty(u_int *ptr)
// This doesn't necessarily find all clean entry points, just
// guarantees that it's not dirty
-static int isclean(int addr)
+static int isclean(void *addr)
{
#ifndef HAVE_ARMV7
u_int *ptr=((u_int *)addr)+4;
emit_cmovb_imm(1,rt);
}
+#ifdef DRC_DBG
+extern void gen_interupt();
+extern void do_insn_cmp();
+#define FUNCNAME(f) { (intptr_t)f, " " #f }
+static const struct {
+ intptr_t addr;
+ const char *name;
+} function_names[] = {
+ FUNCNAME(cc_interrupt),
+ FUNCNAME(gen_interupt),
+ FUNCNAME(get_addr_ht),
+ FUNCNAME(get_addr),
+ FUNCNAME(jump_handler_read8),
+ FUNCNAME(jump_handler_read16),
+ FUNCNAME(jump_handler_read32),
+ FUNCNAME(jump_handler_write8),
+ 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),
+ FUNCNAME(new_dyna_leave),
+ FUNCNAME(pcsx_mtc0),
+ FUNCNAME(pcsx_mtc0_ds),
+ FUNCNAME(do_insn_cmp),
+};
+
+static const char *func_name(intptr_t a)
+{
+ int i;
+ for (i = 0; i < sizeof(function_names)/sizeof(function_names[0]); i++)
+ if (function_names[i].addr == a)
+ return function_names[i].name;
+ return "";
+}
+#else
+#define func_name(x) ""
+#endif
+
static void emit_call(int a)
{
- assem_debug("bl %x (%x+%x)\n",a,(int)out,a-(int)out-8);
+ assem_debug("bl %x (%x+%x)%s\n",a,(int)out,a-(int)out-8,func_name(a));
u_int offset=genjmp(a);
output_w32(0xeb000000|offset);
}
-static void emit_jmp(int a)
+static void emit_jmp(const void *a_)
{
- assem_debug("b %x (%x+%x)\n",a,(int)out,a-(int)out-8);
+ int a = (int)a_;
+ assem_debug("b %x (%x+%x)%s\n",a,(int)out,a-(int)out-8,func_name(a));
u_int offset=genjmp(a);
output_w32(0xea000000|offset);
}
output_w32(0x2a000000|offset);
}
-static void emit_jcc(int a)
+static void emit_jcc(void *a_)
{
+ int a = (int)a_;
assem_debug("bcc %x\n",a);
u_int offset=genjmp(a);
output_w32(0x3a000000|offset);
if(n) {
if((int)out-literals[0][0]<4096-n) return;
}
- int jaddr=(int)out;
+ void *jaddr = out;
emit_jmp(0);
literal_pool(0);
- set_jump_target(jaddr,(int)out);
+ set_jump_target(jaddr, out);
}
-static void emit_extjump2(u_int addr, int target, int linker)
+static void emit_extjump2(u_int addr, int target, void *linker)
{
u_char *ptr=(u_char *)addr;
assert((ptr[3]&0x0e)==0xa);
static void emit_extjump(int addr, int target)
{
- emit_extjump2(addr, target, (int)dyna_linker);
+ emit_extjump2(addr, target, dyna_linker);
}
static void emit_extjump_ds(int addr, int target)
{
- emit_extjump2(addr, target, (int)dyna_linker_ds);
+ emit_extjump2(addr, target, dyna_linker_ds);
}
// put rt_val into rt, potentially making use of rs with value rs_val
}
}
-static void mov_loadtype_adj(int type,int rs,int rt)
+static void mov_loadtype_adj(enum stub_type type,int rs,int rt)
{
switch(type) {
case LOADB_STUB: emit_signextend8(rs,rt); break;
static void do_readstub(int n)
{
- assem_debug("do_readstub %x\n",start+stubs[n][3]*4);
+ assem_debug("do_readstub %x\n",start+stubs[n].a*4);
literal_pool(256);
- set_jump_target(stubs[n][1],(int)out);
- int type=stubs[n][0];
- int i=stubs[n][3];
- int rs=stubs[n][4];
- struct regstat *i_regs=(struct regstat *)stubs[n][5];
- u_int reglist=stubs[n][7];
+ set_jump_target(stubs[n].addr, out);
+ enum stub_type type=stubs[n].type;
+ int i=stubs[n].a;
+ int rs=stubs[n].b;
+ struct regstat *i_regs=(struct regstat *)stubs[n].c;
+ u_int reglist=stubs[n].e;
signed char *i_regmap=i_regs->regmap;
int rt;
if(itype[i]==C1LS||itype[i]==C2LS||itype[i]==LOADLR) {
rt=get_reg(i_regmap,rt1[i]);
}
assert(rs>=0);
- int r,temp=-1,temp2=HOST_TEMPREG,regs_saved=0,restore_jump=0;
+ int r,temp=-1,temp2=HOST_TEMPREG,regs_saved=0;
+ void *restore_jump = NULL;
reglist|=(1<<rs);
for(r=0;r<=12;r++) {
if(((1<<r)&0x13ff)&&((1<<r)®list)==0) {
case LOADH_STUB: emit_ldrccsh_dualindexed(temp2,rs,rt); break;
case LOADHU_STUB: emit_ldrcch_dualindexed(temp2,rs,rt); break;
case LOADW_STUB: emit_ldrcc_dualindexed(temp2,rs,rt); break;
+ default: assert(0);
}
}
if(regs_saved) {
- restore_jump=(int)out;
+ restore_jump=out;
emit_jcc(0); // jump to reg restore
}
else
- emit_jcc(stubs[n][2]); // return address
+ emit_jcc(stubs[n].retaddr); // return address
if(!regs_saved)
save_regs(reglist);
int cc=get_reg(i_regmap,CCREG);
if(cc<0)
emit_loadreg(CCREG,2);
- emit_addimm(cc<0?2:cc,CLOCK_ADJUST((int)stubs[n][6]+1),2);
+ emit_addimm(cc<0?2:cc,CLOCK_ADJUST((int)stubs[n].d+1),2);
emit_call(handler);
if(itype[i]==C1LS||itype[i]==C2LS||(rt>=0&&rt1[i]!=0)) {
mov_loadtype_adj(type,0,rt);
}
if(restore_jump)
- set_jump_target(restore_jump,(int)out);
+ set_jump_target(restore_jump, out);
restore_regs(reglist);
- emit_jmp(stubs[n][2]); // return address
+ emit_jmp(stubs[n].retaddr); // return address
}
// return memhandler, or get directly accessable address and return 0
-static u_int get_direct_memhandler(void *table,u_int addr,int type,u_int *addr_host)
+static u_int get_direct_memhandler(void *table,u_int addr,enum stub_type type,u_int *addr_host)
{
u_int l1,l2=0;
l1=((u_int *)table)[addr>>12];
}
}
-static void inline_readstub(int type, int i, u_int addr, signed char regmap[], int target, int adj, u_int reglist)
+static void inline_readstub(enum stub_type type, int i, u_int addr, signed char regmap[], int target, int adj, u_int reglist)
{
int rs=get_reg(regmap,target);
int rt=get_reg(regmap,target);
static void do_writestub(int n)
{
- assem_debug("do_writestub %x\n",start+stubs[n][3]*4);
+ assem_debug("do_writestub %x\n",start+stubs[n].a*4);
literal_pool(256);
- set_jump_target(stubs[n][1],(int)out);
- int type=stubs[n][0];
- int i=stubs[n][3];
- int rs=stubs[n][4];
- struct regstat *i_regs=(struct regstat *)stubs[n][5];
- u_int reglist=stubs[n][7];
+ set_jump_target(stubs[n].addr, out);
+ enum stub_type type=stubs[n].type;
+ int i=stubs[n].a;
+ int rs=stubs[n].b;
+ struct regstat *i_regs=(struct regstat *)stubs[n].c;
+ u_int reglist=stubs[n].e;
signed char *i_regmap=i_regs->regmap;
int rt,r;
if(itype[i]==C1LS||itype[i]==C2LS) {
}
assert(rs>=0);
assert(rt>=0);
- int rtmp,temp=-1,temp2=HOST_TEMPREG,regs_saved=0,restore_jump=0,ra;
+ int rtmp,temp=-1,temp2=HOST_TEMPREG,regs_saved=0;
+ void *restore_jump = NULL;
int reglist2=reglist|(1<<rs)|(1<<rt);
for(rtmp=0;rtmp<=12;rtmp++) {
if(((1<<rtmp)&0x13ff)&&((1<<rtmp)®list2)==0) {
default: assert(0);
}
if(regs_saved) {
- restore_jump=(int)out;
+ restore_jump=out;
emit_jcc(0); // jump to reg restore
}
else
- emit_jcc(stubs[n][2]); // return address (invcode check)
+ emit_jcc(stubs[n].retaddr); // return address (invcode check)
if(!regs_saved)
save_regs(reglist);
case STOREB_STUB: handler=(int)jump_handler_write8; break;
case STOREH_STUB: handler=(int)jump_handler_write16; break;
case STOREW_STUB: handler=(int)jump_handler_write32; break;
+ default: assert(0);
}
assert(handler!=0);
pass_args(rs,rt);
int cc=get_reg(i_regmap,CCREG);
if(cc<0)
emit_loadreg(CCREG,2);
- emit_addimm(cc<0?2:cc,CLOCK_ADJUST((int)stubs[n][6]+1),2);
+ emit_addimm(cc<0?2:cc,CLOCK_ADJUST((int)stubs[n].d+1),2);
// returns new cycle_count
emit_call(handler);
- emit_addimm(0,-CLOCK_ADJUST((int)stubs[n][6]+1),cc<0?2:cc);
+ emit_addimm(0,-CLOCK_ADJUST((int)stubs[n].d+1),cc<0?2:cc);
if(cc<0)
emit_storereg(CCREG,2);
if(restore_jump)
- set_jump_target(restore_jump,(int)out);
+ set_jump_target(restore_jump, out);
restore_regs(reglist);
- ra=stubs[n][2];
- emit_jmp(ra);
+ emit_jmp(stubs[n].retaddr);
}
-static void inline_writestub(int type, int i, u_int addr, signed char regmap[], int target, int adj, u_int reglist)
+static void inline_writestub(enum stub_type type, int i, u_int addr, signed char regmap[], int target, int adj, u_int reglist)
{
int rs=get_reg(regmap,-1);
int rt=get_reg(regmap,target);
static void do_unalignedwritestub(int n)
{
- assem_debug("do_unalignedwritestub %x\n",start+stubs[n][3]*4);
+ assem_debug("do_unalignedwritestub %x\n",start+stubs[n].a*4);
literal_pool(256);
- set_jump_target(stubs[n][1],(int)out);
+ set_jump_target(stubs[n].addr, out);
- int i=stubs[n][3];
- struct regstat *i_regs=(struct regstat *)stubs[n][4];
- int addr=stubs[n][5];
- u_int reglist=stubs[n][7];
+ int i=stubs[n].a;
+ struct regstat *i_regs=(struct regstat *)stubs[n].c;
+ int addr=stubs[n].b;
+ u_int reglist=stubs[n].e;
signed char *i_regmap=i_regs->regmap;
int temp2=get_reg(i_regmap,FTEMP);
int rt;
int cc=get_reg(i_regmap,CCREG);
if(cc<0)
emit_loadreg(CCREG,2);
- emit_addimm(cc<0?2:cc,CLOCK_ADJUST((int)stubs[n][6]+1),2);
+ emit_addimm(cc<0?2:cc,CLOCK_ADJUST((int)stubs[n].d+1),2);
emit_call((int)(opcode[i]==0x2a?jump_handle_swl:jump_handle_swr));
- emit_addimm(0,-CLOCK_ADJUST((int)stubs[n][6]+1),cc<0?2:cc);
+ emit_addimm(0,-CLOCK_ADJUST((int)stubs[n].d+1),cc<0?2:cc);
if(cc<0)
emit_storereg(CCREG,2);
restore_regs(reglist);
- emit_jmp(stubs[n][2]); // return address
+ emit_jmp(stubs[n].retaddr); // return address
#else
emit_andimm(addr,0xfffffffc,temp2);
emit_writeword(temp2,(int)&address);
emit_loadreg(CCREG,2);
}
emit_movimm((u_int)readmem,0);
- emit_addimm(cc<0?2:cc,2*stubs[n][6]+2,2);
+ emit_addimm(cc<0?2:cc,2*stubs[n].d+2,2);
emit_call((int)&indirect_jump_indexed);
restore_regs(reglist);
emit_readword_dualindexedx4(0,1,15);
emit_readword((int)&Count,HOST_TEMPREG);
emit_readword((int)&next_interupt,2);
- emit_addimm(HOST_TEMPREG,-2*stubs[n][6]-2,HOST_TEMPREG);
+ emit_addimm(HOST_TEMPREG,-2*stubs[n].d-2,HOST_TEMPREG);
emit_writeword(2,(int)&last_count);
emit_sub(HOST_TEMPREG,2,cc<0?HOST_TEMPREG:cc);
if(cc<0) {
emit_storereg(CCREG,HOST_TEMPREG);
}
restore_regs(reglist);
- emit_jmp(stubs[n][2]); // return address
+ emit_jmp(stubs[n].retaddr); // return address
#endif
}
static void do_invstub(int n)
{
literal_pool(20);
- u_int reglist=stubs[n][3];
- set_jump_target(stubs[n][1],(int)out);
+ u_int reglist=stubs[n].a;
+ set_jump_target(stubs[n].addr, out);
save_regs(reglist);
- if(stubs[n][4]!=0) emit_mov(stubs[n][4],0);
+ if(stubs[n].b!=0) emit_mov(stubs[n].b,0);
emit_call((int)&invalidate_addr);
restore_regs(reglist);
- emit_jmp(stubs[n][2]); // return address
+ emit_jmp(stubs[n].retaddr); // return address
}
-int do_dirty_stub(int i)
+void *do_dirty_stub(int i)
{
assem_debug("do_dirty_stub %x\n",start+i*4);
u_int addr=(u_int)source;
#endif
emit_movimm(start+i*4,0);
emit_call((int)start<(int)0xC0000000?(int)&verify_code:(int)&verify_code_vm);
- int entry=(int)out;
+ void *entry = out;
load_regs_entry(i);
- if(entry==(int)out) entry=instr_addr[i];
+ if (entry == out)
+ entry = instr_addr[i];
emit_jmp(instr_addr[i]);
return entry;
}
static void do_cop1stub(int n)
{
literal_pool(256);
- 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];
- struct regstat *i_regs=(struct regstat *)stubs[n][5];
- int ds=stubs[n][6];
+ assem_debug("do_cop1stub %x\n",start+stubs[n].a*4);
+ set_jump_target(stubs[n].addr, out);
+ int i=stubs[n].a;
+// int rs=stubs[n].b;
+ struct regstat *i_regs=(struct regstat *)stubs[n].c;
+ int ds=stubs[n].d;
if(!ds) {
load_all_consts(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty,i);
//if(i_regs!=®s[i]) printf("oops: regs[i]=%x i_regs=%x",(int)®s[i],(int)i_regs);
if(regs[i].regmap_entry[HOST_CCREG]!=CCREG) emit_loadreg(CCREG,HOST_CCREG);
emit_movimm(start+(i-ds)*4,EAX); // Get PC
emit_addimm(HOST_CCREG,CLOCK_ADJUST(ccadj[i]),HOST_CCREG); // CHECK: is this right? There should probably be an extra cycle...
- emit_jmp(ds?(int)fp_exception_ds:(int)fp_exception);
+ emit_jmp(ds?fp_exception_ds:fp_exception);
}
/* Special assem */
return MTYPE_8000;
}
-static int emit_fastpath_cmp_jump(int i,int addr,int *addr_reg_override)
+static void *emit_fastpath_cmp_jump(int i,int addr,int *addr_reg_override)
{
- int jaddr=0,type=0;
+ void *jaddr = NULL;
+ int type=0;
int mr=rs1[i];
if(((smrv_strong|smrv_weak)>>mr)&1) {
type=get_ptr_mem_type(smrv[mr]);
if (psxH == (void *)0x1f800000) {
emit_addimm(addr,-0x1f800000,HOST_TEMPREG);
emit_cmpimm(HOST_TEMPREG,0x1000);
- jaddr=(int)out;
+ jaddr=out;
emit_jc(0);
}
else {
if(type==0)
{
emit_cmpimm(addr,RAM_SIZE);
- jaddr=(int)out;
+ jaddr=out;
#ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
// Hint to branch predictor that the branch is unlikely to be taken
if(rs1[i]>=28)
{
int s,th,tl,temp,temp2,addr,map=-1;
int offset;
- int jaddr=0;
+ void *jaddr=0;
int memtarget=0,c=0;
int fastload_reg_override=0;
u_int hr,reglist=0;
if(fastload_reg_override) a=fastload_reg_override;
//emit_readword_indexed((int)rdram-0x80000000,temp2,temp2);
emit_readword_indexed_tlb(0,a,map,temp2);
- if(jaddr) add_stub(LOADW_STUB,jaddr,(int)out,i,temp2,(int)i_regs,ccadj[i],reglist);
+ if(jaddr) add_stub_r(LOADW_STUB,jaddr,out,i,temp2,i_regs,ccadj[i],reglist);
}
else
inline_readstub(LOADW_STUB,i,(constmap[i][s]+offset)&0xFFFFFFFC,i_regs->regmap,FTEMP,ccadj[i],reglist);
//if(th>=0) emit_readword_indexed((int)rdram-0x80000000,temp2,temp2h);
//emit_readword_indexed((int)rdram-0x7FFFFFFC,temp2,temp2);
emit_readdword_indexed_tlb(0,temp2,map,temp2h,temp2);
- if(jaddr) add_stub(LOADD_STUB,jaddr,(int)out,i,temp2,(int)i_regs,ccadj[i],reglist);
+ if(jaddr) add_stub_r(LOADD_STUB,jaddr,out,i,temp2,i_regs,ccadj[i],reglist);
}
else
inline_readstub(LOADD_STUB,i,(constmap[i][s]+offset)&0xFFFFFFF8,i_regs->regmap,FTEMP,ccadj[i],reglist);
{
// XXX: should just just do the exception instead
if(!cop1_usable) {
- int jaddr=(int)out;
+ void *jaddr=out;
emit_jmp(0);
- add_stub(FP_STUB,jaddr,(int)out,i,0,(int)i_regs,is_delayslot,0);
+ add_stub_r(FP_STUB,jaddr,out,i,0,i_regs,is_delayslot,0);
cop1_usable=1;
}
}
emit_subcs(remainder,HOST_TEMPREG,remainder);
emit_adcs(quotient,quotient,quotient);
emit_shrimm(HOST_TEMPREG,1,HOST_TEMPREG);
- emit_jcc((int)out-16); // -4
+ emit_jcc(out-16); // -4
emit_teq(d1,d2);
emit_negmi(quotient,quotient);
emit_test(d1,d1);
emit_subcs(remainder,d2,remainder);
emit_adcs(quotient,quotient,quotient);
emit_shrcc_imm(d2,1,d2);
- emit_jcc((int)out-16); // -4
+ emit_jcc(out-16); // -4
}
}
else // 64-bit