Annotation of cf/mips64_jit.c, revision 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.