}
}
-void ll_remove_matching_addrs(struct ll_entry **head,uintptr_t addr,int shift)
+static void ll_remove_matching_addrs(struct ll_entry **head,
+ uintptr_t base_offs_s, int shift)
{
struct ll_entry *next;
while(*head) {
- if(((uintptr_t)((*head)->addr)>>shift)==(addr>>shift) ||
- ((uintptr_t)((*head)->addr-MAX_OUTPUT_BLOCK_SIZE)>>shift)==(addr>>shift))
+ uintptr_t o1 = (u_char *)(*head)->addr - ndrc->translation_cache;
+ uintptr_t o2 = o1 - MAX_OUTPUT_BLOCK_SIZE;
+ if ((o1 >> shift) == base_offs_s || (o2 >> shift) == base_offs_s)
{
inv_debug("EXP: Remove pointer to %p (%x)\n",(*head)->addr,(*head)->vaddr);
remove_hash((*head)->vaddr);
}
// Dereference the pointers and remove if it matches
-static void ll_kill_pointers(struct ll_entry *head,uintptr_t addr,int shift)
+static void ll_kill_pointers(struct ll_entry *head,
+ uintptr_t base_offs_s, int shift)
{
while(head) {
- uintptr_t ptr = (uintptr_t)get_pointer(head->addr);
- inv_debug("EXP: Lookup pointer to %lx at %p (%x)\n",(long)ptr,head->addr,head->vaddr);
- if(((ptr>>shift)==(addr>>shift)) ||
- (((ptr-MAX_OUTPUT_BLOCK_SIZE)>>shift)==(addr>>shift)))
+ u_char *ptr = get_pointer(head->addr);
+ uintptr_t o1 = ptr - ndrc->translation_cache;
+ uintptr_t o2 = o1 - MAX_OUTPUT_BLOCK_SIZE;
+ inv_debug("EXP: Lookup pointer to %p at %p (%x)\n",ptr,head->addr,head->vaddr);
+ if ((o1 >> shift) == base_offs_s || (o2 >> shift) == base_offs_s)
{
inv_debug("EXP: Kill pointer at %p (%x)\n",head->addr,head->vaddr);
void *host_addr=find_extjump_insn(head->addr);
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
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)
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);
while(expirep!=end)
{
int shift=TARGET_SIZE_2-3; // Divide into 8 blocks
- uintptr_t base=(uintptr_t)ndrc->translation_cache+((expirep>>13)<<shift); // Base address of this block
+ uintptr_t base_offs = ((uintptr_t)(expirep >> 13) << shift); // Base offset of this block
+ uintptr_t base_offs_s = base_offs >> shift;
inv_debug("EXP: Phase %d\n",expirep);
switch((expirep>>11)&3)
{
case 0:
// Clear jump_in and jump_dirty
- ll_remove_matching_addrs(jump_in+(expirep&2047),base,shift);
- ll_remove_matching_addrs(jump_dirty+(expirep&2047),base,shift);
- ll_remove_matching_addrs(jump_in+2048+(expirep&2047),base,shift);
- ll_remove_matching_addrs(jump_dirty+2048+(expirep&2047),base,shift);
+ ll_remove_matching_addrs(jump_in+(expirep&2047),base_offs_s,shift);
+ ll_remove_matching_addrs(jump_dirty+(expirep&2047),base_offs_s,shift);
+ ll_remove_matching_addrs(jump_in+2048+(expirep&2047),base_offs_s,shift);
+ ll_remove_matching_addrs(jump_dirty+2048+(expirep&2047),base_offs_s,shift);
break;
case 1:
// Clear pointers
- ll_kill_pointers(jump_out[expirep&2047],base,shift);
- ll_kill_pointers(jump_out[(expirep&2047)+2048],base,shift);
+ ll_kill_pointers(jump_out[expirep&2047],base_offs_s,shift);
+ ll_kill_pointers(jump_out[(expirep&2047)+2048],base_offs_s,shift);
break;
case 2:
// Clear hash table
for(i=0;i<32;i++) {
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)) {
+ uintptr_t o1 = (u_char *)ht_bin->tcaddr[1] - ndrc->translation_cache;
+ uintptr_t o2 = o1 - MAX_OUTPUT_BLOCK_SIZE;
+ if ((o1 >> shift) == base_offs_s || (o2 >> shift) == base_offs_s) {
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)) {
+ o1 = (u_char *)ht_bin->tcaddr[0] - ndrc->translation_cache;
+ o2 = o1 - MAX_OUTPUT_BLOCK_SIZE;
+ if ((o1 >> shift) == base_offs_s || (o2 >> shift) == base_offs_s) {
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];
// Clear jump_out
if((expirep&2047)==0)
do_clear_cache();
- ll_remove_matching_addrs(jump_out+(expirep&2047),base,shift);
- ll_remove_matching_addrs(jump_out+2048+(expirep&2047),base,shift);
+ ll_remove_matching_addrs(jump_out+(expirep&2047),base_offs_s,shift);
+ ll_remove_matching_addrs(jump_out+2048+(expirep&2047),base_offs_s,shift);
break;
}
expirep=(expirep+1)&65535;