📄 translate.c
字号:
opn = "ldr"; break; case OPC_SDR: GEN_LOAD_REG_TN(T1, rt); op_ldst(sdr); opn = "sdr"; break;#endif case OPC_LW:#if defined (MIPS_HAS_UNALIGNED_LS) case OPC_ULW:#endif op_ldst(lw); GEN_STORE_TN_REG(rt, T0); opn = "lw"; break; case OPC_SW:#if defined (MIPS_HAS_UNALIGNED_LS) case OPC_USW:#endif GEN_LOAD_REG_TN(T1, rt); op_ldst(sw); opn = "sw"; break; case OPC_LH:#if defined (MIPS_HAS_UNALIGNED_LS) case OPC_ULH:#endif op_ldst(lh); GEN_STORE_TN_REG(rt, T0); opn = "lh"; break; case OPC_SH:#if defined (MIPS_HAS_UNALIGNED_LS) case OPC_USH:#endif GEN_LOAD_REG_TN(T1, rt); op_ldst(sh); opn = "sh"; break; case OPC_LHU:#if defined (MIPS_HAS_UNALIGNED_LS) case OPC_ULHU:#endif 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]);}/* Arithmetic with immediate operand */static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt, int rs, int16_t imm){ uint32_t uimm; const unsigned char *opn = "unk"; if (rt == 0 && opc != OPC_ADDI) { /* 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_SLTI || opc == OPC_SLTIU) uimm = (int32_t)imm; /* Sign extent 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; 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: gen_op_srl(); opn = "srl"; break; default: MIPS_INVAL("imm arith"); generate_exception(ctx, EXCP_RI); return; } GEN_STORE_TN_REG(rt, T0); MIPS_DEBUG("%s %s, %s, %x", opn, regnames[rt], regnames[rs], uimm);}/* Arithmetic */static void gen_arith (DisasContext *ctx, uint16_t opc, int rd, int rs, int rt){ const unsigned char *opn = "unk"; if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB) { /* if no destination, treat it as a NOP * For add & sub, we must generate the overflow exception when needed. */ MIPS_DEBUG("NOP"); return; } GEN_LOAD_REG_TN(T0, rs); GEN_LOAD_REG_TN(T1, rt); switch (opc) { case OPC_ADD: save_cpu_state(ctx, 1); gen_op_addo(); opn = "add"; break; case OPC_ADDU: gen_op_add(); opn = "addu"; break; case OPC_SUB: save_cpu_state(ctx, 1); gen_op_subo(); opn = "sub"; break; case OPC_SUBU: gen_op_sub(); opn = "subu"; break; case OPC_SLT: gen_op_lt(); opn = "slt"; break; case OPC_SLTU: gen_op_ltu(); opn = "sltu"; break; case OPC_AND: gen_op_and(); opn = "and"; break; case OPC_NOR: gen_op_nor(); opn = "nor"; break; case OPC_OR: gen_op_or(); opn = "or"; break; case OPC_XOR: gen_op_xor(); opn = "xor"; break; case OPC_MUL: gen_op_mul(); opn = "mul"; break; case OPC_MOVN: gen_op_movn(rd); opn = "movn"; goto print; case OPC_MOVZ: gen_op_movz(rd); opn = "movz"; goto print; case OPC_SLLV: gen_op_sllv(); opn = "sllv"; break; case OPC_SRAV: gen_op_srav(); opn = "srav"; break; case OPC_SRLV: gen_op_srlv(); opn = "srlv"; break; default: MIPS_INVAL("arith"); generate_exception(ctx, EXCP_RI); return; } GEN_STORE_TN_REG(rd, T0); print: MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);}/* Arithmetic on HI/LO registers */static void gen_HILO (DisasContext *ctx, uint16_t opc, int reg){ const unsigned char *opn = "unk"; if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) { /* Treat as a NOP */ MIPS_DEBUG("NOP"); return; } switch (opc) { case OPC_MFHI: gen_op_load_HI(); GEN_STORE_TN_REG(reg, T0); opn = "mfhi"; break; case OPC_MFLO: gen_op_load_LO(); GEN_STORE_TN_REG(reg, T0); opn = "mflo"; break; case OPC_MTHI: GEN_LOAD_REG_TN(T0, reg); gen_op_store_HI(); opn = "mthi"; break; case OPC_MTLO: GEN_LOAD_REG_TN(T0, reg); gen_op_store_LO(); opn = "mtlo"; break; default: MIPS_INVAL("HILO"); generate_exception(ctx, EXCP_RI); return; } MIPS_DEBUG("%s %s", opn, regnames[reg]);}static void gen_muldiv (DisasContext *ctx, uint16_t opc, int rs, int rt){ const unsigned char *opn = "unk"; GEN_LOAD_REG_TN(T0, rs); GEN_LOAD_REG_TN(T1, rt); switch (opc) { case OPC_DIV: gen_op_div(); opn = "div"; break; case OPC_DIVU: gen_op_divu(); opn = "divu"; break; case OPC_MULT: gen_op_mult(); opn = "mult"; break; case OPC_MULTU: gen_op_multu(); opn = "multu"; break; case OPC_MADD: gen_op_madd(); opn = "madd"; break; case OPC_MADDU: gen_op_maddu(); opn = "maddu"; break; case OPC_MSUB: gen_op_msub(); opn = "msub"; break; case OPC_MSUBU: gen_op_msubu(); opn = "msubu"; break; default: MIPS_INVAL("mul/div"); generate_exception(ctx, EXCP_RI); return; } MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);}static void gen_cl (DisasContext *ctx, uint16_t opc, int rd, int rs){ const unsigned char *opn = "unk"; if (rd == 0) { /* Treat as a NOP */ MIPS_DEBUG("NOP"); return; } GEN_LOAD_REG_TN(T0, rs); switch (opc) { case OPC_CLO: /* CLO */ gen_op_clo(); opn = "clo"; break; case OPC_CLZ: /* CLZ */ gen_op_clz(); opn = "clz"; break; default: MIPS_INVAL("CLx"); generate_exception(ctx, EXCP_RI); return; } gen_op_store_T0_gpr(rd); MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);}/* Traps */static void gen_trap (DisasContext *ctx, uint16_t opc, int rs, int rt, int16_t imm){ int cond; cond = 0; /* Load needed operands */ switch (opc) { case OPC_TEQ: case OPC_TGE: case OPC_TGEU: case OPC_TLT: case OPC_TLTU: case OPC_TNE: /* Compare two registers */ if (rs != rt) { GEN_LOAD_REG_TN(T0, rs); GEN_LOAD_REG_TN(T1, rt); cond = 1; } case OPC_TEQI: case OPC_TGEI: case OPC_TGEIU: case OPC_TLTI: case OPC_TLTIU: case OPC_TNEI: /* Compare register to immediate */ if (rs != 0 || imm != 0) { GEN_LOAD_REG_TN(T0, rs); GEN_LOAD_IMM_TN(T1, (int32_t)imm); cond = 1; } break; } if (cond == 0) { switch (opc) { case OPC_TEQ: /* rs == rs */ case OPC_TEQI: /* r0 == 0 */ case OPC_TGE: /* rs >= rs */ case OPC_TGEI: /* r0 >= 0 */ case OPC_TGEU: /* rs >= rs unsigned */ case OPC_TGEIU: /* r0 >= 0 unsigned */ /* Always trap */ gen_op_set_T0(1); break; case OPC_TLT: /* rs < rs */ case OPC_TLTI: /* r0 < 0 */ case OPC_TLTU: /* rs < rs unsigned */ case OPC_TLTIU: /* r0 < 0 unsigned */ case OPC_TNE: /* rs != rs */ case OPC_TNEI: /* r0 != 0 */ /* Never trap: treat as NOP */ return; default: MIPS_INVAL("TRAP");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -