53 |
for(i=0,count=0;ppc32_insn_tags[i].emit;i++) |
for(i=0,count=0;ppc32_insn_tags[i].emit;i++) |
54 |
count++; |
count++; |
55 |
|
|
56 |
ilt = ilt_create(count+1, |
ilt = ilt_create("ppc32j",count, |
57 |
(ilt_get_insn_cbk_t)ppc32_jit_get_insn, |
(ilt_get_insn_cbk_t)ppc32_jit_get_insn, |
58 |
(ilt_check_cbk_t)ppc32_jit_chk_lo, |
(ilt_check_cbk_t)ppc32_jit_chk_lo, |
59 |
(ilt_check_cbk_t)ppc32_jit_chk_hi); |
(ilt_check_cbk_t)ppc32_jit_chk_hi); |
68 |
size_t len; |
size_t len; |
69 |
int i; |
int i; |
70 |
|
|
71 |
|
/* JIT mapping for executable pages */ |
72 |
|
len = PPC_JIT_IA_HASH_SIZE * sizeof(void *); |
73 |
|
cpu->exec_blk_map = m_memalign(4096,len); |
74 |
|
memset(cpu->exec_blk_map,0,len); |
75 |
|
|
76 |
/* Physical mapping for executable pages */ |
/* Physical mapping for executable pages */ |
77 |
len = 1048576 * sizeof(void *); |
len = PPC_JIT_PHYS_HASH_SIZE * sizeof(void *); |
78 |
cpu->exec_phys_map = m_memalign(4096,len); |
cpu->exec_phys_map = m_memalign(4096,len); |
79 |
memset(cpu->exec_phys_map,0,len); |
memset(cpu->exec_phys_map,0,len); |
80 |
|
|
127 |
u_int ppc32_jit_flush(cpu_ppc_t *cpu,u_int threshold) |
u_int ppc32_jit_flush(cpu_ppc_t *cpu,u_int threshold) |
128 |
{ |
{ |
129 |
ppc32_jit_tcb_t *p,*next; |
ppc32_jit_tcb_t *p,*next; |
130 |
|
m_uint32_t ia_hash; |
131 |
u_int count = 0; |
u_int count = 0; |
132 |
|
|
133 |
if (!threshold) |
if (!threshold) |
137 |
next = p->next; |
next = p->next; |
138 |
|
|
139 |
if (p->acc_count <= threshold) { |
if (p->acc_count <= threshold) { |
140 |
cpu->exec_phys_map[p->phys_page] = NULL; |
ia_hash = ppc32_jit_get_ia_hash(p->start_ia); |
141 |
ppc32_jit_tcb_free(cpu,p,TRUE); |
ppc32_jit_tcb_free(cpu,p,TRUE); |
142 |
|
|
143 |
|
if (cpu->exec_blk_map[ia_hash] == p) |
144 |
|
cpu->exec_blk_map[ia_hash] = NULL; |
145 |
count++; |
count++; |
146 |
} |
} |
147 |
} |
} |
171 |
/* Free the exec page array */ |
/* Free the exec page array */ |
172 |
free(cpu->exec_page_array); |
free(cpu->exec_page_array); |
173 |
|
|
174 |
|
/* Free JIT block mapping */ |
175 |
|
free(cpu->exec_blk_map); |
176 |
|
|
177 |
/* Free physical mapping for executable pages */ |
/* Free physical mapping for executable pages */ |
178 |
free(cpu->exec_phys_map); |
free(cpu->exec_phys_map); |
179 |
} |
} |
180 |
|
|
181 |
/* Allocate an exec page */ |
/* Allocate an exec page */ |
374 |
} |
} |
375 |
|
|
376 |
/* Adjust the JIT buffer if its size is not sufficient */ |
/* Adjust the JIT buffer if its size is not sufficient */ |
377 |
static int ppc32_jit_tcb_adjust_buffer(cpu_ppc_t *cpu, |
static int ppc32_jit_tcb_adjust_buffer(cpu_ppc_t *cpu,ppc32_jit_tcb_t *block) |
|
ppc32_jit_tcb_t *block) |
|
378 |
{ |
{ |
379 |
insn_exec_page_t *new_buffer; |
insn_exec_page_t *new_buffer; |
380 |
|
|
438 |
block->prev->next = block->next; |
block->prev->next = block->next; |
439 |
else |
else |
440 |
cpu->tcb_list = block->next; |
cpu->tcb_list = block->next; |
441 |
|
|
442 |
|
/* Remove the block from the physical mapping hash table */ |
443 |
|
if (block->phys_pprev) { |
444 |
|
if (block->phys_next) |
445 |
|
block->phys_next->phys_pprev = block->phys_pprev; |
446 |
|
|
447 |
|
*(block->phys_pprev) = block->phys_next; |
448 |
|
|
449 |
|
block->phys_pprev = NULL; |
450 |
|
block->phys_next = NULL; |
451 |
|
} |
452 |
} |
} |
453 |
|
|
454 |
/* Free the patch tables */ |
/* Free the patch tables */ |
463 |
|
|
464 |
/* Free the PowerPC-to-native code mapping */ |
/* Free the PowerPC-to-native code mapping */ |
465 |
free(block->jit_insn_ptr); |
free(block->jit_insn_ptr); |
466 |
|
|
|
/* Make the block return to the free list */ |
|
467 |
block->next = cpu->tcb_free_list; |
block->next = cpu->tcb_free_list; |
468 |
cpu->tcb_free_list = block; |
cpu->tcb_free_list = block; |
469 |
} |
} |
473 |
static ppc32_jit_tcb_t *ppc32_jit_tcb_create(cpu_ppc_t *cpu,m_uint32_t vaddr) |
static ppc32_jit_tcb_t *ppc32_jit_tcb_create(cpu_ppc_t *cpu,m_uint32_t vaddr) |
474 |
{ |
{ |
475 |
ppc32_jit_tcb_t *block = NULL; |
ppc32_jit_tcb_t *block = NULL; |
476 |
|
m_uint32_t phys_page; |
477 |
|
|
478 |
|
if (unlikely(cpu->translate(cpu,cpu->ia,PPC32_MTS_ICACHE,&phys_page))) |
479 |
|
return NULL; |
480 |
|
|
481 |
if (!(block = ppc32_jit_tcb_alloc(cpu))) |
if (!(block = ppc32_jit_tcb_alloc(cpu))) |
482 |
goto err_block_alloc; |
goto err_block_alloc; |
483 |
|
|
484 |
block->start_ia = vaddr; |
block->start_ia = vaddr; |
485 |
|
block->phys_page = phys_page; |
486 |
|
block->phys_hash = ppc32_jit_get_phys_hash(phys_page); |
487 |
|
|
488 |
/* Allocate the first JIT buffer */ |
/* Allocate the first JIT buffer */ |
489 |
if (!(block->jit_buffer = exec_page_alloc(cpu))) |
if (!(block->jit_buffer = exec_page_alloc(cpu))) |
569 |
|
|
570 |
cpu->tcb_list = block; |
cpu->tcb_list = block; |
571 |
|
|
572 |
|
/* Add the block to the physical mapping hash table */ |
573 |
|
block->phys_next = cpu->exec_phys_map[block->phys_hash]; |
574 |
|
block->phys_pprev = &cpu->exec_phys_map[block->phys_hash]; |
575 |
|
|
576 |
|
if (cpu->exec_phys_map[block->phys_hash] != NULL) |
577 |
|
cpu->exec_phys_map[block->phys_hash]->phys_pprev = &block->phys_next; |
578 |
|
|
579 |
|
cpu->exec_phys_map[block->phys_hash] = block; |
580 |
|
|
581 |
cpu->compiled_pages++; |
cpu->compiled_pages++; |
582 |
return block; |
return block; |
583 |
|
|
602 |
ppc32_jit_tcb_exec(cpu,block); |
ppc32_jit_tcb_exec(cpu,block); |
603 |
} |
} |
604 |
|
|
|
/* Check if the specified address belongs to the specified block */ |
|
|
int ppc32_jit_tcb_local_addr(ppc32_jit_tcb_t *block,m_uint32_t vaddr, |
|
|
u_char **jit_addr) |
|
|
{ |
|
|
if ((vaddr >= block->start_ia) && |
|
|
((vaddr - block->start_ia) < PPC32_MIN_PAGE_SIZE)) |
|
|
{ |
|
|
*jit_addr = ppc32_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 ppc32_jit_tcb_match(cpu_ppc_t *cpu,ppc32_jit_tcb_t *block) |
|
|
{ |
|
|
m_uint32_t vpage; |
|
|
|
|
|
vpage = cpu->ia & ~PPC32_MIN_PAGE_IMASK; |
|
|
return(block->start_ia == vpage); |
|
|
} |
|
|
|
|
605 |
/* Execute compiled PowerPC code */ |
/* Execute compiled PowerPC code */ |
606 |
void *ppc32_jit_run_cpu(cpu_gen_t *gen) |
void *ppc32_jit_run_cpu(cpu_gen_t *gen) |
607 |
{ |
{ |
608 |
cpu_ppc_t *cpu = CPU_PPC32(gen); |
cpu_ppc_t *cpu = CPU_PPC32(gen); |
609 |
pthread_t timer_irq_thread; |
pthread_t timer_irq_thread; |
610 |
ppc32_jit_tcb_t *block; |
ppc32_jit_tcb_t *block; |
611 |
m_uint32_t phys_page; |
m_uint32_t ia_hash; |
612 |
int timer_irq_check = 0; |
int timer_irq_check = 0; |
613 |
|
|
614 |
if (pthread_create(&timer_irq_thread,NULL, |
if (pthread_create(&timer_irq_thread,NULL,(void *)ppc32_timer_irq_run,cpu)) |
|
(void *)ppc32_timer_irq_run,cpu)) |
|
615 |
{ |
{ |
616 |
fprintf(stderr, |
fprintf(stderr, |
617 |
"VM '%s': unable to create Timer IRQ thread for CPU%u.\n", |
"VM '%s': unable to create Timer IRQ thread for CPU%u.\n", |
640 |
} |
} |
641 |
} |
} |
642 |
|
|
|
/* Check IRQs */ |
|
|
if (unlikely(cpu->irq_check)) |
|
|
ppc32_trigger_irq(cpu); |
|
|
|
|
643 |
/* Handle the virtual CPU clock */ |
/* Handle the virtual CPU clock */ |
644 |
if (++timer_irq_check == cpu->timer_irq_check_itv) { |
if (++timer_irq_check == cpu->timer_irq_check_itv) { |
645 |
timer_irq_check = 0; |
timer_irq_check = 0; |
651 |
cpu->timer_irq_pending--; |
cpu->timer_irq_pending--; |
652 |
|
|
653 |
vm_set_irq(cpu->vm,0); |
vm_set_irq(cpu->vm,0); |
|
//ppc32_trigger_timer_irq(cpu); |
|
654 |
} |
} |
655 |
} |
} |
656 |
|
|
657 |
/* Get the physical page address corresponding to PC register */ |
/* Check IRQs */ |
658 |
if (unlikely(cpu->translate(cpu,cpu->ia,PPC32_MTS_ICACHE,&phys_page))) { |
if (unlikely(cpu->irq_check)) |
659 |
fprintf(stderr,"VM '%s': no physical page for CPU%u PC=0x%8.8xx\n", |
ppc32_trigger_irq(cpu); |
|
cpu->vm->name,gen->id,cpu->ia); |
|
|
cpu_stop(gen); |
|
|
break; |
|
|
} |
|
660 |
|
|
661 |
block = cpu->exec_phys_map[phys_page]; |
/* Get the JIT block corresponding to IA register */ |
662 |
|
ia_hash = ppc32_jit_get_ia_hash(cpu->ia); |
663 |
|
block = cpu->exec_blk_map[ia_hash]; |
664 |
|
|
665 |
/* No block found, compile the page */ |
/* No block found, compile the page */ |
666 |
if (unlikely(!block) || unlikely(!ppc32_jit_tcb_match(cpu,block))) |
if (unlikely(!block) || unlikely(!ppc32_jit_tcb_match(cpu,block))) |
667 |
{ |
{ |
668 |
if (block != NULL) { |
if (block != NULL) { |
669 |
ppc32_jit_tcb_free(cpu,block,TRUE); |
ppc32_jit_tcb_free(cpu,block,TRUE); |
670 |
cpu->exec_phys_map[phys_page] = NULL; |
cpu->exec_blk_map[ia_hash] = NULL; |
671 |
} |
} |
672 |
|
|
673 |
block = ppc32_jit_tcb_compile(cpu,cpu->ia); |
block = ppc32_jit_tcb_compile(cpu,cpu->ia); |
674 |
|
|
675 |
if (unlikely(!block)) { |
if (unlikely(!block)) { |
676 |
fprintf(stderr, |
fprintf(stderr, |
677 |
"VM '%s': unable to compile block for CPU%u IA=0x%8.8x\n", |
"VM '%s': unable to compile block for CPU%u IA=0x%8.8x\n", |
680 |
break; |
break; |
681 |
} |
} |
682 |
|
|
683 |
block->phys_page = phys_page; |
cpu->exec_blk_map[ia_hash] = block; |
|
cpu->exec_phys_map[phys_page] = block; |
|
684 |
} |
} |
685 |
|
|
686 |
#if DEBUG_BLOCK_TIMESTAMP |
#if DEBUG_BLOCK_TIMESTAMP |