#endif
#include "new_dynarec_config.h"
+#include "../psxhle.h" //emulator interface
#include "emu_if.h" //emulator interface
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+#endif
+
//#define DISASM
//#define assem_debug printf
//#define inv_debug printf
#define MAXBLOCK 4096
#define MAX_OUTPUT_BLOCK_SIZE 262144
+// stubs
+enum stub_type {
+ CC_STUB = 1,
+ FP_STUB = 2,
+ LOADB_STUB = 3,
+ LOADH_STUB = 4,
+ LOADW_STUB = 5,
+ LOADD_STUB = 6,
+ LOADBU_STUB = 7,
+ LOADHU_STUB = 8,
+ STOREB_STUB = 9,
+ STOREH_STUB = 10,
+ STOREW_STUB = 11,
+ STORED_STUB = 12,
+ STORELR_STUB = 13,
+ INVCODE_STUB = 14,
+};
+
struct regstat
{
signed char regmap_entry[HOST_REGS];
struct ll_entry *next;
};
+struct ht_entry
+{
+ u_int vaddr[2];
+ void *tcaddr[2];
+};
+
+struct code_stub
+{
+ enum stub_type type;
+ void *addr;
+ void *retaddr;
+ u_int a;
+ uintptr_t b;
+ uintptr_t c;
+ u_int d;
+ u_int e;
+};
+
// used by asm:
u_char *out;
- u_int hash_table[65536][4] __attribute__((aligned(16)));
+ struct ht_entry hash_table[65536] __attribute__((aligned(16)));
struct ll_entry *jump_in[4096] __attribute__((aligned(16)));
struct ll_entry *jump_dirty[4096];
static u_int will_dirty[MAXBLOCK];
static int ccadj[MAXBLOCK];
static int slen;
- static u_int instr_addr[MAXBLOCK];
+ static void *instr_addr[MAXBLOCK];
static u_int link_addr[MAXBLOCK][3];
static int linkcount;
- static u_int stubs[MAXBLOCK*3][8];
+ static struct code_stub stubs[MAXBLOCK*3];
static int stubcount;
static u_int literals[1024][2];
static int literalcount;
#define C2OP 29 // Coprocessor 2 operation
#define INTCALL 30// Call interpreter to handle rare corner cases
- /* stubs */
-#define CC_STUB 1
-#define FP_STUB 2
-#define LOADB_STUB 3
-#define LOADH_STUB 4
-#define LOADW_STUB 5
-#define LOADD_STUB 6
-#define LOADBU_STUB 7
-#define LOADHU_STUB 8
-#define STOREB_STUB 9
-#define STOREH_STUB 10
-#define STOREW_STUB 11
-#define STORED_STUB 12
-#define STORELR_STUB 13
-#define INVCODE_STUB 14
-
/* branch codes */
#define TAKEN 1
#define NOTTAKEN 2
static int verify_dirty(u_int *ptr);
static int get_final_value(int hr, int i, int *value);
-static void add_stub(int type,int addr,int retaddr,int a,int b,int c,int d,int e);
+static void add_stub(enum stub_type type, void *addr, void *retaddr,
+ u_int a, uintptr_t b, uintptr_t c, u_int d, u_int e);
+static void add_stub_r(enum stub_type type, void *addr, void *retaddr,
+ int i, int addr_reg, struct regstat *i_regs, int ccadj, u_int reglist);
static void add_to_linker(int addr,int target,int ext);
static int tracedebug=0;
return get_page(vaddr);
}
+static struct ht_entry *hash_table_get(u_int vaddr)
+{
+ return &hash_table[((vaddr>>16)^vaddr)&0xFFFF];
+}
+
+static void hash_table_add(struct ht_entry *ht_bin, u_int vaddr, void *tcaddr)
+{
+ ht_bin->vaddr[1] = ht_bin->vaddr[0];
+ ht_bin->tcaddr[1] = ht_bin->tcaddr[0];
+ ht_bin->vaddr[0] = vaddr;
+ ht_bin->tcaddr[0] = tcaddr;
+}
+
+// some messy ari64's code, seems to rely on unsigned 32bit overflow
+static int doesnt_expire_soon(void *tcaddr)
+{
+ u_int diff = (u_int)((u_char *)tcaddr - out) << (32-TARGET_SIZE_2);
+ return diff > (u_int)(0x60000000 + (MAX_OUTPUT_BLOCK_SIZE << (32-TARGET_SIZE_2)));
+}
+
// Get address from virtual address
// This is called from the recompiled JR/JALR instructions
void *get_addr(u_int vaddr)
while(head!=NULL) {
if(head->vaddr==vaddr) {
//printf("TRACE: count=%d next=%d (get_addr match %x: %x)\n",Count,next_interupt,vaddr,(int)head->addr);
- u_int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF];
- ht_bin[3]=ht_bin[1];
- ht_bin[2]=ht_bin[0];
- ht_bin[1]=(u_int)head->addr;
- ht_bin[0]=vaddr;
+ hash_table_add(hash_table_get(vaddr), vaddr, head->addr);
return head->addr;
}
head=head->next;
if(head->vaddr==vaddr) {
//printf("TRACE: count=%d next=%d (get_addr match dirty %x: %x)\n",Count,next_interupt,vaddr,(int)head->addr);
// Don't restore blocks which are about to expire from the cache
- if((((u_int)head->addr-(u_int)out)<<(32-TARGET_SIZE_2))>0x60000000+(MAX_OUTPUT_BLOCK_SIZE<<(32-TARGET_SIZE_2)))
- if(verify_dirty(head->addr)) {
+ if (doesnt_expire_soon(head->addr))
+ if (verify_dirty(head->addr)) {
//printf("restore candidate: %x (%d) d=%d\n",vaddr,page,invalid_code[vaddr>>12]);
invalid_code[vaddr>>12]=0;
inv_code_start=inv_code_end=~0;
restore_candidate[vpage>>3]|=1<<(vpage&7);
}
else restore_candidate[page>>3]|=1<<(page&7);
- u_int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF];
- if(ht_bin[0]==vaddr) {
- ht_bin[1]=(u_int)head->addr; // Replace existing entry
- }
+ struct ht_entry *ht_bin = hash_table_get(vaddr);
+ if (ht_bin->vaddr[0] == vaddr)
+ ht_bin->tcaddr[0] = head->addr; // Replace existing entry
else
- {
- ht_bin[3]=ht_bin[1];
- ht_bin[2]=ht_bin[0];
- ht_bin[1]=(int)head->addr;
- ht_bin[0]=vaddr;
- }
+ hash_table_add(ht_bin, vaddr, head->addr);
+
return head->addr;
}
}
void *get_addr_ht(u_int vaddr)
{
//printf("TRACE: count=%d next=%d (get_addr_ht %x)\n",Count,next_interupt,vaddr);
- u_int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF];
- if(ht_bin[0]==vaddr) return (void *)ht_bin[1];
- if(ht_bin[2]==vaddr) return (void *)ht_bin[3];
+ const struct ht_entry *ht_bin = hash_table_get(vaddr);
+ if (ht_bin->vaddr[0] == vaddr) return ht_bin->tcaddr[0];
+ if (ht_bin->vaddr[1] == vaddr) return ht_bin->tcaddr[1];
return get_addr(vaddr);
}
// but don't return addresses which are about to expire from the cache
void *check_addr(u_int vaddr)
{
- u_int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF];
- if(ht_bin[0]==vaddr) {
- if(((ht_bin[1]-MAX_OUTPUT_BLOCK_SIZE-(u_int)out)<<(32-TARGET_SIZE_2))>0x60000000+(MAX_OUTPUT_BLOCK_SIZE<<(32-TARGET_SIZE_2)))
- if(isclean(ht_bin[1])) return (void *)ht_bin[1];
- }
- if(ht_bin[2]==vaddr) {
- if(((ht_bin[3]-MAX_OUTPUT_BLOCK_SIZE-(u_int)out)<<(32-TARGET_SIZE_2))>0x60000000+(MAX_OUTPUT_BLOCK_SIZE<<(32-TARGET_SIZE_2)))
- if(isclean(ht_bin[3])) return (void *)ht_bin[3];
+ struct ht_entry *ht_bin = hash_table_get(vaddr);
+ size_t i;
+ for (i = 0; i < ARRAY_SIZE(ht_bin->vaddr); i++) {
+ if (ht_bin->vaddr[i] == vaddr)
+ if (doesnt_expire_soon((u_char *)ht_bin->tcaddr[i] - MAX_OUTPUT_BLOCK_SIZE))
+ if (isclean(ht_bin->tcaddr[i]))
+ return ht_bin->tcaddr[i];
}
u_int page=get_page(vaddr);
struct ll_entry *head;
head=jump_in[page];
- while(head!=NULL) {
- if(head->vaddr==vaddr) {
- if((((u_int)head->addr-(u_int)out)<<(32-TARGET_SIZE_2))>0x60000000+(MAX_OUTPUT_BLOCK_SIZE<<(32-TARGET_SIZE_2))) {
+ while (head != NULL) {
+ if (head->vaddr == vaddr) {
+ if (doesnt_expire_soon(head->addr)) {
// Update existing entry with current address
- if(ht_bin[0]==vaddr) {
- ht_bin[1]=(int)head->addr;
+ if (ht_bin->vaddr[0] == vaddr) {
+ ht_bin->tcaddr[0] = head->addr;
return head->addr;
}
- if(ht_bin[2]==vaddr) {
- ht_bin[3]=(int)head->addr;
+ if (ht_bin->vaddr[1] == vaddr) {
+ ht_bin->tcaddr[1] = head->addr;
return head->addr;
}
// Insert into hash table with low priority.
// Don't evict existing entries, as they are probably
// addresses that are being accessed frequently.
- if(ht_bin[0]==-1) {
- ht_bin[1]=(int)head->addr;
- ht_bin[0]=vaddr;
- }else if(ht_bin[2]==-1) {
- ht_bin[3]=(int)head->addr;
- ht_bin[2]=vaddr;
+ if (ht_bin->vaddr[0] == -1) {
+ ht_bin->vaddr[0] = vaddr;
+ ht_bin->tcaddr[0] = head->addr;
+ }
+ else if (ht_bin->vaddr[1] == -1) {
+ ht_bin->vaddr[1] = vaddr;
+ ht_bin->tcaddr[1] = head->addr;
}
return head->addr;
}
void remove_hash(int vaddr)
{
//printf("remove hash: %x\n",vaddr);
- u_int *ht_bin=hash_table[(((vaddr)>>16)^vaddr)&0xFFFF];
- if(ht_bin[2]==vaddr) {
- ht_bin[2]=ht_bin[3]=-1;
+ struct ht_entry *ht_bin = hash_table_get(vaddr);
+ if (ht_bin->vaddr[1] == vaddr) {
+ ht_bin->vaddr[1] = -1;
+ ht_bin->tcaddr[1] = NULL;
}
- if(ht_bin[0]==vaddr) {
- ht_bin[0]=ht_bin[2];
- ht_bin[1]=ht_bin[3];
- ht_bin[2]=ht_bin[3]=-1;
+ if (ht_bin->vaddr[0] == vaddr) {
+ ht_bin->vaddr[0] = ht_bin->vaddr[1];
+ ht_bin->tcaddr[0] = ht_bin->tcaddr[1];
+ ht_bin->vaddr[1] = -1;
+ ht_bin->tcaddr[1] = NULL;
}
}
#ifdef __arm__
mark_clear_cache(host_addr);
#endif
- set_jump_target((int)host_addr,(int)head->addr);
+ set_jump_target(host_addr, head->addr);
}
head=head->next;
}
#ifdef __arm__
mark_clear_cache(host_addr);
#endif
- set_jump_target((int)host_addr,(int)head->addr);
+ set_jump_target(host_addr, head->addr);
next=head->next;
free(head);
head=next;
while(head!=NULL) {
if(!invalid_code[head->vaddr>>12]) {
// Don't restore blocks which are about to expire from the cache
- if((((u_int)head->addr-(u_int)out)<<(32-TARGET_SIZE_2))>0x60000000+(MAX_OUTPUT_BLOCK_SIZE<<(32-TARGET_SIZE_2))) {
+ if (doesnt_expire_soon(head->addr)) {
u_int start,end;
if(verify_dirty(head->addr)) {
//printf("Possibly Restore %x (%x)\n",head->vaddr, (int)head->addr);
inv=1;
}
if(!inv) {
- void * clean_addr=(void *)get_clean_addr((int)head->addr);
- if((((u_int)clean_addr-(u_int)out)<<(32-TARGET_SIZE_2))>0x60000000+(MAX_OUTPUT_BLOCK_SIZE<<(32-TARGET_SIZE_2))) {
+ void *clean_addr = get_clean_addr(head->addr);
+ if (doesnt_expire_soon(clean_addr)) {
u_int ppage=page;
inv_debug("INV: Restored %x (%x/%x)\n",head->vaddr, (int)head->addr, (int)clean_addr);
//printf("page=%x, addr=%x\n",page,head->vaddr);
//assert(head->vaddr>>12==(page|0x80000));
ll_add_flags(jump_in+ppage,head->vaddr,head->reg_sv_flags,clean_addr);
- u_int *ht_bin=hash_table[((head->vaddr>>16)^head->vaddr)&0xFFFF];
- if(ht_bin[0]==head->vaddr) {
- ht_bin[1]=(u_int)clean_addr; // Replace existing entry
- }
- if(ht_bin[2]==head->vaddr) {
- ht_bin[3]=(u_int)clean_addr; // Replace existing entry
- }
+ struct ht_entry *ht_bin = hash_table_get(head->vaddr);
+ if (ht_bin->vaddr[0] == head->vaddr)
+ ht_bin->tcaddr[0] = clean_addr; // Replace existing entry
+ if (ht_bin->vaddr[1] == head->vaddr)
+ ht_bin->tcaddr[1] = clean_addr; // Replace existing entry
}
}
}
//else ...
}
-static void add_stub(int type,int addr,int retaddr,int a,int b,int c,int d,int e)
+static void add_stub(enum stub_type type, void *addr, void *retaddr,
+ u_int a, uintptr_t b, uintptr_t c, u_int d, u_int e)
{
- stubs[stubcount][0]=type;
- stubs[stubcount][1]=addr;
- stubs[stubcount][2]=retaddr;
- stubs[stubcount][3]=a;
- stubs[stubcount][4]=b;
- stubs[stubcount][5]=c;
- stubs[stubcount][6]=d;
- stubs[stubcount][7]=e;
+ assert(a < ARRAY_SIZE(stubs));
+ stubs[stubcount].type = type;
+ stubs[stubcount].addr = addr;
+ stubs[stubcount].retaddr = retaddr;
+ stubs[stubcount].a = a;
+ stubs[stubcount].b = b;
+ stubs[stubcount].c = c;
+ stubs[stubcount].d = d;
+ stubs[stubcount].e = e;
stubcount++;
}
+static void add_stub_r(enum stub_type type, void *addr, void *retaddr,
+ int i, int addr_reg, struct regstat *i_regs, int ccadj, u_int reglist)
+{
+ add_stub(type, addr, retaddr, i, addr_reg, (uintptr_t)i_regs, ccadj, reglist);
+}
+
// Write out a single register
void wb_register(signed char r,signed char regmap[],uint64_t dirty,uint64_t is32)
{
int mchecksum()
{
- //if(!tracedebug) return 0;
int i;
int sum=0;
for(i=0;i<2097152;i++) {
printf("\n");
}
-void enabletrace()
-{
- tracedebug=1;
-}
-
-void memdebug(int i)
-{
- //printf("TRACE: count=%d next=%d (checksum %x) lo=%8x%8x\n",Count,next_interupt,mchecksum(),(int)(reg[LOREG]>>32),(int)reg[LOREG]);
- //printf("TRACE: count=%d next=%d (rchecksum %x)\n",Count,next_interupt,rchecksum());
- //rlist();
- //if(tracedebug) {
- //if(Count>=-2084597794) {
- if((signed int)Count>=-2084597794&&(signed int)Count<0) {
- //if(0) {
- printf("TRACE: count=%d next=%d (checksum %x)\n",Count,next_interupt,mchecksum());
- //printf("TRACE: count=%d next=%d (checksum %x) Status=%x\n",Count,next_interupt,mchecksum(),Status);
- //printf("TRACE: count=%d next=%d (checksum %x) hi=%8x%8x\n",Count,next_interupt,mchecksum(),(int)(reg[HIREG]>>32),(int)reg[HIREG]);
- rlist();
- #ifdef __i386__
- printf("TRACE: %x\n",(&i)[-1]);
- #endif
- #ifdef __arm__
- int j;
- printf("TRACE: %x \n",(&j)[10]);
- printf("TRACE: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n",(&j)[1],(&j)[2],(&j)[3],(&j)[4],(&j)[5],(&j)[6],(&j)[7],(&j)[8],(&j)[9],(&j)[10],(&j)[11],(&j)[12],(&j)[13],(&j)[14],(&j)[15],(&j)[16],(&j)[17],(&j)[18],(&j)[19],(&j)[20]);
- #endif
- //fflush(stdout);
- }
- //printf("TRACE: %x\n",(&i)[-1]);
-}
-
void alu_assemble(int i,struct regstat *i_regs)
{
if(opcode2[i]>=0x20&&opcode2[i]<=0x23) { // ADD/ADDU/SUB/SUBU
{
int s,th,tl,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(jaddr)
- add_stub(LOADB_STUB,jaddr,(int)out,i,addr,(int)i_regs,ccadj[i],reglist);
+ add_stub_r(LOADB_STUB,jaddr,out,i,addr,i_regs,ccadj[i],reglist);
}
else
inline_readstub(LOADB_STUB,i,constmap[i][s]+offset,i_regs->regmap,rt1[i],ccadj[i],reglist);
}
}
if(jaddr)
- add_stub(LOADH_STUB,jaddr,(int)out,i,addr,(int)i_regs,ccadj[i],reglist);
+ add_stub_r(LOADH_STUB,jaddr,out,i,addr,i_regs,ccadj[i],reglist);
}
else
inline_readstub(LOADH_STUB,i,constmap[i][s]+offset,i_regs->regmap,rt1[i],ccadj[i],reglist);
emit_readword_indexed_tlb(0,a,map,tl);
}
if(jaddr)
- add_stub(LOADW_STUB,jaddr,(int)out,i,addr,(int)i_regs,ccadj[i],reglist);
+ 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);
}
}
if(jaddr)
- add_stub(LOADBU_STUB,jaddr,(int)out,i,addr,(int)i_regs,ccadj[i],reglist);
+ add_stub_r(LOADBU_STUB,jaddr,out,i,addr,i_regs,ccadj[i],reglist);
}
else
inline_readstub(LOADBU_STUB,i,constmap[i][s]+offset,i_regs->regmap,rt1[i],ccadj[i],reglist);
}
}
if(jaddr)
- add_stub(LOADHU_STUB,jaddr,(int)out,i,addr,(int)i_regs,ccadj[i],reglist);
+ add_stub_r(LOADHU_STUB,jaddr,out,i,addr,i_regs,ccadj[i],reglist);
}
else
inline_readstub(LOADHU_STUB,i,constmap[i][s]+offset,i_regs->regmap,rt1[i],ccadj[i],reglist);
emit_readword_indexed_tlb(0,a,map,tl);
}
if(jaddr)
- add_stub(LOADW_STUB,jaddr,(int)out,i,addr,(int)i_regs,ccadj[i],reglist);
+ 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_readdword_indexed_tlb(0,a,map,th,tl);
}
if(jaddr)
- add_stub(LOADD_STUB,jaddr,(int)out,i,addr,(int)i_regs,ccadj[i],reglist);
+ add_stub_r(LOADD_STUB,jaddr,out,i,addr,i_regs,ccadj[i],reglist);
}
else
inline_readstub(LOADD_STUB,i,constmap[i][s]+offset,i_regs->regmap,rt1[i],ccadj[i],reglist);
}
}
- //emit_storereg(rt1[i],tl); // DEBUG
- //if(opcode[i]==0x23)
- //if(opcode[i]==0x24)
- //if(opcode[i]==0x23||opcode[i]==0x24)
- /*if(opcode[i]==0x21||opcode[i]==0x23||opcode[i]==0x24)
- {
- //emit_pusha();
- save_regs(0x100f);
- emit_readword((int)&last_count,ECX);
- #ifdef __i386__
- if(get_reg(i_regs->regmap,CCREG)<0)
- emit_loadreg(CCREG,HOST_CCREG);
- emit_add(HOST_CCREG,ECX,HOST_CCREG);
- emit_addimm(HOST_CCREG,2*ccadj[i],HOST_CCREG);
- emit_writeword(HOST_CCREG,(int)&Count);
- #endif
- #ifdef __arm__
- if(get_reg(i_regs->regmap,CCREG)<0)
- emit_loadreg(CCREG,0);
- else
- emit_mov(HOST_CCREG,0);
- emit_add(0,ECX,0);
- emit_addimm(0,2*ccadj[i],0);
- emit_writeword(0,(int)&Count);
- #endif
- emit_call((int)memdebug);
- //emit_popa();
- restore_regs(0x100f);
- }*/
}
#ifndef loadlr_assemble
int s,th,tl,map=-1;
int addr,temp;
int offset;
- int jaddr=0,type;
+ void *jaddr=0;
+ enum stub_type type;
int memtarget=0,c=0;
int agr=AGEN1+(i&1);
int faststore_reg_override=0;
if(jaddr) {
// PCSX store handlers don't check invcode again
reglist|=1<<addr;
- add_stub(type,jaddr,(int)out,i,addr,(int)i_regs,ccadj[i],reglist);
+ add_stub_r(type,jaddr,out,i,addr,i_regs,ccadj[i],reglist);
jaddr=0;
}
if(!(i_regs->waswritten&(1<<rs1[i]))&&!(new_dynarec_hacks&NDHACK_NO_SMC_CHECK)) {
#if defined(HAVE_CONDITIONAL_CALL) && !defined(DESTRUCTIVE_SHIFT)
emit_callne(invalidate_addr_reg[addr]);
#else
- int jaddr2=(int)out;
+ void *jaddr2 = out;
emit_jne(0);
- add_stub(INVCODE_STUB,jaddr2,(int)out,reglist|(1<<HOST_CCREG),addr,0,0,0);
+ add_stub(INVCODE_STUB,jaddr2,out,reglist|(1<<HOST_CCREG),addr,0,0,0);
#endif
}
}
u_int addr_val=constmap[i][s]+offset;
if(jaddr) {
- add_stub(type,jaddr,(int)out,i,addr,(int)i_regs,ccadj[i],reglist);
+ add_stub_r(type,jaddr,out,i,addr,i_regs,ccadj[i],reglist);
} else if(c&&!memtarget) {
inline_writestub(type,i,addr_val,i_regs->regmap,rs2[i],ccadj[i],reglist);
}
wb_dirtys(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty);
emit_movimm(start+i*4+4,0);
emit_writeword(0,(int)&pcaddr);
- emit_jmp((int)do_interrupt);
+ emit_jmp(do_interrupt);
}
}
- //if(opcode[i]==0x2B || opcode[i]==0x3F)
- //if(opcode[i]==0x2B || opcode[i]==0x28)
- //if(opcode[i]==0x2B || opcode[i]==0x29)
- //if(opcode[i]==0x2B)
- /*if(opcode[i]==0x2B || opcode[i]==0x28 || opcode[i]==0x29 || opcode[i]==0x3F)
- {
- #ifdef __i386__
- emit_pusha();
- #endif
- #ifdef __arm__
- save_regs(0x100f);
- #endif
- emit_readword((int)&last_count,ECX);
- #ifdef __i386__
- if(get_reg(i_regs->regmap,CCREG)<0)
- emit_loadreg(CCREG,HOST_CCREG);
- emit_add(HOST_CCREG,ECX,HOST_CCREG);
- emit_addimm(HOST_CCREG,2*ccadj[i],HOST_CCREG);
- emit_writeword(HOST_CCREG,(int)&Count);
- #endif
- #ifdef __arm__
- if(get_reg(i_regs->regmap,CCREG)<0)
- emit_loadreg(CCREG,0);
- else
- emit_mov(HOST_CCREG,0);
- emit_add(0,ECX,0);
- emit_addimm(0,2*ccadj[i],0);
- emit_writeword(0,(int)&Count);
- #endif
- emit_call((int)memdebug);
- #ifdef __i386__
- emit_popa();
- #endif
- #ifdef __arm__
- restore_regs(0x100f);
- #endif
- }*/
}
void storelr_assemble(int i,struct regstat *i_regs)
int temp;
int temp2=-1;
int offset;
- int jaddr=0;
- int case1,case2,case3;
- int done0,done1,done2;
+ void *jaddr=0;
+ void *case1, *case2, *case3;
+ void *done0, *done1, *done2;
int memtarget=0,c=0;
int agr=AGEN1+(i&1);
u_int hr,reglist=0;
if(!c) {
emit_cmpimm(s<0||offset?temp:s,RAM_SIZE);
if(!offset&&s!=temp) emit_mov(s,temp);
- jaddr=(int)out;
+ jaddr=out;
emit_jno(0);
}
else
{
if(!memtarget||!rs1[i]) {
- jaddr=(int)out;
+ jaddr=out;
emit_jmp(0);
}
}
emit_xorimm(temp,3,temp);
#endif
emit_testimm(temp,2);
- case2=(int)out;
+ case2=out;
emit_jne(0);
emit_testimm(temp,1);
- case1=(int)out;
+ case1=out;
emit_jne(0);
// 0
if (opcode[i]==0x2A) { // SWL
emit_writebyte_indexed(tl,3,temp);
if(rs2[i]) emit_shldimm(th,tl,24,temp2);
}
- done0=(int)out;
+ done0=out;
emit_jmp(0);
// 1
- set_jump_target(case1,(int)out);
+ set_jump_target(case1, out);
if (opcode[i]==0x2A) { // SWL
// Write 3 msb into three least significant bytes
if(rs2[i]) emit_rorimm(tl,8,tl);
// Write two lsb into two most significant bytes
emit_writehword_indexed(tl,1,temp);
}
- done1=(int)out;
+ done1=out;
emit_jmp(0);
// 2
- set_jump_target(case2,(int)out);
+ set_jump_target(case2, out);
emit_testimm(temp,1);
- case3=(int)out;
+ case3=out;
emit_jne(0);
if (opcode[i]==0x2A) { // SWL
// Write two msb into two least significant bytes
emit_writehword_indexed(tl,0,temp);
if(rs2[i]) emit_rorimm(tl,24,tl);
}
- done2=(int)out;
+ done2=out;
emit_jmp(0);
// 3
- set_jump_target(case3,(int)out);
+ set_jump_target(case3, out);
if (opcode[i]==0x2A) { // SWL
// Write msb into least significant byte
if(rs2[i]) emit_rorimm(tl,24,tl);
// Write entire word
emit_writeword_indexed(tl,-3,temp);
}
- set_jump_target(done0,(int)out);
- set_jump_target(done1,(int)out);
- set_jump_target(done2,(int)out);
+ set_jump_target(done0, out);
+ set_jump_target(done1, out);
+ set_jump_target(done2, out);
if (opcode[i]==0x2C) { // SDL
emit_testimm(temp,4);
- done0=(int)out;
+ done0=out;
emit_jne(0);
emit_andimm(temp,~3,temp);
emit_writeword_indexed(temp2,4,temp);
- set_jump_target(done0,(int)out);
+ set_jump_target(done0, out);
}
if (opcode[i]==0x2D) { // SDR
emit_testimm(temp,4);
- done0=(int)out;
+ done0=out;
emit_jeq(0);
emit_andimm(temp,~3,temp);
emit_writeword_indexed(temp2,-4,temp);
- set_jump_target(done0,(int)out);
+ set_jump_target(done0, out);
}
if(!c||!memtarget)
- add_stub(STORELR_STUB,jaddr,(int)out,i,(int)i_regs,temp,ccadj[i],reglist);
+ add_stub_r(STORELR_STUB,jaddr,out,i,temp,i_regs,ccadj[i],reglist);
if(!(i_regs->waswritten&(1<<rs1[i]))&&!(new_dynarec_hacks&NDHACK_NO_SMC_CHECK)) {
#ifdef RAM_OFFSET
int map=get_reg(i_regs->regmap,ROREG);
#if defined(HAVE_CONDITIONAL_CALL) && !defined(DESTRUCTIVE_SHIFT)
emit_callne(invalidate_addr_reg[temp]);
#else
- int jaddr2=(int)out;
+ void *jaddr2 = out;
emit_jne(0);
- add_stub(INVCODE_STUB,jaddr2,(int)out,reglist|(1<<HOST_CCREG),temp,0,0,0);
+ add_stub(INVCODE_STUB,jaddr2,out,reglist|(1<<HOST_CCREG),temp,0,0,0);
#endif
}
- /*
- emit_pusha();
- //save_regs(0x100f);
- emit_readword((int)&last_count,ECX);
- if(get_reg(i_regs->regmap,CCREG)<0)
- emit_loadreg(CCREG,HOST_CCREG);
- emit_add(HOST_CCREG,ECX,HOST_CCREG);
- emit_addimm(HOST_CCREG,2*ccadj[i],HOST_CCREG);
- emit_writeword(HOST_CCREG,(int)&Count);
- emit_call((int)memdebug);
- emit_popa();
- //restore_regs(0x100f);
- */
}
void c1ls_assemble(int i,struct regstat *i_regs)
int ar;
int offset;
int memtarget=0,c=0;
- int jaddr2=0,type;
+ void *jaddr2=NULL;
+ enum stub_type type;
int agr=AGEN1+(i&1);
int fastio_reg_override=0;
u_int hr,reglist=0;
type=LOADW_STUB;
if(c&&!memtarget) {
- jaddr2=(int)out;
+ jaddr2=out;
emit_jmp(0); // inline_readstub/inline_writestub?
}
else {
}
}
if(jaddr2)
- add_stub(type,jaddr2,(int)out,i,ar,(int)i_regs,ccadj[i],reglist);
+ add_stub_r(type,jaddr2,out,i,ar,i_regs,ccadj[i],reglist);
if(opcode[i]==0x3a) // SWC2
if(!(i_regs->waswritten&(1<<rs1[i]))&&!(new_dynarec_hacks&NDHACK_NO_SMC_CHECK)) {
#if defined(HOST_IMM8)
#if defined(HAVE_CONDITIONAL_CALL) && !defined(DESTRUCTIVE_SHIFT)
emit_callne(invalidate_addr_reg[ar]);
#else
- int jaddr3=(int)out;
+ void *jaddr3 = out;
emit_jne(0);
- add_stub(INVCODE_STUB,jaddr3,(int)out,reglist|(1<<HOST_CCREG),ar,0,0,0);
+ add_stub(INVCODE_STUB,jaddr3,out,reglist|(1<<HOST_CCREG),ar,0,0,0);
#endif
}
if (opcode[i]==0x32) { // LWC2
(void)ccreg;
emit_movimm(start+i*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((int)jump_syscall_hle); // XXX
+ emit_jmp(jump_syscall_hle); // XXX
}
void hlecall_assemble(int i,struct regstat *i_regs)
{
+ extern void psxNULL();
signed char ccreg=get_reg(i_regs->regmap,CCREG);
assert(ccreg==HOST_CCREG);
assert(!is_delayslot);
(void)ccreg;
emit_movimm(start+i*4+4,0); // Get PC
- emit_movimm((int)psxHLEt[source[i]&7],1);
+ uint32_t hleCode = source[i] & 0x03ffffff;
+ if (hleCode >= ARRAY_SIZE(psxHLEt))
+ emit_movimm((int)psxNULL,1);
+ else
+ emit_movimm((int)psxHLEt[hleCode],1);
emit_addimm(HOST_CCREG,CLOCK_ADJUST(ccadj[i]),HOST_CCREG); // XXX
- emit_jmp((int)jump_hlecall);
+ emit_jmp(jump_hlecall);
}
void intcall_assemble(int i,struct regstat *i_regs)
(void)ccreg;
emit_movimm(start+i*4,0); // Get PC
emit_addimm(HOST_CCREG,CLOCK_ADJUST(ccadj[i]),HOST_CCREG);
- emit_jmp((int)jump_intcall);
+ emit_jmp(jump_intcall);
}
void ds_assemble(int i,struct regstat *i_regs)
return 1;
}
+#ifdef DRC_DBG
+static void drc_dbg_emit_do_cmp(int i)
+{
+ extern void do_insn_cmp();
+ extern int cycle;
+ u_int hr,reglist=0;
+
+ for(hr=0;hr<HOST_REGS;hr++)
+ if(regs[i].regmap[hr]>=0) reglist|=1<<hr;
+ save_regs(reglist);
+ emit_movimm(start+i*4,0);
+ emit_writeword(0,(int)&pcaddr);
+ emit_call((int)do_insn_cmp);
+ //emit_readword((int)&cycle,0);
+ //emit_addimm(0,2,0);
+ //emit_writeword(0,(int)&cycle);
+ restore_regs(reglist);
+}
+#else
+#define drc_dbg_emit_do_cmp(x)
+#endif
+
// Used when a branch jumps into the delay slot of another branch
void ds_assemble_entry(int i)
{
int t=(ba[i]-start)>>2;
- if(!instr_addr[t]) instr_addr[t]=(u_int)out;
+ if (!instr_addr[t])
+ instr_addr[t] = out;
assem_debug("Assemble delay slot at %x\n",ba[i]);
assem_debug("<->\n");
+ drc_dbg_emit_do_cmp(t);
if(regs[t].regmap_entry[HOST_CCREG]==CCREG&®s[t].regmap[HOST_CCREG]!=CCREG)
wb_register(CCREG,regs[t].regmap_entry,regs[t].wasdirty,regs[t].was32);
load_regs(regs[t].regmap_entry,regs[t].regmap,regs[t].was32,rs1[t],rs2[t]);
void do_cc(int i,signed char i_regmap[],int *adj,int addr,int taken,int invert)
{
int count;
- int jaddr;
- int idle=0;
+ void *jaddr;
+ void *idle=NULL;
int t=0;
if(itype[i]==RJUMP)
{
if(taken==TAKEN && i==(ba[i]-start)>>2 && source[i+1]==0) {
// Idle loop
if(count&1) emit_addimm_and_set_flags(2*(count+2),HOST_CCREG);
- idle=(int)out;
+ idle=out;
//emit_subfrommem(&idlecount,HOST_CCREG); // Count idle cycles
emit_andimm(HOST_CCREG,3,HOST_CCREG);
- jaddr=(int)out;
+ jaddr=out;
emit_jmp(0);
}
else if(*adj==0||invert) {
cycles=CLOCK_ADJUST(*adj)+count+2-*adj;
}
emit_addimm_and_set_flags(cycles,HOST_CCREG);
- jaddr=(int)out;
+ jaddr=out;
emit_jns(0);
}
else
{
emit_cmpimm(HOST_CCREG,-CLOCK_ADJUST(count+2));
- jaddr=(int)out;
+ jaddr=out;
emit_jns(0);
}
- add_stub(CC_STUB,jaddr,idle?idle:(int)out,(*adj==0||invert||idle)?0:(count+2),i,addr,taken,0);
+ add_stub(CC_STUB,jaddr,idle?idle:out,(*adj==0||invert||idle)?0:(count+2),i,addr,taken,0);
}
-void do_ccstub(int n)
+static void do_ccstub(int n)
{
literal_pool(256);
- assem_debug("do_ccstub %x\n",start+stubs[n][4]*4);
- set_jump_target(stubs[n][1],(int)out);
- int i=stubs[n][4];
- if(stubs[n][6]==NULLDS) {
+ assem_debug("do_ccstub %x\n",start+stubs[n].b*4);
+ set_jump_target(stubs[n].addr, out);
+ int i=stubs[n].b;
+ if(stubs[n].d==NULLDS) {
// Delay slot instruction is nullified ("likely" branch)
wb_dirtys(regs[i].regmap,regs[i].is32,regs[i].dirty);
}
- else if(stubs[n][6]!=TAKEN) {
+ else if(stubs[n].d!=TAKEN) {
wb_dirtys(branch_regs[i].regmap,branch_regs[i].is32,branch_regs[i].dirty);
}
else {
if(internal_branch(branch_regs[i].is32,ba[i]))
wb_needed_dirtys(branch_regs[i].regmap,branch_regs[i].is32,branch_regs[i].dirty,ba[i]);
}
- if(stubs[n][5]!=-1)
+ if(stubs[n].c!=-1)
{
// Save PC as return address
- emit_movimm(stubs[n][5],EAX);
+ emit_movimm(stubs[n].c,EAX);
emit_writeword(EAX,(int)&pcaddr);
}
else
}
// Update cycle count
assert(branch_regs[i].regmap[HOST_CCREG]==CCREG||branch_regs[i].regmap[HOST_CCREG]==-1);
- if(stubs[n][3]) emit_addimm(HOST_CCREG,CLOCK_ADJUST((int)stubs[n][3]),HOST_CCREG);
+ if(stubs[n].a) emit_addimm(HOST_CCREG,CLOCK_ADJUST((int)stubs[n].a),HOST_CCREG);
emit_call((int)cc_interrupt);
- if(stubs[n][3]) emit_addimm(HOST_CCREG,-CLOCK_ADJUST((int)stubs[n][3]),HOST_CCREG);
- if(stubs[n][6]==TAKEN) {
+ if(stubs[n].a) emit_addimm(HOST_CCREG,-CLOCK_ADJUST((int)stubs[n].a),HOST_CCREG);
+ if(stubs[n].d==TAKEN) {
if(internal_branch(branch_regs[i].is32,ba[i]))
load_needed_regs(branch_regs[i].regmap,regs[(ba[i]-start)>>2].regmap_entry);
else if(itype[i]==RJUMP) {
else
emit_loadreg(rs1[i],get_reg(branch_regs[i].regmap,rs1[i]));
}
- }else if(stubs[n][6]==NOTTAKEN) {
+ }else if(stubs[n].d==NOTTAKEN) {
if(i<slen-2) load_needed_regs(branch_regs[i].regmap,regmap_pre[i+2]);
else load_all_regs(branch_regs[i].regmap);
- }else if(stubs[n][6]==NULLDS) {
+ }else if(stubs[n].d==NULLDS) {
// Delay slot instruction is nullified ("likely" branch)
if(i<slen-2) load_needed_regs(regs[i].regmap,regmap_pre[i+2]);
else load_all_regs(regs[i].regmap);
}else{
load_all_regs(branch_regs[i].regmap);
}
- emit_jmp(stubs[n][2]); // return address
-
- /* This works but uses a lot of memory...
- emit_readword((int)&last_count,ECX);
- emit_add(HOST_CCREG,ECX,EAX);
- emit_writeword(EAX,(int)&Count);
- emit_call((int)gen_interupt);
- emit_readword((int)&Count,HOST_CCREG);
- emit_readword((int)&next_interupt,EAX);
- emit_readword((int)&pending_exception,EBX);
- emit_writeword(EAX,(int)&last_count);
- emit_sub(HOST_CCREG,EAX,HOST_CCREG);
- emit_test(EBX,EBX);
- int jne_instr=(int)out;
- emit_jne(0);
- if(stubs[n][3]) emit_addimm(HOST_CCREG,-2*stubs[n][3],HOST_CCREG);
- load_all_regs(branch_regs[i].regmap);
- emit_jmp(stubs[n][2]); // return address
- set_jump_target(jne_instr,(int)out);
- emit_readword((int)&pcaddr,EAX);
- // Call get_addr_ht instead of doing the hash table here.
- // This code is executed infrequently and takes up a lot of space
- // so smaller is better.
- emit_storereg(CCREG,HOST_CCREG);
- emit_pushreg(EAX);
- emit_call((int)get_addr_ht);
- emit_loadreg(CCREG,HOST_CCREG);
- emit_addimm(ESP,4,ESP);
- emit_jmpreg(EAX);*/
+ emit_jmp(stubs[n].retaddr);
}
static void add_to_linker(int addr,int target,int ext)
#ifdef REG_PREFETCH
if(temp>=0)
{
- if(i_regmap[temp]!=PTEMP) emit_movimm((int)hash_table[((return_address>>16)^return_address)&0xFFFF],temp);
+ if(i_regmap[temp]!=PTEMP) emit_movimm((int)hash_table_get(return_address),temp);
}
#endif
emit_movimm(return_address,rt); // PC into link register
#ifdef IMM_PREFETCH
- emit_prefetch(hash_table[((return_address>>16)^return_address)&0xFFFF]);
+ emit_prefetch(hash_table_get(return_address));
#endif
}
}
signed char *i_regmap=i_regs->regmap;
int return_address=start+i*4+8;
if(get_reg(branch_regs[i].regmap,31)>0)
- if(i_regmap[temp]==PTEMP) emit_movimm((int)hash_table[((return_address>>16)^return_address)&0xFFFF],temp);
+ if(i_regmap[temp]==PTEMP) emit_movimm((int)hash_table_get(return_address),temp);
}
#endif
if(rt1[i]==31&&(rt1[i]==rs1[i+1]||rt1[i]==rs2[i+1])) {
#ifdef REG_PREFETCH
if(temp>=0)
{
- if(i_regmap[temp]!=PTEMP) emit_movimm((int)hash_table[((return_address>>16)^return_address)&0xFFFF],temp);
+ if(i_regmap[temp]!=PTEMP) emit_movimm((int)hash_table_get(return_address),temp);
}
#endif
emit_movimm(return_address,rt); // PC into link register
#ifdef IMM_PREFETCH
- emit_prefetch(hash_table[((return_address>>16)^return_address)&0xFFFF]);
+ emit_prefetch(hash_table_get(return_address));
#endif
}
if((temp=get_reg(branch_regs[i].regmap,PTEMP))>=0) {
signed char *i_regmap=i_regs->regmap;
int return_address=start+i*4+8;
- if(i_regmap[temp]==PTEMP) emit_movimm((int)hash_table[((return_address>>16)^return_address)&0xFFFF],temp);
+ if(i_regmap[temp]==PTEMP) emit_movimm((int)hash_table_get(return_address),temp);
}
}
#endif
//if(adj) emit_addimm(cc,2*(ccadj[i]+2-adj),cc); // ??? - Shouldn't happen
//assert(adj==0);
emit_addimm_and_set_flags(CLOCK_ADJUST(ccadj[i]+2),HOST_CCREG);
- add_stub(CC_STUB,(int)out,jump_vaddr_reg[rs],0,i,-1,TAKEN,0);
+ add_stub(CC_STUB,out,jump_vaddr_reg[rs],0,i,-1,TAKEN,0);
if(itype[i+1]==COP0&&(source[i+1]&0x3f)==0x10)
// special case for RFE
emit_jmp(0);
else
#endif
{
- //if(rs!=EAX) emit_mov(rs,EAX);
- //emit_jmp((int)jump_vaddr_eax);
emit_jmp(jump_vaddr_reg[rs]);
}
- /* Check hash table
- temp=!rs;
- emit_mov(rs,temp);
- emit_shrimm(rs,16,rs);
- emit_xor(temp,rs,rs);
- emit_movzwl_reg(rs,rs);
- emit_shlimm(rs,4,rs);
- emit_cmpmem_indexed((int)hash_table,rs,temp);
- emit_jne((int)out+14);
- emit_readword_indexed((int)hash_table+4,rs,rs);
- emit_jmpreg(rs);
- emit_cmpmem_indexed((int)hash_table+8,rs,temp);
- emit_addimm_no_flags(8,rs);
- emit_jeq((int)out-17);
- // No hit on hash table, call compiler
- emit_pushreg(temp);
-//DEBUG >
-#ifdef DEBUG_CYCLE_COUNT
- emit_readword((int)&last_count,ECX);
- emit_add(HOST_CCREG,ECX,HOST_CCREG);
- emit_readword((int)&next_interupt,ECX);
- emit_writeword(HOST_CCREG,(int)&Count);
- emit_sub(HOST_CCREG,ECX,HOST_CCREG);
- emit_writeword(ECX,(int)&last_count);
-#endif
-//DEBUG <
- emit_storereg(CCREG,HOST_CCREG);
- emit_call((int)get_addr);
- emit_loadreg(CCREG,HOST_CCREG);
- emit_addimm(ESP,4,ESP);
- emit_jmpreg(EAX);*/
#ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
if(rt1[i]!=31&&i<slen-2&&(((u_int)out)&7)) emit_mov(13,13);
#endif
}
else if(nop) {
emit_addimm_and_set_flags(CLOCK_ADJUST(ccadj[i]+2),cc);
- int jaddr=(int)out;
+ void *jaddr=out;
emit_jns(0);
- add_stub(CC_STUB,jaddr,(int)out,0,i,start+i*4+8,NOTTAKEN,0);
+ add_stub(CC_STUB,jaddr,out,0,i,start+i*4+8,NOTTAKEN,0);
}
else {
- int taken=0,nottaken=0,nottaken1=0;
+ void *taken = NULL, *nottaken = NULL, *nottaken1 = NULL;
do_cc(i,branch_regs[i].regmap,&adj,-1,0,invert);
if(adj&&!invert) emit_addimm(cc,CLOCK_ADJUST(ccadj[i]+2-adj),cc);
if(!only32)
{
if(s2h>=0) emit_cmp(s1h,s2h);
else emit_test(s1h,s1h);
- nottaken1=(int)out;
+ nottaken1=out;
emit_jne(1);
}
if(opcode[i]==5) // BNE
{
if(s2h>=0) emit_cmp(s1h,s2h);
else emit_test(s1h,s1h);
- if(invert) taken=(int)out;
+ if(invert) taken=out;
else add_to_linker((int)out,ba[i],internal);
emit_jne(0);
}
if(opcode[i]==6) // BLEZ
{
emit_test(s1h,s1h);
- if(invert) taken=(int)out;
+ if(invert) taken=out;
else add_to_linker((int)out,ba[i],internal);
emit_js(0);
- nottaken1=(int)out;
+ nottaken1=out;
emit_jne(1);
}
if(opcode[i]==7) // BGTZ
{
emit_test(s1h,s1h);
- nottaken1=(int)out;
+ nottaken1=out;
emit_js(1);
- if(invert) taken=(int)out;
+ if(invert) taken=out;
else add_to_linker((int)out,ba[i],internal);
emit_jne(0);
}
if(s2l>=0) emit_cmp(s1l,s2l);
else emit_test(s1l,s1l);
if(invert){
- nottaken=(int)out;
+ nottaken=out;
emit_jne(1);
}else{
add_to_linker((int)out,ba[i],internal);
if(s2l>=0) emit_cmp(s1l,s2l);
else emit_test(s1l,s1l);
if(invert){
- nottaken=(int)out;
+ nottaken=out;
emit_jeq(1);
}else{
add_to_linker((int)out,ba[i],internal);
{
emit_cmpimm(s1l,1);
if(invert){
- nottaken=(int)out;
+ nottaken=out;
emit_jge(1);
}else{
add_to_linker((int)out,ba[i],internal);
{
emit_cmpimm(s1l,1);
if(invert){
- nottaken=(int)out;
+ nottaken=out;
emit_jl(1);
}else{
add_to_linker((int)out,ba[i],internal);
}
}
if(invert) {
- if(taken) set_jump_target(taken,(int)out);
+ if(taken) set_jump_target(taken, out);
#ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
if(match&&(!internal||!is_ds[(ba[i]-start)>>2])) {
if(adj) {
emit_jmp(0);
}
}
- set_jump_target(nottaken,(int)out);
+ set_jump_target(nottaken, out);
}
- if(nottaken1) set_jump_target(nottaken1,(int)out);
+ if(nottaken1) set_jump_target(nottaken1, out);
if(adj) {
if(!invert) emit_addimm(cc,CLOCK_ADJUST(adj),cc);
}
//if(likely[i]) printf("IOL\n");
//else
//printf("IOE\n");
- int taken=0,nottaken=0,nottaken1=0;
+ void *taken = NULL, *nottaken = NULL, *nottaken1 = NULL;
if(!unconditional&&!nop) {
if(!only32)
{
{
if(s2h>=0) emit_cmp(s1h,s2h);
else emit_test(s1h,s1h);
- nottaken1=(int)out;
+ nottaken1=out;
emit_jne(2);
}
if((opcode[i]&0x2f)==5) // BNE
{
if(s2h>=0) emit_cmp(s1h,s2h);
else emit_test(s1h,s1h);
- taken=(int)out;
+ taken=out;
emit_jne(1);
}
if((opcode[i]&0x2f)==6) // BLEZ
{
emit_test(s1h,s1h);
- taken=(int)out;
+ taken=out;
emit_js(1);
- nottaken1=(int)out;
+ nottaken1=out;
emit_jne(2);
}
if((opcode[i]&0x2f)==7) // BGTZ
{
emit_test(s1h,s1h);
- nottaken1=(int)out;
+ nottaken1=out;
emit_js(2);
- taken=(int)out;
+ taken=out;
emit_jne(1);
}
} // if(!only32)
{
if(s2l>=0) emit_cmp(s1l,s2l);
else emit_test(s1l,s1l);
- nottaken=(int)out;
+ nottaken=out;
emit_jne(2);
}
if((opcode[i]&0x2f)==5) // BNE
{
if(s2l>=0) emit_cmp(s1l,s2l);
else emit_test(s1l,s1l);
- nottaken=(int)out;
+ nottaken=out;
emit_jeq(2);
}
if((opcode[i]&0x2f)==6) // BLEZ
{
emit_cmpimm(s1l,1);
- nottaken=(int)out;
+ nottaken=out;
emit_jge(2);
}
if((opcode[i]&0x2f)==7) // BGTZ
{
emit_cmpimm(s1l,1);
- nottaken=(int)out;
+ nottaken=out;
emit_jl(2);
}
} // if(!unconditional)
ds_unneeded_upper|=1;
// branch taken
if(!nop) {
- if(taken) set_jump_target(taken,(int)out);
+ if(taken) set_jump_target(taken, out);
assem_debug("1:\n");
wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,regs[i].is32,
ds_unneeded,ds_unneeded_upper);
// branch not taken
cop1_usable=prev_cop1_usable;
if(!unconditional) {
- if(nottaken1) set_jump_target(nottaken1,(int)out);
- set_jump_target(nottaken,(int)out);
+ if(nottaken1) set_jump_target(nottaken1, out);
+ set_jump_target(nottaken, out);
assem_debug("2:\n");
if(!likely[i]) {
wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,regs[i].is32,
// Cycle count isn't in a register, temporarily load it then write it out
emit_loadreg(CCREG,HOST_CCREG);
emit_addimm_and_set_flags(CLOCK_ADJUST(ccadj[i]+2),HOST_CCREG);
- int jaddr=(int)out;
+ void *jaddr=out;
emit_jns(0);
- add_stub(CC_STUB,jaddr,(int)out,0,i,start+i*4+8,NOTTAKEN,0);
+ add_stub(CC_STUB,jaddr,out,0,i,start+i*4+8,NOTTAKEN,0);
emit_storereg(CCREG,HOST_CCREG);
}
else{
cc=get_reg(i_regmap,CCREG);
assert(cc==HOST_CCREG);
emit_addimm_and_set_flags(CLOCK_ADJUST(ccadj[i]+2),cc);
- int jaddr=(int)out;
+ void *jaddr=out;
emit_jns(0);
- add_stub(CC_STUB,jaddr,(int)out,0,i,start+i*4+8,likely[i]?NULLDS:NOTTAKEN,0);
+ add_stub(CC_STUB,jaddr,out,0,i,start+i*4+8,likely[i]?NULLDS:NOTTAKEN,0);
}
}
}
return_address=start+i*4+8;
emit_movimm(return_address,rt); // PC into link register
#ifdef IMM_PREFETCH
- if(!nevertaken) emit_prefetch(hash_table[((return_address>>16)^return_address)&0xFFFF]);
+ if(!nevertaken) emit_prefetch(hash_table_get(return_address));
#endif
}
}
}
else if(nevertaken) {
emit_addimm_and_set_flags(CLOCK_ADJUST(ccadj[i]+2),cc);
- int jaddr=(int)out;
+ void *jaddr=out;
emit_jns(0);
- add_stub(CC_STUB,jaddr,(int)out,0,i,start+i*4+8,NOTTAKEN,0);
+ add_stub(CC_STUB,jaddr,out,0,i,start+i*4+8,NOTTAKEN,0);
}
else {
- int nottaken=0;
+ void *nottaken = NULL;
do_cc(i,branch_regs[i].regmap,&adj,-1,0,invert);
if(adj&&!invert) emit_addimm(cc,CLOCK_ADJUST(ccadj[i]+2-adj),cc);
if(!only32)
{
emit_test(s1h,s1h);
if(invert){
- nottaken=(int)out;
+ nottaken=out;
emit_jns(1);
}else{
add_to_linker((int)out,ba[i],internal);
{
emit_test(s1h,s1h);
if(invert){
- nottaken=(int)out;
+ nottaken=out;
emit_js(1);
}else{
add_to_linker((int)out,ba[i],internal);
{
emit_test(s1l,s1l);
if(invert){
- nottaken=(int)out;
+ nottaken=out;
emit_jns(1);
}else{
add_to_linker((int)out,ba[i],internal);
{
emit_test(s1l,s1l);
if(invert){
- nottaken=(int)out;
+ nottaken=out;
emit_js(1);
}else{
add_to_linker((int)out,ba[i],internal);
emit_jmp(0);
}
}
- set_jump_target(nottaken,(int)out);
+ set_jump_target(nottaken, out);
}
if(adj) {
{
// In-order execution (branch first)
//printf("IOE\n");
- int nottaken=0;
+ void *nottaken = NULL;
if(rt1[i]==31) {
int rt,return_address;
rt=get_reg(branch_regs[i].regmap,31);
return_address=start+i*4+8;
emit_movimm(return_address,rt); // PC into link register
#ifdef IMM_PREFETCH
- emit_prefetch(hash_table[((return_address>>16)^return_address)&0xFFFF]);
+ emit_prefetch(hash_table_get(return_address));
#endif
}
}
if((opcode2[i]&0x0d)==0) // BLTZ/BLTZL/BLTZAL/BLTZALL
{
emit_test(s1h,s1h);
- nottaken=(int)out;
+ nottaken=out;
emit_jns(1);
}
if((opcode2[i]&0x0d)==1) // BGEZ/BGEZL/BGEZAL/BGEZALL
{
emit_test(s1h,s1h);
- nottaken=(int)out;
+ nottaken=out;
emit_js(1);
}
} // if(!only32)
if((opcode2[i]&0x0d)==0) // BLTZ/BLTZL/BLTZAL/BLTZALL
{
emit_test(s1l,s1l);
- nottaken=(int)out;
+ nottaken=out;
emit_jns(1);
}
if((opcode2[i]&0x0d)==1) // BGEZ/BGEZL/BGEZAL/BGEZALL
{
emit_test(s1l,s1l);
- nottaken=(int)out;
+ nottaken=out;
emit_js(1);
}
}
// branch not taken
cop1_usable=prev_cop1_usable;
if(!unconditional) {
- set_jump_target(nottaken,(int)out);
+ set_jump_target(nottaken, out);
assem_debug("1:\n");
if(!likely[i]) {
wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,regs[i].is32,
// Cycle count isn't in a register, temporarily load it then write it out
emit_loadreg(CCREG,HOST_CCREG);
emit_addimm_and_set_flags(CLOCK_ADJUST(ccadj[i]+2),HOST_CCREG);
- int jaddr=(int)out;
+ void *jaddr=out;
emit_jns(0);
- add_stub(CC_STUB,jaddr,(int)out,0,i,start+i*4+8,NOTTAKEN,0);
+ add_stub(CC_STUB,jaddr,out,0,i,start+i*4+8,NOTTAKEN,0);
emit_storereg(CCREG,HOST_CCREG);
}
else{
cc=get_reg(i_regmap,CCREG);
assert(cc==HOST_CCREG);
emit_addimm_and_set_flags(CLOCK_ADJUST(ccadj[i]+2),cc);
- int jaddr=(int)out;
+ void *jaddr=out;
emit_jns(0);
- add_stub(CC_STUB,jaddr,(int)out,0,i,start+i*4+8,likely[i]?NULLDS:NOTTAKEN,0);
+ add_stub(CC_STUB,jaddr,out,0,i,start+i*4+8,likely[i]?NULLDS:NOTTAKEN,0);
}
}
}
match=match_bt(branch_regs[i].regmap,branch_regs[i].is32,branch_regs[i].dirty,ba[i]);
assem_debug("fmatch=%d\n",match);
int fs,cs;
- int eaddr;
+ void *eaddr;
int invert=0;
int internal=internal_branch(branch_regs[i].is32,ba[i]);
if(i==(ba[i]-start)>>2) assem_debug("idle loop\n");
cs=get_reg(i_regmap,CSREG);
assert(cs>=0);
emit_testimm(cs,0x20000000);
- eaddr=(int)out;
+ eaddr=out;
emit_jeq(0);
- add_stub(FP_STUB,eaddr,(int)out,i,cs,(int)i_regs,0,0);
+ add_stub_r(FP_STUB,eaddr,out,i,cs,i_regs,0,0);
cop1_usable=1;
}
do_cc(i,branch_regs[i].regmap,&adj,-1,0,invert);
assem_debug("cycle count (adj)\n");
if(1) {
- int nottaken=0;
+ void *nottaken = NULL;
if(adj&&!invert) emit_addimm(cc,CLOCK_ADJUST(ccadj[i]+2-adj),cc);
if(1) {
assert(fs>=0);
if(source[i]&0x10000) // BC1T
{
if(invert){
- nottaken=(int)out;
+ nottaken=out;
emit_jeq(1);
}else{
add_to_linker((int)out,ba[i],internal);
}
else // BC1F
if(invert){
- nottaken=(int)out;
+ nottaken=out;
emit_jne(1);
}else{
add_to_linker((int)out,ba[i],internal);
add_to_linker((int)out,ba[i],internal);
emit_jmp(0);
}
- set_jump_target(nottaken,(int)out);
+ set_jump_target(nottaken, out);
}
if(adj) {
{
// In-order execution (branch first)
//printf("IOE\n");
- int nottaken=0;
+ void *nottaken = NULL;
if(1) {
//printf("branch(%d): eax=%d ecx=%d edx=%d ebx=%d ebp=%d esi=%d edi=%d\n",i,branch_regs[i].regmap[0],branch_regs[i].regmap[1],branch_regs[i].regmap[2],branch_regs[i].regmap[3],branch_regs[i].regmap[5],branch_regs[i].regmap[6],branch_regs[i].regmap[7]);
if(1) {
emit_testimm(fs,0x800000);
if(source[i]&0x10000) // BC1T
{
- nottaken=(int)out;
+ nottaken=out;
emit_jeq(1);
}
else // BC1F
{
- nottaken=(int)out;
+ nottaken=out;
emit_jne(1);
}
}
// branch not taken
if(1) { // <- FIXME (don't need this)
- set_jump_target(nottaken,(int)out);
+ set_jump_target(nottaken, out);
assem_debug("1:\n");
if(!likely[i]) {
wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,regs[i].is32,
// Cycle count isn't in a register, temporarily load it then write it out
emit_loadreg(CCREG,HOST_CCREG);
emit_addimm_and_set_flags(CLOCK_ADJUST(ccadj[i]+2),HOST_CCREG);
- int jaddr=(int)out;
+ void *jaddr=out;
emit_jns(0);
- add_stub(CC_STUB,jaddr,(int)out,0,i,start+i*4+8,NOTTAKEN,0);
+ add_stub(CC_STUB,jaddr,out,0,i,start+i*4+8,NOTTAKEN,0);
emit_storereg(CCREG,HOST_CCREG);
}
else{
cc=get_reg(i_regmap,CCREG);
assert(cc==HOST_CCREG);
emit_addimm_and_set_flags(CLOCK_ADJUST(ccadj[i]+2),cc);
- int jaddr=(int)out;
+ void *jaddr=out;
emit_jns(0);
- add_stub(CC_STUB,jaddr,(int)out,0,i,start+i*4+8,likely[i]?NULLDS:NOTTAKEN,0);
+ add_stub(CC_STUB,jaddr,out,0,i,start+i*4+8,likely[i]?NULLDS:NOTTAKEN,0);
}
}
}
int s1h=get_reg(i_regs->regmap,rs1[i]|64);
int s2l=get_reg(i_regs->regmap,rs2[i]);
int s2h=get_reg(i_regs->regmap,rs2[i]|64);
- int taken=0;
- int nottaken=0;
+ void *taken = NULL;
+ void *nottaken = NULL;
int unconditional=0;
if(rs1[i]==0)
{
if(s1h>=0) {
if(s2h>=0) emit_cmp(s1h,s2h);
else emit_test(s1h,s1h);
- nottaken=(int)out;
+ nottaken=out;
emit_jne(0);
}
if(s2l>=0) emit_cmp(s1l,s2l);
else emit_test(s1l,s1l);
- if(nottaken) set_jump_target(nottaken,(int)out);
- nottaken=(int)out;
+ if(nottaken) set_jump_target(nottaken, out);
+ nottaken=out;
emit_jne(0);
}
if((opcode[i]&0x3f)==0x15) // BNEL
if(s1h>=0) {
if(s2h>=0) emit_cmp(s1h,s2h);
else emit_test(s1h,s1h);
- taken=(int)out;
+ taken=out;
emit_jne(0);
}
if(s2l>=0) emit_cmp(s1l,s2l);
else emit_test(s1l,s1l);
- nottaken=(int)out;
+ nottaken=out;
emit_jeq(0);
- if(taken) set_jump_target(taken,(int)out);
+ if(taken) set_jump_target(taken, out);
}
if((opcode[i]&0x3f)==6) // BLEZ
{
if((source[i]&0x30000)==0x20000) // BC1FL
{
emit_testimm(s1l,0x800000);
- nottaken=(int)out;
+ nottaken=out;
emit_jne(0);
}
if((source[i]&0x30000)==0x30000) // BC1TL
{
emit_testimm(s1l,0x800000);
- nottaken=(int)out;
+ nottaken=out;
emit_jeq(0);
}
}
void *compiled_target_addr=check_addr(target_addr);
emit_extjump_ds((int)branch_addr,target_addr);
if(compiled_target_addr) {
- set_jump_target((int)branch_addr,(int)compiled_target_addr);
+ set_jump_target(branch_addr, compiled_target_addr);
add_link(target_addr,stub);
}
- else set_jump_target((int)branch_addr,(int)stub);
+ else set_jump_target(branch_addr, stub);
if(likely[i]) {
// Not-taken path
- set_jump_target((int)nottaken,(int)out);
+ set_jump_target(nottaken, out);
wb_dirtys(regs[i].regmap,regs[i].is32,regs[i].dirty);
void *branch_addr=out;
emit_jmp(0);
void *compiled_target_addr=check_addr(target_addr);
emit_extjump_ds((int)branch_addr,target_addr);
if(compiled_target_addr) {
- set_jump_target((int)branch_addr,(int)compiled_target_addr);
+ set_jump_target(branch_addr, compiled_target_addr);
add_link(target_addr,stub);
}
- else set_jump_target((int)branch_addr,(int)stub);
+ else set_jump_target(branch_addr, stub);
}
}
#else
emit_cmpimm(btaddr,start+4);
#endif
- int branch=(int)out;
+ void *branch = out;
emit_jeq(0);
store_regs_bt(regs[0].regmap,regs[0].is32,regs[0].dirty,-1);
emit_jmp(jump_vaddr_reg[btaddr]);
- set_jump_target(branch,(int)out);
+ set_jump_target(branch, out);
store_regs_bt(regs[0].regmap,regs[0].is32,regs[0].dirty,start+4);
load_regs_bt(regs[0].regmap,regs[0].is32,regs[0].dirty,start+4);
}
#else
#ifndef NO_WRITE_EXEC
// not all systems allow execute in data segment by default
- if (mprotect(out, 1<<TARGET_SIZE_2, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
+ if (mprotect((void *)BASE_ADDR, 1<<TARGET_SIZE_2, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
SysPrintf("mprotect() failed: %s\n", strerror(errno));
#endif
#endif
u_int addr;
o = 0;
- for (p = 0; p < sizeof(jump_in) / sizeof(jump_in[0]); p++) {
+ for (p = 0; p < ARRAY_SIZE(jump_in); p++) {
bcnt = 0;
for (head = jump_in[p]; head != NULL; head = head->next) {
tmp_blocks[bcnt].addr = head->vaddr;
u_int state_rflags = 0;
int i;
- assem_debug("NOTCOMPILED: addr = %x -> %x\n", (int)addr, (int)out);
- //printf("NOTCOMPILED: addr = %x -> %x\n", (int)addr, (int)out);
+ assem_debug("NOTCOMPILED: addr = %x -> %p\n", addr, out);
//printf("TRACE: count=%d next=%d (compile %x)\n",Count,next_interupt,addr);
//if(debug)
//printf("TRACE: count=%d next=%d (checksum %x)\n",Count,next_interupt,mchecksum());
//printf("fpu mapping=%x enabled=%x\n",(Status & 0x04000000)>>26,(Status & 0x20000000)>>29);
- /*if(Count>=312978186) {
- rlist();
- }*/
- //rlist();
// this is just for speculation
for (i = 1; i < 32; i++) {
invalid_code[start>>12]=0;
emit_movimm(start,0);
emit_writeword(0,(int)&pcaddr);
- emit_jmp((int)new_dyna_leave);
+ emit_jmp(new_dyna_leave);
literal_pool(0);
end_block(beginning);
ll_add_flags(jump_in+page,start,state_rflags,(void *)beginning);
ds=1;
pagespan_ds();
}
- u_int instr_addr0_override=0;
+ void *instr_addr0_override = NULL;
if (start == 0x80030000) {
// nasty hack for fastbios thing
// override block entry to this code
- instr_addr0_override=(u_int)out;
+ instr_addr0_override = out;
emit_movimm(start,0);
// abuse io address var as a flag that we
// have already returned here once
if(ds) {
ds=0; // Skip delay slot
if(bt[i]) assem_debug("OOPS - branch into delay slot\n");
- instr_addr[i]=0;
+ instr_addr[i] = NULL;
} else {
speculate_register_values(i);
#ifndef DESTRUCTIVE_WRITEBACK
loop_preload(regmap_pre[i],regs[i].regmap_entry);
}
// branch target entry point
- instr_addr[i]=(u_int)out;
+ instr_addr[i] = out;
assem_debug("<->\n");
+ drc_dbg_emit_do_cmp(i);
+
// load regs
if(regs[i].regmap_entry[HOST_CCREG]==CCREG&®s[i].regmap[HOST_CCREG]!=CCREG)
wb_register(CCREG,regs[i].regmap_entry,regs[i].wasdirty,regs[i].was32);
// Stubs
for(i=0;i<stubcount;i++)
{
- switch(stubs[i][0])
+ switch(stubs[i].type)
{
case LOADB_STUB:
case LOADH_STUB:
void *addr=check_addr(link_addr[i][1]);
emit_extjump(link_addr[i][0],link_addr[i][1]);
if(addr) {
- set_jump_target(link_addr[i][0],(int)addr);
+ set_jump_target(link_addr[i][0], addr);
add_link(link_addr[i][1],stub);
}
- else set_jump_target(link_addr[i][0],(int)stub);
+ else set_jump_target(link_addr[i][0], stub);
}
else
{
u_int vpage=get_vpage(vaddr);
literal_pool(256);
{
- assem_debug("%8x (%d) <- %8x\n",instr_addr[i],i,start+i*4);
+ assem_debug("%p (%d) <- %8x\n",instr_addr[i],i,start+i*4);
assem_debug("jump_in: %x\n",start+i*4);
- ll_add(jump_dirty+vpage,vaddr,(void *)out);
- int entry_point=do_dirty_stub(i);
- ll_add_flags(jump_in+page,vaddr,state_rflags,(void *)entry_point);
+ ll_add(jump_dirty+vpage,vaddr,out);
+ void *entry_point = do_dirty_stub(i);
+ ll_add_flags(jump_in+page,vaddr,state_rflags,entry_point);
// If there was an existing entry in the hash table,
// replace it with the new address.
// Don't add new entries. We'll insert the
// ones that actually get used in check_addr().
- u_int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF];
- if(ht_bin[0]==vaddr) {
- ht_bin[1]=entry_point;
- }
- if(ht_bin[2]==vaddr) {
- ht_bin[3]=entry_point;
- }
+ struct ht_entry *ht_bin = hash_table_get(vaddr);
+ if (ht_bin->vaddr[0] == vaddr)
+ ht_bin->tcaddr[0] = entry_point;
+ if (ht_bin->vaddr[1] == vaddr)
+ ht_bin->tcaddr[1] = entry_point;
}
}
}
while(expirep!=end)
{
int shift=TARGET_SIZE_2-3; // Divide into 8 blocks
- int base=(int)BASE_ADDR+((expirep>>13)<<shift); // Base address of this block
+ uintptr_t base=(uintptr_t)BASE_ADDR+((expirep>>13)<<shift); // Base address of this block
inv_debug("EXP: Phase %d\n",expirep);
switch((expirep>>11)&3)
{
case 2:
// Clear hash table
for(i=0;i<32;i++) {
- u_int *ht_bin=hash_table[((expirep&2047)<<5)+i];
- if((ht_bin[3]>>shift)==(base>>shift) ||
- ((ht_bin[3]-MAX_OUTPUT_BLOCK_SIZE)>>shift)==(base>>shift)) {
- inv_debug("EXP: Remove hash %x -> %x\n",ht_bin[2],ht_bin[3]);
- ht_bin[2]=ht_bin[3]=-1;
- }
- if((ht_bin[1]>>shift)==(base>>shift) ||
- ((ht_bin[1]-MAX_OUTPUT_BLOCK_SIZE)>>shift)==(base>>shift)) {
- inv_debug("EXP: Remove hash %x -> %x\n",ht_bin[0],ht_bin[1]);
- ht_bin[0]=ht_bin[2];
- ht_bin[1]=ht_bin[3];
- ht_bin[2]=ht_bin[3]=-1;
+ struct ht_entry *ht_bin = &hash_table[((expirep&2047)<<5)+i];
+ if (((uintptr_t)ht_bin->tcaddr[1]>>shift) == (base>>shift) ||
+ (((uintptr_t)ht_bin->tcaddr[1]-MAX_OUTPUT_BLOCK_SIZE)>>shift)==(base>>shift)) {
+ inv_debug("EXP: Remove hash %x -> %p\n",ht_bin->vaddr[1],ht_bin->tcaddr[1]);
+ ht_bin->vaddr[1] = -1;
+ ht_bin->tcaddr[1] = NULL;
+ }
+ if (((uintptr_t)ht_bin->tcaddr[0]>>shift) == (base>>shift) ||
+ (((uintptr_t)ht_bin->tcaddr[0]-MAX_OUTPUT_BLOCK_SIZE)>>shift)==(base>>shift)) {
+ inv_debug("EXP: Remove hash %x -> %p\n",ht_bin->vaddr[0],ht_bin->tcaddr[0]);
+ ht_bin->vaddr[0] = ht_bin->vaddr[1];
+ ht_bin->tcaddr[0] = ht_bin->tcaddr[1];
+ ht_bin->vaddr[1] = -1;
+ ht_bin->tcaddr[1] = NULL;
}
}
break;