📄 mathemu.c
字号:
(opcode[3]>>4,opcode[3]&15,opcode[2]>>4); return 0; case 9: /* RRE format, ldebr & mdebr instruction */ /* float store but double load */ emu_store_rege((opcode[3]>>4)&15); emu_store_rege(opcode[3]&15); /* call the emulation function */ ((void (*)(int, int))jump_table[opcode[1]]) (opcode[3]>>4,opcode[3]&15); emu_load_regd((opcode[3]>>4)&15); return 0; case 10: /* RRE format, ledbr instruction */ /* double store but float load */ emu_store_regd((opcode[3]>>4)&15); emu_store_regd(opcode[3]&15); /* call the emulation function */ ((void (*)(int, int))jump_table[opcode[1]]) (opcode[3]>>4,opcode[3]&15); emu_load_rege((opcode[3]>>4)&15); return 0; default: return 1; }}static void* calc_addr(struct pt_regs *regs,int rx,int rb,int disp){ rx &= 0xf; rb &= 0xf; disp &= 0xfff; return (void*) ((rx != 0 ? regs->gprs[rx] : 0) + /* index */ (rb != 0 ? regs->gprs[rb] : 0) + /* base */ disp);} int math_emu_ed(__u8 *opcode, struct pt_regs * regs) { static const __u8 format_table[] = { 0, 0, 0, 0, 5, 1, 2, 1, 2, 2, 2, 2, 5, 2, 4, 4, 2, 1, 1, 0, 2, 1, 0, 2, 1, 1, 1, 1, 1, 1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const void *jump_table[]= { NULL, NULL, NULL, NULL, emu_ldeb, emu_lxdb, emu_lxeb, emu_mxdb, emu_keb, emu_ceb, emu_aeb, emu_seb, emu_mdeb, emu_deb, emu_maeb, emu_mseb, emu_tceb, emu_tcdb, emu_tcxb, NULL, emu_sqeb, emu_sqdb, NULL, emu_meeb, emu_kdb, emu_cdb, emu_adb, emu_sdb, emu_mdb, emu_ddb, emu_madb, emu_msdb }; switch (format_table[opcode[5]]) { case 1: /* RXE format, __u64 constant */ { __u64 *dxb, temp; __u32 opc; emu_store_regd((opcode[1]>>4)&15); opc = *((__u32 *) opcode); dxb = (__u64 *) calc_addr(regs,opc>>16,opc>>12,opc); /* FIXME: how to react if copy_from_user fails ? */ copy_from_user(&temp, dxb, 8); /* call the emulation function */ ((void (*)(int, __u64))jump_table[opcode[5]]) (opcode[1]>>4,temp); emu_load_regd((opcode[1]>>4)&15); return 0; } case 2: /* RXE format, __u32 constant */ { __u32 *dxb, temp; __u32 opc; emu_store_rege((opcode[1]>>4)&15); opc = *((__u32 *) opcode); dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc); /* FIXME: how to react if get_user fails ? */ get_user(temp, dxb); /* call the emulation function */ ((void (*)(int, __u32))jump_table[opcode[5]]) (opcode[1]>>4,temp); emu_load_rege((opcode[1]>>4)&15); return 0; } case 3: /* RXF format, __u64 constant */ { __u32 *dxb, temp; __u32 opc; emu_store_regd((opcode[1]>>4)&15); opc = *((__u32 *) opcode); dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc); /* FIXME: how to react if copy_from_user fails ? */ copy_from_user(&temp, dxb, 8); /* call the emulation function */ ((void (*)(int, __u32, int))jump_table[opcode[5]]) (opcode[1]>>4,temp,opcode[4]>>4); emu_load_regd((opcode[1]>>4)&15); return 0; } case 4: /* RXF format, __u32 constant */ { __u32 *dxb, temp; __u32 opc; emu_store_rege((opcode[1]>>4)&15); opc = *((__u32 *) opcode); dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc); /* FIXME: how to react if get_user fails ? */ get_user(temp, dxb); /* call the emulation function */ ((void (*)(int, __u32, int))jump_table[opcode[5]]) (opcode[1]>>4,temp,opcode[4]>>4); emu_load_rege((opcode[1]>>4)&15); return 0; } case 5: /* RXE format, __u32 constant */ /* store_rege and load_regd */ { __u32 *dxb, temp; __u32 opc; emu_store_rege((opcode[1]>>4)&15); opc = *((__u32 *) opcode); dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc); /* FIXME: how to react if get_user fails ? */ get_user(temp, dxb); /* call the emulation function */ ((void (*)(int, __u32))jump_table[opcode[5]]) (opcode[1]>>4,temp); emu_load_regd((opcode[1]>>4)&15); return 0; } default: return 1; }}/* * Emulate LDR Rx,Ry with Rx or Ry not in {0, 2, 4, 6} */void math_emu_ldr(__u8 *opcode) { __u16 opc = *((__u16 *) opcode); if ((opc & 0x0090) == 0) { /* test if rx in {0,2,4,6} */ /* we got an exception therfore ry can't be in {0,2,4,6} */ __asm__ __volatile ( /* load rx from fp_regs.fprs[ry] */ " bras 1,0f\n" " ld 0,0(%1)\n" "0: ex %0,0(1)" : /* no output */ : "a" (opc&0x00f0), "a" (¤t->thread.fp_regs.fprs[opc&0x000f].d) : "1" ); } else if ((opc & 0x0009) == 0) { /* test if ry in {0,2,4,6} */ __asm__ __volatile ( /* store ry to fp_regs.fprs[rx] */ " bras 1,0f\n" " std 0,0(%1)\n" "0: ex %0,0(1)" : /* no output */ : "a" ((opc&0x000f)<<4), "a" (¤t->thread.fp_regs.fprs[(opc&0x00f0)>>4].d) : "1" ); } else { /* move fp_regs.fprs[ry] to fp_regs.fprs[rx] */ current->thread.fp_regs.fprs[(opc&0x00f0)>>4] = current->thread.fp_regs.fprs[opc&0x000f]; }}/* * Emulate LER Rx,Ry with Rx or Ry not in {0, 2, 4, 6} */void math_emu_ler(__u8 *opcode) { __u16 opc = *((__u16 *) opcode); if ((opc & 0x0090) == 0) { /* test if rx in {0,2,4,6} */ /* we got an exception therfore ry can't be in {0,2,4,6} */ __asm__ __volatile ( /* load rx from fp_regs.fprs[ry] */ " bras 1,0f\n" " le 0,0(%1)\n" "0: ex %0,0(1)" : /* no output */ : "a" (opc&0x00f0), "a" (¤t->thread.fp_regs.fprs[opc&0x000f].f) : "1" ); } else if ((opc & 0x0009) == 0) { /* test if ry in {0,2,4,6} */ __asm__ __volatile ( /* store ry to fp_regs.fprs[rx] */ " bras 1,0f\n" " ste 0,0(%1)\n" "0: ex %0,0(1)" : /* no output */ : "a" ((opc&0x000f)<<4), "a" (¤t->thread.fp_regs.fprs[(opc&0x00f0)>>4].f) : "1" ); } else { /* move fp_regs.fprs[ry] to fp_regs.fprs[rx] */ current->thread.fp_regs.fprs[(opc&0x00f0)>>4] = current->thread.fp_regs.fprs[opc&0x000f]; }}/* * Emulate LD R,D(X,B) with R not in {0, 2, 4, 6} */void math_emu_ld(__u8 *opcode, struct pt_regs * regs) { __u32 opc = *((__u32 *) opcode); __u64 *dxb; dxb = (__u64 *) calc_addr(regs,opc>>16,opc>>12,opc); /* FIXME: how to react if copy_from_user fails ? */ copy_from_user(¤t->thread.fp_regs.fprs[(opc>>20)&15].d, dxb, 8);}/* * Emulate LE R,D(X,B) with R not in {0, 2, 4, 6} */void math_emu_le(__u8 *opcode, struct pt_regs * regs) { __u32 opc = *((__u32 *) opcode); __u32 *mem, *dxb; dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc); /* FIXME: how to react if get_user fails ? */ mem = (__u32 *) (¤t->thread.fp_regs.fprs[(opc>>20)&15].f); get_user(mem[0], dxb);}/* * Emulate STD R,D(X,B) with R not in {0, 2, 4, 6} */void math_emu_std(__u8 *opcode, struct pt_regs * regs) { __u32 opc = *((__u32 *) opcode); __u64 *dxb; dxb = (__u64 *) calc_addr(regs,opc>>16,opc>>12,opc); /* FIXME: how to react if copy_to_user fails ? */ copy_to_user(dxb, ¤t->thread.fp_regs.fprs[(opc>>20)&15].d, 8);}/* * Emulate STE R,D(X,B) with R not in {0, 2, 4, 6} */void math_emu_ste(__u8 *opcode, struct pt_regs * regs) { __u32 opc = *((__u32 *) opcode); __u32 *mem, *dxb; dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc); /* FIXME: how to react if put_user fails ? */ mem = (__u32 *) (¤t->thread.fp_regs.fprs[(opc>>20)&15].f); put_user(mem[0], dxb);}/* * Emulate LFPC D(B) */int math_emu_lfpc(__u8 *opcode, struct pt_regs *regs) { /* FIXME: how to do that ?!? */ return 0;}/* * Emulate STFPC D(B) */int math_emu_stfpc(__u8 *opcode, struct pt_regs *regs) { /* FIXME: how to do that ?!? */ return 0;}/* * Emulate SRNM D(B) */int math_emu_srnm(__u8 *opcode, struct pt_regs *regs) { /* FIXME: how to do that ?!? */ return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -