📄 ri.c
字号:
{ absy<<=1; if(absx<absy){ absy>>= 1; break; } bm<<=1; } for(;bm;bm>>=1){ if(absx>=absy){ absx -= absy; absquotient |= bm; if(absx == 0) break; } absy >>= 1; } absremainder = absx;end: if( flag ){/*符号相异*/ quotient = -absquotient; remainder = x-quotient*y; }else { quotient = absquotient; remainder = x - quotient*y; } regs->lo =(unsigned long)quotient; regs->hi = (unsigned long)remainder; #ifdef __test_ri__// printf("x is: %d\r\n",x);// printf("y is: %d\r\n",y);// printf("result is: %d (:\r\n",quotient);#endif return 0;}static int emu_divu(struct pt_regs *regs,mips_instruction ir){ unsigned int x,y,bm=1; unsigned int quotient = 0,remainder = 0; /*the "ir" is the instruction causing the exception*/ x = regs->regs[MIPSInst_RS(ir)]; y = regs->regs[MIPSInst_RT(ir)]; if( y == 0 ) {/*overflow*/ return SIGABRT; } if(x<y) {/*don't need to calculate*/ quotient = 0; remainder = x; goto end; } while(!(y&0x80000000)) { y<<=1; if(x<y){ y>>= 1; break; } bm<<=1; } for(;bm;bm>>=1){ if(x>=y){ x -= y; quotient |= bm; if(x == 0) break; } y >>= 1; } remainder = x;end: regs->lo = quotient; regs->hi = remainder; return 0; }/* * Compute the return address and do emulate branch simulation, if required. */#define EFAULT 1int __compute_return_epc(struct pt_regs *regs){ unsigned int *addr, bit, fcr31; long epc; mips_instruction insn; epc = regs->cp0_epc; if (epc & 3) { printf("%s: unaligned epc - sending SIGBUS.\n");// force_sig(SIGBUS, current); return -EFAULT; } /* * Read the instruction */ addr = (unsigned int *) (unsigned long) epc;#if 0 if (__get_user(insn, addr)) { printf("%s: bad epc value - sending SIGSEGV.\n");// force_sig(SIGSEGV, current); return -EFAULT; }#endif//bjzheng add __get_user is prevent page_fault exception,if this occurs,load from disk,but now my whole code is in ram. insn=*addr;// printf("instruction is %x",insn); regs->regs[0] = 0; switch (MIPSInst_OPCODE(insn)) { /* * jr and jalr are in r_format format. */ case spec_op: switch (MIPSInst_FUNC(insn)) { case jalr_op: regs->regs[MIPSInst_RD(insn)] = epc + 8; /* Fall through */ case jr_op: regs->cp0_epc = regs->regs[MIPSInst_RS(insn)]; break; } break; /* * This group contains: * bltz_op, bgez_op, bltzl_op, bgezl_op, * bltzal_op, bgezal_op, bltzall_op, bgezall_op. */ case bcond_op: switch (MIPSInst_RT(insn)) { case bltz_op: case bltzl_op: if ((long)regs->regs[MIPSInst_RS(insn)] < 0) epc = epc + 4 + (MIPSInst_SIMM(insn) << 2); else epc += 8; regs->cp0_epc = epc; break; case bgez_op: case bgezl_op: if ((long)regs->regs[MIPSInst_RS(insn)] >= 0) epc = epc + 4 + (MIPSInst_SIMM(insn) << 2); else epc += 8; regs->cp0_epc = epc; break; case bltzal_op: case bltzall_op: regs->regs[31] = epc + 8; if ((long)regs->regs[MIPSInst_RS(insn)] < 0) epc = epc + 4 + (MIPSInst_SIMM(insn) << 2); else epc += 8; regs->cp0_epc = epc; break; case bgezal_op: case bgezall_op: regs->regs[31] = epc + 8; if ((long)regs->regs[MIPSInst_RS(insn)] >= 0) epc = epc + 4 + (MIPSInst_SIMM(insn) << 2); else epc += 8; regs->cp0_epc = epc; break; } break; /* * These are unconditional and in j_format. */ case jal_op: regs->regs[31] = regs->cp0_epc + 8; case j_op: epc += 4; epc >>= 28; epc <<= 28; epc |= (MIPSInst_JTARGET(insn) << 2); regs->cp0_epc = epc; break; /* * These are conditional and in i_format. */ case beq_op: case beql_op: if (regs->regs[MIPSInst_RS(insn)] == regs->regs[MIPSInst_RT(insn)]) epc = epc + 4 + (MIPSInst_SIMM(insn) << 2); else epc += 8; regs->cp0_epc = epc; break; case bne_op: case bnel_op: if (regs->regs[MIPSInst_RS(insn)] != regs->regs[MIPSInst_RT(insn)]) epc = epc + 4 + (MIPSInst_SIMM(insn) << 2); else epc += 8; regs->cp0_epc = epc; break; case blez_op: /* not really i_format */ case blezl_op: /* rt field assumed to be zero */ if ((long)regs->regs[MIPSInst_RS(insn)] <= 0) epc = epc + 4 + (MIPSInst_SIMM(insn) << 2); else epc += 8; regs->cp0_epc = epc; break; case bgtz_op: case bgtzl_op: /* rt field assumed to be zero */ if ((long)regs->regs[MIPSInst_RS(insn)] > 0) epc = epc + 4 + (MIPSInst_SIMM(insn) << 2); else epc += 8; regs->cp0_epc = epc; break; /* * And now the FPA/cp1 branch instructions. */ case cop1_op:#ifdef CONFIG_MIPS_FPU_EMULATOR if(!(mips_cpu.options & MIPS_CPU_FPU)) fcr31 = current->tss.fpu.soft.sr; else#endif asm ("cfc1\t%0,$31":"=r" (fcr31)); bit = (MIPSInst_RT(insn) >> 2); bit += (bit != 0); bit += 23; switch (MIPSInst_RT(insn)) { case 0: /* bc1f */ case 2: /* bc1fl */ if (~fcr31 & (1 << bit)) epc = epc + 4 + (MIPSInst_SIMM(insn) << 2); else epc += 8; regs->cp0_epc = epc; break; case 1: /* bc1t */ case 3: /* bc1tl */ if (fcr31 & (1 << bit)) epc = epc + 4 + (MIPSInst_SIMM(insn) << 2); else epc += 8; regs->cp0_epc = epc; break; } break; } return 0;}int do_ri (struct pt_regs *xcp){ mips_instruction ir; vaddr_t_l emulpc; vaddr_t_l contpc; int err = 0; int sig; ir = mips_get_word_l(xcp, REG_TO_VA_l xcp->cp0_epc, &err); if (err) { return SIGBUS; } /* XXX NEC Vr54xx bug workaround *//* if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr (&ir)) xcp->cp0_cause &= ~CAUSEF_BD;*/ if (xcp->cp0_cause & CAUSEF_BD) { /* The instruction to be emulated is in a branch delay slot * which means that we have to emulate the branch instruction * BEFORE we do the emulating instruction. * This branch could be a COP1 branch */ emulpc = REG_TO_VA_l(xcp->cp0_epc + 4); /* Snapshot emulation target */#ifndef __bjzheng__ if( __compute_return_epc(xcp)) {/*compute the return address*/#ifdef DBG _mon_printf ("failed to emulate branch at %p\n", REG_TO_VA_l (xcp->cp0_epc));#endif return -1;; }#endif ir = mips_get_word_l(xcp, emulpc, &err); if (err) { return SIGBUS; } contpc = REG_TO_VA_l xcp->cp0_epc; } else { /* not in the Branch delay slot*/ emulpc = REG_TO_VA_l xcp->cp0_epc; contpc = REG_TO_VA_l xcp->cp0_epc + 4; } switch(MIPSInst_OPCODE(ir)) { case lwl_op: /*lwl instruction*/ sig = emu_lwl(xcp,ir,emulpc); if( sig!=0) { /*emul has failed*/ return sig; } break; case lwr_op:/*lwr instruction*/ sig = emu_lwr(xcp,ir,emulpc); if ( sig != 0){ /*emulate has failed!\n");*/ return sig; } break; case swl_op: sig = emu_swl(xcp,ir,emulpc); if( sig!=0 ) { /*emul has failed!*/ printf("emu_swl error\r\n"); return sig; } break; case swr_op: sig = emu_swr(xcp,ir,emulpc); if( sig!=0 ) { /*emul has failed!*/ printf("emu_swr error\r\n"); return sig; } break; case spec_op: switch (MIPSInst_FUNC(ir)){ case div_op:/*div_op*/#ifdef GODSONEV1 global_div_num++;#endif sig = emu_div(xcp,ir); if(sig) { return sig; } break; case divu_op:/* divu_op:*/#ifdef GODSONEV1 global_div_num++;#endif sig = emu_divu(xcp,ir); if(sig) { return sig; } break; default: } default: } /*we do it*/ xcp->cp0_epc = VA_TO_REG_l(contpc); xcp->cp0_cause &= ~CAUSEF_BD; return sig;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -