📄 translate.c
字号:
gen_op_cmp_ ## fmt ## _ngt, \}; \static inline void gen_cmp_ ## fmt(int n) \{ \ cond_ ## fmt ## _table[n](); \}FOP_CONDS(d)FOP_CONDS(s)#endif /* MIPS_USES_FPU */typedef struct DisasContext { struct TranslationBlock *tb; target_ulong pc, saved_pc; uint32_t opcode; /* Routine used to access memory */ int mem_idx; uint32_t hflags, saved_hflags; uint32_t CP0_Status; int bstate; target_ulong btarget;} DisasContext;enum { BS_NONE = 0, /* We go out of the TB without reaching a branch or an * exception condition */ BS_STOP = 1, /* We want to stop translation for any reason */ BS_BRANCH = 2, /* We reached a branch condition */ BS_EXCP = 3, /* We reached an exception condition */};#if defined MIPS_DEBUG_DISAS#define MIPS_DEBUG(fmt, args...) \do { \ if (loglevel & CPU_LOG_TB_IN_ASM) { \ fprintf(logfile, TLSZ ": %08x " fmt "\n", \ ctx->pc, ctx->opcode , ##args); \ } \} while (0)#else#define MIPS_DEBUG(fmt, args...) do { } while(0)#endif#define MIPS_INVAL(op) \do { \ MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \ ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \} while (0)#define GEN_LOAD_REG_TN(Tn, Rn) \do { \ if (Rn == 0) { \ glue(gen_op_reset_, Tn)(); \ } else { \ glue(gen_op_load_gpr_, Tn)(Rn); \ } \} while (0)#define GEN_LOAD_IMM_TN(Tn, Imm) \do { \ if (Imm == 0) { \ glue(gen_op_reset_, Tn)(); \ } else { \ glue(gen_op_set_, Tn)(Imm); \ } \} while (0)#define GEN_STORE_TN_REG(Rn, Tn) \do { \ if (Rn != 0) { \ glue(glue(gen_op_store_, Tn),_gpr)(Rn); \ } \} while (0)#define GEN_LOAD_FREG_FTN(FTn, Fn) \do { \ glue(gen_op_load_fpr_, FTn)(Fn); \} while (0)#define GEN_STORE_FTN_FREG(Fn, FTn) \do { \ glue(gen_op_store_fpr_, FTn)(Fn); \} while (0)static inline void save_cpu_state (DisasContext *ctx, int do_save_pc){#if defined MIPS_DEBUG_DISAS if (loglevel & CPU_LOG_TB_IN_ASM) { fprintf(logfile, "hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags); }#endif if (do_save_pc && ctx->pc != ctx->saved_pc) { gen_op_save_pc(ctx->pc); ctx->saved_pc = ctx->pc; } if (ctx->hflags != ctx->saved_hflags) { gen_op_save_state(ctx->hflags); ctx->saved_hflags = ctx->hflags; if (ctx->hflags & MIPS_HFLAG_BR) { gen_op_save_breg_target(); } else if (ctx->hflags & MIPS_HFLAG_B) { gen_op_save_btarget(ctx->btarget); } else if (ctx->hflags & MIPS_HFLAG_BMASK) { gen_op_save_bcond(); gen_op_save_btarget(ctx->btarget); } }}static inline void generate_exception_err (DisasContext *ctx, int excp, int err){#if defined MIPS_DEBUG_DISAS if (loglevel & CPU_LOG_TB_IN_ASM) fprintf(logfile, "%s: raise exception %d\n", __func__, excp);#endif save_cpu_state(ctx, 1); if (err == 0) gen_op_raise_exception(excp); else gen_op_raise_exception_err(excp, err); ctx->bstate = BS_EXCP;}static inline void generate_exception (DisasContext *ctx, int excp){ generate_exception_err (ctx, excp, 0);}#if defined(CONFIG_USER_ONLY)#define op_ldst(name) gen_op_##name##_raw()#define OP_LD_TABLE(width)#define OP_ST_TABLE(width)#else#define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()#define OP_LD_TABLE(width) \static GenOpFunc *gen_op_l##width[] = { \ &gen_op_l##width##_user, \ &gen_op_l##width##_kernel, \}#define OP_ST_TABLE(width) \static GenOpFunc *gen_op_s##width[] = { \ &gen_op_s##width##_user, \ &gen_op_s##width##_kernel, \}#endif#ifdef MIPS_HAS_MIPS64OP_LD_TABLE(d);OP_LD_TABLE(dl);OP_LD_TABLE(dr);OP_ST_TABLE(d);OP_ST_TABLE(dl);OP_ST_TABLE(dr);OP_LD_TABLE(ld);OP_ST_TABLE(cd);#endifOP_LD_TABLE(w);OP_LD_TABLE(wu);OP_LD_TABLE(wl);OP_LD_TABLE(wr);OP_ST_TABLE(w);OP_ST_TABLE(wl);OP_ST_TABLE(wr);OP_LD_TABLE(h);OP_LD_TABLE(hu);OP_ST_TABLE(h);OP_LD_TABLE(b);OP_LD_TABLE(bu);OP_ST_TABLE(b);OP_LD_TABLE(l);OP_ST_TABLE(c);#ifdef MIPS_USES_FPUOP_LD_TABLE(wc1);OP_ST_TABLE(wc1);OP_LD_TABLE(dc1);OP_ST_TABLE(dc1);#endif/* Load and store */static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, int base, int16_t offset){ const char *opn = "unk"; if (base == 0) { GEN_LOAD_IMM_TN(T0, offset); } else if (offset == 0) { gen_op_load_gpr_T0(base); } else { gen_op_load_gpr_T0(base); gen_op_set_T1(offset); gen_op_add(); } /* Don't do NOP if destination is zero: we must perform the actual * memory access */ switch (opc) {#ifdef MIPS_HAS_MIPS64 case OPC_LD: op_ldst(ld); GEN_STORE_TN_REG(rt, T0); opn = "ld"; break; case OPC_LLD: op_ldst(lld); GEN_STORE_TN_REG(rt, T0); opn = "lld"; break; case OPC_SD: GEN_LOAD_REG_TN(T1, rt); op_ldst(sd); opn = "sd"; break; case OPC_SCD: GEN_LOAD_REG_TN(T1, rt); op_ldst(scd); opn = "scd"; break; case OPC_LDL: op_ldst(ldl); GEN_STORE_TN_REG(rt, T0); opn = "ldl"; break; case OPC_SDL: GEN_LOAD_REG_TN(T1, rt); op_ldst(sdl); opn = "sdl"; break; case OPC_LDR: op_ldst(ldr); GEN_STORE_TN_REG(rt, T0); opn = "ldr"; break; case OPC_SDR: GEN_LOAD_REG_TN(T1, rt); op_ldst(sdr); opn = "sdr"; break;#endif case OPC_LW: op_ldst(lw); GEN_STORE_TN_REG(rt, T0); opn = "lw"; break; case OPC_LWU: op_ldst(lwu); GEN_STORE_TN_REG(rt, T0); opn = "lwu"; break; case OPC_SW: GEN_LOAD_REG_TN(T1, rt); op_ldst(sw); opn = "sw"; break; case OPC_LH: op_ldst(lh); GEN_STORE_TN_REG(rt, T0); opn = "lh"; break; case OPC_SH: GEN_LOAD_REG_TN(T1, rt); op_ldst(sh); opn = "sh"; break; case OPC_LHU: op_ldst(lhu); GEN_STORE_TN_REG(rt, T0); opn = "lhu"; break; case OPC_LB: op_ldst(lb); GEN_STORE_TN_REG(rt, T0); opn = "lb"; break; case OPC_SB: GEN_LOAD_REG_TN(T1, rt); op_ldst(sb); opn = "sb"; break; case OPC_LBU: op_ldst(lbu); GEN_STORE_TN_REG(rt, T0); opn = "lbu"; break; case OPC_LWL: GEN_LOAD_REG_TN(T1, rt); op_ldst(lwl); GEN_STORE_TN_REG(rt, T0); opn = "lwl"; break; case OPC_SWL: GEN_LOAD_REG_TN(T1, rt); op_ldst(swl); opn = "swr"; break; case OPC_LWR: GEN_LOAD_REG_TN(T1, rt); op_ldst(lwr); GEN_STORE_TN_REG(rt, T0); opn = "lwr"; break; case OPC_SWR: GEN_LOAD_REG_TN(T1, rt); op_ldst(swr); opn = "swr"; break; case OPC_LL: op_ldst(ll); GEN_STORE_TN_REG(rt, T0); opn = "ll"; break; case OPC_SC: GEN_LOAD_REG_TN(T1, rt); op_ldst(sc); GEN_STORE_TN_REG(rt, T0); opn = "sc"; break; default: MIPS_INVAL("load/store"); generate_exception(ctx, EXCP_RI); return; } MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);}#ifdef MIPS_USES_FPU/* Load and store */static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, int base, int16_t offset){ const char *opn = "unk"; if (base == 0) { GEN_LOAD_IMM_TN(T0, offset); } else if (offset == 0) { gen_op_load_gpr_T0(base); } else { gen_op_load_gpr_T0(base); gen_op_set_T1(offset); gen_op_add(); } /* Don't do NOP if destination is zero: we must perform the actual * memory access */ switch (opc) { case OPC_LWC1: op_ldst(lwc1); GEN_STORE_FTN_FREG(ft, WT0); opn = "lwc1"; break; case OPC_SWC1: GEN_LOAD_FREG_FTN(WT0, ft); op_ldst(swc1); opn = "swc1"; break; case OPC_LDC1: op_ldst(ldc1); GEN_STORE_FTN_FREG(ft, DT0); opn = "ldc1"; break; case OPC_SDC1: GEN_LOAD_FREG_FTN(DT0, ft); op_ldst(sdc1); opn = "sdc1"; break; default: MIPS_INVAL("float load/store"); generate_exception_err(ctx, EXCP_CpU, 1); return; } MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);}#endif /* MIPS_USES_FPU *//* Arithmetic with immediate operand */static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, int rs, int16_t imm){ uint32_t uimm; const char *opn = "unk"; if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) { /* if no destination, treat it as a NOP * For addi, we must generate the overflow exception when needed. */ MIPS_DEBUG("NOP"); return; } if (opc == OPC_ADDI || opc == OPC_ADDIU || opc == OPC_DADDI || opc == OPC_DADDIU || opc == OPC_SLTI || opc == OPC_SLTIU) uimm = (int32_t)imm; /* Sign extend to 32 bits */ else uimm = (uint16_t)imm; if (opc != OPC_LUI) { GEN_LOAD_REG_TN(T0, rs); GEN_LOAD_IMM_TN(T1, uimm); } else { uimm = uimm << 16; GEN_LOAD_IMM_TN(T0, uimm); } switch (opc) { case OPC_ADDI: save_cpu_state(ctx, 1); gen_op_addo(); opn = "addi"; break; case OPC_ADDIU: gen_op_add(); opn = "addiu"; break;#ifdef MIPS_HAS_MIPS64 case OPC_DADDI: save_cpu_state(ctx, 1); gen_op_daddo(); opn = "daddi"; break; case OPC_DADDIU: gen_op_dadd(); opn = "daddiu"; break;#endif case OPC_SLTI: gen_op_lt(); opn = "slti"; break; case OPC_SLTIU: gen_op_ltu(); opn = "sltiu"; break; case OPC_ANDI: gen_op_and(); opn = "andi"; break; case OPC_ORI: gen_op_or(); opn = "ori"; break; case OPC_XORI: gen_op_xor(); opn = "xori"; break; case OPC_LUI: opn = "lui"; break; case OPC_SLL: gen_op_sll(); opn = "sll"; break; case OPC_SRA: gen_op_sra(); opn = "sra"; break; case OPC_SRL: if ((ctx->opcode >> 21) & 1) { gen_op_rotr(); opn = "rotr"; } else { gen_op_srl(); opn = "srl"; } break;#ifdef MIPS_HAS_MIPS64
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -