- set_jump_target(nottaken,(int)out);
- assem_debug("1:\n");
- if(!likely[i]) {
- wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,regs[i].is32,
- ds_unneeded,ds_unneeded_upper);
- load_regs(regs[i].regmap,branch_regs[i].regmap,regs[i].was32,rs1[i+1],rs2[i+1]);
- address_generation(i+1,&branch_regs[i],0);
- load_regs(regs[i].regmap,branch_regs[i].regmap,regs[i].was32,CCREG,CCREG);
- ds_assemble(i+1,&branch_regs[i]);
- }
- cc=get_reg(branch_regs[i].regmap,CCREG);
- if(cc==-1&&!likely[i]) {
- // 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_DIVIDER*(ccadj[i]+2),HOST_CCREG);
- int jaddr=(int)out;
- emit_jns(0);
- add_stub(CC_STUB,jaddr,(int)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_DIVIDER*(ccadj[i]+2),cc);
- int jaddr=(int)out;
- emit_jns(0);
- add_stub(CC_STUB,jaddr,(int)out,0,i,start+i*4+8,likely[i]?NULLDS:NOTTAKEN,0);
- }
- }
- }
-}
-
-void fjump_assemble(int i,struct regstat *i_regs)
-{
- signed char *i_regmap=i_regs->regmap;
- int cc;
- int match;
- 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;
- int invert=0;
- int internal=internal_branch(branch_regs[i].is32,ba[i]);
- if(i==(ba[i]-start)>>2) assem_debug("idle loop\n");
- if(!match) invert=1;
- #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
- if(i>(ba[i]-start)>>2) invert=1;
- #endif
-
- if(ooo[i]) {
- fs=get_reg(branch_regs[i].regmap,FSREG);
- address_generation(i+1,i_regs,regs[i].regmap_entry); // Is this okay?
- }
- else {
- fs=get_reg(i_regmap,FSREG);
- }
-
- // Check cop1 unusable
- if(!cop1_usable) {
- cs=get_reg(i_regmap,CSREG);
- assert(cs>=0);
- emit_testimm(cs,0x20000000);
- eaddr=(int)out;
- emit_jeq(0);
- add_stub(FP_STUB,eaddr,(int)out,i,cs,(int)i_regs,0,0);
- cop1_usable=1;
- }
-
- if(ooo[i]) {
- // Out of order execution (delay slot first)
- //printf("OOOE\n");
- ds_assemble(i+1,i_regs);
- int adj;
- uint64_t bc_unneeded=branch_regs[i].u;
- uint64_t bc_unneeded_upper=branch_regs[i].uu;
- bc_unneeded&=~((1LL<<rs1[i])|(1LL<<rs2[i]));
- bc_unneeded_upper&=~((1LL<<us1[i])|(1LL<<us2[i]));
- bc_unneeded|=1;
- bc_unneeded_upper|=1;
- wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,regs[i].is32,
- bc_unneeded,bc_unneeded_upper);
- load_regs(regs[i].regmap,branch_regs[i].regmap,regs[i].was32,rs1[i],rs1[i]);
- load_regs(regs[i].regmap,branch_regs[i].regmap,regs[i].was32,CCREG,CCREG);
- cc=get_reg(branch_regs[i].regmap,CCREG);
- assert(cc==HOST_CCREG);
- do_cc(i,branch_regs[i].regmap,&adj,-1,0,invert);
- assem_debug("cycle count (adj)\n");
- if(1) {
- int nottaken=0;
- if(adj&&!invert) emit_addimm(cc,CLOCK_DIVIDER*(ccadj[i]+2-adj),cc);
- if(1) {
- assert(fs>=0);
- emit_testimm(fs,0x800000);
- if(source[i]&0x10000) // BC1T
- {
- if(invert){
- nottaken=(int)out;
- emit_jeq(1);
- }else{
- add_to_linker((int)out,ba[i],internal);
- emit_jne(0);
- }
- }
- else // BC1F
- if(invert){
- nottaken=(int)out;
- emit_jne(1);
- }else{
- add_to_linker((int)out,ba[i],internal);
- emit_jeq(0);
- }
- {
- }
- } // if(!only32)
-
- if(invert) {
- if(adj) emit_addimm(cc,-CLOCK_DIVIDER*adj,cc);
- #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
- else if(match) emit_addnop(13);
- #endif
- store_regs_bt(branch_regs[i].regmap,branch_regs[i].is32,branch_regs[i].dirty,ba[i]);
- load_regs_bt(branch_regs[i].regmap,branch_regs[i].is32,branch_regs[i].dirty,ba[i]);
- if(internal)
- assem_debug("branch: internal\n");
- else
- assem_debug("branch: external\n");
- if(internal&&is_ds[(ba[i]-start)>>2]) {
- ds_assemble_entry(i);
- }
- else {
- add_to_linker((int)out,ba[i],internal);
- emit_jmp(0);
- }
- set_jump_target(nottaken,(int)out);
- }
-
- if(adj) {
- if(!invert) emit_addimm(cc,CLOCK_DIVIDER*adj,cc);
- }
- } // (!unconditional)
- } // if(ooo)
- else
- {
- // In-order execution (branch first)
- //printf("IOE\n");
- int nottaken=0;
- 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) {
- assert(fs>=0);
- emit_testimm(fs,0x800000);
- if(source[i]&0x10000) // BC1T
- {
- nottaken=(int)out;
- emit_jeq(1);
- }
- else // BC1F
- {
- nottaken=(int)out;
- emit_jne(1);
- }
- }
- } // if(!unconditional)
- int adj;
- uint64_t ds_unneeded=branch_regs[i].u;
- uint64_t ds_unneeded_upper=branch_regs[i].uu;
- ds_unneeded&=~((1LL<<rs1[i+1])|(1LL<<rs2[i+1]));
- ds_unneeded_upper&=~((1LL<<us1[i+1])|(1LL<<us2[i+1]));
- if((~ds_unneeded_upper>>rt1[i+1])&1) ds_unneeded_upper&=~((1LL<<dep1[i+1])|(1LL<<dep2[i+1]));
- ds_unneeded|=1;
- ds_unneeded_upper|=1;
- // branch taken
- //assem_debug("1:\n");
- wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,regs[i].is32,
- ds_unneeded,ds_unneeded_upper);
- // load regs
- load_regs(regs[i].regmap,branch_regs[i].regmap,regs[i].was32,rs1[i+1],rs2[i+1]);
- address_generation(i+1,&branch_regs[i],0);
- load_regs(regs[i].regmap,branch_regs[i].regmap,regs[i].was32,CCREG,INVCP);
- ds_assemble(i+1,&branch_regs[i]);
- cc=get_reg(branch_regs[i].regmap,CCREG);
- if(cc==-1) {
- emit_loadreg(CCREG,cc=HOST_CCREG);
- // CHECK: Is the following instruction (fall thru) allocated ok?
- }
- assert(cc==HOST_CCREG);
- store_regs_bt(branch_regs[i].regmap,branch_regs[i].is32,branch_regs[i].dirty,ba[i]);
- do_cc(i,i_regmap,&adj,ba[i],TAKEN,0);
- assem_debug("cycle count (adj)\n");
- if(adj) emit_addimm(cc,CLOCK_DIVIDER*(ccadj[i]+2-adj),cc);
- load_regs_bt(branch_regs[i].regmap,branch_regs[i].is32,branch_regs[i].dirty,ba[i]);
- if(internal)
- assem_debug("branch: internal\n");
- else
- assem_debug("branch: external\n");
- if(internal&&is_ds[(ba[i]-start)>>2]) {
- ds_assemble_entry(i);
- }
- else {
- add_to_linker((int)out,ba[i],internal);
- emit_jmp(0);
- }
-
- // branch not taken
- if(1) { // <- FIXME (don't need this)
- set_jump_target(nottaken,(int)out);