📄 mips64_x86_trans.c
字号:
/* cp0 register */ x86_mov_reg_imm(b->jit_ptr,X86_ECX,rd); /* gpr */ x86_mov_reg_imm(b->jit_ptr,X86_EDX,rt); /* cpu instance */ x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); mips64_emit_basic_c_call(b,f);}/* Virtual Breakpoint */void mips64_emit_breakpoint(mips64_jit_tcb_t *b){ x86_alu_reg_imm(b->jit_ptr,X86_SUB,X86_ESP,12); x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); mips64_emit_c_call(b,mips64_run_breakpoint); x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12);}/* Unknown opcode handler */static asmlinkage void mips64_unknown_opcode(cpu_mips_t *cpu,m_uint32_t opcode){ printf("MIPS64: unhandled opcode 0x%8.8x at 0x%llx (ra=0x%llx)\n", opcode,cpu->pc,cpu->gpr[MIPS_GPR_RA]); mips64_dump_regs(cpu->gen);}/* Emit unhandled instruction code */static int mips64_emit_unknown(cpu_mips_t *cpu,mips64_jit_tcb_t *b, mips_insn_t opcode){ x86_mov_reg_imm(b->jit_ptr,X86_EAX,opcode); x86_alu_reg_imm(b->jit_ptr,X86_SUB,X86_ESP,4); x86_push_reg(b->jit_ptr,X86_EAX); x86_push_reg(b->jit_ptr,X86_EDI); mips64_emit_c_call(b,mips64_unknown_opcode); x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12); return(0);}/* Invalid delay slot handler */static fastcall void mips64_invalid_delay_slot(cpu_mips_t *cpu){ printf("MIPS64: invalid instruction in delay slot at 0x%llx (ra=0x%llx)\n", cpu->pc,cpu->gpr[MIPS_GPR_RA]); mips64_dump_regs(cpu->gen); /* Halt the virtual CPU */ cpu->pc = 0;}/* Emit unhandled instruction code */int mips64_emit_invalid_delay_slot(mips64_jit_tcb_t *b){ x86_alu_reg_imm(b->jit_ptr,X86_SUB,X86_ESP,12); x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); mips64_emit_c_call(b,mips64_invalid_delay_slot); x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12); mips64_jit_tcb_push_epilog(b); return(0);}/* * Increment count register and trigger the timer IRQ if value in compare * register is the same. */void mips64_inc_cp0_count_reg(mips64_jit_tcb_t *b){ x86_inc_membase(b->jit_ptr,X86_EDI,OFFSET(cpu_mips_t,cp0_virt_cnt_reg));}/* Check if there are pending IRQ */void mips64_check_pending_irq(mips64_jit_tcb_t *b){ u_char *test1; /* Check the pending IRQ flag */ x86_mov_reg_membase(b->jit_ptr,X86_EAX, X86_EDI,OFFSET(cpu_mips_t,irq_pending),4); x86_test_reg_reg(b->jit_ptr,X86_EAX,X86_EAX); test1 = b->jit_ptr; x86_branch8(b->jit_ptr, X86_CC_Z, 0, 1); /* Save PC */ mips64_set_pc(b,b->start_pc+((b->mips_trans_pos-1)<<2)); /* Trigger the IRQ */ x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); mips64_emit_basic_c_call(b,mips64_trigger_irq); mips64_jit_tcb_push_epilog(b); x86_patch(test1,b->jit_ptr);}/* Increment the number of executed instructions (performance debugging) */void mips64_inc_perf_counter(mips64_jit_tcb_t *b){ x86_inc_membase(b->jit_ptr,X86_EDI,OFFSET(cpu_mips_t,perf_counter));}/* ADD */DECLARE_INSN(ADD){ int rs = bits(insn,21,25); int rt = bits(insn,16,20); int rd = bits(insn,11,15); /* TODO: Exception handling */ x86_mov_reg_membase(b->jit_ptr,X86_EAX,X86_EDI,REG_OFFSET(rs),4); x86_alu_reg_membase(b->jit_ptr,X86_ADD,X86_EAX,X86_EDI,REG_OFFSET(rt)); x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(rd),X86_EAX,4); x86_cdq(b->jit_ptr); x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(rd)+4,X86_EDX,4); return(0);}/* ADDI */DECLARE_INSN(ADDI){ int rs = bits(insn,21,25); int rt = bits(insn,16,20); int imm = bits(insn,0,15); m_uint64_t val = sign_extend(imm,16); /* TODO: Exception handling */ x86_mov_reg_imm(b->jit_ptr,X86_EAX,val & 0xffffffff); x86_alu_reg_membase(b->jit_ptr,X86_ADD,X86_EAX,X86_EDI,REG_OFFSET(rs)); x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(rt),X86_EAX,4); x86_cdq(b->jit_ptr); x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(rt)+4,X86_EDX,4); return(0);}/* ADDIU */DECLARE_INSN(ADDIU){ int rs = bits(insn,21,25); int rt = bits(insn,16,20); int imm = bits(insn,0,15); m_uint64_t val = sign_extend(imm,16); x86_mov_reg_imm(b->jit_ptr,X86_EAX,val & 0xffffffff); x86_alu_reg_membase(b->jit_ptr,X86_ADD,X86_EAX,X86_EDI,REG_OFFSET(rs)); x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(rt),X86_EAX,4); x86_cdq(b->jit_ptr); x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(rt)+4,X86_EDX,4); return(0);}/* ADDU */DECLARE_INSN(ADDU){ int rs = bits(insn,21,25); int rt = bits(insn,16,20); int rd = bits(insn,11,15); x86_mov_reg_membase(b->jit_ptr,X86_EAX,X86_EDI,REG_OFFSET(rs),4); x86_alu_reg_membase(b->jit_ptr,X86_ADD,X86_EAX,X86_EDI,REG_OFFSET(rt)); x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(rd),X86_EAX,4); x86_cdq(b->jit_ptr); x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(rd)+4,X86_EDX,4); return(0);}/* AND */DECLARE_INSN(AND){ int rs = bits(insn,21,25); int rt = bits(insn,16,20); int rd = bits(insn,11,15); x86_mov_reg_membase(b->jit_ptr,X86_EAX,X86_EDI,REG_OFFSET(rs),4); x86_mov_reg_membase(b->jit_ptr,X86_EBX,X86_EDI,REG_OFFSET(rs)+4,4); x86_alu_reg_membase(b->jit_ptr,X86_AND,X86_EAX,X86_EDI,REG_OFFSET(rt)); x86_alu_reg_membase(b->jit_ptr,X86_AND,X86_EBX,X86_EDI,REG_OFFSET(rt)+4); x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(rd),X86_EAX,4); x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(rd)+4,X86_EBX,4); return(0);}/* ANDI */DECLARE_INSN(ANDI){ int rs = bits(insn,21,25); int rt = bits(insn,16,20); int imm = bits(insn,0,15); x86_mov_reg_imm(b->jit_ptr,X86_EAX,imm); x86_alu_reg_reg(b->jit_ptr,X86_XOR,X86_EBX,X86_EBX); x86_alu_reg_membase(b->jit_ptr,X86_AND,X86_EAX,X86_EDI,REG_OFFSET(rs)); x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(rt),X86_EAX,4); x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(rt)+4,X86_EBX,4); return(0);}/* B (Branch, virtual instruction) */DECLARE_INSN(B){ int offset = bits(insn,0,15); m_uint64_t new_pc; /* compute the new pc */ new_pc = b->start_pc + (b->mips_trans_pos << 2); new_pc += sign_extend(offset << 2,18); /* insert the instruction in the delay slot */ mips64_jit_fetch_and_emit(cpu,b,1); /* set the new pc in cpu structure */ mips64_set_jump(cpu,b,new_pc,1); return(0);}/* BAL (Branch and Link, virtual instruction) */DECLARE_INSN(BAL){ int offset = bits(insn,0,15); m_uint64_t new_pc; /* compute the new pc */ new_pc = b->start_pc + (b->mips_trans_pos << 2); new_pc += sign_extend(offset << 2,18); /* set the return address (instruction after the delay slot) */ mips64_set_ra(b,b->start_pc + ((b->mips_trans_pos + 1) << 2)); /* insert the instruction in the delay slot */ mips64_jit_fetch_and_emit(cpu,b,1); /* set the new pc in cpu structure */ mips64_set_jump(cpu,b,new_pc,0); return(0);}/* BEQ (Branch On Equal) */DECLARE_INSN(BEQ){ int rs = bits(insn,21,25); int rt = bits(insn,16,20); int offset = bits(insn,0,15); u_char *test1,*test2; m_uint64_t new_pc; /* compute the new pc */ new_pc = b->start_pc + (b->mips_trans_pos << 2); new_pc += sign_extend(offset << 2,18); /* * compare gpr[rs] and gpr[rt]. * compare the low 32 bits first (higher probability). */ x86_mov_reg_membase(b->jit_ptr,X86_EAX,X86_EDI,REG_OFFSET(rs),4); x86_alu_reg_membase(b->jit_ptr,X86_CMP,X86_EAX,X86_EDI,REG_OFFSET(rt)); test1 = b->jit_ptr; x86_branch32(b->jit_ptr, X86_CC_NE, 0, 1); x86_mov_reg_membase(b->jit_ptr,X86_EBX,X86_EDI,REG_OFFSET(rs)+4,4); x86_alu_reg_membase(b->jit_ptr,X86_CMP,X86_EBX,X86_EDI,REG_OFFSET(rt)+4); test2 = b->jit_ptr; x86_branch32(b->jit_ptr, X86_CC_NE, 0, 1); /* insert the instruction in the delay slot */ mips64_jit_fetch_and_emit(cpu,b,2); /* set the new pc in cpu structure */ mips64_set_jump(cpu,b,new_pc,1); x86_patch(test1,b->jit_ptr); x86_patch(test2,b->jit_ptr); /* if the branch is not taken, we have to execute the delay slot too */ mips64_jit_fetch_and_emit(cpu,b,1); return(0);}/* BEQL (Branch On Equal Likely) */DECLARE_INSN(BEQL){ int rs = bits(insn,21,25); int rt = bits(insn,16,20); int offset = bits(insn,0,15); u_char *test1,*test2; m_uint64_t new_pc; /* compute the new pc */ new_pc = b->start_pc + (b->mips_trans_pos << 2); new_pc += sign_extend(offset << 2,18); /* * compare gpr[rs] and gpr[rt]. * compare the low 32 bits first (higher probability). */ x86_mov_reg_membase(b->jit_ptr,X86_EAX,X86_EDI,REG_OFFSET(rs),4); x86_alu_reg_membase(b->jit_ptr,X86_CMP,X86_EAX,X86_EDI,REG_OFFSET(rt)); test1 = b->jit_ptr; x86_branch32(b->jit_ptr, X86_CC_NE, 0, 1); x86_mov_reg_membase(b->jit_ptr,X86_EBX,X86_EDI,REG_OFFSET(rs)+4,4); x86_alu_reg_membase(b->jit_ptr,X86_CMP,X86_EBX,X86_EDI,REG_OFFSET(rt)+4); test2 = b->jit_ptr; x86_branch32(b->jit_ptr, X86_CC_NE, 0, 1); /* insert the instruction in the delay slot */ mips64_jit_fetch_and_emit(cpu,b,1); /* set the new pc in cpu structure */ mips64_set_jump(cpu,b,new_pc,1); x86_patch(test1,b->jit_ptr); x86_patch(test2,b->jit_ptr); return(0);}/* BEQZ (Branch On Equal Zero - optimization) */DECLARE_INSN(BEQZ){ int rs = bits(insn,21,25); int offset = bits(insn,0,15); u_char *test1,*test2; m_uint64_t new_pc; /* compute the new pc */ new_pc = b->start_pc + (b->mips_trans_pos << 2); new_pc += sign_extend(offset << 2,18); /* * compare gpr[rs] with 0. * compare the low 32 bits first (higher probability). */ x86_alu_membase_imm(b->jit_ptr,X86_CMP,X86_EDI,REG_OFFSET(rs),0); test1 = b->jit_ptr; x86_branch32(b->jit_ptr, X86_CC_NE, 0, 1); x86_alu_membase_imm(b->jit_ptr,X86_CMP,X86_EDI,REG_OFFSET(rs)+4,0); test2 = b->jit_ptr; x86_branch32(b->jit_ptr, X86_CC_NE, 0, 1); /* insert the instruction in the delay slot */ mips64_jit_fetch_and_emit(cpu,b,2); /* set the new pc in cpu structure */ mips64_set_jump(cpu,b,new_pc,1); x86_patch(test1,b->jit_ptr); x86_patch(test2,b->jit_ptr); /* if the branch is not taken, we have to execute the delay slot too */ mips64_jit_fetch_and_emit(cpu,b,1); return(0);}/* BNEZ (Branch On Not Equal Zero - optimization) */DECLARE_INSN(BNEZ){ int rs = bits(insn,21,25); int offset = bits(insn,0,15); u_char *test1,*test2; m_uint64_t new_pc; /* compute the new pc */ new_pc = b->start_pc + (b->mips_trans_pos << 2); new_pc += sign_extend(offset << 2,18); /* * compare gpr[rs] with 0. * compare the low 32 bits first (higher probability). */ x86_alu_membase_imm(b->jit_ptr,X86_CMP,X86_EDI,REG_OFFSET(rs),0); test1 = b->jit_ptr; x86_branch8(b->jit_ptr, X86_CC_NE, 0, 1); x86_alu_membase_imm(b->jit_ptr,X86_CMP,X86_EDI,REG_OFFSET(rs)+4,0); test2 = b->jit_ptr; x86_branch32(b->jit_ptr, X86_CC_E, 0, 1); x86_patch(test1,b->jit_ptr); /* insert the instruction in the delay slot */ mips64_jit_fetch_and_emit(cpu,b,2); /* set the new pc in cpu structure */ mips64_set_jump(cpu,b,new_pc,1); x86_patch(test2,b->jit_ptr); /* if the branch is not taken, we have to execute the delay slot too */ mips64_jit_fetch_and_emit(cpu,b,1); return(0);}/* BGEZ (Branch On Greater or Equal Than Zero) */DECLARE_INSN(BGEZ){ int rs = bits(insn,21,25); int offset = bits(insn,0,15); u_char *test1; m_uint64_t new_pc; /* compute the new pc */ new_pc = b->start_pc + (b->mips_trans_pos << 2); new_pc += sign_extend(offset << 2,18); /* If sign bit is set, don't take the branch */ x86_mov_reg_membase(b->jit_ptr,X86_EAX,X86_EDI,REG_OFFSET(rs)+4,4); x86_test_reg_reg(b->jit_ptr,X86_EAX,X86_EAX); test1 = b->jit_ptr; x86_branch32(b->jit_ptr, X86_CC_S, 0, 1); /* insert the instruction in the delay slot */ mips64_jit_fetch_and_emit(cpu,b,2); /* set the new pc in cpu structure */ mips64_set_jump(cpu,b,new_pc,1); x86_patch(test1,b->jit_ptr); /* if the branch is not taken, we have to execute the delay slot too */ mips64_jit_fetch_and_emit(cpu,b,1); return(0);}/* BGEZAL (Branch On Greater or Equal Than Zero And Link) */DECLARE_INSN(BGEZAL){ int rs = bits(insn,21,25); int offset = bits(insn,0,15); u_char *test1; m_uint64_t new_pc; /* compute the new pc */ new_pc = b->start_pc + (b->mips_trans_pos << 2); new_pc += sign_extend(offset << 2,18); /* set the return address (instruction after the delay slot) */ mips64_set_ra(b,b->start_pc + ((b->mips_trans_pos + 1) << 2)); /* If sign bit is set, don't take the branch */ x86_mov_reg_membase(b->jit_ptr,X86_EAX,X86_EDI,REG_OFFSET(rs)+4,4); x86_test_reg_reg(b->jit_ptr,X86_EAX,X86_EAX); test1 = b->jit_ptr; x86_branch32(b->jit_ptr, X86_CC_S, 0, 1); /* insert the instruction in the delay slot */ mips64_jit_fetch_and_emit(cpu,b,2); /* set the new pc in cpu structure */ mips64_set_jump(cpu,b,new_pc,1); x86_patch(test1,b->jit_ptr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -