Annotation of cf/mips64_jit.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

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