cp1emu.c 29 KB

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