fpudispatch.c 38 KB

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