First Commit of my working state
[simh.git] / Interdata / id_fp.c
CommitLineData
196ba1fc
PH
1/* id_fp.c: Interdata floating point instructions\r
2\r
3 Copyright (c) 2000-2005, Robert M. Supnik\r
4\r
5 Permission is hereby granted, free of charge, to any person obtaining a\r
6 copy of this software and associated documentation files (the "Software"),\r
7 to deal in the Software without restriction, including without limitation\r
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
9 and/or sell copies of the Software, and to permit persons to whom the\r
10 Software is furnished to do so, subject to the following conditions:\r
11\r
12 The above copyright notice and this permission notice shall be included in\r
13 all copies or substantial portions of the Software.\r
14\r
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21\r
22 Except as contained in this notice, the name of Robert M Supnik shall not be\r
23 used in advertising or otherwise to promote the sale, use or other dealings\r
24 in this Software without prior written authorization from Robert M Supnik.\r
25\r
26 The Interdata uses IBM 360 floating point format:\r
27\r
28 0 7 8 15 23 31\r
29 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
30 |S| exponent | fraction | :single\r
31 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
32 | fraction low | :double\r
33 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
34\r
35 where S = 0 for plus, 1 for minus\r
36 exponent = 16**n, in excess 64 code\r
37 fraction = .hhhhhh, seen as 6-14 hexadecimal digits\r
38\r
39 Numbers can be normalized or unnormalized but are always normalized\r
40 when loaded.\r
41\r
42 Interdata has 8 floating point registers, F0, F2, ... , FE. In floating\r
43 point instructions, the low order bit of the register number is ignored. \r
44\r
45 On floating point overflow, the exponent and fraction are set to 1's.\r
46 On floating point underflow, the exponent and fraction are set to 0's.\r
47\r
48 Interdata has both 32b only and 32b/64b floating point implementations.\r
49 In 32b only implementations, add and subtract are truncated, but multiply\r
50 and divide are rounded, and the floating point registers are kept in\r
51 memory. In 64b implementations, all single precision precision operations\r
52 are rounded, double precision operations are truncated, and the floating\r
53 point registers are kept in separate hardware arrays.\r
54*/\r
55\r
56#include "id_defs.h"\r
57\r
58struct ufp { /* unpacked fp */\r
59 int32 sign; /* sign */\r
60 int32 exp; /* unbiased exp */\r
61 uint32 h; /* fr high */\r
62 uint32 l; /* fr low */\r
63 };\r
64\r
65#define FP_V_SIGN 31 /* sign */\r
66#define FP_M_SIGN 0x1\r
67#define FP_GETSIGN(x) (((x) >> FP_V_SIGN) & FP_M_SIGN)\r
68#define FP_V_EXP 24 /* exponent */\r
69#define FP_M_EXP 0x7F\r
70#define FP_GETEXP(x) (((x) >> FP_V_EXP) & FP_M_EXP)\r
71#define FP_V_FRH 0 /* fraction */\r
72#define FP_M_FRH 0xFFFFFF\r
73#define FP_GETFRH(x) (((x) >> FP_V_FRH) & FP_M_FRH)\r
74#define FP_GETFRL(x) (x)\r
75\r
76#define FP_BIAS 0x40 /* exp bias */\r
77#define FP_CARRY (1 << FP_V_EXP ) /* carry out */\r
78#define FP_NORM (0xF << (FP_V_EXP - 4)) /* normalized */\r
79#define FP_ROUND 0x80000000\r
80\r
81/* Double precision fraction add/subtract/compare */\r
82\r
83#define FR_ADD(d,s) d.l = (d.l + s.l) & DMASK32; \\r
84 d.h = (d.h + s.h + (d.l < s.l)) & DMASK32 \r
85\r
86#define FR_SUB(d,s) d.h = (d.h - s.h - (d.l < s.l)) & DMASK32; \\r
87 d.l = (d.l - s.l) & DMASK32\r
88\r
89#define FR_GE(s1,s2) ((s1.h > s2.h) || \\r
90 ((s1.h == s2.h) && (s1.l >= s2.l)))\r
91\r
92/* Variable and constant shifts; for constants, 0 < k < 32 */\r
93\r
94#define FR_RSH_V(v,s) if ((s) < 32) { \\r
95 v.l = ((v.l >> (s)) | \\r
96 (v.h << (32 - (s)))) & DMASK32; \\r
97 v.h = (v.h >> (s)) & DMASK32; \\r
98 } \\r
99 else { \\r
100 v.l = v.h >> ((s) - 32); \\r
101 v.h = 0; \\r
102 }\r
103\r
104#define FR_RSH_K(v,s) v.l = ((v.l >> (s)) | \\r
105 (v.h << (32 - (s)))) & DMASK32; \\r
106 v.h = (v.h >> (s)) & DMASK32\r
107\r
108#define FR_LSH_K(v,s) v.h = ((v.h << (s)) | \\r
109 (v.l >> (32 - (s)))) & DMASK32; \\r
110 v.l = (v.l << (s)) & DMASK32\r
111\r
112#define Q_RND(op) (OP_DPFP (op) == 0)\r
113#define Q_RND_AS(op) ((OP_DPFP (op) == 0) && fp_in_hwre)\r
114\r
115extern uint32 *R;\r
116extern uint32 F[8];\r
117extern dpr_t D[8];\r
118extern uint16 decrom[];\r
119extern uint32 fp_in_hwre;\r
120extern uint32 ReadF (uint32 loc, uint32 rel);\r
121extern void WriteF (uint32 loc, uint32 dat, uint32 rel);\r
122void ReadFP2 (struct ufp *fop, uint32 op, uint32 r2, uint32 ea);\r
123void UnpackFPR (struct ufp *fop, uint32 op, uint32 r1);\r
124void NormUFP (struct ufp *fop);\r
125uint32 StoreFPR (struct ufp *fop, uint32 op, uint32 r1, uint32 rnd);\r
126uint32 StoreFPX (struct ufp *fop, uint32 op, uint32 r1);\r
127\r
128/* Floating point load */\r
129\r
130uint32 f_l (uint32 op, uint32 r1, uint32 r2, uint32 ea)\r
131{\r
132struct ufp fop2;\r
133\r
134ReadFP2 (&fop2, op, r2, ea); /* get op, normalize */\r
135return StoreFPR (&fop2, op, r1, 0); /* store, chk unflo */\r
136}\r
137\r
138/* Floating point compare */\r
139\r
140uint32 f_c (uint32 op, uint32 r1, uint32 r2, uint32 ea)\r
141{\r
142struct ufp fop1, fop2;\r
143\r
144ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */\r
145UnpackFPR (&fop1, op, r1); /* get op1, norm */\r
146if (fop1.sign ^ fop2.sign) /* signs differ? */\r
147 return (fop2.sign? CC_G: (CC_C | CC_L));\r
148if (fop1.exp != fop2.exp) /* exps differ? */\r
149 return (((fop1.exp > fop2.exp) ^ fop1.sign)? CC_G: (CC_C | CC_L));\r
150if (fop1.h != fop2.h) /* hi fracs differ? */\r
151 return (((fop1.h > fop2.h) ^ fop1.sign)? CC_G: (CC_C | CC_L));\r
152if (OP_DPFP (op) && (fop1.l != fop2.l)) /* dp: low fracs diff? */\r
153 return (((fop1.l > fop2.l) ^ fop1.sign)? CC_G: (CC_C | CC_L));\r
154return 0;\r
155}\r
156\r
157/* Floating to integer conversion */\r
158\r
159uint32 f_fix (uint32 op, uint32 r1, uint32 r2) /* 16b */\r
160{\r
161struct ufp res;\r
162uint32 cc;\r
163\r
164UnpackFPR (&res, op, r2); /* get op2, norm */\r
165if ((res.h == 0) || (res.exp < 0x41)) { /* result zero? */\r
166 R[r1] = 0;\r
167 return 0;\r
168 }\r
169if ((res.exp > 0x44) || /* result too big? */\r
170 ((res.exp == 0x44) && (res.h >= 0x00800000))) {\r
171 res.h = MMASK16;\r
172 cc = CC_V;\r
173 }\r
174else {\r
175 res.h = res.h >> ((0x46 - res.exp) * 4); /* right align frac */\r
176 cc = 0;\r
177 }\r
178if (res.sign) {\r
179 R[r1] = ((res.h ^ DMASK16) + 1) & DMASK16; /* negate result */\r
180 return cc | CC_L;\r
181 }\r
182R[r1] = res.h & DMASK16;\r
183return cc | CC_G;\r
184}\r
185\r
186uint32 f_fix32 (uint32 op, uint32 r1, uint32 r2) /* 32b */\r
187{\r
188struct ufp res;\r
189uint32 cc;\r
190\r
191UnpackFPR (&res, op, r2); /* get op2, norm */\r
192if ((res.h == 0) || (res.exp < 0x41)) { /* result zero? */\r
193 R[r1] = 0;\r
194 return 0;\r
195 }\r
196if ((res.exp > 0x48) || /* result too big? */\r
197 ((res.exp == 0x48) && (res.h >= 0x00800000))) {\r
198 res.h = MMASK32;\r
199 cc = CC_V;\r
200 }\r
201else {\r
202 FR_LSH_K (res, 8); /* get all in 32b */\r
203 res.h = res.h >> ((0x48 - res.exp) * 4); /* right align frac */\r
204 cc = 0;\r
205 }\r
206if (res.sign) {\r
207 R[r1] = (res.h ^ DMASK32) + 1; /* negate result */\r
208 return cc | CC_L;\r
209 }\r
210R[r1] = res.h;\r
211return cc | CC_G;\r
212}\r
213\r
214/* Integer to floating conversion */\r
215\r
216uint32 f_flt (uint32 op, uint32 r1, uint32 r2) /* 16b */\r
217{\r
218struct ufp res = { 0, 0x44, 0, 0 }; /* +, 16**4 */\r
219uint32 cc;\r
220\r
221if (R[r2] == 0) cc = 0; /* zero arg? */\r
222else if (R[r2] & SIGN16) { /* neg arg? */\r
223 res.sign = FP_M_SIGN; /* set sign */\r
224 res.h = ((~R[r2] + 1) & DMASK16) << 8; /* get magnitude */\r
225 cc = CC_L;\r
226 }\r
227else {\r
228 res.h = R[r2] << 8; /* pos nz arg */\r
229 cc = CC_G;\r
230 }\r
231NormUFP (&res); /* normalize */\r
232StoreFPR (&res, op, r1, 0); /* store result */\r
233return cc;\r
234}\r
235\r
236uint32 f_flt32 (uint32 op, uint32 r1, uint32 r2) /* 32b */\r
237{\r
238struct ufp res = { 0, 0x48, 0, 0 }; /* +, 16**8 */\r
239uint32 cc, t;\r
240\r
241t = R[r2]; /* int op */\r
242if (t) { /* nonzero arg? */\r
243 if (t & SIGN32) { /* neg arg? */\r
244 res.sign = FP_M_SIGN; /* set sign */\r
245 t = (~t + 1) & DMASK32; /* get magnitude */\r
246 cc = CC_L;\r
247 }\r
248 else cc = CC_G; /* pos nz arg */\r
249 res.h = t >> 8; /* hi frac */\r
250 res.l = t << 24; /* lo frac */\r
251 }\r
252else cc = 0; /* zero arg */\r
253NormUFP (&res); /* normalize */\r
254StoreFPR (&res, op, r1, 0); /* store result */\r
255return cc;\r
256}\r
257\r
258/* Floating point add/subtract */\r
259\r
260uint32 f_as (uint32 op, uint32 r1, uint32 r2, uint32 ea)\r
261{\r
262struct ufp fop1, fop2, t;\r
263int32 ediff;\r
264\r
265ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */\r
266UnpackFPR (&fop1, op, r1); /* get op1, norm */\r
267if (op & 1) fop2.sign = fop2.sign ^ 1; /* if sub, inv sign2 */\r
268if (fop1.h == 0) fop1 = fop2; /* if op1 = 0, res = op2 */\r
269else if (fop2.h != 0) { /* if op2 = 0, no add */\r
270 if ((fop1.exp < fop2.exp) || /* |op1| < |op2|? */\r
271 ((fop1.exp == fop2.exp) &&\r
272 ((fop1.h < fop2.h) ||\r
273 ((fop1.h == fop2.h) && (fop1.l < fop2.l))))) {\r
274 t = fop2; /* swap operands */\r
275 fop2 = fop1;\r
276 fop1 = t;\r
277 }\r
278 ediff = fop1.exp - fop2.exp; /* exp difference */\r
279 if (OP_DPFP (op) || fp_in_hwre) { /* dbl prec or hwre? */\r
280 if (ediff >= 14) fop2.h = fop2.l = 0; /* diff too big? */\r
281 else if (ediff) { /* any difference? */\r
282 FR_RSH_V (fop2, ediff * 4); /* shift frac */\r
283 }\r
284 }\r
285 else { /* sgl prec ucode */\r
286 if (ediff >= 6) fop2.h = 0; /* diff too big? */\r
287 else if (ediff) /* any difference? */\r
288 fop2.h = fop2.h >> (ediff * 4); /* shift frac */\r
289 }\r
290 if (fop1.sign ^ fop2.sign) { /* eff subtract */\r
291 FR_SUB (fop1, fop2); /* sub fractions */\r
292 NormUFP (&fop1); /* normalize result */\r
293 }\r
294 else {\r
295 FR_ADD (fop1, fop2); /* add fractions */\r
296 if (fop1.h & FP_CARRY) { /* carry out? */\r
297 FR_RSH_K (fop1, 4); /* renormalize */\r
298 fop1.exp = fop1.exp + 1; /* incr exp */\r
299 }\r
300 }\r
301 } /* end if fop2 */\r
302return StoreFPR (&fop1, op, r1, Q_RND_AS (op)); /* store result */\r
303}\r
304\r
305/* Floating point multiply\r
306\r
307 Notes:\r
308 - Exponent overflow/underflow is tested right after the exponent\r
309 add, without regard to potential changes due to normalization\r
310 - Exponent underflow is tested right after normalization, without\r
311 regard to changes due to rounding\r
312 - Single precision hardware multiply may generate up to 48b\r
313 - Double precision multiply generates 56b with no guard bits\r
314*/\r
315\r
316int32 f_m (uint32 op, uint32 r1, uint32 r2, uint32 ea)\r
317{\r
318struct ufp fop1, fop2;\r
319struct ufp res = { 0, 0, 0, 0 };\r
320uint32 i;\r
321\r
322ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */\r
323UnpackFPR (&fop1, op, r1); /* get op1, norm */\r
324if (fop1.h && fop2.h) { /* if both != 0 */\r
325 res.sign = fop1.sign ^ fop2.sign; /* sign = diff */\r
326 res.exp = fop1.exp + fop2.exp - FP_BIAS; /* exp = sum */\r
327 if ((res.exp < 0) || (res.exp > FP_M_EXP)) /* ovf/undf? */\r
328 return StoreFPX (&res, op, r1); /* early out */\r
329 if ((fop1.l | fop2.l) == 0) { /* 24b x 24b? */\r
330 for (i = 0; i < 24; i++) { /* 24 iterations */\r
331 if (fop2.h & 1) res.h = res.h + fop1.h; /* add hi only */\r
332 FR_RSH_K (res, 1); /* shift dp res */\r
333 fop2.h = fop2.h >> 1;\r
334 }\r
335 }\r
336 else { /* some low 0's */\r
337 if (fop2.l != 0) { /* 56b x 56b? */\r
338 for (i = 0; i < 32; i++) { /* do low 32b */\r
339 if (fop2.l & 1) { FR_ADD (res, fop1); }\r
340 FR_RSH_K (res, 1);\r
341 fop2.l = fop2.l >> 1;\r
342 }\r
343 }\r
344 for (i = 0; i < 24; i++) { /* do hi 24b */\r
345 if (fop2.h & 1) { FR_ADD (res, fop1); }\r
346 FR_RSH_K (res, 1);\r
347 fop2.h = fop2.h >> 1;\r
348 }\r
349 }\r
350 NormUFP (&res); /* normalize */\r
351 if (res.exp < 0) /* underflow? */\r
352 return StoreFPX (&res, op, r1); /* early out */\r
353 }\r
354return StoreFPR (&res, op, r1, Q_RND (op)); /* store */\r
355}\r
356\r
357/* Floating point divide - see overflow/underflow notes for multiply */\r
358\r
359int32 f_d (uint32 op, uint32 r1, uint32 r2, uint32 ea)\r
360{\r
361struct ufp fop1, fop2;\r
362struct ufp quo = { 0, 0, 0, 0 };\r
363int32 i;\r
364\r
365ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */\r
366UnpackFPR (&fop1, op, r1); /* get op1, norm */\r
367if (fop2.h == 0) return CC_C | CC_V; /* div by zero? */\r
368if (fop1.h) { /* dvd != 0? */\r
369 quo.sign = fop1.sign ^ fop2.sign; /* sign = diff */\r
370 quo.exp = fop1.exp - fop2.exp + FP_BIAS; /* exp = diff */\r
371 if ((quo.exp < 0) || (quo.exp > FP_M_EXP)) /* ovf/undf? */\r
372 return StoreFPX (&quo, op, r1); /* early out */\r
373 if (!FR_GE (fop1, fop2)) {\r
374 FR_LSH_K (fop1, 4); /* ensure success */\r
375 }\r
376 else { /* exp off by 1 */\r
377 quo.exp = quo.exp + 1; /* incr exponent */\r
378 if (quo.exp > FP_M_EXP) /* overflow? */\r
379 return StoreFPX (&quo, op, r1); /* early out */\r
380 }\r
381 for (i = 0; i < (OP_DPFP (op)? 14: 6); i++) { /* 6/14 hex digits */\r
382 FR_LSH_K (quo, 4); /* shift quotient */\r
383 while (FR_GE (fop1, fop2)) { /* while sub works */\r
384 FR_SUB (fop1, fop2); /* decrement */\r
385 quo.l = quo.l + 1; /* add quo bit */\r
386 }\r
387 FR_LSH_K (fop1, 4); /* shift divd */\r
388 }\r
389 if (!OP_DPFP (op)) { /* single? */\r
390 quo.h = quo.l; /* move quotient */\r
391 if (fop1.h >= (fop2.h << 3)) quo.l = FP_ROUND;\r
392 else quo.l = 0;\r
393 } /* don't need to normalize */\r
394 } /* end if fop1.h */\r
395return StoreFPR (&quo, op, r1, Q_RND (op)); /* store result */\r
396}\r
397\r
398/* Utility routines */\r
399\r
400/* Unpack floating point number */\r
401\r
402void UnpackFPR (struct ufp *fop, uint32 op, uint32 r1)\r
403{\r
404uint32 hi;\r
405\r
406if (OP_DPFP (op)) { /* double prec? */\r
407 hi = D[r1 >> 1].h; /* get hi */\r
408 fop->l = FP_GETFRL (D[r1 >> 1].l); /* get lo */\r
409 }\r
410else {\r
411 hi = ReadFReg (r1); /* single prec */\r
412 fop->l = 0; /* lo is zero */\r
413 }\r
414fop->h = FP_GETFRH (hi); /* get hi frac */\r
415if (fop->h || fop->l) { /* non-zero? */\r
416 fop->sign = FP_GETSIGN (hi); /* get sign */\r
417 fop->exp = FP_GETEXP (hi); /* get exp */\r
418 NormUFP (fop); /* normalize */\r
419 }\r
420else fop->sign = fop->exp = 0; /* clean zero */\r
421return;\r
422}\r
423\r
424/* Read memory operand */\r
425\r
426void ReadFP2 (struct ufp *fop, uint32 op, uint32 r2, uint32 ea)\r
427{\r
428uint32 hi;\r
429\r
430if (OP_TYPE (op) > OP_RR) { /* mem ref? */\r
431 hi = ReadF (ea, VR); /* get hi */\r
432 if (OP_DPFP (op)) fop->l = ReadF (ea + 4, VR); /* dp? get lo */\r
433 else fop->l = 0; /* sp, lo = 0 */\r
434 }\r
435else {\r
436 if (OP_DPFP (op)) { /* RR */\r
437 hi = D[r2 >> 1].h; /* dp? get dp reg */\r
438 fop->l = D[r2 >> 1].l;\r
439 }\r
440 else {\r
441 hi = ReadFReg (r2); /* get sp reg */\r
442 fop->l = 0;\r
443 }\r
444 }\r
445fop->h = FP_GETFRH (hi); /* get hi frac */\r
446if (fop->h || fop->l) { /* non-zero? */\r
447 fop->sign = FP_GETSIGN (hi); /* get sign */\r
448 fop->exp = FP_GETEXP (hi); /* get exp */\r
449 NormUFP (fop); /* normalize */\r
450 }\r
451else fop->sign = fop->exp = 0; /* clean zero */\r
452return;\r
453}\r
454\r
455/* Normalize unpacked floating point number */\r
456\r
457void NormUFP (struct ufp *fop)\r
458{\r
459if ((fop->h & FP_M_FRH) || fop->l) { /* any fraction? */\r
460 while ((fop->h & FP_NORM) == 0) { /* until norm */\r
461 fop->h = (fop->h << 4) | ((fop->l >> 28) & 0xF);\r
462 fop->l = fop->l << 4;\r
463 fop->exp = fop->exp - 1;\r
464 }\r
465 }\r
466else fop->sign = fop->exp = 0; /* clean 0 */\r
467return;\r
468}\r
469\r
470/* Round fp number, store, generate condition codes */\r
471\r
472uint32 StoreFPR (struct ufp *fop, uint32 op, uint32 r1, uint32 rnd)\r
473{\r
474uint32 hi, cc;\r
475\r
476if (rnd && (fop->l & FP_ROUND)) { /* round? */\r
477 fop->h = fop->h + 1; /* add 1 to frac */\r
478 if (fop->h & FP_CARRY) { /* carry out? */\r
479 fop->h = fop->h >> 4; /* renormalize */\r
480 fop->exp = fop->exp + 1; /* incr exp */\r
481 }\r
482 }\r
483if (fop->h == 0) { /* result 0? */\r
484 hi = fop->l = 0; /* store clean 0 */\r
485 cc = 0;\r
486 }\r
487else if (fop->exp < 0) { /* underflow? */\r
488 hi = fop->l = 0; /* store clean 0 */\r
489 cc = CC_V;\r
490 }\r
491else if (fop->exp > FP_M_EXP) { /* overflow? */\r
492 hi = (fop->sign)? 0xFFFFFFFF: 0x7FFFFFFF;\r
493 fop->l = 0xFFFFFFFF;\r
494 cc = (CC_V | ((fop->sign)? CC_L: CC_G));\r
495 }\r
496else {\r
497 hi = ((fop->sign & FP_M_SIGN) << FP_V_SIGN) | /* pack result */\r
498 ((fop->exp & FP_M_EXP) << FP_V_EXP) |\r
499 ((fop->h & FP_M_FRH) << FP_V_FRH);\r
500 cc = (fop->sign)? CC_L: CC_G; /* set cc's */\r
501 }\r
502if (OP_DPFP (op)) { /* double precision? */\r
503 D[r1 >> 1].h = hi;\r
504 D[r1 >> 1].l = fop->l;\r
505 }\r
506else {\r
507 WriteFReg (r1, hi);\r
508 }\r
509return cc;\r
510}\r
511\r
512/* Generate exception result */\r
513\r
514uint32 StoreFPX (struct ufp *fop, uint32 op, uint32 r1)\r
515{\r
516uint32 cc = CC_V;\r
517\r
518if (fop->exp < 0) fop->h = fop->l = 0; /* undf? clean 0 */\r
519else {\r
520 fop->h = (fop->sign)? 0xFFFFFFFF: 0x7FFFFFFF; /* overflow */\r
521 fop->l = 0xFFFFFFFF;\r
522 cc = cc | ((fop->sign)? CC_L: CC_G);\r
523 }\r
524if (OP_DPFP (op)) { /* double precision? */\r
525 D[r1 >> 1].h = fop->h;\r
526 D[r1 >> 1].l = fop->l;\r
527 }\r
528else {\r
529 WriteFReg (r1, fop->h);\r
530 }\r
531return cc;\r
532}\r