return itype[i] == RJUMP || itype[i] == UJUMP || itype[i] == CJUMP || itype[i] == SJUMP;
}
+static int ds_writes_rjump_rs(int i)
+{
+ return rs1[i] != 0 && (rs1[i] == rt1[i+1] || rs1[i] == rt2[i+1]);
+}
+
static u_int get_page(u_int vaddr)
{
u_int page=vaddr&~0xe0000000;
inv_debug("INVALIDATE: kill pointer to %x (%p)\n",head->vaddr,head->addr);
void *host_addr=find_extjump_insn(head->addr);
mark_clear_cache(host_addr);
- set_jump_target(host_addr, head->addr);
+ set_jump_target(host_addr, head->addr); // point back to dyna_linker
next=head->next;
free(head);
head=next;
// Add an entry to jump_out after making a link
// src should point to code by emit_extjump2()
-void add_link(u_int vaddr,void *src)
+void add_jump_out(u_int vaddr,void *src)
{
u_int page=get_page(vaddr);
- inv_debug("add_link: %p -> %x (%d)\n",src,vaddr,page);
+ inv_debug("add_jump_out: %p -> %x (%d)\n",src,vaddr,page);
check_extjump2(src);
ll_add(jump_out+page,vaddr,src);
- //void *ptr=get_pointer(src);
- //inv_debug("add_link: Pointer is to %p\n",ptr);
+ //inv_debug("add_jump_out: to %p\n",get_pointer(src));
}
// If a code block was found to be unmodified (bit was set in
if(itype[i]==RJUMP)
{
int r=get_reg(branch_regs[i].regmap,rs1[i]);
- if(rs1[i]==rt1[i+1]||rs1[i]==rt2[i+1]) {
+ if (ds_writes_rjump_rs(i)) {
r=get_reg(branch_regs[i].regmap,RTEMP);
}
emit_writeword(r,&pcaddr);
int ra_done=0;
rs=get_reg(branch_regs[i].regmap,rs1[i]);
assert(rs>=0);
- if(rs1[i]==rt1[i+1]||rs1[i]==rt2[i+1]) {
+ if (ds_writes_rjump_rs(i)) {
// Delay slot abuse, make a copy of the branch address register
temp=get_reg(branch_regs[i].regmap,RTEMP);
assert(temp>=0);
emit_extjump_ds(branch_addr, target_addr);
if(compiled_target_addr) {
set_jump_target(branch_addr, compiled_target_addr);
- add_link(target_addr,stub);
+ add_jump_out(target_addr,stub);
}
else set_jump_target(branch_addr, stub);
if(likely[i]) {
emit_extjump_ds(branch_addr, target_addr);
if(compiled_target_addr) {
set_jump_target(branch_addr, compiled_target_addr);
- add_link(target_addr,stub);
+ add_jump_out(target_addr,stub);
}
else set_jump_target(branch_addr, stub);
}
u_int page=get_page(vaddr);
u_int vpage=get_vpage(vaddr);
ll_add(jump_dirty+vpage,vaddr,(void *)out);
- do_dirty_stub_ds();
+ do_dirty_stub_ds(slen*4);
ll_add(jump_in+page,vaddr,(void *)out);
assert(regs[0].regmap_entry[HOST_CCREG]==CCREG);
if(regs[0].regmap[HOST_CCREG]!=CCREG)
{
case 0x00: strcpy(insn[i],"BLTZ"); type=SJUMP; break;
case 0x01: strcpy(insn[i],"BGEZ"); type=SJUMP; break;
- case 0x02: strcpy(insn[i],"BLTZL"); type=SJUMP; break;
- case 0x03: strcpy(insn[i],"BGEZL"); type=SJUMP; break;
- case 0x08: strcpy(insn[i],"TGEI"); type=NI; break;
- case 0x09: strcpy(insn[i],"TGEIU"); type=NI; break;
- case 0x0A: strcpy(insn[i],"TLTI"); type=NI; break;
- case 0x0B: strcpy(insn[i],"TLTIU"); type=NI; break;
- case 0x0C: strcpy(insn[i],"TEQI"); type=NI; break;
- case 0x0E: strcpy(insn[i],"TNEI"); type=NI; break;
+ //case 0x02: strcpy(insn[i],"BLTZL"); type=SJUMP; break;
+ //case 0x03: strcpy(insn[i],"BGEZL"); type=SJUMP; break;
+ //case 0x08: strcpy(insn[i],"TGEI"); type=NI; break;
+ //case 0x09: strcpy(insn[i],"TGEIU"); type=NI; break;
+ //case 0x0A: strcpy(insn[i],"TLTI"); type=NI; break;
+ //case 0x0B: strcpy(insn[i],"TLTIU"); type=NI; break;
+ //case 0x0C: strcpy(insn[i],"TEQI"); type=NI; break;
+ //case 0x0E: strcpy(insn[i],"TNEI"); type=NI; break;
case 0x10: strcpy(insn[i],"BLTZAL"); type=SJUMP; break;
case 0x11: strcpy(insn[i],"BGEZAL"); type=SJUMP; break;
- case 0x12: strcpy(insn[i],"BLTZALL"); type=SJUMP; break;
- case 0x13: strcpy(insn[i],"BGEZALL"); type=SJUMP; break;
+ //case 0x12: strcpy(insn[i],"BLTZALL"); type=SJUMP; break;
+ //case 0x13: strcpy(insn[i],"BGEZALL"); type=SJUMP; break;
}
break;
case 0x02: strcpy(insn[i],"J"); type=UJUMP; break;
else if(type==CJUMP||type==SJUMP)
ba[i]=start+i*4+4+((signed int)((unsigned int)source[i]<<16)>>14);
else ba[i]=-1;
+
+ /* simplify always (not)taken branches */
+ if (type == CJUMP && rs1[i] == rs2[i]) {
+ rs1[i] = rs2[i] = 0;
+ if (!(op & 1)) {
+ itype[i] = type = UJUMP;
+ rs2[i] = CCREG;
+ }
+ }
+ else if (type == SJUMP && rs1[i] == 0 && (op2 & 1))
+ itype[i] = type = UJUMP;
+
+ /* messy cases to just pass over to the interpreter */
if (i > 0 && is_jump(i-1)) {
int do_in_intrp=0;
// branch in delay slot?
- if(type==RJUMP||type==UJUMP||type==CJUMP||type==SJUMP) {
+ if (is_jump(i)) {
// don't handle first branch and call interpreter if it's hit
SysPrintf("branch in delay slot @%08x (%08x)\n", addr + i*4, addr);
do_in_intrp=1;
i--; // don't compile the DS
}
}
+
/* Is this the end of the block? */
if (i > 0 && is_ujump(i-1)) {
if(rt1[i-1]==0) { // Continue past subroutine call (JAL)
clear_const(¤t,rt1[i]);
alloc_cc(¤t,i);
dirty_reg(¤t,CCREG);
- if(rs1[i]!=rt1[i+1]&&rs1[i]!=rt2[i+1]) {
+ if (!ds_writes_rjump_rs(i)) {
alloc_reg(¤t,i,rs1[i]);
if (rt1[i]!=0) {
alloc_reg(¤t,i,rt1[i]);
literal_pool_jumpover(256);
}
}
- //assert(is_ujump(i-2));
+
+ assert(slen > 0);
+ if (itype[slen-1] == INTCALL) {
+ // no ending needed for this block since INTCALL never returns
+ }
// If the block did not end with an unconditional branch,
// add a jump to the next instruction.
- if(i>1) {
+ else if (i > 1) {
if(!is_ujump(i-2)&&itype[i-1]!=SPAN) {
assert(itype[i-1]!=UJUMP&&itype[i-1]!=CJUMP&&itype[i-1]!=SJUMP&&itype[i-1]!=RJUMP);
assert(i==slen);
emit_extjump(link_addr[i].addr, link_addr[i].target);
if (addr) {
set_jump_target(link_addr[i].addr, addr);
- add_link(link_addr[i].target,stub);
+ add_jump_out(link_addr[i].target,stub);
}
else
set_jump_target(link_addr[i].addr, stub);
//#endif
}
}
+
+ u_int source_len = slen*4;
+ if (itype[slen-1] == INTCALL && source_len > 4)
+ // no need to treat the last instruction as compiled
+ // as interpreter fully handles it
+ source_len -= 4;
+
+ if ((u_char *)copy + source_len > (u_char *)shadow + sizeof(shadow))
+ copy = shadow;
+
// External Branch Targets (jump_in)
- if(copy+slen*4>(void *)shadow+sizeof(shadow)) copy=shadow;
for(i=0;i<slen;i++)
{
if(bt[i]||i==0)
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,out);
- void *entry_point = do_dirty_stub(i);
+ void *entry_point = do_dirty_stub(i, source_len);
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.
#endif
assert(out - (u_char *)beginning < MAX_OUTPUT_BLOCK_SIZE);
//printf("shadow buffer: %p-%p\n",copy,(u_char *)copy+slen*4);
- memcpy(copy,source,slen*4);
- copy+=slen*4;
+ memcpy(copy, source, source_len);
+ copy += source_len;
end_block(beginning);