cp1emu.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:39k
源码类别:

嵌入式Linux

开发平台:

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 <linux/mm.h>
  38. #include <linux/signal.h>
  39. #include <linux/smp.h>
  40. #include <linux/smp_lock.h>
  41. #include <asm/asm.h>
  42. #include <asm/branch.h>
  43. #include <asm/bootinfo.h>
  44. #include <asm/byteorder.h>
  45. #include <asm/cpu.h>
  46. #include <asm/inst.h>
  47. #include <asm/uaccess.h>
  48. #include <asm/processor.h>
  49. #include <asm/mipsregs.h>
  50. #include <asm/system.h>
  51. #include <asm/pgtable.h>
  52. #include <asm/fpu_emulator.h>
  53. #include "ieee754.h"
  54. /* Strap kernel emulator for full MIPS IV emulation */
  55. #ifdef __mips
  56. #undef __mips
  57. #endif
  58. #define __mips 4
  59. typedef void *vaddr_t;
  60. /* Function which emulates the instruction in a branch delay slot. */
  61. static int mips_dsemul(struct pt_regs *, mips_instruction, vaddr_t);
  62. /* Function which emulates a floating point instruction. */
  63. static int fpu_emu(struct pt_regs *, struct mips_fpu_soft_struct *,
  64.  mips_instruction);
  65. #if __mips >= 4 && __mips != 32
  66. static int fpux_emu(struct pt_regs *,
  67.     struct mips_fpu_soft_struct *, mips_instruction);
  68. #endif
  69. /* Further private data for which no space exists in mips_fpu_soft_struct */
  70. struct mips_fpu_emulator_private fpuemuprivate;
  71. /* Control registers */
  72. #define FPCREG_RID 0 /* $0  = revision id */
  73. #define FPCREG_CSR 31 /* $31 = csr */
  74. /* Convert Mips rounding mode (0..3) to IEEE library modes. */
  75. static const unsigned char ieee_rm[4] = {
  76. IEEE754_RN, IEEE754_RZ, IEEE754_RU, IEEE754_RD
  77. };
  78. #if __mips >= 4
  79. /* convert condition code register number to csr bit */
  80. static const unsigned int fpucondbit[8] = {
  81. FPU_CSR_COND0,
  82. FPU_CSR_COND1,
  83. FPU_CSR_COND2,
  84. FPU_CSR_COND3,
  85. FPU_CSR_COND4,
  86. FPU_CSR_COND5,
  87. FPU_CSR_COND6,
  88. FPU_CSR_COND7
  89. };
  90. #endif
  91. /* 
  92.  * Redundant with logic already in kernel/branch.c,
  93.  * embedded in compute_return_epc.  At some point,
  94.  * a single subroutine should be used across both
  95.  * modules.
  96.  */
  97. static int isBranchInstr(mips_instruction * i)
  98. {
  99. switch (MIPSInst_OPCODE(*i)) {
  100. case spec_op:
  101. switch (MIPSInst_FUNC(*i)) {
  102. case jalr_op:
  103. case jr_op:
  104. return 1;
  105. }
  106. break;
  107. case bcond_op:
  108. switch (MIPSInst_RT(*i)) {
  109. case bltz_op:
  110. case bgez_op:
  111. case bltzl_op:
  112. case bgezl_op:
  113. case bltzal_op:
  114. case bgezal_op:
  115. case bltzall_op:
  116. case bgezall_op:
  117. return 1;
  118. }
  119. break;
  120. case j_op:
  121. case jal_op:
  122. case jalx_op:
  123. case beq_op:
  124. case bne_op:
  125. case blez_op:
  126. case bgtz_op:
  127. case beql_op:
  128. case bnel_op:
  129. case blezl_op:
  130. case bgtzl_op:
  131. return 1;
  132. case cop0_op:
  133. case cop1_op:
  134. case cop2_op:
  135. case cop1x_op:
  136. if (MIPSInst_RS(*i) == bc_op)
  137. return 1;
  138. break;
  139. }
  140. return 0;
  141. }
  142. #define REG_TO_VA (vaddr_t)
  143. #define VA_TO_REG (unsigned long)
  144. static unsigned long mips_get_word(struct pt_regs *xcp, void *va, int *perr)
  145. {
  146. unsigned long temp;
  147. if (!user_mode(xcp)) {
  148. *perr = 0;
  149. return (*(unsigned long *) va);
  150. }
  151. *perr = (int) get_user(temp, (unsigned long *) va);
  152. return temp;
  153. }
  154. static unsigned long long
  155. mips_get_dword(struct pt_regs *xcp, void *va, int *perr)
  156. {
  157. unsigned long long temp;
  158. if (!user_mode(xcp)) {
  159. *perr = 0;
  160. return (*(unsigned long long *) va);
  161. }
  162. *perr = (int) get_user(temp, (unsigned long long *) va);
  163. return temp;
  164. }
  165. static int mips_put_word(struct pt_regs *xcp, void *va, unsigned long val)
  166. {
  167. if (!user_mode(xcp)) {
  168. *(unsigned long *) va = val;
  169. return 0;
  170. }
  171. return put_user(val, (unsigned long *) va);
  172. }
  173. static int mips_put_dword(struct pt_regs *xcp, void *va, long long val)
  174. {
  175. if (!user_mode(xcp)) {
  176. *(unsigned long long *) va = val;
  177. return 0;
  178. }
  179. return put_user(val, (unsigned long long *) va);
  180. }
  181. /*
  182.  * In the Linux kernel, we support selection of FPR format on the
  183.  * basis of the Status.FR bit.  This does imply that, if a full 32
  184.  * FPRs are desired, there needs to be a flip-flop that can be written
  185.  * to one at that bit position.  In any case, normal MIPS ABI uses
  186.  * only the even FPRs (Status.FR = 0).
  187.  */
  188. #define CP0_STATUS_FR_SUPPORT
  189. /*
  190.  * Emulate the single floating point instruction pointed at by EPC.
  191.  * Two instructions if the instruction is in a branch delay slot.
  192.  */
  193. static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
  194. {
  195. mips_instruction ir;
  196. vaddr_t emulpc;
  197. vaddr_t contpc;
  198. unsigned int cond;
  199. int err = 0;
  200. ir = mips_get_word(xcp, REG_TO_VA xcp->cp0_epc, &err);
  201. if (err) {
  202. fpuemuprivate.stats.errors++;
  203. return SIGBUS;
  204. }
  205. /* XXX NEC Vr54xx bug workaround */
  206. if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir))
  207. xcp->cp0_cause &= ~CAUSEF_BD;
  208. if (xcp->cp0_cause & CAUSEF_BD) {
  209. /*
  210.  * The instruction to be emulated is in a branch delay slot
  211.  * which means that we have to  emulate the branch instruction
  212.  * BEFORE we do the cop1 instruction. 
  213.  *
  214.  * This branch could be a COP1 branch, but in that case we
  215.  * would have had a trap for that instruction, and would not
  216.  * come through this route.
  217.  *
  218.  * Linux MIPS branch emulator operates on context, updating the
  219.  * cp0_epc.
  220.  */
  221. emulpc = REG_TO_VA(xcp->cp0_epc + 4); /* Snapshot emulation target */
  222. if (__compute_return_epc(xcp)) {
  223. #ifdef CP1DBG
  224. printk("failed to emulate branch at %pn",
  225.     REG_TO_VA(xcp->cp0_epc));
  226. #endif
  227. return SIGILL;;
  228. }
  229. ir = mips_get_word(xcp, emulpc, &err);
  230. if (err) {
  231. fpuemuprivate.stats.errors++;
  232. return SIGBUS;
  233. }
  234. contpc = REG_TO_VA xcp->cp0_epc;
  235. } else {
  236. emulpc = REG_TO_VA xcp->cp0_epc;
  237. contpc = REG_TO_VA xcp->cp0_epc + 4;
  238. }
  239. emul:
  240. fpuemuprivate.stats.emulated++;
  241. switch (MIPSInst_OPCODE(ir)) {
  242. #ifdef CP0_STATUS_FR_SUPPORT
  243. /* R4000+ 64-bit fpu registers */
  244. #ifndef SINGLE_ONLY_FPU
  245. case ldc1_op:
  246. {
  247. void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
  248.     + MIPSInst_SIMM(ir);
  249. int ft = MIPSInst_RT(ir);
  250. if (!(xcp->cp0_status & ST0_FR))
  251. ft &= ~1;
  252. ctx->regs[ft] = mips_get_dword(xcp, va, &err);
  253. fpuemuprivate.stats.loads++;
  254. if (err) {
  255. fpuemuprivate.stats.errors++;
  256. return SIGBUS;
  257. }
  258. }
  259. break;
  260. case sdc1_op:
  261. {
  262. void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
  263.     + MIPSInst_SIMM(ir);
  264. int ft = MIPSInst_RT(ir);
  265. if (!(xcp->cp0_status & ST0_FR))
  266. ft &= ~1;
  267. fpuemuprivate.stats.stores++;
  268. if (mips_put_dword(xcp, va, ctx->regs[ft])) {
  269. fpuemuprivate.stats.errors++;
  270. return SIGBUS;
  271. }
  272. }
  273. break;
  274. #endif
  275. case lwc1_op:
  276. {
  277. void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
  278.     + MIPSInst_SIMM(ir);
  279. fpureg_t val;
  280. int ft = MIPSInst_RT(ir);
  281. fpuemuprivate.stats.loads++;
  282. val = mips_get_word(xcp, va, &err);
  283. if (err) {
  284. fpuemuprivate.stats.errors++;
  285. return SIGBUS;
  286. }
  287. if (xcp->cp0_status & ST0_FR) {
  288. /* load whole register */
  289. ctx->regs[ft] = val;
  290. } else if (ft & 1) {
  291. /* load to m.s. 32 bits */
  292. #ifdef SINGLE_ONLY_FPU
  293. /* illegal register in single-float mode */
  294. return SIGILL;
  295. #else
  296. ctx->regs[(ft & ~1)] &= 0xffffffff;
  297. ctx->regs[(ft & ~1)] |= val << 32;
  298. #endif
  299. } else {
  300. /* load to l.s. 32 bits */
  301. ctx->regs[ft] &= ~0xffffffffLL;
  302. ctx->regs[ft] |= val;
  303. }
  304. }
  305. break;
  306. case swc1_op:
  307. {
  308. void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
  309.     + MIPSInst_SIMM(ir);
  310. unsigned int val;
  311. int ft = MIPSInst_RT(ir);
  312. fpuemuprivate.stats.stores++;
  313. if (xcp->cp0_status & ST0_FR) {
  314. /* store whole register */
  315. val = ctx->regs[ft];
  316. } else if (ft & 1) {
  317. #ifdef SINGLE_ONLY_FPU
  318. /* illegal register in single-float mode */
  319. return SIGILL;
  320. #else
  321. /* store from m.s. 32 bits */
  322. val = ctx->regs[(ft & ~1)] >> 32;
  323. #endif
  324. } else {
  325. /* store from l.s. 32 bits */
  326. val = ctx->regs[ft];
  327. }
  328. if (mips_put_word(xcp, va, val)) {
  329. fpuemuprivate.stats.errors++;
  330. return SIGBUS;
  331. }
  332. }
  333. break;
  334. #else /* old 32-bit fpu registers */
  335. case lwc1_op:
  336. {
  337. void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
  338.     + MIPSInst_SIMM(ir);
  339. ctx->regs[MIPSInst_RT(ir)] =
  340.     mips_get_word(xcp, va, &err);
  341. fpuemuprivate.stats.loads++;
  342. if (err) {
  343. fpuemuprivate.stats.errors++;
  344. return SIGBUS;
  345. }
  346. }
  347. break;
  348. case swc1_op:
  349. {
  350. void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
  351.     + MIPSInst_SIMM(ir);
  352. fpuemuprivate.stats.stores++;
  353. if (mips_put_word
  354.     (xcp, va, ctx->regs[MIPSInst_RT(ir)])) {
  355. fpuemuprivate.stats.errors++;
  356. return SIGBUS;
  357. }
  358. }
  359. break;
  360. case ldc1_op:
  361. {
  362. void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
  363.     + MIPSInst_SIMM(ir);
  364. unsigned int rt = MIPSInst_RT(ir) & ~1;
  365. int errs = 0;
  366. fpuemuprivate.stats.loads++;
  367. #if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
  368. ctx->regs[rt + 1] =
  369.     mips_get_word(xcp, va + 0, &err);
  370. errs += err;
  371. ctx->regs[rt + 0] =
  372.     mips_get_word(xcp, va + 4, &err);
  373. errs += err;
  374. #else
  375. ctx->regs[rt + 0] =
  376.     mips_get_word(xcp, va + 0, &err);
  377. errs += err;
  378. ctx->regs[rt + 1] =
  379.     mips_get_word(xcp, va + 4, &err);
  380. errs += err;
  381. #endif
  382. if (err)
  383. return SIGBUS;
  384. }
  385. break;
  386. case sdc1_op:
  387. {
  388. void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
  389.     + MIPSInst_SIMM(ir);
  390. unsigned int rt = MIPSInst_RT(ir) & ~1;
  391. fpuemuprivate.stats.stores++;
  392. #if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
  393. if (mips_put_word(xcp, va + 0, ctx->regs[rt + 1]))
  394. return SIGBUS;
  395. if (mips_put_word(xcp, va + 4, ctx->regs[rt + 0]))
  396. return SIGBUS;
  397. #else
  398. if (mips_put_word(xcp, va + 0, ctx->regs[rt + 0]))
  399. return SIGBUS;
  400. if (mips_put_word(xcp, va + 4, ctx->regs[rt + 1]))
  401. return SIGBUS;
  402. #endif
  403. }
  404. break;
  405. #endif
  406. case cop1_op:
  407. switch (MIPSInst_RS(ir)) {
  408. #ifdef CP0_STATUS_FR_SUPPORT
  409. #if __mips64 && !defined(SINGLE_ONLY_FPU)
  410. case dmfc_op:
  411. /* copregister fs -> gpr[rt] */
  412. if (MIPSInst_RT(ir) != 0) {
  413. int fs = MIPSInst_RD(ir);
  414. if (!(xcp->cp0_status & ST0_FR))
  415. fs &= ~1;
  416. xcp->regs[MIPSInst_RT(ir)] = ctx->regs[fs];
  417. }
  418. break;
  419. case dmtc_op: {
  420. /* copregister fs <- rt */
  421. fpureg_t value;
  422. int fs = MIPSInst_RD(ir);
  423. if (!(xcp->cp0_status & ST0_FR))
  424. fs &= ~1;
  425. value =
  426.     (MIPSInst_RT(ir) ==
  427.      0) ? 0 : xcp->regs[MIPSInst_RT(ir)];
  428. ctx->regs[fs] = value;
  429. break;
  430. }
  431. #endif
  432. case mfc_op:
  433. /* copregister rd -> gpr[rt] */
  434. if (MIPSInst_RT(ir) != 0) {
  435. /* default value from l.s. 32 bits */
  436. int value = ctx->regs[MIPSInst_RD(ir)];
  437. if (MIPSInst_RD(ir) & 1) {
  438. #ifdef SINGLE_ONLY_FPU
  439. /* illegal register in single-float mode */
  440. return SIGILL;
  441. #else
  442. if (!(xcp->cp0_status & ST0_FR)) {
  443. /* move from m.s. 32 bits */
  444. value =
  445.     ctx->
  446.     regs[MIPSInst_RD(ir) &
  447.  ~1] >> 32;
  448. }
  449. #endif
  450. }
  451. xcp->regs[MIPSInst_RT(ir)] = value;
  452. }
  453. break;
  454. case mtc_op:
  455. /* copregister rd <- rt */
  456. {
  457. fpureg_t value;
  458. if (MIPSInst_RT(ir) == 0)
  459. value = 0;
  460. else
  461. value =
  462.     (unsigned int) xcp->
  463.     regs[MIPSInst_RT(ir)];
  464. if (MIPSInst_RD(ir) & 1) {
  465. #ifdef SINGLE_ONLY_FPU
  466. /* illegal register in single-float mode */
  467. return SIGILL;
  468. #else
  469. if (!(xcp->cp0_status & ST0_FR)) {
  470. /* move to m.s. 32 bits */
  471. ctx->
  472.     regs[
  473.  (MIPSInst_RD(ir) &
  474.   ~1)] &=
  475.     0xffffffff;
  476. ctx->
  477.     regs[
  478.  (MIPSInst_RD(ir) &
  479.   ~1)] |=
  480.     value << 32;
  481. break;
  482. }
  483. #endif
  484. }
  485. /* move to l.s. 32 bits */
  486. ctx->regs[MIPSInst_RD(ir)] &=
  487.     ~0xffffffffLL;
  488. ctx->regs[MIPSInst_RD(ir)] |= value;
  489. }
  490. break;
  491. #else
  492. case mfc_op:
  493. /* copregister rd -> gpr[rt] */
  494. if (MIPSInst_RT(ir) != 0) {
  495. unsigned value =
  496.     ctx->regs[MIPSInst_RD(ir)];
  497. xcp->regs[MIPSInst_RT(ir)] = value;
  498. }
  499. break;
  500. case mtc_op:
  501. /* copregister rd <- rt */
  502. {
  503. unsigned value;
  504. value =
  505.     (MIPSInst_RT(ir) ==
  506.      0) ? 0 : xcp->regs[MIPSInst_RT(ir)];
  507. ctx->regs[MIPSInst_RD(ir)] = value;
  508. }
  509. break;
  510. #endif
  511. case cfc_op:
  512. /* cop control register rd -> gpr[rt] */
  513. {
  514. unsigned value;
  515. if (MIPSInst_RD(ir) == FPCREG_CSR) {
  516. value = ctx->sr;
  517. #ifdef CSRTRACE
  518. printk
  519.     ("%p gpr[%d]<-csr=%08xn",
  520.      REG_TO_VA(xcp->cp0_epc),
  521.      MIPSInst_RT(ir), value);
  522. #endif
  523. } else if (MIPSInst_RD(ir) == FPCREG_RID)
  524. value = 0;
  525. else
  526. value = 0;
  527. if (MIPSInst_RT(ir))
  528. xcp->regs[MIPSInst_RT(ir)] = value;
  529. }
  530. break;
  531. case ctc_op:
  532. /* copregister rd <- rt */
  533. {
  534. unsigned value;
  535. if (MIPSInst_RT(ir) == 0)
  536. value = 0;
  537. else
  538. value = xcp->regs[MIPSInst_RT(ir)];
  539. /* we only have one writable control reg
  540.  */
  541. if (MIPSInst_RD(ir) == FPCREG_CSR) {
  542. #ifdef CSRTRACE
  543. printk
  544.     ("%p gpr[%d]->csr=%08xn",
  545.      REG_TO_VA(xcp->cp0_epc),
  546.      MIPSInst_RT(ir), value);
  547. #endif
  548. ctx->sr = value;
  549. /* copy new rounding mode to ieee library state! */
  550. ieee754_csr.rm =
  551.     ieee_rm[value & 0x3];
  552. }
  553. }
  554. break;
  555. case bc_op: {
  556. int likely = 0;
  557. if (xcp->cp0_cause & CAUSEF_BD)
  558. return SIGILL;
  559. #if __mips >= 4
  560. cond = ctx-> sr & fpucondbit[MIPSInst_RT(ir) >> 2];
  561. #else
  562. cond = ctx->sr & FPU_CSR_COND;
  563. #endif
  564. switch (MIPSInst_RT(ir) & 3) {
  565. case bcfl_op:
  566. likely = 1;
  567. case bcf_op:
  568. cond = !cond;
  569. break;
  570. case bctl_op:
  571. likely = 1;
  572. case bct_op:
  573. break;
  574. default:
  575. /* thats an illegal instruction */
  576. return SIGILL;
  577. }
  578. xcp->cp0_cause |= CAUSEF_BD;
  579. if (cond) {
  580. /* branch taken: emulate dslot instruction */
  581. xcp->cp0_epc += 4;
  582. contpc = REG_TO_VA xcp->cp0_epc +
  583.          (MIPSInst_SIMM(ir) << 2);
  584. ir = mips_get_word(xcp, REG_TO_VA(xcp->cp0_epc),
  585.       &err);
  586. if (err) {
  587. fpuemuprivate.stats.errors++;
  588. return SIGBUS;
  589. }
  590. switch (MIPSInst_OPCODE(ir)) {
  591. case lwc1_op:
  592. case swc1_op:
  593. #if (__mips >= 2 || __mips64) && !defined(SINGLE_ONLY_FPU)
  594. case ldc1_op:
  595. case sdc1_op:
  596. #endif
  597. case cop1_op:
  598. #if __mips >= 4 && __mips != 32
  599. case cop1x_op:
  600. #endif
  601. /* its one of ours */
  602. goto emul;
  603. #if __mips >= 4
  604. case spec_op:
  605. if (MIPSInst_FUNC(ir) == movc_op)
  606. goto emul;
  607. break;
  608. #endif
  609. }
  610. /*
  611.  * Single step the non-cp1 instruction in the
  612.  * dslot
  613.  */
  614. return mips_dsemul(xcp, ir, contpc);
  615. } else {
  616. /* branch not taken */
  617. if (likely)
  618. /*
  619.  * branch likely nullifies dslot if not
  620.  * taken
  621.  */
  622. xcp->cp0_epc += 4;
  623. /* else continue & execute dslot as normal insn */
  624. }
  625. break;
  626. }
  627. default: {
  628. int sig;
  629. if (!(MIPSInst_RS(ir) & 0x10))
  630. return SIGILL;
  631. /* a real fpu computation instruction */
  632. if ((sig = fpu_emu(xcp, ctx, ir)))
  633. return sig;
  634. }
  635. }
  636. break;
  637. #if __mips >= 4 && __mips != 32
  638. case cop1x_op:
  639. {
  640. int sig;
  641. if ((sig = fpux_emu(xcp, ctx, ir)))
  642. return sig;
  643. }
  644. break;
  645. #endif
  646. #if __mips >= 4
  647. case spec_op:
  648. if (MIPSInst_FUNC(ir) != movc_op)
  649. return SIGILL;
  650. cond = fpucondbit[MIPSInst_RT(ir) >> 2];
  651. if (((ctx->sr & cond) != 0) !=
  652.     ((MIPSInst_RT(ir) & 1) != 0)) return 0;
  653. xcp->regs[MIPSInst_RD(ir)] = xcp->regs[MIPSInst_RS(ir)];
  654. break;
  655. #endif
  656. default:
  657. return SIGILL;
  658. }
  659. /* we did it !! */
  660. xcp->cp0_epc = VA_TO_REG(contpc);
  661. xcp->cp0_cause &= ~CAUSEF_BD;
  662. return 0;
  663. }
  664. /*
  665.  * Emulate the arbritrary instruction ir at xcp->cp0_epc.  Required when
  666.  * we have to emulate the instruction in a COP1 branch delay slot.  Do
  667.  * not change cp0_epc due to the instruction
  668.  *
  669.  * According to the spec:
  670.  * 1) it shouldnt be a branch :-)
  671.  * 2) it can be a COP instruction :-(
  672.  * 3) if we are tring to run a protected memory space we must take
  673.  *    special care on memory access instructions :-(
  674.  */
  675. /*
  676.  * "Trampoline" return routine to catch exception following
  677.  *  execution of delay-slot instruction execution.
  678.  */
  679. int do_dsemulret(struct pt_regs *xcp)
  680. {
  681. #ifdef DSEMUL_TRACE
  682. printk("desemulretn");
  683. #endif
  684. /* Set EPC to return to post-branch instruction */
  685. xcp->cp0_epc = current->thread.dsemul_epc;
  686. /*
  687.  * Clear the state that got us here.
  688.  */
  689. current->thread.dsemul_aerpc = (unsigned long) 0;
  690. return 0;
  691. }
  692. #define AdELOAD 0x8c000001 /* lw $0,1($0) */
  693. static int
  694. mips_dsemul(struct pt_regs *xcp, mips_instruction ir, vaddr_t cpc)
  695. {
  696. mips_instruction *dsemul_insns;
  697. mips_instruction forcetrap;
  698. extern asmlinkage void handle_dsemulret(void);
  699. if (ir == 0) { /* a nop is easy */
  700. xcp->cp0_epc = VA_TO_REG(cpc);
  701. return 0;
  702. }
  703. #ifdef DSEMUL_TRACE
  704. printk("desemul %p %pn", REG_TO_VA(xcp->cp0_epc), cpc);
  705. #endif
  706. /* 
  707.  * The strategy is to push the instruction onto the user stack 
  708.  * and put a trap after it which we can catch and jump to 
  709.  * the required address any alternative apart from full 
  710.  * instruction emulation!!.
  711.  */
  712. dsemul_insns = (mips_instruction *) (xcp->regs[29] & ~3);
  713. dsemul_insns -= 3; /* Two instructions, plus one for luck ;-) */
  714. /* Verify that the stack pointer is not competely insane */
  715. if (verify_area(VERIFY_WRITE, dsemul_insns,
  716.                 sizeof(mips_instruction) * 2))
  717. return SIGBUS;
  718. if (mips_put_word(xcp, &dsemul_insns[0], ir)) {
  719. fpuemuprivate.stats.errors++;
  720. return SIGBUS;
  721. }
  722. /* 
  723.  * Algorithmics used a system call instruction, and
  724.  * borrowed that vector.  MIPS/Linux version is a bit
  725.  * more heavyweight in the interests of portability and
  726.  * multiprocessor support.  We flag the thread for special
  727.  * handling in the unaligned access handler and force an
  728.  * address error excpetion.
  729.  */
  730. /* If one is *really* paranoid, one tests for a bad stack pointer */
  731. if ((xcp->regs[29] & 0x3) == 0x3)
  732. forcetrap = AdELOAD - 1;
  733. else
  734. forcetrap = AdELOAD;
  735. if (mips_put_word(xcp, &dsemul_insns[1], forcetrap)) {
  736. fpuemuprivate.stats.errors++;
  737. return (SIGBUS);
  738. }
  739. /* Set thread state to catch and handle the exception */
  740. current->thread.dsemul_epc = (unsigned long) cpc;
  741. current->thread.dsemul_aerpc = (unsigned long) &dsemul_insns[1];
  742. xcp->cp0_epc = VA_TO_REG & dsemul_insns[0];
  743. flush_cache_sigtramp((unsigned long) dsemul_insns);
  744. return SIGILL; /* force out of emulation loop */
  745. }
  746. /* 
  747.  * Conversion table from MIPS compare ops 48-63
  748.  * cond = ieee754dp_cmp(x,y,IEEE754_UN);
  749.  */
  750. static const unsigned char cmptab[8] = {
  751. 0, /* cmp_0 (sig) cmp_sf */
  752. IEEE754_CUN, /* cmp_un (sig) cmp_ngle */
  753. IEEE754_CEQ, /* cmp_eq (sig) cmp_seq */
  754. IEEE754_CEQ | IEEE754_CUN, /* cmp_ueq (sig) cmp_ngl  */
  755. IEEE754_CLT, /* cmp_olt (sig) cmp_lt */
  756. IEEE754_CLT | IEEE754_CUN, /* cmp_ult (sig) cmp_nge */
  757. IEEE754_CLT | IEEE754_CEQ, /* cmp_ole (sig) cmp_le */
  758. IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */
  759. };
  760. #define SIFROMREG(si,x) ((si) = ctx->regs[x])
  761. #define SITOREG(si,x) (ctx->regs[x] = (int)(si))
  762. #if __mips64 && !defined(SINGLE_ONLY_FPU)
  763. #define DIFROMREG(di,x) ((di) = ctx->regs[x])
  764. #define DITOREG(di,x) (ctx->regs[x] = (di))
  765. #endif
  766. #define SPFROMREG(sp,x) ((sp).bits = ctx->regs[x])
  767. #define SPTOREG(sp,x) (ctx->regs[x] = (sp).bits)
  768. #ifdef CP0_STATUS_FR_SUPPORT
  769. #define DPFROMREG(dp,x) ((dp).bits = 
  770. ctx->regs[(xcp->cp0_status & ST0_FR) ? x : (x & ~1)])
  771. #define DPTOREG(dp,x) (ctx->regs[(xcp->cp0_status & ST0_FR) ? x : (x & ~1)]
  772. = (dp).bits)
  773. #else
  774. /* Beware: MIPS COP1 doubles are always little_word endian in registers */
  775. #define DPFROMREG(dp,x)
  776.   ((dp).bits = ((unsigned long long)ctx->regs[(x)+1] << 32) | ctx->regs[x])
  777. #define DPTOREG(dp,x) 
  778.   (ctx->regs[x] = (dp).bits, ctx->regs[(x)+1] = (dp).bits >> 32)
  779. #endif
  780. #if __mips >= 4 && __mips != 32
  781. /*
  782.  * Additional MIPS4 instructions
  783.  */
  784. static ieee754dp fpemu_dp_recip(ieee754dp d)
  785. {
  786. return ieee754dp_div(ieee754dp_one(0), d);
  787. }
  788. static ieee754dp fpemu_dp_rsqrt(ieee754dp d)
  789. {
  790. return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d));
  791. }
  792. static ieee754sp fpemu_sp_recip(ieee754sp s)
  793. {
  794. return ieee754sp_div(ieee754sp_one(0), s);
  795. }
  796. static ieee754sp fpemu_sp_rsqrt(ieee754sp s)
  797. {
  798. return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s));
  799. }
  800. static ieee754dp fpemu_dp_madd(ieee754dp r, ieee754dp s, ieee754dp t)
  801. {
  802. return ieee754dp_add(ieee754dp_mul(s, t), r);
  803. }
  804. static ieee754dp fpemu_dp_msub(ieee754dp r, ieee754dp s, ieee754dp t)
  805. {
  806. return ieee754dp_sub(ieee754dp_mul(s, t), r);
  807. }
  808. static ieee754dp fpemu_dp_nmadd(ieee754dp r, ieee754dp s, ieee754dp t)
  809. {
  810. return ieee754dp_neg(ieee754dp_add(ieee754dp_mul(s, t), r));
  811. }
  812. static ieee754dp fpemu_dp_nmsub(ieee754dp r, ieee754dp s, ieee754dp t)
  813. {
  814. return ieee754dp_neg(ieee754dp_sub(ieee754dp_mul(s, t), r));
  815. }
  816. static ieee754sp fpemu_sp_madd(ieee754sp r, ieee754sp s, ieee754sp t)
  817. {
  818. return ieee754sp_add(ieee754sp_mul(s, t), r);
  819. }
  820. static ieee754sp fpemu_sp_msub(ieee754sp r, ieee754sp s, ieee754sp t)
  821. {
  822. return ieee754sp_sub(ieee754sp_mul(s, t), r);
  823. }
  824. static ieee754sp fpemu_sp_nmadd(ieee754sp r, ieee754sp s, ieee754sp t)
  825. {
  826. return ieee754sp_neg(ieee754sp_add(ieee754sp_mul(s, t), r));
  827. }
  828. static ieee754sp fpemu_sp_nmsub(ieee754sp r, ieee754sp s, ieee754sp t)
  829. {
  830. return ieee754sp_neg(ieee754sp_sub(ieee754sp_mul(s, t), r));
  831. }
  832. static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
  833.                     mips_instruction ir)
  834. {
  835. unsigned rcsr = 0; /* resulting csr */
  836. fpuemuprivate.stats.cp1xops++;
  837. switch (MIPSInst_FMA_FFMT(ir)) {
  838. case s_fmt: /* 0 */
  839. {
  840. ieee754sp(*handler) (ieee754sp, ieee754sp,
  841.      ieee754sp);
  842. ieee754sp fd, fr, fs, ft;
  843. switch (MIPSInst_FUNC(ir)) {
  844. case lwxc1_op:
  845. {
  846. void *va =
  847.     REG_TO_VA(xcp->
  848.       regs[MIPSInst_FR(ir)]
  849.       +
  850.       xcp->
  851.       regs[MIPSInst_FT
  852.    (ir)]);
  853. fpureg_t val;
  854. int err = 0;
  855. val = mips_get_word(xcp, va, &err);
  856. if (err) {
  857. fpuemuprivate.stats.
  858.     errors++;
  859. return SIGBUS;
  860. }
  861. if (xcp->cp0_status & ST0_FR) {
  862. /* load whole register */
  863. ctx->
  864.     regs[MIPSInst_FD(ir)] =
  865.     val;
  866. } else if (MIPSInst_FD(ir) & 1) {
  867. /* load to m.s. 32 bits */
  868. #if defined(SINGLE_ONLY_FPU)
  869. /* illegal register in single-float mode */
  870. return SIGILL;
  871. #else
  872. ctx->
  873.     regs[
  874.  (MIPSInst_FD(ir) &
  875.   ~1)] &=
  876.     0xffffffff;
  877. ctx->
  878.     regs[
  879.  (MIPSInst_FD(ir) &
  880.   ~1)] |=
  881.     val << 32;
  882. #endif
  883. } else {
  884. /* load to l.s. 32 bits */
  885. ctx->
  886.     regs[MIPSInst_FD(ir)]
  887.     &= ~0xffffffffLL;
  888. ctx->
  889.     regs[MIPSInst_FD(ir)]
  890.     |= val;
  891. }
  892. }
  893. break;
  894. case swxc1_op:
  895. {
  896. void *va =
  897.     REG_TO_VA(xcp->
  898.       regs[MIPSInst_FR(ir)]
  899.       +
  900.       xcp->
  901.       regs[MIPSInst_FT
  902.    (ir)]);
  903. unsigned int val;
  904. if (xcp->cp0_status & ST0_FR) {
  905. /* store whole register */
  906. val =
  907.     ctx->
  908.     regs[MIPSInst_FS(ir)];
  909. } else if (MIPSInst_FS(ir) & 1) {
  910. #if defined(SINGLE_ONLY_FPU)
  911. /* illegal register in single-float mode */
  912. return SIGILL;
  913. #else
  914. /* store from m.s. 32 bits */
  915. val =
  916.     ctx->
  917.     regs[
  918.  (MIPSInst_FS(ir) &
  919.   ~1)] >> 32;
  920. #endif
  921. } else {
  922. /* store from l.s. 32 bits */
  923. val =
  924.     ctx->
  925.     regs[MIPSInst_FS(ir)];
  926. }
  927. if (mips_put_word(xcp, va, val)) {
  928. fpuemuprivate.stats.
  929.     errors++;
  930. return SIGBUS;
  931. }
  932. }
  933. break;
  934. case madd_s_op:
  935. handler = fpemu_sp_madd;
  936. goto scoptop;
  937. case msub_s_op:
  938. handler = fpemu_sp_msub;
  939. goto scoptop;
  940. case nmadd_s_op:
  941. handler = fpemu_sp_nmadd;
  942. goto scoptop;
  943. case nmsub_s_op:
  944. handler = fpemu_sp_nmsub;
  945. goto scoptop;
  946.       scoptop:
  947. SPFROMREG(fr, MIPSInst_FR(ir));
  948. SPFROMREG(fs, MIPSInst_FS(ir));
  949. SPFROMREG(ft, MIPSInst_FT(ir));
  950. fd = (*handler) (fr, fs, ft);
  951. SPTOREG(fd, MIPSInst_FD(ir));
  952.       copcsr:
  953. if (ieee754_cxtest(IEEE754_INEXACT))
  954. rcsr |=
  955.     FPU_CSR_INE_X | FPU_CSR_INE_S;
  956. if (ieee754_cxtest(IEEE754_UNDERFLOW))
  957. rcsr |=
  958.     FPU_CSR_UDF_X | FPU_CSR_UDF_S;
  959. if (ieee754_cxtest(IEEE754_OVERFLOW))
  960. rcsr |=
  961.     FPU_CSR_OVF_X | FPU_CSR_OVF_S;
  962. if (ieee754_cxtest
  963.     (IEEE754_INVALID_OPERATION)) rcsr |=
  964.     FPU_CSR_INV_X | FPU_CSR_INV_S;
  965. ctx->sr =
  966.     (ctx->sr & ~FPU_CSR_ALL_X) | rcsr;
  967. if ((ctx->sr >> 5) & ctx->
  968.     sr & FPU_CSR_ALL_E) {
  969. /*printk ("SIGFPE: fpu csr = %08xn",ctx->sr); */
  970. return SIGFPE;
  971. }
  972. break;
  973. default:
  974. return SIGILL;
  975. }
  976. }
  977. break;
  978. #if !defined(SINGLE_ONLY_FPU)
  979. case d_fmt: /* 1 */
  980. {
  981. ieee754dp(*handler) (ieee754dp, ieee754dp,
  982.      ieee754dp);
  983. ieee754dp fd, fr, fs, ft;
  984. switch (MIPSInst_FUNC(ir)) {
  985. case ldxc1_op:
  986. {
  987. void *va =
  988.     REG_TO_VA(xcp->
  989.       regs[MIPSInst_FR(ir)]
  990.       +
  991.       xcp->
  992.       regs[MIPSInst_FT
  993.    (ir)]);
  994. int err = 0;
  995. ctx->regs[MIPSInst_FD(ir)] =
  996.     mips_get_dword(xcp, va, &err);
  997. if (err) {
  998. fpuemuprivate.stats.
  999.     errors++;
  1000. return SIGBUS;
  1001. }
  1002. }
  1003. break;
  1004. case sdxc1_op:
  1005. {
  1006. void *va =
  1007.     REG_TO_VA(xcp->
  1008.       regs[MIPSInst_FR(ir)]
  1009.       +
  1010.       xcp->
  1011.       regs[MIPSInst_FT
  1012.    (ir)]);
  1013. if (mips_put_dword
  1014.     (xcp, va,
  1015.      ctx->regs[MIPSInst_FS(ir)])) {
  1016. fpuemuprivate.stats.
  1017.     errors++;
  1018. return SIGBUS;
  1019. }
  1020. }
  1021. break;
  1022. case madd_d_op:
  1023. handler = fpemu_dp_madd;
  1024. goto dcoptop;
  1025. case msub_d_op:
  1026. handler = fpemu_dp_msub;
  1027. goto dcoptop;
  1028. case nmadd_d_op:
  1029. handler = fpemu_dp_nmadd;
  1030. goto dcoptop;
  1031. case nmsub_d_op:
  1032. handler = fpemu_dp_nmsub;
  1033. goto dcoptop;
  1034.       dcoptop:
  1035. DPFROMREG(fr, MIPSInst_FR(ir));
  1036. DPFROMREG(fs, MIPSInst_FS(ir));
  1037. DPFROMREG(ft, MIPSInst_FT(ir));
  1038. fd = (*handler) (fr, fs, ft);
  1039. DPTOREG(fd, MIPSInst_FD(ir));
  1040. goto copcsr;
  1041. default:
  1042. return SIGILL;
  1043. }
  1044. }
  1045. break;
  1046. #endif
  1047. case 0x7: /* 7 */
  1048. {
  1049. if (MIPSInst_FUNC(ir) != pfetch_op) {
  1050. return SIGILL;
  1051. }
  1052. /* ignore prefx operation */
  1053. }
  1054. break;
  1055. default:
  1056. return SIGILL;
  1057. }
  1058. return 0;
  1059. }
  1060. #endif
  1061. /*
  1062.  * Emulate a single COP1 arithmetic instruction.
  1063.  */
  1064. static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
  1065.                    mips_instruction ir)
  1066. {
  1067. int rfmt; /* resulting format */
  1068. unsigned rcsr = 0; /* resulting csr */
  1069. unsigned cond;
  1070. union {
  1071. ieee754dp d;
  1072. ieee754sp s;
  1073. int w;
  1074. #if __mips64
  1075. long long l;
  1076. #endif
  1077. } rv; /* resulting value */
  1078. fpuemuprivate.stats.cp1ops++;
  1079. switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
  1080. case s_fmt: { /* 0 */
  1081. ieee754sp(*handler) ();
  1082. switch (MIPSInst_FUNC(ir)) {
  1083. /* binary ops */
  1084. case fadd_op:
  1085. handler = ieee754sp_add;
  1086. goto scopbop;
  1087. case fsub_op:
  1088. handler = ieee754sp_sub;
  1089. goto scopbop;
  1090. case fmul_op:
  1091. handler = ieee754sp_mul;
  1092. goto scopbop;
  1093. case fdiv_op:
  1094. handler = ieee754sp_div;
  1095. goto scopbop;
  1096. /* unary  ops */
  1097. #if __mips >= 2 || __mips64
  1098. case fsqrt_op:
  1099. handler = ieee754sp_sqrt;
  1100. goto scopuop;
  1101. #endif
  1102. #if __mips >= 4 && __mips != 32
  1103. case frsqrt_op:
  1104. handler = fpemu_sp_rsqrt;
  1105. goto scopuop;
  1106. case frecip_op:
  1107. handler = fpemu_sp_recip;
  1108. goto scopuop;
  1109. #endif
  1110. #if __mips >= 4
  1111. case fmovc_op:
  1112. cond = fpucondbit[MIPSInst_FT(ir) >> 2];
  1113. if (((ctx->sr & cond) != 0) !=
  1114.     ((MIPSInst_FT(ir) & 1) != 0))
  1115. return 0;
  1116. SPFROMREG(rv.s, MIPSInst_FS(ir));
  1117. break;
  1118. case fmovz_op:
  1119. if (xcp->regs[MIPSInst_FT(ir)] != 0)
  1120. return 0;
  1121. SPFROMREG(rv.s, MIPSInst_FS(ir));
  1122. break;
  1123. case fmovn_op:
  1124. if (xcp->regs[MIPSInst_FT(ir)] == 0)
  1125. return 0;
  1126. SPFROMREG(rv.s, MIPSInst_FS(ir));
  1127. break;
  1128. #endif
  1129. case fabs_op:
  1130. handler = ieee754sp_abs;
  1131. goto scopuop;
  1132. case fneg_op:
  1133. handler = ieee754sp_neg;
  1134. goto scopuop;
  1135. case fmov_op:
  1136. /* an easy one */
  1137. SPFROMREG(rv.s, MIPSInst_FS(ir));
  1138. break;
  1139. /* binary op on handler */
  1140. scopbop:
  1141. {
  1142. ieee754sp fs, ft;
  1143. SPFROMREG(fs, MIPSInst_FS(ir));
  1144. SPFROMREG(ft, MIPSInst_FT(ir));
  1145. rv.s = (*handler) (fs, ft);
  1146. goto copcsr;
  1147. }
  1148. scopuop:
  1149. {
  1150. ieee754sp fs;
  1151. SPFROMREG(fs, MIPSInst_FS(ir));
  1152. rv.s = (*handler) (fs);
  1153. goto copcsr;
  1154. }
  1155. copcsr:
  1156. if (ieee754_cxtest(IEEE754_INEXACT))
  1157. rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;
  1158. if (ieee754_cxtest(IEEE754_UNDERFLOW))
  1159. rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;
  1160. if (ieee754_cxtest(IEEE754_OVERFLOW))
  1161. rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;
  1162. if (ieee754_cxtest(IEEE754_ZERO_DIVIDE))
  1163. rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S;
  1164. if (ieee754_cxtest
  1165. (IEEE754_INVALID_OPERATION)) rcsr |=
  1166.     FPU_CSR_INV_X | FPU_CSR_INV_S;
  1167. break;
  1168. /* unary conv ops */
  1169. case fcvts_op:
  1170. return SIGILL; /* not defined */
  1171. case fcvtd_op: {
  1172. #ifdef SINGLE_ONLY_FPU
  1173. return SIGILL; /* not defined */
  1174. #else
  1175. ieee754sp fs;
  1176. SPFROMREG(fs, MIPSInst_FS(ir));
  1177. rv.d = ieee754dp_fsp(fs);
  1178. rfmt = d_fmt;
  1179. goto copcsr;
  1180. }
  1181. #endif
  1182. case fcvtw_op: {
  1183. ieee754sp fs;
  1184. SPFROMREG(fs, MIPSInst_FS(ir));
  1185. rv.w = ieee754sp_tint(fs);
  1186. rfmt = w_fmt;
  1187. goto copcsr;
  1188. }
  1189. #if __mips >= 2 || __mips64
  1190. case fround_op:
  1191. case ftrunc_op:
  1192. case fceil_op:
  1193. case ffloor_op: {
  1194. unsigned int oldrm = ieee754_csr.rm;
  1195. ieee754sp fs;
  1196. SPFROMREG(fs, MIPSInst_FS(ir));
  1197. ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
  1198. rv.w = ieee754sp_tint(fs);
  1199. ieee754_csr.rm = oldrm;
  1200. rfmt = w_fmt;
  1201. goto copcsr;
  1202. }
  1203. #endif /* __mips >= 2 */
  1204. #if __mips64 && !defined(SINGLE_ONLY_FPU)
  1205. case fcvtl_op: {
  1206. ieee754sp fs;
  1207. SPFROMREG(fs, MIPSInst_FS(ir));
  1208. rv.l = ieee754sp_tlong(fs);
  1209. rfmt = l_fmt;
  1210. goto copcsr;
  1211. }
  1212. case froundl_op:
  1213. case ftruncl_op:
  1214. case fceill_op:
  1215. case ffloorl_op: {
  1216. unsigned int oldrm = ieee754_csr.rm;
  1217. ieee754sp fs;
  1218. SPFROMREG(fs, MIPSInst_FS(ir));
  1219. ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
  1220. rv.l = ieee754sp_tlong(fs);
  1221. ieee754_csr.rm = oldrm;
  1222. rfmt = l_fmt;
  1223. goto copcsr;
  1224. }
  1225. #endif /* __mips64 && !fpu(single) */
  1226. default:
  1227. if (MIPSInst_FUNC(ir) >= fcmp_op) {
  1228. unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
  1229. ieee754sp fs, ft;
  1230. SPFROMREG(fs, MIPSInst_FS(ir));
  1231. SPFROMREG(ft, MIPSInst_FT(ir));
  1232. rv.w = ieee754sp_cmp(fs, ft, cmptab[cmpop & 0x7]);
  1233. rfmt = -1;
  1234. if ((cmpop & 0x8) && ieee754_cxtest(IEEE754_INVALID_OPERATION))
  1235. rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
  1236. } else {
  1237. return SIGILL;
  1238. }
  1239. break;
  1240. }
  1241. break;
  1242. }
  1243. #if !defined(SINGLE_ONLY_FPU)
  1244. case d_fmt: {
  1245. ieee754dp(*handler) ();
  1246. switch (MIPSInst_FUNC(ir)) {
  1247. /* binary ops */
  1248. case fadd_op:
  1249. handler = ieee754dp_add;
  1250. goto dcopbop;
  1251. case fsub_op:
  1252. handler = ieee754dp_sub;
  1253. goto dcopbop;
  1254. case fmul_op:
  1255. handler = ieee754dp_mul;
  1256. goto dcopbop;
  1257. case fdiv_op:
  1258. handler = ieee754dp_div;
  1259. goto dcopbop;
  1260. /* unary  ops */
  1261. #if __mips >= 2 || __mips64
  1262. case fsqrt_op:
  1263. handler = ieee754dp_sqrt;
  1264. goto dcopuop;
  1265. #endif
  1266. #if __mips >= 4 && __mips != 32
  1267. case frsqrt_op:
  1268. handler = fpemu_dp_rsqrt;
  1269. goto dcopuop;
  1270. case frecip_op:
  1271. handler = fpemu_dp_recip;
  1272. goto dcopuop;
  1273. #endif
  1274. #if __mips >= 4
  1275. case fmovc_op:
  1276. cond = fpucondbit[MIPSInst_FT(ir) >> 2];
  1277. if (((ctx->sr & cond) != 0) != ((MIPSInst_FT(ir) & 1) != 0))
  1278. return 0;
  1279. DPFROMREG(rv.d, MIPSInst_FS(ir));
  1280. break;
  1281. case fmovz_op:
  1282. if (xcp->regs[MIPSInst_FT(ir)] != 0)
  1283. return 0;
  1284. DPFROMREG(rv.d, MIPSInst_FS(ir));
  1285. break;
  1286. case fmovn_op:
  1287. if (xcp->regs[MIPSInst_FT(ir)] == 0)
  1288. return 0;
  1289. DPFROMREG(rv.d, MIPSInst_FS(ir));
  1290. break;
  1291. #endif
  1292. case fabs_op:
  1293. handler = ieee754dp_abs;
  1294. goto dcopuop;
  1295. case fneg_op:
  1296. handler = ieee754dp_neg;
  1297. goto dcopuop;
  1298. case fmov_op:
  1299. /* an easy one */
  1300. DPFROMREG(rv.d, MIPSInst_FS(ir));
  1301. break;
  1302. /* binary op on handler */
  1303. dcopbop:
  1304. {
  1305. ieee754dp fs, ft;
  1306. DPFROMREG(fs, MIPSInst_FS(ir));
  1307. DPFROMREG(ft, MIPSInst_FT(ir));
  1308. rv.d = (*handler) (fs, ft);
  1309. goto copcsr;
  1310. }
  1311. dcopuop:
  1312. {
  1313. ieee754dp fs;
  1314. DPFROMREG(fs, MIPSInst_FS(ir));
  1315. rv.d = (*handler) (fs);
  1316. goto copcsr;
  1317. }
  1318. /* unary conv ops */
  1319. case fcvts_op: {
  1320. ieee754dp fs;
  1321. DPFROMREG(fs, MIPSInst_FS(ir));
  1322. rv.s = ieee754sp_fdp(fs);
  1323. rfmt = s_fmt;
  1324. goto copcsr;
  1325. }
  1326. case fcvtd_op:
  1327. return SIGILL; /* not defined */
  1328. case fcvtw_op: {
  1329. ieee754dp fs;
  1330. DPFROMREG(fs, MIPSInst_FS(ir));
  1331. rv.w = ieee754dp_tint(fs); /* wrong */
  1332. rfmt = w_fmt;
  1333. goto copcsr;
  1334. }
  1335. #if __mips >= 2 || __mips64
  1336. case fround_op:
  1337. case ftrunc_op:
  1338. case fceil_op:
  1339. case ffloor_op: {
  1340. unsigned int oldrm = ieee754_csr.rm;
  1341. ieee754dp fs;
  1342. DPFROMREG(fs, MIPSInst_FS(ir));
  1343. ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
  1344. rv.w = ieee754dp_tint(fs);
  1345. ieee754_csr.rm = oldrm;
  1346. rfmt = w_fmt;
  1347. goto copcsr;
  1348. }
  1349. #endif
  1350. #if __mips64 && !defined(SINGLE_ONLY_FPU)
  1351. case fcvtl_op: {
  1352. ieee754dp fs;
  1353. DPFROMREG(fs, MIPSInst_FS(ir));
  1354. rv.l = ieee754dp_tlong(fs);
  1355. rfmt = l_fmt;
  1356. goto copcsr;
  1357. }
  1358. case froundl_op:
  1359. case ftruncl_op:
  1360. case fceill_op:
  1361. case ffloorl_op: {
  1362. unsigned int oldrm = ieee754_csr.rm;
  1363. ieee754dp fs;
  1364. DPFROMREG(fs, MIPSInst_FS(ir));
  1365. ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
  1366. rv.l = ieee754dp_tlong(fs);
  1367. ieee754_csr.rm = oldrm;
  1368. rfmt = l_fmt;
  1369. goto copcsr;
  1370. }
  1371. #endif /* __mips >= 3 && !fpu(single) */
  1372. default:
  1373. if (MIPSInst_FUNC(ir) >= fcmp_op) {
  1374. unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
  1375. ieee754dp fs, ft;
  1376. DPFROMREG(fs, MIPSInst_FS(ir));
  1377. DPFROMREG(ft, MIPSInst_FT(ir));
  1378. rv.w = ieee754dp_cmp(fs, ft, cmptab[cmpop & 0x7]);
  1379. rfmt = -1;
  1380. if ((cmpop & 0x8) && ieee754_cxtest (IEEE754_INVALID_OPERATION))
  1381. rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
  1382. } else {
  1383. return SIGILL;
  1384. }
  1385. break;
  1386. }
  1387. break;
  1388. }
  1389. #endif /* !defined(SINGLE_ONLY_FPU) */
  1390. case w_fmt: {
  1391. switch (MIPSInst_FUNC(ir)) {
  1392. case fcvts_op:
  1393. /* convert word to single precision real */
  1394. rv.s = ieee754sp_fint(ctx-> regs[MIPSInst_FS(ir)]);
  1395. rfmt = s_fmt;
  1396. goto copcsr;
  1397. #if !defined(SINGLE_ONLY_FPU)
  1398. case fcvtd_op:
  1399. /* convert word to double precision real */
  1400. rv.d = ieee754dp_fint(ctx-> regs[MIPSInst_FS(ir)]);
  1401. rfmt = d_fmt;
  1402. goto copcsr;
  1403. #endif
  1404. default:
  1405. return SIGILL;
  1406. }
  1407. break;
  1408. }
  1409. #if __mips64 && !defined(SINGLE_ONLY_FPU)
  1410. case l_fmt: {
  1411. switch (MIPSInst_FUNC(ir)) {
  1412. case fcvts_op:
  1413. /* convert long to single precision real */
  1414. rv.s = ieee754sp_flong(ctx-> regs[MIPSInst_FS(ir)]);
  1415. rfmt = s_fmt;
  1416. goto copcsr;
  1417. case fcvtd_op:
  1418. /* convert long to double precision real */
  1419. rv.d = ieee754dp_flong(ctx-> regs[MIPSInst_FS(ir)]);
  1420. rfmt = d_fmt;
  1421. goto copcsr;
  1422. default:
  1423. return SIGILL;
  1424. }
  1425. break;
  1426. }
  1427. #endif
  1428. default:
  1429. return SIGILL;
  1430. }
  1431. /*
  1432.  * Update the fpu CSR register for this operation.
  1433.  * If an exception is required, generate a tidy SIGFPE exception,
  1434.  * without updating the result register.
  1435.  * Note: cause exception bits do not accumulate, they are rewritten
  1436.  * for each op; only the flag/sticky bits accumulate.
  1437.  */
  1438. ctx->sr = (ctx->sr & ~FPU_CSR_ALL_X) | rcsr;
  1439. if ((ctx->sr >> 5) & ctx->sr & FPU_CSR_ALL_E) {
  1440. /*printk ("SIGFPE: fpu csr = %08xn",ctx->sr); */
  1441. return SIGFPE;
  1442. }
  1443. /* 
  1444.  * Now we can safely write the result back to the register file.
  1445.  */
  1446. switch (rfmt) {
  1447. case -1: {
  1448. #if __mips >= 4
  1449. cond = fpucondbit[MIPSInst_FD(ir) >> 2];
  1450. #else
  1451. cond = FPU_CSR_COND;
  1452. #endif
  1453. if (rv.w)
  1454. ctx->sr |= cond;
  1455. else
  1456. ctx->sr &= ~cond;
  1457. break;
  1458. }
  1459. #if !defined(SINGLE_ONLY_FPU)
  1460. case d_fmt:
  1461. DPTOREG(rv.d, MIPSInst_FD(ir));
  1462. break;
  1463. #endif
  1464. case s_fmt:
  1465. SPTOREG(rv.s, MIPSInst_FD(ir));
  1466. break;
  1467. case w_fmt:
  1468. SITOREG(rv.w, MIPSInst_FD(ir));
  1469. break;
  1470. #if __mips64 && !defined(SINGLE_ONLY_FPU)
  1471. case l_fmt:
  1472. DITOREG(rv.l, MIPSInst_FD(ir));
  1473. break;
  1474. #endif
  1475. default:
  1476. return SIGILL;
  1477. }
  1478. return 0;
  1479. }
  1480. /*
  1481.  * Emulate the floating point instruction at EPC, and continue to run until we
  1482.  * hit a non-fp instruction, or a backward branch.  This cuts down dramatically
  1483.  * on the per instruction exception overhead.
  1484.  */
  1485. int fpu_emulator_cop1Handler(struct pt_regs *xcp)
  1486. {
  1487. struct mips_fpu_soft_struct *ctx = &current->thread.fpu.soft;
  1488. unsigned long oldepc, prevepc;
  1489. unsigned int insn;
  1490. int sig = 0;
  1491. int err = 0;
  1492. oldepc = xcp->cp0_epc;
  1493. do {
  1494. if (current->need_resched)
  1495. schedule();
  1496. prevepc = xcp->cp0_epc;
  1497. insn = mips_get_word(xcp, REG_TO_VA(xcp->cp0_epc), &err);
  1498. if (err) {
  1499. fpuemuprivate.stats.errors++;
  1500. return SIGBUS;
  1501. }
  1502. if (insn != 0)
  1503. sig = cop1Emulate(xcp, ctx);
  1504. else
  1505. xcp->cp0_epc += 4; /* skip nops */
  1506. if (mips_cpu.options & MIPS_CPU_FPU)
  1507. break;
  1508. } while (xcp->cp0_epc > prevepc && sig == 0);
  1509. /* SIGILL indicates a non-fpu instruction */
  1510. if (sig == SIGILL && xcp->cp0_epc != oldepc)
  1511. /* but if epc has advanced, then ignore it */
  1512. sig = 0;
  1513. return sig;
  1514. }
  1515. #ifdef NOTDEF
  1516. /*
  1517.  * Patch up the hardware fpu state when an f.p. exception occurs.  
  1518.  */
  1519. static int cop1Patcher(int xcptno, struct pt_regs *xcp)
  1520. {
  1521. struct mips_fpu_soft_struct *ctx = &current->thread.fpu.soft;
  1522. unsigned sr;
  1523. int sig;
  1524. /* reenable Cp1, else fpe_save() will get nested exception */
  1525. sr = mips_bissr(ST0_CU1);
  1526. /* get fpu registers and status, then clear pending exceptions */
  1527. fpe_save(ctx);
  1528. fpe_setsr(ctx->sr &= ~FPU_CSR_ALL_X);
  1529. /* get current rounding mode for IEEE library, and emulate insn */
  1530. ieee754_csr.rm = ieee_rm[ctx->sr & 0x3];
  1531. sig = cop1Emulate(xcp, ctx);
  1532. /* don't return with f.p. exceptions pending */
  1533. ctx->sr &= ~FPU_CSR_ALL_X;
  1534. fpe_restore(ctx);
  1535. mips_setsr(sr);
  1536. return sig;
  1537. }
  1538. void _cop1_init(int emulate)
  1539. {
  1540. extern int _nofpu;
  1541. if (emulate) {
  1542. /* 
  1543.  * Install cop1 emulator to handle "coprocessor unusable" exception
  1544.  */
  1545. xcption(XCPTCPU, cop1Handler);
  1546. fpuemuactive = 1; /* tell dbg.c that we are in charge */
  1547. _nofpu = 0; /* tell setjmp() it "has" an fpu */
  1548. } else {
  1549. /* 
  1550.  * Install cop1 emulator for floating point exceptions only,
  1551.  * i.e. denormalised results, underflow, overflow etc, which
  1552.  * must be emulated in s/w.
  1553.  */
  1554. #ifdef 1
  1555. /* r4000 or above use dedicate exception */
  1556. xcption(XCPTFPE, cop1Patcher);
  1557. #else
  1558. /* r3000 et al use interrupt */
  1559. extern int _sbd_getfpuintr(void);
  1560. int intno = _sbd_getfpuintr();
  1561. intrupt(intno, cop1Patcher, 0);
  1562. mips_bissr(SR_IM0 << intno);
  1563. #endif
  1564. #if (#cpu(r4640) || #cpu(r4650)) && !defined(SINGLE_ONLY_FPU)
  1565. /* For R4640/R4650 compiled *without* the -msingle-float flag,
  1566.    then we share responsibility: the h/w handles the single
  1567.    precision operations, and the trap emulator handles the
  1568.    double precision. We set fpuemuactive so that dbg.c first
  1569.    fetches the s/w state before saving the h/w state. */
  1570. fpuemuactive = 1;
  1571. {
  1572. int i;
  1573. /* initialise the unused d.p high order words to be NaN */
  1574. for (i = 0; i < 32; i++)
  1575. current->thread.fpu.soft.regs[i] =
  1576.     0x7ff80bad00000000LL;
  1577. }
  1578. #endif /* (r4640 || r4650) && !fpu(single) */
  1579. }
  1580. }
  1581. #endif