fpudispatch.c 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444
  1. /*
  2. * Linux/PA-RISC Project (http://www.parisc-linux.org/)
  3. *
  4. * Floating-point emulation code
  5. * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2, or (at your option)
  10. * any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. */
  21. /*
  22. * BEGIN_DESC
  23. *
  24. * File:
  25. * @(#) pa/fp/fpudispatch.c $Revision: 1.1 $
  26. *
  27. * Purpose:
  28. * <<please update with a synopsis of the functionality provided by this file>>
  29. *
  30. * External Interfaces:
  31. * <<the following list was autogenerated, please review>>
  32. * emfpudispatch(ir, dummy1, dummy2, fpregs)
  33. * fpudispatch(ir, excp_code, holder, fpregs)
  34. *
  35. * Internal Interfaces:
  36. * <<the following list was autogenerated, please review>>
  37. * static u_int decode_06(u_int, u_int *)
  38. * static u_int decode_0c(u_int, u_int, u_int, u_int *)
  39. * static u_int decode_0e(u_int, u_int, u_int, u_int *)
  40. * static u_int decode_26(u_int, u_int *)
  41. * static u_int decode_2e(u_int, u_int *)
  42. * static void update_status_cbit(u_int *, u_int, u_int, u_int)
  43. *
  44. * Theory:
  45. * <<please update with a overview of the operation of this file>>
  46. *
  47. * END_DESC
  48. */
  49. #define FPUDEBUG 0
  50. #include "float.h"
  51. #include <linux/bug.h>
  52. #include <linux/kernel.h>
  53. #include <asm/processor.h>
  54. /* #include <sys/debug.h> */
  55. /* #include <machine/sys/mdep_private.h> */
  56. #define COPR_INST 0x30000000
  57. /*
  58. * definition of extru macro. If pos and len are constants, the compiler
  59. * will generate an extru instruction when optimized
  60. */
  61. #define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1))
  62. /* definitions of bit field locations in the instruction */
  63. #define fpmajorpos 5
  64. #define fpr1pos 10
  65. #define fpr2pos 15
  66. #define fptpos 31
  67. #define fpsubpos 18
  68. #define fpclass1subpos 16
  69. #define fpclasspos 22
  70. #define fpfmtpos 20
  71. #define fpdfpos 18
  72. #define fpnulpos 26
  73. /*
  74. * the following are the extra bits for the 0E major op
  75. */
  76. #define fpxr1pos 24
  77. #define fpxr2pos 19
  78. #define fpxtpos 25
  79. #define fpxpos 23
  80. #define fp0efmtpos 20
  81. /*
  82. * the following are for the multi-ops
  83. */
  84. #define fprm1pos 10
  85. #define fprm2pos 15
  86. #define fptmpos 31
  87. #define fprapos 25
  88. #define fptapos 20
  89. #define fpmultifmt 26
  90. /*
  91. * the following are for the fused FP instructions
  92. */
  93. /* fprm1pos 10 */
  94. /* fprm2pos 15 */
  95. #define fpraupos 18
  96. #define fpxrm2pos 19
  97. /* fpfmtpos 20 */
  98. #define fpralpos 23
  99. #define fpxrm1pos 24
  100. /* fpxtpos 25 */
  101. #define fpfusedsubop 26
  102. /* fptpos 31 */
  103. /*
  104. * offset to constant zero in the FP emulation registers
  105. */
  106. #define fpzeroreg (32*sizeof(double)/sizeof(u_int))
  107. /*
  108. * extract the major opcode from the instruction
  109. */
  110. #define get_major(op) extru(op,fpmajorpos,6)
  111. /*
  112. * extract the two bit class field from the FP instruction. The class is at bit
  113. * positions 21-22
  114. */
  115. #define get_class(op) extru(op,fpclasspos,2)
  116. /*
  117. * extract the 3 bit subop field. For all but class 1 instructions, it is
  118. * located at bit positions 16-18
  119. */
  120. #define get_subop(op) extru(op,fpsubpos,3)
  121. /*
  122. * extract the 2 or 3 bit subop field from class 1 instructions. It is located
  123. * at bit positions 15-16 (PA1.1) or 14-16 (PA2.0)
  124. */
  125. #define get_subop1_PA1_1(op) extru(op,fpclass1subpos,2) /* PA89 (1.1) fmt */
  126. #define get_subop1_PA2_0(op) extru(op,fpclass1subpos,3) /* PA 2.0 fmt */
  127. /* definitions of unimplemented exceptions */
  128. #define MAJOR_0C_EXCP 0x09
  129. #define MAJOR_0E_EXCP 0x0b
  130. #define MAJOR_06_EXCP 0x03
  131. #define MAJOR_26_EXCP 0x23
  132. #define MAJOR_2E_EXCP 0x2b
  133. #define PA83_UNIMP_EXCP 0x01
  134. /*
  135. * Special Defines for TIMEX specific code
  136. */
  137. #define FPU_TYPE_FLAG_POS (EM_FPU_TYPE_OFFSET>>2)
  138. #define TIMEX_ROLEX_FPU_MASK (TIMEX_EXTEN_FLAG|ROLEX_EXTEN_FLAG)
  139. /*
  140. * Static function definitions
  141. */
  142. #define _PROTOTYPES
  143. #if defined(_PROTOTYPES) || defined(_lint)
  144. static u_int decode_0c(u_int, u_int, u_int, u_int *);
  145. static u_int decode_0e(u_int, u_int, u_int, u_int *);
  146. static u_int decode_06(u_int, u_int *);
  147. static u_int decode_26(u_int, u_int *);
  148. static u_int decode_2e(u_int, u_int *);
  149. static void update_status_cbit(u_int *, u_int, u_int, u_int);
  150. #else /* !_PROTOTYPES&&!_lint */
  151. static u_int decode_0c();
  152. static u_int decode_0e();
  153. static u_int decode_06();
  154. static u_int decode_26();
  155. static u_int decode_2e();
  156. static void update_status_cbit();
  157. #endif /* _PROTOTYPES&&!_lint */
  158. #define VASSERT(x)
  159. static void parisc_linux_get_fpu_type(u_int fpregs[])
  160. {
  161. /* on pa-linux the fpu type is not filled in by the
  162. * caller; it is constructed here
  163. */
  164. if (boot_cpu_data.cpu_type == pcxs)
  165. fpregs[FPU_TYPE_FLAG_POS] = TIMEX_EXTEN_FLAG;
  166. else if (boot_cpu_data.cpu_type == pcxt ||
  167. boot_cpu_data.cpu_type == pcxt_)
  168. fpregs[FPU_TYPE_FLAG_POS] = ROLEX_EXTEN_FLAG;
  169. else if (boot_cpu_data.cpu_type >= pcxu)
  170. fpregs[FPU_TYPE_FLAG_POS] = PA2_0_FPU_FLAG;
  171. }
  172. /*
  173. * this routine will decode the excepting floating point instruction and
  174. * call the approiate emulation routine.
  175. * It is called by decode_fpu with the following parameters:
  176. * fpudispatch(current_ir, unimplemented_code, 0, &Fpu_register)
  177. * where current_ir is the instruction to be emulated,
  178. * unimplemented_code is the exception_code that the hardware generated
  179. * and &Fpu_register is the address of emulated FP reg 0.
  180. */
  181. u_int
  182. fpudispatch(u_int ir, u_int excp_code, u_int holder, u_int fpregs[])
  183. {
  184. u_int class, subop;
  185. u_int fpu_type_flags;
  186. /* All FP emulation code assumes that ints are 4-bytes in length */
  187. VASSERT(sizeof(int) == 4);
  188. parisc_linux_get_fpu_type(fpregs);
  189. fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */
  190. class = get_class(ir);
  191. if (class == 1) {
  192. if (fpu_type_flags & PA2_0_FPU_FLAG)
  193. subop = get_subop1_PA2_0(ir);
  194. else
  195. subop = get_subop1_PA1_1(ir);
  196. }
  197. else
  198. subop = get_subop(ir);
  199. if (FPUDEBUG) printk("class %d subop %d\n", class, subop);
  200. switch (excp_code) {
  201. case MAJOR_0C_EXCP:
  202. case PA83_UNIMP_EXCP:
  203. return(decode_0c(ir,class,subop,fpregs));
  204. case MAJOR_0E_EXCP:
  205. return(decode_0e(ir,class,subop,fpregs));
  206. case MAJOR_06_EXCP:
  207. return(decode_06(ir,fpregs));
  208. case MAJOR_26_EXCP:
  209. return(decode_26(ir,fpregs));
  210. case MAJOR_2E_EXCP:
  211. return(decode_2e(ir,fpregs));
  212. default:
  213. /* "crashme Night Gallery painting nr 2. (asm_crash.s).
  214. * This was fixed for multi-user kernels, but
  215. * workstation kernels had a panic here. This allowed
  216. * any arbitrary user to panic the kernel by executing
  217. * setting the FP exception registers to strange values
  218. * and generating an emulation trap. The emulation and
  219. * exception code must never be able to panic the
  220. * kernel.
  221. */
  222. return(UNIMPLEMENTEDEXCEPTION);
  223. }
  224. }
  225. /*
  226. * this routine is called by $emulation_trap to emulate a coprocessor
  227. * instruction if one doesn't exist
  228. */
  229. u_int
  230. emfpudispatch(u_int ir, u_int dummy1, u_int dummy2, u_int fpregs[])
  231. {
  232. u_int class, subop, major;
  233. u_int fpu_type_flags;
  234. /* All FP emulation code assumes that ints are 4-bytes in length */
  235. VASSERT(sizeof(int) == 4);
  236. fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */
  237. major = get_major(ir);
  238. class = get_class(ir);
  239. if (class == 1) {
  240. if (fpu_type_flags & PA2_0_FPU_FLAG)
  241. subop = get_subop1_PA2_0(ir);
  242. else
  243. subop = get_subop1_PA1_1(ir);
  244. }
  245. else
  246. subop = get_subop(ir);
  247. switch (major) {
  248. case 0x0C:
  249. return(decode_0c(ir,class,subop,fpregs));
  250. case 0x0E:
  251. return(decode_0e(ir,class,subop,fpregs));
  252. case 0x06:
  253. return(decode_06(ir,fpregs));
  254. case 0x26:
  255. return(decode_26(ir,fpregs));
  256. case 0x2E:
  257. return(decode_2e(ir,fpregs));
  258. default:
  259. return(PA83_UNIMP_EXCP);
  260. }
  261. }
  262. static u_int
  263. decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
  264. {
  265. u_int r1,r2,t; /* operand register offsets */
  266. u_int fmt; /* also sf for class 1 conversions */
  267. u_int df; /* for class 1 conversions */
  268. u_int *status;
  269. u_int retval, local_status;
  270. u_int fpu_type_flags;
  271. if (ir == COPR_INST) {
  272. fpregs[0] = EMULATION_VERSION << 11;
  273. return(NOEXCEPTION);
  274. }
  275. status = &fpregs[0]; /* fp status register */
  276. local_status = fpregs[0]; /* and local copy */
  277. r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(u_int);
  278. if (r1 == 0) /* map fr0 source to constant zero */
  279. r1 = fpzeroreg;
  280. t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);
  281. if (t == 0 && class != 2) /* don't allow fr0 as a dest */
  282. return(MAJOR_0C_EXCP);
  283. fmt = extru(ir,fpfmtpos,2); /* get fmt completer */
  284. switch (class) {
  285. case 0:
  286. switch (subop) {
  287. case 0: /* COPR 0,0 emulated above*/
  288. case 1:
  289. return(MAJOR_0C_EXCP);
  290. case 2: /* FCPY */
  291. switch (fmt) {
  292. case 2: /* illegal */
  293. return(MAJOR_0C_EXCP);
  294. case 3: /* quad */
  295. t &= ~3; /* force to even reg #s */
  296. r1 &= ~3;
  297. fpregs[t+3] = fpregs[r1+3];
  298. fpregs[t+2] = fpregs[r1+2];
  299. case 1: /* double */
  300. fpregs[t+1] = fpregs[r1+1];
  301. case 0: /* single */
  302. fpregs[t] = fpregs[r1];
  303. return(NOEXCEPTION);
  304. }
  305. case 3: /* FABS */
  306. switch (fmt) {
  307. case 2: /* illegal */
  308. return(MAJOR_0C_EXCP);
  309. case 3: /* quad */
  310. t &= ~3; /* force to even reg #s */
  311. r1 &= ~3;
  312. fpregs[t+3] = fpregs[r1+3];
  313. fpregs[t+2] = fpregs[r1+2];
  314. case 1: /* double */
  315. fpregs[t+1] = fpregs[r1+1];
  316. case 0: /* single */
  317. /* copy and clear sign bit */
  318. fpregs[t] = fpregs[r1] & 0x7fffffff;
  319. return(NOEXCEPTION);
  320. }
  321. case 6: /* FNEG */
  322. switch (fmt) {
  323. case 2: /* illegal */
  324. return(MAJOR_0C_EXCP);
  325. case 3: /* quad */
  326. t &= ~3; /* force to even reg #s */
  327. r1 &= ~3;
  328. fpregs[t+3] = fpregs[r1+3];
  329. fpregs[t+2] = fpregs[r1+2];
  330. case 1: /* double */
  331. fpregs[t+1] = fpregs[r1+1];
  332. case 0: /* single */
  333. /* copy and invert sign bit */
  334. fpregs[t] = fpregs[r1] ^ 0x80000000;
  335. return(NOEXCEPTION);
  336. }
  337. case 7: /* FNEGABS */
  338. switch (fmt) {
  339. case 2: /* illegal */
  340. return(MAJOR_0C_EXCP);
  341. case 3: /* quad */
  342. t &= ~3; /* force to even reg #s */
  343. r1 &= ~3;
  344. fpregs[t+3] = fpregs[r1+3];
  345. fpregs[t+2] = fpregs[r1+2];
  346. case 1: /* double */
  347. fpregs[t+1] = fpregs[r1+1];
  348. case 0: /* single */
  349. /* copy and set sign bit */
  350. fpregs[t] = fpregs[r1] | 0x80000000;
  351. return(NOEXCEPTION);
  352. }
  353. case 4: /* FSQRT */
  354. switch (fmt) {
  355. case 0:
  356. return(sgl_fsqrt(&fpregs[r1],0,
  357. &fpregs[t],status));
  358. case 1:
  359. return(dbl_fsqrt(&fpregs[r1],0,
  360. &fpregs[t],status));
  361. case 2:
  362. case 3: /* quad not implemented */
  363. return(MAJOR_0C_EXCP);
  364. }
  365. case 5: /* FRND */
  366. switch (fmt) {
  367. case 0:
  368. return(sgl_frnd(&fpregs[r1],0,
  369. &fpregs[t],status));
  370. case 1:
  371. return(dbl_frnd(&fpregs[r1],0,
  372. &fpregs[t],status));
  373. case 2:
  374. case 3: /* quad not implemented */
  375. return(MAJOR_0C_EXCP);
  376. }
  377. } /* end of switch (subop) */
  378. case 1: /* class 1 */
  379. df = extru(ir,fpdfpos,2); /* get dest format */
  380. if ((df & 2) || (fmt & 2)) {
  381. /*
  382. * fmt's 2 and 3 are illegal of not implemented
  383. * quad conversions
  384. */
  385. return(MAJOR_0C_EXCP);
  386. }
  387. /*
  388. * encode source and dest formats into 2 bits.
  389. * high bit is source, low bit is dest.
  390. * bit = 1 --> double precision
  391. */
  392. fmt = (fmt << 1) | df;
  393. switch (subop) {
  394. case 0: /* FCNVFF */
  395. switch(fmt) {
  396. case 0: /* sgl/sgl */
  397. return(MAJOR_0C_EXCP);
  398. case 1: /* sgl/dbl */
  399. return(sgl_to_dbl_fcnvff(&fpregs[r1],0,
  400. &fpregs[t],status));
  401. case 2: /* dbl/sgl */
  402. return(dbl_to_sgl_fcnvff(&fpregs[r1],0,
  403. &fpregs[t],status));
  404. case 3: /* dbl/dbl */
  405. return(MAJOR_0C_EXCP);
  406. }
  407. case 1: /* FCNVXF */
  408. switch(fmt) {
  409. case 0: /* sgl/sgl */
  410. return(sgl_to_sgl_fcnvxf(&fpregs[r1],0,
  411. &fpregs[t],status));
  412. case 1: /* sgl/dbl */
  413. return(sgl_to_dbl_fcnvxf(&fpregs[r1],0,
  414. &fpregs[t],status));
  415. case 2: /* dbl/sgl */
  416. return(dbl_to_sgl_fcnvxf(&fpregs[r1],0,
  417. &fpregs[t],status));
  418. case 3: /* dbl/dbl */
  419. return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
  420. &fpregs[t],status));
  421. }
  422. case 2: /* FCNVFX */
  423. switch(fmt) {
  424. case 0: /* sgl/sgl */
  425. return(sgl_to_sgl_fcnvfx(&fpregs[r1],0,
  426. &fpregs[t],status));
  427. case 1: /* sgl/dbl */
  428. return(sgl_to_dbl_fcnvfx(&fpregs[r1],0,
  429. &fpregs[t],status));
  430. case 2: /* dbl/sgl */
  431. return(dbl_to_sgl_fcnvfx(&fpregs[r1],0,
  432. &fpregs[t],status));
  433. case 3: /* dbl/dbl */
  434. return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
  435. &fpregs[t],status));
  436. }
  437. case 3: /* FCNVFXT */
  438. switch(fmt) {
  439. case 0: /* sgl/sgl */
  440. return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0,
  441. &fpregs[t],status));
  442. case 1: /* sgl/dbl */
  443. return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0,
  444. &fpregs[t],status));
  445. case 2: /* dbl/sgl */
  446. return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0,
  447. &fpregs[t],status));
  448. case 3: /* dbl/dbl */
  449. return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
  450. &fpregs[t],status));
  451. }
  452. case 5: /* FCNVUF (PA2.0 only) */
  453. switch(fmt) {
  454. case 0: /* sgl/sgl */
  455. return(sgl_to_sgl_fcnvuf(&fpregs[r1],0,
  456. &fpregs[t],status));
  457. case 1: /* sgl/dbl */
  458. return(sgl_to_dbl_fcnvuf(&fpregs[r1],0,
  459. &fpregs[t],status));
  460. case 2: /* dbl/sgl */
  461. return(dbl_to_sgl_fcnvuf(&fpregs[r1],0,
  462. &fpregs[t],status));
  463. case 3: /* dbl/dbl */
  464. return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
  465. &fpregs[t],status));
  466. }
  467. case 6: /* FCNVFU (PA2.0 only) */
  468. switch(fmt) {
  469. case 0: /* sgl/sgl */
  470. return(sgl_to_sgl_fcnvfu(&fpregs[r1],0,
  471. &fpregs[t],status));
  472. case 1: /* sgl/dbl */
  473. return(sgl_to_dbl_fcnvfu(&fpregs[r1],0,
  474. &fpregs[t],status));
  475. case 2: /* dbl/sgl */
  476. return(dbl_to_sgl_fcnvfu(&fpregs[r1],0,
  477. &fpregs[t],status));
  478. case 3: /* dbl/dbl */
  479. return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
  480. &fpregs[t],status));
  481. }
  482. case 7: /* FCNVFUT (PA2.0 only) */
  483. switch(fmt) {
  484. case 0: /* sgl/sgl */
  485. return(sgl_to_sgl_fcnvfut(&fpregs[r1],0,
  486. &fpregs[t],status));
  487. case 1: /* sgl/dbl */
  488. return(sgl_to_dbl_fcnvfut(&fpregs[r1],0,
  489. &fpregs[t],status));
  490. case 2: /* dbl/sgl */
  491. return(dbl_to_sgl_fcnvfut(&fpregs[r1],0,
  492. &fpregs[t],status));
  493. case 3: /* dbl/dbl */
  494. return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
  495. &fpregs[t],status));
  496. }
  497. case 4: /* undefined */
  498. return(MAJOR_0C_EXCP);
  499. } /* end of switch subop */
  500. case 2: /* class 2 */
  501. fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
  502. r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(u_int);
  503. if (r2 == 0)
  504. r2 = fpzeroreg;
  505. if (fpu_type_flags & PA2_0_FPU_FLAG) {
  506. /* FTEST if nullify bit set, otherwise FCMP */
  507. if (extru(ir, fpnulpos, 1)) { /* FTEST */
  508. switch (fmt) {
  509. case 0:
  510. /*
  511. * arg0 is not used
  512. * second param is the t field used for
  513. * ftest,acc and ftest,rej
  514. * third param is the subop (y-field)
  515. */
  516. BUG();
  517. /* Unsupported
  518. * return(ftest(0L,extru(ir,fptpos,5),
  519. * &fpregs[0],subop));
  520. */
  521. case 1:
  522. case 2:
  523. case 3:
  524. return(MAJOR_0C_EXCP);
  525. }
  526. } else { /* FCMP */
  527. switch (fmt) {
  528. case 0:
  529. retval = sgl_fcmp(&fpregs[r1],
  530. &fpregs[r2],extru(ir,fptpos,5),
  531. &local_status);
  532. update_status_cbit(status,local_status,
  533. fpu_type_flags, subop);
  534. return(retval);
  535. case 1:
  536. retval = dbl_fcmp(&fpregs[r1],
  537. &fpregs[r2],extru(ir,fptpos,5),
  538. &local_status);
  539. update_status_cbit(status,local_status,
  540. fpu_type_flags, subop);
  541. return(retval);
  542. case 2: /* illegal */
  543. case 3: /* quad not implemented */
  544. return(MAJOR_0C_EXCP);
  545. }
  546. }
  547. } /* end of if for PA2.0 */
  548. else { /* PA1.0 & PA1.1 */
  549. switch (subop) {
  550. case 2:
  551. case 3:
  552. case 4:
  553. case 5:
  554. case 6:
  555. case 7:
  556. return(MAJOR_0C_EXCP);
  557. case 0: /* FCMP */
  558. switch (fmt) {
  559. case 0:
  560. retval = sgl_fcmp(&fpregs[r1],
  561. &fpregs[r2],extru(ir,fptpos,5),
  562. &local_status);
  563. update_status_cbit(status,local_status,
  564. fpu_type_flags, subop);
  565. return(retval);
  566. case 1:
  567. retval = dbl_fcmp(&fpregs[r1],
  568. &fpregs[r2],extru(ir,fptpos,5),
  569. &local_status);
  570. update_status_cbit(status,local_status,
  571. fpu_type_flags, subop);
  572. return(retval);
  573. case 2: /* illegal */
  574. case 3: /* quad not implemented */
  575. return(MAJOR_0C_EXCP);
  576. }
  577. case 1: /* FTEST */
  578. switch (fmt) {
  579. case 0:
  580. /*
  581. * arg0 is not used
  582. * second param is the t field used for
  583. * ftest,acc and ftest,rej
  584. * third param is the subop (y-field)
  585. */
  586. BUG();
  587. /* unsupported
  588. * return(ftest(0L,extru(ir,fptpos,5),
  589. * &fpregs[0],subop));
  590. */
  591. case 1:
  592. case 2:
  593. case 3:
  594. return(MAJOR_0C_EXCP);
  595. }
  596. } /* end of switch subop */
  597. } /* end of else for PA1.0 & PA1.1 */
  598. case 3: /* class 3 */
  599. r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(u_int);
  600. if (r2 == 0)
  601. r2 = fpzeroreg;
  602. switch (subop) {
  603. case 5:
  604. case 6:
  605. case 7:
  606. return(MAJOR_0C_EXCP);
  607. case 0: /* FADD */
  608. switch (fmt) {
  609. case 0:
  610. return(sgl_fadd(&fpregs[r1],&fpregs[r2],
  611. &fpregs[t],status));
  612. case 1:
  613. return(dbl_fadd(&fpregs[r1],&fpregs[r2],
  614. &fpregs[t],status));
  615. case 2: /* illegal */
  616. case 3: /* quad not implemented */
  617. return(MAJOR_0C_EXCP);
  618. }
  619. case 1: /* FSUB */
  620. switch (fmt) {
  621. case 0:
  622. return(sgl_fsub(&fpregs[r1],&fpregs[r2],
  623. &fpregs[t],status));
  624. case 1:
  625. return(dbl_fsub(&fpregs[r1],&fpregs[r2],
  626. &fpregs[t],status));
  627. case 2: /* illegal */
  628. case 3: /* quad not implemented */
  629. return(MAJOR_0C_EXCP);
  630. }
  631. case 2: /* FMPY */
  632. switch (fmt) {
  633. case 0:
  634. return(sgl_fmpy(&fpregs[r1],&fpregs[r2],
  635. &fpregs[t],status));
  636. case 1:
  637. return(dbl_fmpy(&fpregs[r1],&fpregs[r2],
  638. &fpregs[t],status));
  639. case 2: /* illegal */
  640. case 3: /* quad not implemented */
  641. return(MAJOR_0C_EXCP);
  642. }
  643. case 3: /* FDIV */
  644. switch (fmt) {
  645. case 0:
  646. return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
  647. &fpregs[t],status));
  648. case 1:
  649. return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
  650. &fpregs[t],status));
  651. case 2: /* illegal */
  652. case 3: /* quad not implemented */
  653. return(MAJOR_0C_EXCP);
  654. }
  655. case 4: /* FREM */
  656. switch (fmt) {
  657. case 0:
  658. return(sgl_frem(&fpregs[r1],&fpregs[r2],
  659. &fpregs[t],status));
  660. case 1:
  661. return(dbl_frem(&fpregs[r1],&fpregs[r2],
  662. &fpregs[t],status));
  663. case 2: /* illegal */
  664. case 3: /* quad not implemented */
  665. return(MAJOR_0C_EXCP);
  666. }
  667. } /* end of class 3 switch */
  668. } /* end of switch(class) */
  669. /* If we get here, something is really wrong! */
  670. return(MAJOR_0C_EXCP);
  671. }
  672. static u_int
  673. decode_0e(ir,class,subop,fpregs)
  674. u_int ir,class,subop;
  675. u_int fpregs[];
  676. {
  677. u_int r1,r2,t; /* operand register offsets */
  678. u_int fmt; /* also sf for class 1 conversions */
  679. u_int df; /* dest format for class 1 conversions */
  680. u_int *status;
  681. u_int retval, local_status;
  682. u_int fpu_type_flags;
  683. status = &fpregs[0];
  684. local_status = fpregs[0];
  685. r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1)));
  686. if (r1 == 0)
  687. r1 = fpzeroreg;
  688. t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
  689. if (t == 0 && class != 2)
  690. return(MAJOR_0E_EXCP);
  691. if (class < 2) /* class 0 or 1 has 2 bit fmt */
  692. fmt = extru(ir,fpfmtpos,2);
  693. else /* class 2 and 3 have 1 bit fmt */
  694. fmt = extru(ir,fp0efmtpos,1);
  695. /*
  696. * An undefined combination, double precision accessing the
  697. * right half of a FPR, can get us into trouble.
  698. * Let's just force proper alignment on it.
  699. */
  700. if (fmt == DBL) {
  701. r1 &= ~1;
  702. if (class != 1)
  703. t &= ~1;
  704. }
  705. switch (class) {
  706. case 0:
  707. switch (subop) {
  708. case 0: /* unimplemented */
  709. case 1:
  710. return(MAJOR_0E_EXCP);
  711. case 2: /* FCPY */
  712. switch (fmt) {
  713. case 2:
  714. case 3:
  715. return(MAJOR_0E_EXCP);
  716. case 1: /* double */
  717. fpregs[t+1] = fpregs[r1+1];
  718. case 0: /* single */
  719. fpregs[t] = fpregs[r1];
  720. return(NOEXCEPTION);
  721. }
  722. case 3: /* FABS */
  723. switch (fmt) {
  724. case 2:
  725. case 3:
  726. return(MAJOR_0E_EXCP);
  727. case 1: /* double */
  728. fpregs[t+1] = fpregs[r1+1];
  729. case 0: /* single */
  730. fpregs[t] = fpregs[r1] & 0x7fffffff;
  731. return(NOEXCEPTION);
  732. }
  733. case 6: /* FNEG */
  734. switch (fmt) {
  735. case 2:
  736. case 3:
  737. return(MAJOR_0E_EXCP);
  738. case 1: /* double */
  739. fpregs[t+1] = fpregs[r1+1];
  740. case 0: /* single */
  741. fpregs[t] = fpregs[r1] ^ 0x80000000;
  742. return(NOEXCEPTION);
  743. }
  744. case 7: /* FNEGABS */
  745. switch (fmt) {
  746. case 2:
  747. case 3:
  748. return(MAJOR_0E_EXCP);
  749. case 1: /* double */
  750. fpregs[t+1] = fpregs[r1+1];
  751. case 0: /* single */
  752. fpregs[t] = fpregs[r1] | 0x80000000;
  753. return(NOEXCEPTION);
  754. }
  755. case 4: /* FSQRT */
  756. switch (fmt) {
  757. case 0:
  758. return(sgl_fsqrt(&fpregs[r1],0,
  759. &fpregs[t], status));
  760. case 1:
  761. return(dbl_fsqrt(&fpregs[r1],0,
  762. &fpregs[t], status));
  763. case 2:
  764. case 3:
  765. return(MAJOR_0E_EXCP);
  766. }
  767. case 5: /* FRMD */
  768. switch (fmt) {
  769. case 0:
  770. return(sgl_frnd(&fpregs[r1],0,
  771. &fpregs[t], status));
  772. case 1:
  773. return(dbl_frnd(&fpregs[r1],0,
  774. &fpregs[t], status));
  775. case 2:
  776. case 3:
  777. return(MAJOR_0E_EXCP);
  778. }
  779. } /* end of switch (subop */
  780. case 1: /* class 1 */
  781. df = extru(ir,fpdfpos,2); /* get dest format */
  782. /*
  783. * Fix Crashme problem (writing to 31R in double precision)
  784. * here too.
  785. */
  786. if (df == DBL) {
  787. t &= ~1;
  788. }
  789. if ((df & 2) || (fmt & 2))
  790. return(MAJOR_0E_EXCP);
  791. fmt = (fmt << 1) | df;
  792. switch (subop) {
  793. case 0: /* FCNVFF */
  794. switch(fmt) {
  795. case 0: /* sgl/sgl */
  796. return(MAJOR_0E_EXCP);
  797. case 1: /* sgl/dbl */
  798. return(sgl_to_dbl_fcnvff(&fpregs[r1],0,
  799. &fpregs[t],status));
  800. case 2: /* dbl/sgl */
  801. return(dbl_to_sgl_fcnvff(&fpregs[r1],0,
  802. &fpregs[t],status));
  803. case 3: /* dbl/dbl */
  804. return(MAJOR_0E_EXCP);
  805. }
  806. case 1: /* FCNVXF */
  807. switch(fmt) {
  808. case 0: /* sgl/sgl */
  809. return(sgl_to_sgl_fcnvxf(&fpregs[r1],0,
  810. &fpregs[t],status));
  811. case 1: /* sgl/dbl */
  812. return(sgl_to_dbl_fcnvxf(&fpregs[r1],0,
  813. &fpregs[t],status));
  814. case 2: /* dbl/sgl */
  815. return(dbl_to_sgl_fcnvxf(&fpregs[r1],0,
  816. &fpregs[t],status));
  817. case 3: /* dbl/dbl */
  818. return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
  819. &fpregs[t],status));
  820. }
  821. case 2: /* FCNVFX */
  822. switch(fmt) {
  823. case 0: /* sgl/sgl */
  824. return(sgl_to_sgl_fcnvfx(&fpregs[r1],0,
  825. &fpregs[t],status));
  826. case 1: /* sgl/dbl */
  827. return(sgl_to_dbl_fcnvfx(&fpregs[r1],0,
  828. &fpregs[t],status));
  829. case 2: /* dbl/sgl */
  830. return(dbl_to_sgl_fcnvfx(&fpregs[r1],0,
  831. &fpregs[t],status));
  832. case 3: /* dbl/dbl */
  833. return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
  834. &fpregs[t],status));
  835. }
  836. case 3: /* FCNVFXT */
  837. switch(fmt) {
  838. case 0: /* sgl/sgl */
  839. return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0,
  840. &fpregs[t],status));
  841. case 1: /* sgl/dbl */
  842. return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0,
  843. &fpregs[t],status));
  844. case 2: /* dbl/sgl */
  845. return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0,
  846. &fpregs[t],status));
  847. case 3: /* dbl/dbl */
  848. return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
  849. &fpregs[t],status));
  850. }
  851. case 5: /* FCNVUF (PA2.0 only) */
  852. switch(fmt) {
  853. case 0: /* sgl/sgl */
  854. return(sgl_to_sgl_fcnvuf(&fpregs[r1],0,
  855. &fpregs[t],status));
  856. case 1: /* sgl/dbl */
  857. return(sgl_to_dbl_fcnvuf(&fpregs[r1],0,
  858. &fpregs[t],status));
  859. case 2: /* dbl/sgl */
  860. return(dbl_to_sgl_fcnvuf(&fpregs[r1],0,
  861. &fpregs[t],status));
  862. case 3: /* dbl/dbl */
  863. return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
  864. &fpregs[t],status));
  865. }
  866. case 6: /* FCNVFU (PA2.0 only) */
  867. switch(fmt) {
  868. case 0: /* sgl/sgl */
  869. return(sgl_to_sgl_fcnvfu(&fpregs[r1],0,
  870. &fpregs[t],status));
  871. case 1: /* sgl/dbl */
  872. return(sgl_to_dbl_fcnvfu(&fpregs[r1],0,
  873. &fpregs[t],status));
  874. case 2: /* dbl/sgl */
  875. return(dbl_to_sgl_fcnvfu(&fpregs[r1],0,
  876. &fpregs[t],status));
  877. case 3: /* dbl/dbl */
  878. return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
  879. &fpregs[t],status));
  880. }
  881. case 7: /* FCNVFUT (PA2.0 only) */
  882. switch(fmt) {
  883. case 0: /* sgl/sgl */
  884. return(sgl_to_sgl_fcnvfut(&fpregs[r1],0,
  885. &fpregs[t],status));
  886. case 1: /* sgl/dbl */
  887. return(sgl_to_dbl_fcnvfut(&fpregs[r1],0,
  888. &fpregs[t],status));
  889. case 2: /* dbl/sgl */
  890. return(dbl_to_sgl_fcnvfut(&fpregs[r1],0,
  891. &fpregs[t],status));
  892. case 3: /* dbl/dbl */
  893. return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
  894. &fpregs[t],status));
  895. }
  896. case 4: /* undefined */
  897. return(MAJOR_0C_EXCP);
  898. } /* end of switch subop */
  899. case 2: /* class 2 */
  900. /*
  901. * Be careful out there.
  902. * Crashme can generate cases where FR31R is specified
  903. * as the source or target of a double precision operation.
  904. * Since we just pass the address of the floating-point
  905. * register to the emulation routines, this can cause
  906. * corruption of fpzeroreg.
  907. */
  908. if (fmt == DBL)
  909. r2 = (extru(ir,fpr2pos,5)<<1);
  910. else
  911. r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
  912. fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
  913. if (r2 == 0)
  914. r2 = fpzeroreg;
  915. if (fpu_type_flags & PA2_0_FPU_FLAG) {
  916. /* FTEST if nullify bit set, otherwise FCMP */
  917. if (extru(ir, fpnulpos, 1)) { /* FTEST */
  918. /* not legal */
  919. return(MAJOR_0E_EXCP);
  920. } else { /* FCMP */
  921. switch (fmt) {
  922. /*
  923. * fmt is only 1 bit long
  924. */
  925. case 0:
  926. retval = sgl_fcmp(&fpregs[r1],
  927. &fpregs[r2],extru(ir,fptpos,5),
  928. &local_status);
  929. update_status_cbit(status,local_status,
  930. fpu_type_flags, subop);
  931. return(retval);
  932. case 1:
  933. retval = dbl_fcmp(&fpregs[r1],
  934. &fpregs[r2],extru(ir,fptpos,5),
  935. &local_status);
  936. update_status_cbit(status,local_status,
  937. fpu_type_flags, subop);
  938. return(retval);
  939. }
  940. }
  941. } /* end of if for PA2.0 */
  942. else { /* PA1.0 & PA1.1 */
  943. switch (subop) {
  944. case 1:
  945. case 2:
  946. case 3:
  947. case 4:
  948. case 5:
  949. case 6:
  950. case 7:
  951. return(MAJOR_0E_EXCP);
  952. case 0: /* FCMP */
  953. switch (fmt) {
  954. /*
  955. * fmt is only 1 bit long
  956. */
  957. case 0:
  958. retval = sgl_fcmp(&fpregs[r1],
  959. &fpregs[r2],extru(ir,fptpos,5),
  960. &local_status);
  961. update_status_cbit(status,local_status,
  962. fpu_type_flags, subop);
  963. return(retval);
  964. case 1:
  965. retval = dbl_fcmp(&fpregs[r1],
  966. &fpregs[r2],extru(ir,fptpos,5),
  967. &local_status);
  968. update_status_cbit(status,local_status,
  969. fpu_type_flags, subop);
  970. return(retval);
  971. }
  972. } /* end of switch subop */
  973. } /* end of else for PA1.0 & PA1.1 */
  974. case 3: /* class 3 */
  975. /*
  976. * Be careful out there.
  977. * Crashme can generate cases where FR31R is specified
  978. * as the source or target of a double precision operation.
  979. * Since we just pass the address of the floating-point
  980. * register to the emulation routines, this can cause
  981. * corruption of fpzeroreg.
  982. */
  983. if (fmt == DBL)
  984. r2 = (extru(ir,fpr2pos,5)<<1);
  985. else
  986. r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
  987. if (r2 == 0)
  988. r2 = fpzeroreg;
  989. switch (subop) {
  990. case 5:
  991. case 6:
  992. case 7:
  993. return(MAJOR_0E_EXCP);
  994. /*
  995. * Note that fmt is only 1 bit for class 3 */
  996. case 0: /* FADD */
  997. switch (fmt) {
  998. case 0:
  999. return(sgl_fadd(&fpregs[r1],&fpregs[r2],
  1000. &fpregs[t],status));
  1001. case 1:
  1002. return(dbl_fadd(&fpregs[r1],&fpregs[r2],
  1003. &fpregs[t],status));
  1004. }
  1005. case 1: /* FSUB */
  1006. switch (fmt) {
  1007. case 0:
  1008. return(sgl_fsub(&fpregs[r1],&fpregs[r2],
  1009. &fpregs[t],status));
  1010. case 1:
  1011. return(dbl_fsub(&fpregs[r1],&fpregs[r2],
  1012. &fpregs[t],status));
  1013. }
  1014. case 2: /* FMPY or XMPYU */
  1015. /*
  1016. * check for integer multiply (x bit set)
  1017. */
  1018. if (extru(ir,fpxpos,1)) {
  1019. /*
  1020. * emulate XMPYU
  1021. */
  1022. switch (fmt) {
  1023. case 0:
  1024. /*
  1025. * bad instruction if t specifies
  1026. * the right half of a register
  1027. */
  1028. if (t & 1)
  1029. return(MAJOR_0E_EXCP);
  1030. BUG();
  1031. /* unsupported
  1032. * impyu(&fpregs[r1],&fpregs[r2],
  1033. * &fpregs[t]);
  1034. */
  1035. return(NOEXCEPTION);
  1036. case 1:
  1037. return(MAJOR_0E_EXCP);
  1038. }
  1039. }
  1040. else { /* FMPY */
  1041. switch (fmt) {
  1042. case 0:
  1043. return(sgl_fmpy(&fpregs[r1],
  1044. &fpregs[r2],&fpregs[t],status));
  1045. case 1:
  1046. return(dbl_fmpy(&fpregs[r1],
  1047. &fpregs[r2],&fpregs[t],status));
  1048. }
  1049. }
  1050. case 3: /* FDIV */
  1051. switch (fmt) {
  1052. case 0:
  1053. return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
  1054. &fpregs[t],status));
  1055. case 1:
  1056. return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
  1057. &fpregs[t],status));
  1058. }
  1059. case 4: /* FREM */
  1060. switch (fmt) {
  1061. case 0:
  1062. return(sgl_frem(&fpregs[r1],&fpregs[r2],
  1063. &fpregs[t],status));
  1064. case 1:
  1065. return(dbl_frem(&fpregs[r1],&fpregs[r2],
  1066. &fpregs[t],status));
  1067. }
  1068. } /* end of class 3 switch */
  1069. } /* end of switch(class) */
  1070. /* If we get here, something is really wrong! */
  1071. return(MAJOR_0E_EXCP);
  1072. }
  1073. /*
  1074. * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction
  1075. */
  1076. static u_int
  1077. decode_06(ir,fpregs)
  1078. u_int ir;
  1079. u_int fpregs[];
  1080. {
  1081. u_int rm1, rm2, tm, ra, ta; /* operands */
  1082. u_int fmt;
  1083. u_int error = 0;
  1084. u_int status;
  1085. u_int fpu_type_flags;
  1086. union {
  1087. double dbl;
  1088. float flt;
  1089. struct { u_int i1; u_int i2; } ints;
  1090. } mtmp, atmp;
  1091. status = fpregs[0]; /* use a local copy of status reg */
  1092. fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */
  1093. fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */
  1094. if (fmt == 0) { /* DBL */
  1095. rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);
  1096. if (rm1 == 0)
  1097. rm1 = fpzeroreg;
  1098. rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);
  1099. if (rm2 == 0)
  1100. rm2 = fpzeroreg;
  1101. tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);
  1102. if (tm == 0)
  1103. return(MAJOR_06_EXCP);
  1104. ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);
  1105. ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);
  1106. if (ta == 0)
  1107. return(MAJOR_06_EXCP);
  1108. if (fpu_type_flags & TIMEX_ROLEX_FPU_MASK) {
  1109. if (ra == 0) {
  1110. /* special case FMPYCFXT, see sgl case below */
  1111. if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],
  1112. &mtmp.ints.i1,&status))
  1113. error = 1;
  1114. if (dbl_to_sgl_fcnvfxt(&fpregs[ta],
  1115. &atmp.ints.i1,&atmp.ints.i1,&status))
  1116. error = 1;
  1117. }
  1118. else {
  1119. if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
  1120. &status))
  1121. error = 1;
  1122. if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
  1123. &status))
  1124. error = 1;
  1125. }
  1126. }
  1127. else
  1128. {
  1129. if (ra == 0)
  1130. ra = fpzeroreg;
  1131. if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
  1132. &status))
  1133. error = 1;
  1134. if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
  1135. &status))
  1136. error = 1;
  1137. }
  1138. if (error)
  1139. return(MAJOR_06_EXCP);
  1140. else {
  1141. /* copy results */
  1142. fpregs[tm] = mtmp.ints.i1;
  1143. fpregs[tm+1] = mtmp.ints.i2;
  1144. fpregs[ta] = atmp.ints.i1;
  1145. fpregs[ta+1] = atmp.ints.i2;
  1146. fpregs[0] = status;
  1147. return(NOEXCEPTION);
  1148. }
  1149. }
  1150. else { /* SGL */
  1151. /*
  1152. * calculate offsets for single precision numbers
  1153. * See table 6-14 in PA-89 architecture for mapping
  1154. */
  1155. rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */
  1156. rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */
  1157. rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */
  1158. rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */
  1159. tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */
  1160. tm |= extru(ir,fptmpos-4,1); /* add right word offset */
  1161. ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */
  1162. ra |= extru(ir,fprapos-4,1); /* add right word offset */
  1163. ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */
  1164. ta |= extru(ir,fptapos-4,1); /* add right word offset */
  1165. if (ra == 0x20 &&(fpu_type_flags & TIMEX_ROLEX_FPU_MASK)) {
  1166. /* special case FMPYCFXT (really 0)
  1167. * This instruction is only present on the Timex and
  1168. * Rolex fpu's in so if it is the special case and
  1169. * one of these fpu's we run the FMPYCFXT instruction
  1170. */
  1171. if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
  1172. &status))
  1173. error = 1;
  1174. if (sgl_to_sgl_fcnvfxt(&fpregs[ta],&atmp.ints.i1,
  1175. &atmp.ints.i1,&status))
  1176. error = 1;
  1177. }
  1178. else {
  1179. if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
  1180. &status))
  1181. error = 1;
  1182. if (sgl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
  1183. &status))
  1184. error = 1;
  1185. }
  1186. if (error)
  1187. return(MAJOR_06_EXCP);
  1188. else {
  1189. /* copy results */
  1190. fpregs[tm] = mtmp.ints.i1;
  1191. fpregs[ta] = atmp.ints.i1;
  1192. fpregs[0] = status;
  1193. return(NOEXCEPTION);
  1194. }
  1195. }
  1196. }
  1197. /*
  1198. * routine to decode the 26 (FMPYSUB) instruction
  1199. */
  1200. static u_int
  1201. decode_26(ir,fpregs)
  1202. u_int ir;
  1203. u_int fpregs[];
  1204. {
  1205. u_int rm1, rm2, tm, ra, ta; /* operands */
  1206. u_int fmt;
  1207. u_int error = 0;
  1208. u_int status;
  1209. union {
  1210. double dbl;
  1211. float flt;
  1212. struct { u_int i1; u_int i2; } ints;
  1213. } mtmp, atmp;
  1214. status = fpregs[0];
  1215. fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */
  1216. if (fmt == 0) { /* DBL */
  1217. rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);
  1218. if (rm1 == 0)
  1219. rm1 = fpzeroreg;
  1220. rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);
  1221. if (rm2 == 0)
  1222. rm2 = fpzeroreg;
  1223. tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);
  1224. if (tm == 0)
  1225. return(MAJOR_26_EXCP);
  1226. ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);
  1227. if (ra == 0)
  1228. return(MAJOR_26_EXCP);
  1229. ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);
  1230. if (ta == 0)
  1231. return(MAJOR_26_EXCP);
  1232. if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))
  1233. error = 1;
  1234. if (dbl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))
  1235. error = 1;
  1236. if (error)
  1237. return(MAJOR_26_EXCP);
  1238. else {
  1239. /* copy results */
  1240. fpregs[tm] = mtmp.ints.i1;
  1241. fpregs[tm+1] = mtmp.ints.i2;
  1242. fpregs[ta] = atmp.ints.i1;
  1243. fpregs[ta+1] = atmp.ints.i2;
  1244. fpregs[0] = status;
  1245. return(NOEXCEPTION);
  1246. }
  1247. }
  1248. else { /* SGL */
  1249. /*
  1250. * calculate offsets for single precision numbers
  1251. * See table 6-14 in PA-89 architecture for mapping
  1252. */
  1253. rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */
  1254. rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */
  1255. rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */
  1256. rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */
  1257. tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */
  1258. tm |= extru(ir,fptmpos-4,1); /* add right word offset */
  1259. ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */
  1260. ra |= extru(ir,fprapos-4,1); /* add right word offset */
  1261. ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */
  1262. ta |= extru(ir,fptapos-4,1); /* add right word offset */
  1263. if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))
  1264. error = 1;
  1265. if (sgl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))
  1266. error = 1;
  1267. if (error)
  1268. return(MAJOR_26_EXCP);
  1269. else {
  1270. /* copy results */
  1271. fpregs[tm] = mtmp.ints.i1;
  1272. fpregs[ta] = atmp.ints.i1;
  1273. fpregs[0] = status;
  1274. return(NOEXCEPTION);
  1275. }
  1276. }
  1277. }
  1278. /*
  1279. * routine to decode the 2E (FMPYFADD,FMPYNFADD) instructions
  1280. */
  1281. static u_int
  1282. decode_2e(ir,fpregs)
  1283. u_int ir;
  1284. u_int fpregs[];
  1285. {
  1286. u_int rm1, rm2, ra, t; /* operands */
  1287. u_int fmt;
  1288. fmt = extru(ir,fpfmtpos,1); /* get fmt completer */
  1289. if (fmt == DBL) { /* DBL */
  1290. rm1 = extru(ir,fprm1pos,5) * sizeof(double)/sizeof(u_int);
  1291. if (rm1 == 0)
  1292. rm1 = fpzeroreg;
  1293. rm2 = extru(ir,fprm2pos,5) * sizeof(double)/sizeof(u_int);
  1294. if (rm2 == 0)
  1295. rm2 = fpzeroreg;
  1296. ra = ((extru(ir,fpraupos,3)<<2)|(extru(ir,fpralpos,3)>>1)) *
  1297. sizeof(double)/sizeof(u_int);
  1298. if (ra == 0)
  1299. ra = fpzeroreg;
  1300. t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);
  1301. if (t == 0)
  1302. return(MAJOR_2E_EXCP);
  1303. if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */
  1304. return(dbl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],
  1305. &fpregs[ra], &fpregs[0], &fpregs[t]));
  1306. } else {
  1307. return(dbl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],
  1308. &fpregs[ra], &fpregs[0], &fpregs[t]));
  1309. }
  1310. } /* end DBL */
  1311. else { /* SGL */
  1312. rm1 = (extru(ir,fprm1pos,5)<<1)|(extru(ir,fpxrm1pos,1));
  1313. if (rm1 == 0)
  1314. rm1 = fpzeroreg;
  1315. rm2 = (extru(ir,fprm2pos,5)<<1)|(extru(ir,fpxrm2pos,1));
  1316. if (rm2 == 0)
  1317. rm2 = fpzeroreg;
  1318. ra = (extru(ir,fpraupos,3)<<3)|extru(ir,fpralpos,3);
  1319. if (ra == 0)
  1320. ra = fpzeroreg;
  1321. t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
  1322. if (t == 0)
  1323. return(MAJOR_2E_EXCP);
  1324. if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */
  1325. return(sgl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],
  1326. &fpregs[ra], &fpregs[0], &fpregs[t]));
  1327. } else {
  1328. return(sgl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],
  1329. &fpregs[ra], &fpregs[0], &fpregs[t]));
  1330. }
  1331. } /* end SGL */
  1332. }
  1333. /*
  1334. * update_status_cbit
  1335. *
  1336. * This routine returns the correct FP status register value in
  1337. * *status, based on the C-bit & V-bit returned by the FCMP
  1338. * emulation routine in new_status. The architecture type
  1339. * (PA83, PA89 or PA2.0) is available in fpu_type. The y_field
  1340. * and the architecture type are used to determine what flavor
  1341. * of FCMP is being emulated.
  1342. */
  1343. static void
  1344. update_status_cbit(status, new_status, fpu_type, y_field)
  1345. u_int *status, new_status;
  1346. u_int fpu_type;
  1347. u_int y_field;
  1348. {
  1349. /*
  1350. * For PA89 FPU's which implement the Compare Queue and
  1351. * for PA2.0 FPU's, update the Compare Queue if the y-field = 0,
  1352. * otherwise update the specified bit in the Compare Array.
  1353. * Note that the y-field will always be 0 for non-PA2.0 FPU's.
  1354. */
  1355. if ((fpu_type & TIMEX_EXTEN_FLAG) ||
  1356. (fpu_type & ROLEX_EXTEN_FLAG) ||
  1357. (fpu_type & PA2_0_FPU_FLAG)) {
  1358. if (y_field == 0) {
  1359. *status = ((*status & 0x04000000) >> 5) | /* old Cbit */
  1360. ((*status & 0x003ff000) >> 1) | /* old CQ */
  1361. (new_status & 0xffc007ff); /* all other bits*/
  1362. } else {
  1363. *status = (*status & 0x04000000) | /* old Cbit */
  1364. ((new_status & 0x04000000) >> (y_field+4)) |
  1365. (new_status & ~0x04000000 & /* other bits */
  1366. ~(0x04000000 >> (y_field+4)));
  1367. }
  1368. }
  1369. /* if PA83, just update the C-bit */
  1370. else {
  1371. *status = new_status;
  1372. }
  1373. }