cp1emu.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:29k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * cp1emu.c: a MIPS coprocessor 1 (fpu) instruction emulator
  3.  *
  4.  * MIPS floating point support
  5.  * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
  6.  * http://www.algor.co.uk
  7.  *
  8.  * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
  9.  * Copyright (C) 2000  MIPS Technologies, Inc.
  10.  *
  11.  *  This program is free software; you can distribute it and/or modify it
  12.  *  under the terms of the GNU General Public License (Version 2) as
  13.  *  published by the Free Software Foundation.
  14.  *
  15.  *  This program is distributed in the hope it will be useful, but WITHOUT
  16.  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  17.  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  18.  *  for more details.
  19.  *
  20.  *  You should have received a copy of the GNU General Public License along
  21.  *  with this program; if not, write to the Free Software Foundation, Inc.,
  22.  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  23.  *
  24.  * A complete emulator for MIPS coprocessor 1 instructions.  This is
  25.  * required for #float(switch) or #float(trap), where it catches all
  26.  * COP1 instructions via the "CoProcessor Unusable" exception.
  27.  *
  28.  * More surprisingly it is also required for #float(ieee), to help out
  29.  * the hardware fpu at the boundaries of the IEEE-754 representation
  30.  * (denormalised values, infinities, underflow, etc).  It is made
  31.  * quite nasty because emulation of some non-COP1 instructions is
  32.  * required, e.g. in branch delay slots.
  33.  *
  34.  * Note if you know that you won't have an fpu, then you'll get much
  35.  * better performance by compiling with -msoft-float!
  36.  */
  37. #include <asm/inst.h>
  38. #include <asm/bootinfo.h>
  39. #include <asm/cpu.h>
  40. #include <asm/processor.h>
  41. #include <asm/ptrace.h>
  42. #include <asm/signal.h>
  43. #include <asm/mipsregs.h>
  44. #include <asm/fpu_emulator.h>
  45. #include <asm/uaccess.h>
  46. #include <asm/branch.h>
  47. #include "ieee754.h"
  48. #include "dsemul.h"
  49. /* Strap kernel emulator for full MIPS IV emulation */
  50. #ifdef __mips
  51. #undef __mips
  52. #endif
  53. #define __mips 4
  54. /* Function which emulates a floating point instruction. */
  55. static int fpu_emu(struct pt_regs *, struct mips_fpu_soft_struct *,
  56. mips_instruction);
  57. #if __mips >= 4 && __mips != 32
  58. static int fpux_emu(struct pt_regs *,
  59. struct mips_fpu_soft_struct *, mips_instruction);
  60. #endif
  61. /* Further private data for which no space exists in mips_fpu_soft_struct */
  62. struct mips_fpu_emulator_private fpuemuprivate;
  63. /* Control registers */
  64. #define FPCREG_RID 0 /* $0  = revision id */
  65. #define FPCREG_CSR 31 /* $31 = csr */
  66. /* Convert Mips rounding mode (0..3) to IEEE library modes. */
  67. static const unsigned char ieee_rm[4] = {
  68. IEEE754_RN, IEEE754_RZ, IEEE754_RU, IEEE754_RD
  69. };
  70. #if __mips >= 4
  71. /* convert condition code register number to csr bit */
  72. static const unsigned int fpucondbit[8] = {
  73. FPU_CSR_COND0,
  74. FPU_CSR_COND1,
  75. FPU_CSR_COND2,
  76. FPU_CSR_COND3,
  77. FPU_CSR_COND4,
  78. FPU_CSR_COND5,
  79. FPU_CSR_COND6,
  80. FPU_CSR_COND7
  81. };
  82. #endif
  83. /*
  84.  * Redundant with logic already in kernel/branch.c,
  85.  * embedded in compute_return_epc.  At some point,
  86.  * a single subroutine should be used across both
  87.  * modules.
  88.  */
  89. static int isBranchInstr(mips_instruction * i)
  90. {
  91. switch (MIPSInst_OPCODE(*i)) {
  92. case spec_op:
  93. switch (MIPSInst_FUNC(*i)) {
  94. case jalr_op:
  95. case jr_op:
  96. return 1;
  97. }
  98. break;
  99. case bcond_op:
  100. switch (MIPSInst_RT(*i)) {
  101. case bltz_op:
  102. case bgez_op:
  103. case bltzl_op:
  104. case bgezl_op:
  105. case bltzal_op:
  106. case bgezal_op:
  107. case bltzall_op:
  108. case bgezall_op:
  109. return 1;
  110. }
  111. break;
  112. case j_op:
  113. case jal_op:
  114. case jalx_op:
  115. case beq_op:
  116. case bne_op:
  117. case blez_op:
  118. case bgtz_op:
  119. case beql_op:
  120. case bnel_op:
  121. case blezl_op:
  122. case bgtzl_op:
  123. return 1;
  124. case cop0_op:
  125. case cop1_op:
  126. case cop2_op:
  127. case cop1x_op:
  128. if (MIPSInst_RS(*i) == bc_op)
  129. return 1;
  130. break;
  131. }
  132. return 0;
  133. }
  134. /*
  135.  * In the Linux kernel, we support selection of FPR format on the
  136.  * basis of the Status.FR bit.  This does imply that, if a full 32
  137.  * FPRs are desired, there needs to be a flip-flop that can be written
  138.  * to one at that bit position.  In any case, O32 MIPS ABI uses
  139.  * only the even FPRs (Status.FR = 0).
  140.  */
  141. #define CP0_STATUS_FR_SUPPORT
  142. #ifdef CP0_STATUS_FR_SUPPORT
  143. #define FR_BIT ST0_FR
  144. #else
  145. #define FR_BIT 0
  146. #endif
  147. #define SIFROMREG(si,x) ((si) = 
  148. (xcp->cp0_status & FR_BIT) || !(x & 1) ? 
  149. (int)ctx->regs[x] : 
  150. (int)(ctx->regs[x & ~1] >> 32 ))
  151. #define SITOREG(si,x) (ctx->regs[x & ~((xcp->cp0_status & FR_BIT) == 0)] = 
  152. (xcp->cp0_status & FR_BIT) || !(x & 1) ? 
  153. ctx->regs[x & ~1] >> 32 << 32 | (u32)(si) : 
  154. ctx->regs[x & ~1] << 32 >> 32 | (u64)(si) << 32)
  155. #define DIFROMREG(di,x) ((di) = 
  156. ctx->regs[x & ~((xcp->cp0_status & FR_BIT) == 0)])
  157. #define DITOREG(di,x) (ctx->regs[x & ~((xcp->cp0_status & FR_BIT) == 0)] 
  158. = (di))
  159. #define DIFROMREG(di,x) ((di) = 
  160. ctx->regs[x & ~((xcp->cp0_status & FR_BIT) == 0)])
  161. #define DITOREG(di,x) (ctx->regs[x & ~((xcp->cp0_status & FR_BIT) == 0)] 
  162. = (di))
  163. #define SPFROMREG(sp,x) SIFROMREG((sp).bits,x)
  164. #define SPTOREG(sp,x) SITOREG((sp).bits,x)
  165. #define DPFROMREG(dp,x) DIFROMREG((dp).bits,x)
  166. #define DPTOREG(dp,x) DITOREG((dp).bits,x)
  167. /*
  168.  * Emulate the single floating point instruction pointed at by EPC.
  169.  * Two instructions if the instruction is in a branch delay slot.
  170.  */
  171. static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
  172. {
  173. mips_instruction ir;
  174. vaddr_t emulpc, contpc;
  175. unsigned int cond;
  176. if (get_user(ir, (mips_instruction *) REG_TO_VA xcp->cp0_epc)) {
  177. fpuemuprivate.stats.errors++;
  178. return SIGBUS;
  179. }
  180. /* XXX NEC Vr54xx bug workaround */
  181. if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir))
  182. xcp->cp0_cause &= ~CAUSEF_BD;
  183. if (xcp->cp0_cause & CAUSEF_BD) {
  184. /*
  185.  * The instruction to be emulated is in a branch delay slot
  186.  * which means that we have to  emulate the branch instruction
  187.  * BEFORE we do the cop1 instruction.
  188.  *
  189.  * This branch could be a COP1 branch, but in that case we
  190.  * would have had a trap for that instruction, and would not
  191.  * come through this route.
  192.  *
  193.  * Linux MIPS branch emulator operates on context, updating the
  194.  * cp0_epc.
  195.  */
  196. emulpc = REG_TO_VA(xcp->cp0_epc + 4); /* Snapshot emulation target */
  197. if (__compute_return_epc(xcp)) {
  198. #ifdef CP1DBG
  199. printk("failed to emulate branch at %pn",
  200. REG_TO_VA(xcp->cp0_epc));
  201. #endif
  202. return SIGILL;
  203. }
  204. if (get_user(ir, (mips_instruction *) emulpc)) {
  205. fpuemuprivate.stats.errors++;
  206. return SIGBUS;
  207. }
  208. /* __computer_return_epc() will have updated cp0_epc */
  209. contpc = REG_TO_VA xcp->cp0_epc;
  210. /* In order not to confuse ptrace() et al, tweak context */
  211. xcp->cp0_epc = VA_TO_REG emulpc - 4;
  212. }
  213. else {
  214. emulpc = REG_TO_VA xcp->cp0_epc;
  215. contpc = REG_TO_VA(xcp->cp0_epc + 4);
  216. }
  217.       emul:
  218. fpuemuprivate.stats.emulated++;
  219. switch (MIPSInst_OPCODE(ir)) {
  220. #ifndef SINGLE_ONLY_FPU
  221. case ldc1_op:{
  222. u64 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] +
  223. MIPSInst_SIMM(ir));
  224. u64 val;
  225. fpuemuprivate.stats.loads++;
  226. if (get_user(val, va)) {
  227. fpuemuprivate.stats.errors++;
  228. return SIGBUS;
  229. }
  230. DITOREG(val, MIPSInst_RT(ir));
  231. break;
  232. }
  233. case sdc1_op:{
  234. u64 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] +
  235. MIPSInst_SIMM(ir));
  236. u64 val;
  237. fpuemuprivate.stats.stores++;
  238. DIFROMREG(val, MIPSInst_RT(ir));
  239. if (put_user(val, va)) {
  240. fpuemuprivate.stats.errors++;
  241. return SIGBUS;
  242. }
  243. break;
  244. }
  245. #endif
  246. case lwc1_op:{
  247. u32 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] +
  248. MIPSInst_SIMM(ir));
  249. u32 val;
  250. fpuemuprivate.stats.loads++;
  251. if (get_user(val, va)) {
  252. fpuemuprivate.stats.errors++;
  253. return SIGBUS;
  254. }
  255. #ifdef SINGLE_ONLY_FPU
  256. if (MIPSInst_RT(ir) & 1) {
  257. /* illegal register in single-float mode */
  258. return SIGILL;
  259. }
  260. #endif
  261. SITOREG(val, MIPSInst_RT(ir));
  262. break;
  263. }
  264. case swc1_op:{
  265. u32 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] +
  266. MIPSInst_SIMM(ir));
  267. u32 val;
  268. fpuemuprivate.stats.stores++;
  269. #ifdef SINGLE_ONLY_FPU
  270. if (MIPSInst_RT(ir) & 1) {
  271. /* illegal register in single-float mode */
  272. return SIGILL;
  273. }
  274. #endif
  275. SIFROMREG(val, MIPSInst_RT(ir));
  276. if (put_user(val, va)) {
  277. fpuemuprivate.stats.errors++;
  278. return SIGBUS;
  279. }
  280. break;
  281. }
  282. case cop1_op:
  283. switch (MIPSInst_RS(ir)) {
  284. #if __mips64 && !defined(SINGLE_ONLY_FPU)
  285. case dmfc_op:
  286. /* copregister fs -> gpr[rt] */
  287. if (MIPSInst_RT(ir) != 0) {
  288. DIFROMREG(xcp->regs[MIPSInst_RT(ir)],
  289. MIPSInst_RD(ir));
  290. }
  291. break;
  292. case dmtc_op:
  293. /* copregister fs <- rt */
  294. DITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));
  295. break;
  296. #endif
  297. case mfc_op:
  298. /* copregister rd -> gpr[rt] */
  299. #ifdef SINGLE_ONLY_FPU
  300. if (MIPSInst_RD(ir) & 1) {
  301. /* illegal register in single-float mode */
  302. return SIGILL;
  303. }
  304. #endif
  305. if (MIPSInst_RT(ir) != 0) {
  306. SIFROMREG(xcp->regs[MIPSInst_RT(ir)],
  307. MIPSInst_RD(ir));
  308. }
  309. break;
  310. case mtc_op:
  311. /* copregister rd <- rt */
  312. #ifdef SINGLE_ONLY_FPU
  313. if (MIPSInst_RD(ir) & 1) {
  314. /* illegal register in single-float mode */
  315. return SIGILL;
  316. }
  317. #endif
  318. SITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));
  319. break;
  320. case cfc_op:{
  321. /* cop control register rd -> gpr[rt] */
  322. u32 value;
  323. if (ir == CP1UNDEF) {
  324. return do_dsemulret(xcp);
  325. }
  326. if (MIPSInst_RD(ir) == FPCREG_CSR) {
  327. value = ctx->sr;
  328. #ifdef CSRTRACE
  329. printk("%p gpr[%d]<-csr=%08xn",
  330. REG_TO_VA(xcp->cp0_epc),
  331. MIPSInst_RT(ir), value);
  332. #endif
  333. }
  334. else if (MIPSInst_RD(ir) == FPCREG_RID)
  335. value = 0;
  336. else
  337. value = 0;
  338. if (MIPSInst_RT(ir))
  339. xcp->regs[MIPSInst_RT(ir)] = value;
  340. break;
  341. }
  342. case ctc_op:{
  343. /* copregister rd <- rt */
  344. u32 value;
  345. if (MIPSInst_RT(ir) == 0)
  346. value = 0;
  347. else
  348. value = xcp->regs[MIPSInst_RT(ir)];
  349. /* we only have one writable control reg
  350.  */
  351. if (MIPSInst_RD(ir) == FPCREG_CSR) {
  352. #ifdef CSRTRACE
  353. printk("%p gpr[%d]->csr=%08xn",
  354. REG_TO_VA(xcp->cp0_epc),
  355. MIPSInst_RT(ir), value);
  356. #endif
  357. ctx->sr = value;
  358. /* copy new rounding mode and
  359.    flush bit to ieee library state! */
  360. ieee754_csr.nod = (ctx->sr & 0x1000000) != 0;
  361. ieee754_csr.rm = ieee_rm[value & 0x3];
  362. }
  363. if ((ctx->sr >> 5) & ctx->sr & FPU_CSR_ALL_E) {
  364. return SIGFPE;
  365. }
  366. break;
  367. }
  368. case bc_op:{
  369. int likely = 0;
  370. if (xcp->cp0_cause & CAUSEF_BD)
  371. return SIGILL;
  372. #if __mips >= 4
  373. cond = ctx->sr & fpucondbit[MIPSInst_RT(ir) >> 2];
  374. #else
  375. cond = ctx->sr & FPU_CSR_COND;
  376. #endif
  377. switch (MIPSInst_RT(ir) & 3) {
  378. case bcfl_op:
  379. likely = 1;
  380. case bcf_op:
  381. cond = !cond;
  382. break;
  383. case bctl_op:
  384. likely = 1;
  385. case bct_op:
  386. break;
  387. default:
  388. /* thats an illegal instruction */
  389. return SIGILL;
  390. }
  391. xcp->cp0_cause |= CAUSEF_BD;
  392. if (cond) {
  393. /* branch taken: emulate dslot
  394.  * instruction
  395.  */
  396. xcp->cp0_epc += 4;
  397. contpc = REG_TO_VA
  398. (xcp->cp0_epc +
  399. (MIPSInst_SIMM(ir) << 2));
  400. if (get_user(ir, (mips_instruction *)
  401. REG_TO_VA xcp->cp0_epc)) {
  402. fpuemuprivate.stats.errors++;
  403. return SIGBUS;
  404. }
  405. switch (MIPSInst_OPCODE(ir)) {
  406. case lwc1_op:
  407. case swc1_op:
  408. #if (__mips >= 2 || __mips64) && !defined(SINGLE_ONLY_FPU)
  409. case ldc1_op:
  410. case sdc1_op:
  411. #endif
  412. case cop1_op:
  413. #if __mips >= 4 && __mips != 32
  414. case cop1x_op:
  415. #endif
  416. /* its one of ours */
  417. goto emul;
  418. #if __mips >= 4
  419. case spec_op:
  420. if (MIPSInst_FUNC(ir) == movc_op)
  421. goto emul;
  422. break;
  423. #endif
  424. }
  425. /*
  426.  * Single step the non-cp1
  427.  * instruction in the dslot
  428.  */
  429. return mips_dsemul(xcp, ir, VA_TO_REG contpc);
  430. }
  431. else {
  432. /* branch not taken */
  433. if (likely) {
  434. /*
  435.  * branch likely nullifies
  436.  * dslot if not taken
  437.  */
  438. xcp->cp0_epc += 4;
  439. contpc += 4;
  440. /*
  441.  * else continue & execute
  442.  * dslot as normal insn
  443.  */
  444. }
  445. }
  446. break;
  447. }
  448. default:
  449. if (!(MIPSInst_RS(ir) & 0x10))
  450. return SIGILL;
  451. {
  452. int sig;
  453. /* a real fpu computation instruction */
  454. if ((sig = fpu_emu(xcp, ctx, ir)))
  455. return sig;
  456. }
  457. }
  458. break;
  459. #if __mips >= 4 && __mips != 32
  460. case cop1x_op:{
  461. int sig;
  462. if ((sig = fpux_emu(xcp, ctx, ir)))
  463. return sig;
  464. break;
  465. }
  466. #endif
  467. #if __mips >= 4
  468. case spec_op:
  469. if (MIPSInst_FUNC(ir) != movc_op)
  470. return SIGILL;
  471. cond = fpucondbit[MIPSInst_RT(ir) >> 2];
  472. if (((ctx->sr & cond) != 0) != ((MIPSInst_RT(ir) & 1) != 0))
  473. return 0;
  474. xcp->regs[MIPSInst_RD(ir)] = xcp->regs[MIPSInst_RS(ir)];
  475. break;
  476. #endif
  477. default:
  478. return SIGILL;
  479. }
  480. /* we did it !! */
  481. xcp->cp0_epc = VA_TO_REG(contpc);
  482. xcp->cp0_cause &= ~CAUSEF_BD;
  483. return 0;
  484. }
  485. /*
  486.  * Conversion table from MIPS compare ops 48-63
  487.  * cond = ieee754dp_cmp(x,y,IEEE754_UN,sig);
  488.  */
  489. static const unsigned char cmptab[8] = {
  490. 0, /* cmp_0 (sig) cmp_sf */
  491. IEEE754_CUN, /* cmp_un (sig) cmp_ngle */
  492. IEEE754_CEQ, /* cmp_eq (sig) cmp_seq */
  493. IEEE754_CEQ | IEEE754_CUN, /* cmp_ueq (sig) cmp_ngl  */
  494. IEEE754_CLT, /* cmp_olt (sig) cmp_lt */
  495. IEEE754_CLT | IEEE754_CUN, /* cmp_ult (sig) cmp_nge */
  496. IEEE754_CLT | IEEE754_CEQ, /* cmp_ole (sig) cmp_le */
  497. IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */
  498. };
  499. #if __mips >= 4 && __mips != 32
  500. /*
  501.  * Additional MIPS4 instructions
  502.  */
  503. #define DEF3OP(name, p, f1, f2, f3) 
  504. static ieee754##p fpemu_##p##_##name (ieee754##p r, ieee754##p s, 
  505.     ieee754##p t) 
  506. struct ieee754_csr ieee754_csr_save; 
  507. s = f1 (s, t); 
  508. ieee754_csr_save = ieee754_csr; 
  509. s = f2 (s, r); 
  510. ieee754_csr_save.cx |= ieee754_csr.cx; 
  511. ieee754_csr_save.sx |= ieee754_csr.sx; 
  512. s = f3 (s); 
  513. ieee754_csr.cx |= ieee754_csr_save.cx; 
  514. ieee754_csr.sx |= ieee754_csr_save.sx; 
  515. return s; 
  516. }
  517. static ieee754dp fpemu_dp_recip(ieee754dp d)
  518. {
  519. return ieee754dp_div(ieee754dp_one(0), d);
  520. }
  521. static ieee754dp fpemu_dp_rsqrt(ieee754dp d)
  522. {
  523. return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d));
  524. }
  525. static ieee754sp fpemu_sp_recip(ieee754sp s)
  526. {
  527. return ieee754sp_div(ieee754sp_one(0), s);
  528. }
  529. static ieee754sp fpemu_sp_rsqrt(ieee754sp s)
  530. {
  531. return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s));
  532. }
  533. DEF3OP(madd, sp, ieee754sp_mul, ieee754sp_add,);
  534. DEF3OP(msub, sp, ieee754sp_mul, ieee754sp_sub,);
  535. DEF3OP(nmadd, sp, ieee754sp_mul, ieee754sp_add, ieee754sp_neg);
  536. DEF3OP(nmsub, sp, ieee754sp_mul, ieee754sp_sub, ieee754sp_neg);
  537. DEF3OP(madd, dp, ieee754dp_mul, ieee754dp_add,);
  538. DEF3OP(msub, dp, ieee754dp_mul, ieee754dp_sub,);
  539. DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg);
  540. DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg);
  541. static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
  542. mips_instruction ir)
  543. {
  544. unsigned rcsr = 0; /* resulting csr */
  545. fpuemuprivate.stats.cp1xops++;
  546. switch (MIPSInst_FMA_FFMT(ir)) {
  547. case s_fmt:{ /* 0 */
  548. ieee754sp(*handler) (ieee754sp, ieee754sp, ieee754sp);
  549. ieee754sp fd, fr, fs, ft;
  550. u32 *va;
  551. u32 val;
  552. switch (MIPSInst_FUNC(ir)) {
  553. case lwxc1_op:
  554. va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] +
  555. xcp->regs[MIPSInst_FT(ir)]);
  556. fpuemuprivate.stats.loads++;
  557. if (get_user(val, va)) {
  558. fpuemuprivate.stats.errors++;
  559. return SIGBUS;
  560. }
  561. #ifdef SINGLE_ONLY_FPU
  562. if (MIPSInst_FD(ir) & 1) {
  563. /* illegal register in single-float
  564.  * mode
  565.  */
  566. return SIGILL;
  567. }
  568. #endif
  569. SITOREG(val, MIPSInst_FD(ir));
  570. break;
  571. case swxc1_op:
  572. va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] +
  573. xcp->regs[MIPSInst_FT(ir)]);
  574. fpuemuprivate.stats.stores++;
  575. #ifdef SINGLE_ONLY_FPU
  576. if (MIPSInst_FS(ir) & 1) {
  577. /* illegal register in single-float
  578.  * mode
  579.  */
  580. return SIGILL;
  581. }
  582. #endif
  583. SIFROMREG(val, MIPSInst_FS(ir));
  584. if (put_user(val, va)) {
  585. fpuemuprivate.stats.errors++;
  586. return SIGBUS;
  587. }
  588. break;
  589. case madd_s_op:
  590. handler = fpemu_sp_madd;
  591. goto scoptop;
  592. case msub_s_op:
  593. handler = fpemu_sp_msub;
  594. goto scoptop;
  595. case nmadd_s_op:
  596. handler = fpemu_sp_nmadd;
  597. goto scoptop;
  598. case nmsub_s_op:
  599. handler = fpemu_sp_nmsub;
  600. goto scoptop;
  601.       scoptop:
  602. SPFROMREG(fr, MIPSInst_FR(ir));
  603. SPFROMREG(fs, MIPSInst_FS(ir));
  604. SPFROMREG(ft, MIPSInst_FT(ir));
  605. fd = (*handler) (fr, fs, ft);
  606. SPTOREG(fd, MIPSInst_FD(ir));
  607.       copcsr:
  608. if (ieee754_cxtest(IEEE754_INEXACT))
  609. rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;
  610. if (ieee754_cxtest(IEEE754_UNDERFLOW))
  611. rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;
  612. if (ieee754_cxtest(IEEE754_OVERFLOW))
  613. rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;
  614. if (ieee754_cxtest(IEEE754_INVALID_OPERATION))
  615. rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S;
  616. ctx->sr = (ctx->sr & ~FPU_CSR_ALL_X) | rcsr;
  617. if (ieee754_csr.nod)
  618. ctx->sr |= 0x1000000;
  619. if ((ctx->sr >> 5) & ctx->sr & FPU_CSR_ALL_E) {
  620. /*printk ("SIGFPE: fpu csr = %08xn",
  621.    ctx->sr); */
  622. return SIGFPE;
  623. }
  624. break;
  625. default:
  626. return SIGILL;
  627. }
  628. break;
  629. }
  630. #ifndef SINGLE_ONLY_FPU
  631. case d_fmt:{ /* 1 */
  632. ieee754dp(*handler) (ieee754dp, ieee754dp, ieee754dp);
  633. ieee754dp fd, fr, fs, ft;
  634. u64 *va;
  635. u64 val;
  636. switch (MIPSInst_FUNC(ir)) {
  637. case ldxc1_op:
  638. va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] +
  639. xcp->regs[MIPSInst_FT(ir)]);
  640. fpuemuprivate.stats.loads++;
  641. if (get_user(val, va)) {
  642. fpuemuprivate.stats.errors++;
  643. return SIGBUS;
  644. }
  645. DITOREG(val, MIPSInst_FD(ir));
  646. break;
  647. case sdxc1_op:
  648. va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] +
  649. xcp->regs[MIPSInst_FT(ir)]);
  650. fpuemuprivate.stats.stores++;
  651. DIFROMREG(val, MIPSInst_FS(ir));
  652. if (put_user(val, va)) {
  653. fpuemuprivate.stats.errors++;
  654. return SIGBUS;
  655. }
  656. break;
  657. case madd_d_op:
  658. handler = fpemu_dp_madd;
  659. goto dcoptop;
  660. case msub_d_op:
  661. handler = fpemu_dp_msub;
  662. goto dcoptop;
  663. case nmadd_d_op:
  664. handler = fpemu_dp_nmadd;
  665. goto dcoptop;
  666. case nmsub_d_op:
  667. handler = fpemu_dp_nmsub;
  668. goto dcoptop;
  669.       dcoptop:
  670. DPFROMREG(fr, MIPSInst_FR(ir));
  671. DPFROMREG(fs, MIPSInst_FS(ir));
  672. DPFROMREG(ft, MIPSInst_FT(ir));
  673. fd = (*handler) (fr, fs, ft);
  674. DPTOREG(fd, MIPSInst_FD(ir));
  675. goto copcsr;
  676. default:
  677. return SIGILL;
  678. }
  679. break;
  680. }
  681. #endif
  682. case 0x7: /* 7 */
  683. if (MIPSInst_FUNC(ir) != pfetch_op) {
  684. return SIGILL;
  685. }
  686. /* ignore prefx operation */
  687. break;
  688. default:
  689. return SIGILL;
  690. }
  691. return 0;
  692. }
  693. #endif
  694. /*
  695.  * Emulate a single COP1 arithmetic instruction.
  696.  */
  697. static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
  698. mips_instruction ir)
  699. {
  700. int rfmt; /* resulting format */
  701. unsigned rcsr = 0; /* resulting csr */
  702. unsigned cond;
  703. union {
  704. ieee754dp d;
  705. ieee754sp s;
  706. int w;
  707. #if __mips64
  708. s64 l;
  709. #endif
  710. } rv; /* resulting value */
  711. fpuemuprivate.stats.cp1ops++;
  712. switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
  713. case s_fmt:{ /* 0 */
  714. union {
  715. ieee754sp(*b) (ieee754sp, ieee754sp);
  716. ieee754sp(*u) (ieee754sp);
  717. } handler;
  718. switch (MIPSInst_FUNC(ir)) {
  719. /* binary ops */
  720. case fadd_op:
  721. handler.b = ieee754sp_add;
  722. goto scopbop;
  723. case fsub_op:
  724. handler.b = ieee754sp_sub;
  725. goto scopbop;
  726. case fmul_op:
  727. handler.b = ieee754sp_mul;
  728. goto scopbop;
  729. case fdiv_op:
  730. handler.b = ieee754sp_div;
  731. goto scopbop;
  732. /* unary  ops */
  733. #if __mips >= 2 || __mips64
  734. case fsqrt_op:
  735. handler.u = ieee754sp_sqrt;
  736. goto scopuop;
  737. #endif
  738. #if __mips >= 4 && __mips != 32
  739. case frsqrt_op:
  740. handler.u = fpemu_sp_rsqrt;
  741. goto scopuop;
  742. case frecip_op:
  743. handler.u = fpemu_sp_recip;
  744. goto scopuop;
  745. #endif
  746. #if __mips >= 4
  747. case fmovc_op:
  748. cond = fpucondbit[MIPSInst_FT(ir) >> 2];
  749. if (((ctx->sr & cond) != 0) !=
  750. ((MIPSInst_FT(ir) & 1) != 0))
  751. return 0;
  752. SPFROMREG(rv.s, MIPSInst_FS(ir));
  753. break;
  754. case fmovz_op:
  755. if (xcp->regs[MIPSInst_FT(ir)] != 0)
  756. return 0;
  757. SPFROMREG(rv.s, MIPSInst_FS(ir));
  758. break;
  759. case fmovn_op:
  760. if (xcp->regs[MIPSInst_FT(ir)] == 0)
  761. return 0;
  762. SPFROMREG(rv.s, MIPSInst_FS(ir));
  763. break;
  764. #endif
  765. case fabs_op:
  766. handler.u = ieee754sp_abs;
  767. goto scopuop;
  768. case fneg_op:
  769. handler.u = ieee754sp_neg;
  770. goto scopuop;
  771. case fmov_op:
  772. /* an easy one */
  773. SPFROMREG(rv.s, MIPSInst_FS(ir));
  774. goto copcsr;
  775. /* binary op on handler */
  776.       scopbop:
  777. {
  778. ieee754sp fs, ft;
  779. SPFROMREG(fs, MIPSInst_FS(ir));
  780. SPFROMREG(ft, MIPSInst_FT(ir));
  781. rv.s = (*handler.b) (fs, ft);
  782. goto copcsr;
  783. }
  784.       scopuop:
  785. {
  786. ieee754sp fs;
  787. SPFROMREG(fs, MIPSInst_FS(ir));
  788. rv.s = (*handler.u) (fs);
  789. goto copcsr;
  790. }
  791.       copcsr:
  792. if (ieee754_cxtest(IEEE754_INEXACT))
  793. rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;
  794. if (ieee754_cxtest(IEEE754_UNDERFLOW))
  795. rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;
  796. if (ieee754_cxtest(IEEE754_OVERFLOW))
  797. rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;
  798. if (ieee754_cxtest(IEEE754_ZERO_DIVIDE))
  799. rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S;
  800. if (ieee754_cxtest(IEEE754_INVALID_OPERATION))
  801. rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S;
  802. break;
  803. /* unary conv ops */
  804. case fcvts_op:
  805. return SIGILL; /* not defined */
  806. case fcvtd_op:{
  807. #ifdef SINGLE_ONLY_FPU
  808. return SIGILL; /* not defined */
  809. #else
  810. ieee754sp fs;
  811. SPFROMREG(fs, MIPSInst_FS(ir));
  812. rv.d = ieee754dp_fsp(fs);
  813. rfmt = d_fmt;
  814. goto copcsr;
  815. }
  816. #endif
  817. case fcvtw_op:{
  818. ieee754sp fs;
  819. SPFROMREG(fs, MIPSInst_FS(ir));
  820. rv.w = ieee754sp_tint(fs);
  821. rfmt = w_fmt;
  822. goto copcsr;
  823. }
  824. #if __mips >= 2 || __mips64
  825. case fround_op:
  826. case ftrunc_op:
  827. case fceil_op:
  828. case ffloor_op:{
  829. unsigned int oldrm = ieee754_csr.rm;
  830. ieee754sp fs;
  831. SPFROMREG(fs, MIPSInst_FS(ir));
  832. ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
  833. rv.w = ieee754sp_tint(fs);
  834. ieee754_csr.rm = oldrm;
  835. rfmt = w_fmt;
  836. goto copcsr;
  837. }
  838. #endif /* __mips >= 2 */
  839. #if __mips64 && !defined(SINGLE_ONLY_FPU)
  840. case fcvtl_op:{
  841. ieee754sp fs;
  842. SPFROMREG(fs, MIPSInst_FS(ir));
  843. rv.l = ieee754sp_tlong(fs);
  844. rfmt = l_fmt;
  845. goto copcsr;
  846. }
  847. case froundl_op:
  848. case ftruncl_op:
  849. case fceill_op:
  850. case ffloorl_op:{
  851. unsigned int oldrm = ieee754_csr.rm;
  852. ieee754sp fs;
  853. SPFROMREG(fs, MIPSInst_FS(ir));
  854. ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
  855. rv.l = ieee754sp_tlong(fs);
  856. ieee754_csr.rm = oldrm;
  857. rfmt = l_fmt;
  858. goto copcsr;
  859. }
  860. #endif /* __mips64 && !fpu(single) */
  861. default:
  862. if (MIPSInst_FUNC(ir) >= fcmp_op) {
  863. unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
  864. ieee754sp fs, ft;
  865. SPFROMREG(fs, MIPSInst_FS(ir));
  866. SPFROMREG(ft, MIPSInst_FT(ir));
  867. rv.w = ieee754sp_cmp(fs, ft,
  868. cmptab[cmpop & 0x7], cmpop & 0x8);
  869. rfmt = -1;
  870. if ((cmpop & 0x8) && ieee754_cxtest
  871. (IEEE754_INVALID_OPERATION))
  872. rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
  873. else
  874. goto copcsr;
  875. }
  876. else {
  877. return SIGILL;
  878. }
  879. break;
  880. }
  881. break;
  882. }
  883. #ifndef SINGLE_ONLY_FPU
  884. case d_fmt:{
  885. union {
  886. ieee754dp(*b) (ieee754dp, ieee754dp);
  887. ieee754dp(*u) (ieee754dp);
  888. } handler;
  889. switch (MIPSInst_FUNC(ir)) {
  890. /* binary ops */
  891. case fadd_op:
  892. handler.b = ieee754dp_add;
  893. goto dcopbop;
  894. case fsub_op:
  895. handler.b = ieee754dp_sub;
  896. goto dcopbop;
  897. case fmul_op:
  898. handler.b = ieee754dp_mul;
  899. goto dcopbop;
  900. case fdiv_op:
  901. handler.b = ieee754dp_div;
  902. goto dcopbop;
  903. /* unary  ops */
  904. #if __mips >= 2 || __mips64
  905. case fsqrt_op:
  906. handler.u = ieee754dp_sqrt;
  907. goto dcopuop;
  908. #endif
  909. #if __mips >= 4 && __mips != 32
  910. case frsqrt_op:
  911. handler.u = fpemu_dp_rsqrt;
  912. goto dcopuop;
  913. case frecip_op:
  914. handler.u = fpemu_dp_recip;
  915. goto dcopuop;
  916. #endif
  917. #if __mips >= 4
  918. case fmovc_op:
  919. cond = fpucondbit[MIPSInst_FT(ir) >> 2];
  920. if (((ctx->sr & cond) != 0) !=
  921. ((MIPSInst_FT(ir) & 1) != 0))
  922. return 0;
  923. DPFROMREG(rv.d, MIPSInst_FS(ir));
  924. break;
  925. case fmovz_op:
  926. if (xcp->regs[MIPSInst_FT(ir)] != 0)
  927. return 0;
  928. DPFROMREG(rv.d, MIPSInst_FS(ir));
  929. break;
  930. case fmovn_op:
  931. if (xcp->regs[MIPSInst_FT(ir)] == 0)
  932. return 0;
  933. DPFROMREG(rv.d, MIPSInst_FS(ir));
  934. break;
  935. #endif
  936. case fabs_op:
  937. handler.u = ieee754dp_abs;
  938. goto dcopuop;
  939. case fneg_op:
  940. handler.u = ieee754dp_neg;
  941. goto dcopuop;
  942. case fmov_op:
  943. /* an easy one */
  944. DPFROMREG(rv.d, MIPSInst_FS(ir));
  945. goto copcsr;
  946. /* binary op on handler */
  947.       dcopbop:{
  948. ieee754dp fs, ft;
  949. DPFROMREG(fs, MIPSInst_FS(ir));
  950. DPFROMREG(ft, MIPSInst_FT(ir));
  951. rv.d = (*handler.b) (fs, ft);
  952. goto copcsr;
  953. }
  954.       dcopuop:{
  955. ieee754dp fs;
  956. DPFROMREG(fs, MIPSInst_FS(ir));
  957. rv.d = (*handler.u) (fs);
  958. goto copcsr;
  959. }
  960. /* unary conv ops */
  961. case fcvts_op:{
  962. ieee754dp fs;
  963. DPFROMREG(fs, MIPSInst_FS(ir));
  964. rv.s = ieee754sp_fdp(fs);
  965. rfmt = s_fmt;
  966. goto copcsr;
  967. }
  968. case fcvtd_op:
  969. return SIGILL; /* not defined */
  970. case fcvtw_op:{
  971. ieee754dp fs;
  972. DPFROMREG(fs, MIPSInst_FS(ir));
  973. rv.w = ieee754dp_tint(fs); /* wrong */
  974. rfmt = w_fmt;
  975. goto copcsr;
  976. }
  977. #if __mips >= 2 || __mips64
  978. case fround_op:
  979. case ftrunc_op:
  980. case fceil_op:
  981. case ffloor_op:{
  982. unsigned int oldrm = ieee754_csr.rm;
  983. ieee754dp fs;
  984. DPFROMREG(fs, MIPSInst_FS(ir));
  985. ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
  986. rv.w = ieee754dp_tint(fs);
  987. ieee754_csr.rm = oldrm;
  988. rfmt = w_fmt;
  989. goto copcsr;
  990. }
  991. #endif
  992. #if __mips64 && !defined(SINGLE_ONLY_FPU)
  993. case fcvtl_op:{
  994. ieee754dp fs;
  995. DPFROMREG(fs, MIPSInst_FS(ir));
  996. rv.l = ieee754dp_tlong(fs);
  997. rfmt = l_fmt;
  998. goto copcsr;
  999. }
  1000. case froundl_op:
  1001. case ftruncl_op:
  1002. case fceill_op:
  1003. case ffloorl_op:{
  1004. unsigned int oldrm = ieee754_csr.rm;
  1005. ieee754dp fs;
  1006. DPFROMREG(fs, MIPSInst_FS(ir));
  1007. ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
  1008. rv.l = ieee754dp_tlong(fs);
  1009. ieee754_csr.rm = oldrm;
  1010. rfmt = l_fmt;
  1011. goto copcsr;
  1012. }
  1013. #endif /* __mips >= 3 && !fpu(single) */
  1014. default:
  1015. if (MIPSInst_FUNC(ir) >= fcmp_op) {
  1016. unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
  1017. ieee754dp fs, ft;
  1018. DPFROMREG(fs, MIPSInst_FS(ir));
  1019. DPFROMREG(ft, MIPSInst_FT(ir));
  1020. rv.w = ieee754dp_cmp(fs, ft,
  1021. cmptab[cmpop & 0x7], cmpop & 0x8);
  1022. rfmt = -1;
  1023. if ((cmpop & 0x8)
  1024. &&
  1025. ieee754_cxtest
  1026. (IEEE754_INVALID_OPERATION))
  1027. rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
  1028. else
  1029. goto copcsr;
  1030. }
  1031. else {
  1032. return SIGILL;
  1033. }
  1034. break;
  1035. }
  1036. break;
  1037. }
  1038. #endif /* ifndef SINGLE_ONLY_FPU */
  1039. case w_fmt:{
  1040. ieee754sp fs;
  1041. switch (MIPSInst_FUNC(ir)) {
  1042. case fcvts_op:
  1043. /* convert word to single precision real */
  1044. SPFROMREG(fs, MIPSInst_FS(ir));
  1045. rv.s = ieee754sp_fint(fs.bits);
  1046. rfmt = s_fmt;
  1047. goto copcsr;
  1048. #ifndef SINGLE_ONLY_FPU
  1049. case fcvtd_op:
  1050. /* convert word to double precision real */
  1051. SPFROMREG(fs, MIPSInst_FS(ir));
  1052. rv.d = ieee754dp_fint(fs.bits);
  1053. rfmt = d_fmt;
  1054. goto copcsr;
  1055. #endif
  1056. default:
  1057. return SIGILL;
  1058. }
  1059. break;
  1060. }
  1061. #if __mips64 && !defined(SINGLE_ONLY_FPU)
  1062. case l_fmt:{
  1063. switch (MIPSInst_FUNC(ir)) {
  1064. case fcvts_op:
  1065. /* convert long to single precision real */
  1066. rv.s = ieee754sp_flong(ctx->regs[MIPSInst_FS(ir)]);
  1067. rfmt = s_fmt;
  1068. goto copcsr;
  1069. case fcvtd_op:
  1070. /* convert long to double precision real */
  1071. rv.d = ieee754dp_flong(ctx->regs[MIPSInst_FS(ir)]);
  1072. rfmt = d_fmt;
  1073. goto copcsr;
  1074. default:
  1075. return SIGILL;
  1076. }
  1077. break;
  1078. }
  1079. #endif
  1080. default:
  1081. return SIGILL;
  1082. }
  1083. /*
  1084.  * Update the fpu CSR register for this operation.
  1085.  * If an exception is required, generate a tidy SIGFPE exception,
  1086.  * without updating the result register.
  1087.  * Note: cause exception bits do not accumulate, they are rewritten
  1088.  * for each op; only the flag/sticky bits accumulate.
  1089.  */
  1090. ctx->sr = (ctx->sr & ~FPU_CSR_ALL_X) | rcsr;
  1091. if ((ctx->sr >> 5) & ctx->sr & FPU_CSR_ALL_E) {
  1092. /*printk ("SIGFPE: fpu csr = %08xn",ctx->sr); */
  1093. return SIGFPE;
  1094. }
  1095. /*
  1096.  * Now we can safely write the result back to the register file.
  1097.  */
  1098. switch (rfmt) {
  1099. case -1:{
  1100. #if __mips >= 4
  1101. cond = fpucondbit[MIPSInst_FD(ir) >> 2];
  1102. #else
  1103. cond = FPU_CSR_COND;
  1104. #endif
  1105. if (rv.w)
  1106. ctx->sr |= cond;
  1107. else
  1108. ctx->sr &= ~cond;
  1109. break;
  1110. }
  1111. #ifndef SINGLE_ONLY_FPU
  1112. case d_fmt:
  1113. DPTOREG(rv.d, MIPSInst_FD(ir));
  1114. break;
  1115. #endif
  1116. case s_fmt:
  1117. SPTOREG(rv.s, MIPSInst_FD(ir));
  1118. break;
  1119. case w_fmt:
  1120. SITOREG(rv.w, MIPSInst_FD(ir));
  1121. break;
  1122. #if __mips64 && !defined(SINGLE_ONLY_FPU)
  1123. case l_fmt:
  1124. DITOREG(rv.l, MIPSInst_FD(ir));
  1125. break;
  1126. #endif
  1127. default:
  1128. return SIGILL;
  1129. }
  1130. return 0;
  1131. }
  1132. int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp,
  1133. struct mips_fpu_soft_struct *ctx)
  1134. {
  1135. gpreg_t oldepc, prevepc;
  1136. mips_instruction insn, *insnp;
  1137. int sig = 0;
  1138. oldepc = xcp->cp0_epc;
  1139. do {
  1140. prevepc = xcp->cp0_epc;
  1141. /*
  1142.  * This is a braindead way to do it but the only sane way I
  1143.  * found to keep the 64-bit egcs 1.1.2 from crashing.
  1144.  */
  1145. insnp = (mips_instruction *) REG_TO_VA xcp->cp0_epc;
  1146. if (verify_area(VERIFY_READ, insnp, 4) ||
  1147. __get_user(insn, insnp)) {
  1148. fpuemuprivate.stats.errors++;
  1149. return SIGBUS;
  1150. }
  1151. if (insn == 0)
  1152. xcp->cp0_epc += 4; /* skip nops */
  1153. else {
  1154. /* Update ieee754_csr. Only relevant if we have a
  1155.    h/w FPU */
  1156. ieee754_csr.nod = (ctx->sr & 0x1000000) != 0;
  1157. ieee754_csr.rm = ieee_rm[ctx->sr & 0x3];
  1158. ieee754_csr.cx = (ctx->sr >> 12) & 0x1f;
  1159. sig = cop1Emulate(xcp, ctx);
  1160. }
  1161. if (mips_cpu.options & MIPS_CPU_FPU)
  1162. break;
  1163. if (sig)
  1164. break;
  1165. #ifdef STANDALONE_EMULATOR
  1166. if (xcptno == EX_FPE)
  1167. break;
  1168. #else
  1169. if (current->need_resched)
  1170. schedule();
  1171. #endif
  1172. } while (xcp->cp0_epc > prevepc);
  1173. /* SIGILL indicates a non-fpu instruction */
  1174. if (sig == SIGILL && xcp->cp0_epc != oldepc)
  1175. /* but if epc has advanced, then ignore it */
  1176. sig = 0;
  1177. return sig;
  1178. }