return;
}
r=cur->regmap[preferred_reg];
- if(r<64&&((cur->u>>r)&1)) {
- cur->regmap[preferred_reg]=reg;
- cur->dirty&=~(1<<preferred_reg);
- cur->isconst&=~(1<<preferred_reg);
- return;
- }
- if(r>=64&&((cur->uu>>(r&63))&1)) {
+ assert(r < 64);
+ if((cur->u>>r)&1) {
cur->regmap[preferred_reg]=reg;
cur->dirty&=~(1<<preferred_reg);
cur->isconst&=~(1<<preferred_reg);
{
r=cur->regmap[hr];
if(r>=0) {
- if(r<64) {
- if((cur->u>>r)&1) {cur->regmap[hr]=-1;break;}
- }
- else
- {
- if((cur->uu>>(r&63))&1) {cur->regmap[hr]=-1;break;}
- }
+ assert(r < 64);
+ if((cur->u>>r)&1) {cur->regmap[hr]=-1;break;}
}
}
// Try to allocate any available register, but prefer
// Don't evict the cycle count at entry points, otherwise the entry
// stub will have to write it.
if(bt[i]&&hsn[CCREG]>2) hsn[CCREG]=2;
- if(i>1&&hsn[CCREG]>2&&(itype[i-2]==RJUMP||itype[i-2]==UJUMP||itype[i-2]==CJUMP||itype[i-2]==SJUMP||itype[i-2]==FJUMP)) hsn[CCREG]=2;
+ if(i>1&&hsn[CCREG]>2&&(itype[i-2]==RJUMP||itype[i-2]==UJUMP||itype[i-2]==CJUMP||itype[i-2]==SJUMP)) hsn[CCREG]=2;
for(j=10;j>=3;j--)
{
// Alloc preferred register if available
SysPrintf("This shouldn't happen (alloc_reg)");exit(1);
}
-static void alloc_reg64(struct regstat *cur,int i,signed char reg)
-{
- int preferred_reg = 8+(reg&1);
- int r,hr;
-
- // allocate the lower 32 bits
- alloc_reg(cur,i,reg);
-
- // Don't allocate unused registers
- if((cur->uu>>reg)&1) return;
-
- // see if the upper half is already allocated
- for(hr=0;hr<HOST_REGS;hr++)
- {
- if(cur->regmap[hr]==reg+64) return;
- }
-
- // Keep the same mapping if the register was already allocated in a loop
- preferred_reg = loop_reg(i,reg,preferred_reg);
-
- // Try to allocate the preferred register
- if(cur->regmap[preferred_reg]==-1) {
- cur->regmap[preferred_reg]=reg|64;
- cur->dirty&=~(1<<preferred_reg);
- cur->isconst&=~(1<<preferred_reg);
- return;
- }
- r=cur->regmap[preferred_reg];
- if(r<64&&((cur->u>>r)&1)) {
- cur->regmap[preferred_reg]=reg|64;
- cur->dirty&=~(1<<preferred_reg);
- cur->isconst&=~(1<<preferred_reg);
- return;
- }
- if(r>=64&&((cur->uu>>(r&63))&1)) {
- cur->regmap[preferred_reg]=reg|64;
- cur->dirty&=~(1<<preferred_reg);
- cur->isconst&=~(1<<preferred_reg);
- return;
- }
-
- // Clear any unneeded registers
- // We try to keep the mapping consistent, if possible, because it
- // makes branches easier (especially loops). So we try to allocate
- // first (see above) before removing old mappings. If this is not
- // possible then go ahead and clear out the registers that are no
- // longer needed.
- for(hr=HOST_REGS-1;hr>=0;hr--)
- {
- r=cur->regmap[hr];
- if(r>=0) {
- if(r<64) {
- if((cur->u>>r)&1) {cur->regmap[hr]=-1;break;}
- }
- else
- {
- if((cur->uu>>(r&63))&1) {cur->regmap[hr]=-1;break;}
- }
- }
- }
- // Try to allocate any available register, but prefer
- // registers that have not been used recently.
- if(i>0) {
- for(hr=0;hr<HOST_REGS;hr++) {
- if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
- if(regs[i-1].regmap[hr]!=rs1[i-1]&®s[i-1].regmap[hr]!=rs2[i-1]&®s[i-1].regmap[hr]!=rt1[i-1]&®s[i-1].regmap[hr]!=rt2[i-1]) {
- cur->regmap[hr]=reg|64;
- cur->dirty&=~(1<<hr);
- cur->isconst&=~(1<<hr);
- return;
- }
- }
- }
- }
- // Try to allocate any available register
- for(hr=0;hr<HOST_REGS;hr++) {
- if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
- cur->regmap[hr]=reg|64;
- cur->dirty&=~(1<<hr);
- cur->isconst&=~(1<<hr);
- return;
- }
- }
-
- // Ok, now we have to evict someone
- // Pick a register we hopefully won't need soon
- u_char hsn[MAXREG+1];
- memset(hsn,10,sizeof(hsn));
- int j;
- lsn(hsn,i,&preferred_reg);
- //printf("eax=%d ecx=%d edx=%d ebx=%d ebp=%d esi=%d edi=%d\n",cur->regmap[0],cur->regmap[1],cur->regmap[2],cur->regmap[3],cur->regmap[5],cur->regmap[6],cur->regmap[7]);
- //printf("hsn(%x): %d %d %d %d %d %d %d\n",start+i*4,hsn[cur->regmap[0]&63],hsn[cur->regmap[1]&63],hsn[cur->regmap[2]&63],hsn[cur->regmap[3]&63],hsn[cur->regmap[5]&63],hsn[cur->regmap[6]&63],hsn[cur->regmap[7]&63]);
- if(i>0) {
- // Don't evict the cycle count at entry points, otherwise the entry
- // stub will have to write it.
- if(bt[i]&&hsn[CCREG]>2) hsn[CCREG]=2;
- if(i>1&&hsn[CCREG]>2&&(itype[i-2]==RJUMP||itype[i-2]==UJUMP||itype[i-2]==CJUMP||itype[i-2]==SJUMP||itype[i-2]==FJUMP)) hsn[CCREG]=2;
- for(j=10;j>=3;j--)
- {
- // Alloc preferred register if available
- if(hsn[r=cur->regmap[preferred_reg]&63]==j) {
- for(hr=0;hr<HOST_REGS;hr++) {
- // Evict both parts of a 64-bit register
- if((cur->regmap[hr]&63)==r) {
- cur->regmap[hr]=-1;
- cur->dirty&=~(1<<hr);
- cur->isconst&=~(1<<hr);
- }
- }
- cur->regmap[preferred_reg]=reg|64;
- return;
- }
- 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|64;
- 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) {
- cur->regmap[hr]=reg|64;
- cur->dirty&=~(1<<hr);
- cur->isconst&=~(1<<hr);
- return;
- }
- }
- }
- }
- }
- }
- }
- for(j=10;j>=0;j--)
- {
- 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|64;
- 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|64;
- cur->dirty&=~(1<<hr);
- cur->isconst&=~(1<<hr);
- return;
- }
- }
- }
- }
- }
- SysPrintf("This shouldn't happen");exit(1);
-}
-
// Allocate a temporary register. This is done without regard to
// dirty status or whether the register we request is on the unneeded list
// Note: This will only allocate one register, even if called multiple times
{
r=cur->regmap[hr];
if(r>=0) {
- if(r<64) {
- if((cur->u>>r)&1) {
- if(i==0||((unneeded_reg[i-1]>>r)&1)) {
- cur->regmap[hr]=reg;
- cur->dirty&=~(1<<hr);
- cur->isconst&=~(1<<hr);
- return;
- }
- }
- }
- else
- {
- if((cur->uu>>(r&63))&1) {
- if(i==0||((unneeded_reg_upper[i-1]>>(r&63))&1)) {
- cur->regmap[hr]=reg;
- cur->dirty&=~(1<<hr);
- cur->isconst&=~(1<<hr);
- return;
- }
+ assert(r < 64);
+ if((cur->u>>r)&1) {
+ if(i==0||((unneeded_reg[i-1]>>r)&1)) {
+ cur->regmap[hr]=reg;
+ cur->dirty&=~(1<<hr);
+ cur->isconst&=~(1<<hr);
+ return;
}
}
}
// Don't evict the cycle count at entry points, otherwise the entry
// stub will have to write it.
if(bt[i]&&hsn[CCREG]>2) hsn[CCREG]=2;
- if(i>1&&hsn[CCREG]>2&&(itype[i-2]==RJUMP||itype[i-2]==UJUMP||itype[i-2]==CJUMP||itype[i-2]==SJUMP||itype[i-2]==FJUMP)) hsn[CCREG]=2;
+ if(i>1&&hsn[CCREG]>2&&(itype[i-2]==RJUMP||itype[i-2]==UJUMP||itype[i-2]==CJUMP||itype[i-2]==SJUMP)) hsn[CCREG]=2;
for(j=10;j>=3;j--)
{
for(r=1;r<=MAXREG;r++)
output_w32(0xe0b00000|rd_rn_rm(rt,rs1,rs2));
}
-static void emit_sbc(int rs1,int rs2,int rt)
-{
- assem_debug("sbc %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
- output_w32(0xe0c00000|rd_rn_rm(rt,rs1,rs2));
-}
-
-static void emit_sbcs(int rs1,int rs2,int rt)
-{
- assem_debug("sbcs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
- output_w32(0xe0d00000|rd_rn_rm(rt,rs1,rs2));
-}
-
static void emit_neg(int rs, int rt)
{
assem_debug("rsb %s,%s,#0\n",regname[rt],regname[rs]);
output_w32(0xe2600000|rd_rn_rm(rt,rs,0));
}
-static void emit_negs(int rs, int rt)
-{
- assem_debug("rsbs %s,%s,#0\n",regname[rt],regname[rs]);
- output_w32(0xe2700000|rd_rn_rm(rt,rs,0));
-}
-
static void emit_sub(int rs1,int rs2,int rt)
{
assem_debug("sub %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
output_w32(0xe0400000|rd_rn_rm(rt,rs1,rs2));
}
-static void emit_subs(int rs1,int rs2,int rt)
-{
- assem_debug("subs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
- output_w32(0xe0500000|rd_rn_rm(rt,rs1,rs2));
-}
-
static void emit_zeroreg(int rt)
{
assem_debug("mov %s,#0\n",regname[rt]);
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==FSREG) addr=(int)&FCR31;
if(r==INVCP) addr=(int)&invc_ptr;
u_int offset = addr-(u_int)&dynarec_local;
assert(offset<4096);
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==FSREG) addr=(int)&FCR31;
u_int offset = addr-(u_int)&dynarec_local;
assert(offset<4096);
assem_debug("str %s,fp+%d\n",regname[hr],offset);
output_w32(0xe1800000|rd_rn_rm(rt,rs1,rs2));
}
-static void emit_or_and_set_flags(int rs1,int rs2,int rt)
-{
- assem_debug("orrs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
- output_w32(0xe1900000|rd_rn_rm(rt,rs1,rs2));
-}
-
static void emit_orrshl_imm(u_int rs,u_int imm,u_int rt)
{
assert(rs<16);
output_w32(0xe2a00000|rd_rn_rm(rt,rs,0)|armval);
}
-static void emit_rscimm(int rs,int imm,u_int rt)
-{
- assert(0);
- u_int armval;
- genimm_checked(imm,&armval);
- assem_debug("rsc %s,%s,#%d\n",regname[rt],regname[rs],imm);
- output_w32(0xe2e00000|rd_rn_rm(rt,rs,0)|armval);
-}
-
static void emit_addimm64_32(int rsh,int rsl,int imm,int rth,int rtl)
{
// TODO: if(genimm(imm,&armval)) ...
output_w32(0x33a00000|rd_rn_rm(rt,0,0)|armval);
}
-static void emit_cmovs_imm(int imm,int rt)
-{
- assem_debug("movmi %s,#%d\n",regname[rt],imm);
- u_int armval;
- genimm_checked(imm,&armval);
- output_w32(0x43a00000|rd_rn_rm(rt,0,0)|armval);
-}
-
static void emit_cmovne_reg(int rs,int rt)
{
assem_debug("movne %s,%s\n",regname[rt],regname[rs]);
emit_cmovb_imm(1,rt);
}
-static void emit_slti64_32(int rsh,int rsl,int imm,int rt)
-{
- assert(rsh!=rt);
- emit_slti32(rsl,imm,rt);
- if(imm>=0)
- {
- emit_test(rsh,rsh);
- emit_cmovne_imm(0,rt);
- emit_cmovs_imm(1,rt);
- }
- else
- {
- emit_cmpimm(rsh,-1);
- emit_cmovne_imm(0,rt);
- emit_cmovl_imm(1,rt);
- }
-}
-
-static void emit_sltiu64_32(int rsh,int rsl,int imm,int rt)
-{
- assert(rsh!=rt);
- emit_sltiu32(rsl,imm,rt);
- if(imm>=0)
- {
- emit_test(rsh,rsh);
- emit_cmovne_imm(0,rt);
- }
- else
- {
- emit_cmpimm(rsh,-1);
- emit_cmovne_imm(1,rt);
- }
-}
-
static void emit_cmp(int rs,int rt)
{
assem_debug("cmp %s,%s\n",regname[rs],regname[rt]);
emit_cmovne_imm(1,rt);
}
-static void emit_set_gz64_32(int rsh, int rsl, int rt)
-{
- //assem_debug("set_gz64\n");
- emit_set_gz32(rsl,rt);
- emit_test(rsh,rsh);
- emit_cmovne_imm(1,rt);
- emit_cmovs_imm(0,rt);
-}
-
-static void emit_set_nz64_32(int rsh, int rsl, int rt)
-{
- //assem_debug("set_nz64\n");
- emit_or_and_set_flags(rsh,rsl,rt);
- emit_cmovne_imm(1,rt);
-}
-
static void emit_set_if_less32(int rs1, int rs2, int rt)
{
//assem_debug("set if less (%%%s,%%%s),%%%s\n",regname[rs1],regname[rs2],regname[rt]);
emit_cmovb_imm(1,rt);
}
-static void emit_set_if_less64_32(int u1, int l1, int u2, int l2, int rt)
-{
- //assem_debug("set if less64 (%%%s,%%%s,%%%s,%%%s),%%%s\n",regname[u1],regname[l1],regname[u2],regname[l2],regname[rt]);
- assert(u1!=rt);
- assert(u2!=rt);
- emit_cmp(l1,l2);
- emit_movimm(0,rt);
- emit_sbcs(u1,u2,HOST_TEMPREG);
- emit_cmovl_imm(1,rt);
-}
-
-static void emit_set_if_carry64_32(int u1, int l1, int u2, int l2, int rt)
-{
- //assem_debug("set if carry64 (%%%s,%%%s,%%%s,%%%s),%%%s\n",regname[u1],regname[l1],regname[u2],regname[l2],regname[rt]);
- assert(u1!=rt);
- assert(u2!=rt);
- emit_cmp(l1,l2);
- emit_movimm(0,rt);
- emit_sbcs(u1,u2,HOST_TEMPREG);
- emit_cmovb_imm(1,rt);
-}
-
#ifdef DRC_DBG
extern void gen_interupt();
extern void do_insn_cmp();
emit_call(&verify_code_ds);
}
+// FP_STUB
static void do_cop1stub(int n)
{
literal_pool(256);
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);
+ load_all_consts(regs[i].regmap_entry,regs[i].wasdirty,i);
//if(i_regs!=®s[i]) printf("oops: regs[i]=%x i_regs=%x",(int)®s[i],(int)i_regs);
}
//else {printf("fp exception in delay slot\n");}
- wb_dirtys(i_regs->regmap_entry,i_regs->was32,i_regs->wasdirty);
+ wb_dirtys(i_regs->regmap_entry,i_regs->wasdirty);
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...
signed char s=get_reg(i_regs->regmap,rs1[i]);
char copr=(source[i]>>11)&0x1f;
assert(s>=0);
- wb_register(rs1[i],i_regs->regmap,i_regs->dirty,i_regs->is32);
+ wb_register(rs1[i],i_regs->regmap,i_regs->dirty);
if(copr==9||copr==11||copr==12||copr==13) {
emit_readword(&last_count,HOST_TEMPREG);
emit_loadreg(CCREG,HOST_CCREG); // TODO: do proper reg alloc
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));
- cop1_usable=0;
}
else
{
assert(opcode2[i]==0x10);
- if((source[i]&0x3f)==0x10) // RFE
+ //if((source[i]&0x3f)==0x10) // RFE
{
emit_readword(&Status,0);
emit_andimm(0,0x3c,1);
static void cop1_unusable(int i,struct regstat *i_regs)
{
// XXX: should just just do the exception instead
- if(!cop1_usable) {
+ //if(!cop1_usable)
+ {
void *jaddr=out;
emit_jmp(0);
add_stub_r(FP_STUB,jaddr,out,i,0,i_regs,is_delayslot,0);
- cop1_usable=1;
}
}
cop1_unusable(i, i_regs);
}
-static void fconv_assemble_arm(int i,struct regstat *i_regs)
-{
- cop1_unusable(i, i_regs);
-}
-#define fconv_assemble fconv_assemble_arm
-
-static void fcomp_assemble(int i,struct regstat *i_regs)
-{
- cop1_unusable(i, i_regs);
-}
-
-static void float_assemble(int i,struct regstat *i_regs)
-{
- cop1_unusable(i, i_regs);
-}
-
static void multdiv_assemble_arm(int i,struct regstat *i_regs)
{
// case 0x18: MULT
#endif
}
-static void wb_valid(signed char pre[],signed char entry[],u_int dirty_pre,u_int dirty,uint64_t is32_pre,uint64_t u,uint64_t uu)
+static void wb_valid(signed char pre[],signed char entry[],u_int dirty_pre,u_int dirty,uint64_t u)
{
//if(dirty_pre==dirty) return;
int hr,reg;
if(((dirty_pre&~dirty)>>hr)&1) {
if(reg>0&®<34) {
emit_storereg(reg,hr);
- if( ((is32_pre&~uu)>>reg)&1 ) {
- emit_sarimm(hr,31,HOST_TEMPREG);
- emit_storereg(reg|64,HOST_TEMPREG);
- }
}
else if(reg>=64) {
- emit_storereg(reg,hr);
+ assert(0);
}
}
}