cp1emu.c 29 KB

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