/[dynamips]/trunk/ppc32_jit.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /trunk/ppc32_jit.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11 - (hide annotations)
Sat Oct 6 16:33:40 2007 UTC (16 years, 6 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.8-RC1/ppc32_jit.c
File MIME type: text/plain
File size: 35275 byte(s)
dynamips-0.2.8-RC1

1 dpavlin 7 /*
2     * Cisco router simulation platform.
3     * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4     *
5     * PPC32 JIT compiler.
6     */
7    
8     #include <stdio.h>
9     #include <stdlib.h>
10     #include <unistd.h>
11     #include <string.h>
12     #include <sys/types.h>
13     #include <sys/stat.h>
14     #include <sys/mman.h>
15     #include <signal.h>
16     #include <fcntl.h>
17     #include <assert.h>
18    
19     #include "cpu.h"
20     #include "device.h"
21     #include "ppc32.h"
22     #include "ppc32_exec.h"
23     #include "ppc32_jit.h"
24     #include "insn_lookup.h"
25     #include "memory.h"
26     #include "ptask.h"
27    
28     #include PPC32_ARCH_INC_FILE
29    
30     /* Instruction Lookup Table */
31     static insn_lookup_t *ilt = NULL;
32    
33     static void *ppc32_jit_get_insn(int index)
34     {
35     return(&ppc32_insn_tags[index]);
36     }
37    
38     static int ppc32_jit_chk_lo(struct ppc32_insn_tag *tag,int value)
39     {
40     return((value & tag->mask) == (tag->value & 0xFFFF));
41     }
42    
43     static int ppc32_jit_chk_hi(struct ppc32_insn_tag *tag,int value)
44     {
45     return((value & (tag->mask >> 16)) == (tag->value >> 16));
46     }
47    
48     /* Initialize instruction lookup table */
49     void ppc32_jit_create_ilt(void)
50     {
51     int i,count;
52    
53     for(i=0,count=0;ppc32_insn_tags[i].emit;i++)
54     count++;
55    
56 dpavlin 8 ilt = ilt_create("ppc32j",count,
57 dpavlin 7 (ilt_get_insn_cbk_t)ppc32_jit_get_insn,
58     (ilt_check_cbk_t)ppc32_jit_chk_lo,
59     (ilt_check_cbk_t)ppc32_jit_chk_hi);
60     }
61    
62     /* Initialize the JIT structure */
63     int ppc32_jit_init(cpu_ppc_t *cpu)
64     {
65     insn_exec_page_t *cp;
66     u_char *cp_addr;
67     u_int area_size;
68     size_t len;
69     int i;
70    
71 dpavlin 8 /* 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 dpavlin 7 /* Physical mapping for executable pages */
77 dpavlin 8 len = PPC_JIT_PHYS_HASH_SIZE * sizeof(void *);
78 dpavlin 7 cpu->exec_phys_map = m_memalign(4096,len);
79     memset(cpu->exec_phys_map,0,len);
80    
81     /* Get area size */
82     if (!(area_size = cpu->vm->exec_area_size))
83     area_size = PPC_EXEC_AREA_SIZE;
84    
85     /* Create executable page area */
86     cpu->exec_page_area_size = area_size * 1048576;
87     cpu->exec_page_area = mmap(NULL,cpu->exec_page_area_size,
88     PROT_EXEC|PROT_READ|PROT_WRITE,
89     MAP_SHARED|MAP_ANONYMOUS,-1,(off_t)0);
90    
91     if (!cpu->exec_page_area) {
92     fprintf(stderr,
93     "ppc32_jit_init: unable to create exec area (size %lu)\n",
94     (u_long)cpu->exec_page_area_size);
95     return(-1);
96     }
97    
98     /* Carve the executable page area */
99     cpu->exec_page_count = cpu->exec_page_area_size / PPC_JIT_BUFSIZE;
100    
101     cpu->exec_page_array = calloc(cpu->exec_page_count,
102     sizeof(insn_exec_page_t));
103    
104     if (!cpu->exec_page_array) {
105     fprintf(stderr,"ppc32_jit_init: unable to create exec page array\n");
106     return(-1);
107     }
108    
109     for(i=0,cp_addr=cpu->exec_page_area;i<cpu->exec_page_count;i++) {
110     cp = &cpu->exec_page_array[i];
111    
112     cp->ptr = cp_addr;
113     cp_addr += PPC_JIT_BUFSIZE;
114    
115     cp->next = cpu->exec_page_free_list;
116     cpu->exec_page_free_list = cp;
117     }
118    
119     printf("CPU%u: carved JIT exec zone of %lu Mb into %lu pages of %u Kb.\n",
120     cpu->gen->id,
121     (u_long)(cpu->exec_page_area_size / 1048576),
122     (u_long)cpu->exec_page_count,PPC_JIT_BUFSIZE / 1024);
123     return(0);
124     }
125    
126     /* Flush the JIT */
127     u_int ppc32_jit_flush(cpu_ppc_t *cpu,u_int threshold)
128     {
129     ppc32_jit_tcb_t *p,*next;
130 dpavlin 8 m_uint32_t ia_hash;
131 dpavlin 7 u_int count = 0;
132    
133     if (!threshold)
134     threshold = (u_int)(-1); /* UINT_MAX not defined everywhere */
135    
136     for(p=cpu->tcb_list;p;p=next) {
137     next = p->next;
138    
139     if (p->acc_count <= threshold) {
140 dpavlin 8 ia_hash = ppc32_jit_get_ia_hash(p->start_ia);
141 dpavlin 7 ppc32_jit_tcb_free(cpu,p,TRUE);
142 dpavlin 8
143     if (cpu->exec_blk_map[ia_hash] == p)
144     cpu->exec_blk_map[ia_hash] = NULL;
145 dpavlin 7 count++;
146     }
147     }
148    
149     cpu->compiled_pages -= count;
150     return(count);
151     }
152    
153     /* Shutdown the JIT */
154     void ppc32_jit_shutdown(cpu_ppc_t *cpu)
155     {
156     ppc32_jit_tcb_t *p,*next;
157    
158     /* Flush the JIT */
159     ppc32_jit_flush(cpu,0);
160    
161     /* Free the instruction blocks */
162     for(p=cpu->tcb_free_list;p;p=next) {
163     next = p->next;
164     free(p);
165     }
166    
167     /* Unmap the executable page area */
168     if (cpu->exec_page_area)
169     munmap(cpu->exec_page_area,cpu->exec_page_area_size);
170    
171     /* Free the exec page array */
172     free(cpu->exec_page_array);
173    
174 dpavlin 8 /* Free JIT block mapping */
175     free(cpu->exec_blk_map);
176    
177 dpavlin 7 /* Free physical mapping for executable pages */
178 dpavlin 8 free(cpu->exec_phys_map);
179 dpavlin 7 }
180    
181     /* Allocate an exec page */
182     static inline insn_exec_page_t *exec_page_alloc(cpu_ppc_t *cpu)
183     {
184     insn_exec_page_t *p;
185     u_int count;
186    
187     /* If the free list is empty, flush JIT */
188     if (unlikely(!cpu->exec_page_free_list))
189     {
190     if (cpu->jit_flush_method) {
191     cpu_log(cpu->gen,
192     "JIT","flushing data structures (compiled pages=%u)\n",
193     cpu->compiled_pages);
194     ppc32_jit_flush(cpu,0);
195     } else {
196     count = ppc32_jit_flush(cpu,100);
197     cpu_log(cpu->gen,"JIT","partial JIT flush (count=%u)\n",count);
198    
199     if (!cpu->exec_page_free_list)
200     ppc32_jit_flush(cpu,0);
201     }
202    
203     /* Use both methods alternatively */
204     cpu->jit_flush_method = 1 - cpu->jit_flush_method;
205     }
206    
207     if (unlikely(!(p = cpu->exec_page_free_list)))
208     return NULL;
209    
210     cpu->exec_page_free_list = p->next;
211     cpu->exec_page_alloc++;
212     return p;
213     }
214    
215     /* Free an exec page and returns it to the pool */
216     static inline void exec_page_free(cpu_ppc_t *cpu,insn_exec_page_t *p)
217     {
218     if (p) {
219     p->next = cpu->exec_page_free_list;
220     cpu->exec_page_free_list = p;
221     cpu->exec_page_alloc--;
222     }
223     }
224    
225     /* Find the JIT code emitter for the specified PowerPC instruction */
226     static struct ppc32_insn_tag *insn_tag_find(ppc_insn_t ins)
227     {
228     struct ppc32_insn_tag *tag = NULL;
229     int index;
230    
231 dpavlin 11 index = ilt_lookup(ilt,ins);
232 dpavlin 7 tag = ppc32_jit_get_insn(index);
233     return tag;
234     }
235    
236     /* Fetch a PowerPC instruction */
237     static forced_inline ppc_insn_t insn_fetch(ppc32_jit_tcb_t *b)
238     {
239     return(vmtoh32(b->ppc_code[b->ppc_trans_pos]));
240     }
241    
242 dpavlin 9 #define DEBUG_HREG 0
243    
244     /* Show register allocation status */
245     static void ppc32_jit_show_hreg_status(cpu_ppc_t *cpu)
246     {
247     struct hreg_map *map;
248    
249     printf("PPC32-JIT: reg status for insn '%s'\n",cpu->jit_hreg_seq_name);
250    
251     for(map=cpu->hreg_map_list;map;map=map->next) {
252     switch(map->flags) {
253     case 0:
254     printf(" hreg %d is free, mapped to vreg %d\n",
255     map->hreg,map->vreg);
256     break;
257     case HREG_FLAG_ALLOC_LOCKED:
258     printf(" hreg %d is locked, mapped to vreg %d\n",
259     map->hreg,map->vreg);
260     break;
261     case HREG_FLAG_ALLOC_FORCED:
262     printf(" hreg %d is in forced alloc\n",map->hreg);
263     break;
264     }
265     }
266     }
267    
268     /* Extract an host reg mapping from the register list */
269     static void ppc32_jit_extract_hreg(cpu_ppc_t *cpu,struct hreg_map *map)
270     {
271     if (map->prev != NULL)
272     map->prev->next = map->next;
273     else
274     cpu->hreg_map_list = map->next;
275    
276     if (map->next != NULL)
277     map->next->prev = map->prev;
278     else
279     cpu->hreg_lru = map->prev;
280     }
281    
282     /* Insert a reg map as head of list (as MRU element) */
283     void ppc32_jit_insert_hreg_mru(cpu_ppc_t *cpu,struct hreg_map *map)
284     {
285     map->next = cpu->hreg_map_list;
286     map->prev = NULL;
287    
288     if (map->next == NULL) {
289     cpu->hreg_lru = map;
290     } else {
291     map->next->prev = map;
292     }
293    
294     cpu->hreg_map_list = map;
295     }
296    
297     /* Start register allocation sequence */
298     void ppc32_jit_start_hreg_seq(cpu_ppc_t *cpu,char *insn)
299     {
300     struct hreg_map *map;
301    
302     #if DEBUG_HREG
303     printf("Starting hreg_seq insn='%s'\n",insn);
304     #endif
305    
306     /* Reset the allocation state of all host registers */
307     for(map=cpu->hreg_map_list;map;map=map->next)
308     map->flags = 0;
309    
310     /* Save the instruction name for debugging/error analysis */
311     cpu->jit_hreg_seq_name = insn;
312     }
313    
314     /* Close register allocation sequence */
315     void ppc32_jit_close_hreg_seq(cpu_ppc_t *cpu)
316     {
317     #if DEBUG_HREG
318     ppc32_show_hreg_status(cpu);
319     #endif
320     }
321    
322     /* Find a free host register to use */
323     static struct hreg_map *ppc32_jit_get_free_hreg(cpu_ppc_t *cpu)
324     {
325     struct hreg_map *map,*oldest_free = NULL;
326    
327     for(map=cpu->hreg_lru;map;map=map->prev) {
328     if ((map->vreg == -1) && (map->flags == 0))
329     return map;
330    
331     if ((map->flags == 0) && !oldest_free)
332     oldest_free = map;
333     }
334    
335     if (!oldest_free) {
336     fprintf(stderr,
337     "ppc32_get_free_hreg: unable to find free reg for insn %s\n",
338     cpu->jit_hreg_seq_name);
339     }
340    
341     return oldest_free;
342     }
343    
344     /* Allocate an host register */
345     int ppc32_jit_alloc_hreg(cpu_ppc_t *cpu,int ppc_reg)
346     {
347     struct hreg_map *map;
348     int hreg;
349    
350     /*
351     * If PPC reg is invalid, the caller requested for a temporary register.
352     */
353     if (ppc_reg == -1) {
354     if ((map = ppc32_jit_get_free_hreg(cpu)) == NULL)
355     return(-1);
356    
357     /* Allocate the register and invalidate its PPC mapping if present */
358     map->flags = HREG_FLAG_ALLOC_LOCKED;
359    
360     if (map->vreg != -1) {
361     cpu->ppc_reg_map[map->vreg] = -1;
362     map->vreg = -1;
363     }
364    
365     return(map->hreg);
366     }
367    
368     hreg = cpu->ppc_reg_map[ppc_reg];
369    
370     /*
371     * If the PPC register is already mapped to an host register, re-use this
372     * mapping and put this as MRU mapping.
373     */
374     if (hreg != -1) {
375     map = &cpu->hreg_map[hreg];
376     } else {
377     /*
378     * This PPC register has no mapping to host register. Find a free
379     * register.
380     */
381     if ((map = ppc32_jit_get_free_hreg(cpu)) == NULL)
382     return(-1);
383    
384     /* Remove the old PPC mapping if present */
385     if (map->vreg != -1)
386     cpu->ppc_reg_map[map->vreg] = -1;
387    
388     /* Establish the new mapping */
389     cpu->ppc_reg_map[ppc_reg] = map->hreg;
390     map->vreg = ppc_reg;
391     }
392    
393     /* Prevent this register from further allocation in this instruction */
394     map->flags = HREG_FLAG_ALLOC_LOCKED;
395     ppc32_jit_extract_hreg(cpu,map);
396     ppc32_jit_insert_hreg_mru(cpu,map);
397     return(map->hreg);
398     }
399    
400     /* Force allocation of an host register */
401     int ppc32_jit_alloc_hreg_forced(cpu_ppc_t *cpu,int hreg)
402     {
403     int ppc_reg;
404    
405     ppc_reg = cpu->hreg_map[hreg].vreg;
406    
407     /* Check that this register is not already allocated */
408     if (cpu->hreg_map[hreg].flags != 0) {
409     fprintf(stderr,"ppc32_alloc_hreg_forced: trying to force allocation "
410     "of hreg %d (insn %s)\n",
411     hreg,cpu->jit_hreg_seq_name);
412     return(-1);
413     }
414    
415     cpu->hreg_map[hreg].flags = HREG_FLAG_ALLOC_FORCED;
416     cpu->hreg_map[hreg].vreg = -1;
417    
418     if (ppc_reg != -1)
419     cpu->ppc_reg_map[ppc_reg] = -1;
420    
421     return(0);
422     }
423    
424 dpavlin 7 /* Emit a breakpoint if necessary */
425     #if BREAKPOINT_ENABLE
426     static void insn_emit_breakpoint(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b)
427     {
428     m_uint32_t ia;
429     int i;
430    
431     ia = b->start_ia+((b->ppc_trans_pos-1)<<2);
432    
433     for(i=0;i<PPC32_MAX_BREAKPOINTS;i++)
434     if (ia == cpu->breakpoints[i]) {
435 dpavlin 9 ppc32_emit_breakpoint(cpu,b);
436 dpavlin 7 break;
437     }
438     }
439     #endif /* BREAKPOINT_ENABLE */
440    
441     /* Fetch a PowerPC instruction and emit corresponding translated code */
442     struct ppc32_insn_tag *ppc32_jit_fetch_and_emit(cpu_ppc_t *cpu,
443     ppc32_jit_tcb_t *block)
444     {
445     struct ppc32_insn_tag *tag;
446     ppc_insn_t code;
447    
448     code = insn_fetch(block);
449     tag = insn_tag_find(code);
450     assert(tag);
451    
452     tag->emit(cpu,block,code);
453     return tag;
454     }
455    
456     /* Add end of JIT block */
457     static void ppc32_jit_tcb_add_end(ppc32_jit_tcb_t *b)
458     {
459 dpavlin 9 ppc32_set_ia(&b->jit_ptr,b->start_ia+(b->ppc_trans_pos<<2));
460     ppc32_jit_tcb_push_epilog(&b->jit_ptr);
461 dpavlin 7 }
462    
463     /* Record a patch to apply in a compiled block */
464 dpavlin 9 int ppc32_jit_tcb_record_patch(ppc32_jit_tcb_t *block,jit_op_t *iop,
465     u_char *jit_ptr,m_uint32_t vaddr)
466 dpavlin 7 {
467     struct ppc32_jit_patch_table *ipt = block->patch_table;
468     struct ppc32_insn_patch *patch;
469    
470     /* pc must be 32-bit aligned */
471     if (vaddr & 0x03) {
472 dpavlin 9 fprintf(stderr,
473     "Block 0x%8.8x: trying to record an invalid IA (0x%8.8x)\n",
474     block->start_ia,vaddr);
475 dpavlin 7 return(-1);
476     }
477    
478     if (!ipt || (ipt->cur_patch >= PPC32_INSN_PATCH_TABLE_SIZE))
479     {
480     /* full table or no table, create a new one */
481     ipt = malloc(sizeof(*ipt));
482     if (!ipt) {
483     fprintf(stderr,"Block 0x%8.8x: unable to create patch table.\n",
484     block->start_ia);
485     return(-1);
486     }
487    
488     memset(ipt,0,sizeof(*ipt));
489     ipt->next = block->patch_table;
490     block->patch_table = ipt;
491     }
492    
493     #if DEBUG_BLOCK_PATCH
494     printf("Block 0x%8.8x: recording patch [JIT:%p->ppc:0x%8.8x], "
495     "MTP=%d\n",block->start_ia,jit_ptr,vaddr,block->ppc_trans_pos);
496     #endif
497    
498     patch = &ipt->patches[ipt->cur_patch];
499     patch->jit_insn = jit_ptr;
500     patch->ppc_ia = vaddr;
501 dpavlin 9 ipt->cur_patch++;
502    
503     patch->next = iop->arg_ptr;
504     iop->arg_ptr = patch;
505 dpavlin 7 return(0);
506     }
507    
508 dpavlin 9 /* Apply patches for a JIT instruction block */
509 dpavlin 7 static int ppc32_jit_tcb_apply_patches(cpu_ppc_t *cpu,
510 dpavlin 9 ppc32_jit_tcb_t *block,
511     jit_op_t *iop)
512 dpavlin 7 {
513     struct ppc32_insn_patch *patch;
514 dpavlin 9 u_char *jit_ptr,*jit_dst;
515     u_int pos;
516 dpavlin 7
517 dpavlin 9 for(patch=iop->arg_ptr;patch;patch=patch->next) {
518     jit_ptr = (patch->jit_insn - iop->ob_data) + iop->ob_final;
519 dpavlin 7
520 dpavlin 9 pos = (patch->ppc_ia & PPC32_MIN_PAGE_IMASK) >> 2;
521     jit_dst = block->jit_insn_ptr[pos];
522    
523     if (jit_dst) {
524     #if DEBUG_BLOCK_PATCH
525     printf("Block 0x%8.8x: applying patch "
526     "[JIT:%p->ppc:0x%8.8x=JIT:%p, ]\n",
527     block->start_ia,patch->jit_insn,patch->ppc_ia,jit_dst);
528 dpavlin 7 #endif
529 dpavlin 9 ppc32_jit_tcb_set_patch(jit_ptr,jit_dst);
530     } else {
531     printf("Block 0x%8.8x: null dst for patch!\n",block->start_ia);
532 dpavlin 7 }
533 dpavlin 9 }
534    
535 dpavlin 7 return(0);
536     }
537    
538     /* Free the patch table */
539     static void ppc32_jit_tcb_free_patches(ppc32_jit_tcb_t *block)
540     {
541     struct ppc32_jit_patch_table *p,*next;
542    
543     for(p=block->patch_table;p;p=next) {
544     next = p->next;
545     free(p);
546     }
547    
548     block->patch_table = NULL;
549     }
550    
551     /* Adjust the JIT buffer if its size is not sufficient */
552 dpavlin 8 static int ppc32_jit_tcb_adjust_buffer(cpu_ppc_t *cpu,ppc32_jit_tcb_t *block)
553 dpavlin 7 {
554     insn_exec_page_t *new_buffer;
555    
556     if ((block->jit_ptr - block->jit_buffer->ptr) <= (PPC_JIT_BUFSIZE - 512))
557     return(0);
558    
559     #if DEBUG_BLOCK_CHUNK
560     printf("Block 0x%8.8x: adjusting JIT buffer...\n",block->start_ia);
561     #endif
562    
563     if (block->jit_chunk_pos >= PPC_JIT_MAX_CHUNKS) {
564     fprintf(stderr,"Block 0x%8.8x: too many JIT chunks.\n",block->start_ia);
565     return(-1);
566     }
567    
568     if (!(new_buffer = exec_page_alloc(cpu)))
569     return(-1);
570    
571     /* record the new exec page */
572     block->jit_chunks[block->jit_chunk_pos++] = block->jit_buffer;
573     block->jit_buffer = new_buffer;
574    
575     /* jump to the new exec page (link) */
576     ppc32_jit_tcb_set_jump(block->jit_ptr,new_buffer->ptr);
577     block->jit_ptr = new_buffer->ptr;
578     return(0);
579     }
580    
581     /* Allocate an instruction block */
582     static inline ppc32_jit_tcb_t *ppc32_jit_tcb_alloc(cpu_ppc_t *cpu)
583     {
584     ppc32_jit_tcb_t *p;
585    
586     if (cpu->tcb_free_list) {
587     p = cpu->tcb_free_list;
588     cpu->tcb_free_list = p->next;
589     } else {
590     if (!(p = malloc(sizeof(*p))))
591     return NULL;
592     }
593    
594     memset(p,0,sizeof(*p));
595     return p;
596     }
597    
598 dpavlin 9 /* Free the code chunks */
599     static void
600     ppc32_jit_tcb_free_code_chunks(cpu_ppc_t *cpu,ppc32_jit_tcb_t *block)
601     {
602     int i;
603    
604     /* Free code pages */
605     for(i=0;i<PPC_JIT_MAX_CHUNKS;i++) {
606     exec_page_free(cpu,block->jit_chunks[i]);
607     block->jit_chunks[i] = NULL;
608     }
609    
610     /* Free the current JIT buffer */
611     exec_page_free(cpu,block->jit_buffer);
612     block->jit_buffer = NULL;
613     }
614    
615 dpavlin 7 /* Free an instruction block */
616     void ppc32_jit_tcb_free(cpu_ppc_t *cpu,ppc32_jit_tcb_t *block,
617 dpavlin 9 int list_removal)
618 dpavlin 7 {
619     if (block) {
620     if (list_removal) {
621     /* Remove the block from the linked list */
622     if (block->next)
623     block->next->prev = block->prev;
624     else
625     cpu->tcb_last = block->prev;
626    
627     if (block->prev)
628     block->prev->next = block->next;
629     else
630     cpu->tcb_list = block->next;
631 dpavlin 8
632     /* Remove the block from the physical mapping hash table */
633     if (block->phys_pprev) {
634     if (block->phys_next)
635     block->phys_next->phys_pprev = block->phys_pprev;
636    
637     *(block->phys_pprev) = block->phys_next;
638    
639     block->phys_pprev = NULL;
640     block->phys_next = NULL;
641     }
642 dpavlin 7 }
643    
644     /* Free the patch tables */
645     ppc32_jit_tcb_free_patches(block);
646    
647     /* Free code pages */
648 dpavlin 9 ppc32_jit_tcb_free_code_chunks(cpu,block);
649 dpavlin 7
650     /* Free the PowerPC-to-native code mapping */
651     free(block->jit_insn_ptr);
652 dpavlin 8
653 dpavlin 7 block->next = cpu->tcb_free_list;
654     cpu->tcb_free_list = block;
655     }
656     }
657    
658     /* Create an instruction block */
659     static ppc32_jit_tcb_t *ppc32_jit_tcb_create(cpu_ppc_t *cpu,m_uint32_t vaddr)
660     {
661     ppc32_jit_tcb_t *block = NULL;
662 dpavlin 8 m_uint32_t phys_page;
663 dpavlin 7
664 dpavlin 8 if (unlikely(cpu->translate(cpu,cpu->ia,PPC32_MTS_ICACHE,&phys_page)))
665     return NULL;
666    
667 dpavlin 7 if (!(block = ppc32_jit_tcb_alloc(cpu)))
668     goto err_block_alloc;
669    
670     block->start_ia = vaddr;
671 dpavlin 8 block->phys_page = phys_page;
672     block->phys_hash = ppc32_jit_get_phys_hash(phys_page);
673 dpavlin 7
674     /* Allocate the first JIT buffer */
675     if (!(block->jit_buffer = exec_page_alloc(cpu)))
676     goto err_jit_alloc;
677    
678     block->jit_ptr = block->jit_buffer->ptr;
679     block->ppc_code = cpu->mem_op_lookup(cpu,block->start_ia,PPC32_MTS_ICACHE);
680    
681     if (!block->ppc_code) {
682     fprintf(stderr,"%% No memory map for code execution at 0x%8.8x\n",
683     block->start_ia);
684     goto err_lookup;
685     }
686    
687     #if DEBUG_BLOCK_TIMESTAMP
688     block->tm_first_use = block->tm_last_use = jit_jiffies;
689     #endif
690     return block;
691    
692     err_lookup:
693     err_jit_alloc:
694     ppc32_jit_tcb_free(cpu,block,FALSE);
695     err_block_alloc:
696     fprintf(stderr,"%% Unable to create instruction block for vaddr=0x%8.8x\n",
697     vaddr);
698     return NULL;
699     }
700    
701 dpavlin 9 /* ======================================================================== */
702    
703     /* Dump a JIT opcode */
704     static void ppc32_op_dump_opcode(jit_op_t *op)
705     {
706     switch(op->opcode) {
707     case JIT_OP_BRANCH_TARGET:
708     printf("branch_target");
709     break;
710     case JIT_OP_BRANCH_JUMP:
711     printf("branch_jump");
712     break;
713     case JIT_OP_EOB:
714     printf("eob");
715     break;
716     case JIT_OP_LOAD_GPR:
717     printf("load_gpr(%d,$%d,r:%d)",
718     op->param[0],op->param[1],op->param[2]);
719     break;
720     case JIT_OP_STORE_GPR:
721     printf("store_gpr(%d,$%d,r:%d)",
722     op->param[0],op->param[1],op->param[2]);
723     break;
724     case JIT_OP_ALTER_HOST_REG:
725     printf("alter_host_reg(%d)",op->param[0]);
726     break;
727     case JIT_OP_UPDATE_FLAGS:
728     printf("update_flags(%d,%s)",
729     op->param[0],(op->param[1] ? "signed" : "unsigned"));
730     break;
731     case JIT_OP_REQUIRE_FLAGS:
732     printf("require_flags(%d)",op->param[0]);
733     break;
734     case JIT_OP_TRASH_FLAGS:
735     printf("trash_flags(%d)",op->param[0]);
736     break;
737     case JIT_OP_INSN_OUTPUT:
738     printf("insn_out(\"%s\")",op->insn_name);
739     break;
740     case JIT_OP_SET_HOST_REG_IMM32:
741     printf("set_host_reg_imm32(%d,0x%8.8x)",op->param[0],op->param[1]);
742     break;
743     default:
744     printf("op(%u)",op->opcode);
745     }
746     }
747    
748     /* Dump JIT operations (debugging) */
749     static void ppc32_op_dump(cpu_gen_t *cpu,ppc32_jit_tcb_t *b)
750     {
751     m_uint32_t ia = b->start_ia;
752     jit_op_t *op;
753     int i;
754    
755     printf("PPC32-JIT: dump of page 0x%8.8x\n",ia);
756    
757     for(i=0;i<PPC32_INSN_PER_PAGE;i++,ia+=sizeof(ppc_insn_t)) {
758     printf(" 0x%8.8x: ", ia);
759    
760     for(op=cpu->jit_op_array[i];op;op=op->next) {
761     ppc32_op_dump_opcode(op);
762     printf(" ");
763     }
764    
765     printf("\n");
766     }
767    
768     printf("\n");
769     }
770    
771     /* PPC register mapping */
772     typedef struct {
773     int host_reg;
774     jit_op_t *last_store;
775     m_uint32_t last_store_ia;
776     }ppc_reg_map_t;
777    
778     /* Clear register mapping (with PPC register) */
779     static void ppc32_clear_ppc_reg_map(ppc_reg_map_t *ppc_map,int *host_map,
780     int reg)
781     {
782     int i,hreg;
783    
784     if (reg == JIT_OP_ALL_REGS) {
785     for(i=0;i<PPC32_GPR_NR;i++) {
786     ppc_map[i].host_reg = JIT_OP_INV_REG;
787     ppc_map[i].last_store = NULL;
788     }
789    
790     for(i=0;i<JIT_HOST_NREG;i++)
791     host_map[i] = JIT_OP_INV_REG;
792     } else {
793     hreg = ppc_map[reg].host_reg;
794    
795     if (hreg != JIT_OP_INV_REG)
796     host_map[hreg] = JIT_OP_INV_REG;
797    
798     ppc_map[reg].host_reg = JIT_OP_INV_REG;
799     ppc_map[reg].last_store = NULL;
800     }
801     }
802    
803     /* Clear register mapping (with host register) */
804     static void ppc32_clear_host_reg_map(ppc_reg_map_t *ppc_map,int *host_map,
805     int reg)
806     {
807     int ppc_reg;
808    
809     if (host_map[reg] != JIT_OP_INV_REG) {
810     ppc_reg = host_map[reg];
811    
812     ppc_map[ppc_reg].host_reg = JIT_OP_INV_REG;
813     ppc_map[ppc_reg].last_store = NULL;
814     host_map[reg] = JIT_OP_INV_REG;
815     }
816     }
817    
818     /* Dump register mapping */
819     static void ppc32_dump_reg_map(ppc_reg_map_t *map_array,int *host_map)
820     {
821     int i;
822    
823     printf("PPC32-JIT: current register mapping:\n");
824    
825     for(i=0;i<PPC32_GPR_NR;i++)
826     printf(" ppc reg %2.2d: %d\n",i,map_array[i].host_reg);
827    
828     printf("\n");
829    
830     for(i=0;i<JIT_HOST_NREG;i++)
831     printf(" hreg %d: %d\n",i,host_map[i]);
832    
833     printf("\n");
834     }
835    
836     /* Check register mapping consistency */
837     static int ppc32_check_reg_map(ppc_reg_map_t *map_array,int *host_map)
838     {
839     ppc_reg_map_t *map;
840     int i;
841    
842     for(i=0;i<PPC32_GPR_NR;i++) {
843     map = &map_array[i];
844    
845     if ((map->host_reg != JIT_OP_INV_REG) && (host_map[map->host_reg] != i))
846     goto error;
847     }
848    
849     for(i=0;i<JIT_HOST_NREG;i++) {
850     if ((host_map[i] != JIT_OP_INV_REG) &&
851     (map_array[host_map[i]].host_reg != i))
852     goto error;
853     }
854    
855     return(0);
856    
857     error:
858     printf("PPC32_JIT: inconsistency in register mapping.\n");
859     ppc32_dump_reg_map(map_array,host_map);
860     exit(1);
861     }
862    
863     /* Optimize JIT operations */
864     static void ppc32_op_optimize(cpu_gen_t *cpu,ppc32_jit_tcb_t *b)
865     {
866     ppc_reg_map_t ppc_map[PPC32_GPR_NR],*map;
867     int reg,host_map[JIT_HOST_NREG];
868     jit_op_t *op,*opx,*last_cr_update[8];
869     m_uint32_t cur_ia;
870     int i,j;
871    
872     ppc32_clear_ppc_reg_map(ppc_map,host_map,JIT_OP_ALL_REGS);
873    
874     for(i=0;i<8;i++)
875     last_cr_update[i] = NULL;
876    
877     for(i=0;i<PPC32_INSN_PER_PAGE;i++) {
878     for(op=cpu->jit_op_array[i];op;op=op->next)
879     {
880     //ppc32_check_reg_map(ppc_map,host_map);
881     cur_ia = b->start_ia + (i << 2);
882    
883     switch(op->opcode) {
884     /* Clear mapping if end of block or branch target */
885     case JIT_OP_BRANCH_TARGET:
886     case JIT_OP_EOB:
887     ppc32_clear_ppc_reg_map(ppc_map,host_map,JIT_OP_ALL_REGS);
888    
889     for(j=0;j<8;j++)
890     last_cr_update[j] = NULL;
891     break;
892    
893     /* Branch jump: clear "store" operation status */
894     case JIT_OP_BRANCH_JUMP:
895     for(j=0;j<PPC32_GPR_NR;j++)
896     ppc_map[j].last_store = NULL;
897    
898     for(j=0;j<8;j++)
899     last_cr_update[j] = NULL;
900     break;
901    
902     /* Alteration of a specific host register */
903     case JIT_OP_ALTER_HOST_REG:
904     reg = op->param[0];
905    
906     if (reg != JIT_OP_ALL_REGS) {
907     if (host_map[reg] != JIT_OP_INV_REG)
908     ppc32_clear_ppc_reg_map(ppc_map,host_map,host_map[reg]);
909     } else {
910     ppc32_clear_ppc_reg_map(ppc_map,host_map,JIT_OP_ALL_REGS);
911     }
912     break;
913    
914     /* Save reg mapping and last operation */
915     case JIT_OP_STORE_GPR:
916     reg = op->param[0];
917     map = &ppc_map[op->param[1]];
918    
919     /* clear old mapping */
920     if (reg != map->host_reg) {
921     ppc32_clear_host_reg_map(ppc_map,host_map,reg);
922     ppc32_clear_ppc_reg_map(ppc_map,host_map,op->param[1]);
923     }
924    
925     /* cancel previous store op for this PPC register */
926     if (map->last_store) {
927     map->last_store->param[0] = JIT_OP_INV_REG;
928     map->last_store = NULL;
929     }
930    
931     map->host_reg = reg;
932     map->last_store = op;
933     map->last_store_ia = cur_ia;
934     host_map[reg] = op->param[1];
935     break;
936    
937     /* Load reg: check if can avoid it */
938     case JIT_OP_LOAD_GPR:
939     reg = op->param[0];
940     map = &ppc_map[op->param[1]];
941    
942     if (reg == map->host_reg) {
943     /* Cancel this load */
944     op->param[0] = JIT_OP_INV_REG;
945     } else {
946     /* clear old mapping */
947     ppc32_clear_host_reg_map(ppc_map,host_map,reg);
948     ppc32_clear_ppc_reg_map(ppc_map,host_map,op->param[1]);
949    
950     /* Save this reg mapping */
951     map->host_reg = op->param[0];
952     map->last_store = NULL;
953     host_map[op->param[0]] = op->param[1];
954     }
955     break;
956    
957     /* Trash flags */
958     case JIT_OP_TRASH_FLAGS:
959     for(j=0;j<8;j++)
960     last_cr_update[j] = NULL;
961     break;
962    
963     /* Flags required */
964     case JIT_OP_REQUIRE_FLAGS:
965     if (op->param[0] != JIT_OP_PPC_ALL_FLAGS) {
966     last_cr_update[op->param[0]] = NULL;
967     } else {
968     for(j=0;j<8;j++)
969     last_cr_update[j] = NULL;
970     }
971     break;
972    
973     /* Update flags */
974     case JIT_OP_UPDATE_FLAGS:
975     opx = last_cr_update[op->param[0]];
976    
977     if (opx != NULL)
978     opx->param[0] = JIT_OP_INV_REG;
979    
980     last_cr_update[op->param[0]] = op;
981     break;
982     }
983     }
984     }
985     }
986    
987     /* Generate the JIT code for the specified JIT op list */
988     static void ppc32_op_gen_list(ppc32_jit_tcb_t *b,int ipos,jit_op_t *op_list,
989     u_char *jit_start)
990     {
991     jit_op_t *op;
992    
993     for(op=op_list;op;op=op->next) {
994     switch(op->opcode) {
995     case JIT_OP_INSN_OUTPUT:
996     ppc32_op_insn_output(b,op);
997     break;
998     case JIT_OP_LOAD_GPR:
999     ppc32_op_load_gpr(b,op);
1000     break;
1001     case JIT_OP_STORE_GPR:
1002     ppc32_op_store_gpr(b,op);
1003     break;
1004     case JIT_OP_UPDATE_FLAGS:
1005     ppc32_op_update_flags(b,op);
1006     break;
1007     case JIT_OP_BRANCH_TARGET:
1008     b->jit_insn_ptr[ipos] = jit_start;
1009     break;
1010     case JIT_OP_MOVE_HOST_REG:
1011     ppc32_op_move_host_reg(b,op);
1012     break;
1013     case JIT_OP_SET_HOST_REG_IMM32:
1014     ppc32_op_set_host_reg_imm32(b,op);
1015     break;
1016     }
1017     }
1018     }
1019    
1020     /* Opcode emit start */
1021     static inline void ppc32_op_emit_start(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b)
1022     {
1023     cpu_gen_t *c = cpu->gen;
1024     jit_op_t *op;
1025    
1026     if (c->jit_op_array[b->ppc_trans_pos] == NULL)
1027     c->jit_op_current = &c->jit_op_array[b->ppc_trans_pos];
1028     else {
1029     for(op=c->jit_op_array[b->ppc_trans_pos];op;op=op->next)
1030     c->jit_op_current = &op->next;
1031     }
1032     }
1033    
1034     /* Generate the JIT code for the current page, given an op list */
1035     static int ppc32_op_gen_page(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b)
1036     {
1037     struct ppc32_insn_tag *tag;
1038     cpu_gen_t *gcpu = cpu->gen;
1039     jit_op_t *iop;
1040     m_uint32_t cur_ia;
1041     u_char *jit_ptr;
1042     int i;
1043    
1044     /* Generate JIT opcodes */
1045     for(b->ppc_trans_pos=0;
1046     b->ppc_trans_pos<PPC32_INSN_PER_PAGE;
1047     b->ppc_trans_pos++)
1048     {
1049     ppc32_op_emit_start(cpu,b);
1050    
1051     cur_ia = b->start_ia + (b->ppc_trans_pos << 2);
1052    
1053     if (ppc32_jit_tcb_get_target_bit(b,cur_ia))
1054     ppc32_op_emit_basic_opcode(cpu,JIT_OP_BRANCH_TARGET);
1055    
1056 dpavlin 11 #if DEBUG_INSN_PERF_CNT
1057     ppc32_inc_perf_counter(cpu);
1058     #endif
1059     #if BREAKPOINT_ENABLE
1060     if (cpu->breakpoints_enabled)
1061     insn_emit_breakpoint(cpu,b);
1062     #endif
1063    
1064 dpavlin 9 if (unlikely(!(tag = ppc32_jit_fetch_and_emit(cpu,b)))) {
1065     fprintf(stderr,"ppc32_op_gen_page: unable to fetch instruction.\n");
1066     return(-1);
1067     }
1068     }
1069    
1070     /*
1071     * Mark the first instruction as a potential target, as well as the
1072     * current IA value.
1073     */
1074     ppc32_op_emit_branch_target(cpu,b,b->start_ia);
1075     ppc32_op_emit_branch_target(cpu,b,cpu->ia);
1076    
1077     /* Optimize condition register and general registers */
1078     ppc32_op_optimize(gcpu,b);
1079    
1080     /* Generate JIT code for each instruction in page */
1081     for(i=0;i<PPC32_INSN_PER_PAGE;i++)
1082     {
1083     jit_ptr = b->jit_ptr;
1084    
1085     /* Generate output code */
1086     ppc32_op_gen_list(b,i,gcpu->jit_op_array[i],jit_ptr);
1087    
1088     /* Adjust the JIT buffer if its size is not sufficient */
1089     ppc32_jit_tcb_adjust_buffer(cpu,b);
1090     }
1091    
1092     /* Apply patches and free opcodes */
1093     for(i=0;i<PPC32_INSN_PER_PAGE;i++) {
1094     for(iop=gcpu->jit_op_array[i];iop;iop=iop->next)
1095     if (iop->opcode == JIT_OP_INSN_OUTPUT)
1096     ppc32_jit_tcb_apply_patches(cpu,b,iop);
1097    
1098     jit_op_free_list(gcpu,gcpu->jit_op_array[i]);
1099     gcpu->jit_op_array[i] = NULL;
1100     }
1101    
1102     /* Add end of page (returns to caller) */
1103     ppc32_set_page_jump(cpu,b);
1104    
1105     /* Free patch tables */
1106     ppc32_jit_tcb_free_patches(b);
1107     return(0);
1108     }
1109    
1110     /* ======================================================================== */
1111    
1112 dpavlin 7 /* Compile a PowerPC instruction page */
1113     static inline
1114     ppc32_jit_tcb_t *ppc32_jit_tcb_compile(cpu_ppc_t *cpu,m_uint32_t vaddr)
1115     {
1116     ppc32_jit_tcb_t *block;
1117     m_uint32_t page_addr;
1118    
1119     page_addr = vaddr & ~PPC32_MIN_PAGE_IMASK;
1120    
1121     if (unlikely(!(block = ppc32_jit_tcb_create(cpu,page_addr)))) {
1122     fprintf(stderr,"insn_page_compile: unable to create JIT block.\n");
1123     return NULL;
1124     }
1125    
1126     /* Allocate the array used to convert PPC code ptr to native code ptr */
1127 dpavlin 9 if (!(block->jit_insn_ptr = calloc(PPC32_INSN_PER_PAGE,sizeof(u_char *)))) {
1128 dpavlin 7 fprintf(stderr,"insn_page_compile: unable to create JIT mappings.\n");
1129     goto error;
1130     }
1131    
1132 dpavlin 9 /* Compile the page */
1133     if (ppc32_op_gen_page(cpu,block) == -1) {
1134     fprintf(stderr,"insn_page_compile: unable to compile page.\n");
1135     goto error;
1136 dpavlin 7 }
1137 dpavlin 9
1138 dpavlin 7 /* Add the block to the linked list */
1139     block->next = cpu->tcb_list;
1140     block->prev = NULL;
1141    
1142     if (cpu->tcb_list)
1143     cpu->tcb_list->prev = block;
1144     else
1145     cpu->tcb_last = block;
1146    
1147     cpu->tcb_list = block;
1148    
1149 dpavlin 8 /* Add the block to the physical mapping hash table */
1150     block->phys_next = cpu->exec_phys_map[block->phys_hash];
1151     block->phys_pprev = &cpu->exec_phys_map[block->phys_hash];
1152    
1153     if (cpu->exec_phys_map[block->phys_hash] != NULL)
1154     cpu->exec_phys_map[block->phys_hash]->phys_pprev = &block->phys_next;
1155    
1156     cpu->exec_phys_map[block->phys_hash] = block;
1157    
1158 dpavlin 7 cpu->compiled_pages++;
1159     return block;
1160    
1161     error:
1162     ppc32_jit_tcb_free(cpu,block,FALSE);
1163     return NULL;
1164     }
1165    
1166 dpavlin 9 /* Recompile a page */
1167     int ppc32_jit_tcb_recompile(cpu_ppc_t *cpu,ppc32_jit_tcb_t *block)
1168     {
1169     #if 0
1170     printf("PPC32-JIT: recompiling page 0x%8.8x\n",block->start_ia);
1171     #endif
1172    
1173     /* Free old code chunks */
1174     ppc32_jit_tcb_free_code_chunks(cpu,block);
1175    
1176     /* Reset code ptr array */
1177     memset(block->jit_insn_ptr,0,PPC32_INSN_PER_PAGE * sizeof(u_char *));
1178    
1179     /* Allocate the first JIT buffer */
1180     if (!(block->jit_buffer = exec_page_alloc(cpu)))
1181     return(-1);
1182    
1183     /* Recompile the page */
1184     if (ppc32_op_gen_page(cpu,block) == -1) {
1185     fprintf(stderr,"insn_page_compile: unable to recompile page.\n");
1186     return(-1);
1187     }
1188    
1189     block->target_undef_cnt = 0;
1190     return(0);
1191     }
1192    
1193 dpavlin 7 /* Run a compiled PowerPC instruction block */
1194 dpavlin 11 static forced_inline
1195 dpavlin 7 void ppc32_jit_tcb_run(cpu_ppc_t *cpu,ppc32_jit_tcb_t *block)
1196     {
1197     if (unlikely(cpu->ia & 0x03)) {
1198     fprintf(stderr,"ppc32_jit_tcb_run: Invalid IA 0x%8.8x.\n",cpu->ia);
1199     ppc32_dump_regs(cpu->gen);
1200     ppc32_dump_mmu(cpu->gen);
1201     cpu_stop(cpu->gen);
1202     return;
1203     }
1204    
1205     /* Execute JIT compiled code */
1206     ppc32_jit_tcb_exec(cpu,block);
1207     }
1208    
1209     /* Execute compiled PowerPC code */
1210     void *ppc32_jit_run_cpu(cpu_gen_t *gen)
1211     {
1212     cpu_ppc_t *cpu = CPU_PPC32(gen);
1213     pthread_t timer_irq_thread;
1214     ppc32_jit_tcb_t *block;
1215 dpavlin 8 m_uint32_t ia_hash;
1216 dpavlin 7 int timer_irq_check = 0;
1217    
1218 dpavlin 9 ppc32_jit_init_hreg_mapping(cpu);
1219    
1220 dpavlin 8 if (pthread_create(&timer_irq_thread,NULL,(void *)ppc32_timer_irq_run,cpu))
1221 dpavlin 7 {
1222     fprintf(stderr,
1223     "VM '%s': unable to create Timer IRQ thread for CPU%u.\n",
1224     cpu->vm->name,gen->id);
1225     cpu_stop(cpu->gen);
1226     return NULL;
1227     }
1228    
1229     gen->cpu_thread_running = TRUE;
1230 dpavlin 11 cpu_exec_loop_set(gen);
1231 dpavlin 7
1232     start_cpu:
1233     gen->idle_count = 0;
1234    
1235     for(;;) {
1236     if (unlikely(gen->state != CPU_STATE_RUNNING))
1237     break;
1238    
1239     #if DEBUG_BLOCK_PERF_CNT
1240     cpu->perf_counter++;
1241     #endif
1242     /* Handle virtual idle loop */
1243     if (unlikely(cpu->ia == cpu->idle_pc)) {
1244     if (++gen->idle_count == gen->idle_max) {
1245     cpu_idle_loop(gen);
1246     gen->idle_count = 0;
1247     }
1248     }
1249    
1250     /* Handle the virtual CPU clock */
1251     if (++timer_irq_check == cpu->timer_irq_check_itv) {
1252     timer_irq_check = 0;
1253    
1254     if (cpu->timer_irq_pending && !cpu->irq_disable &&
1255     (cpu->msr & PPC32_MSR_EE))
1256     {
1257     cpu->timer_irq_armed = 0;
1258     cpu->timer_irq_pending--;
1259    
1260     vm_set_irq(cpu->vm,0);
1261     }
1262     }
1263    
1264 dpavlin 8 /* Check IRQs */
1265     if (unlikely(cpu->irq_check))
1266     ppc32_trigger_irq(cpu);
1267 dpavlin 7
1268 dpavlin 8 /* Get the JIT block corresponding to IA register */
1269     ia_hash = ppc32_jit_get_ia_hash(cpu->ia);
1270     block = cpu->exec_blk_map[ia_hash];
1271 dpavlin 9
1272 dpavlin 7 /* No block found, compile the page */
1273     if (unlikely(!block) || unlikely(!ppc32_jit_tcb_match(cpu,block)))
1274     {
1275     if (block != NULL) {
1276     ppc32_jit_tcb_free(cpu,block,TRUE);
1277 dpavlin 8 cpu->exec_blk_map[ia_hash] = NULL;
1278 dpavlin 7 }
1279    
1280     block = ppc32_jit_tcb_compile(cpu,cpu->ia);
1281 dpavlin 8
1282 dpavlin 7 if (unlikely(!block)) {
1283     fprintf(stderr,
1284     "VM '%s': unable to compile block for CPU%u IA=0x%8.8x\n",
1285     cpu->vm->name,gen->id,cpu->ia);
1286     cpu_stop(gen);
1287     break;
1288     }
1289    
1290 dpavlin 8 cpu->exec_blk_map[ia_hash] = block;
1291 dpavlin 7 }
1292    
1293     #if DEBUG_BLOCK_TIMESTAMP
1294     block->tm_last_use = jit_jiffies++;
1295     #endif
1296     block->acc_count++;
1297     ppc32_jit_tcb_run(cpu,block);
1298     }
1299    
1300     if (!cpu->ia) {
1301     cpu_stop(gen);
1302     cpu_log(gen,"JIT","IA=0, halting CPU.\n");
1303     }
1304    
1305     /* Check regularly if the CPU has been restarted */
1306     while(gen->cpu_thread_running) {
1307     gen->seq_state++;
1308    
1309     switch(gen->state) {
1310     case CPU_STATE_RUNNING:
1311     gen->state = CPU_STATE_RUNNING;
1312     goto start_cpu;
1313    
1314     case CPU_STATE_HALTED:
1315     gen->cpu_thread_running = FALSE;
1316     pthread_join(timer_irq_thread,NULL);
1317     break;
1318     }
1319    
1320     /* CPU is paused */
1321     usleep(200000);
1322     }
1323    
1324     return NULL;
1325     }

  ViewVC Help
Powered by ViewVC 1.1.26