Annotation of cf/mips64_jit.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Cisco 7200 (Predator) simulation platform.
                      3:  * Copyright (c) 2005,2006 Christophe Fillot ([email protected])
                      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_exec.h"
                     27: #include "insn_lookup.h"
                     28: #include "ptask.h"
                     29: 
                     30: extern rbtree_tree *sym_tree;
                     31: 
                     32: #if DEBUG_BLOCK_TIMESTAMP
                     33: static volatile m_uint64_t jit_jiffies = 0;
                     34: #endif
                     35: 
                     36: /* MIPS jump instructions for block scan */
                     37: struct insn_jump mips64_insn_jumps[] = {
                     38:    { "b"       , 0xffff0000, 0x10000000, 16, 1 },
                     39:    { "bal"     , 0xffff0000, 0x04110000, 16, 1 },
                     40:    { "beq"     , 0xfc000000, 0x10000000, 16, 1 },
                     41:    { "beql"    , 0xfc000000, 0x50000000, 16, 1 },
                     42:    { "bgez"    , 0xfc1f0000, 0x04010000, 16, 1 },
                     43:    { "bgezl"   , 0xfc1f0000, 0x04030000, 16, 1 },
                     44:    { "bgezal"  , 0xfc1f0000, 0x04110000, 16, 1 },
                     45:    { "bgezall" , 0xfc1f0000, 0x04130000, 16, 1 },
                     46:    { "bgtz"    , 0xfc1f0000, 0x1c000000, 16, 1 },
                     47:    { "bgtzl"   , 0xfc1f0000, 0x5c000000, 16, 1 },
                     48:    { "blez"    , 0xfc1f0000, 0x18000000, 16, 1 },
                     49:    { "blezl"   , 0xfc1f0000, 0x58000000, 16, 1 },
                     50:    { "bltz"    , 0xfc1f0000, 0x04000000, 16, 1 },
                     51:    { "bltzl"   , 0xfc1f0000, 0x04020000, 16, 1 },
                     52:    { "bltzal"  , 0xfc1f0000, 0x04100000, 16, 1 },
                     53:    { "bltzall" , 0xfc1f0000, 0x04120000, 16, 1 },
                     54:    { "bne"     , 0xfc000000, 0x14000000, 16, 1 },
                     55:    { "bnel"    , 0xfc000000, 0x54000000, 16, 1 },
                     56:    { "j"       , 0xfc000000, 0x08000000, 26, 0 },
                     57:    { NULL      , 0x00000000, 0x00000000,  0, 0 },
                     58: };
                     59: 
                     60: /* Instruction Lookup Table */
                     61: static insn_lookup_t *ilt = NULL;
                     62: 
                     63: static void *mips64_jit_get_insn(int index)
                     64: {
                     65:    return(&mips64_insn_tags[index]);
                     66: }
                     67: 
                     68: static int mips64_jit_chk_lo(struct insn_tag *tag,int value)
                     69: {
                     70:    return((value & tag->mask) == (tag->value & 0xFFFF));
                     71: }
                     72: 
                     73: static int mips64_jit_chk_hi(struct insn_tag *tag,int value)
                     74: {
                     75:    return((value & (tag->mask >> 16)) == (tag->value >> 16));
                     76: }
                     77: 
                     78: /* Initialize instruction lookup table */
                     79: void mips64_jit_create_ilt(void)
                     80: {
                     81:    int i,count;
                     82: 
                     83:    for(i=0,count=0;mips64_insn_tags[i].emit;i++)
                     84:       count++;
                     85: 
                     86:    ilt = ilt_create(count,
                     87:                     (ilt_get_insn_cbk_t)mips64_jit_get_insn,
                     88:                     (ilt_check_cbk_t)mips64_jit_chk_lo,
                     89:                     (ilt_check_cbk_t)mips64_jit_chk_hi);
                     90: }
                     91: 
                     92: /* Find the JIT code emitter for the specified MIPS instruction */
                     93: struct insn_tag *insn_tag_find(mips_insn_t ins)
                     94: {
                     95:    struct insn_tag *tag = NULL;
                     96:    int index;
                     97: 
                     98:    index = ilt_lookup(ilt,ins);
                     99:    tag = mips64_jit_get_insn(index);
                    100:    return tag;
                    101: }
                    102: 
                    103: /* Check if the specified MIPS instruction is a jump */
                    104: struct insn_jump *insn_jump_find(mips_insn_t ins)
                    105: {
                    106:    struct insn_jump *jump = NULL;
                    107:    int i;
                    108: 
                    109:    for(i=0;mips64_insn_jumps[i].name;i++)
                    110:       if ((ins & mips64_insn_jumps[i].mask) == mips64_insn_jumps[i].value) {
                    111:          jump = &mips64_insn_jumps[i];
                    112:          break;
                    113:       }
                    114: 
                    115:    return(jump);
                    116: }
                    117: 
                    118: /* Fetch a MIPS instruction */
                    119: static inline mips_insn_t insn_fetch(insn_block_t *b)
                    120: {
                    121:    return(vmtoh32(b->mips_code[b->mips_trans_pos]));
                    122: }
                    123: 
                    124: /* Emit a breakpoint if necessary */
                    125: static void insn_emit_breakpoint(cpu_mips_t *cpu,insn_block_t *b)
                    126: {
                    127:    m_uint64_t pc;
                    128:    int i;
                    129: 
                    130:    pc = b->start_pc+((b->mips_trans_pos-1)<<2);
                    131: 
                    132:    for(i=0;i<MIPS64_MAX_BREAKPOINTS;i++)
                    133:       if (pc == cpu->breakpoints[i]) {
                    134:          mips64_emit_breakpoint(b);
                    135:          break;
                    136:       }
                    137: }
                    138: 
                    139: /* Fetch a MIPS instruction and emit corresponding translated code */
                    140: struct insn_tag *insn_fetch_and_emit(cpu_mips_t *cpu,insn_block_t *block,
                    141:                                      int delay_slot)
                    142: {
                    143:    struct insn_tag *tag;
                    144:    mips_insn_t code;
                    145: 
                    146:    code = insn_fetch(block);
                    147:    tag = insn_tag_find(code);
                    148:    assert(tag);
                    149:    
                    150:    if (delay_slot && !tag->delay_slot) {
                    151:       fprintf(stderr,"%% Invalid instruction 0x%8.8x in delay slot.\n",code);
                    152:       return NULL;
                    153:    }
                    154: 
                    155:    if (!delay_slot) {
                    156:       block->jit_insn_ptr[block->mips_trans_pos] = block->jit_ptr;
                    157:    }
                    158: 
                    159:    if (delay_slot != 2)
                    160:       block->mips_trans_pos++;
                    161: 
                    162: #if BREAKPOINT_ENABLE
                    163:    if (cpu->breakpoints_enabled)
                    164:       insn_emit_breakpoint(cpu,block);
                    165: #endif
                    166: 
                    167:    mips64_inc_cp0_count_reg(block);
                    168: 
                    169:    if (!delay_slot)
                    170:       mips64_check_pending_irq(block);
                    171: 
                    172:    tag->emit(cpu,block,code);
                    173:    return tag;
                    174: }
                    175: 
                    176: /* 
                    177:  * This is a special case of MIPS instruction emitting, when this fucking
                    178:  * GCC compiler has been able to optimize a lot and to branch in a delay
                    179:  * slot.
                    180:  */
                    181: u_char *insn_special_emit(cpu_mips_t *cpu,insn_block_t *block,m_uint64_t vaddr)
                    182: {   
                    183:    struct insn_tag *tag;
                    184:    mips_insn_t code;
                    185:    u_int offset;
                    186:    u_char *cptr;
                    187:    
                    188:    /* the caller will patch to this address */
                    189:    cptr = block->jit_ptr;
                    190: 
                    191:    offset = (vaddr - block->start_pc) >> 2;
                    192:    block->jit_insn_ptr[offset] = cptr;
                    193:    code = vmtoh32(block->mips_code[offset]);
                    194:    tag = insn_tag_find(code);
                    195:    assert(tag);
                    196: 
                    197:    tag->emit(cpu,block,code);
                    198:    mips64_set_pc(block,vaddr+4);
                    199:    insn_block_push_epilog(block);
                    200:    return cptr;
                    201: }
                    202: 
                    203: /* Add end of JIT block */
                    204: void insn_block_add_end(insn_block_t *b)
                    205: {
                    206:    mips64_set_pc(b,b->start_pc+(b->mips_trans_pos<<2));
                    207:    insn_block_push_epilog(b);
                    208: }
                    209: 
                    210: /* Create a instruction block */
                    211: insn_block_t *insn_block_create(cpu_mips_t *cpu,m_uint64_t vaddr)
                    212: {
                    213:    insn_block_t *block = NULL;
                    214: 
                    215:    if (!(block = malloc(sizeof(*block))))
                    216:       goto error;
                    217: 
                    218:    memset(block,0,sizeof(*block));
                    219:    block->start_pc = vaddr;
                    220:    block->jit_bufsize = MIPS_JIT_BUFSIZE;
                    221: 
                    222:    if (!(block->jit_buffer = malloc(block->jit_bufsize)))
                    223:       goto error;
                    224: 
                    225:    block->jit_ptr = block->jit_buffer;
                    226:    block->mips_code = cpu->mem_op_lookup(cpu,block->start_pc);
                    227: 
                    228:    if (!block->mips_code) {
                    229:       fprintf(stderr,"%% No memory map for code execution at 0x%llx\n",
                    230:               block->start_pc);
                    231:       goto error;
                    232:    }
                    233: 
                    234: #if DEBUG_BLOCK_TIMESTAMP
                    235:    block->tm_first_use = block->tm_last_use = jit_jiffies;
                    236: #endif
                    237:    return block;
                    238: 
                    239:  error:
                    240:    free(block);
                    241:    fprintf(stderr,"%% Unable to create instruction block for vaddr=0x%llx\n", 
                    242:            vaddr);
                    243:    return NULL;
                    244: }
                    245: 
                    246: /* Record a patch to apply in a compiled block */
                    247: int insn_block_record_patch(insn_block_t *block,u_char *jit_ptr,
                    248:                             m_uint64_t vaddr)
                    249: {
                    250:    struct insn_patch_table *ipt = block->patch_table;
                    251:    struct insn_patch *patch;
                    252: 
                    253:    /* pc must be 32-bit aligned */
                    254:    if (vaddr & 0x03) {
                    255:       fprintf(stderr,"Block 0x%8.8llx: trying to record an invalid PC "
                    256:               "(0x%8.8llx) - mips_trans_pos=%d.\n",
                    257:               block->start_pc,vaddr,block->mips_trans_pos);
                    258:       return(-1);
                    259:    }
                    260: 
                    261:    if (!ipt || (ipt->cur_patch >= INSN_PATCH_TABLE_SIZE))
                    262:    {
                    263:       /* full table or no table, create a new one */
                    264:       ipt = malloc(sizeof(*ipt));
                    265:       if (!ipt) {
                    266:          fprintf(stderr,"%% Unable to create patch table.\n");
                    267:          return(-1);
                    268:       }
                    269: 
                    270:       memset(ipt,0,sizeof(*ipt));
                    271:       ipt->next = block->patch_table;
                    272:       block->patch_table = ipt;
                    273:    }
                    274: 
                    275: #if DEBUG_BLOCK_PATCH
                    276:    printf("Block 0x%8.8llx: recording patch [JIT:%p->mips:0x%8.8llx], "
                    277:           "MTP=%d\n",block->start_pc,jit_ptr,vaddr,block->mips_trans_pos);
                    278: #endif
                    279: 
                    280:    patch = &ipt->patches[ipt->cur_patch];
                    281:    patch->jit_insn = jit_ptr;
                    282:    patch->mips_pc = vaddr;
                    283:    ipt->cur_patch++;   
                    284:    return(0);
                    285: }
                    286: 
                    287: /* Apply all patches */
                    288: int insn_block_apply_patches(cpu_mips_t *cpu,insn_block_t *block)
                    289: {
                    290:    struct insn_patch_table *ipt;
                    291:    struct insn_patch *patch;
                    292:    u_char *jit_dst;
                    293:    int i;
                    294: 
                    295:    for(ipt=block->patch_table;ipt;ipt=ipt->next)
                    296:       for(i=0;i<ipt->cur_patch;i++) 
                    297:       {
                    298:          patch = &ipt->patches[i];
                    299:          jit_dst = insn_block_get_jit_ptr(block,patch->mips_pc);
                    300: 
                    301:          if (!jit_dst) {
                    302: #if DEBUG_BLOCK_PATCH
                    303:             printf("Block 0x%8.8llx: trying to apply a null patch "
                    304:                    "(PC=0x%llx)\n",
                    305:                    block->start_pc,patch->mips_pc);
                    306: #endif
                    307:             jit_dst = insn_special_emit(cpu,block,patch->mips_pc);
                    308:          }
                    309: 
                    310:          insn_block_set_patch(patch->jit_insn,jit_dst);
                    311: 
                    312: #if DEBUG_BLOCK_PATCH
                    313:          printf("Block 0x%8.8llx: applying patch "
                    314:                 "[JIT:%p->mips:0x%8.8llx=JIT:%p]\n",
                    315:                 block->start_pc,patch->jit_insn,patch->mips_pc,jit_dst);
                    316: #endif
                    317:       }
                    318: 
                    319:    return(0);
                    320: }
                    321: 
                    322: /* Adjust the JIT buffer if its size is not sufficient */
                    323: int insn_block_adjust_jit_buffer(insn_block_t *block)
                    324: {
                    325:    u_char *new_ptr;
                    326: 
                    327:    if ((block->jit_ptr - block->jit_buffer) <= (block->jit_bufsize - 512))
                    328:       return(0);
                    329: 
                    330: #if DEBUG_BLOCK_CHUNK  
                    331:    printf("Block 0x%llx: adjusting JIT buffer...\n",block->start_pc);
                    332: #endif
                    333: 
                    334:    if (block->jit_chunk_pos >= INSN_MAX_CHUNKS) {
                    335:       fprintf(stderr,"Block 0x%llx: too many JIT chunks.\n",block->start_pc);
                    336:       return(-1);
                    337:    }
                    338: 
                    339:    /* save the current JIT block */
                    340:    block->jit_chunks[block->jit_chunk_pos++] = block->jit_buffer;
                    341: 
                    342:    if (!(new_ptr = malloc(block->jit_bufsize)))
                    343:       return(-1);
                    344: 
                    345:    /* jump to the new block */
                    346:    insn_block_set_jump(block->jit_ptr,new_ptr);
                    347:    block->jit_ptr = block->jit_buffer = new_ptr;
                    348:    return(0);
                    349: }
                    350: 
                    351: /* Scan an instruction block to determine its length */
                    352: int insn_block_scan(insn_block_t *block)
                    353: {
                    354:    struct insn_jump *jump;
                    355:    m_uint64_t cur_pc,last_jrra_pc;
                    356:    m_uint64_t next_pc,max_next_pc;
                    357:    m_int64_t offset;
                    358:    mips_insn_t code;
                    359:    size_t len;
                    360: 
                    361:    last_jrra_pc = max_next_pc = 0;
                    362: 
                    363:    for(block->mips_code_len = 0, cur_pc = block->start_pc;
                    364:        block->mips_code_len < MIPS_MAX_BLOCK_INSN;
                    365:        block->mips_code_len++, cur_pc += 4)
                    366:    {
                    367:       code = vmtoh32(block->mips_code[block->mips_code_len]);
                    368: 
                    369: #if DEBUG_BLOCK_SCAN
                    370:       printf("insn_block_scan: cur_pc = 0x%llx, instruction = 0x%8.8x\n",
                    371:              cur_pc,code);
                    372: #endif     
                    373:  
                    374:       /* jr ra = jump to return address */
                    375:       if (code == MIPS_INSN_JR_RA) {
                    376:          last_jrra_pc = cur_pc;
                    377: 
                    378:          if (last_jrra_pc >= max_next_pc) {
                    379:             block->mips_code_len++;  /* account delay slot */
                    380:             break;
                    381:          }
                    382: 
                    383:          continue;
                    384:       }
                    385: 
                    386:       /* check if we have a jump instruction */
                    387:       if (!(jump = insn_jump_find(code)))
                    388:          continue;
                    389: 
                    390: #if DEBUG_BLOCK_SCAN
                    391:       printf("insn_block_scan: jump \"%s\" detected (max_next_pc=0x%llx)\n",
                    392:              jump->name, max_next_pc);
                    393: #endif
                    394: 
                    395:       /* we have a jump, compute next pc */
                    396:       offset = (code & ((1 << jump->offset_bits) - 1)) << 2;
                    397: 
                    398:       if (jump->relative) {
                    399:          next_pc = cur_pc + 4 + sign_extend(offset,jump->offset_bits+2);
                    400:       } else {
                    401:          next_pc = (cur_pc & ~((1 << (jump->offset_bits + 2)) - 1)) | offset;
                    402:       }
                    403: 
                    404:       if (next_pc > max_next_pc)
                    405:          max_next_pc = next_pc;
                    406: 
                    407: #if DEBUG_BLOCK_SCAN
                    408:       printf("insn_block_scan: next_pc=0x%llx, max_next_pc=0x%llx\n",
                    409:              next_pc,max_next_pc);
                    410: #endif
                    411:    }
                    412: 
                    413:    block->mips_code_len++;
                    414:    block->end_pc = block->start_pc + (block->mips_code_len * 4);
                    415:    
                    416:    len = block->mips_code_len * sizeof(u_char *);
                    417: 
                    418:    if (!(block->jit_insn_ptr = malloc(len))) {
                    419:       fprintf(stderr,"insn_block_scan: unable to create JIT/mips mapping.\n");
                    420:       return(-1);
                    421:    }
                    422: 
                    423:    memset(block->jit_insn_ptr,0,len);
                    424: 
                    425: #if DEBUG_BLOCK_SCAN
                    426:    printf("insn_block_scan: start_pc = 0x%llx, end_pc = 0x%llx\n",
                    427:           block->start_pc, block->end_pc);
                    428: #endif
                    429: 
                    430:    return(0);
                    431: }
                    432: 
                    433: /* Compile a MIPS instruction block */
                    434: static inline int insn_block_compile(cpu_mips_t *cpu,insn_block_t *block)
                    435: {  
                    436:    struct insn_tag *tag;
                    437: 
                    438:    block->mips_trans_pos = 0;
                    439: 
                    440:    while(block->mips_trans_pos < block->mips_code_len)
                    441:    {
                    442:       if (!(tag = insn_fetch_and_emit(cpu,block,0)))
                    443:          return(-1);
                    444: 
                    445: #if DEBUG_BLOCK_COMPILE
                    446:       printf("Block 0x%8.8llx: emitted tag 0x%8.8x/0x%8.8x\n",
                    447:              block->start_pc,tag->mask,tag->value);
                    448: #endif
                    449: 
                    450:       insn_block_adjust_jit_buffer(block);
                    451:    }
                    452: 
                    453:    insn_block_add_end(block);
                    454:    insn_block_apply_patches(cpu,block);
                    455:    return(0);
                    456: }
                    457: 
                    458: /* Compile a MIPS instruction block */
                    459: static insn_block_t *insn_block_scan_and_compile(cpu_mips_t *cpu,
                    460:                                                  m_uint64_t vaddr)
                    461: {
                    462:    insn_block_t *block;
                    463: 
                    464:    if (!(block = insn_block_create(cpu,vaddr)))
                    465:       return NULL;
                    466: 
                    467:    if ((insn_block_scan(block) == -1) || (insn_block_compile(cpu,block) == -1))
                    468:       return NULL;
                    469: 
                    470:    rbtree_insert(cpu->insn_block_tree,block,block);
                    471:    return block;
                    472: }
                    473: 
                    474: /* Run a compiled MIPS instruction block */
                    475: static inline void insn_block_run(cpu_mips_t *cpu,insn_block_t *block)
                    476: {
                    477: #if DEBUG_SYM_TREE
                    478:    struct symbol *sym = NULL;
                    479:    int mark = FALSE;
                    480: #endif
                    481: 
                    482:    if (unlikely(cpu->pc & 0x03)) {
                    483:       fprintf(stderr,"insn_block_run: Invalid PC 0x%llx.\n",cpu->pc);
                    484:       mips64_dump_regs(cpu);
                    485:       tlb_dump(cpu);
                    486:       exit(EXIT_FAILURE);
                    487:    }
                    488: 
                    489: #if DEBUG_SYM_TREE
                    490:    if (sym_tree)
                    491:    {
                    492:       if ((sym = sym_lookup(cpu->pc)) != NULL) {
                    493:          fprintf(log_file,
                    494:                  "function_run: %s (PC=0x%llx) "
                    495:                  "RA = 0x%llx\na0=0x%llx, "
                    496:                  "a1=0x%llx, a2=0x%llx, a3=0x%llx\n",
                    497:                  sym->name, cpu->pc, cpu->gpr[MIPS_GPR_RA],
                    498:                  cpu->gpr[MIPS_GPR_A0], cpu->gpr[MIPS_GPR_A1],
                    499:                  cpu->gpr[MIPS_GPR_A2], cpu->gpr[MIPS_GPR_A3]);
                    500:          mark = TRUE;
                    501:       }
                    502:    }
                    503: #endif
                    504: 
                    505: #if DEBUG_INSN_ITRACE
                    506:    if (insn_itrace) {
                    507:       fprintf(log_file,
                    508:               "block_run(S): PC = 0x%llx [start_pc=0x%llx,end_pc=0x%llx] "
                    509:               "RA = 0x%llx\na0=0x%llx, a1=0x%llx, a2=0x%llx, a3=0x%llx\n",
                    510:               cpu->pc,block->start_pc,block->end_pc,
                    511:               cpu->gpr[MIPS_GPR_RA],
                    512:               cpu->gpr[MIPS_GPR_A0],
                    513:               cpu->gpr[MIPS_GPR_A1],
                    514:               cpu->gpr[MIPS_GPR_A2],
                    515:               cpu->gpr[MIPS_GPR_A3]);
                    516:    }
                    517: #endif
                    518: 
                    519:    /* Execute JIT compiled code */
                    520:    insn_block_exec_jit_code(cpu,block);
                    521: 
                    522: #if DEBUG_SYM_TREE
                    523:    if (mark) {
                    524:       fprintf(log_file,"function_end: %s, v0 = 0x%llx\n",
                    525:               sym->name,cpu->gpr[MIPS_GPR_V0]);
                    526:    }
                    527: #endif
                    528: 
                    529: #if DEBUG_INSN_ITRACE
                    530:    if (insn_itrace) {
                    531:       fprintf(log_file,"block_run(E): PC = 0x%llx, v0 = 0x%llx\n",
                    532:               cpu->pc, cpu->gpr[MIPS_GPR_V0]);
                    533:    }
                    534: #endif
                    535: }
                    536: 
                    537: /* Tree comparison function */
                    538: int insn_block_cmp(m_uint64_t *vaddr,insn_block_t *b)
                    539: {
                    540:    if (*vaddr < b->start_pc)
                    541:       return(-1);
                    542: 
                    543:    if (*vaddr >= b->end_pc)
                    544:       return(1);
                    545: 
                    546:    return(0);
                    547: }
                    548: 
                    549: /* Check if the specified address belongs to the specified block */
                    550: int insn_block_local_addr(insn_block_t *block,m_uint64_t vaddr,
                    551:                           u_char **jit_addr)
                    552: {
                    553:    if ((vaddr >= block->start_pc) && (vaddr < block->end_pc)) {
                    554:       *jit_addr = insn_block_get_jit_ptr(block,vaddr);
                    555:       return(1);
                    556:    }
                    557:    return(0);
                    558: }
                    559: 
                    560: /* Execute a compiled MIPS code */
                    561: void *insn_block_execute(cpu_mips_t *cpu)
                    562: {
                    563:    insn_block_t *block;
                    564: 
                    565:  start_cpu:
                    566:    for(;;) {
                    567:       if (unlikely(!cpu->pc) || unlikely(cpu->state != MIPS_CPU_RUNNING))
                    568:          break;
                    569: 
                    570:       block = insn_block_locate_fast(cpu,cpu->pc);
                    571: 
                    572:       if (!block) {
                    573:          block = insn_block_scan_and_compile(cpu,cpu->pc);
                    574:          if (unlikely(!block)) {
                    575:             cpu->pc = 0;
                    576:             break;
                    577:          }
                    578:       }
                    579: 
                    580: #if DEBUG_BLOCK_TIMESTAMP
                    581:       block->tm_last_use = jit_jiffies++;
                    582: #endif
                    583:       block->acc_count++;
                    584:       insn_block_run(cpu,block);
                    585:    }
                    586:    
                    587:    if (!cpu->pc) {
                    588:       cpu_stop(cpu);
                    589:       m_log("CPU","CPU%u has PC=0, halting CPU.\n",cpu->id);
                    590:    }
                    591: 
                    592:    /* check regularly if the CPU has been restarted */
                    593:    do {
                    594:       if (cpu->state == MIPS_CPU_RUNNING)
                    595:          goto start_cpu;
                    596:       
                    597:       usleep(200000);
                    598:    }while(1);
                    599: 
                    600:    return NULL;
                    601: }
                    602: 
                    603: /* Dump an instruction block */
                    604: void insn_block_dump_tree_node(insn_block_t *b,void *empty,m_tmcnt_t *ct)
                    605: {
                    606: #if DEBUG_BLOCK_TIMESTAMP
                    607:    m_uint64_t deltaT = jit_jiffies - b->tm_last_use;
                    608: 
                    609:    m_log("RBTREE","Block 0x%llx (end=0x%llx): count=%10llu, deltaT=%12llu\n",
                    610:          b->start_pc,b->end_pc,b->acc_count,deltaT);
                    611: #else
                    612:    m_log("RBTREE","Block 0x%llx (end=0x%llx): count=%llu\n",
                    613:          b->start_pc,b->end_pc,b->acc_count);
                    614: #endif
                    615: }
                    616: 
                    617: /* Dump the instruction block tree */
                    618: void insn_block_dump_tree(cpu_mips_t *cpu)
                    619: {
                    620:    m_log("RBTREE","Height: %d\n",rbtree_height(cpu->insn_block_tree));
                    621: 
                    622:    rbtree_foreach(cpu->insn_block_tree,
                    623:                   (tree_fforeach)insn_block_dump_tree_node,
                    624:                   NULL);
                    625: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.