16 |
#include <fcntl.h> |
#include <fcntl.h> |
17 |
#include <assert.h> |
#include <assert.h> |
18 |
|
|
19 |
|
#include "sbox.h" |
20 |
#include "cpu.h" |
#include "cpu.h" |
21 |
#include "device.h" |
#include "device.h" |
22 |
#include "mips64.h" |
#include "mips64.h" |
83 |
for(i=0,count=0;mips64_insn_tags[i].emit;i++) |
for(i=0,count=0;mips64_insn_tags[i].emit;i++) |
84 |
count++; |
count++; |
85 |
|
|
86 |
ilt = ilt_create(count+1, |
ilt = ilt_create("mips64j",count, |
87 |
(ilt_get_insn_cbk_t)mips64_jit_get_insn, |
(ilt_get_insn_cbk_t)mips64_jit_get_insn, |
88 |
(ilt_check_cbk_t)mips64_jit_chk_lo, |
(ilt_check_cbk_t)mips64_jit_chk_lo, |
89 |
(ilt_check_cbk_t)mips64_jit_chk_hi); |
(ilt_check_cbk_t)mips64_jit_chk_hi); |
99 |
int i; |
int i; |
100 |
|
|
101 |
/* Physical mapping for executable pages */ |
/* Physical mapping for executable pages */ |
102 |
len = 1048576 * sizeof(void *); |
len = MIPS_JIT_PC_HASH_SIZE * sizeof(void *); |
103 |
cpu->exec_phys_map = m_memalign(4096,len); |
cpu->exec_blk_map = m_memalign(4096,len); |
104 |
memset(cpu->exec_phys_map,0,len); |
memset(cpu->exec_blk_map,0,len); |
105 |
|
|
106 |
/* Get area size */ |
/* Get area size */ |
107 |
if (!(area_size = cpu->vm->exec_area_size)) |
if (!(area_size = cpu->vm->exec_area_size)) |
152 |
u_int mips64_jit_flush(cpu_mips_t *cpu,u_int threshold) |
u_int mips64_jit_flush(cpu_mips_t *cpu,u_int threshold) |
153 |
{ |
{ |
154 |
mips64_jit_tcb_t *p,*next; |
mips64_jit_tcb_t *p,*next; |
155 |
|
m_uint32_t pc_hash; |
156 |
u_int count = 0; |
u_int count = 0; |
157 |
|
|
158 |
if (!threshold) |
if (!threshold) |
162 |
next = p->next; |
next = p->next; |
163 |
|
|
164 |
if (p->acc_count <= threshold) { |
if (p->acc_count <= threshold) { |
165 |
cpu->exec_phys_map[p->phys_page] = NULL; |
pc_hash = mips64_jit_get_pc_hash(p->start_pc); |
166 |
|
cpu->exec_blk_map[pc_hash] = NULL; |
167 |
mips64_jit_tcb_free(cpu,p,TRUE); |
mips64_jit_tcb_free(cpu,p,TRUE); |
168 |
count++; |
count++; |
169 |
} |
} |
195 |
free(cpu->exec_page_array); |
free(cpu->exec_page_array); |
196 |
|
|
197 |
/* Free physical mapping for executable pages */ |
/* Free physical mapping for executable pages */ |
198 |
free(cpu->exec_phys_map); |
free(cpu->exec_blk_map); |
199 |
} |
} |
200 |
|
|
201 |
/* Allocate an exec page */ |
/* Allocate an exec page */ |
321 |
return(dev->handler(vm->boot_cpu,dev,offset,op_size,op_type,data)); |
return(dev->handler(vm->boot_cpu,dev,offset,op_size,op_type,data)); |
322 |
} |
} |
323 |
|
|
324 |
|
/* Check if an instruction is in a delay slot or not */ |
325 |
|
int mips64_jit_is_delay_slot(mips64_jit_tcb_t *b,m_uint64_t pc) |
326 |
|
{ |
327 |
|
struct mips64_insn_tag *tag; |
328 |
|
m_uint32_t offset,insn; |
329 |
|
|
330 |
|
offset = (pc - b->start_pc) >> 2; |
331 |
|
|
332 |
|
if (!offset) |
333 |
|
return(FALSE); |
334 |
|
|
335 |
|
/* Fetch the previous instruction to determine if it is a jump */ |
336 |
|
insn = vmtoh32(b->mips_code[offset-1]); |
337 |
|
tag = insn_tag_find(insn); |
338 |
|
assert(tag != NULL); |
339 |
|
return(!tag->delay_slot); |
340 |
|
} |
341 |
|
|
342 |
/* Fetch a MIPS instruction and emit corresponding translated code */ |
/* Fetch a MIPS instruction and emit corresponding translated code */ |
343 |
struct mips64_insn_tag *mips64_jit_fetch_and_emit(cpu_mips_t *cpu, |
struct mips64_insn_tag *mips64_jit_fetch_and_emit(cpu_mips_t *cpu, |
344 |
mips64_jit_tcb_t *block, |
mips64_jit_tcb_t *block, |
717 |
#endif |
#endif |
718 |
} |
} |
719 |
|
|
|
/* Check if the specified address belongs to the specified block */ |
|
|
int mips64_jit_tcb_local_addr(mips64_jit_tcb_t *block,m_uint64_t vaddr, |
|
|
u_char **jit_addr) |
|
|
{ |
|
|
if ((vaddr >= block->start_pc) && |
|
|
((vaddr - block->start_pc) < MIPS_MIN_PAGE_SIZE)) |
|
|
{ |
|
|
*jit_addr = mips64_jit_tcb_get_host_ptr(block,vaddr); |
|
|
return(1); |
|
|
} |
|
|
|
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* Check if PC register matches the compiled block virtual address */ |
|
|
static forced_inline |
|
|
int mips64_jit_tcb_match(cpu_mips_t *cpu,mips64_jit_tcb_t *block) |
|
|
{ |
|
|
m_uint64_t vpage; |
|
|
|
|
|
vpage = cpu->pc & ~(m_uint64_t)MIPS_MIN_PAGE_IMASK; |
|
|
return(block->start_pc == vpage); |
|
|
} |
|
|
|
|
720 |
/* Execute compiled MIPS code */ |
/* Execute compiled MIPS code */ |
721 |
void *mips64_jit_run_cpu(cpu_gen_t *gen) |
void *mips64_jit_run_cpu(cpu_gen_t *gen) |
722 |
{ |
{ |
723 |
cpu_mips_t *cpu = CPU_MIPS64(gen); |
cpu_mips_t *cpu = CPU_MIPS64(gen); |
724 |
pthread_t timer_irq_thread; |
pthread_t timer_irq_thread; |
725 |
mips64_jit_tcb_t *block; |
mips64_jit_tcb_t *block; |
|
m_uint32_t phys_page; |
|
726 |
int timer_irq_check = 0; |
int timer_irq_check = 0; |
727 |
|
m_uint32_t pc_hash; |
728 |
|
|
729 |
if (pthread_create(&timer_irq_thread,NULL, |
if (pthread_create(&timer_irq_thread,NULL, |
730 |
(void *)mips64_timer_irq_run,cpu)) |
(void *)mips64_timer_irq_run,cpu)) |
737 |
} |
} |
738 |
|
|
739 |
gen->cpu_thread_running = TRUE; |
gen->cpu_thread_running = TRUE; |
|
|
|
740 |
start_cpu: |
start_cpu: |
741 |
gen->idle_count = 0; |
gen->idle_count = 0; |
742 |
|
|
766 |
} |
} |
767 |
} |
} |
768 |
|
|
769 |
/* Get the physical page address corresponding to PC register */ |
pc_hash = mips64_jit_get_pc_hash(cpu->pc); |
770 |
if (unlikely(cpu->translate(cpu,cpu->pc,&phys_page))) { |
block = cpu->exec_blk_map[pc_hash]; |
|
fprintf(stderr,"VM '%s': no physical page for CPU%u PC=0x%llx\n", |
|
|
cpu->vm->name,gen->id,cpu->pc); |
|
|
cpu_stop(gen); |
|
|
break; |
|
|
} |
|
|
|
|
|
block = cpu->exec_phys_map[phys_page]; |
|
771 |
|
|
772 |
/* No block found, compile the page */ |
/* No block found, compile the page */ |
773 |
if (unlikely(!block) || unlikely(!mips64_jit_tcb_match(cpu,block))) |
if (unlikely(!block) || unlikely(!mips64_jit_tcb_match(cpu,block))) |
774 |
{ |
{ |
775 |
if (block != NULL) { |
if (block != NULL) { |
776 |
mips64_jit_tcb_free(cpu,block,TRUE); |
mips64_jit_tcb_free(cpu,block,TRUE); |
777 |
cpu->exec_phys_map[phys_page] = NULL; |
cpu->exec_blk_map[pc_hash] = NULL; |
778 |
} |
} |
779 |
|
|
780 |
block = mips64_jit_tcb_compile(cpu,cpu->pc); |
block = mips64_jit_tcb_compile(cpu,cpu->pc); |
786 |
break; |
break; |
787 |
} |
} |
788 |
|
|
789 |
block->phys_page = phys_page; |
cpu->exec_blk_map[pc_hash] = block; |
|
cpu->exec_phys_map[phys_page] = block; |
|
790 |
} |
} |
791 |
|
|
792 |
#if DEBUG_BLOCK_TIMESTAMP |
#if DEBUG_BLOCK_TIMESTAMP |