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

嵌入式Linux

开发平台:

Unix_Linux

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