--- upstream/dynamips-0.2.6-RC4/mips64_exec.c 2007/10/06 16:08:03 5 +++ upstream/dynamips-0.2.8-RC1/mips64_exec.c 2007/10/06 16:33:40 11 @@ -1,5 +1,5 @@ /* - * Cisco 7200 (Predator) simulation platform. + * Cisco router simulation platform. * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) * * MIPS64 Step-by-step execution. @@ -16,18 +16,15 @@ #include #include -#include "rbtree.h" -#include "mips64.h" -#include "dynamips.h" -#include "vm.h" -#include "memory.h" #include "cpu.h" -#include "cp0.h" +#include "vm.h" #include "mips64_exec.h" +#include "memory.h" #include "insn_lookup.h" +#include "dynamips.h" /* Forward declaration of instruction array */ -static struct insn_exec_tag mips64_exec_tags[]; +static struct mips64_insn_exec_tag mips64_exec_tags[]; static insn_lookup_t *ilt = NULL; /* ILT */ @@ -36,12 +33,12 @@ return(&mips64_exec_tags[index]); } -static int mips64_exec_chk_lo(struct insn_exec_tag *tag,int value) +static int mips64_exec_chk_lo(struct mips64_insn_exec_tag *tag,int value) { return((value & tag->mask) == (tag->value & 0xFFFF)); } -static int mips64_exec_chk_hi(struct insn_exec_tag *tag,int value) +static int mips64_exec_chk_hi(struct mips64_insn_exec_tag *tag,int value) { return((value & (tag->mask >> 16)) == (tag->value >> 16)); } @@ -54,7 +51,7 @@ for(i=0,count=0;mips64_exec_tags[i].exec;i++) count++; - ilt = ilt_create(count, + ilt = ilt_create("mips64e",count, (ilt_get_insn_cbk_t)mips64_exec_get_insn, (ilt_check_cbk_t)mips64_exec_chk_lo, (ilt_check_cbk_t)mips64_exec_chk_hi); @@ -84,7 +81,7 @@ { char insn_name[64],insn_format[32],*name; int base,rs,rd,rt,sa,offset,imm; - struct insn_exec_tag *tag; + struct mips64_insn_exec_tag *tag; m_uint64_t new_pc; int index; @@ -282,28 +279,28 @@ } /* Execute a memory operation */ -static forced_inline int mips64_exec_memop(cpu_mips_t *cpu,int memop, - m_uint64_t vaddr,u_int dst_reg, - int keep_ll_bit) +static forced_inline void mips64_exec_memop(cpu_mips_t *cpu,int memop, + m_uint64_t vaddr,u_int dst_reg, + int keep_ll_bit) { fastcall mips_memop_fn fn; if (!keep_ll_bit) cpu->ll_bit = 0; fn = cpu->mem_op_fn[memop]; - return(fn(cpu,vaddr,dst_reg)); + fn(cpu,vaddr,dst_reg); } /* Execute a memory operation (2) */ -static forced_inline int mips64_exec_memop2(cpu_mips_t *cpu,int memop, - m_uint64_t base,int offset, - u_int dst_reg,int keep_ll_bit) +static forced_inline void mips64_exec_memop2(cpu_mips_t *cpu,int memop, + m_uint64_t base,int offset, + u_int dst_reg,int keep_ll_bit) { m_uint64_t vaddr = cpu->gpr[base] + sign_extend(offset,16); fastcall mips_memop_fn fn; - + if (!keep_ll_bit) cpu->ll_bit = 0; fn = cpu->mem_op_fn[memop]; - return(fn(cpu,vaddr,dst_reg)); + fn(cpu,vaddr,dst_reg); } /* Fetch an instruction */ @@ -325,15 +322,23 @@ return(0); } +/* Unknown opcode */ +static fastcall int mips64_exec_unknown(cpu_mips_t *cpu,mips_insn_t insn) +{ + printf("MIPS64: unknown opcode 0x%8.8x at pc = 0x%llx\n",insn,cpu->pc); + mips64_dump_regs(cpu->gen); + return(0); +} + /* Execute a single instruction */ static forced_inline int mips64_exec_single_instruction(cpu_mips_t *cpu,mips_insn_t instruction) { register fastcall int (*exec)(cpu_mips_t *,mips_insn_t) = NULL; - struct insn_exec_tag *tag; + struct mips64_insn_exec_tag *tag; int index; -#if DEBUG_PERF_COUNTER +#if DEBUG_INSN_PERF_CNT cpu->perf_counter++; #endif @@ -345,31 +350,23 @@ tag = mips64_exec_get_insn(index); exec = tag->exec; - if (likely(exec != NULL)) { #if NJM_STATS_ENABLE - cpu->insn_exec_count++; - mips64_exec_tags[index].count++; + cpu->insn_exec_count++; + mips64_exec_tags[index].count++; #endif #if 0 { char buffer[80]; if (mips64_dump_insn(buffer,sizeof(buffer),0,cpu->pc,instruction)!=-1) - fprintf(log_file,"0x%llx: %s\n",cpu->pc,buffer); + cpu_log(cpu->gen,"EXEC","0x%llx: %s\n",cpu->pc,buffer); } #endif - - return(exec(cpu,instruction)); - } - - printf("MIPS64: unknown opcode 0x%8.8x at pc = 0x%llx\n", - instruction,cpu->pc); - mips64_dump_regs(cpu); - return(0); + return(exec(cpu,instruction)); } /* Single-step execution */ -void mips64_exec_single_step(cpu_mips_t *cpu,mips_insn_t instruction) +fastcall void mips64_exec_single_step(cpu_mips_t *cpu,mips_insn_t instruction) { int res; @@ -380,36 +377,38 @@ } /* Run MIPS code in step-by-step mode */ -void *mips64_exec_run_cpu(cpu_mips_t *cpu) +void *mips64_exec_run_cpu(cpu_gen_t *gen) { + cpu_mips_t *cpu = CPU_MIPS64(gen); pthread_t timer_irq_thread; - mips_insn_t insn; int timer_irq_check = 0; + mips_insn_t insn; int res; if (pthread_create(&timer_irq_thread,NULL, (void *)mips64_timer_irq_run,cpu)) { fprintf(stderr,"VM '%s': unable to create Timer IRQ thread for CPU%u.\n", - cpu->vm->name,cpu->id); - cpu_stop(cpu); + cpu->vm->name,gen->id); + cpu_stop(gen); return NULL; } - cpu->cpu_thread_running = TRUE; + gen->cpu_thread_running = TRUE; + cpu_exec_loop_set(gen); start_cpu: - cpu->idle_count = 0; + gen->idle_count = 0; for(;;) { - if (unlikely(cpu->state != MIPS_CPU_RUNNING)) + if (unlikely(gen->state != CPU_STATE_RUNNING)) break; /* Handle virtual idle loop */ if (unlikely(cpu->pc == cpu->idle_pc)) { - if (++cpu->idle_count == cpu->idle_max) { - mips64_idle_loop(cpu); - cpu->idle_count = 0; + if (++gen->idle_count == gen->idle_max) { + cpu_idle_loop(gen); + gen->idle_count = 0; } } @@ -438,25 +437,25 @@ res = mips64_exec_single_instruction(cpu,insn); /* Normal flow ? */ - if (likely(!res)) cpu->pc += 4; + if (likely(!res)) cpu->pc += sizeof(mips_insn_t); } if (!cpu->pc) { - cpu_stop(cpu); - cpu_log(cpu,"SLOW_EXEC","PC=0, halting CPU.\n"); + cpu_stop(gen); + cpu_log(gen,"SLOW_EXEC","PC=0, halting CPU.\n"); } /* Check regularly if the CPU has been restarted */ - while(cpu->cpu_thread_running) { - cpu->seq_state++; + while(gen->cpu_thread_running) { + gen->seq_state++; - switch(cpu->state) { - case MIPS_CPU_RUNNING: - cpu->state = MIPS_CPU_RUNNING; + switch(gen->state) { + case CPU_STATE_RUNNING: + gen->state = CPU_STATE_RUNNING; goto start_cpu; - case MIPS_CPU_HALTED: - cpu->cpu_thread_running = FALSE; + case CPU_STATE_HALTED: + gen->cpu_thread_running = FALSE; pthread_join(timer_irq_thread,NULL); break; } @@ -1077,7 +1076,8 @@ int op = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_CACHE,base,offset,op,FALSE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_CACHE,base,offset,op,FALSE); + return(0); } /* CFC0 */ @@ -1086,7 +1086,7 @@ int rt = bits(insn,16,20); int rd = bits(insn,11,15); - cp0_exec_cfc0(cpu,rt,rd); + mips64_cp0_exec_cfc0(cpu,rt,rd); return(0); } @@ -1096,7 +1096,7 @@ int rt = bits(insn,16,20); int rd = bits(insn,11,15); - cp0_exec_ctc0(cpu,rt,rd); + mips64_cp0_exec_ctc0(cpu,rt,rd); return(0); } @@ -1160,7 +1160,7 @@ int rt = bits(insn,16,20); int rd = bits(insn,11,15); - cp0_exec_dmfc0(cpu,rt,rd); + mips64_cp0_exec_dmfc0(cpu,rt,rd); return(0); } @@ -1180,7 +1180,7 @@ int rt = bits(insn,16,20); int rd = bits(insn,11,15); - cp0_exec_dmtc0(cpu,rt,rd); + mips64_cp0_exec_dmtc0(cpu,rt,rd); return(0); } @@ -1395,7 +1395,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_LB,base,offset,rt,TRUE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_LB,base,offset,rt,TRUE); + return(0); } /* LBU (Load Byte Unsigned) */ @@ -1405,7 +1406,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_LBU,base,offset,rt,TRUE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_LBU,base,offset,rt,TRUE); + return(0); } /* LD (Load Double-Word) */ @@ -1415,7 +1417,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_LD,base,offset,rt,TRUE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_LD,base,offset,rt,TRUE); + return(0); } /* LDC1 (Load Double-Word to Coprocessor 1) */ @@ -1425,7 +1428,8 @@ int ft = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_LDC1,base,offset,ft,TRUE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_LDC1,base,offset,ft,TRUE); + return(0); } /* LDL (Load Double-Word Left) */ @@ -1435,7 +1439,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_LDL,base,offset,rt,TRUE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_LDL,base,offset,rt,TRUE); + return(0); } /* LDR (Load Double-Word Right) */ @@ -1445,7 +1450,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_LDR,base,offset,rt,TRUE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_LDR,base,offset,rt,TRUE); + return(0); } /* LH (Load Half-Word) */ @@ -1455,7 +1461,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_LH,base,offset,rt,TRUE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_LH,base,offset,rt,TRUE); + return(0); } /* LHU (Load Half-Word Unsigned) */ @@ -1465,7 +1472,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_LHU,base,offset,rt,TRUE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_LHU,base,offset,rt,TRUE); + return(0); } /* LI (virtual) */ @@ -1485,7 +1493,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_LL,base,offset,rt,TRUE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_LL,base,offset,rt,TRUE); + return(0); } /* LUI */ @@ -1505,7 +1514,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_LW,base,offset,rt,TRUE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_LW,base,offset,rt,TRUE); + return(0); } /* LWL (Load Word Left) */ @@ -1515,7 +1525,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_LWL,base,offset,rt,TRUE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_LWL,base,offset,rt,TRUE); + return(0); } /* LWR (Load Word Right) */ @@ -1525,7 +1536,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_LWR,base,offset,rt,TRUE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_LWR,base,offset,rt,TRUE); + return(0); } /* LWU (Load Word Unsigned) */ @@ -1535,7 +1547,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_LWU,base,offset,rt,TRUE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_LWU,base,offset,rt,TRUE); + return(0); } /* MFC0 */ @@ -1544,7 +1557,7 @@ int rt = bits(insn,16,20); int rd = bits(insn,11,15); - cp0_exec_mfc0(cpu,rt,rd); + mips64_cp0_exec_mfc0(cpu,rt,rd); return(0); } @@ -1592,7 +1605,7 @@ int rt = bits(insn,16,20); int rd = bits(insn,11,15); - cp0_exec_mtc0(cpu,rt,rd); + mips64_cp0_exec_mtc0(cpu,rt,rd); return(0); } @@ -1725,7 +1738,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_SB,base,offset,rt,FALSE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_SB,base,offset,rt,FALSE); + return(0); } /* SC (Store Conditional) */ @@ -1735,7 +1749,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_SC,base,offset,rt,TRUE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_SC,base,offset,rt,TRUE); + return(0); } /* SD (Store Double-Word) */ @@ -1745,7 +1760,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_SD,base,offset,rt,FALSE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_SD,base,offset,rt,FALSE); + return(0); } /* SDL (Store Double-Word Left) */ @@ -1755,7 +1771,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_SDL,base,offset,rt,FALSE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_SDL,base,offset,rt,FALSE); + return(0); } /* SDR (Store Double-Word Right) */ @@ -1765,7 +1782,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_SDR,base,offset,rt,FALSE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_SDR,base,offset,rt,FALSE); + return(0); } /* SDC1 (Store Double-Word from Coprocessor 1) */ @@ -1775,7 +1793,8 @@ int ft = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_SDC1,base,offset,ft,FALSE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_SDC1,base,offset,ft,FALSE); + return(0); } /* SH (Store Half-Word) */ @@ -1785,7 +1804,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_SH,base,offset,rt,FALSE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_SH,base,offset,rt,FALSE); + return(0); } /* SLL */ @@ -1962,7 +1982,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_SW,base,offset,rt,FALSE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_SW,base,offset,rt,FALSE); + return(0); } /* SWL (Store Word Left) */ @@ -1972,7 +1993,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_SWL,base,offset,rt,FALSE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_SWL,base,offset,rt,FALSE); + return(0); } /* SWR (Store Word Right) */ @@ -1982,7 +2004,8 @@ int rt = bits(insn,16,20); int offset = bits(insn,0,15); - return(mips64_exec_memop2(cpu,MIPS_MEMOP_SWR,base,offset,rt,FALSE)); + mips64_exec_memop2(cpu,MIPS_MEMOP_SWR,base,offset,rt,FALSE); + return(0); } /* SYNC */ @@ -2030,28 +2053,28 @@ /* TLBP */ static fastcall int mips64_exec_TLBP(cpu_mips_t *cpu,mips_insn_t insn) { - cp0_exec_tlbp(cpu); + mips64_cp0_exec_tlbp(cpu); return(0); } /* TLBR */ static fastcall int mips64_exec_TLBR(cpu_mips_t *cpu,mips_insn_t insn) { - cp0_exec_tlbr(cpu); + mips64_cp0_exec_tlbr(cpu); return(0); } /* TLBWI */ static fastcall int mips64_exec_TLBWI(cpu_mips_t *cpu,mips_insn_t insn) { - cp0_exec_tlbwi(cpu); + mips64_cp0_exec_tlbwi(cpu); return(0); } /* TLBWR */ static fastcall int mips64_exec_TLBWR(cpu_mips_t *cpu,mips_insn_t insn) { - cp0_exec_tlbwr(cpu); + mips64_cp0_exec_tlbwr(cpu); return(0); } @@ -2078,7 +2101,7 @@ } /* MIPS instruction array */ -static struct insn_exec_tag mips64_exec_tags[] = { +static struct mips64_insn_exec_tag mips64_exec_tags[] = { { "li" , mips64_exec_LI , 0xffe00000 , 0x24000000, 1, 16 }, { "move" , mips64_exec_MOVE , 0xfc1f07ff , 0x00000021, 1, 15 }, { "b" , mips64_exec_B , 0xffff0000 , 0x10000000, 0, 10 }, @@ -2198,6 +2221,7 @@ { "tlbwr" , mips64_exec_TLBWR , 0xffffffff , 0x42000006, 1, 1 }, { "xor" , mips64_exec_XOR , 0xfc0007ff , 0x00000026, 1, 3 }, { "xori" , mips64_exec_XORI , 0xfc000000 , 0x38000000, 1, 5 }, + { "unknown", mips64_exec_unknown , 0x00000000 , 0x00000000, 1, 0 }, { NULL , NULL , 0x00000000 , 0x00000000, 1, 0 }, };