/[dynamips]/upstream/dynamips-0.2.6-RC3/mips64_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

Contents of /upstream/dynamips-0.2.6-RC3/mips64_jit.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Sat Oct 6 16:01:44 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.5/mips64_jit.c
File MIME type: text/plain
File size: 20055 byte(s)
import 0.2.5 from upstream

1 /*
2 * Cisco 7200 (Predator) simulation platform.
3 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4 *
5 * MIPS64 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 ARCH_INC_FILE
20
21 #include "rbtree.h"
22 #include "cp0.h"
23 #include "memory.h"
24 #include "cpu.h"
25 #include "device.h"
26 #include "mips64.h"
27 #include "mips64_exec.h"
28 #include "insn_lookup.h"
29 #include "ptask.h"
30
31 #if DEBUG_BLOCK_TIMESTAMP
32 static volatile m_uint64_t jit_jiffies = 0;
33 #endif
34
35 /* MIPS jump instructions for block scan */
36 struct insn_jump mips64_insn_jumps[] = {
37 { "b" , 0xffff0000, 0x10000000, 16, 1 },
38 { "bal" , 0xffff0000, 0x04110000, 16, 1 },
39 { "beq" , 0xfc000000, 0x10000000, 16, 1 },
40 { "beql" , 0xfc000000, 0x50000000, 16, 1 },
41 { "bgez" , 0xfc1f0000, 0x04010000, 16, 1 },
42 { "bgezl" , 0xfc1f0000, 0x04030000, 16, 1 },
43 { "bgezal" , 0xfc1f0000, 0x04110000, 16, 1 },
44 { "bgezall" , 0xfc1f0000, 0x04130000, 16, 1 },
45 { "bgtz" , 0xfc1f0000, 0x1c000000, 16, 1 },
46 { "bgtzl" , 0xfc1f0000, 0x5c000000, 16, 1 },
47 { "blez" , 0xfc1f0000, 0x18000000, 16, 1 },
48 { "blezl" , 0xfc1f0000, 0x58000000, 16, 1 },
49 { "bltz" , 0xfc1f0000, 0x04000000, 16, 1 },
50 { "bltzl" , 0xfc1f0000, 0x04020000, 16, 1 },
51 { "bltzal" , 0xfc1f0000, 0x04100000, 16, 1 },
52 { "bltzall" , 0xfc1f0000, 0x04120000, 16, 1 },
53 { "bne" , 0xfc000000, 0x14000000, 16, 1 },
54 { "bnel" , 0xfc000000, 0x54000000, 16, 1 },
55 { "j" , 0xfc000000, 0x08000000, 26, 0 },
56 { NULL , 0x00000000, 0x00000000, 0, 0 },
57 };
58
59 /* Instruction Lookup Table */
60 static insn_lookup_t *ilt = NULL;
61
62 static void *mips64_jit_get_insn(int index)
63 {
64 return(&mips64_insn_tags[index]);
65 }
66
67 static int mips64_jit_chk_lo(struct insn_tag *tag,int value)
68 {
69 return((value & tag->mask) == (tag->value & 0xFFFF));
70 }
71
72 static int mips64_jit_chk_hi(struct insn_tag *tag,int value)
73 {
74 return((value & (tag->mask >> 16)) == (tag->value >> 16));
75 }
76
77 /* Initialize instruction lookup table */
78 void mips64_jit_create_ilt(void)
79 {
80 int i,count;
81
82 for(i=0,count=0;mips64_insn_tags[i].emit;i++)
83 count++;
84
85 ilt = ilt_create(count,
86 (ilt_get_insn_cbk_t)mips64_jit_get_insn,
87 (ilt_check_cbk_t)mips64_jit_chk_lo,
88 (ilt_check_cbk_t)mips64_jit_chk_hi);
89 }
90
91 /* Initialize the JIT structure */
92 int mips64_jit_init(cpu_mips_t *cpu)
93 {
94 insn_exec_page_t *cp;
95 u_char *cp_addr;
96 u_int area_size;
97 size_t len;
98 int i;
99
100 /* Physical mapping for executable pages */
101 len = 1048576 * sizeof(void *);
102 cpu->exec_phys_map = m_memalign(4096,len);
103 memset(cpu->exec_phys_map,0,len);
104
105 /* Get area size */
106 if (!(area_size = cpu->vm->exec_area_size))
107 area_size = MIPS_EXEC_AREA_SIZE;
108
109 /* Create executable page area */
110 cpu->exec_page_area_size = area_size * 1048576;
111 cpu->exec_page_area = mmap(NULL,cpu->exec_page_area_size,
112 PROT_EXEC|PROT_READ|PROT_WRITE,
113 MAP_SHARED|MAP_ANONYMOUS,-1,(off_t)0);
114
115 if (!cpu->exec_page_area) {
116 fprintf(stderr,
117 "mips64_jit_init: unable to create exec area (size %lu)\n",
118 (u_long)cpu->exec_page_area_size);
119 return(-1);
120 }
121
122 /* Carve the executable page area */
123 cpu->exec_page_count = cpu->exec_page_area_size / MIPS_JIT_BUFSIZE;
124
125 cpu->exec_page_array = calloc(cpu->exec_page_count,
126 sizeof(insn_exec_page_t));
127
128 if (!cpu->exec_page_array) {
129 fprintf(stderr,"mips64_jit_init: unable to create exec page array\n");
130 return(-1);
131 }
132
133 for(i=0,cp_addr=cpu->exec_page_area;i<cpu->exec_page_count;i++) {
134 cp = &cpu->exec_page_array[i];
135
136 cp->ptr = cp_addr;
137 cp_addr += MIPS_JIT_BUFSIZE;
138
139 cp->next = cpu->exec_page_free_list;
140 cpu->exec_page_free_list = cp;
141 }
142
143 printf("CPU%u: carved JIT exec zone of %lu Mb into %lu pages of %u Kb.\n",
144 cpu->id,(u_long)(cpu->exec_page_area_size / 1048576),
145 (u_long)cpu->exec_page_count,MIPS_JIT_BUFSIZE / 1024);
146 return(0);
147 }
148
149 /* Flush the JIT */
150 u_int mips64_jit_flush(cpu_mips_t *cpu,u_int threshold)
151 {
152 insn_block_t *p,*next;
153 u_int count = 0;
154
155 if (!threshold)
156 threshold = (u_int)(-1); /* UINT_MAX not defined everywhere */
157
158 for(p=cpu->insn_block_list;p;p=next) {
159 next = p->next;
160
161 if (p->acc_count <= threshold) {
162 cpu->exec_phys_map[p->phys_page] = NULL;
163 insn_block_free(cpu,p,TRUE);
164 count++;
165 }
166 }
167
168 cpu->compiled_pages -= count;
169 return(count);
170 }
171
172 /* Shutdown the JIT */
173 void mips64_jit_shutdown(cpu_mips_t *cpu)
174 {
175 insn_block_t *p,*next;
176
177 /* Flush the JIT */
178 mips64_jit_flush(cpu,0);
179
180 /* Free the instruction blocks */
181 for(p=cpu->insn_block_free_list;p;p=next) {
182 next = p->next;
183 free(p);
184 }
185
186 /* Unmap the executable page area */
187 if (cpu->exec_page_area)
188 munmap(cpu->exec_page_area,cpu->exec_page_area_size);
189
190 /* Free the exec page array */
191 free(cpu->exec_page_array);
192
193 /* Free physical mapping for executable pages */
194 free(cpu->exec_phys_map);
195 }
196
197 /* Allocate an exec page */
198 static inline insn_exec_page_t *exec_page_alloc(cpu_mips_t *cpu)
199 {
200 insn_exec_page_t *p;
201 u_int count;
202
203 /* If the free list is empty, flush JIT */
204 if (unlikely(!cpu->exec_page_free_list))
205 {
206 if (cpu->jit_flush_method) {
207 cpu_log(cpu,"JIT","flushing data structures (compiled pages=%u)\n",
208 cpu->compiled_pages);
209 mips64_jit_flush(cpu,0);
210 } else {
211 count = mips64_jit_flush(cpu,100);
212 cpu_log(cpu,"JIT","partial JIT flush (count=%u)\n",count);
213
214 if (!cpu->exec_page_free_list)
215 mips64_jit_flush(cpu,0);
216 }
217
218 /* Use both methods alternatively */
219 cpu->jit_flush_method = 1 - cpu->jit_flush_method;
220 }
221
222 if (unlikely(!(p = cpu->exec_page_free_list)))
223 return NULL;
224
225 cpu->exec_page_free_list = p->next;
226 cpu->exec_page_alloc++;
227 return p;
228 }
229
230 /* Free an exec page and returns it to the pool */
231 static inline void exec_page_free(cpu_mips_t *cpu,insn_exec_page_t *p)
232 {
233 if (p) {
234 p->next = cpu->exec_page_free_list;
235 cpu->exec_page_free_list = p;
236 cpu->exec_page_alloc--;
237 }
238 }
239
240 /* Find the JIT code emitter for the specified MIPS instruction */
241 struct insn_tag *insn_tag_find(mips_insn_t ins)
242 {
243 struct insn_tag *tag = NULL;
244 int index;
245
246 index = ilt_lookup(ilt,ins);
247 tag = mips64_jit_get_insn(index);
248 return tag;
249 }
250
251 /* Check if the specified MIPS instruction is a jump */
252 struct insn_jump *insn_jump_find(mips_insn_t ins)
253 {
254 struct insn_jump *jump = NULL;
255 int i;
256
257 for(i=0;mips64_insn_jumps[i].name;i++)
258 if ((ins & mips64_insn_jumps[i].mask) == mips64_insn_jumps[i].value) {
259 jump = &mips64_insn_jumps[i];
260 break;
261 }
262
263 return(jump);
264 }
265
266 /* Fetch a MIPS instruction */
267 static forced_inline mips_insn_t insn_fetch(insn_block_t *b)
268 {
269 return(vmtoh32(b->mips_code[b->mips_trans_pos]));
270 }
271
272 /* Emit a breakpoint if necessary */
273 #if BREAKPOINT_ENABLE
274 static void insn_emit_breakpoint(cpu_mips_t *cpu,insn_block_t *b)
275 {
276 m_uint64_t pc;
277 int i;
278
279 pc = b->start_pc+((b->mips_trans_pos-1)<<2);
280
281 for(i=0;i<MIPS64_MAX_BREAKPOINTS;i++)
282 if (pc == cpu->breakpoints[i]) {
283 mips64_emit_breakpoint(b);
284 break;
285 }
286 }
287 #endif /* BREAKPOINT_ENABLE */
288
289 /* Fetch a MIPS instruction and emit corresponding translated code */
290 struct insn_tag *insn_fetch_and_emit(cpu_mips_t *cpu,insn_block_t *block,
291 int delay_slot)
292 {
293 struct insn_tag *tag;
294 mips_insn_t code;
295
296 code = insn_fetch(block);
297 tag = insn_tag_find(code);
298 assert(tag);
299
300 if (delay_slot && !tag->delay_slot) {
301 mips64_emit_invalid_delay_slot(block);
302 return NULL;
303 }
304
305 if (!delay_slot) {
306 block->jit_insn_ptr[block->mips_trans_pos] = block->jit_ptr;
307 }
308
309 if (delay_slot != 2)
310 block->mips_trans_pos++;
311
312 #if DEBUG_PERF_COUNTER
313 mips64_inc_perf_counter(block);
314 #endif
315
316 if (!delay_slot) {
317 /* Check for IRQs + Increment count register before jumps */
318 if (!tag->delay_slot) {
319 mips64_inc_cp0_count_reg(block);
320 mips64_check_pending_irq(block);
321 }
322 }
323
324 #if BREAKPOINT_ENABLE
325 if (cpu->breakpoints_enabled)
326 insn_emit_breakpoint(cpu,block);
327 #endif
328
329 tag->emit(cpu,block,code);
330 return tag;
331 }
332
333 /* Add end of JIT block */
334 void insn_block_add_end(insn_block_t *b)
335 {
336 mips64_set_pc(b,b->start_pc+(b->mips_trans_pos<<2));
337 insn_block_push_epilog(b);
338 }
339
340 /* Record a patch to apply in a compiled block */
341 int insn_block_record_patch(insn_block_t *block,u_char *jit_ptr,
342 m_uint64_t vaddr)
343 {
344 struct insn_patch_table *ipt = block->patch_table;
345 struct insn_patch *patch;
346
347 /* pc must be 32-bit aligned */
348 if (vaddr & 0x03) {
349 fprintf(stderr,"Block 0x%8.8llx: trying to record an invalid PC "
350 "(0x%8.8llx) - mips_trans_pos=%d.\n",
351 block->start_pc,vaddr,block->mips_trans_pos);
352 return(-1);
353 }
354
355 if (!ipt || (ipt->cur_patch >= INSN_PATCH_TABLE_SIZE))
356 {
357 /* full table or no table, create a new one */
358 ipt = malloc(sizeof(*ipt));
359 if (!ipt) {
360 fprintf(stderr,"%% Unable to create patch table.\n");
361 return(-1);
362 }
363
364 memset(ipt,0,sizeof(*ipt));
365 ipt->next = block->patch_table;
366 block->patch_table = ipt;
367 }
368
369 #if DEBUG_BLOCK_PATCH
370 printf("Block 0x%8.8llx: recording patch [JIT:%p->mips:0x%8.8llx], "
371 "MTP=%d\n",block->start_pc,jit_ptr,vaddr,block->mips_trans_pos);
372 #endif
373
374 patch = &ipt->patches[ipt->cur_patch];
375 patch->jit_insn = jit_ptr;
376 patch->mips_pc = vaddr;
377 ipt->cur_patch++;
378 return(0);
379 }
380
381 /* Apply all patches */
382 int insn_block_apply_patches(cpu_mips_t *cpu,insn_block_t *block)
383 {
384 struct insn_patch_table *ipt;
385 struct insn_patch *patch;
386 u_char *jit_dst;
387 int i;
388
389 for(ipt=block->patch_table;ipt;ipt=ipt->next)
390 for(i=0;i<ipt->cur_patch;i++)
391 {
392 patch = &ipt->patches[i];
393 jit_dst = insn_block_get_jit_ptr(block,patch->mips_pc);
394
395 if (jit_dst) {
396 #if DEBUG_BLOCK_PATCH
397 printf("Block 0x%8.8llx: applying patch "
398 "[JIT:%p->mips:0x%8.8llx=JIT:%p]\n",
399 block->start_pc,patch->jit_insn,patch->mips_pc,jit_dst);
400 #endif
401 insn_block_set_patch(patch->jit_insn,jit_dst);
402 }
403 }
404
405 return(0);
406 }
407
408 /* Free the patch table */
409 static void insn_block_free_patches(insn_block_t *block)
410 {
411 struct insn_patch_table *p,*next;
412
413 for(p=block->patch_table;p;p=next) {
414 next = p->next;
415 free(p);
416 }
417
418 block->patch_table = NULL;
419 }
420
421 /* Adjust the JIT buffer if its size is not sufficient */
422 int insn_block_adjust_jit_buffer(cpu_mips_t *cpu,insn_block_t *block)
423 {
424 insn_exec_page_t *new_buffer;
425
426 if ((block->jit_ptr - block->jit_buffer->ptr) <= (MIPS_JIT_BUFSIZE - 512))
427 return(0);
428
429 #if DEBUG_BLOCK_CHUNK
430 printf("Block 0x%llx: adjusting JIT buffer...\n",block->start_pc);
431 #endif
432
433 if (block->jit_chunk_pos >= INSN_MAX_CHUNKS) {
434 fprintf(stderr,"Block 0x%llx: too many JIT chunks.\n",block->start_pc);
435 return(-1);
436 }
437
438 if (!(new_buffer = exec_page_alloc(cpu)))
439 return(-1);
440
441 /* record the new exec page */
442 block->jit_chunks[block->jit_chunk_pos++] = block->jit_buffer;
443 block->jit_buffer = new_buffer;
444
445 /* jump to the new exec page (link) */
446 insn_block_set_jump(block->jit_ptr,new_buffer->ptr);
447 block->jit_ptr = new_buffer->ptr;
448 return(0);
449 }
450
451 /* Allocate an instruction block */
452 static inline insn_block_t *insn_block_alloc(cpu_mips_t *cpu)
453 {
454 insn_block_t *p;
455
456 if (cpu->insn_block_free_list) {
457 p = cpu->insn_block_free_list;
458 cpu->insn_block_free_list = p->next;
459 } else {
460 if (!(p = malloc(sizeof(*p))))
461 return NULL;
462 }
463
464 memset(p,0,sizeof(*p));
465 return p;
466 }
467
468 /* Free an instruction block */
469 void insn_block_free(cpu_mips_t *cpu,insn_block_t *block,int list_removal)
470 {
471 int i;
472
473 if (block) {
474 if (list_removal) {
475 /* Remove the block from the linked list */
476 if (block->next)
477 block->next->prev = block->prev;
478 else
479 cpu->insn_block_last = block->prev;
480
481 if (block->prev)
482 block->prev->next = block->next;
483 else
484 cpu->insn_block_list = block->next;
485 }
486
487 /* Free the patch tables */
488 insn_block_free_patches(block);
489
490 /* Free code pages */
491 for(i=0;i<INSN_MAX_CHUNKS;i++)
492 exec_page_free(cpu,block->jit_chunks[i]);
493
494 /* Free the current JIT buffer */
495 exec_page_free(cpu,block->jit_buffer);
496
497 /* Free the MIPS-to-native code mapping */
498 free(block->jit_insn_ptr);
499
500 /* Make the block return to the free list */
501 block->next = cpu->insn_block_free_list;
502 cpu->insn_block_free_list = block;
503 }
504 }
505
506 /* Create an instruction block */
507 static insn_block_t *insn_block_create(cpu_mips_t *cpu,m_uint64_t vaddr)
508 {
509 insn_block_t *block = NULL;
510
511 if (!(block = insn_block_alloc(cpu)))
512 goto err_block_alloc;
513
514 block->start_pc = vaddr;
515
516 /* Allocate the first JIT buffer */
517 if (!(block->jit_buffer = exec_page_alloc(cpu)))
518 goto err_jit_alloc;
519
520 block->jit_ptr = block->jit_buffer->ptr;
521 block->mips_code = cpu->mem_op_lookup(cpu,block->start_pc);
522
523 if (!block->mips_code) {
524 fprintf(stderr,"%% No memory map for code execution at 0x%llx\n",
525 block->start_pc);
526 goto err_lookup;
527 }
528
529 #if DEBUG_BLOCK_TIMESTAMP
530 block->tm_first_use = block->tm_last_use = jit_jiffies;
531 #endif
532 return block;
533
534 err_lookup:
535 err_jit_alloc:
536 insn_block_free(cpu,block,FALSE);
537 err_block_alloc:
538 fprintf(stderr,"%% Unable to create instruction block for vaddr=0x%llx\n",
539 vaddr);
540 return NULL;
541 }
542
543 /* Compile a MIPS instruction page */
544 static inline insn_block_t *insn_page_compile(cpu_mips_t *cpu,m_uint64_t vaddr)
545 {
546 m_uint64_t page_addr;
547 insn_block_t *block;
548 struct insn_tag *tag;
549 size_t len;
550
551 page_addr = vaddr & ~(m_uint64_t)MIPS_MIN_PAGE_IMASK;
552
553 if (unlikely(!(block = insn_block_create(cpu,page_addr)))) {
554 fprintf(stderr,"insn_page_compile: unable to create JIT block.\n");
555 return NULL;
556 }
557
558 /* Allocate the array used to convert MIPS code ptr to native code ptr */
559 len = MIPS_MIN_PAGE_SIZE / sizeof(mips_insn_t);
560
561 if (!(block->jit_insn_ptr = calloc(len,sizeof(u_char *)))) {
562 fprintf(stderr,"insn_page_compile: unable to create JIT mappings.\n");
563 goto error;
564 }
565
566 /* Emit native code for each instruction */
567 block->mips_trans_pos = 0;
568
569 while(block->mips_trans_pos < (MIPS_MIN_PAGE_SIZE/sizeof(mips_insn_t)))
570 {
571 if (unlikely(!(tag = insn_fetch_and_emit(cpu,block,0)))) {
572 fprintf(stderr,"insn_page_compile: unable to fetch instruction.\n");
573 goto error;
574 }
575
576 #if DEBUG_BLOCK_COMPILE
577 printf("Page 0x%8.8llx: emitted tag 0x%8.8x/0x%8.8x\n",
578 block->start_pc,tag->mask,tag->value);
579 #endif
580
581 insn_block_adjust_jit_buffer(cpu,block);
582 }
583
584 insn_block_add_end(block);
585 insn_block_apply_patches(cpu,block);
586 insn_block_free_patches(block);
587
588 /* Add the block to the linked list */
589 block->next = cpu->insn_block_list;
590 block->prev = NULL;
591
592 if (cpu->insn_block_list)
593 cpu->insn_block_list->prev = block;
594 else
595 cpu->insn_block_last = block;
596
597 cpu->insn_block_list = block;
598
599 cpu->compiled_pages++;
600 return block;
601
602 error:
603 insn_block_free(cpu,block,FALSE);
604 return NULL;
605 }
606
607 /* Run a compiled MIPS instruction block */
608 static forced_inline void insn_block_run(cpu_mips_t *cpu,insn_block_t *block)
609 {
610 #if DEBUG_SYM_TREE
611 struct symbol *sym = NULL;
612 int mark = FALSE;
613 #endif
614
615 if (unlikely(cpu->pc & 0x03)) {
616 fprintf(stderr,"insn_block_run: Invalid PC 0x%llx.\n",cpu->pc);
617 mips64_dump_regs(cpu);
618 tlb_dump(cpu);
619 cpu_stop(cpu);
620 return;
621 }
622
623 #if DEBUG_SYM_TREE
624 if (cpu->sym_trace && cpu->sym_tree)
625 {
626 if ((sym = mips64_sym_lookup(cpu,cpu->pc)) != NULL) {
627 cpu_log(cpu,"insn_block_run(start)",
628 "%s (PC=0x%llx) RA = 0x%llx\na0=0x%llx, "
629 "a1=0x%llx, a2=0x%llx, a3=0x%llx\n",
630 sym->name, cpu->pc, cpu->gpr[MIPS_GPR_RA],
631 cpu->gpr[MIPS_GPR_A0], cpu->gpr[MIPS_GPR_A1],
632 cpu->gpr[MIPS_GPR_A2], cpu->gpr[MIPS_GPR_A3]);
633 mark = TRUE;
634 }
635 }
636 #endif
637
638 /* Execute JIT compiled code */
639 insn_block_exec_jit_code(cpu,block);
640
641 #if DEBUG_SYM_TREE
642 if (mark) {
643 cpu_log(cpu,"insn_block_run(end)","%s, v0 = 0x%llx\n",
644 sym->name,cpu->gpr[MIPS_GPR_V0]);
645 }
646 #endif
647 }
648
649 /* Check if the specified address belongs to the specified block */
650 int insn_block_local_addr(insn_block_t *block,m_uint64_t vaddr,
651 u_char **jit_addr)
652 {
653 if ((vaddr >= block->start_pc) &&
654 ((vaddr - block->start_pc) < MIPS_MIN_PAGE_SIZE))
655 {
656 *jit_addr = insn_block_get_jit_ptr(block,vaddr);
657 return(1);
658 }
659
660 return(0);
661 }
662
663 /* Execute a compiled MIPS code */
664 void *insn_block_execute(cpu_mips_t *cpu)
665 {
666 pthread_t timer_irq_thread;
667 insn_block_t *block;
668 m_uint32_t phys_page;
669 int idle_count = 0;
670 int timer_irq_check = 0;
671
672 if (pthread_create(&timer_irq_thread,NULL,
673 (void *)mips64_timer_irq_run,cpu))
674 {
675 fprintf(stderr,"VM '%s': unable to create Timer IRQ thread for CPU%u.\n",
676 cpu->vm->name,cpu->id);
677 cpu_stop(cpu);
678 return NULL;
679 }
680
681 cpu->cpu_thread_running = TRUE;
682 start_cpu:
683 for(;;) {
684 if (unlikely(!cpu->pc) || unlikely(cpu->state != MIPS_CPU_RUNNING))
685 break;
686
687 /* Handle virtual idle loop */
688 if (unlikely(cpu->pc == cpu->idle_pc)) {
689 if (++idle_count == cpu->idle_max) {
690 mips64_idle_loop(cpu);
691 idle_count = 0;
692 }
693 }
694
695 /* Handle the virtual CPU clock */
696 if (++timer_irq_check == cpu->timer_irq_check_itv) {
697 timer_irq_check = 0;
698
699 if (cpu->timer_irq_pending && !cpu->irq_disable) {
700 mips64_trigger_timer_irq(cpu);
701 mips64_trigger_irq(cpu);
702 cpu->timer_irq_pending--;
703 }
704 }
705
706 /* Get the physical page address corresponding to PC register */
707 if (unlikely(cpu->translate(cpu,cpu->pc,&phys_page))) {
708 fprintf(stderr,"VM '%s': no physical page for CPU%u PC=0x%llx\n",
709 cpu->vm->name,cpu->id,cpu->pc);
710 cpu_stop(cpu);
711 break;
712 }
713
714 block = cpu->exec_phys_map[phys_page];
715
716 /* No block found, compile the page */
717 if (unlikely(!block)) {
718 block = insn_page_compile(cpu,cpu->pc);
719 if (unlikely(!block)) {
720 fprintf(stderr,
721 "VM '%s': unable to compile block for CPU%u PC=0x%llx\n",
722 cpu->vm->name,cpu->id,cpu->pc);
723 cpu_stop(cpu);
724 break;
725 }
726
727 block->phys_page = phys_page;
728 cpu->exec_phys_map[phys_page] = block;
729 }
730
731 #if DEBUG_BLOCK_TIMESTAMP
732 block->tm_last_use = jit_jiffies++;
733 #endif
734 block->acc_count++;
735 insn_block_run(cpu,block);
736 }
737
738 if (!cpu->pc) {
739 cpu_stop(cpu);
740 cpu_log(cpu,"JIT","PC=0, halting CPU.\n");
741 }
742
743 /* Check regularly if the CPU has been restarted */
744 while(cpu->cpu_thread_running) {
745 cpu->seq_state++;
746
747 switch(cpu->state) {
748 case MIPS_CPU_RUNNING:
749 cpu->state = MIPS_CPU_RUNNING;
750 goto start_cpu;
751
752 case MIPS_CPU_HALTED:
753 cpu->cpu_thread_running = FALSE;
754 pthread_join(timer_irq_thread,NULL);
755 break;
756 }
757
758 /* CPU is paused */
759 usleep(200000);
760 }
761
762 return NULL;
763 }

  ViewVC Help
Powered by ViewVC 1.1.26