📄 translate.c
字号:
break; case 0x18 ... 0x1B: /* MULT / DIV */ gen_muldiv(ctx, op1 | EXT_SPECIAL, rs, rt); break; case 0x08 ... 0x09: /* Jumps */ gen_compute_branch(ctx, op1 | EXT_SPECIAL, rs, rd, sa); return; case 0x30 ... 0x34: /* Traps */ case 0x36: gen_trap(ctx, op1 | EXT_SPECIAL, rs, rt, -1); break; case 0x10: /* Move from HI/LO */ case 0x12: gen_HILO(ctx, op1 | EXT_SPECIAL, rd); break; case 0x11: case 0x13: /* Move to HI/LO */ gen_HILO(ctx, op1 | EXT_SPECIAL, rs); break; case 0x0C: /* SYSCALL */ generate_exception(ctx, EXCP_SYSCALL); break; case 0x0D: /* BREAK */ generate_exception(ctx, EXCP_BREAK); break; case 0x0F: /* SYNC */ /* Treat as a noop */ break; case 0x05: /* Pmon entry point */ gen_op_pmon((ctx->opcode >> 6) & 0x1F); break; case 0x01: /* MOVCI */#if defined (MIPS_HAS_MOVCI) /* XXX */#else /* Not implemented */ generate_exception_err (ctx, EXCP_CpU, 1);#endif break;#if defined (TARGET_MIPS64) case 0x14: /* MIPS64 specific opcodes */ case 0x16: case 0x17: case 0x1C ... 0x1F: case 0x2C ... 0x2F: case 0x37: case 0x39 ... 0x3B: case 0x3E ... 0x3F:#endif default: /* Invalid */ MIPS_INVAL("special"); generate_exception(ctx, EXCP_RI); break; } break; case 0x1C: /* Special2 opcode */ op1 = ctx->opcode & 0x3F; switch (op1) {#if defined (MIPS_USES_R4K_EXT) /* Those instructions are not part of MIPS32 core */ case 0x00 ... 0x01: /* Multiply and add/sub */ case 0x04 ... 0x05: gen_muldiv(ctx, op1 | EXT_SPECIAL2, rs, rt); break; case 0x02: /* MUL */ gen_arith(ctx, op1 | EXT_SPECIAL2, rd, rs, rt); break; case 0x20 ... 0x21: /* CLO / CLZ */ gen_cl(ctx, op1 | EXT_SPECIAL2, rd, rs); break;#endif case 0x3F: /* SDBBP */ /* XXX: not clear which exception should be raised * when in debug mode... */ if (!(ctx->hflags & MIPS_HFLAG_DM)) { generate_exception(ctx, EXCP_DBp); } else { generate_exception(ctx, EXCP_DBp); } /* Treat as a noop */ break; default: /* Invalid */ MIPS_INVAL("special2"); generate_exception(ctx, EXCP_RI); break; } break; case 0x01: /* B REGIMM opcode */ op1 = ((ctx->opcode >> 16) & 0x1F); switch (op1) { case 0x00 ... 0x03: /* REGIMM branches */ case 0x10 ... 0x13: gen_compute_branch(ctx, op1 | EXT_REGIMM, rs, -1, imm << 2); return; case 0x08 ... 0x0C: /* Traps */ case 0x0E: gen_trap(ctx, op1 | EXT_REGIMM, rs, -1, imm); break; default: /* Invalid */ MIPS_INVAL("REGIMM"); generate_exception(ctx, EXCP_RI); break; } break; case 0x10: /* CP0 opcode */ op1 = ((ctx->opcode >> 21) & 0x1F); switch (op1) { case 0x00: case 0x04: gen_cp0(ctx, op1 | EXT_CP0, rt, rd); break; default: gen_cp0(ctx, (ctx->opcode & 0x3F) | EXT_CP0, rt, rd); break; } break; case 0x08 ... 0x0F: /* Arithmetic with immediate opcode */ gen_arith_imm(ctx, op, rt, rs, imm); break; case 0x02 ... 0x03: /* Jump */ offset = (int32_t)(ctx->opcode & 0x03FFFFFF) << 2; gen_compute_branch(ctx, op, rs, rt, offset); return; case 0x04 ... 0x07: /* Branch */ case 0x14 ... 0x17: gen_compute_branch(ctx, op, rs, rt, imm << 2); return; case 0x20 ... 0x26: /* Load and stores */ case 0x28 ... 0x2E: case 0x30: case 0x38: gen_ldst(ctx, op, rt, rs, imm); break; case 0x2F: /* Cache operation */ /* Treat as a noop */ break; case 0x33: /* Prefetch */ /* Treat as a noop */ break; case 0x3F: /* HACK */ break; /* Floating point. */ case 0x31: /* LWC1 */ case 0x35: /* LDC1 */ case 0x39: /* SWC1 */ case 0x3D: /* SDC1 */ case 0x11: /* CP1 opcode */#if defined(MIPS_USES_FPU) /* XXX: not correct */#else generate_exception_err(ctx, EXCP_CpU, 1);#endif break; /* COP2. */ case 0x32: /* LWC2 */ case 0x36: /* LDC2 */ case 0x3A: /* SWC2 */ case 0x3E: /* SDC2 */ case 0x12: /* CP2 opcode */ /* Not implemented */ generate_exception_err(ctx, EXCP_CpU, 2); break; case 0x13: /* CP3 opcode */ /* Not implemented */ generate_exception_err(ctx, EXCP_CpU, 3); break;#if defined (TARGET_MIPS64) case 0x18 ... 0x1B: case 0x27: case 0x34: case 0x37: /* MIPS64 opcodes */#endif#if defined (MIPS_HAS_JALX) case 0x1D: /* JALX: not implemented */#endif case 0x1E: /* ASE specific */ default: /* Invalid */ MIPS_INVAL(""); generate_exception(ctx, EXCP_RI); break; } if (ctx->hflags & MIPS_HFLAG_BMASK) { int hflags = ctx->hflags; /* Branches completion */ ctx->hflags &= ~MIPS_HFLAG_BMASK; ctx->bstate = BS_BRANCH; save_cpu_state(ctx, 0); switch (hflags & MIPS_HFLAG_BMASK) { case MIPS_HFLAG_B: /* unconditional branch */ MIPS_DEBUG("unconditional branch"); gen_goto_tb(ctx, 0, ctx->btarget); break; case MIPS_HFLAG_BL: /* blikely taken case */ MIPS_DEBUG("blikely branch taken"); gen_goto_tb(ctx, 0, ctx->btarget); break; case MIPS_HFLAG_BC: /* Conditional branch */ MIPS_DEBUG("conditional branch"); { int l1; l1 = gen_new_label(); gen_op_jnz_T2(l1); gen_goto_tb(ctx, 1, ctx->pc + 4); gen_set_label(l1); gen_goto_tb(ctx, 0, ctx->btarget); } break; case MIPS_HFLAG_BR: /* unconditional branch to register */ MIPS_DEBUG("branch to register"); gen_op_breg(); break; default: MIPS_DEBUG("unknown branch"); break; } }}int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, int search_pc){ DisasContext ctx, *ctxp = &ctx; target_ulong pc_start; uint16_t *gen_opc_end; int j, lj = -1; if (search_pc && loglevel) fprintf (logfile, "search pc %d\n", search_pc); pc_start = tb->pc; gen_opc_ptr = gen_opc_buf; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; gen_opparam_ptr = gen_opparam_buf; nb_gen_labels = 0; ctx.pc = pc_start; ctx.saved_pc = -1; ctx.tb = tb; ctx.bstate = BS_NONE; /* Restore delay slot state from the tb context. */ ctx.hflags = tb->flags; ctx.saved_hflags = ctx.hflags; if (ctx.hflags & MIPS_HFLAG_BR) { gen_op_restore_breg_target(); } else if (ctx.hflags & MIPS_HFLAG_B) { ctx.btarget = env->btarget; } else if (ctx.hflags & MIPS_HFLAG_BMASK) { /* If we are in the delay slot of a conditional branch, * restore the branch condition from env->bcond to T2 */ ctx.btarget = env->btarget; gen_op_restore_bcond(); }#if defined(CONFIG_USER_ONLY) ctx.mem_idx = 0;#else ctx.mem_idx = (ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM ? 0 : 1;#endif ctx.CP0_Status = env->CP0_Status;#ifdef DEBUG_DISAS if (loglevel & CPU_LOG_TB_CPU) { fprintf(logfile, "------------------------------------------------\n"); /* FIXME: This may print out stale hflags from env... */ cpu_dump_state(env, logfile, fprintf, 0); }#endif#if defined MIPS_DEBUG_DISAS if (loglevel & CPU_LOG_TB_IN_ASM) fprintf(logfile, "\ntb %p super %d cond %04x\n", tb, ctx.mem_idx, ctx.hflags);#endif while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) { if (env->nb_breakpoints > 0) { for(j = 0; j < env->nb_breakpoints; j++) { if (env->breakpoints[j] == ctx.pc) { save_cpu_state(ctxp, 1); ctx.bstate = BS_BRANCH; gen_op_debug(); goto done_generating; } } } if (search_pc) { j = gen_opc_ptr - gen_opc_buf; if (lj < j) { lj++; while (lj < j) gen_opc_instr_start[lj++] = 0; } gen_opc_pc[lj] = ctx.pc; gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK; gen_opc_instr_start[lj] = 1; } ctx.opcode = ldl_code(ctx.pc); decode_opc(&ctx); ctx.pc += 4; if (env->singlestep_enabled) break; if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) break;#if defined (MIPS_SINGLE_STEP) break;#endif } if (env->singlestep_enabled) { save_cpu_state(ctxp, ctx.bstate == BS_NONE); gen_op_debug(); goto done_generating; } else if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) { save_cpu_state(ctxp, 0); gen_goto_tb(&ctx, 0, ctx.pc); } gen_op_reset_T0(); /* Generate the return instruction */ gen_op_exit_tb();done_generating: *gen_opc_ptr = INDEX_op_end; if (search_pc) { j = gen_opc_ptr - gen_opc_buf; lj++; while (lj <= j) gen_opc_instr_start[lj++] = 0; tb->size = 0; } else { tb->size = ctx.pc - pc_start; }#ifdef DEBUG_DISAS#if defined MIPS_DEBUG_DISAS if (loglevel & CPU_LOG_TB_IN_ASM) fprintf(logfile, "\n");#endif if (loglevel & CPU_LOG_TB_IN_ASM) { fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); target_disas(logfile, pc_start, ctx.pc - pc_start, 0); fprintf(logfile, "\n"); } if (loglevel & CPU_LOG_TB_OP) { fprintf(logfile, "OP:\n"); dump_ops(gen_opc_buf, gen_opparam_buf); fprintf(logfile, "\n"); } if (loglevel & CPU_LOG_TB_CPU) { fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags); }#endif return 0;}int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb){ return gen_intermediate_code_internal(env, tb, 0);}int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb){ return gen_intermediate_code_internal(env, tb, 1);}void cpu_dump_state (CPUState *env, FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...), int flags){ uint32_t c0_status; int i; cpu_fprintf(f, "pc=0x%08x HI=0x%08x LO=0x%08x ds %04x %08x %d\n", env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond); for (i = 0; i < 32; i++) { if ((i & 3) == 0) cpu_fprintf(f, "GPR%02d:", i); cpu_fprintf(f, " %s %08x", regnames[i], env->gpr[i]); if ((i & 3) == 3) cpu_fprintf(f, "\n"); } c0_status = env->CP0_Status; if (env->hflags & MIPS_HFLAG_UM) c0_status |= (1 << CP0St_UM); if (env->hflags & MIPS_HFLAG_ERL) c0_status |= (1 << CP0St_ERL); if (env->hflags & MIPS_HFLAG_EXL) c0_status |= (1 << CP0St_EXL); cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x%08x\n", c0_status, env->CP0_Cause, env->CP0_EPC); cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%08x\n", env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);}CPUMIPSState *cpu_mips_init (void){ CPUMIPSState *env; env = qemu_mallocz(sizeof(CPUMIPSState)); if (!env) return NULL; cpu_exec_init(env); tlb_flush(env, 1); /* Minimal init */ env->PC = 0xBFC00000;#if defined (MIPS_USES_R4K_TLB) env->CP0_random = MIPS_TLB_NB - 1;#endif env->CP0_Wired = 0; env->CP0_Config0 = MIPS_CONFIG0;#if defined (MIPS_CONFIG1) env->CP0_Config1 = MIPS_CONFIG1;#endif#if defined (MIPS_CONFIG2) env->CP0_Config2 = MIPS_CONFIG2;#endif#if defined (MIPS_CONFIG3) env->CP0_Config3 = MIPS_CONFIG3;#endif env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV); env->CP0_WatchLo = 0; env->hflags = MIPS_HFLAG_ERL; /* Count register increments in debug mode, EJTAG version 1 */ env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER); env->CP0_PRid = MIPS_CPU; env->exception_index = EXCP_NONE;#if defined(CONFIG_USER_ONLY) env->hflags |= MIPS_HFLAG_UM;#endif return env;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -