1 /* FLOAT.C (c) Copyright Peter Kuschnerus, 2000-2009 */
2 /* ESA/390 Hex Floatingpoint Instructions */
3
4 /*-------------------------------------------------------------------*/
5 /* This module implements the ESA/390 Hex Floatingpoint Instructions */
6 /* described in the manual ESA/390 Principles of Operation. */
7 /*-------------------------------------------------------------------*/
8
9 /*-------------------------------------------------------------------*/
10 /* Incorporated all floating point instructions from cpu.c in order */
11 /* to implement revised instruction decoding. */
12 /* Jan Jaeger 01/07/00 */
13 /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */
14 /*-------------------------------------------------------------------*/
15
16 /*-------------------------------------------------------------------*/
17 /* Added the square-root-facility (instructions SQDR, SQER). */
18 /* Peter Kuschnerus 01/09/00 */
19 /*-------------------------------------------------------------------*/
20
21 /*-------------------------------------------------------------------*/
22 /* Added the HFP-extension-facility (26 additional instructions). */
23 /* Added the AFP-Registers-facility (additional float registers). */
24 /* Peter Kuschnerus 13/12/00 */
25 /* Long Displacement Facility: LDY,LEY,STDY,STEY R.Bowler 29/06/03 */
26 /* FPS Extensions Facility: LXR,LZER,LZDR,LZXR R.Bowler 06juil03 */
27 /* HFP Multiply and Add/Subtract Facility R.Bowler 10juil03 */
28 /* Convert 64fixed to float family CEGR,CDGR,CXGR BvdHelm 28/01/06 */
29 /* Completed the family CGER, CGDR and CGXR BvdHelm 04/11/06 */
30 /*-------------------------------------------------------------------*/
31
32 #include "hstdinc.h"
33
34 #if !defined(_HENGINE_DLL_)
35 #define _HENGINE_DLL_
36 #endif
37
38 #if !defined(_FLOAT_C_)
39 #define _FLOAT_C_
40 #endif
41
42 #include "hercules.h"
43 #include "opcode.h"
44 #include "inline.h"
45
46
47 #if defined(FEATURE_HEXADECIMAL_FLOATING_POINT)
48
49 /* Rename all inline functions for multi architectural support *JJ */
50 #undef get_sf
51 #undef store_sf
52 #undef get_lf
53 #undef store_lf
54 #undef get_ef
55 #undef store_ef
56 #undef vfetch_sf
57 #undef vfetch_lf
58 #undef normal_sf
59 #undef normal_lf
60 #undef normal_ef
61 #undef overflow_sf
62 #undef overflow_lf
63 #undef overflow_ef
64 #undef underflow_sf
65 #undef underflow_lf
66 #undef underflow_ef
67 #undef over_under_flow_sf
68 #undef over_under_flow_lf
69 #undef over_under_flow_ef
70 #undef significance_sf
71 #undef significance_lf
72 #undef significance_ef
73 #undef add_ef
74 #undef add_lf
75 #undef add_sf
76 #undef cmp_ef
77 #undef cmp_lf
78 #undef cmp_sf
79 #undef div_U128
80 #undef div_U256
81 #undef div_ef
82 #undef div_lf
83 #undef div_sf
84 #undef mul_ef
85 #undef mul_sf
86 #undef mul_lf
87 #undef mul_lf_to_ef
88 #undef mul_sf_to_lf
89 #undef square_root_fraction
90 #undef sq_sf
91 #undef sq_lf
92 #if __GEN_ARCH == 370
93 #define get_ef s370_get_ef
94 #define get_lf s370_get_lf
95 #define get_sf s370_get_sf
96 #define normal_ef s370_normal_ef
97 #define normal_lf s370_normal_lf
98 #define normal_sf s370_normal_sf
99 #define over_under_flow_ef s370_over_under_flow_ef
100 #define over_under_flow_lf s370_over_under_flow_lf
101 #define over_under_flow_sf s370_over_under_flow_sf
102 #define overflow_ef s370_overflow_ef
103 #define overflow_lf s370_overflow_lf
104 #define overflow_sf s370_overflow_sf
105 #define significance_ef s370_significance_ef
106 #define significance_lf s370_significance_lf
107 #define significance_sf s370_significance_sf
108 #define store_ef s370_store_ef
109 #define store_lf s370_store_lf
110 #define store_sf s370_store_sf
111 #define underflow_ef s370_underflow_ef
112 #define underflow_lf s370_underflow_lf
113 #define underflow_sf s370_underflow_sf
114 #define vfetch_lf s370_vfetch_lf
115 #define vfetch_sf s370_vfetch_sf
116 #define add_ef s370_add_ef
117 #define add_lf s370_add_lf
118 #define add_sf s370_add_sf
119 #define cmp_ef s370_cmp_ef
120 #define cmp_lf s370_cmp_lf
121 #define cmp_sf s370_cmp_sf
122 #define div_U128 s370_div_U128
123 #define div_U256 s370_div_U256
124 #define div_ef s370_div_ef
125 #define div_lf s370_div_lf
126 #define div_sf s370_div_sf
127 #define mul_ef s370_mul_ef
128 #define mul_sf s370_mul_sf
129 #define mul_lf s370_mul_lf
130 #define mul_lf_to_ef s370_mul_lf_to_ef
131 #define mul_sf_to_lf s370_mul_sf_to_lf
132 #define square_root_fraction s370_square_root_fraction
133 #define sq_sf s370_sq_sf
134 #define sq_lf s370_sq_lf
135 #elif __GEN_ARCH == 390
136 #define get_ef s390_get_ef
137 #define get_lf s390_get_lf
138 #define get_sf s390_get_sf
139 #define normal_ef s390_normal_ef
140 #define normal_lf s390_normal_lf
141 #define normal_sf s390_normal_sf
142 #define over_under_flow_ef s390_over_under_flow_ef
143 #define over_under_flow_lf s390_over_under_flow_lf
144 #define over_under_flow_sf s390_over_under_flow_sf
145 #define overflow_ef s390_overflow_ef
146 #define overflow_lf s390_overflow_lf
147 #define overflow_sf s390_overflow_sf
148 #define significance_ef s390_significance_ef
149 #define significance_lf s390_significance_lf
150 #define significance_sf s390_significance_sf
151 #define store_ef s390_store_ef
152 #define store_lf s390_store_lf
153 #define store_sf s390_store_sf
154 #define underflow_ef s390_underflow_ef
155 #define underflow_lf s390_underflow_lf
156 #define underflow_sf s390_underflow_sf
157 #define vfetch_lf s390_vfetch_lf
158 #define vfetch_sf s390_vfetch_sf
159 #define add_ef s390_add_ef
160 #define add_lf s390_add_lf
161 #define add_sf s390_add_sf
162 #define cmp_ef s390_cmp_ef
163 #define cmp_lf s390_cmp_lf
164 #define cmp_sf s390_cmp_sf
165 #define div_U128 s390_div_U128
166 #define div_U256 s390_div_U256
167 #define div_ef s390_div_ef
168 #define div_lf s390_div_lf
169 #define div_sf s390_div_sf
170 #define mul_ef s390_mul_ef
171 #define mul_sf s390_mul_sf
172 #define mul_lf s390_mul_lf
173 #define mul_lf_to_ef s390_mul_lf_to_ef
174 #define mul_sf_to_lf s390_mul_sf_to_lf
175 #define square_root_fraction s390_square_root_fraction
176 #define sq_sf s390_sq_sf
177 #define sq_lf s390_sq_lf
178 #elif __GEN_ARCH == 900
179 #define get_ef z900_get_ef
180 #define get_lf z900_get_lf
181 #define get_sf z900_get_sf
182 #define normal_ef z900_normal_ef
183 #define normal_lf z900_normal_lf
184 #define normal_sf z900_normal_sf
185 #define over_under_flow_ef z900_over_under_flow_ef
186 #define over_under_flow_lf z900_over_under_flow_lf
187 #define over_under_flow_sf z900_over_under_flow_sf
188 #define overflow_ef z900_overflow_ef
189 #define overflow_lf z900_overflow_lf
190 #define overflow_sf z900_overflow_sf
191 #define significance_ef z900_significance_ef
192 #define significance_lf z900_significance_lf
193 #define significance_sf z900_significance_sf
194 #define store_ef z900_store_ef
195 #define store_lf z900_store_lf
196 #define store_sf z900_store_sf
197 #define underflow_ef z900_underflow_ef
198 #define underflow_lf z900_underflow_lf
199 #define underflow_sf z900_underflow_sf
200 #define vfetch_lf z900_vfetch_lf
201 #define vfetch_sf z900_vfetch_sf
202 #define add_ef z900_add_ef
203 #define add_lf z900_add_lf
204 #define add_sf z900_add_sf
205 #define cmp_ef z900_cmp_ef
206 #define cmp_lf z900_cmp_lf
207 #define cmp_sf z900_cmp_sf
208 #define div_U128 z900_div_U128
209 #define div_U256 z900_div_U256
210 #define div_ef z900_div_ef
211 #define div_lf z900_div_lf
212 #define div_sf z900_div_sf
213 #define mul_ef z900_mul_ef
214 #define mul_sf z900_mul_sf
215 #define mul_lf z900_mul_lf
216 #define mul_lf_to_ef z900_mul_lf_to_ef
217 #define mul_sf_to_lf z900_mul_sf_to_lf
218 #define square_root_fraction z900_square_root_fraction
219 #define sq_sf z900_sq_sf
220 #define sq_lf z900_sq_lf
221 #else
222 #error Unable to determine GEN_ARCH
223 #endif
224
225 #if !defined(_FLOAT_C)
226
227 #define _FLOAT_C
228
229
230 /*-------------------------------------------------------------------*/
231 /* Definitions */
232 /*-------------------------------------------------------------------*/
233 #define POS 0 /* Positive value of sign */
234 #define NEG 1 /* Negative value of sign */
235 #define UNNORMAL 0 /* Without normalisation */
236 #define NORMAL 1 /* With normalisation */
237 #define OVUNF 1 /* Check for over/underflow */
238 #define NOOVUNF 0 /* Leave exponent as is (for
239 multiply-add/subtrace) */
240 #define SIGEX 1 /* Significance exception if
241 result fraction is zero */
242 #define NOSIGEX 0 /* Do not raise significance
243 exception, use true zero */
244
245 #define FLOAT_DEBUG 0 /* Change to 1 to enable debug messages */
246
247 /*-------------------------------------------------------------------*/
248 /* Add 128 bit unsigned integer */
249 /* The result is placed in operand a */
250 /* */
251 /* msa most significant 64 bit of operand a */
252 /* lsa least significant 64 bit of operand a */
253 /* msb most significant 64 bit of operand b */
254 /* lsb least significant 64 bit of operand b */
255 /* */
256 /* all operands are expected to be defined as U64 */
257 /*-------------------------------------------------------------------*/
258 #define add_U128(msa, lsa, msb, lsb) \
259 (lsa) += (lsb); \
260 (msa) += (msb); \
261 if ((lsa) < (lsb)) \
262 (msa)++
263
264
265 /*-------------------------------------------------------------------*/
266 /* Subtract 128 bit unsigned integer */
267 /* The operand b is subtracted from operand a */
268 /* The result is placed in operand a */
269 /* */
270 /* msa most significant 64 bit of operand a */
271 /* lsa least significant 64 bit of operand a */
272 /* msb most significant 64 bit of operand b */
273 /* lsb least significant 64 bit of operand b */
274 /* */
275 /* all operands are expected to be defined as U64 */
276 /*-------------------------------------------------------------------*/
277 #define sub_U128(msa, lsa, msb, lsb) \
278 (msa) -= (msb); \
279 if ((lsa) < (lsb)) \
280 (msa)--; \
281 (lsa) -= (lsb)
282
283
284 /*-------------------------------------------------------------------*/
285 /* Subtract 128 bit unsigned integer reverse */
286 /* The operand a is subtracted from operand b */
287 /* The result is placed in operand a */
288 /* */
289 /* msa most significant 64 bit of operand a */
290 /* lsa least significant 64 bit of operand a */
291 /* msb most significant 64 bit of operand b */
292 /* lsb least significant 64 bit of operand b */
293 /* */
294 /* all operands are expected to be defined as U64 */
295 /*-------------------------------------------------------------------*/
296 #define sub_reverse_U128(msa, lsa, msb, lsb) \
297 (msa) = (msb) - (msa); \
298 if ((lsb) < (lsa)) \
299 (msa)--; \
300 (lsa) = (lsb) - (lsa)
301
302
303 /*-------------------------------------------------------------------*/
304 /* Shift 128 bit one bit right */
305 /* */
306 /* ms most significant 64 bit of operand */
307 /* ls least significant 64 bit of operand */
308 /* */
309 /* all operands are expected to be defined as U64 */
310 /*-------------------------------------------------------------------*/
311 #define shift_right_U128(ms, ls) \
312 (ls) = ((ls) >> 1) | ((ms) << 63); \
313 (ms) >>= 1
314
315
316 /*-------------------------------------------------------------------*/
317 /* Shift 128 bit one bit left */
318 /* */
319 /* ms most significant 64 bit of operand */
320 /* ls least significant 64 bit of operand */
321 /* */
322 /* all operands are expected to be defined as U64 */
323 /*-------------------------------------------------------------------*/
324 #define shift_left_U128(ms, ls) \
325 (ms) = ((ms) << 1) | ((ls) >> 63); \
326 (ls) <<= 1
327
328 /*-------------------------------------------------------------------*/
329 /* Shift 128 bit 4 bits right with shifted digit */
330 /* */
331 /* ms most significant 64 bit of operand */
332 /* ls least significant 64 bit of operand */
333 /* dig least significant 4 bits removed by right shift */
334 /* */
335 /* all operands are expected to be defined as U64 */
336 /*-------------------------------------------------------------------*/
337 #define shift_right4_U128(ms, ls, dig) \
338 (dig) = (ls) & 0xF; \
339 (ls) = ((ls) >> 4) | ((ms) << 60); \
340 (ms) >>= 4
341
342
343 /*-------------------------------------------------------------------*/
344 /* Shift 128 bit 4 bits left with shifted digit */
345 /* */
346 /* ms most significant 64 bit of operand */
347 /* ls least significant 64 bit of operand */
348 /* dig most significant 4 bits removed by left shift */
349 /* */
350 /* all operands are expected to be defined as U64 */
351 /*-------------------------------------------------------------------*/
352 #define shift_left4_U128(ms, ls, dig) \
353 (dig) = (ms) >> 60; \
354 (ms) = ((ms) << 4) | ((ls) >> 60); \
355 (ls) <<= 4
356
357
358 /*-------------------------------------------------------------------*/
359 /* Shift 256 bit one bit left */
360 /* */
361 /* mms most significant 64 bit of operand */
362 /* ms more significant 64 bit of operand */
363 /* ls less significant 64 bit of operand */
364 /* lls least significant 64 bit of operand */
365 /* */
366 /* all operands are expected to be defined as U64 */
367 /*-------------------------------------------------------------------*/
368 #define shift_left_U256(mms, ms, ls, lls) \
369 (mms) = ((mms) << 1) | ((ms) >> 63); \
370 (ms) = ((ms) << 1) | ((ls) >> 63); \
371 (ls) = ((ls) << 1) | ((lls) >> 63); \
372 (lls) <<= 1
373
374
375 /*-------------------------------------------------------------------*/
376 /* Structure definition for internal short floatingpoint format */
377 /*-------------------------------------------------------------------*/
378 typedef struct _SHORT_FLOAT {
379 U32 short_fract; /* Fraction */
380 short expo; /* Exponent + 64 */
381 BYTE sign; /* Sign */
382 } SHORT_FLOAT;
383
384
385 /*-------------------------------------------------------------------*/
386 /* Structure definition for internal long floatingpoint format */
387 /*-------------------------------------------------------------------*/
388 typedef struct _LONG_FLOAT {
389 U64 long_fract; /* Fraction */
390 short expo; /* Exponent + 64 */
391 BYTE sign; /* Sign */
392 } LONG_FLOAT;
393
394
395 /*-------------------------------------------------------------------*/
396 /* Structure definition for internal extended floatingpoint format */
397 /*-------------------------------------------------------------------*/
398 typedef struct _EXTENDED_FLOAT {
399 U64 ms_fract, ls_fract; /* Fraction */
400 short expo; /* Exponent + 64 */
401 BYTE sign; /* Sign */
402 } EXTENDED_FLOAT;
403
404
405 #endif /*!defined(_FLOAT_C)*/
406
407
408 /*-------------------------------------------------------------------*/
409 /* Static inline functions */
410 /*-------------------------------------------------------------------*/
411
412 /*-------------------------------------------------------------------*/
413 /* Get short float from register */
414 /* */
415 /* Input: */
416 /* fl Internal float format to be converted to */
417 /* fpr Pointer to register to be converted from */
418 /*-------------------------------------------------------------------*/
get_sf(SHORT_FLOAT * fl,U32 * fpr)419 static inline void get_sf( SHORT_FLOAT *fl, U32 *fpr )
420 {
421 fl->sign = *fpr >> 31;
422 fl->expo = (*fpr >> 24) & 0x007F;
423 fl->short_fract = *fpr & 0x00FFFFFF;
424
425 } /* end function get_sf */
426
427
428 /*-------------------------------------------------------------------*/
429 /* Store short float to register */
430 /* */
431 /* Input: */
432 /* fl Internal float format to be converted from */
433 /* fpr Pointer to register to be converted to */
434 /*-------------------------------------------------------------------*/
store_sf(SHORT_FLOAT * fl,U32 * fpr)435 static inline void store_sf( SHORT_FLOAT *fl, U32 *fpr )
436 {
437 *fpr = ((U32)fl->sign << 31)
438 | ((U32)fl->expo << 24)
439 | (fl->short_fract);
440
441 } /* end function store_sf */
442
443
444 /*-------------------------------------------------------------------*/
445 /* Get long float from register */
446 /* */
447 /* Input: */
448 /* fl Internal float format to be converted to */
449 /* fpr Pointer to register to be converted from */
450 /*-------------------------------------------------------------------*/
get_lf(LONG_FLOAT * fl,U32 * fpr)451 static inline void get_lf( LONG_FLOAT *fl, U32 *fpr )
452 {
453 fl->sign = *fpr >> 31;
454 fl->expo = (*fpr >> 24) & 0x007F;
455 fl->long_fract = ((U64)(fpr[0] & 0x00FFFFFF) << 32)
456 | fpr[1];
457
458 } /* end function get_lf */
459
460
461 /*-------------------------------------------------------------------*/
462 /* Store long float to register */
463 /* */
464 /* Input: */
465 /* fl Internal float format to be converted from */
466 /* fpr Pointer to register to be converted to */
467 /*-------------------------------------------------------------------*/
store_lf(LONG_FLOAT * fl,U32 * fpr)468 static inline void store_lf( LONG_FLOAT *fl, U32 *fpr )
469 {
470 fpr[0] = ((U32)fl->sign << 31)
471 | ((U32)fl->expo << 24)
472 | (fl->long_fract >> 32);
473 fpr[1] = fl->long_fract;
474
475 } /* end function store_lf */
476
477
478 /*-------------------------------------------------------------------*/
479 /* Get extended float from register */
480 /* */
481 /* Input: */
482 /* fl Internal float format to be converted to */
483 /* fpr Pointer to register to be converted from */
484 /*-------------------------------------------------------------------*/
get_ef(EXTENDED_FLOAT * fl,U32 * fpr)485 static inline void get_ef( EXTENDED_FLOAT *fl, U32 *fpr )
486 {
487 fl->sign = *fpr >> 31;
488 fl->expo = (*fpr >> 24) & 0x007F;
489 fl->ms_fract = ((U64)(fpr[0] & 0x00FFFFFF) << 24)
490 | (fpr[1] >> 8);
491 fl->ls_fract = (((U64)fpr[1]) << 56)
492 | (((U64)(fpr[FPREX] & 0x00FFFFFF)) << 32)
493 | fpr[FPREX+1];
494
495 } /* end function get_ef */
496
497
498 /*-------------------------------------------------------------------*/
499 /* Store extended float to register */
500 /* */
501 /* Input: */
502 /* fl Internal float format to be converted from */
503 /* fpr Pointer to register to be converted from */
504 /*-------------------------------------------------------------------*/
store_ef(EXTENDED_FLOAT * fl,U32 * fpr)505 static inline void store_ef( EXTENDED_FLOAT *fl, U32 *fpr )
506 {
507 fpr[0] = ((U32)fl->sign << 31)
508 | ((U32)fl->expo << 24)
509 | (fl->ms_fract >> 24);
510 fpr[1] = (fl->ms_fract << 8)
511 | (fl->ls_fract >> 56);
512 fpr[FPREX] = ((U32)fl->sign << 31)
513 | ((fl->ls_fract >> 32) & 0x00FFFFFF);
514 fpr[FPREX+1] = fl->ls_fract;
515
516 if ( fpr[0] || fpr[1] || fpr[FPREX] || fpr[FPREX+1] ) {
517 fpr[FPREX] |= ((((U32)fl->expo - 14) << 24) & 0x7f000000);
518 }
519
520 } /* end function store_ef */
521
522 #if defined(FEATURE_HFP_UNNORMALIZED_EXTENSION)
523 /*-------------------------------------------------------------------*/
524 /* Store extended float high-order part to register unnormalized */
525 /* */
526 /* Input: */
527 /* fl Internal float format to be converted from */
528 /* fpr Pointer to register to be converted to */
529 /*-------------------------------------------------------------------*/
ARCH_DEP(store_ef_unnorm_hi)530 static inline void ARCH_DEP(store_ef_unnorm_hi)( EXTENDED_FLOAT *fl, U32 *fpr )
531 {
532 fpr[0] = ((U32)fl->sign << 31)
533 | (((U32)fl->expo & 0x7f) << 24)
534 | ((fl->ms_fract >> 24) & 0x00FFFFFF);
535 fpr[1] = (fl->ms_fract << 8)
536 | (fl->ls_fract >> 56);
537
538 } /* end ARCH_DEP(store_ef_unnorm_hi) */
539
540
541 /*-------------------------------------------------------------------*/
542 /* Store extended float low-order part to register unnormalized */
543 /* */
544 /* Input: */
545 /* fl Internal float format to be converted from */
546 /* fpr Pointer to register to be converted to */
547 /*-------------------------------------------------------------------*/
ARCH_DEP(store_ef_unnorm_lo)548 static inline void ARCH_DEP(store_ef_unnorm_lo)( EXTENDED_FLOAT *fl, U32 *fpr )
549 {
550 fpr[0] = ((U32)fl->sign << 31)
551 | ((((U32)fl->expo - 14 ) & 0x7f) << 24)
552 | ((fl->ls_fract >> 32) & 0x00FFFFFF);
553 fpr[1] = fl->ls_fract;
554
555 } /* end ARCH_DEP(store_ef_unnorm_lo) */
556
557 /*-------------------------------------------------------------------*/
558 /* Store extended float to register pair unnormalized */
559 /* */
560 /* Input: */
561 /* fl Internal float format to be converted from */
562 /* fpr Pointer to register to be converted to */
563 /*-------------------------------------------------------------------*/
ARCH_DEP(store_ef_unnorm)564 static inline void ARCH_DEP(store_ef_unnorm)( EXTENDED_FLOAT *fl, U32 *fpr )
565 {
566 ARCH_DEP(store_ef_unnorm_hi)(fl,fpr);
567 ARCH_DEP(store_ef_unnorm_lo)(fl,fpr+FPREX);
568
569 } /* end ARCH_DEP(store_ef_unnorm) */
570
571
572 /*-------------------------------------------------------------------*/
573 /* Convert long to extended format unnormalized */
574 /* */
575 /* Input: */
576 /* fl Internal float format to be converted from */
577 /* fpr Pointer to register to be converted to */
578 /*-------------------------------------------------------------------*/
ARCH_DEP(lf_to_ef_unnorm)579 static inline void ARCH_DEP(lf_to_ef_unnorm)
580 ( EXTENDED_FLOAT *fx, LONG_FLOAT *fl )
581 {
582 fx->sign = fl->sign;
583 fx->expo = fl->expo;
584 fx->ms_fract = fl->long_fract >> 8;
585 fx->ls_fract = (fl->long_fract & 0xff) << 56;
586
587 } /* end ARCH_DEP(lf_to_ef_unnorm) */
588
589 #endif /* defined(FEATURE_HFP_UNNORMALIZED_EXTENSION) */
590
591
592 /*-------------------------------------------------------------------*/
593 /* Fetch a short floatingpoint operand from virtual storage */
594 /* */
595 /* Input: */
596 /* fl Internal float format */
597 /* addr Logical address of leftmost byte of operand */
598 /* arn Access register number */
599 /* regs CPU register context */
600 /* */
601 /* A program check may be generated if the logical address */
602 /* causes an addressing, translation, or fetch protection */
603 /* exception, and in this case the function does not return. */
604 /*-------------------------------------------------------------------*/
vfetch_sf(SHORT_FLOAT * fl,VADR addr,int arn,REGS * regs)605 static inline void vfetch_sf( SHORT_FLOAT *fl, VADR addr, int arn,
606 REGS *regs )
607 {
608 U32 value; /* Operand value */
609
610 /* Fetch 4 bytes from operand address */
611 value = ARCH_DEP(vfetch4) (addr, arn, regs);
612
613 /* Extract sign and exponent from high-order byte */
614 fl->sign = value >> 31;
615 fl->expo = (value >> 24) & 0x007F;
616
617 /* Extract fraction from low-order 3 bytes */
618 fl->short_fract = value & 0x00FFFFFF;
619
620 } /* end function vfetch_sf */
621
622
623 /*-------------------------------------------------------------------*/
624 /* Fetch a long floatingpoint operand from virtual storage */
625 /* */
626 /* Input: */
627 /* fl Internal float format */
628 /* addr Logical address of leftmost byte of operand */
629 /* arn Access register number */
630 /* regs CPU register context */
631 /* */
632 /* A program check may be generated if the logical address */
633 /* causes an addressing, translation, or fetch protection */
634 /* exception, and in this case the function does not return. */
635 /*-------------------------------------------------------------------*/
vfetch_lf(LONG_FLOAT * fl,VADR addr,int arn,REGS * regs)636 static inline void vfetch_lf( LONG_FLOAT *fl, VADR addr, int arn,
637 REGS *regs )
638 {
639 U64 value; /* Operand value */
640
641 /* Fetch 8 bytes from operand address */
642 value = ARCH_DEP(vfetch8) (addr, arn, regs);
643
644 /* Extract sign and exponent from high-order byte */
645 fl->sign = value >> 63;
646 fl->expo = (value >> 56) & 0x007F;
647
648 /* Extract fraction from low-order 7 bytes */
649 fl->long_fract = value & 0x00FFFFFFFFFFFFFFULL;
650
651 } /* end function vfetch_lf */
652
653
654 /*-------------------------------------------------------------------*/
655 /* Normalize short float */
656 /* */
657 /* Input: */
658 /* fl Internal float */
659 /*-------------------------------------------------------------------*/
normal_sf(SHORT_FLOAT * fl)660 static inline void normal_sf( SHORT_FLOAT *fl )
661 {
662 if (fl->short_fract) {
663 if ((fl->short_fract & 0x00FFFF00) == 0) {
664 fl->short_fract <<= 16;
665 fl->expo -= 4;
666 }
667 if ((fl->short_fract & 0x00FF0000) == 0) {
668 fl->short_fract <<= 8;
669 fl->expo -= 2;
670 }
671 if ((fl->short_fract & 0x00F00000) == 0) {
672 fl->short_fract <<= 4;
673 (fl->expo)--;
674 }
675 } else {
676 fl->sign = POS;
677 fl->expo = 0;
678 }
679
680 } /* end function normal_sf */
681
682
683 /*-------------------------------------------------------------------*/
684 /* Normalize long float */
685 /* */
686 /* Input: */
687 /* fl Internal float */
688 /*-------------------------------------------------------------------*/
normal_lf(LONG_FLOAT * fl)689 static inline void normal_lf( LONG_FLOAT *fl )
690 {
691 if (fl->long_fract) {
692 if ((fl->long_fract & 0x00FFFFFFFF000000ULL) == 0) {
693 fl->long_fract <<= 32;
694 fl->expo -= 8;
695 }
696 if ((fl->long_fract & 0x00FFFF0000000000ULL) == 0) {
697 fl->long_fract <<= 16;
698 fl->expo -= 4;
699 }
700 if ((fl->long_fract & 0x00FF000000000000ULL) == 0) {
701 fl->long_fract <<= 8;
702 fl->expo -= 2;
703 }
704 if ((fl->long_fract & 0x00F0000000000000ULL) == 0) {
705 fl->long_fract <<= 4;
706 (fl->expo)--;
707 }
708 } else {
709 fl->sign = POS;
710 fl->expo = 0;
711 }
712
713 } /* end function normal_lf */
714
715
716 /*-------------------------------------------------------------------*/
717 /* Normalize extended float */
718 /* */
719 /* Input: */
720 /* fl Internal float */
721 /*-------------------------------------------------------------------*/
normal_ef(EXTENDED_FLOAT * fl)722 static inline void normal_ef( EXTENDED_FLOAT *fl )
723 {
724 if (fl->ms_fract || fl->ls_fract) {
725 if (fl->ms_fract == 0) {
726 fl->ms_fract = fl->ls_fract >> 16;
727 fl->ls_fract <<= 48;
728 fl->expo -= 12;
729 }
730 if ((fl->ms_fract & 0x0000FFFFFFFF0000ULL) == 0) {
731 if (fl->ls_fract) {
732 fl->ms_fract = (fl->ms_fract << 32)
733 | (fl->ls_fract >> 32);
734 fl->ls_fract <<= 32;
735 } else {
736 fl->ms_fract <<= 32;
737 }
738 fl->expo -= 8;
739 }
740 if ((fl->ms_fract & 0x0000FFFF00000000ULL) == 0) {
741 if (fl->ls_fract) {
742 fl->ms_fract = (fl->ms_fract << 16)
743 | (fl->ls_fract >> 48);
744 fl->ls_fract <<= 16;
745 } else {
746 fl->ms_fract <<= 16;
747 }
748 fl->expo -= 4;
749 }
750 if ((fl->ms_fract & 0x0000FF0000000000ULL) == 0) {
751 if (fl->ls_fract) {
752 fl->ms_fract = (fl->ms_fract << 8)
753 | (fl->ls_fract >> 56);
754 fl->ls_fract <<= 8;
755 } else {
756 fl->ms_fract <<= 8;
757 }
758 fl->expo -= 2;
759 }
760 if ((fl->ms_fract & 0x0000F00000000000ULL) == 0) {
761 if (fl->ls_fract) {
762 fl->ms_fract = (fl->ms_fract << 4)
763 | (fl->ls_fract >> 60);
764 fl->ls_fract <<= 4;
765 } else {
766 fl->ms_fract <<= 4;
767 }
768 (fl->expo)--;
769 }
770 } else {
771 fl->sign = POS;
772 fl->expo = 0;
773 }
774
775 } /* end function normal_ef */
776
777
778 /*-------------------------------------------------------------------*/
779 /* Overflow of short float */
780 /* */
781 /* Input: */
782 /* fl Internal float */
783 /* regs CPU register context */
784 /* Value: */
785 /* exeption */
786 /*-------------------------------------------------------------------*/
overflow_sf(SHORT_FLOAT * fl,REGS * regs)787 static inline int overflow_sf( SHORT_FLOAT *fl, REGS *regs )
788 {
789 UNREFERENCED(regs);
790
791 if (fl->expo > 127) {
792 fl->expo &= 0x007F;
793 return(PGM_EXPONENT_OVERFLOW_EXCEPTION);
794 }
795 return(0);
796
797 } /* end function overflow_sf */
798
799
800 /*-------------------------------------------------------------------*/
801 /* Overflow of long float */
802 /* */
803 /* Input: */
804 /* fl Internal float */
805 /* regs CPU register context */
806 /* Value: */
807 /* exeption */
808 /*-------------------------------------------------------------------*/
overflow_lf(LONG_FLOAT * fl,REGS * regs)809 static inline int overflow_lf( LONG_FLOAT *fl, REGS *regs )
810 {
811 UNREFERENCED(regs);
812
813 if (fl->expo > 127) {
814 fl->expo &= 0x007F;
815 return(PGM_EXPONENT_OVERFLOW_EXCEPTION);
816 }
817 return(0);
818
819 } /* end function overflow_lf */
820
821
822 /*-------------------------------------------------------------------*/
823 /* Overflow of extended float */
824 /* */
825 /* Input: */
826 /* fl Internal float */
827 /* regs CPU register context */
828 /* Value: */
829 /* exeption */
830 /*-------------------------------------------------------------------*/
overflow_ef(EXTENDED_FLOAT * fl,REGS * regs)831 static inline int overflow_ef( EXTENDED_FLOAT *fl, REGS *regs )
832 {
833 UNREFERENCED(regs);
834
835 if (fl->expo > 127) {
836 fl->expo &= 0x007F;
837 return(PGM_EXPONENT_OVERFLOW_EXCEPTION);
838 }
839 return(0);
840
841 } /* end function overflow_ef */
842
843
844 /*-------------------------------------------------------------------*/
845 /* Underflow of short float */
846 /* */
847 /* Input: */
848 /* fl Internal float */
849 /* regs CPU register context */
850 /* Value: */
851 /* exeption */
852 /*-------------------------------------------------------------------*/
underflow_sf(SHORT_FLOAT * fl,REGS * regs)853 static inline int underflow_sf( SHORT_FLOAT *fl, REGS *regs )
854 {
855 if (fl->expo < 0) {
856 if (EUMASK(®s->psw)) {
857 fl->expo &= 0x007F;
858 return(PGM_EXPONENT_UNDERFLOW_EXCEPTION);
859 } else {
860 /* set true 0 */
861
862 fl->short_fract = 0;
863 fl->expo = 0;
864 fl->sign = POS;
865 }
866 }
867 return(0);
868
869 } /* end function underflow_sf */
870
871
872 /*-------------------------------------------------------------------*/
873 /* Underflow of long float */
874 /* */
875 /* Input: */
876 /* fl Internal float */
877 /* regs CPU register context */
878 /* Value: */
879 /* exeption */
880 /*-------------------------------------------------------------------*/
underflow_lf(LONG_FLOAT * fl,REGS * regs)881 static inline int underflow_lf( LONG_FLOAT *fl, REGS *regs )
882 {
883 if (fl->expo < 0) {
884 if (EUMASK(®s->psw)) {
885 fl->expo &= 0x007F;
886 return(PGM_EXPONENT_UNDERFLOW_EXCEPTION);
887 } else {
888 /* set true 0 */
889
890 fl->long_fract = 0;
891 fl->expo = 0;
892 fl->sign = POS;
893 }
894 }
895 return(0);
896
897 } /* end function underflow_lf */
898
899
900 /*-------------------------------------------------------------------*/
901 /* Underflow of extended float */
902 /* */
903 /* Input: */
904 /* fl Internal float */
905 /* fpr Pointer to register to be stored to */
906 /* regs CPU register context */
907 /* Value: */
908 /* exeption */
909 /*-------------------------------------------------------------------*/
underflow_ef(EXTENDED_FLOAT * fl,U32 * fpr,REGS * regs)910 static inline int underflow_ef( EXTENDED_FLOAT *fl, U32 *fpr,
911 REGS *regs )
912 {
913 if (fl->expo < 0) {
914 if (EUMASK(®s->psw)) {
915 fl->expo &= 0x007F;
916 store_ef( fl, fpr );
917 return(PGM_EXPONENT_UNDERFLOW_EXCEPTION);
918 } else {
919 /* set true 0 */
920
921 fpr[0] = 0;
922 fpr[1] = 0;
923 fpr[FPREX] = 0;
924 fpr[FPREX+1] = 0;
925 fl->ms_fract = 0;
926 fl->ls_fract = 0;
927 return(0);
928 }
929 }
930
931 store_ef( fl, fpr );
932 return(0);
933
934 } /* end function underflow_ef */
935
936
937 /*-------------------------------------------------------------------*/
938 /* Overflow and underflow of short float */
939 /* */
940 /* Input: */
941 /* fl Internal float */
942 /* regs CPU register context */
943 /* Value: */
944 /* exeption */
945 /*-------------------------------------------------------------------*/
over_under_flow_sf(SHORT_FLOAT * fl,REGS * regs)946 static inline int over_under_flow_sf( SHORT_FLOAT *fl, REGS *regs )
947 {
948 if (fl->expo > 127) {
949 fl->expo &= 0x007F;
950 return(PGM_EXPONENT_OVERFLOW_EXCEPTION);
951 } else {
952 if (fl->expo < 0) {
953 if (EUMASK(®s->psw)) {
954 fl->expo &= 0x007F;
955 return(PGM_EXPONENT_UNDERFLOW_EXCEPTION);
956 } else {
957 /* set true 0 */
958
959 fl->short_fract = 0;
960 fl->expo = 0;
961 fl->sign = POS;
962 }
963 }
964 }
965 return(0);
966
967 } /* end function over_under_flow_sf */
968
969
970 /*-------------------------------------------------------------------*/
971 /* Overflow and underflow of long float */
972 /* */
973 /* Input: */
974 /* fl Internal float */
975 /* regs CPU register context */
976 /* Value: */
977 /* exeption */
978 /*-------------------------------------------------------------------*/
over_under_flow_lf(LONG_FLOAT * fl,REGS * regs)979 static inline int over_under_flow_lf( LONG_FLOAT *fl, REGS *regs )
980 {
981 if (fl->expo > 127) {
982 fl->expo &= 0x007F;
983 return(PGM_EXPONENT_OVERFLOW_EXCEPTION);
984 } else {
985 if (fl->expo < 0) {
986 if (EUMASK(®s->psw)) {
987 fl->expo &= 0x007F;
988 return(PGM_EXPONENT_UNDERFLOW_EXCEPTION);
989 } else {
990 /* set true 0 */
991
992 fl->long_fract = 0;
993 fl->expo = 0;
994 fl->sign = POS;
995 }
996 }
997 }
998 return(0);
999
1000 } /* end function over_under_flow_lf */
1001
1002
1003 /*-------------------------------------------------------------------*/
1004 /* Overflow and underflow of extended float */
1005 /* */
1006 /* Input: */
1007 /* fl Internal float */
1008 /* regs CPU register context */
1009 /* Value: */
1010 /* exeption */
1011 /*-------------------------------------------------------------------*/
over_under_flow_ef(EXTENDED_FLOAT * fl,REGS * regs)1012 static inline int over_under_flow_ef( EXTENDED_FLOAT *fl, REGS *regs )
1013 {
1014 if (fl->expo > 127) {
1015 fl->expo &= 0x007F;
1016 return(PGM_EXPONENT_OVERFLOW_EXCEPTION);
1017 } else {
1018 if (fl->expo < 0) {
1019 if (EUMASK(®s->psw)) {
1020 fl->expo &= 0x007F;
1021 return(PGM_EXPONENT_UNDERFLOW_EXCEPTION);
1022 } else {
1023 /* set true 0 */
1024
1025 fl->ms_fract = 0;
1026 fl->ls_fract = 0;
1027 fl->expo = 0;
1028 fl->sign = POS;
1029 }
1030 }
1031 }
1032 return(0);
1033
1034 } /* end function over_under_flow_ef */
1035
1036
1037 /*-------------------------------------------------------------------*/
1038 /* Significance of short float */
1039 /* The fraction is expected to be zero */
1040 /* */
1041 /* Input: */
1042 /* fl Internal float */
1043 /* sigex Allow significance exception if true */
1044 /* regs CPU register context */
1045 /* Value: */
1046 /* exeption */
1047 /*-------------------------------------------------------------------*/
significance_sf(SHORT_FLOAT * fl,BYTE sigex,REGS * regs)1048 static inline int significance_sf( SHORT_FLOAT *fl, BYTE sigex,
1049 REGS *regs )
1050 {
1051 fl->sign = POS;
1052 if (sigex && SGMASK(®s->psw)) {
1053 return(PGM_SIGNIFICANCE_EXCEPTION);
1054 }
1055 /* set true 0 */
1056
1057 fl->expo = 0;
1058 return(0);
1059
1060 } /* end function significance_sf */
1061
1062
1063 /*-------------------------------------------------------------------*/
1064 /* Significance of long float */
1065 /* The fraction is expected to be zero */
1066 /* */
1067 /* Input: */
1068 /* fl Internal float */
1069 /* sigex Allow significance exception if true */
1070 /* regs CPU register context */
1071 /* Value: */
1072 /* exeption */
1073 /*-------------------------------------------------------------------*/
significance_lf(LONG_FLOAT * fl,BYTE sigex,REGS * regs)1074 static inline int significance_lf( LONG_FLOAT *fl, BYTE sigex,
1075 REGS *regs )
1076 {
1077 fl->sign = POS;
1078 if (sigex && SGMASK(®s->psw)) {
1079 return(PGM_SIGNIFICANCE_EXCEPTION);
1080 }
1081 /* set true 0 */
1082
1083 fl->expo = 0;
1084 return(0);
1085
1086 } /* end function significance_lf */
1087
1088
1089 /*-------------------------------------------------------------------*/
1090 /* Significance of extended float */
1091 /* The fraction is expected to be zero */
1092 /* */
1093 /* Input: */
1094 /* fl Internal float */
1095 /* fpr Pointer to register to be stored to */
1096 /* regs CPU register context */
1097 /* Value: */
1098 /* exeption */
1099 /*-------------------------------------------------------------------*/
significance_ef(EXTENDED_FLOAT * fl,U32 * fpr,REGS * regs)1100 static inline int significance_ef( EXTENDED_FLOAT *fl, U32 *fpr,
1101 REGS *regs )
1102 {
1103 fpr[1] = 0;
1104 fpr[FPREX+1] = 0;
1105
1106 if (SGMASK(®s->psw)) {
1107 fpr[0] = (U32)fl->expo << 24;
1108 fpr[FPREX] = (((U32)fl->expo - 14) << 24) & 0x7f000000;
1109 return(PGM_SIGNIFICANCE_EXCEPTION);
1110 }
1111 /* set true 0 */
1112
1113 fpr[0] = 0;
1114 fpr[FPREX] = 0;
1115 return(0);
1116
1117 } /* end function significance_ef */
1118
1119
1120 /*-------------------------------------------------------------------*/
1121 /* Static functions */
1122 /*-------------------------------------------------------------------*/
1123
1124 /*-------------------------------------------------------------------*/
1125 /* Add short float */
1126 /* */
1127 /* Input: */
1128 /* fl Float */
1129 /* add_fl Float to be added */
1130 /* normal Normalize if true */
1131 /* sigex Allow significance exception if true */
1132 /* regs CPU register context */
1133 /* Value: */
1134 /* exeption */
1135 /*-------------------------------------------------------------------*/
add_sf(SHORT_FLOAT * fl,SHORT_FLOAT * add_fl,BYTE normal,BYTE sigex,REGS * regs)1136 static int add_sf( SHORT_FLOAT *fl, SHORT_FLOAT *add_fl,
1137 BYTE normal, BYTE sigex, REGS *regs )
1138 {
1139 int pgm_check;
1140 BYTE shift;
1141
1142 pgm_check = 0;
1143 if (add_fl->short_fract || add_fl->expo) { /* add_fl not 0 */
1144 if (fl->short_fract || fl->expo) { /* fl not 0 */
1145 /* both not 0 */
1146
1147 if (fl->expo == add_fl->expo) {
1148 /* expo equal */
1149
1150 /* both guard digits */
1151 fl->short_fract <<= 4;
1152 add_fl->short_fract <<= 4;
1153 } else {
1154 /* expo not equal, denormalize */
1155
1156 if (fl->expo < add_fl->expo) {
1157 /* shift minus guard digit */
1158 shift = add_fl->expo - fl->expo - 1;
1159 fl->expo = add_fl->expo;
1160
1161 if (shift) {
1162 if (shift >= 6
1163 || ((fl->short_fract >>= (shift * 4)) == 0)) {
1164 /* 0, copy summand */
1165
1166 fl->sign = add_fl->sign;
1167 fl->short_fract = add_fl->short_fract;
1168
1169 if (fl->short_fract == 0) {
1170 pgm_check = significance_sf(fl, sigex, regs);
1171 } else {
1172 if (normal == NORMAL) {
1173 normal_sf(fl);
1174 pgm_check = underflow_sf(fl, regs);
1175 }
1176 }
1177 return(pgm_check);
1178 }
1179 }
1180 /* guard digit */
1181 add_fl->short_fract <<= 4;
1182 } else {
1183 /* shift minus guard digit */
1184 shift = fl->expo - add_fl->expo - 1;
1185
1186 if (shift) {
1187 if (shift >= 6
1188 || ((add_fl->short_fract >>= (shift * 4)) == 0)) {
1189 /* 0, nothing to add */
1190
1191 if (fl->short_fract == 0) {
1192 pgm_check = significance_sf(fl, sigex, regs);
1193 } else {
1194 if (normal == NORMAL) {
1195 normal_sf(fl);
1196 pgm_check = underflow_sf(fl, regs);
1197 }
1198 }
1199 return(pgm_check);
1200 }
1201 }
1202 /* guard digit */
1203 fl->short_fract <<= 4;
1204 }
1205 }
1206
1207 /* compute with guard digit */
1208 if (fl->sign == add_fl->sign) {
1209 fl->short_fract += add_fl->short_fract;
1210 } else {
1211 if (fl->short_fract == add_fl->short_fract) {
1212 /* true 0 */
1213
1214 fl->short_fract = 0;
1215 return( significance_sf(fl, sigex, regs) );
1216
1217 } else if (fl->short_fract > add_fl->short_fract) {
1218 fl->short_fract -= add_fl->short_fract;
1219 } else {
1220 fl->short_fract = add_fl->short_fract - fl->short_fract;
1221 fl->sign = add_fl->sign;
1222 }
1223 }
1224
1225 /* handle overflow with guard digit */
1226 if (fl->short_fract & 0xF0000000) {
1227 fl->short_fract >>= 8;
1228 (fl->expo)++;
1229 pgm_check = overflow_sf(fl, regs);
1230 } else {
1231
1232 if (normal == NORMAL) {
1233 /* normalize with guard digit */
1234 if (fl->short_fract) {
1235 /* not 0 */
1236
1237 if (fl->short_fract & 0x0F000000) {
1238 /* not normalize, just guard digit */
1239 fl->short_fract >>= 4;
1240 } else {
1241 (fl->expo)--;
1242 normal_sf(fl);
1243 pgm_check = underflow_sf(fl, regs);
1244 }
1245 } else {
1246 /* true 0 */
1247
1248 pgm_check = significance_sf(fl, sigex, regs);
1249 }
1250 } else {
1251 /* not normalize, just guard digit */
1252 fl->short_fract >>= 4;
1253 if (fl->short_fract == 0) {
1254 pgm_check = significance_sf(fl, sigex, regs);
1255 }
1256 }
1257 }
1258 return(pgm_check);
1259 } else { /* fl 0, add_fl not 0 */
1260 /* copy summand */
1261
1262 fl->expo = add_fl->expo;
1263 fl->sign = add_fl->sign;
1264 fl->short_fract = add_fl->short_fract;
1265 if (fl->short_fract == 0) {
1266 return( significance_sf(fl, sigex, regs) );
1267 }
1268 }
1269 } else { /* add_fl 0 */
1270 if (fl->short_fract == 0) { /* fl 0 */
1271 /* both 0 */
1272
1273 return( significance_sf(fl, sigex, regs) );
1274 }
1275 }
1276 if (normal == NORMAL) {
1277 normal_sf(fl);
1278 pgm_check = underflow_sf(fl, regs);
1279 }
1280 return(pgm_check);
1281
1282 } /* end function add_sf */
1283
1284
1285 /*-------------------------------------------------------------------*/
1286 /* Add long float */
1287 /* */
1288 /* Input: */
1289 /* fl Float */
1290 /* add_fl Float to be added */
1291 /* normal Normalize if true */
1292 /* sigex Allow significance exception if true */
1293 /* regs CPU register context */
1294 /* Value: */
1295 /* exeption */
1296 /*-------------------------------------------------------------------*/
add_lf(LONG_FLOAT * fl,LONG_FLOAT * add_fl,BYTE normal,BYTE sigex,REGS * regs)1297 static int add_lf( LONG_FLOAT *fl, LONG_FLOAT *add_fl,
1298 BYTE normal, BYTE sigex, REGS *regs )
1299 {
1300 int pgm_check;
1301 BYTE shift;
1302
1303 pgm_check = 0;
1304 if (add_fl->long_fract || add_fl->expo) { /* add_fl not 0 */
1305 if (fl->long_fract || fl->expo) { /* fl not 0 */
1306 /* both not 0 */
1307
1308 if (fl->expo == add_fl->expo) {
1309 /* expo equal */
1310
1311 /* both guard digits */
1312 fl->long_fract <<= 4;
1313 add_fl->long_fract <<= 4;
1314 } else {
1315 /* expo not equal, denormalize */
1316
1317 if (fl->expo < add_fl->expo) {
1318 /* shift minus guard digit */
1319 shift = add_fl->expo - fl->expo - 1;
1320 fl->expo = add_fl->expo;
1321
1322 if (shift) {
1323 if (shift >= 14
1324 || ((fl->long_fract >>= (shift * 4)) == 0)) {
1325 /* 0, copy summand */
1326
1327 fl->sign = add_fl->sign;
1328 fl->long_fract = add_fl->long_fract;
1329
1330 if (fl->long_fract == 0) {
1331 pgm_check = significance_lf(fl, sigex, regs);
1332 } else {
1333 if (normal == NORMAL) {
1334 normal_lf(fl);
1335 pgm_check = underflow_lf(fl, regs);
1336 }
1337 }
1338 return(pgm_check);
1339 }
1340 }
1341 /* guard digit */
1342 add_fl->long_fract <<= 4;
1343 } else {
1344 /* shift minus guard digit */
1345 shift = fl->expo - add_fl->expo - 1;
1346
1347 if (shift) {
1348 if (shift >= 14
1349 || ((add_fl->long_fract >>= (shift * 4)) == 0)) {
1350 /* 0, nothing to add */
1351
1352 if (fl->long_fract == 0) {
1353 pgm_check = significance_lf(fl, sigex, regs);
1354 } else {
1355 if (normal == NORMAL) {
1356 normal_lf(fl);
1357 pgm_check = underflow_lf(fl, regs);
1358 }
1359 }
1360 return(pgm_check);
1361 }
1362 }
1363 /* guard digit */
1364 fl->long_fract <<= 4;
1365 }
1366 }
1367
1368 /* compute with guard digit */
1369 if (fl->sign == add_fl->sign) {
1370 fl->long_fract += add_fl->long_fract;
1371 } else {
1372 if (fl->long_fract == add_fl->long_fract) {
1373 /* true 0 */
1374
1375 fl->long_fract = 0;
1376 return( significance_lf(fl, sigex, regs) );
1377
1378 } else if (fl->long_fract > add_fl->long_fract) {
1379 fl->long_fract -= add_fl->long_fract;
1380 } else {
1381 fl->long_fract = add_fl->long_fract - fl->long_fract;
1382 fl->sign = add_fl->sign;
1383 }
1384 }
1385
1386 /* handle overflow with guard digit */
1387 if (fl->long_fract & 0xF000000000000000ULL) {
1388 fl->long_fract >>= 8;
1389 (fl->expo)++;
1390 pgm_check = overflow_lf(fl, regs);
1391 } else {
1392
1393 if (normal == NORMAL) {
1394 /* normalize with guard digit */
1395 if (fl->long_fract) {
1396 /* not 0 */
1397
1398 if (fl->long_fract & 0x0F00000000000000ULL) {
1399 /* not normalize, just guard digit */
1400 fl->long_fract >>= 4;
1401 } else {
1402 (fl->expo)--;
1403 normal_lf(fl);
1404 pgm_check = underflow_lf(fl, regs);
1405 }
1406 } else {
1407 /* true 0 */
1408
1409 pgm_check = significance_lf(fl, sigex, regs);
1410 }
1411 } else {
1412 /* not normalize, just guard digit */
1413 fl->long_fract >>= 4;
1414 if (fl->long_fract == 0) {
1415 pgm_check = significance_lf(fl, sigex, regs);
1416 }
1417 }
1418 }
1419 return(pgm_check);
1420 } else { /* fl 0, add_fl not 0 */
1421 /* copy summand */
1422
1423 fl->expo = add_fl->expo;
1424 fl->sign = add_fl->sign;
1425 fl->long_fract = add_fl->long_fract;
1426 if (fl->long_fract == 0) {
1427 return( significance_lf(fl, sigex, regs) );
1428 }
1429 }
1430 } else { /* add_fl 0 */
1431 if (fl->long_fract == 0) { /* fl 0 */
1432 /* both 0 */
1433
1434 return( significance_lf(fl, sigex, regs) );
1435 }
1436 }
1437 if (normal == NORMAL) {
1438 normal_lf(fl);
1439 pgm_check = underflow_lf(fl, regs);
1440 }
1441 return(pgm_check);
1442
1443 } /* end function add_lf */
1444
1445
1446 /*-------------------------------------------------------------------*/
1447 /* Add extended float normalized */
1448 /* */
1449 /* Input: */
1450 /* fl Float */
1451 /* add_fl Float to be added */
1452 /* fpr Pointer to register */
1453 /* regs CPU register context */
1454 /* Value: */
1455 /* exeption */
1456 /*-------------------------------------------------------------------*/
add_ef(EXTENDED_FLOAT * fl,EXTENDED_FLOAT * add_fl,U32 * fpr,REGS * regs)1457 static int add_ef( EXTENDED_FLOAT *fl, EXTENDED_FLOAT *add_fl,
1458 U32 *fpr, REGS *regs )
1459 {
1460 int pgm_check;
1461 BYTE shift;
1462
1463 pgm_check = 0;
1464 if (add_fl->ms_fract || add_fl->ls_fract || add_fl->expo) { /* add_fl not 0 */
1465 if (fl->ms_fract || fl->ls_fract || fl->expo) { /* fl not 0 */
1466 /* both not 0 */
1467
1468 if (fl->expo == add_fl->expo) {
1469 /* expo equal */
1470
1471 /* both guard digits */
1472 fl->ms_fract = (fl->ms_fract << 4)
1473 | (fl->ls_fract >> 60);
1474 fl->ls_fract <<= 4;
1475 add_fl->ms_fract = (add_fl->ms_fract << 4)
1476 | (add_fl->ls_fract >> 60);
1477 add_fl->ls_fract <<= 4;
1478 } else {
1479 /* expo not equal, denormalize */
1480
1481 if (fl->expo < add_fl->expo) {
1482 /* shift minus guard digit */
1483 shift = add_fl->expo - fl->expo - 1;
1484 fl->expo = add_fl->expo;
1485
1486 if (shift) {
1487 if (shift >= 28) {
1488 /* 0, copy summand */
1489
1490 fl->sign = add_fl->sign;
1491 fl->ms_fract = add_fl->ms_fract;
1492 fl->ls_fract = add_fl->ls_fract;
1493
1494 if ((fl->ms_fract == 0)
1495 && (fl->ls_fract == 0)) {
1496 pgm_check = significance_ef(fl, fpr, regs);
1497 } else {
1498 normal_ef(fl);
1499 pgm_check = underflow_ef(fl, fpr, regs);
1500 }
1501 return(pgm_check);
1502 } else if (shift >= 16) {
1503 fl->ls_fract = fl->ms_fract;
1504 if (shift > 16) {
1505 fl->ls_fract >>= (shift - 16) * 4;
1506 }
1507 fl->ms_fract = 0;
1508 } else {
1509 shift *= 4;
1510 fl->ls_fract = fl->ms_fract << (64 - shift)
1511 | fl->ls_fract >> shift;
1512 fl->ms_fract >>= shift;
1513 }
1514
1515 if ((fl->ms_fract == 0)
1516 && (fl->ls_fract == 0)) {
1517 /* 0, copy summand */
1518
1519 fl->sign = add_fl->sign;
1520 fl->ms_fract = add_fl->ms_fract;
1521 fl->ls_fract = add_fl->ls_fract;
1522
1523 if ((fl->ms_fract == 0)
1524 && (fl->ls_fract == 0)) {
1525 pgm_check = significance_ef(fl, fpr, regs);
1526 } else {
1527 normal_ef(fl);
1528 pgm_check = underflow_ef(fl, fpr, regs);
1529 }
1530 return(pgm_check);
1531 }
1532 }
1533 /* guard digit */
1534 add_fl->ms_fract = (add_fl->ms_fract << 4)
1535 | (add_fl->ls_fract >> 60);
1536 add_fl->ls_fract <<= 4;
1537 } else {
1538 /* shift minus guard digit */
1539 shift = fl->expo - add_fl->expo - 1;
1540
1541 if (shift) {
1542 if (shift >= 28) {
1543 /* 0, nothing to add */
1544
1545 if ((fl->ms_fract == 0)
1546 && (fl->ls_fract == 0)) {
1547 pgm_check = significance_ef(fl, fpr, regs);
1548 } else {
1549 normal_ef(fl);
1550 pgm_check = underflow_ef(fl, fpr, regs);
1551 }
1552 return(pgm_check);
1553 } else if (shift >= 16) {
1554 add_fl->ls_fract = add_fl->ms_fract;
1555 if (shift > 16) {
1556 add_fl->ls_fract >>= (shift - 16) * 4;
1557 }
1558 add_fl->ms_fract = 0;
1559 } else {
1560 shift *= 4;
1561 add_fl->ls_fract = add_fl->ms_fract << (64 - shift)
1562 | add_fl->ls_fract >> shift;
1563 add_fl->ms_fract >>= shift;
1564 }
1565
1566 if ((add_fl->ms_fract == 0)
1567 && (add_fl->ls_fract == 0)) {
1568 /* 0, nothing to add */
1569
1570 if ((fl->ms_fract == 0)
1571 && (fl->ls_fract == 0)) {
1572 pgm_check = significance_ef(fl, fpr, regs);
1573 } else {
1574 normal_ef(fl);
1575 pgm_check = underflow_ef(fl, fpr, regs);
1576 }
1577 return(pgm_check);
1578 }
1579 }
1580 /* guard digit */
1581 fl->ms_fract = (fl->ms_fract << 4)
1582 | (fl->ls_fract >> 60);
1583 fl->ls_fract <<= 4;
1584 }
1585 }
1586
1587 /* compute with guard digit */
1588 if (fl->sign == add_fl->sign) {
1589 add_U128(fl->ms_fract, fl->ls_fract, add_fl->ms_fract, add_fl->ls_fract);
1590 } else {
1591 if ((fl->ms_fract == add_fl->ms_fract)
1592 && (fl->ls_fract == add_fl->ls_fract)) {
1593 /* true 0 */
1594
1595 fl->ms_fract = 0;
1596 fl->ls_fract = 0;
1597 return( significance_ef(fl, fpr, regs) );
1598
1599 } else if ( (fl->ms_fract > add_fl->ms_fract)
1600 || ( (fl->ms_fract == add_fl->ms_fract)
1601 && (fl->ls_fract > add_fl->ls_fract))) {
1602 sub_U128(fl->ms_fract, fl->ls_fract, add_fl->ms_fract, add_fl->ls_fract);
1603 } else {
1604 sub_reverse_U128(fl->ms_fract, fl->ls_fract, add_fl->ms_fract, add_fl->ls_fract);
1605 fl->sign = add_fl->sign;
1606 }
1607 }
1608
1609 /* handle overflow with guard digit */
1610 if (fl->ms_fract & 0x00F0000000000000ULL) {
1611 fl->ls_fract = (fl->ms_fract << 56)
1612 | (fl->ls_fract >> 8);
1613 fl->ms_fract >>= 8;
1614 (fl->expo)++;
1615 pgm_check = overflow_ef(fl, regs);
1616 store_ef( fl, fpr );
1617 } else {
1618 /* normalize with guard digit */
1619 if (fl->ms_fract
1620 || fl->ls_fract) {
1621 /* not 0 */
1622
1623 if (fl->ms_fract & 0x000F000000000000ULL) {
1624 /* not normalize, just guard digit */
1625 fl->ls_fract = (fl->ms_fract << 60)
1626 | (fl->ls_fract >> 4);
1627 fl->ms_fract >>= 4;
1628 store_ef( fl, fpr );
1629 } else {
1630 (fl->expo)--;
1631 normal_ef(fl);
1632 pgm_check = underflow_ef(fl, fpr, regs);
1633 }
1634 } else {
1635 /* true 0 */
1636
1637 pgm_check = significance_ef(fl, fpr, regs);
1638 }
1639 }
1640 return(pgm_check);
1641 } else { /* fl 0, add_fl not 0 */
1642 /* copy summand */
1643
1644 fl->expo = add_fl->expo;
1645 fl->sign = add_fl->sign;
1646 fl->ms_fract = add_fl->ms_fract;
1647 fl->ls_fract = add_fl->ls_fract;
1648 if ((fl->ms_fract == 0)
1649 && (fl->ls_fract == 0)) {
1650 return( significance_ef(fl, fpr, regs) );
1651 }
1652 }
1653 } else { /* add_fl 0*/
1654 if ((fl->ms_fract == 0) && (fl->ls_fract == 0)) { /* fl 0 */
1655 /* both 0 */
1656
1657 return( significance_ef(fl, fpr, regs) );
1658 }
1659 }
1660 normal_ef(fl);
1661 return( underflow_ef(fl, fpr, regs) );
1662
1663 } /* end function add_ef */
1664
1665
1666 /*-------------------------------------------------------------------*/
1667 /* Compare short float */
1668 /* */
1669 /* Input: */
1670 /* fl Float */
1671 /* cmp_fl Float to be compared */
1672 /* regs CPU register context */
1673 /*-------------------------------------------------------------------*/
cmp_sf(SHORT_FLOAT * fl,SHORT_FLOAT * cmp_fl,REGS * regs)1674 static void cmp_sf( SHORT_FLOAT *fl, SHORT_FLOAT *cmp_fl, REGS *regs )
1675 {
1676 BYTE shift;
1677
1678 if (cmp_fl->short_fract || cmp_fl->expo) { /* cmp_fl not 0 */
1679 if (fl->short_fract || fl->expo) { /* fl not 0 */
1680 /* both not 0 */
1681
1682 if (fl->expo == cmp_fl->expo) {
1683 /* expo equal */
1684
1685 /* both guard digits */
1686 fl->short_fract <<= 4;
1687 cmp_fl->short_fract <<= 4;
1688 } else {
1689 /* expo not equal, denormalize */
1690
1691 if (fl->expo < cmp_fl->expo) {
1692 /* shift minus guard digit */
1693 shift = cmp_fl->expo - fl->expo - 1;
1694
1695 if (shift) {
1696 if (shift >= 6
1697 || ((fl->short_fract >>= (shift * 4)) == 0)) {
1698 /* Set condition code */
1699 if (cmp_fl->short_fract) {
1700 regs->psw.cc = cmp_fl->sign ? 2 : 1;
1701 } else {
1702 regs->psw.cc = 0;
1703 }
1704 return;
1705 }
1706 }
1707 /* guard digit */
1708 cmp_fl->short_fract <<= 4;
1709 } else {
1710 /* shift minus guard digit */
1711 shift = fl->expo - cmp_fl->expo - 1;
1712
1713 if (shift) {
1714 if (shift >= 6
1715 || ((cmp_fl->short_fract >>= (shift * 4)) == 0)) {
1716 /* Set condition code */
1717 if (fl->short_fract) {
1718 regs->psw.cc = fl->sign ? 1 : 2;
1719 } else {
1720 regs->psw.cc = 0;
1721 }
1722 return;
1723 }
1724 }
1725 /* guard digit */
1726 fl->short_fract <<= 4;
1727 }
1728 }
1729
1730 /* compute with guard digit */
1731 if (fl->sign != cmp_fl->sign) {
1732 fl->short_fract += cmp_fl->short_fract;
1733 } else if (fl->short_fract >= cmp_fl->short_fract) {
1734 fl->short_fract -= cmp_fl->short_fract;
1735 } else {
1736 fl->short_fract = cmp_fl->short_fract - fl->short_fract;
1737 fl->sign = ! (cmp_fl->sign);
1738 }
1739
1740 /* handle overflow with guard digit */
1741 if (fl->short_fract & 0xF0000000) {
1742 fl->short_fract >>= 4;
1743 }
1744
1745 /* Set condition code */
1746 if (fl->short_fract) {
1747 regs->psw.cc = fl->sign ? 1 : 2;
1748 } else {
1749 regs->psw.cc = 0;
1750 }
1751 return;
1752 } else { /* fl 0, cmp_fl not 0 */
1753 /* Set condition code */
1754 if (cmp_fl->short_fract) {
1755 regs->psw.cc = cmp_fl->sign ? 2 : 1;
1756 } else {
1757 regs->psw.cc = 0;
1758 }
1759 return;
1760 }
1761 } else { /* cmp_fl 0 */
1762 /* Set condition code */
1763 if (fl->short_fract) {
1764 regs->psw.cc = fl->sign ? 1 : 2;
1765 } else {
1766 regs->psw.cc = 0;
1767 }
1768 return;
1769 }
1770
1771 } /* end function cmp_sf */
1772
1773
1774 /*-------------------------------------------------------------------*/
1775 /* Compare long float */
1776 /* */
1777 /* Input: */
1778 /* fl Float */
1779 /* cmp_fl Float to be compared */
1780 /* regs CPU register context */
1781 /*-------------------------------------------------------------------*/
cmp_lf(LONG_FLOAT * fl,LONG_FLOAT * cmp_fl,REGS * regs)1782 static void cmp_lf( LONG_FLOAT *fl, LONG_FLOAT *cmp_fl, REGS *regs )
1783 {
1784 BYTE shift;
1785
1786 if (cmp_fl->long_fract || cmp_fl->expo) { /* cmp_fl not 0 */
1787 if (fl->long_fract || fl->expo) { /* fl not 0 */
1788 /* both not 0 */
1789
1790 if (fl->expo == cmp_fl->expo) {
1791 /* expo equal */
1792
1793 /* both guard digits */
1794 fl->long_fract <<= 4;
1795 cmp_fl->long_fract <<= 4;
1796 } else {
1797 /* expo not equal, denormalize */
1798
1799 if (fl->expo < cmp_fl->expo) {
1800 /* shift minus guard digit */
1801 shift = cmp_fl->expo - fl->expo - 1;
1802
1803 if (shift) {
1804 if (shift >= 14 || ((fl->long_fract >>= (shift * 4)) == 0)) {
1805 /* Set condition code */
1806 if (cmp_fl->long_fract) {
1807 regs->psw.cc = cmp_fl->sign ? 2 : 1;
1808 } else {
1809 regs->psw.cc = 0;
1810 }
1811 return;
1812 }
1813 }
1814 /* guard digit */
1815 cmp_fl->long_fract <<= 4;
1816 } else {
1817 /* shift minus guard digit */
1818 shift = fl->expo - cmp_fl->expo - 1;
1819
1820 if (shift) {
1821 if (shift >= 14 || ((cmp_fl->long_fract >>= (shift * 4)) == 0)) {
1822 /* Set condition code */
1823 if (fl->long_fract) {
1824 regs->psw.cc = fl->sign ? 1 : 2;
1825 } else {
1826 regs->psw.cc = 0;
1827 }
1828 return;
1829 }
1830 }
1831 /* guard digit */
1832 fl->long_fract <<= 4;
1833 }
1834 }
1835
1836 /* compute with guard digit */
1837 if (fl->sign != cmp_fl->sign) {
1838 fl->long_fract += cmp_fl->long_fract;
1839 } else if (fl->long_fract >= cmp_fl->long_fract) {
1840 fl->long_fract -= cmp_fl->long_fract;
1841 } else {
1842 fl->long_fract = cmp_fl->long_fract - fl->long_fract;
1843 fl->sign = ! (cmp_fl->sign);
1844 }
1845
1846 /* handle overflow with guard digit */
1847 if (fl->long_fract & 0xF0000000) {
1848 fl->long_fract >>= 4;
1849 }
1850
1851 /* Set condition code */
1852 if (fl->long_fract) {
1853 regs->psw.cc = fl->sign ? 1 : 2;
1854 } else {
1855 regs->psw.cc = 0;
1856 }
1857 return;
1858 } else { /* fl 0, cmp_fl not 0 */
1859 /* Set condition code */
1860 if (cmp_fl->long_fract) {
1861 regs->psw.cc = cmp_fl->sign ? 2 : 1;
1862 } else {
1863 regs->psw.cc = 0;
1864 }
1865 return;
1866 }
1867 } else { /* cmp_fl 0 */
1868 /* Set condition code */
1869 if (fl->long_fract) {
1870 regs->psw.cc = fl->sign ? 1 : 2;
1871 } else {
1872 regs->psw.cc = 0;
1873 }
1874 return;
1875 }
1876
1877 } /* end function cmp_lf */
1878
1879
1880 #if defined (FEATURE_HFP_EXTENSIONS)
1881 /*-------------------------------------------------------------------*/
1882 /* Compare extended float */
1883 /* */
1884 /* Input: */
1885 /* fl Float */
1886 /* cmp_fl Float to be compared */
1887 /* regs CPU register context */
1888 /*-------------------------------------------------------------------*/
cmp_ef(EXTENDED_FLOAT * fl,EXTENDED_FLOAT * cmp_fl,REGS * regs)1889 static void cmp_ef( EXTENDED_FLOAT *fl, EXTENDED_FLOAT *cmp_fl,
1890 REGS *regs )
1891 {
1892 BYTE shift;
1893
1894 if (cmp_fl->ms_fract || cmp_fl->ls_fract || cmp_fl->expo) { /* cmp_fl not 0 */
1895 if (fl->ms_fract || fl->ls_fract || fl->expo) { /* fl not 0 */
1896 /* both not 0 */
1897
1898 if (fl->expo == cmp_fl->expo) {
1899 /* expo equal */
1900
1901 /* both guard digits */
1902 fl->ms_fract = (fl->ms_fract << 4)
1903 | (fl->ls_fract >> 60);
1904 fl->ls_fract <<= 4;
1905 cmp_fl->ms_fract = (cmp_fl->ms_fract << 4)
1906 | (cmp_fl->ls_fract >> 60);
1907 cmp_fl->ls_fract <<= 4;
1908 } else {
1909 /* expo not equal, denormalize */
1910
1911 if (fl->expo < cmp_fl->expo) {
1912 /* shift minus guard digit */
1913 shift = cmp_fl->expo - fl->expo - 1;
1914
1915 if (shift) {
1916 if (shift >= 28) {
1917 /* Set condition code */
1918 if (cmp_fl->ms_fract || cmp_fl->ls_fract) {
1919 regs->psw.cc = cmp_fl->sign ? 2 : 1;
1920 } else {
1921 regs->psw.cc = 0;
1922 }
1923 return;
1924 } else if (shift >= 16) {
1925 fl->ls_fract = fl->ms_fract;
1926 if (shift > 16) {
1927 fl->ls_fract >>= (shift - 16) * 4;
1928 }
1929 fl->ms_fract = 0;
1930 } else {
1931 shift *= 4;
1932 fl->ls_fract = fl->ms_fract << (64 - shift)
1933 | fl->ls_fract >> shift;
1934 fl->ms_fract >>= shift;
1935 }
1936 if ((fl->ms_fract == 0)
1937 && (fl->ls_fract == 0)) {
1938 /* Set condition code */
1939 if (cmp_fl->ms_fract || cmp_fl->ls_fract) {
1940 regs->psw.cc = cmp_fl->sign ? 2 : 1;
1941 } else {
1942 regs->psw.cc = 0;
1943 }
1944 return;
1945 }
1946 }
1947 /* guard digit */
1948 cmp_fl->ms_fract = (cmp_fl->ms_fract << 4)
1949 | (cmp_fl->ls_fract >> 60);
1950 cmp_fl->ls_fract <<= 4;
1951 } else {
1952 /* shift minus guard digit */
1953 shift = fl->expo - cmp_fl->expo - 1;
1954
1955 if (shift) {
1956 if (shift >= 28) {
1957 /* Set condition code */
1958 if (fl->ms_fract || fl->ls_fract) {
1959 regs->psw.cc = fl->sign ? 1 : 2;
1960 } else {
1961 regs->psw.cc = 0;
1962 }
1963 return;
1964 } else if (shift >= 16) {
1965 cmp_fl->ls_fract = cmp_fl->ms_fract;
1966 if (shift > 16) {
1967 cmp_fl->ls_fract >>= (shift - 16) * 4;
1968 }
1969 cmp_fl->ms_fract = 0;
1970 } else {
1971 shift *= 4;
1972 cmp_fl->ls_fract = cmp_fl->ms_fract << (64 - shift)
1973 | cmp_fl->ls_fract >> shift;
1974 cmp_fl->ms_fract >>= shift;
1975 }
1976 if ((cmp_fl->ms_fract == 0)
1977 && (cmp_fl->ls_fract == 0)) {
1978 /* Set condition code */
1979 if (fl->ms_fract || fl->ls_fract) {
1980 regs->psw.cc = fl->sign ? 1 : 2;
1981 } else {
1982 regs->psw.cc = 0;
1983 }
1984 return;
1985 }
1986 }
1987 /* guard digit */
1988 fl->ms_fract = (fl->ms_fract << 4)
1989 | (fl->ls_fract >> 60);
1990 fl->ls_fract <<= 4;
1991 }
1992 }
1993
1994 /* compute with guard digit */
1995 if (fl->sign != cmp_fl->sign) {
1996 add_U128(fl->ms_fract, fl->ls_fract, cmp_fl->ms_fract, cmp_fl->ls_fract);
1997 } else if ((fl->ms_fract > cmp_fl->ms_fract)
1998 || ((fl->ms_fract == cmp_fl->ms_fract)
1999 && (fl->ls_fract >= cmp_fl->ls_fract))) {
2000 sub_U128(fl->ms_fract, fl->ls_fract, cmp_fl->ms_fract, cmp_fl->ls_fract);
2001 } else {
2002 sub_reverse_U128(fl->ms_fract, fl->ls_fract, cmp_fl->ms_fract, cmp_fl->ls_fract);
2003 fl->sign = ! (cmp_fl->sign);
2004 }
2005
2006 /* handle overflow with guard digit */
2007 if (fl->ms_fract & 0x00F0000000000000ULL) {
2008 fl->ls_fract = (fl->ms_fract << 60)
2009 | (fl->ls_fract >> 4);
2010 fl->ms_fract >>= 4;
2011 }
2012
2013 /* Set condition code */
2014 if (fl->ms_fract || fl->ls_fract) {
2015 regs->psw.cc = fl->sign ? 1 : 2;
2016 } else {
2017 regs->psw.cc = 0;
2018 }
2019 return;
2020 } else { /* fl 0, cmp_fl not 0 */
2021 /* Set condition code */
2022 if (cmp_fl->ms_fract || cmp_fl->ls_fract) {
2023 regs->psw.cc = cmp_fl->sign ? 2 : 1;
2024 } else {
2025 regs->psw.cc = 0;
2026 }
2027 return;
2028 }
2029 } else { /* cmp_fl 0 */
2030 /* Set condition code */
2031 if (fl->ms_fract || fl->ls_fract) {
2032 regs->psw.cc = fl->sign ? 1 : 2;
2033 } else {
2034 regs->psw.cc = 0;
2035 }
2036 return;
2037 }
2038
2039 } /* end function cmp_ef */
2040 #endif /*defined (FEATURE_HFP_EXTENSIONS)*/
2041
2042
2043 /*-------------------------------------------------------------------*/
2044 /* Multiply short float to long float */
2045 /* */
2046 /* Input: */
2047 /* fl Multiplicand short float */
2048 /* mul_fl Multiplicator short float */
2049 /* result_fl Result long float */
2050 /* regs CPU register context */
2051 /* Value: */
2052 /* exeption */
2053 /*-------------------------------------------------------------------*/
mul_sf_to_lf(SHORT_FLOAT * fl,SHORT_FLOAT * mul_fl,LONG_FLOAT * result_fl,REGS * regs)2054 static int mul_sf_to_lf( SHORT_FLOAT *fl, SHORT_FLOAT *mul_fl,
2055 LONG_FLOAT *result_fl, REGS *regs )
2056 {
2057 if (fl->short_fract && mul_fl->short_fract) {
2058 /* normalize operands */
2059 normal_sf( fl );
2060 normal_sf( mul_fl );
2061
2062 /* multiply fracts */
2063 result_fl->long_fract = (U64) fl->short_fract * mul_fl->short_fract;
2064
2065 /* normalize result and compute expo */
2066 if (result_fl->long_fract & 0x0000F00000000000ULL) {
2067 result_fl->long_fract <<= 8;
2068 result_fl->expo = fl->expo + mul_fl->expo - 64;
2069 } else {
2070 result_fl->long_fract <<= 12;
2071 result_fl->expo = fl->expo + mul_fl->expo - 65;
2072 }
2073
2074 /* determine sign */
2075 result_fl->sign = (fl->sign == mul_fl->sign) ? POS : NEG;
2076
2077 /* handle overflow and underflow */
2078 return( over_under_flow_lf(result_fl, regs) );
2079 } else {
2080 /* set true 0 */
2081
2082 result_fl->long_fract = 0;
2083 result_fl->expo = 0;
2084 result_fl->sign = POS;
2085 return(0);
2086 }
2087
2088 } /* end function mul_sf_to_lf */
2089
2090
2091 /*-------------------------------------------------------------------*/
2092 /* Multiply long float to extended float */
2093 /* */
2094 /* Input: */
2095 /* fl Multiplicand long float */
2096 /* mul_fl Multiplicator long float */
2097 /* result_fl Result extended float */
2098 /* regs CPU register context */
2099 /* Value: */
2100 /* exeption */
2101 /*-------------------------------------------------------------------*/
mul_lf_to_ef(LONG_FLOAT * fl,LONG_FLOAT * mul_fl,EXTENDED_FLOAT * result_fl,REGS * regs)2102 static int mul_lf_to_ef( LONG_FLOAT *fl, LONG_FLOAT *mul_fl,
2103 EXTENDED_FLOAT *result_fl, REGS *regs )
2104 {
2105 U64 wk;
2106
2107 if (fl->long_fract && mul_fl->long_fract) {
2108 /* normalize operands */
2109 normal_lf( fl );
2110 normal_lf( mul_fl );
2111
2112 /* multiply fracts by sum of partial multiplications */
2113 wk = (fl->long_fract & 0x00000000FFFFFFFFULL) * (mul_fl->long_fract & 0x00000000FFFFFFFFULL);
2114 result_fl->ls_fract = wk & 0x00000000FFFFFFFFULL;
2115
2116 wk >>= 32;
2117 wk += ((fl->long_fract & 0x00000000FFFFFFFFULL) * (mul_fl->long_fract >> 32));
2118 wk += ((fl->long_fract >> 32) * (mul_fl->long_fract & 0x00000000FFFFFFFFULL));
2119 result_fl->ls_fract |= wk << 32;
2120
2121 result_fl->ms_fract = (wk >> 32) + ((fl->long_fract >> 32) * (mul_fl->long_fract >> 32));
2122
2123 /* normalize result and compute expo */
2124 if (result_fl->ms_fract & 0x0000F00000000000ULL) {
2125 result_fl->expo = fl->expo + mul_fl->expo - 64;
2126 } else {
2127 result_fl->ms_fract = (result_fl->ms_fract << 4)
2128 | (result_fl->ls_fract >> 60);
2129 result_fl->ls_fract <<= 4;
2130 result_fl->expo = fl->expo + mul_fl->expo - 65;
2131 }
2132
2133 /* determine sign */
2134 result_fl->sign = (fl->sign == mul_fl->sign) ? POS : NEG;
2135
2136 /* handle overflow and underflow */
2137 return( over_under_flow_ef(result_fl, regs) );
2138 } else {
2139 /* set true 0 */
2140
2141 result_fl->ms_fract = 0;
2142 result_fl->ls_fract = 0;
2143 result_fl->expo = 0;
2144 result_fl->sign = POS;
2145 return(0);
2146 }
2147
2148 } /* end function mul_lf_to_ef */
2149
2150
2151 #if defined(FEATURE_HFP_EXTENSIONS) \
2152 || defined(FEATURE_HFP_MULTIPLY_ADD_SUBTRACT)
2153 /*-------------------------------------------------------------------*/
2154 /* Multiply short float */
2155 /* */
2156 /* Input: */
2157 /* fl Multiplicand short float */
2158 /* mul_fl Multiplicator short float */
2159 /* ovunf Handle overflow/underflow if true */
2160 /* regs CPU register context */
2161 /* Value: */
2162 /* exeption */
2163 /*-------------------------------------------------------------------*/
mul_sf(SHORT_FLOAT * fl,SHORT_FLOAT * mul_fl,BYTE ovunf,REGS * regs)2164 static int mul_sf( SHORT_FLOAT *fl, SHORT_FLOAT *mul_fl,
2165 BYTE ovunf, REGS *regs )
2166 {
2167 U64 wk;
2168
2169 if (fl->short_fract && mul_fl->short_fract) {
2170 /* normalize operands */
2171 normal_sf( fl );
2172 normal_sf( mul_fl );
2173
2174 /* multiply fracts */
2175 wk = (U64) fl->short_fract * mul_fl->short_fract;
2176
2177 /* normalize result and compute expo */
2178 if (wk & 0x0000F00000000000ULL) {
2179 fl->short_fract = wk >> 24;
2180 fl->expo = fl->expo + mul_fl->expo - 64;
2181 } else {
2182 fl->short_fract = wk >> 20;
2183 fl->expo = fl->expo + mul_fl->expo - 65;
2184 }
2185
2186 /* determine sign */
2187 fl->sign = (fl->sign == mul_fl->sign) ? POS : NEG;
2188
2189 /* handle overflow and underflow if required */
2190 if (ovunf == OVUNF)
2191 return( over_under_flow_sf(fl, regs) );
2192
2193 /* otherwise leave exponent as is */
2194 return(0);
2195 } else {
2196 /* set true 0 */
2197
2198 fl->short_fract = 0;
2199 fl->expo = 0;
2200 fl->sign = POS;
2201 return(0);
2202 }
2203
2204 } /* end function mul_sf */
2205 #endif /*FEATURE_HFP_EXTENSIONS || FEATURE_HFP_MULTIPLY_ADD_SUBTRACT*/
2206
2207
2208 /*-------------------------------------------------------------------*/
2209 /* Multiply long float */
2210 /* */
2211 /* Input: */
2212 /* fl Multiplicand long float */
2213 /* mul_fl Multiplicator long float */
2214 /* ovunf Handle overflow/underflow if true */
2215 /* regs CPU register context */
2216 /* Value: */
2217 /* exeption */
2218 /*-------------------------------------------------------------------*/
mul_lf(LONG_FLOAT * fl,LONG_FLOAT * mul_fl,BYTE ovunf,REGS * regs)2219 static int mul_lf( LONG_FLOAT *fl, LONG_FLOAT *mul_fl,
2220 BYTE ovunf, REGS *regs )
2221 {
2222 U64 wk;
2223 U32 v;
2224
2225 if (fl->long_fract && mul_fl->long_fract) {
2226 /* normalize operands */
2227 normal_lf( fl );
2228 normal_lf( mul_fl );
2229
2230 /* multiply fracts by sum of partial multiplications */
2231 wk = ((fl->long_fract & 0x00000000FFFFFFFFULL) * (mul_fl->long_fract & 0x00000000FFFFFFFFULL)) >> 32;
2232
2233 wk += ((fl->long_fract & 0x00000000FFFFFFFFULL) * (mul_fl->long_fract >> 32));
2234 wk += ((fl->long_fract >> 32) * (mul_fl->long_fract & 0x00000000FFFFFFFFULL));
2235 v = wk;
2236
2237 fl->long_fract = (wk >> 32) + ((fl->long_fract >> 32) * (mul_fl->long_fract >> 32));
2238
2239 /* normalize result and compute expo */
2240 if (fl->long_fract & 0x0000F00000000000ULL) {
2241 fl->long_fract = (fl->long_fract << 8)
2242 | (v >> 24);
2243 fl->expo = fl->expo + mul_fl->expo - 64;
2244 } else {
2245 fl->long_fract = (fl->long_fract << 12)
2246 | (v >> 20);
2247 fl->expo = fl->expo + mul_fl->expo - 65;
2248 }
2249
2250 /* determine sign */
2251 fl->sign = (fl->sign == mul_fl->sign) ? POS : NEG;
2252
2253 /* handle overflow and underflow if required */
2254 if (ovunf == OVUNF)
2255 return( over_under_flow_lf(fl, regs) );
2256
2257 /* otherwise leave exponent as is */
2258 return(0);
2259 } else {
2260 /* set true 0 */
2261
2262 fl->long_fract = 0;
2263 fl->expo = 0;
2264 fl->sign = POS;
2265 return(0);
2266 }
2267
2268 } /* end function mul_lf */
2269
2270
2271 /*-------------------------------------------------------------------*/
2272 /* Multiply extended float */
2273 /* */
2274 /* Input: */
2275 /* fl Multiplicand extended float */
2276 /* mul_fl Multiplicator extended float */
2277 /* regs CPU register context */
2278 /* Value: */
2279 /* exeption */
2280 /*-------------------------------------------------------------------*/
mul_ef(EXTENDED_FLOAT * fl,EXTENDED_FLOAT * mul_fl,REGS * regs)2281 static int mul_ef( EXTENDED_FLOAT *fl, EXTENDED_FLOAT *mul_fl,
2282 REGS *regs )
2283 {
2284 U64 wk1;
2285 U64 wk2;
2286 U64 wk3;
2287 U64 wk4;
2288 U64 wk;
2289 U32 wk0;
2290 U32 v;
2291
2292 if ((fl->ms_fract || fl->ls_fract)
2293 && (mul_fl->ms_fract || mul_fl->ls_fract)) {
2294 /* normalize operands */
2295 normal_ef ( fl );
2296 normal_ef ( mul_fl );
2297
2298 /* multiply fracts by sum of partial multiplications */
2299 wk0 = ((fl->ls_fract & 0x00000000FFFFFFFFULL) * (mul_fl->ls_fract & 0x00000000FFFFFFFFULL)) >> 32;
2300
2301 wk1 = (fl->ls_fract & 0x00000000FFFFFFFFULL) * (mul_fl->ls_fract >> 32);
2302 wk2 = (fl->ls_fract >> 32) * (mul_fl->ls_fract & 0x00000000FFFFFFFFULL);
2303 wk = wk0 + (wk1 & 0x00000000FFFFFFFFULL) + (wk2 & 0x00000000FFFFFFFFULL);
2304 wk = (wk >> 32) + (wk1 >> 32) + (wk2 >> 32);
2305
2306 wk1 = (fl->ls_fract & 0x00000000FFFFFFFFULL) * (mul_fl->ms_fract & 0x00000000FFFFFFFFULL);
2307 wk2 = (fl->ls_fract >> 32) * (mul_fl->ls_fract >> 32);
2308 wk3 = (fl->ms_fract & 0x00000000FFFFFFFFULL) * (mul_fl->ls_fract & 0x00000000FFFFFFFFULL);
2309 wk += ((wk1 & 0x00000000FFFFFFFFULL) + (wk2 & 0x00000000FFFFFFFFULL) + (wk3 & 0x00000000FFFFFFFFULL));
2310 wk = (wk >> 32) + (wk1 >> 32) + (wk2 >> 32) + (wk3 >> 32);
2311
2312 wk1 = (fl->ls_fract & 0x00000000FFFFFFFFULL) * (mul_fl->ms_fract >> 32);
2313 wk2 = (fl->ls_fract >> 32) * (mul_fl->ms_fract & 0x00000000FFFFFFFFULL);
2314 wk3 = (fl->ms_fract & 0x00000000FFFFFFFFULL) * (mul_fl->ls_fract >> 32);
2315 wk4 = (fl->ms_fract >> 32) * (mul_fl->ls_fract & 0x00000000FFFFFFFFULL);
2316 wk += ((wk1 & 0x00000000FFFFFFFFULL) + (wk2 & 0x00000000FFFFFFFFULL) + (wk3 & 0x00000000FFFFFFFFULL) + (wk4 & 0x00000000FFFFFFFFULL));
2317 v = wk;
2318 wk = (wk >> 32) + (wk1 >> 32) + (wk2 >> 32) + (wk3 >> 32) + (wk4 >> 32);
2319
2320 wk1 = (fl->ls_fract >> 32) * (mul_fl->ms_fract >> 32);
2321 wk2 = (fl->ms_fract & 0x00000000FFFFFFFFULL) * (mul_fl->ms_fract & 0x00000000FFFFFFFFULL);
2322 wk3 = (fl->ms_fract >> 32) * (mul_fl->ls_fract >> 32);
2323 wk += ((wk1 & 0x00000000FFFFFFFFULL) + (wk2 & 0x00000000FFFFFFFFULL) + (wk3 & 0x00000000FFFFFFFFULL));
2324 fl->ls_fract = wk & 0x00000000FFFFFFFFULL;
2325 wk = (wk >> 32) + (wk1 >> 32) + (wk2 >> 32) + (wk3 >> 32);
2326
2327 wk1 = (fl->ms_fract & 0x00000000FFFFFFFFULL) * (mul_fl->ms_fract >> 32);
2328 wk2 = (fl->ms_fract >> 32) * (mul_fl->ms_fract & 0x00000000FFFFFFFFULL);
2329 wk += ((wk1 & 0x00000000FFFFFFFFULL) + (wk2 & 0x00000000FFFFFFFFULL));
2330 fl->ls_fract |= wk << 32;
2331 wk0 = (wk >> 32) + (wk1 >> 32) + (wk2 >> 32);
2332
2333 wk0 += ((fl->ms_fract >> 32) * (mul_fl->ms_fract >> 32));
2334 fl->ms_fract = wk0;
2335
2336 /* normalize result and compute expo */
2337 if (wk0 & 0xF0000000UL) {
2338 fl->ms_fract = (fl->ms_fract << 16)
2339 | (fl->ls_fract >> 48);
2340 fl->ls_fract = (fl->ls_fract << 16)
2341 | (v >> 16);
2342 fl->expo = fl->expo + mul_fl->expo - 64;
2343 } else {
2344 fl->ms_fract = (fl->ms_fract << 20)
2345 | (fl->ls_fract >> 44);
2346 fl->ls_fract = (fl->ls_fract << 20)
2347 | (v >> 12);
2348 fl->expo = fl->expo + mul_fl->expo - 65;
2349 }
2350
2351 /* determine sign */
2352 fl->sign = (fl->sign == mul_fl->sign) ? POS : NEG;
2353
2354 /* handle overflow and underflow */
2355 return ( over_under_flow_ef (fl, regs) );
2356 } else {
2357 /* set true 0 */
2358
2359 fl->ms_fract = 0;
2360 fl->ls_fract = 0;
2361 fl->expo = 0;
2362 fl->sign = POS;
2363 return (0);
2364 }
2365
2366 } /* end function mul_ef */
2367
2368
2369 /*-------------------------------------------------------------------*/
2370 /* Divide short float */
2371 /* */
2372 /* Input: */
2373 /* fl Dividend short float */
2374 /* div_fl Divisor short float */
2375 /* regs CPU register context */
2376 /* Value: */
2377 /* exeption */
2378 /*-------------------------------------------------------------------*/
div_sf(SHORT_FLOAT * fl,SHORT_FLOAT * div_fl,REGS * regs)2379 static int div_sf( SHORT_FLOAT *fl, SHORT_FLOAT *div_fl, REGS *regs )
2380 {
2381 U64 wk;
2382
2383 if (div_fl->short_fract) {
2384 if (fl->short_fract) {
2385 /* normalize operands */
2386 normal_sf( fl );
2387 normal_sf( div_fl );
2388
2389 /* position fracts and compute expo */
2390 if (fl->short_fract < div_fl->short_fract) {
2391 wk = (U64) fl->short_fract << 24;
2392 fl->expo = fl->expo - div_fl->expo + 64;
2393 } else {
2394 wk = (U64) fl->short_fract << 20;
2395 fl->expo = fl->expo - div_fl->expo + 65;
2396 }
2397 /* divide fractions */
2398 fl->short_fract = wk / div_fl->short_fract;
2399
2400 /* determine sign */
2401 fl->sign = (fl->sign == div_fl->sign) ? POS : NEG;
2402
2403 /* handle overflow and underflow */
2404 return( over_under_flow_sf(fl, regs) );
2405 } else {
2406 /* fraction of dividend 0, set true 0 */
2407
2408 fl->short_fract = 0;
2409 fl->expo = 0;
2410 fl->sign = POS;
2411 }
2412 } else {
2413 /* divisor 0 */
2414
2415 ARCH_DEP(program_interrupt) (regs, PGM_FLOATING_POINT_DIVIDE_EXCEPTION);
2416 }
2417 return(0);
2418
2419 } /* end function div_sf */
2420
2421
2422 /*-------------------------------------------------------------------*/
2423 /* Divide long float */
2424 /* */
2425 /* Input: */
2426 /* fl Dividend long float */
2427 /* div_fl Divisor long float */
2428 /* regs CPU register context */
2429 /* Value: */
2430 /* exeption */
2431 /*-------------------------------------------------------------------*/
div_lf(LONG_FLOAT * fl,LONG_FLOAT * div_fl,REGS * regs)2432 static int div_lf( LONG_FLOAT *fl, LONG_FLOAT *div_fl, REGS *regs )
2433 {
2434 U64 wk;
2435 U64 wk2;
2436 int i;
2437
2438 if (div_fl->long_fract) {
2439 if (fl->long_fract) {
2440 /* normalize operands */
2441 normal_lf( fl );
2442 normal_lf( div_fl );
2443
2444 /* position fracts and compute expo */
2445 if (fl->long_fract < div_fl->long_fract) {
2446 fl->expo = fl->expo - div_fl->expo + 64;
2447 } else {
2448 fl->expo = fl->expo - div_fl->expo + 65;
2449 div_fl->long_fract <<= 4;
2450 }
2451
2452 /* partial divide first hex digit */
2453 wk2 = fl->long_fract / div_fl->long_fract;
2454 wk = (fl->long_fract % div_fl->long_fract) << 4;
2455
2456 /* partial divide middle hex digits */
2457 i = 13;
2458 while (i--) {
2459 wk2 = (wk2 << 4)
2460 | (wk / div_fl->long_fract);
2461 wk = (wk % div_fl->long_fract) << 4;
2462 }
2463
2464 /* partial divide last hex digit */
2465 fl->long_fract = (wk2 << 4)
2466 | (wk / div_fl->long_fract);
2467
2468 /* determine sign */
2469 fl->sign = (fl->sign == div_fl->sign) ? POS : NEG;
2470
2471 /* handle overflow and underflow */
2472 return( over_under_flow_lf(fl, regs) );
2473 } else {
2474 /* fraction of dividend 0, set true 0 */
2475
2476 fl->long_fract = 0;
2477 fl->expo = 0;
2478 fl->sign = POS;
2479 }
2480 } else {
2481 /* divisor 0 */
2482
2483 ARCH_DEP(program_interrupt) (regs, PGM_FLOATING_POINT_DIVIDE_EXCEPTION);
2484 }
2485 return(0);
2486
2487 } /* end function div_lf */
2488
2489
2490 /*-------------------------------------------------------------------*/
2491 /* Divide extended float */
2492 /* */
2493 /* Input: */
2494 /* fl Dividend extended float */
2495 /* div_fl Divisor extended float */
2496 /* regs CPU register context */
2497 /* Value: */
2498 /* exeption */
2499 /*-------------------------------------------------------------------*/
div_ef(EXTENDED_FLOAT * fl,EXTENDED_FLOAT * div_fl,REGS * regs)2500 static int div_ef( EXTENDED_FLOAT *fl, EXTENDED_FLOAT *div_fl,
2501 REGS *regs )
2502 {
2503 U64 wkm;
2504 U64 wkl;
2505 int i;
2506
2507 if (div_fl->ms_fract || div_fl->ls_fract) {
2508 if (fl->ms_fract || fl->ls_fract) {
2509 /* normalize operands */
2510 normal_ef( fl );
2511 normal_ef( div_fl );
2512
2513 /* position fracts and compute expo */
2514 if ((fl->ms_fract < div_fl->ms_fract)
2515 || ((fl->ms_fract == div_fl->ms_fract)
2516 && (fl->ls_fract < div_fl->ls_fract))) {
2517 fl->expo = fl->expo - div_fl->expo + 64;
2518 } else {
2519 fl->expo = fl->expo - div_fl->expo + 65;
2520 div_fl->ms_fract = (div_fl->ms_fract << 4)
2521 | (div_fl->ls_fract >> 60);
2522 div_fl->ls_fract <<= 4;
2523 }
2524
2525 /* divide fractions */
2526
2527 /* the first binary digit */
2528 wkm = fl->ms_fract;
2529 wkl = fl->ls_fract;
2530 sub_U128(wkm, wkl, div_fl->ms_fract, div_fl->ls_fract);
2531 wkm = (wkm << 1)
2532 | (wkl >> 63);
2533 wkl <<= 1;
2534 fl->ms_fract = 0;
2535 if (((S64)wkm) >= 0) {
2536 fl->ls_fract = 1;
2537 sub_U128(wkm, wkl, div_fl->ms_fract, div_fl->ls_fract);
2538 } else {
2539 fl->ls_fract = 0;
2540 add_U128(wkm, wkl, div_fl->ms_fract, div_fl->ls_fract);
2541 }
2542
2543 /* the middle binary digits */
2544 i = 111;
2545 while (i--) {
2546 wkm = (wkm << 1)
2547 | (wkl >> 63);
2548 wkl <<= 1;
2549
2550 fl->ms_fract = (fl->ms_fract << 1)
2551 | (fl->ls_fract >> 63);
2552 fl->ls_fract <<= 1;
2553 if (((S64)wkm) >= 0) {
2554 fl->ls_fract |= 1;
2555 sub_U128(wkm, wkl, div_fl->ms_fract, div_fl->ls_fract);
2556 } else {
2557 add_U128(wkm, wkl, div_fl->ms_fract, div_fl->ls_fract);
2558 }
2559 }
2560
2561 /* the last binary digit */
2562 fl->ms_fract = (fl->ms_fract << 1)
2563 | (fl->ls_fract >> 63);
2564 fl->ls_fract <<= 1;
2565 if (((S64)wkm) >= 0) {
2566 fl->ls_fract |= 1;
2567 }
2568
2569 /* determine sign */
2570 fl->sign = (fl->sign == div_fl->sign) ? POS : NEG;
2571
2572 /* handle overflow and underflow */
2573 return( over_under_flow_ef(fl, regs) );
2574 } else {
2575 /* fraction of dividend 0, set true 0 */
2576
2577 fl->ms_fract = 0;
2578 fl->ls_fract = 0;
2579 fl->expo = 0;
2580 fl->sign = POS;
2581 }
2582 } else {
2583 /* divisor 0 */
2584
2585 ARCH_DEP(program_interrupt) (regs, PGM_FLOATING_POINT_DIVIDE_EXCEPTION);
2586 }
2587 return(0);
2588
2589 } /* end function div_ef */
2590
2591
2592 #if defined (FEATURE_SQUARE_ROOT)
2593 /*-------------------------------------------------------------------*/
2594 /* Square root of fraction */
2595 /* This routine uses the Newton-Iteration-Method */
2596 /* The iteration is startet with a table look up */
2597 /* */
2598 /* Input: */
2599 /* a short fraction expanded to U64 */
2600 /* Value: */
2601 /* square root as U32 */
2602 /*-------------------------------------------------------------------*/
square_root_fraction(U64 a)2603 static U32 square_root_fraction( U64 a )
2604 {
2605 U32 xi;
2606 U32 xj;
2607 static const unsigned short sqtab[] = {
2608 /* 0 */ 0,
2609 /* 1 */ 304,
2610 /* 2 */ 401,
2611 /* 3 */ 476,
2612 /* 4 */ 541,
2613 /* 5 */ 599,
2614 /* 6 */ 652,
2615 /* 7 */ 700,
2616 /* 8 */ 746,
2617 /* 9 */ 788,
2618 /* 10 */ 829,
2619 /* 11 */ 868,
2620 /* 12 */ 905,
2621 /* 13 */ 940,
2622 /* 14 */ 975,
2623 /* 15 */ 1008,
2624 /* 16 */ 1040,
2625 /* 17 */ 1071,
2626 /* 18 */ 1101,
2627 /* 19 */ 1130,
2628 /* 20 */ 1159,
2629 /* 21 */ 1187,
2630 /* 22 */ 1214,
2631 /* 23 */ 1241,
2632 /* 24 */ 1267,
2633 /* 25 */ 1293,
2634 /* 26 */ 1318,
2635 /* 27 */ 1342,
2636 /* 28 */ 1367,
2637 /* 29 */ 1390,
2638 /* 30 */ 1414,
2639 /* 31 */ 1437,
2640 /* 32 */ 1459,
2641 /* 33 */ 1482,
2642 /* 34 */ 1504,
2643 /* 35 */ 1525,
2644 /* 36 */ 1547,
2645 /* 37 */ 1568,
2646 /* 38 */ 1588,
2647 /* 39 */ 1609,
2648 /* 40 */ 1629,
2649 /* 41 */ 1649,
2650 /* 42 */ 1669,
2651 /* 43 */ 1688,
2652 /* 44 */ 1708,
2653 /* 45 */ 1727,
2654 /* 46 */ 1746,
2655 /* 47 */ 1764,
2656 /* 48 */ 1783,
2657 /* 49 */ 1801,
2658 /* 50 */ 1819,
2659 /* 51 */ 1837,
2660 /* 52 */ 1855,
2661 /* 53 */ 1872,
2662 /* 54 */ 1890,
2663 /* 55 */ 1907,
2664 /* 56 */ 1924,
2665 /* 57 */ 1941,
2666 /* 58 */ 1958,
2667 /* 59 */ 1975,
2668 /* 60 */ 1991,
2669 /* 61 */ 2008,
2670 /* 62 */ 2024,
2671 /* 63 */ 2040,
2672 /* 64 */ 2056,
2673 /* 65 */ 2072,
2674 /* 66 */ 2088,
2675 /* 67 */ 2103,
2676 /* 68 */ 2119,
2677 /* 69 */ 2134,
2678 /* 70 */ 2149,
2679 /* 71 */ 2165,
2680 /* 72 */ 2180,
2681 /* 73 */ 2195,
2682 /* 74 */ 2210,
2683 /* 75 */ 2224,
2684 /* 76 */ 2239,
2685 /* 77 */ 2254,
2686 /* 78 */ 2268,
2687 /* 79 */ 2283,
2688 /* 80 */ 2297,
2689 /* 81 */ 2311,
2690 /* 82 */ 2325,
2691 /* 83 */ 2339,
2692 /* 84 */ 2353,
2693 /* 85 */ 2367,
2694 /* 86 */ 2381,
2695 /* 87 */ 2395,
2696 /* 88 */ 2408,
2697 /* 89 */ 2422,
2698 /* 90 */ 2435,
2699 /* 91 */ 2449,
2700 /* 92 */ 2462,
2701 /* 93 */ 2475,
2702 /* 94 */ 2489,
2703 /* 95 */ 2502,
2704 /* 96 */ 2515,
2705 /* 97 */ 2528,
2706 /* 98 */ 2541,
2707 /* 99 */ 2554,
2708 /* 100 */ 2566,
2709 /* 101 */ 2579,
2710 /* 102 */ 2592,
2711 /* 103 */ 2604,
2712 /* 104 */ 2617,
2713 /* 105 */ 2629,
2714 /* 106 */ 2642,
2715 /* 107 */ 2654,
2716 /* 108 */ 2667,
2717 /* 109 */ 2679,
2718 /* 110 */ 2691,
2719 /* 111 */ 2703,
2720 /* 112 */ 2715,
2721 /* 113 */ 2727,
2722 /* 114 */ 2739,
2723 /* 115 */ 2751,
2724 /* 116 */ 2763,
2725 /* 117 */ 2775,
2726 /* 118 */ 2787,
2727 /* 119 */ 2798,
2728 /* 120 */ 2810,
2729 /* 121 */ 2822,
2730 /* 122 */ 2833,
2731 /* 123 */ 2845,
2732 /* 124 */ 2856,
2733 /* 125 */ 2868,
2734 /* 126 */ 2879,
2735 /* 127 */ 2891,
2736 /* 128 */ 2902,
2737 /* 129 */ 2913,
2738 /* 130 */ 2924,
2739 /* 131 */ 2936,
2740 /* 132 */ 2947,
2741 /* 133 */ 2958,
2742 /* 134 */ 2969,
2743 /* 135 */ 2980,
2744 /* 136 */ 2991,
2745 /* 137 */ 3002,
2746 /* 138 */ 3013,
2747 /* 139 */ 3024,
2748 /* 140 */ 3034,
2749 /* 141 */ 3045,
2750 /* 142 */ 3056,
2751 /* 143 */ 3067,
2752 /* 144 */ 3077,
2753 /* 145 */ 3088,
2754 /* 146 */ 3099,
2755 /* 147 */ 3109,
2756 /* 148 */ 3120,
2757 /* 149 */ 3130,
2758 /* 150 */ 3141,
2759 /* 151 */ 3151,
2760 /* 152 */ 3161,
2761 /* 153 */ 3172,
2762 /* 154 */ 3182,
2763 /* 155 */ 3192,
2764 /* 156 */ 3203,
2765 /* 157 */ 3213,
2766 /* 158 */ 3223,
2767 /* 159 */ 3233,
2768 /* 160 */ 3243,
2769 /* 161 */ 3253,
2770 /* 162 */ 3263,
2771 /* 163 */ 3273,
2772 /* 164 */ 3283,
2773 /* 165 */ 3293,
2774 /* 166 */ 3303,
2775 /* 167 */ 3313,
2776 /* 168 */ 3323,
2777 /* 169 */ 3333,
2778 /* 170 */ 3343,
2779 /* 171 */ 3353,
2780 /* 172 */ 3362,
2781 /* 173 */ 3372,
2782 /* 174 */ 3382,
2783 /* 175 */ 3391,
2784 /* 176 */ 3401,
2785 /* 177 */ 3411,
2786 /* 178 */ 3420,
2787 /* 179 */ 3430,
2788 /* 180 */ 3439,
2789 /* 181 */ 3449,
2790 /* 182 */ 3458,
2791 /* 183 */ 3468,
2792 /* 184 */ 3477,
2793 /* 185 */ 3487,
2794 /* 186 */ 3496,
2795 /* 187 */ 3505,
2796 /* 188 */ 3515,
2797 /* 189 */ 3524,
2798 /* 190 */ 3533,
2799 /* 191 */ 3543,
2800 /* 192 */ 3552,
2801 /* 193 */ 3561,
2802 /* 194 */ 3570,
2803 /* 195 */ 3579,
2804 /* 196 */ 3589,
2805 /* 197 */ 3598,
2806 /* 198 */ 3607,
2807 /* 199 */ 3616,
2808 /* 200 */ 3625,
2809 /* 201 */ 3634,
2810 /* 202 */ 3643,
2811 /* 203 */ 3652,
2812 /* 204 */ 3661,
2813 /* 205 */ 3670,
2814 /* 206 */ 3679,
2815 /* 207 */ 3688,
2816 /* 208 */ 3697,
2817 /* 209 */ 3705,
2818 /* 210 */ 3714,
2819 /* 211 */ 3723,
2820 /* 212 */ 3732,
2821 /* 213 */ 3741,
2822 /* 214 */ 3749,
2823 /* 215 */ 3758,
2824 /* 216 */ 3767,
2825 /* 217 */ 3775,
2826 /* 218 */ 3784,
2827 /* 219 */ 3793,
2828 /* 220 */ 3801,
2829 /* 221 */ 3810,
2830 /* 222 */ 3819,
2831 /* 223 */ 3827,
2832 /* 224 */ 3836,
2833 /* 225 */ 3844,
2834 /* 226 */ 3853,
2835 /* 227 */ 3861,
2836 /* 228 */ 3870,
2837 /* 229 */ 3878,
2838 /* 230 */ 3887,
2839 /* 231 */ 3895,
2840 /* 232 */ 3903,
2841 /* 233 */ 3912,
2842 /* 234 */ 3920,
2843 /* 235 */ 3929,
2844 /* 236 */ 3937,
2845 /* 237 */ 3945,
2846 /* 238 */ 3954,
2847 /* 239 */ 3962,
2848 /* 240 */ 3970,
2849 /* 241 */ 3978,
2850 /* 242 */ 3987,
2851 /* 243 */ 3995,
2852 /* 244 */ 4003,
2853 /* 245 */ 4011,
2854 /* 246 */ 4019,
2855 /* 247 */ 4027,
2856 /* 248 */ 4036,
2857 /* 249 */ 4044,
2858 /* 250 */ 4052,
2859 /* 251 */ 4060,
2860 /* 252 */ 4068,
2861 /* 253 */ 4076,
2862 /* 254 */ 4084,
2863 /* 255 */ 4092 };
2864
2865 /* initial table look up */
2866 xi = ((U32) sqtab[a >> 48]) << 16;
2867
2868 if (xi == 0)
2869 return(xi);
2870
2871 /* iterate */
2872 /* exit iteration when xi, xj equal or differ by 1 */
2873 for (;;) {
2874 xj = (((U32)(a / xi)) + xi) >> 1;
2875
2876 if ((xj == xi) || (abs(xj - xi) == 1)) {
2877 break;
2878 }
2879 xi = xj;
2880 }
2881
2882 return(xj);
2883
2884 } /* end function square_root_fraction */
2885
2886
2887 /*-------------------------------------------------------------------*/
2888 /* Divide 128 bit integer by 64 bit integer */
2889 /* The result is returned as 64 bit integer */
2890 /* */
2891 /* Input: */
2892 /* msa most significant 64 bit of dividend */
2893 /* lsa least significant 64 bit of dividend */
2894 /* div divisor */
2895 /* Value: */
2896 /* quotient */
2897 /*-------------------------------------------------------------------*/
div_U128(U64 msa,U64 lsa,U64 div)2898 static U64 div_U128( U64 msa, U64 lsa, U64 div )
2899 {
2900 U64 q;
2901 int i;
2902
2903 /* the first binary digit */
2904 msa -= div;
2905 shift_left_U128(msa, lsa);
2906
2907 if (((S64)msa) >= 0) {
2908 q = 1;
2909 msa -= div;
2910 } else {
2911 q = 0;
2912 msa += div;
2913 }
2914
2915 /* the middle binary digits */
2916 i = 63;
2917 while (i--) {
2918 shift_left_U128(msa, lsa);
2919
2920 q <<= 1;
2921 if (((S64)msa) >= 0) {
2922 q |= 1;
2923 msa -= div;
2924 } else {
2925 msa += div;
2926 }
2927 }
2928
2929 /* the last binary digit */
2930 q <<= 1;
2931 if (((S64)msa) >= 0) {
2932 q |= 1;
2933 }
2934
2935 return(q);
2936
2937 } /* end function div_U128 */
2938
2939
2940 /*-------------------------------------------------------------------*/
2941 /* Square root short float */
2942 /* */
2943 /* Input: */
2944 /* sq_fl Result short float */
2945 /* fl Input short float */
2946 /* regs CPU register context */
2947 /*-------------------------------------------------------------------*/
sq_sf(SHORT_FLOAT * sq_fl,SHORT_FLOAT * fl,REGS * regs)2948 static void sq_sf( SHORT_FLOAT *sq_fl, SHORT_FLOAT *fl, REGS *regs )
2949 {
2950 U64 a;
2951 U32 x;
2952
2953 if (fl->short_fract) {
2954 if (fl->sign) {
2955 /* less than zero */
2956 sq_fl->short_fract = 0;
2957 sq_fl->expo = 0;
2958
2959 ARCH_DEP(program_interrupt) (regs, PGM_SQUARE_ROOT_EXCEPTION);
2960 } else {
2961 /* normalize operand */
2962 normal_sf(fl);
2963
2964 if (fl->expo & 1) {
2965 /* odd */
2966
2967 /* compute characteristic */
2968 sq_fl->expo = (fl->expo + 65) >> 1;
2969
2970 /* with guard digit */
2971 a = (U64) fl->short_fract << 28;
2972 } else {
2973 /* even */
2974
2975 /* compute characteristic */
2976 sq_fl->expo = (fl->expo + 64) >> 1;
2977
2978 /* without guard digit */
2979 a = (U64) fl->short_fract << 32;
2980 }
2981
2982 /* square root of fraction */
2983 /* common subroutine of all square root */
2984 x = square_root_fraction(a);
2985
2986 /* round with guard digit */
2987 sq_fl->short_fract = (x + 8) >> 4;
2988 }
2989 } else {
2990 /* true zero */
2991 sq_fl->short_fract = 0;
2992 sq_fl->expo = 0;
2993 }
2994 /* all results positive */
2995 sq_fl->sign = POS;
2996
2997 } /* end function sq_sf */
2998
2999
3000 /*-------------------------------------------------------------------*/
3001 /* Square root long float */
3002 /* */
3003 /* Input: */
3004 /* sq_fl Result long float */
3005 /* fl Input long float */
3006 /* regs CPU register context */
3007 /*-------------------------------------------------------------------*/
sq_lf(LONG_FLOAT * sq_fl,LONG_FLOAT * fl,REGS * regs)3008 static void sq_lf( LONG_FLOAT *sq_fl, LONG_FLOAT *fl, REGS *regs )
3009 {
3010 U64 msa, lsa;
3011 U64 xi;
3012 U64 xj;
3013
3014 if (fl->long_fract) {
3015 if (fl->sign) {
3016 /* less than zero */
3017
3018 ARCH_DEP(program_interrupt) (regs, PGM_SQUARE_ROOT_EXCEPTION);
3019 } else {
3020 /* normalize operand */
3021 normal_lf(fl);
3022
3023 if (fl->expo & 1) {
3024 /* odd */
3025
3026 /* compute characteristic */
3027 sq_fl->expo = (fl->expo + 65) >> 1;
3028
3029 /* with guard digit */
3030 msa = fl->long_fract >> 4;
3031 lsa = fl->long_fract << 60;
3032 } else {
3033 /* even */
3034
3035 /* compute characteristic */
3036 sq_fl->expo = (fl->expo + 64) >> 1;
3037
3038 /* without guard digit */
3039 msa = fl->long_fract;
3040 lsa = 0;
3041 }
3042
3043 /* square root of fraction low precision */
3044 /* common subroutine of all square root */
3045 xi = ((U64) (square_root_fraction(msa & 0xFFFFFFFFFFFFFFFEULL)) << 32)
3046 | 0x80000000UL;
3047
3048 /* continue iteration for high precision */
3049 for (;;) {
3050 xj = (div_U128(msa, lsa, xi) + xi) >> 1;
3051
3052 if (xj == xi) {
3053 break;
3054 }
3055 xi = xj;
3056 }
3057
3058 /* round with guard digit */
3059 sq_fl->long_fract = (xi + 8) >> 4;
3060 }
3061 } else {
3062 /* true zero */
3063 sq_fl->long_fract = 0;
3064 sq_fl->expo = 0;
3065 }
3066 /* all results positive */
3067 sq_fl->sign = POS;
3068
3069 } /* end function sq_lf */
3070 #endif /* FEATURE_SQUARE_ROOT */
3071
3072
3073 #if defined (FEATURE_HFP_EXTENSIONS)
3074 /*-------------------------------------------------------------------*/
3075 /* Divide 256 bit integer by 128 bit integer */
3076 /* The result is returned as 128 bit integer */
3077 /* */
3078 /* Input: */
3079 /* mmsa most significant 64 bit of dividend */
3080 /* msa more significant 64 bit of dividend */
3081 /* lsa less significant 64 bit of dividend */
3082 /* llsa least significant 64 bit of dividend */
3083 /* msd most significant 64 bit of divisor */
3084 /* lsd least significant 64 bit of divisor */
3085 /* msq most significant 64 bit of quotient */
3086 /* lsq least significant 64 bit of quotient */
3087 /*-------------------------------------------------------------------*/
div_U256(U64 mmsa,U64 msa,U64 lsa,U64 llsa,U64 msd,U64 lsd,U64 * msq,U64 * lsq)3088 static void div_U256( U64 mmsa, U64 msa, U64 lsa, U64 llsa, U64 msd,
3089 U64 lsd, U64 *msq, U64 *lsq )
3090 {
3091 int i;
3092
3093 /* the first binary digit */
3094 sub_U128(mmsa, msa, msd, lsd);
3095 shift_left_U256(mmsa, msa, lsa, llsa);
3096
3097 *msq = 0;
3098 if (((S64)mmsa) >= 0) {
3099 *lsq = 1;
3100 sub_U128(mmsa, msa, msd, lsd);
3101 } else {
3102 *lsq = 0;
3103 add_U128(mmsa, msa, msd, lsd);
3104 }
3105
3106 /* the middle binary digits */
3107 i = 127;
3108 while (i--) {
3109 shift_left_U256(mmsa, msa, lsa, llsa);
3110
3111 shift_left_U128(*msq, *lsq);
3112 if (((S64)mmsa) >= 0) {
3113 *lsq |= 1;
3114 sub_U128(mmsa, msa, msd, lsd);
3115 } else {
3116 add_U128(mmsa, msa, msd, lsd);
3117 }
3118 }
3119
3120 /* the last binary digit */
3121 shift_left_U128(*msq, *lsq);
3122 if (((S64)mmsa) >= 0) {
3123 *lsq |= 1;
3124 }
3125
3126 } /* end function div_U256 */
3127 #endif /* FEATURE_HFP_EXTENSIONS */
3128
3129 #if defined(FEATURE_HFP_UNNORMALIZED_EXTENSION)
3130 /*-------------------------------------------------------------------*/
3131 /* Multiply long float to extended float unnormalized */
3132 /* */
3133 /* Input: */
3134 /* fl Multiplicand long float */
3135 /* mul_fl Multiplicator long float */
3136 /* result_fl Intermediate extended float result */
3137 /* regs CPU register context */
3138 /* Value: */
3139 /* none */
3140 /*-------------------------------------------------------------------*/
ARCH_DEP(mul_lf_to_ef_unnorm)3141 static void ARCH_DEP(mul_lf_to_ef_unnorm)(
3142 LONG_FLOAT *fl, LONG_FLOAT *mul_fl,
3143 EXTENDED_FLOAT *result_fl )
3144 {
3145 U64 wk;
3146
3147 /* multiply fracts by sum of partial multiplications */
3148 wk = (fl->long_fract & 0x00000000FFFFFFFFULL) * (mul_fl->long_fract & 0x00000000FFFFFFFFULL);
3149 result_fl->ls_fract = wk & 0x00000000FFFFFFFFULL;
3150
3151 wk >>= 32;
3152 wk += ((fl->long_fract & 0x00000000FFFFFFFFULL) * (mul_fl->long_fract >> 32));
3153 wk += ((fl->long_fract >> 32) * (mul_fl->long_fract & 0x00000000FFFFFFFFULL));
3154 result_fl->ls_fract |= wk << 32;
3155
3156 result_fl->ms_fract = (wk >> 32) + ((fl->long_fract >> 32) * (mul_fl->long_fract >> 32));
3157
3158 /* compute expo */
3159 result_fl->expo = fl->expo + mul_fl->expo - 64;
3160
3161 /* determine sign */
3162 result_fl->sign = (fl->sign == mul_fl->sign) ? POS : NEG;
3163
3164 } /* end function mul_lf_to_ef_unnorm */
3165
3166
3167 /*-------------------------------------------------------------------*/
3168 /* Add extended float unnormalized */
3169 /* Note: This addition is specific to MULTIPLY AND ADD UNNORMALIZED */
3170 /* set of instructions */
3171 /* */
3172 /* Input: */
3173 /* prod_fl Extended Intermediate product */
3174 /* add_fl Extended Addend */
3175 /* result_fl Extended Intermediate result */
3176 /* Value: */
3177 /* none */
3178 /*-------------------------------------------------------------------*/
ARCH_DEP(add_ef_unnorm)3179 static void ARCH_DEP(add_ef_unnorm)(
3180 EXTENDED_FLOAT *prod_fl, EXTENDED_FLOAT *add_fl,
3181 EXTENDED_FLOAT *result_fl )
3182 {
3183 int ldigits = 0; /* or'd left digits shifted */
3184 int rdigits = 0; /* or'd right digits shifted */
3185 int xdigit; /* digit lost by addend shifting */
3186
3187 /* Note: In EXTENDED_FLOAT, ms_fract and ls_fract taken together*/
3188 /* constitute a U128 value. */
3189
3190 /* Convert separate high/low fractions to contiguous U128 */
3191 #if FLOAT_DEBUG
3192 logmsg (_("Prod Frac: %16.16llX %16.16llX\n"),
3193 prod_fl->ms_fract, prod_fl->ls_fract);
3194
3195 logmsg (_("Adnd Frac: %16.16llX %16.16llX\n"),
3196 add_fl->ms_fract, add_fl->ls_fract);
3197 #endif
3198
3199 result_fl->ms_fract = 0;
3200 result_fl->ls_fract = 0;
3201
3202 /* Default result to product sign in case addend expo == prod expo */
3203 result_fl->sign = prod_fl->sign;
3204
3205 /* Step one - shift addend to match product's characteristic */
3206 if (add_fl->expo < prod_fl->expo)
3207 {
3208 while(add_fl->expo != prod_fl->expo)
3209 {
3210 if ((!add_fl->ms_fract) && (!add_fl->ls_fract))
3211 { /* If both the high and low parts of the fraction are zero */
3212 /* we don't need to shift any more digits. */
3213 /* Just force the exponents equal and quit */
3214 add_fl->expo = prod_fl->expo;
3215 break;
3216 }
3217 /* shift addend fraction right until characteristics are equal */
3218 shift_right4_U128(add_fl->ms_fract, add_fl->ls_fract, xdigit);
3219 rdigits |= xdigit;
3220 add_fl->expo += 1;
3221 }
3222 }
3223 else if(add_fl->expo > prod_fl->expo)
3224 {
3225 while(add_fl->expo != prod_fl->expo)
3226 {
3227 if ((!add_fl->ms_fract) && (!add_fl->ls_fract))
3228 { /* If both the high and low parts of the fraction are zero */
3229 /* we don't need to shift any more digits. */
3230 /* Just force the exponents equal and quit */
3231 add_fl->expo = prod_fl->expo;
3232 break;
3233 }
3234
3235 /* shift addend fraction right until characteristics are equal */
3236 shift_left4_U128(add_fl->ms_fract, add_fl->ls_fract, xdigit);
3237 ldigits |= xdigit;
3238 add_fl->expo -= 1;
3239 }
3240 }
3241 #if FLOAT_DEBUG
3242 logmsg (_("Shft Frac: %16.16llX %16.16llX\n"),
3243 add_fl->ms_fract, add_fl->ls_fract);
3244 #endif
3245
3246 /* Step 2 - Do algebraic addition of aligned fractions */
3247 if (add_fl->sign == prod_fl->sign)
3248 { /* signs equal, so just add fractions */
3249
3250 result_fl->sign = prod_fl->sign;
3251 result_fl->ms_fract = prod_fl->ms_fract;
3252 result_fl->ls_fract = prod_fl->ls_fract;
3253
3254 add_U128(result_fl->ms_fract, result_fl->ls_fract,
3255 add_fl->ms_fract, add_fl->ls_fract);
3256
3257 /* Recognize any overflow of left hand digits */
3258 ldigits |= result_fl->ms_fract >> 48;
3259
3260 /* Remove them from the result */
3261 result_fl->ms_fract &= 0x0000FFFFFFFFFFFFULL;
3262
3263 /* result sign already set to product sign */
3264 }
3265 else
3266 { /* signs unequal, subtract the larger fraction from the smaller */
3267 /* result has sign of the larger fraction */
3268
3269 if ( (prod_fl->ms_fract > add_fl->ms_fract)
3270 || ((prod_fl->ms_fract == add_fl->ms_fract) &&
3271 (prod_fl->ls_fract >= add_fl->ls_fract)) )
3272 /* product fraction larger than or equal to addend fraction */
3273
3274 { /* subtract addend fraction from product fraction */
3275 /* result has sign of product */
3276
3277 result_fl->ms_fract = prod_fl->ms_fract;
3278 result_fl->ls_fract = prod_fl->ls_fract;
3279
3280 if (rdigits)
3281 { /* If any right shifted addend digits, then we need to */
3282 /* borrow from the product fraction to reflect the shifted*/
3283 /* digits participation in the result */
3284 sub_U128(result_fl->ms_fract, result_fl->ls_fract,
3285 (U64)0, (U64)1);
3286 #if FLOAT_DEBUG
3287 logmsg (_("Barw Frac: %16.16llX %16.16llX\n"),
3288 result_fl->ms_fract, result_fl->ls_fract);
3289 #endif
3290 /* Due to participation of right shifted digits */
3291 /* result fraction NOT zero, so true zero will not result */
3292 /* hence, force sign will not to change */
3293 ldigits = 1;
3294 }
3295
3296 sub_U128(result_fl->ms_fract, result_fl->ls_fract,
3297 add_fl->ms_fract, add_fl->ls_fract);
3298 #if FLOAT_DEBUG
3299 logmsg (_("P-A Frac: %16.16llX %16.16llX\n"),
3300 result_fl->ms_fract, result_fl->ls_fract);
3301 #endif
3302 /* result sign already set to product sign above as default */
3303 }
3304 else
3305 /* addend fraction larger than product fraction */
3306
3307 { /* subtract product fraction from addend fraction */
3308 /* result has sign of addend */
3309 result_fl->ms_fract = add_fl->ms_fract;
3310 result_fl->ls_fract = add_fl->ls_fract;
3311
3312 sub_U128(result_fl->ms_fract, result_fl->ls_fract,
3313 prod_fl->ms_fract, prod_fl->ls_fract);
3314 #if FLOAT_DEBUG
3315 logmsg (_("A-P Frac: %16.16llX %16.16llX\n"),
3316 result_fl->ms_fract, result_fl->ls_fract);
3317 #endif
3318 result_fl->sign = add_fl->sign;
3319 }
3320 }
3321 #if FLOAT_DEBUG
3322 logmsg (_("Resl Frac: %16.16llX %16.16llX\n"),
3323 result_fl->ms_fract, result_fl->ls_fract);
3324 #endif
3325
3326 /* result exponent always the same as the product */
3327 result_fl->expo = prod_fl->expo;
3328
3329 /* Step 3 - If fraction is TRULY zero, sign is set to positive */
3330 if ( (!result_fl->ms_fract) && (!result_fl->ls_fract) &&
3331 (!ldigits) && (!rdigits) )
3332 {
3333 result_fl->sign = POS;
3334 }
3335
3336 } /* end ARCH_DEP(add_ef_unnorm) */
3337
3338 #endif /* defined(FEATURE_HFP_UNNORMALIZED_EXTENSION) */
3339
3340
3341 /*-------------------------------------------------------------------*/
3342 /* Extern functions */
3343 /*-------------------------------------------------------------------*/
3344
3345 /*-------------------------------------------------------------------*/
3346 /* 20 LPDR - Load Positive Floating Point Long Register [RR] */
3347 /*-------------------------------------------------------------------*/
DEF_INST(load_positive_float_long_reg)3348 DEF_INST(load_positive_float_long_reg)
3349 {
3350 int r1, r2; /* Values of R fields */
3351 int i1, i2; /* Indexes into fpr array */
3352
3353 RR(inst, regs, r1, r2);
3354 HFPREG2_CHECK(r1, r2, regs);
3355 i1 = FPR2I(r1);
3356 i2 = FPR2I(r2);
3357
3358 /* Copy register contents, clear the sign bit */
3359 regs->fpr[i1] = regs->fpr[i2] & 0x7FFFFFFF;
3360 regs->fpr[i1+1] = regs->fpr[i2+1];
3361
3362 /* Set condition code */
3363 regs->psw.cc = ((regs->fpr[i1] & 0x00FFFFFF)
3364 || regs->fpr[i1+1]) ? 2 : 0;
3365
3366 } /* end DEF_INST(load_positive_float_long_reg) */
3367
3368
3369 /*-------------------------------------------------------------------*/
3370 /* 21 LNDR - Load Negative Floating Point Long Register [RR] */
3371 /*-------------------------------------------------------------------*/
DEF_INST(load_negative_float_long_reg)3372 DEF_INST(load_negative_float_long_reg)
3373 {
3374 int r1, r2; /* Values of R fields */
3375 int i1, i2; /* Indexes into fpr array */
3376
3377 RR(inst, regs, r1, r2);
3378 HFPREG2_CHECK(r1, r2, regs);
3379 i1 = FPR2I(r1);
3380 i2 = FPR2I(r2);
3381
3382 /* Copy register contents, set the sign bit */
3383 regs->fpr[i1] = regs->fpr[i2]
3384 | 0x80000000;
3385 regs->fpr[i1+1] = regs->fpr[i2+1];
3386
3387 /* Set condition code */
3388 regs->psw.cc = ((regs->fpr[i1] & 0x00FFFFFF)
3389 || regs->fpr[i1+1]) ? 1 : 0;
3390
3391 } /* end DEF_INST(load_negative_float_long_reg) */
3392
3393
3394 /*-------------------------------------------------------------------*/
3395 /* 22 LTDR - Load and Test Floating Point Long Register [RR] */
3396 /*-------------------------------------------------------------------*/
DEF_INST(load_and_test_float_long_reg)3397 DEF_INST(load_and_test_float_long_reg)
3398 {
3399 int r1, r2; /* Values of R fields */
3400 int i1, i2; /* Indexes into fpr array */
3401
3402 RR(inst, regs, r1, r2);
3403 HFPREG2_CHECK(r1, r2, regs);
3404 i1 = FPR2I(r1);
3405 i2 = FPR2I(r2);
3406
3407 /* Copy register contents */
3408 regs->fpr[i1] = regs->fpr[i2];
3409 regs->fpr[i1+1] = regs->fpr[i2+1];
3410
3411 /* Set condition code */
3412 if ((regs->fpr[i1] & 0x00FFFFFF) || regs->fpr[i1+1]) {
3413 regs->psw.cc = (regs->fpr[i1] & 0x80000000) ? 1 : 2;
3414 } else {
3415 regs->psw.cc = 0;
3416 }
3417
3418 } /* end DEF_INST(load_and_test_float_long_reg) */
3419
3420
3421 /*-------------------------------------------------------------------*/
3422 /* 23 LCDR - Load Complement Floating Point Long Register [RR] */
3423 /*-------------------------------------------------------------------*/
DEF_INST(load_complement_float_long_reg)3424 DEF_INST(load_complement_float_long_reg)
3425 {
3426 int r1, r2; /* Values of R fields */
3427 int i1, i2; /* Indexes into fpr array */
3428
3429 RR(inst, regs, r1, r2);
3430 HFPREG2_CHECK(r1, r2, regs);
3431 i1 = FPR2I(r1);
3432 i2 = FPR2I(r2);
3433
3434 /* Copy register contents, invert sign bit */
3435 regs->fpr[i1] = regs->fpr[i2] ^ 0x80000000;
3436 regs->fpr[i1+1] = regs->fpr[i2+1];
3437
3438 /* Set condition code */
3439 if ((regs->fpr[i1] & 0x00FFFFFF) || regs->fpr[i1+1]) {
3440 regs->psw.cc = (regs->fpr[i1] & 0x80000000) ? 1 : 2;
3441 } else {
3442 regs->psw.cc = 0;
3443 }
3444
3445 } /* end DEF_INST(load_complement_float_long_reg) */
3446
3447
3448 /*-------------------------------------------------------------------*/
3449 /* 24 HDR - Halve Floating Point Long Register [RR] */
3450 /*-------------------------------------------------------------------*/
DEF_INST(halve_float_long_reg)3451 DEF_INST(halve_float_long_reg)
3452 {
3453 int r1, r2; /* Values of R fields */
3454 int i1, i2; /* Indexes into fpr array */
3455 LONG_FLOAT fl;
3456 int pgm_check;
3457
3458 RR(inst, regs, r1, r2);
3459 HFPREG2_CHECK(r1, r2, regs);
3460 i1 = FPR2I(r1);
3461 i2 = FPR2I(r2);
3462
3463 /* Get register content */
3464 get_lf(&fl, regs->fpr + i2);
3465
3466 /* Halve the value */
3467 if (fl.long_fract & 0x00E0000000000000ULL) {
3468 fl.long_fract >>= 1;
3469 pgm_check = 0;
3470 } else {
3471 fl.long_fract <<= 3;
3472 (fl.expo)--;
3473 normal_lf(&fl);
3474 pgm_check = underflow_lf(&fl, regs);
3475 }
3476
3477 /* Back to register */
3478 store_lf(&fl, regs->fpr + i1);
3479
3480 /* Program check ? */
3481 if (pgm_check) {
3482 ARCH_DEP(program_interrupt) (regs, pgm_check);
3483 }
3484
3485 } /* end DEF_INST(halve_float_long_reg) */
3486
3487
3488 /*-------------------------------------------------------------------*/
3489 /* 25 LDXR - Load Rounded Floating Point Long Register [RR] */
3490 /* Older mnemonic of this instruction is LRDR */
3491 /*-------------------------------------------------------------------*/
DEF_INST(load_rounded_float_long_reg)3492 DEF_INST(load_rounded_float_long_reg)
3493 {
3494 int r1, r2; /* Values of R fields */
3495 int i1, i2; /* Indexes into fpr array */
3496 LONG_FLOAT fl;
3497 int pgm_check;
3498
3499 RR(inst, regs, r1, r2);
3500
3501 HFPREG_CHECK(r1, regs);
3502 HFPODD_CHECK(r2, regs);
3503 i1 = FPR2I(r1);
3504 i2 = FPR2I(r2);
3505
3506 /* Get register content */
3507 get_lf(&fl, regs->fpr + i2);
3508
3509 /* Rounding */
3510 fl.long_fract += ((regs->fpr[FPR2I(r2 + 2)] >> 23) & 1);
3511
3512 /* Handle overflow */
3513 if (fl.long_fract & 0x0F00000000000000ULL) {
3514 fl.long_fract >>= 4;
3515 (fl.expo)++;
3516 pgm_check = overflow_lf(&fl, regs);
3517 } else {
3518 pgm_check = 0;
3519 }
3520
3521 /* Back to register */
3522 store_lf(&fl, regs->fpr + i1);
3523
3524 /* Program check ? */
3525 if (pgm_check) {
3526 ARCH_DEP(program_interrupt) (regs, pgm_check);
3527 }
3528
3529 } /* end DEF_INST(load_rounded_float_long_reg) */
3530
3531
3532 /*-------------------------------------------------------------------*/
3533 /* 26 MXR - Multiply Floating Point Extended Register [RR] */
3534 /*-------------------------------------------------------------------*/
DEF_INST(multiply_float_ext_reg)3535 DEF_INST(multiply_float_ext_reg)
3536 {
3537 int r1, r2; /* Values of R fields */
3538 int i1, i2; /* Indexes into fpr array */
3539 EXTENDED_FLOAT fl;
3540 EXTENDED_FLOAT mul_fl;
3541 int pgm_check;
3542
3543 RR(inst, regs, r1, r2);
3544 HFPODD2_CHECK(r1, r2, regs);
3545 i1 = FPR2I(r1);
3546 i2 = FPR2I(r2);
3547
3548 /* Get the operands */
3549 get_ef(&fl, regs->fpr + i1);
3550 get_ef(&mul_fl, regs->fpr + i2);
3551
3552 /* multiply extended */
3553 pgm_check = mul_ef(&fl, &mul_fl, regs);
3554
3555 /* Back to register */
3556 store_ef(&fl, regs->fpr + i1);
3557
3558 /* Program check ? */
3559 if (pgm_check) {
3560 ARCH_DEP(program_interrupt) (regs, pgm_check);
3561 }
3562
3563 } /* end DEF_INST(multiply_float_ext_reg) */
3564
3565
3566 /*-------------------------------------------------------------------*/
3567 /* 27 MXDR - Multiply Floating Point Long to Extended Reg. [RR] */
3568 /*-------------------------------------------------------------------*/
DEF_INST(multiply_float_long_to_ext_reg)3569 DEF_INST(multiply_float_long_to_ext_reg)
3570 {
3571 int r1, r2; /* Values of R fields */
3572 int i1, i2; /* Indexes into fpr array */
3573 LONG_FLOAT fl;
3574 LONG_FLOAT mul_fl;
3575 EXTENDED_FLOAT result_fl;
3576 int pgm_check;
3577
3578 RR(inst, regs, r1, r2);
3579
3580 HFPODD_CHECK(r1, regs);
3581 HFPREG_CHECK(r2, regs);
3582 i1 = FPR2I(r1);
3583 i2 = FPR2I(r2);
3584
3585 /* Get the operands */
3586 get_lf(&fl, regs->fpr + i1);
3587 get_lf(&mul_fl, regs->fpr + i2);
3588
3589 /* multiply long to extended */
3590 pgm_check = mul_lf_to_ef(&fl, &mul_fl, &result_fl, regs);
3591
3592 /* Back to register */
3593 store_ef(&result_fl, regs->fpr + i1);
3594
3595 /* Program check ? */
3596 if (pgm_check) {
3597 ARCH_DEP(program_interrupt) (regs, pgm_check);
3598 }
3599
3600 } /* end DEF_INST(multiply_float_long_to_ext_reg) */
3601
3602
3603 /*-------------------------------------------------------------------*/
3604 /* 28 LDR - Load Floating Point Long Register [RR] */
3605 /*-------------------------------------------------------------------*/
DEF_INST(load_float_long_reg)3606 DEF_INST(load_float_long_reg)
3607 {
3608 int r1, r2; /* Values of R fields */
3609 int i1, i2; /* Indexes into fpr array */
3610
3611 RR(inst, regs, r1, r2);
3612 HFPREG2_CHECK(r1, r2, regs);
3613 i1 = FPR2I(r1);
3614 i2 = FPR2I(r2);
3615
3616 /* Copy register contents */
3617 regs->fpr[i1] = regs->fpr[i2];
3618 regs->fpr[i1+1] = regs->fpr[i2+1];
3619
3620 } /* end DEF_INST(load_float_long_reg) */
3621
3622
3623 /*-------------------------------------------------------------------*/
3624 /* 29 CDR - Compare Floating Point Long Register [RR] */
3625 /*-------------------------------------------------------------------*/
DEF_INST(compare_float_long_reg)3626 DEF_INST(compare_float_long_reg)
3627 {
3628 int r1, r2; /* Values of R fields */
3629 int i1, i2; /* Indexes into fpr array */
3630 LONG_FLOAT fl;
3631 LONG_FLOAT cmp_fl;
3632
3633 RR(inst, regs, r1, r2);
3634 HFPREG2_CHECK(r1, r2, regs);
3635 i1 = FPR2I(r1);
3636 i2 = FPR2I(r2);
3637
3638 /* Get the operands */
3639 get_lf(&fl, regs->fpr + i1);
3640 get_lf(&cmp_fl, regs->fpr + i2);
3641
3642 /* Compare long */
3643 cmp_lf(&fl, &cmp_fl, regs);
3644
3645 } /* end DEF_INST(compare_float_long_reg) */
3646
3647
3648 /*-------------------------------------------------------------------*/
3649 /* 2A ADR - Add Floating Point Long Register [RR] */
3650 /*-------------------------------------------------------------------*/
DEF_INST(add_float_long_reg)3651 DEF_INST(add_float_long_reg)
3652 {
3653 int r1, r2; /* Values of R fields */
3654 int i1, i2; /* Indexes into fpr array */
3655 LONG_FLOAT fl;
3656 LONG_FLOAT add_fl;
3657 int pgm_check;
3658
3659 RR(inst, regs, r1, r2);
3660 HFPREG2_CHECK(r1, r2, regs);
3661 i1 = FPR2I(r1);
3662 i2 = FPR2I(r2);
3663
3664 /* Get the operands */
3665 get_lf(&fl, regs->fpr + i1);
3666 get_lf(&add_fl, regs->fpr + i2);
3667
3668 /* Add long with normalization */
3669 pgm_check = add_lf(&fl, &add_fl, NORMAL, SIGEX, regs);
3670
3671 /* Set condition code */
3672 if (fl.long_fract) {
3673 regs->psw.cc = fl.sign ? 1 : 2;
3674 } else {
3675 regs->psw.cc = 0;
3676 }
3677
3678 /* Back to register */
3679 store_lf(&fl, regs->fpr + i1);
3680
3681 /* Program check ? */
3682 if (pgm_check) {
3683 ARCH_DEP(program_interrupt) (regs, pgm_check);
3684 }
3685
3686 } /* end DEF_INST(add_float_long_reg) */
3687
3688
3689 /*-------------------------------------------------------------------*/
3690 /* 2B SDR - Subtract Floating Point Long Register [RR] */
3691 /*-------------------------------------------------------------------*/
DEF_INST(subtract_float_long_reg)3692 DEF_INST(subtract_float_long_reg)
3693 {
3694 int r1, r2; /* Values of R fields */
3695 int i1, i2; /* Indexes into fpr array */
3696 LONG_FLOAT fl;
3697 LONG_FLOAT sub_fl;
3698 int pgm_check;
3699
3700 RR(inst, regs, r1, r2);
3701 HFPREG2_CHECK(r1, r2, regs);
3702 i1 = FPR2I(r1);
3703 i2 = FPR2I(r2);
3704
3705 /* Get the operands */
3706 get_lf(&fl, regs->fpr + i1);
3707 get_lf(&sub_fl, regs->fpr + i2);
3708
3709 /* Invert the sign of 2nd operand */
3710 sub_fl.sign = ! (sub_fl.sign);
3711
3712 /* Add long with normalization */
3713 pgm_check = add_lf(&fl, &sub_fl, NORMAL, SIGEX, regs);
3714
3715 /* Set condition code */
3716 if (fl.long_fract) {
3717 regs->psw.cc = fl.sign ? 1 : 2;
3718 } else {
3719 regs->psw.cc = 0;
3720 }
3721
3722 /* Back to register */
3723 store_lf(&fl, regs->fpr + i1);
3724
3725 /* Program check ? */
3726 if (pgm_check) {
3727 ARCH_DEP(program_interrupt) (regs, pgm_check);
3728 }
3729
3730 } /* end DEF_INST(subtract_float_long_reg) */
3731
3732
3733 /*-------------------------------------------------------------------*/
3734 /* 2C MDR - Multiply Floating Point Long Register [RR] */
3735 /*-------------------------------------------------------------------*/
DEF_INST(multiply_float_long_reg)3736 DEF_INST(multiply_float_long_reg)
3737 {
3738 int r1, r2; /* Values of R fields */
3739 int i1, i2; /* Indexes into fpr array */
3740 LONG_FLOAT fl;
3741 LONG_FLOAT mul_fl;
3742 int pgm_check;
3743
3744 RR(inst, regs, r1, r2);
3745 HFPREG2_CHECK(r1, r2, regs);
3746 i1 = FPR2I(r1);
3747 i2 = FPR2I(r2);
3748
3749 /* Get the operands */
3750 get_lf(&fl, regs->fpr + i1);
3751 get_lf(&mul_fl, regs->fpr + i2);
3752
3753 /* multiply long */
3754 pgm_check = mul_lf(&fl, &mul_fl, OVUNF, regs);
3755
3756 /* Back to register */
3757 store_lf(&fl, regs->fpr + i1);
3758
3759 /* Program check ? */
3760 if (pgm_check) {
3761 ARCH_DEP(program_interrupt) (regs, pgm_check);
3762 }
3763
3764 } /* end DEF_INST(multiply_float_long_reg) */
3765
3766
3767 /*-------------------------------------------------------------------*/
3768 /* 2D DDR - Divide Floating Point Long Register [RR] */
3769 /*-------------------------------------------------------------------*/
DEF_INST(divide_float_long_reg)3770 DEF_INST(divide_float_long_reg)
3771 {
3772 int r1, r2; /* Values of R fields */
3773 int i1, i2; /* Indexes into fpr array */
3774 LONG_FLOAT fl;
3775 LONG_FLOAT div_fl;
3776 int pgm_check;
3777
3778 RR(inst, regs, r1, r2);
3779 HFPREG2_CHECK(r1, r2, regs);
3780 i1 = FPR2I(r1);
3781 i2 = FPR2I(r2);
3782
3783 /* Get the operands */
3784 get_lf(&fl, regs->fpr + i1);
3785 get_lf(&div_fl, regs->fpr + i2);
3786
3787 /* divide long */
3788 pgm_check = div_lf(&fl, &div_fl, regs);
3789
3790 /* Back to register */
3791 store_lf(&fl, regs->fpr + i1);
3792
3793 /* Program check ? */
3794 if (pgm_check) {
3795 ARCH_DEP(program_interrupt) (regs, pgm_check);
3796 }
3797
3798 } /* end DEF_INST(divide_float_long_reg) */
3799
3800
3801 /*-------------------------------------------------------------------*/
3802 /* 2E AWR - Add Unnormalized Floating Point Long Register [RR] */
3803 /*-------------------------------------------------------------------*/
DEF_INST(add_unnormal_float_long_reg)3804 DEF_INST(add_unnormal_float_long_reg)
3805 {
3806 int r1, r2; /* Values of R fields */
3807 int i1, i2; /* Indexes into fpr array */
3808 LONG_FLOAT fl;
3809 LONG_FLOAT add_fl;
3810 int pgm_check;
3811
3812 RR(inst, regs, r1, r2);
3813 HFPREG2_CHECK(r1, r2, regs);
3814 i1 = FPR2I(r1);
3815 i2 = FPR2I(r2);
3816
3817 /* Get the operands */
3818 get_lf(&fl, regs->fpr + i1);
3819 get_lf(&add_fl, regs->fpr + i2);
3820
3821 /* Add long without normalization */
3822 pgm_check = add_lf(&fl, &add_fl, UNNORMAL, SIGEX, regs);
3823
3824 /* Set condition code */
3825 if (fl.long_fract) {
3826 regs->psw.cc = fl.sign ? 1 : 2;
3827 } else {
3828 regs->psw.cc = 0;
3829 }
3830
3831 /* Back to register */
3832 store_lf(&fl, regs->fpr + i1);
3833
3834 /* Program check ? */
3835 if (pgm_check) {
3836 ARCH_DEP(program_interrupt) (regs, pgm_check);
3837 }
3838
3839 } /* end DEF_INST(add_unnormal_float_long_reg) */
3840
3841
3842 /*-------------------------------------------------------------------*/
3843 /* 2F SWR - Subtract Unnormalized Floating Point Long Reg. [RR] */
3844 /*-------------------------------------------------------------------*/
DEF_INST(subtract_unnormal_float_long_reg)3845 DEF_INST(subtract_unnormal_float_long_reg)
3846 {
3847 int r1, r2; /* Values of R fields */
3848 int i1, i2; /* Indexes into fpr array */
3849 LONG_FLOAT fl;
3850 LONG_FLOAT sub_fl;
3851 int pgm_check;
3852
3853 RR(inst, regs, r1, r2);
3854 HFPREG2_CHECK(r1, r2, regs);
3855 i1 = FPR2I(r1);
3856 i2 = FPR2I(r2);
3857
3858 /* Get the operands */
3859 get_lf(&fl, regs->fpr + i1);
3860 get_lf(&sub_fl, regs->fpr + i2);
3861
3862 /* Invert the sign of 2nd operand */
3863 sub_fl.sign = ! (sub_fl.sign);
3864
3865 /* Add long without normalization */
3866 pgm_check = add_lf(&fl, &sub_fl, UNNORMAL, SIGEX, regs);
3867
3868 /* Set condition code */
3869 if (fl.long_fract) {
3870 regs->psw.cc = fl.sign ? 1 : 2;
3871 } else {
3872 regs->psw.cc = 0;
3873 }
3874
3875 /* Back to register */
3876 store_lf(&fl, regs->fpr + i1);
3877
3878 /* Program check ? */
3879 if (pgm_check) {
3880 ARCH_DEP(program_interrupt) (regs, pgm_check);
3881 }
3882
3883 } /* end DEF_INST(subtract_unnormal_float_long_reg) */
3884
3885
3886 /*-------------------------------------------------------------------*/
3887 /* 30 LPER - Load Positive Floating Point Short Register [RR] */
3888 /*-------------------------------------------------------------------*/
DEF_INST(load_positive_float_short_reg)3889 DEF_INST(load_positive_float_short_reg)
3890 {
3891 int r1, r2; /* Values of R fields */
3892 int i1, i2; /* Indexes into fpr array */
3893
3894 RR(inst, regs, r1, r2);
3895 HFPREG2_CHECK(r1, r2, regs);
3896 i1 = FPR2I(r1);
3897 i2 = FPR2I(r2);
3898
3899 /* Copy register contents, clear sign bit */
3900 regs->fpr[i1] = regs->fpr[i2] & 0x7FFFFFFF;
3901
3902 /* Set condition code */
3903 regs->psw.cc = (regs->fpr[i1] & 0x00FFFFFF) ? 2 : 0;
3904
3905 } /* end DEF_INST(load_positive_float_short_reg) */
3906
3907
3908 /*-------------------------------------------------------------------*/
3909 /* 31 LNER - Load Negative Floating Point Short Register [RR] */
3910 /*-------------------------------------------------------------------*/
DEF_INST(load_negative_float_short_reg)3911 DEF_INST(load_negative_float_short_reg)
3912 {
3913 int r1, r2; /* Values of R fields */
3914 int i1, i2; /* Indexes into fpr array */
3915
3916 RR(inst, regs, r1, r2);
3917 HFPREG2_CHECK(r1, r2, regs);
3918 i1 = FPR2I(r1);
3919 i2 = FPR2I(r2);
3920
3921 /* Copy register contents, set sign bit */
3922 regs->fpr[i1] = regs->fpr[i2] | 0x80000000;
3923
3924 /* Set condition code */
3925 regs->psw.cc = (regs->fpr[i1] & 0x00FFFFFF) ? 1 : 0;
3926
3927 } /* end DEF_INST(load_negative_float_short_reg) */
3928
3929
3930 /*-------------------------------------------------------------------*/
3931 /* 32 LTER - Load and Test Floating Point Short Register [RR] */
3932 /*-------------------------------------------------------------------*/
DEF_INST(load_and_test_float_short_reg)3933 DEF_INST(load_and_test_float_short_reg)
3934 {
3935 int r1, r2; /* Values of R fields */
3936 int i1, i2; /* Indexes into fpr array */
3937
3938 RR(inst, regs, r1, r2);
3939 HFPREG2_CHECK(r1, r2, regs);
3940 i1 = FPR2I(r1);
3941 i2 = FPR2I(r2);
3942
3943 /* Copy register contents */
3944 regs->fpr[i1] = regs->fpr[i2];
3945
3946 /* Set condition code */
3947 if (regs->fpr[i1] & 0x00FFFFFF) {
3948 regs->psw.cc = (regs->fpr[i1] & 0x80000000) ? 1 : 2;
3949 } else {
3950 regs->psw.cc = 0;
3951 }
3952
3953 } /* end DEF_INST(load_and_test_float_short_reg) */
3954
3955
3956 /*-------------------------------------------------------------------*/
3957 /* 33 LCER - Load Complement Floating Point Short Register [RR] */
3958 /*-------------------------------------------------------------------*/
DEF_INST(load_complement_float_short_reg)3959 DEF_INST(load_complement_float_short_reg)
3960 {
3961 int r1, r2; /* Values of R fields */
3962 int i1, i2; /* Indexes into fpr array */
3963
3964 RR(inst, regs, r1, r2);
3965 HFPREG2_CHECK(r1, r2, regs);
3966 i1 = FPR2I(r1);
3967 i2 = FPR2I(r2);
3968
3969 /* Copy register contents, invert sign bit */
3970 regs->fpr[i1] = regs->fpr[i2] ^ 0x80000000;
3971
3972 /* Set condition code */
3973 if (regs->fpr[i1] & 0x00FFFFFF) {
3974 regs->psw.cc = (regs->fpr[i1] & 0x80000000) ? 1 : 2;
3975 } else {
3976 regs->psw.cc = 0;
3977 }
3978
3979 } /* end DEF_INST(load_complement_float_short_reg) */
3980
3981
3982 /*-------------------------------------------------------------------*/
3983 /* 34 HER - Halve Floating Point Short Register [RR] */
3984 /*-------------------------------------------------------------------*/
DEF_INST(halve_float_short_reg)3985 DEF_INST(halve_float_short_reg)
3986 {
3987 int r1, r2; /* Values of R fields */
3988 int i1, i2; /* Indexes into fpr array */
3989 SHORT_FLOAT fl;
3990 int pgm_check;
3991
3992 RR(inst, regs, r1, r2);
3993 HFPREG2_CHECK(r1, r2, regs);
3994 i1 = FPR2I(r1);
3995 i2 = FPR2I(r2);
3996
3997 /* Get register content */
3998 get_sf(&fl, regs->fpr + i2);
3999
4000 /* Halve the value */
4001 if (fl.short_fract & 0x00E00000) {
4002 fl.short_fract >>= 1;
4003 pgm_check = 0;
4004 } else {
4005 fl.short_fract <<= 3;
4006 (fl.expo)--;
4007 normal_sf(&fl);
4008 pgm_check = underflow_sf(&fl, regs);
4009 }
4010
4011 /* Back to register */
4012 store_sf(&fl, regs->fpr + i1);
4013
4014 /* Program check ? */
4015 if (pgm_check) {
4016 ARCH_DEP(program_interrupt) (regs, pgm_check);
4017 }
4018
4019 } /* end DEF_INST(halve_float_short_reg) */
4020
4021
4022 /*-------------------------------------------------------------------*/
4023 /* 35 LEDR - Load Rounded Floating Point Short Register [RR] */
4024 /* Older mnemonic of this instruction is LRER */
4025 /*-------------------------------------------------------------------*/
DEF_INST(load_rounded_float_short_reg)4026 DEF_INST(load_rounded_float_short_reg)
4027 {
4028 int r1, r2; /* Values of R fields */
4029 int i1, i2; /* Indexes into fpr array */
4030 LONG_FLOAT from_fl;
4031 SHORT_FLOAT to_fl;
4032 int pgm_check;
4033
4034 RR(inst, regs, r1, r2);
4035 HFPREG2_CHECK(r1, r2, regs);
4036 i1 = FPR2I(r1);
4037 i2 = FPR2I(r2);
4038
4039 /* Get register content */
4040 get_lf(&from_fl, regs->fpr + i2);
4041
4042 /* Rounding */
4043 to_fl.short_fract = (from_fl.long_fract + 0x0000000080000000ULL) >> 32;
4044 to_fl.sign = from_fl.sign;
4045 to_fl.expo = from_fl.expo;
4046
4047 /* Handle overflow */
4048 if (to_fl.short_fract & 0x0F000000) {
4049 to_fl.short_fract >>= 4;
4050 (to_fl.expo)++;
4051 pgm_check = overflow_sf(&to_fl, regs);
4052 } else {
4053 pgm_check = 0;
4054 }
4055
4056 /* To register */
4057 store_sf(&to_fl, regs->fpr + i1);
4058
4059 /* Program check ? */
4060 if (pgm_check) {
4061 ARCH_DEP(program_interrupt) (regs, pgm_check);
4062 }
4063
4064 } /* end DEF_INST(load_rounded_float_short_reg) */
4065
4066
4067 /*-------------------------------------------------------------------*/
4068 /* 36 AXR - Add Floating Point Extended Register [RR] */
4069 /*-------------------------------------------------------------------*/
DEF_INST(add_float_ext_reg)4070 DEF_INST(add_float_ext_reg)
4071 {
4072 int r1, r2; /* Values of R fields */
4073 int i1, i2; /* Indexes into fpr array */
4074 EXTENDED_FLOAT fl;
4075 EXTENDED_FLOAT add_fl;
4076 int pgm_check;
4077
4078 RR(inst, regs, r1, r2);
4079 HFPODD2_CHECK(r1, r2, regs);
4080 i1 = FPR2I(r1);
4081 i2 = FPR2I(r2);
4082
4083 /* Get the operands */
4084 get_ef(&fl, regs->fpr + i1);
4085 get_ef(&add_fl, regs->fpr + i2);
4086
4087 /* Add extended */
4088 pgm_check = add_ef(&fl, &add_fl, regs->fpr + i1, regs);
4089
4090 /* Set condition code */
4091 if (fl.ms_fract || fl.ls_fract) {
4092 regs->psw.cc = fl.sign ? 1 : 2;
4093 } else {
4094 regs->psw.cc = 0;
4095 }
4096
4097 /* Program check ? */
4098 if (pgm_check) {
4099 ARCH_DEP(program_interrupt) (regs, pgm_check);
4100 }
4101
4102 } /* end DEF_INST(add_float_ext_reg) */
4103
4104
4105 /*-------------------------------------------------------------------*/
4106 /* 37 SXR - Subtract Floating Point Extended Register [RR] */
4107 /*-------------------------------------------------------------------*/
DEF_INST(subtract_float_ext_reg)4108 DEF_INST(subtract_float_ext_reg)
4109 {
4110 int r1, r2; /* Values of R fields */
4111 int i1, i2; /* Indexes into fpr array */
4112 EXTENDED_FLOAT fl;
4113 EXTENDED_FLOAT sub_fl;
4114 int pgm_check;
4115
4116 RR(inst, regs, r1, r2);
4117 HFPODD2_CHECK(r1, r2, regs);
4118 i1 = FPR2I(r1);
4119 i2 = FPR2I(r2);
4120
4121 /* Get the operands */
4122 get_ef(&fl, regs->fpr + i1);
4123 get_ef(&sub_fl, regs->fpr + i2);
4124
4125 /* Invert the sign of 2nd operand */
4126 sub_fl.sign = ! (sub_fl.sign);
4127
4128 /* Add extended */
4129 pgm_check = add_ef(&fl, &sub_fl, regs->fpr + i1, regs);
4130
4131 /* Set condition code */
4132 if (fl.ms_fract || fl.ls_fract) {
4133 regs->psw.cc = fl.sign ? 1 : 2;
4134 } else {
4135 regs->psw.cc = 0;
4136 }
4137
4138 /* Program check ? */
4139 if (pgm_check) {
4140 ARCH_DEP(program_interrupt) (regs, pgm_check);
4141 }
4142
4143 } /* end DEF_INST(subtract_float_ext_reg) */
4144
4145
4146 /*-------------------------------------------------------------------*/
4147 /* 38 LER - Load Floating Point Short Register [RR] */
4148 /*-------------------------------------------------------------------*/
DEF_INST(load_float_short_reg)4149 DEF_INST(load_float_short_reg)
4150 {
4151 int r1, r2; /* Values of R fields */
4152 int i1, i2; /* Indexes into fpr array */
4153
4154 RR(inst, regs, r1, r2);
4155 HFPREG2_CHECK(r1, r2, regs);
4156 i1 = FPR2I(r1);
4157 i2 = FPR2I(r2);
4158
4159 /* Copy register content */
4160 regs->fpr[i1] = regs->fpr[i2];
4161
4162 } /* end DEF_INST(load_float_short_reg) */
4163
4164
4165 /*-------------------------------------------------------------------*/
4166 /* 39 CER - Compare Floating Point Short Register [RR] */
4167 /*-------------------------------------------------------------------*/
DEF_INST(compare_float_short_reg)4168 DEF_INST(compare_float_short_reg)
4169 {
4170 int r1, r2; /* Values of R fields */
4171 int i1, i2; /* Indexes into fpr array */
4172 SHORT_FLOAT fl;
4173 SHORT_FLOAT cmp_fl;
4174
4175 RR(inst, regs, r1, r2);
4176 HFPREG2_CHECK(r1, r2, regs);
4177 i1 = FPR2I(r1);
4178 i2 = FPR2I(r2);
4179
4180 /* Get the operands */
4181 get_sf(&fl, regs->fpr + i1);
4182 get_sf(&cmp_fl, regs->fpr + i2);
4183
4184 /* Compare short */
4185 cmp_sf(&fl, &cmp_fl, regs);
4186
4187 } /* end DEF_INST(compare_float_short_reg) */
4188
4189
4190 /*-------------------------------------------------------------------*/
4191 /* 3A AER - Add Floating Point Short Register [RR] */
4192 /*-------------------------------------------------------------------*/
DEF_INST(add_float_short_reg)4193 DEF_INST(add_float_short_reg)
4194 {
4195 int r1, r2; /* Values of R fields */
4196 int i1, i2; /* Indexes into fpr array */
4197 SHORT_FLOAT fl;
4198 SHORT_FLOAT add_fl;
4199 int pgm_check;
4200
4201 RR(inst, regs, r1, r2);
4202 HFPREG2_CHECK(r1, r2, regs);
4203 i1 = FPR2I(r1);
4204 i2 = FPR2I(r2);
4205
4206 /* Get the operands */
4207 get_sf(&fl, regs->fpr + i1);
4208 get_sf(&add_fl, regs->fpr + i2);
4209
4210 /* Add short with normalization */
4211 pgm_check = add_sf(&fl, &add_fl, NORMAL, SIGEX, regs);
4212
4213 /* Set condition code */
4214 if (fl.short_fract) {
4215 regs->psw.cc = fl.sign ? 1 : 2;
4216 } else {
4217 regs->psw.cc = 0;
4218 }
4219
4220 /* Back to register */
4221 store_sf(&fl, regs->fpr + i1);
4222
4223 /* Program check ? */
4224 if (pgm_check) {
4225 ARCH_DEP(program_interrupt) (regs, pgm_check);
4226 }
4227
4228 } /* end DEF_INST(add_float_short_reg) */
4229
4230
4231 /*-------------------------------------------------------------------*/
4232 /* 3B SER - Subtract Floating Point Short Register [RR] */
4233 /*-------------------------------------------------------------------*/
DEF_INST(subtract_float_short_reg)4234 DEF_INST(subtract_float_short_reg)
4235 {
4236 int r1, r2; /* Values of R fields */
4237 int i1, i2; /* Indexes into fpr array */
4238 SHORT_FLOAT fl;
4239 SHORT_FLOAT sub_fl;
4240 int pgm_check;
4241
4242 RR(inst, regs, r1, r2);
4243 HFPREG2_CHECK(r1, r2, regs);
4244 i1 = FPR2I(r1);
4245 i2 = FPR2I(r2);
4246
4247 /* Get the operands */
4248 get_sf(&fl, regs->fpr + i1);
4249 get_sf(&sub_fl, regs->fpr + i2);
4250
4251 /* Invert the sign of 2nd operand */
4252 sub_fl.sign = ! (sub_fl.sign);
4253
4254 /* Subtract short with normalization */
4255 pgm_check = add_sf(&fl, &sub_fl, NORMAL, SIGEX, regs);
4256
4257 /* Set condition code */
4258 if (fl.short_fract) {
4259 regs->psw.cc = fl.sign ? 1 : 2;
4260 } else {
4261 regs->psw.cc = 0;
4262 }
4263
4264 /* Back to register */
4265 store_sf(&fl, regs->fpr + i1);
4266
4267 /* Program check ? */
4268 if (pgm_check) {
4269 ARCH_DEP(program_interrupt) (regs, pgm_check);
4270 }
4271
4272 } /* end DEF_INST(subtract_float_short_reg) */
4273
4274
4275 /*-------------------------------------------------------------------*/
4276 /* 3C MDER - Multiply Short to Long Floating Point Register [RR] */
4277 /* Older mnemonic of this instruction is MER */
4278 /*-------------------------------------------------------------------*/
DEF_INST(multiply_float_short_to_long_reg)4279 DEF_INST(multiply_float_short_to_long_reg)
4280 {
4281 int r1, r2; /* Values of R fields */
4282 int i1, i2; /* Indexes into fpr array */
4283 SHORT_FLOAT fl;
4284 SHORT_FLOAT mul_fl;
4285 LONG_FLOAT result_fl;
4286 int pgm_check;
4287
4288 RR(inst, regs, r1, r2);
4289 HFPREG2_CHECK(r1, r2, regs);
4290 i1 = FPR2I(r1);
4291 i2 = FPR2I(r2);
4292
4293 /* Get the operands */
4294 get_sf(&fl, regs->fpr + i1);
4295 get_sf(&mul_fl, regs->fpr + i2);
4296
4297 /* multiply short to long */
4298 pgm_check = mul_sf_to_lf(&fl, &mul_fl, &result_fl, regs);
4299
4300 /* Back to register */
4301 store_lf(&result_fl, regs->fpr + i1);
4302
4303 /* Program check ? */
4304 if (pgm_check) {
4305 ARCH_DEP(program_interrupt) (regs, pgm_check);
4306 }
4307
4308 } /* end DEF_INST(multiply_float_short_to_long_reg) */
4309
4310
4311 /*-------------------------------------------------------------------*/
4312 /* 3D DER - Divide Floating Point Short Register [RR] */
4313 /*-------------------------------------------------------------------*/
DEF_INST(divide_float_short_reg)4314 DEF_INST(divide_float_short_reg)
4315 {
4316 int r1, r2; /* Values of R fields */
4317 int i1, i2; /* Indexes into fpr array */
4318 SHORT_FLOAT fl;
4319 SHORT_FLOAT div_fl;
4320 int pgm_check;
4321
4322 RR(inst, regs, r1, r2);
4323 HFPREG2_CHECK(r1, r2, regs);
4324 i1 = FPR2I(r1);
4325 i2 = FPR2I(r2);
4326
4327 /* Get the operands */
4328 get_sf(&fl, regs->fpr + i1);
4329 get_sf(&div_fl, regs->fpr + i2);
4330
4331 /* divide short */
4332 pgm_check = div_sf(&fl, &div_fl, regs);
4333
4334 /* Back to register */
4335 store_sf(&fl, regs->fpr + i1);
4336
4337 /* Program check ? */
4338 if (pgm_check) {
4339 ARCH_DEP(program_interrupt) (regs, pgm_check);
4340 }
4341
4342 } /* end DEF_INST(divide_float_short_reg) */
4343
4344
4345 /*-------------------------------------------------------------------*/
4346 /* 3E AUR - Add Unnormalized Floating Point Short Register [RR] */
4347 /*-------------------------------------------------------------------*/
DEF_INST(add_unnormal_float_short_reg)4348 DEF_INST(add_unnormal_float_short_reg)
4349 {
4350 int r1, r2; /* Values of R fields */
4351 int i1, i2; /* Indexes into fpr array */
4352 SHORT_FLOAT fl;
4353 SHORT_FLOAT add_fl;
4354 int pgm_check;
4355
4356 RR(inst, regs, r1, r2);
4357 HFPREG2_CHECK(r1, r2, regs);
4358 i1 = FPR2I(r1);
4359 i2 = FPR2I(r2);
4360
4361 /* Get the operands */
4362 get_sf(&fl, regs->fpr + i1);
4363 get_sf(&add_fl, regs->fpr + i2);
4364
4365 /* Add short without normalization */
4366 pgm_check = add_sf(&fl, &add_fl, UNNORMAL, SIGEX, regs);
4367
4368 /* Set condition code */
4369 if (fl.short_fract) {
4370 regs->psw.cc = fl.sign ? 1 : 2;
4371 } else {
4372 regs->psw.cc = 0;
4373 }
4374
4375 /* Back to register */
4376 store_sf(&fl, regs->fpr + i1);
4377
4378 /* Program check ? */
4379 if (pgm_check) {
4380 ARCH_DEP(program_interrupt) (regs, pgm_check);
4381 }
4382
4383 } /* end DEF_INST(add_unnormal_float_short_reg) */
4384
4385
4386 /*-------------------------------------------------------------------*/
4387 /* 3F SUR - Subtract Unnormalized Floating Point Short Reg. [RR] */
4388 /*-------------------------------------------------------------------*/
DEF_INST(subtract_unnormal_float_short_reg)4389 DEF_INST(subtract_unnormal_float_short_reg)
4390 {
4391 int r1, r2; /* Values of R fields */
4392 int i1, i2; /* Indexes into fpr array */
4393 SHORT_FLOAT fl;
4394 SHORT_FLOAT sub_fl;
4395 int pgm_check;
4396
4397 RR(inst, regs, r1, r2);
4398 HFPREG2_CHECK(r1, r2, regs);
4399 i1 = FPR2I(r1);
4400 i2 = FPR2I(r2);
4401
4402 /* Get the operands */
4403 get_sf(&fl, regs->fpr + i1);
4404 get_sf(&sub_fl, regs->fpr + i2);
4405
4406 /* Invert the sign of 2nd operand */
4407 sub_fl.sign = ! (sub_fl.sign);
4408
4409 /* Add short without normalization */
4410 pgm_check = add_sf(&fl, &sub_fl, UNNORMAL, SIGEX, regs);
4411
4412 /* Set condition code */
4413 if (fl.short_fract) {
4414 regs->psw.cc = fl.sign ? 1 : 2;
4415 } else {
4416 regs->psw.cc = 0;
4417 }
4418
4419 /* Back to register */
4420 store_sf(&fl, regs->fpr + i1);
4421
4422 /* Program check ? */
4423 if (pgm_check) {
4424 ARCH_DEP(program_interrupt) (regs, pgm_check);
4425 }
4426
4427 } /* end DEF_INST(subtract_unnormal_float_short_reg) */
4428
4429
4430 /*-------------------------------------------------------------------*/
4431 /* 60 STD - Store Floating Point Long [RX] */
4432 /*-------------------------------------------------------------------*/
DEF_INST(store_float_long)4433 DEF_INST(store_float_long)
4434 {
4435 int r1; /* Value of R field */
4436 int i1; /* Index of R1 in fpr array */
4437 int b2; /* Base of effective addr */
4438 VADR effective_addr2; /* Effective address */
4439 U64 dreg; /* Double word workarea */
4440
4441 RX(inst, regs, r1, b2, effective_addr2);
4442 HFPREG_CHECK(r1, regs);
4443 i1 = FPR2I(r1);
4444
4445 /* Store register contents at operand address */
4446 dreg = ((U64)regs->fpr[i1] << 32) | regs->fpr[i1+1];
4447 ARCH_DEP(vstore8) (dreg, effective_addr2, b2, regs);
4448
4449 } /* end DEF_INST(store_float_long) */
4450
4451
4452 /*-------------------------------------------------------------------*/
4453 /* 67 MXD - Multiply Floating Point Long to Extended [RX] */
4454 /*-------------------------------------------------------------------*/
DEF_INST(multiply_float_long_to_ext)4455 DEF_INST(multiply_float_long_to_ext)
4456 {
4457 int r1; /* Value of R field */
4458 int i1; /* Index of R1 in fpr array */
4459 int b2; /* Base of effective addr */
4460 VADR effective_addr2; /* Effective address */
4461 LONG_FLOAT fl;
4462 LONG_FLOAT mul_fl;
4463 EXTENDED_FLOAT result_fl;
4464 int pgm_check;
4465
4466 RX(inst, regs, r1, b2, effective_addr2);
4467 HFPODD_CHECK(r1, regs);
4468 i1 = FPR2I(r1);
4469
4470 /* Get the operands */
4471 get_lf(&fl, regs->fpr + i1);
4472 vfetch_lf(&mul_fl, effective_addr2, b2, regs );
4473
4474 /* multiply long to extended */
4475 pgm_check = mul_lf_to_ef(&fl, &mul_fl, &result_fl, regs);
4476
4477 /* Back to register */
4478 store_ef(&result_fl, regs->fpr + i1);
4479
4480 /* Program check ? */
4481 if (pgm_check) {
4482 ARCH_DEP(program_interrupt) (regs, pgm_check);
4483 }
4484
4485 } /* end DEF_INST(multiply_float_long_to_ext) */
4486
4487
4488 /*-------------------------------------------------------------------*/
4489 /* 68 LD - Load Floating Point Long [RX] */
4490 /*-------------------------------------------------------------------*/
DEF_INST(load_float_long)4491 DEF_INST(load_float_long)
4492 {
4493 int r1; /* Value of R field */
4494 int i1; /* Index of R1 in fpr array */
4495 int b2; /* Base of effective addr */
4496 VADR effective_addr2; /* Effective address */
4497 U64 dreg; /* Double word workarea */
4498
4499 RX(inst, regs, r1, b2, effective_addr2);
4500 HFPREG_CHECK(r1, regs);
4501 i1 = FPR2I(r1);
4502
4503 /* Fetch value from operand address */
4504 dreg = ARCH_DEP(vfetch8) (effective_addr2, b2, regs);
4505
4506 /* Update register contents */
4507 regs->fpr[i1] = dreg >> 32;
4508 regs->fpr[i1+1] = dreg;
4509
4510 } /* end DEF_INST(load_float_long) */
4511
4512
4513 /*-------------------------------------------------------------------*/
4514 /* 69 CD - Compare Floating Point Long [RX] */
4515 /*-------------------------------------------------------------------*/
DEF_INST(compare_float_long)4516 DEF_INST(compare_float_long)
4517 {
4518 int r1; /* Value of R field */
4519 int i1; /* Index of R1 in fpr array */
4520 int b2; /* Base of effective addr */
4521 VADR effective_addr2; /* Effective address */
4522 LONG_FLOAT fl;
4523 LONG_FLOAT cmp_fl;
4524
4525 RX(inst, regs, r1, b2, effective_addr2);
4526 HFPREG_CHECK(r1, regs);
4527 i1 = FPR2I(r1);
4528
4529 /* Get the operands */
4530 get_lf(&fl, regs->fpr + i1);
4531 vfetch_lf(&cmp_fl, effective_addr2, b2, regs );
4532
4533 /* Compare long */
4534 cmp_lf(&fl, &cmp_fl, regs);
4535
4536 } /* end DEF_INST(compare_float_long) */
4537
4538
4539 /*-------------------------------------------------------------------*/
4540 /* 6A AD - Add Floating Point Long [RX] */
4541 /*-------------------------------------------------------------------*/
DEF_INST(add_float_long)4542 DEF_INST(add_float_long)
4543 {
4544 int r1; /* Value of R field */
4545 int i1; /* Index of R1 in fpr array */
4546 int b2; /* Base of effective addr */
4547 VADR effective_addr2; /* Effective address */
4548 LONG_FLOAT fl;
4549 LONG_FLOAT add_fl;
4550 int pgm_check;
4551
4552 RX(inst, regs, r1, b2, effective_addr2);
4553 HFPREG_CHECK(r1, regs);
4554 i1 = FPR2I(r1);
4555
4556 /* Get the operands */
4557 get_lf(&fl, regs->fpr + i1);
4558 vfetch_lf(&add_fl, effective_addr2, b2, regs );
4559
4560 /* Add long with normalization */
4561 pgm_check = add_lf(&fl, &add_fl, NORMAL, SIGEX, regs);
4562
4563 /* Set condition code */
4564 if (fl.long_fract) {
4565 regs->psw.cc = fl.sign ? 1 : 2;
4566 } else {
4567 regs->psw.cc = 0;
4568 }
4569
4570 /* Back to register */
4571 store_lf(&fl, regs->fpr + i1);
4572
4573 /* Program check ? */
4574 if (pgm_check) {
4575 ARCH_DEP(program_interrupt) (regs, pgm_check);
4576 }
4577
4578 } /* end DEF_INST(add_float_long) */
4579
4580
4581 /*-------------------------------------------------------------------*/
4582 /* 6B SD - Subtract Floating Point Long [RX] */
4583 /*-------------------------------------------------------------------*/
DEF_INST(subtract_float_long)4584 DEF_INST(subtract_float_long)
4585 {
4586 int r1; /* Value of R field */
4587 int i1; /* Index of R1 in fpr array */
4588 int b2; /* Base of effective addr */
4589 VADR effective_addr2; /* Effective address */
4590 LONG_FLOAT fl;
4591 LONG_FLOAT sub_fl;
4592 int pgm_check;
4593
4594 RX(inst, regs, r1, b2, effective_addr2);
4595 HFPREG_CHECK(r1, regs);
4596 i1 = FPR2I(r1);
4597
4598 /* Get the operands */
4599 get_lf(&fl, regs->fpr + i1);
4600 vfetch_lf(&sub_fl, effective_addr2, b2, regs );
4601
4602 /* Invert the sign of 2nd operand */
4603 sub_fl.sign = ! (sub_fl.sign);
4604
4605 /* Add long with normalization */
4606 pgm_check = add_lf(&fl, &sub_fl, NORMAL, SIGEX, regs);
4607
4608 /* Set condition code */
4609 if (fl.long_fract) {
4610 regs->psw.cc = fl.sign ? 1 : 2;
4611 } else {
4612 regs->psw.cc = 0;
4613 }
4614
4615 /* Back to register */
4616 store_lf(&fl, regs->fpr + i1);
4617
4618 /* Program check ? */
4619 if (pgm_check) {
4620 ARCH_DEP(program_interrupt) (regs, pgm_check);
4621 }
4622
4623 } /* end DEF_INST(subtract_float_long) */
4624
4625
4626 /*-------------------------------------------------------------------*/
4627 /* 6C MD - Multiply Floating Point Long [RX] */
4628 /*-------------------------------------------------------------------*/
DEF_INST(multiply_float_long)4629 DEF_INST(multiply_float_long)
4630 {
4631 int r1; /* Value of R field */
4632 int i1; /* Index of R1 in fpr array */
4633 int b2; /* Base of effective addr */
4634 VADR effective_addr2; /* Effective address */
4635 LONG_FLOAT fl;
4636 LONG_FLOAT mul_fl;
4637 int pgm_check;
4638
4639 RX(inst, regs, r1, b2, effective_addr2);
4640 HFPREG_CHECK(r1, regs);
4641 i1 = FPR2I(r1);
4642
4643 /* Get the operands */
4644 get_lf(&fl, regs->fpr + i1);
4645 vfetch_lf(&mul_fl, effective_addr2, b2, regs );
4646
4647 /* multiply long */
4648 pgm_check = mul_lf(&fl, &mul_fl, OVUNF, regs);
4649
4650 /* Back to register */
4651 store_lf(&fl, regs->fpr + i1);
4652
4653 /* Program check ? */
4654 if (pgm_check) {
4655 ARCH_DEP(program_interrupt) (regs, pgm_check);
4656 }
4657
4658 } /* end DEF_INST(multiply_float_long) */
4659
4660
4661 /*-------------------------------------------------------------------*/
4662 /* 6D DD - Divide Floating Point Long [RX] */
4663 /*-------------------------------------------------------------------*/
DEF_INST(divide_float_long)4664 DEF_INST(divide_float_long)
4665 {
4666 int r1; /* Value of R field */
4667 int i1; /* Index of R1 in fpr array */
4668 int b2; /* Base of effective addr */
4669 VADR effective_addr2; /* Effective address */
4670 LONG_FLOAT fl;
4671 LONG_FLOAT div_fl;
4672 int pgm_check;
4673
4674 RX(inst, regs, r1, b2, effective_addr2);
4675 HFPREG_CHECK(r1, regs);
4676 i1 = FPR2I(r1);
4677
4678 /* Get the operands */
4679 get_lf(&fl, regs->fpr + i1);
4680 vfetch_lf(&div_fl, effective_addr2, b2, regs );
4681
4682 /* divide long */
4683 pgm_check = div_lf(&fl, &div_fl, regs);
4684
4685 /* Back to register */
4686 store_lf(&fl, regs->fpr + i1);
4687
4688 /* Program check ? */
4689 if (pgm_check) {
4690 ARCH_DEP(program_interrupt) (regs, pgm_check);
4691 }
4692
4693 } /* end DEF_INST(divide_float_long) */
4694
4695
4696 /*-------------------------------------------------------------------*/
4697 /* 6E AW - Add Unnormalized Floating Point Long [RX] */
4698 /*-------------------------------------------------------------------*/
DEF_INST(add_unnormal_float_long)4699 DEF_INST(add_unnormal_float_long)
4700 {
4701 int r1; /* Value of R field */
4702 int i1; /* Index of R1 in fpr array */
4703 int b2; /* Base of effective addr */
4704 VADR effective_addr2; /* Effective address */
4705 LONG_FLOAT fl;
4706 LONG_FLOAT add_fl;
4707 int pgm_check;
4708
4709 RX(inst, regs, r1, b2, effective_addr2);
4710 HFPREG_CHECK(r1, regs);
4711 i1 = FPR2I(r1);
4712
4713 /* Get the operands */
4714 get_lf(&fl, regs->fpr + i1);
4715 vfetch_lf(&add_fl, effective_addr2, b2, regs );
4716
4717 /* Add long without normalization */
4718 pgm_check = add_lf(&fl, &add_fl, UNNORMAL, SIGEX, regs);
4719
4720 /* Set condition code */
4721 if (fl.long_fract) {
4722 regs->psw.cc = fl.sign ? 1 : 2;
4723 } else {
4724 regs->psw.cc = 0;
4725 }
4726
4727 /* Back to register */
4728 store_lf(&fl, regs->fpr + i1);
4729
4730 /* Program check ? */
4731 if (pgm_check) {
4732 ARCH_DEP(program_interrupt) (regs, pgm_check);
4733 }
4734
4735 } /* end DEF_INST(add_unnormal_float_long) */
4736
4737
4738 /*-------------------------------------------------------------------*/
4739 /* 6F SW - Subtract Unnormalized Floating Point Long [RX] */
4740 /*-------------------------------------------------------------------*/
DEF_INST(subtract_unnormal_float_long)4741 DEF_INST(subtract_unnormal_float_long)
4742 {
4743 int r1; /* Value of R field */
4744 int i1; /* Index of R1 in fpr array */
4745 int b2; /* Base of effective addr */
4746 VADR effective_addr2; /* Effective address */
4747 LONG_FLOAT fl;
4748 LONG_FLOAT sub_fl;
4749 int pgm_check;
4750
4751 RX(inst, regs, r1, b2, effective_addr2);
4752 HFPREG_CHECK(r1, regs);
4753 i1 = FPR2I(r1);
4754
4755 /* Get the operands */
4756 get_lf(&fl, regs->fpr + i1);
4757 vfetch_lf(&sub_fl, effective_addr2, b2, regs );
4758
4759 /* Invert the sign of 2nd operand */
4760 sub_fl.sign = ! (sub_fl.sign);
4761
4762 /* Add long without normalization */
4763 pgm_check = add_lf(&fl, &sub_fl, UNNORMAL, SIGEX, regs);
4764
4765 /* Set condition code */
4766 if (fl.long_fract) {
4767 regs->psw.cc = fl.sign ? 1 : 2;
4768 } else {
4769 regs->psw.cc = 0;
4770 }
4771
4772 /* Back to register */
4773 store_lf(&fl, regs->fpr + i1);
4774
4775 /* Program check ? */
4776 if (pgm_check) {
4777 ARCH_DEP(program_interrupt) (regs, pgm_check);
4778 }
4779
4780 } /* end DEF_INST(subtract_unnormal_float_long) */
4781
4782
4783 /*-------------------------------------------------------------------*/
4784 /* 70 STE - Store Floating Point Short [RX] */
4785 /*-------------------------------------------------------------------*/
DEF_INST(store_float_short)4786 DEF_INST(store_float_short)
4787 {
4788 int r1; /* Value of R field */
4789 int i1; /* Index of R1 in fpr array */
4790 int b2; /* Base of effective addr */
4791 VADR effective_addr2; /* Effective address */
4792
4793 RX(inst, regs, r1, b2, effective_addr2);
4794 HFPREG_CHECK(r1, regs);
4795 i1 = FPR2I(r1);
4796
4797 /* Store register contents at operand address */
4798 ARCH_DEP(vstore4) (regs->fpr[i1], effective_addr2, b2, regs);
4799
4800 } /* end DEF_INST(store_float_short) */
4801
4802
4803 /*-------------------------------------------------------------------*/
4804 /* 78 LE - Load Floating Point Short [RX] */
4805 /*-------------------------------------------------------------------*/
DEF_INST(load_float_short)4806 DEF_INST(load_float_short)
4807 {
4808 int r1; /* Value of R field */
4809 int i1; /* Index of R1 in fpr array */
4810 int b2; /* Base of effective addr */
4811 VADR effective_addr2; /* Effective address */
4812
4813 RX(inst, regs, r1, b2, effective_addr2);
4814 HFPREG_CHECK(r1, regs);
4815 i1 = FPR2I(r1);
4816
4817 /* Update first 32 bits of register from operand address */
4818 regs->fpr[i1] = ARCH_DEP(vfetch4) (effective_addr2, b2, regs);
4819
4820 } /* end DEF_INST(load_float_short) */
4821
4822
4823 /*-------------------------------------------------------------------*/
4824 /* 79 CE - Compare Floating Point Short [RX] */
4825 /*-------------------------------------------------------------------*/
DEF_INST(compare_float_short)4826 DEF_INST(compare_float_short)
4827 {
4828 int r1; /* Value of R field */
4829 int i1; /* Index of R1 in fpr array */
4830 int b2; /* Base of effective addr */
4831 VADR effective_addr2; /* Effective address */
4832 SHORT_FLOAT fl;
4833 SHORT_FLOAT cmp_fl;
4834
4835 RX(inst, regs, r1, b2, effective_addr2);
4836 HFPREG_CHECK(r1, regs);
4837 i1 = FPR2I(r1);
4838
4839 /* Get the operands */
4840 get_sf(&fl, regs->fpr + i1);
4841 vfetch_sf(&cmp_fl, effective_addr2, b2, regs );
4842
4843 /* Compare long */
4844 cmp_sf(&fl, &cmp_fl, regs);
4845
4846 } /* end DEF_INST(compare_float_short) */
4847
4848
4849 /*-------------------------------------------------------------------*/
4850 /* 7A AE - Add Floating Point Short [RX] */
4851 /*-------------------------------------------------------------------*/
DEF_INST(add_float_short)4852 DEF_INST(add_float_short)
4853 {
4854 int r1; /* Value of R field */
4855 int i1; /* Index of R1 in fpr array */
4856 int b2; /* Base of effective addr */
4857 VADR effective_addr2; /* Effective address */
4858 SHORT_FLOAT fl;
4859 SHORT_FLOAT add_fl;
4860 int pgm_check;
4861
4862 RX(inst, regs, r1, b2, effective_addr2);
4863 HFPREG_CHECK(r1, regs);
4864 i1 = FPR2I(r1);
4865
4866 /* Get the operands */
4867 get_sf(&fl, regs->fpr + i1);
4868 vfetch_sf(&add_fl, effective_addr2, b2, regs );
4869
4870 /* Add short with normalization */
4871 pgm_check = add_sf(&fl, &add_fl, NORMAL, SIGEX, regs);
4872
4873 /* Set condition code */
4874 if (fl.short_fract) {
4875 regs->psw.cc = fl.sign ? 1 : 2;
4876 } else {
4877 regs->psw.cc = 0;
4878 }
4879
4880 /* Back to register */
4881 store_sf(&fl, regs->fpr + i1);
4882
4883 /* Program check ? */
4884 if (pgm_check) {
4885 ARCH_DEP(program_interrupt) (regs, pgm_check);
4886 }
4887
4888 } /* end DEF_INST(add_float_short) */
4889
4890
4891 /*-------------------------------------------------------------------*/
4892 /* 7B SE - Subtract Floating Point Short [RX] */
4893 /*-------------------------------------------------------------------*/
DEF_INST(subtract_float_short)4894 DEF_INST(subtract_float_short)
4895 {
4896 int r1; /* Value of R field */
4897 int i1; /* Index of R1 in fpr array */
4898 int b2; /* Base of effective addr */
4899 VADR effective_addr2; /* Effective address */
4900 SHORT_FLOAT fl;
4901 SHORT_FLOAT sub_fl;
4902 int pgm_check;
4903
4904 RX(inst, regs, r1, b2, effective_addr2);
4905 HFPREG_CHECK(r1, regs);
4906 i1 = FPR2I(r1);
4907
4908 /* Get the operands */
4909 get_sf(&fl, regs->fpr + i1);
4910 vfetch_sf(&sub_fl, effective_addr2, b2, regs );
4911
4912 /* Invert the sign of 2nd operand */
4913 sub_fl.sign = ! (sub_fl.sign);
4914
4915 /* Add short with normalization */
4916 pgm_check = add_sf(&fl, &sub_fl, NORMAL, SIGEX, regs);
4917
4918 /* Set condition code */
4919 if (fl.short_fract) {
4920 regs->psw.cc = fl.sign ? 1 : 2;
4921 } else {
4922 regs->psw.cc = 0;
4923 }
4924
4925 /* Back to register */
4926 store_sf(&fl, regs->fpr + i1);
4927
4928 /* Program check ? */
4929 if (pgm_check) {
4930 ARCH_DEP(program_interrupt) (regs, pgm_check);
4931 }
4932
4933 } /* end DEF_INST(subtract_float_short) */
4934
4935
4936 /*-------------------------------------------------------------------*/
4937 /* 7C MDE - Multiply Floating Point Short to Long [RX] */
4938 /* Older mnemonic of this instruction is ME */
4939 /*-------------------------------------------------------------------*/
DEF_INST(multiply_float_short_to_long)4940 DEF_INST(multiply_float_short_to_long)
4941 {
4942 int r1; /* Value of R field */
4943 int i1; /* Index of R1 in fpr array */
4944 int b2; /* Base of effective addr */
4945 VADR effective_addr2; /* Effective address */
4946 SHORT_FLOAT fl;
4947 SHORT_FLOAT mul_fl;
4948 LONG_FLOAT result_fl;
4949 int pgm_check;
4950
4951 RX(inst, regs, r1, b2, effective_addr2);
4952 HFPREG_CHECK(r1, regs);
4953 i1 = FPR2I(r1);
4954
4955 /* Get the operands */
4956 get_sf(&fl, regs->fpr + i1);
4957 vfetch_sf(&mul_fl, effective_addr2, b2, regs );
4958
4959 /* multiply short to long */
4960 pgm_check = mul_sf_to_lf(&fl, &mul_fl, &result_fl, regs);
4961
4962 /* Back to register */
4963 store_lf(&result_fl, regs->fpr + i1);
4964
4965 /* Program check ? */
4966 if (pgm_check) {
4967 ARCH_DEP(program_interrupt) (regs, pgm_check);
4968 }
4969
4970 } /* end DEF_INST(multiply_float_short_to_long) */
4971
4972
4973 /*-------------------------------------------------------------------*/
4974 /* 7D DE - Divide Floating Point Short [RX] */
4975 /*-------------------------------------------------------------------*/
DEF_INST(divide_float_short)4976 DEF_INST(divide_float_short)
4977 {
4978 int r1; /* Value of R field */
4979 int i1; /* Index of R1 in fpr array */
4980 int b2; /* Base of effective addr */
4981 VADR effective_addr2; /* Effective address */
4982 SHORT_FLOAT fl;
4983 SHORT_FLOAT div_fl;
4984 int pgm_check;
4985
4986 RX(inst, regs, r1, b2, effective_addr2);
4987 HFPREG_CHECK(r1, regs);
4988 i1 = FPR2I(r1);
4989
4990 /* Get the operands */
4991 get_sf(&fl, regs->fpr + i1);
4992 vfetch_sf(&div_fl, effective_addr2, b2, regs );
4993
4994 /* divide short */
4995 pgm_check = div_sf(&fl, &div_fl, regs);
4996
4997 /* Back to register */
4998 store_sf(&fl, regs->fpr + i1);
4999
5000 /* Program check ? */
5001 if (pgm_check) {
5002 ARCH_DEP(program_interrupt) (regs, pgm_check);
5003 }
5004
5005 } /* end DEF_INST(divide_float_short) */
5006
5007
5008 /*-------------------------------------------------------------------*/
5009 /* 7E AU - Add Unnormalized Floating Point Short [RX] */
5010 /*-------------------------------------------------------------------*/
DEF_INST(add_unnormal_float_short)5011 DEF_INST(add_unnormal_float_short)
5012 {
5013 int r1; /* Value of R field */
5014 int i1; /* Index of R1 in fpr array */
5015 int b2; /* Base of effective addr */
5016 VADR effective_addr2; /* Effective address */
5017 SHORT_FLOAT fl;
5018 SHORT_FLOAT add_fl;
5019 int pgm_check;
5020
5021 RX(inst, regs, r1, b2, effective_addr2);
5022 HFPREG_CHECK(r1, regs);
5023 i1 = FPR2I(r1);
5024
5025 /* Get the operands */
5026 get_sf(&fl, regs->fpr + i1);
5027 vfetch_sf(&add_fl, effective_addr2, b2, regs );
5028
5029 /* Add short without normalization */
5030 pgm_check = add_sf(&fl, &add_fl, UNNORMAL, SIGEX, regs);
5031
5032 /* Set condition code */
5033 if (fl.short_fract) {
5034 regs->psw.cc = fl.sign ? 1 : 2;
5035 } else {
5036 regs->psw.cc = 0;
5037 }
5038
5039 /* Back to register */
5040 store_sf(&fl, regs->fpr + i1);
5041
5042 /* Program check ? */
5043 if (pgm_check) {
5044 ARCH_DEP(program_interrupt) (regs, pgm_check);
5045 }
5046
5047 } /* end DEF_INST(add_unnormal_float_short) */
5048
5049
5050 /*-------------------------------------------------------------------*/
5051 /* 7F SU - Subtract Unnormalized Floating Point Short [RX] */
5052 /*-------------------------------------------------------------------*/
DEF_INST(subtract_unnormal_float_short)5053 DEF_INST(subtract_unnormal_float_short)
5054 {
5055 int r1; /* Value of R field */
5056 int i1; /* Index of R1 in fpr array */
5057 int b2; /* Base of effective addr */
5058 VADR effective_addr2; /* Effective address */
5059 SHORT_FLOAT fl;
5060 SHORT_FLOAT sub_fl;
5061 int pgm_check;
5062
5063 RX(inst, regs, r1, b2, effective_addr2);
5064 HFPREG_CHECK(r1, regs);
5065 i1 = FPR2I(r1);
5066
5067 /* Get the operands */
5068 get_sf(&fl, regs->fpr + i1);
5069 vfetch_sf(&sub_fl, effective_addr2, b2, regs );
5070
5071 /* Invert the sign of 2nd operand */
5072 sub_fl.sign = ! (sub_fl.sign);
5073
5074 /* Add short without normalization */
5075 pgm_check = add_sf(&fl, &sub_fl, UNNORMAL, SIGEX, regs);
5076
5077 /* Set condition code */
5078 if (fl.short_fract) {
5079 regs->psw.cc = fl.sign ? 1 : 2;
5080 } else {
5081 regs->psw.cc = 0;
5082 }
5083
5084 /* Back to register */
5085 store_sf(&fl, regs->fpr + i1);
5086
5087 /* Program check ? */
5088 if (pgm_check) {
5089 ARCH_DEP(program_interrupt) (regs, pgm_check);
5090 }
5091
5092 } /* end DEF_INST(subtract_unnormal_float_short) */
5093
5094
5095 /*-------------------------------------------------------------------*/
5096 /* B22D DXR - Divide Floating Point Extended Register [RRE] */
5097 /*-------------------------------------------------------------------*/
DEF_INST(divide_float_ext_reg)5098 DEF_INST(divide_float_ext_reg)
5099 {
5100 int r1, r2; /* Values of R fields */
5101 int i1, i2; /* Indexes into fpr array */
5102 EXTENDED_FLOAT fl;
5103 EXTENDED_FLOAT div_fl;
5104 int pgm_check;
5105
5106 RRE(inst, regs, r1, r2);
5107 HFPODD2_CHECK(r1, r2, regs);
5108 i1 = FPR2I(r1);
5109 i2 = FPR2I(r2);
5110
5111 /* Get the operands */
5112 get_ef(&fl, regs->fpr + i1);
5113 get_ef(&div_fl, regs->fpr + i2);
5114
5115 /* divide extended */
5116 pgm_check = div_ef(&fl, &div_fl, regs);
5117
5118 /* Back to register */
5119 store_ef(&fl, regs->fpr + i1);
5120
5121 /* Program check ? */
5122 if (pgm_check) {
5123 ARCH_DEP(program_interrupt) (regs, pgm_check);
5124 }
5125
5126 } /* end DEF_INST(divide_float_ext_reg) */
5127
5128
5129 #if defined (FEATURE_SQUARE_ROOT)
5130 /*-------------------------------------------------------------------*/
5131 /* B244 SQDR - Square Root Floating Point Long Register [RRE] */
5132 /*-------------------------------------------------------------------*/
DEF_INST(squareroot_float_long_reg)5133 DEF_INST(squareroot_float_long_reg)
5134 {
5135 int r1, r2; /* Values of R fields */
5136 int i1, i2; /* Indexes into fpr array */
5137 LONG_FLOAT sq_fl;
5138 LONG_FLOAT fl;
5139
5140 RRE(inst, regs, r1, r2);
5141 HFPREG2_CHECK(r1, r2, regs);
5142 i1 = FPR2I(r1);
5143 i2 = FPR2I(r2);
5144
5145 /* Get the 2nd operand */
5146 get_lf(&fl, regs->fpr + i2);
5147
5148 /* square root long */
5149 sq_lf(&sq_fl, &fl, regs);
5150
5151 /* Back to register */
5152 store_lf(&sq_fl, regs->fpr + i1);
5153
5154 } /* end DEF_INST(squareroot_float_long_reg) */
5155
5156
5157 /*-------------------------------------------------------------------*/
5158 /* B245 SQER - Square Root Floating Point Short Register [RRE] */
5159 /*-------------------------------------------------------------------*/
DEF_INST(squareroot_float_short_reg)5160 DEF_INST(squareroot_float_short_reg)
5161 {
5162 int r1, r2; /* Values of R fields */
5163 int i1, i2; /* Indexes into fpr array */
5164 SHORT_FLOAT sq_fl;
5165 SHORT_FLOAT fl;
5166
5167 RRE(inst, regs, r1, r2);
5168 HFPREG2_CHECK(r1, r2, regs);
5169 i1 = FPR2I(r1);
5170 i2 = FPR2I(r2);
5171
5172 /* Get the 2nd operand */
5173 get_sf(&fl, regs->fpr + i2);
5174
5175 /* square root short */
5176 sq_sf(&sq_fl, &fl, regs);
5177
5178 /* Back to register */
5179 store_sf(&sq_fl, regs->fpr + i1);
5180
5181 } /* end DEF_INST(squareroot_float_short_reg) */
5182 #endif /* FEATURE_SQUARE_ROOT */
5183
5184
5185 #if defined (FEATURE_HFP_EXTENSIONS)
5186 /*-------------------------------------------------------------------*/
5187 /* B324 LDER - Load Length. Float. Short to Long Register [RRE] */
5188 /*-------------------------------------------------------------------*/
DEF_INST(load_lengthened_float_short_to_long_reg)5189 DEF_INST(load_lengthened_float_short_to_long_reg)
5190 {
5191 int r1, r2; /* Values of R fields */
5192 int i1, i2; /* Indexes into fpr array */
5193
5194 RRE(inst, regs, r1, r2);
5195 HFPREG2_CHECK(r1, r2, regs);
5196 i1 = FPR2I(r1);
5197 i2 = FPR2I(r2);
5198
5199 /* Copy register content */
5200 regs->fpr[i1] = regs->fpr[i2];
5201
5202 /* Clear register */
5203 regs->fpr[i1+1] = 0;
5204
5205 } /* end DEF_INST(load_lengthened_float_short_to_long_reg) */
5206
5207
5208 /*-------------------------------------------------------------------*/
5209 /* B325 LXDR - Load Length. Float. Long to Extended Register [RRE] */
5210 /*-------------------------------------------------------------------*/
DEF_INST(load_lengthened_float_long_to_ext_reg)5211 DEF_INST(load_lengthened_float_long_to_ext_reg)
5212 {
5213 int r1, r2; /* Values of R fields */
5214 int i1, i2; /* Indexes into fpr array */
5215
5216 RRE(inst, regs, r1, r2);
5217
5218 HFPODD_CHECK(r1, regs);
5219 HFPREG_CHECK(r2, regs);
5220 i1 = FPR2I(r1);
5221 i2 = FPR2I(r2);
5222
5223 if ((regs->fpr[i2] & 0x00FFFFFF) || regs->fpr[i2+1]) {
5224 /* Copy register contents */
5225 regs->fpr[i1] = regs->fpr[i2];
5226 regs->fpr[i1+1] = regs->fpr[i2+1];
5227
5228 /* Low order register */
5229 regs->fpr[i1+FPREX] = (regs->fpr[i2] & 0x80000000)
5230 | ((regs->fpr[i2] - (14 << 24)) & 0x7F000000);
5231 } else {
5232 /* true zero with sign */
5233 regs->fpr[i1] = regs->fpr[i2] & 0x80000000;
5234 regs->fpr[i1+1] = 0;
5235 regs->fpr[i1+FPREX] = regs->fpr[i1];
5236 }
5237 /* Clear register */
5238 regs->fpr[i1+FPREX+1] = 0;
5239
5240 } /* end DEF_INST(load_lengthened_float_long_to_ext_reg) */
5241
5242
5243 /*-------------------------------------------------------------------*/
5244 /* B326 LXER - Load Length. Float. Short to Extended Register [RRE] */
5245 /*-------------------------------------------------------------------*/
DEF_INST(load_lengthened_float_short_to_ext_reg)5246 DEF_INST(load_lengthened_float_short_to_ext_reg)
5247 {
5248 int r1, r2; /* Values of R fields */
5249 int i1, i2; /* Indexes into fpr array */
5250
5251 RRE(inst, regs, r1, r2);
5252
5253 HFPODD_CHECK(r1, regs);
5254 HFPREG_CHECK(r2, regs);
5255 i1 = FPR2I(r1);
5256 i2 = FPR2I(r2);
5257
5258 if (regs->fpr[i2] & 0x00FFFFFF) {
5259 /* Copy register content */
5260 regs->fpr[i1] = regs->fpr[i2];
5261
5262 /* Low order register */
5263 regs->fpr[i1+FPREX] = (regs->fpr[i2] & 0x80000000)
5264 | ((regs->fpr[i2] - (14 << 24)) & 0x7F000000);
5265 } else {
5266 /* true zero with sign */
5267 regs->fpr[i1] = regs->fpr[i2] & 0x80000000;
5268 regs->fpr[i1+FPREX] = regs->fpr[i1];
5269 }
5270 /* Clear register */
5271 regs->fpr[i1+1] = 0;
5272 regs->fpr[i1+FPREX+1] = 0;
5273
5274 } /* end DEF_INST(load_lengthened_float_short_to_ext_reg) */
5275
5276
5277 /*-------------------------------------------------------------------*/
5278 /* B336 SQXR - Square Root Floating Point Extended Register [RRE] */
5279 /*-------------------------------------------------------------------*/
DEF_INST(squareroot_float_ext_reg)5280 DEF_INST(squareroot_float_ext_reg)
5281 {
5282 int r1, r2; /* Values of R fields */
5283 int i1, i2; /* Indexes into fpr array */
5284 EXTENDED_FLOAT sq_fl;
5285 EXTENDED_FLOAT fl;
5286 U64 mmsa, msa, lsa, llsa;
5287 U64 xi;
5288 U64 xj;
5289 U64 msi, lsi;
5290 U64 msj, lsj;
5291
5292 RRE(inst, regs, r1, r2);
5293 HFPODD2_CHECK(r1, r2, regs);
5294 i1 = FPR2I(r1);
5295 i2 = FPR2I(r2);
5296
5297 /* Get the 2nd operand */
5298 get_ef(&fl, regs->fpr + i2);
5299
5300 if ((fl.ms_fract) || (fl.ls_fract)) {
5301 if (fl.sign) {
5302 /* less than zero */
5303
5304 ARCH_DEP(program_interrupt) (regs, PGM_SQUARE_ROOT_EXCEPTION);
5305 return; /* Never reached */
5306 } else {
5307 /* normalize operand */
5308 normal_ef(&fl);
5309
5310 if (fl.expo & 1) {
5311 /* odd */
5312
5313 /* compute characteristic */
5314 sq_fl.expo = (fl.expo + 65) >> 1;
5315
5316 /* with guard digit */
5317 mmsa = fl.ms_fract >> 4;
5318 msa = (fl.ms_fract << 60)
5319 | (fl.ls_fract >> 4);
5320 lsa = fl.ls_fract << 60;
5321 llsa = 0;
5322 } else {
5323 /* even */
5324
5325 /* compute characteristic */
5326 sq_fl.expo = (fl.expo + 64) >> 1;
5327
5328 /* without guard digit */
5329 mmsa = fl.ms_fract;
5330 msa = fl.ls_fract;
5331 lsa = 0;
5332 llsa = 0;
5333 }
5334
5335 /* square root of fraction low precision */
5336 /* common subroutine of all square root */
5337 xi = ((U64) (square_root_fraction(mmsa & 0xFFFFFFFFFFFFFFFEULL)) << 32)
5338 | 0x80000000UL;
5339
5340 /* continue iteration for high precision */
5341 /* done iteration when xi, xj equal or differ by 1 */
5342 for (;;) {
5343 xj = (div_U128(mmsa, msa, xi) + xi) >> 1;
5344
5345 if ((xj == xi) || (abs(xj - xi) == 1)) {
5346 break;
5347 }
5348 xi = xj;
5349 }
5350
5351 msi = xi;
5352 lsi = 0x8000000000000000ULL;
5353
5354 /* continue iteration for extended precision */
5355 for (;;) {
5356 div_U256(mmsa, msa, lsa, llsa, msi, lsi, &msj, &lsj);
5357 add_U128(msj, lsj, msi, lsi);
5358 shift_right_U128(msj, lsj);
5359
5360 if ((msj == msi)
5361 && (lsj == lsi)) {
5362 break;
5363 }
5364 msi = msj;
5365 lsi = lsj;
5366 }
5367 /* round with guard digit */
5368 add_U128(msi, lsi, 0, 0x80);
5369
5370 sq_fl.ls_fract = (lsi >> 8)
5371 | (msi << 56);
5372 sq_fl.ms_fract = msi >> 8;
5373 }
5374 } else {
5375 /* true zero */
5376 sq_fl.ms_fract = 0;
5377 sq_fl.ls_fract = 0;
5378 sq_fl.expo = 0;
5379 }
5380 /* all results positive */
5381 sq_fl.sign = POS;
5382
5383 /* Back to register */
5384 store_ef(&sq_fl, regs->fpr + i1);
5385
5386 } /* end DEF_INST(squareroot_float_ext_reg) */
5387
5388
5389 /*-------------------------------------------------------------------*/
5390 /* B337 MEER - Multiply Floating Point Short Register [RRE] */
5391 /*-------------------------------------------------------------------*/
DEF_INST(multiply_float_short_reg)5392 DEF_INST(multiply_float_short_reg)
5393 {
5394 int r1, r2; /* Values of R fields */
5395 int i1, i2; /* Indexes into fpr array */
5396 SHORT_FLOAT fl;
5397 SHORT_FLOAT mul_fl;
5398 int pgm_check;
5399
5400 RRE(inst, regs, r1, r2);
5401 HFPREG2_CHECK(r1, r2, regs);
5402 i1 = FPR2I(r1);
5403 i2 = FPR2I(r2);
5404
5405 /* Get the operands */
5406 get_sf(&fl, regs->fpr + i1);
5407 get_sf(&mul_fl, regs->fpr + i2);
5408
5409 /* multiply short to long */
5410 pgm_check = mul_sf(&fl, &mul_fl, OVUNF, regs);
5411
5412 /* Back to register */
5413 store_sf(&fl, regs->fpr + i1);
5414
5415 /* Program check ? */
5416 if (pgm_check) {
5417 ARCH_DEP(program_interrupt) (regs, pgm_check);
5418 }
5419
5420 } /* end DEF_INST(multiply_float_short_reg) */
5421
5422
5423 /*-------------------------------------------------------------------*/
5424 /* B360 LPXR - Load Positive Floating Point Extended Register [RRE] */
5425 /*-------------------------------------------------------------------*/
DEF_INST(load_positive_float_ext_reg)5426 DEF_INST(load_positive_float_ext_reg)
5427 {
5428 int r1, r2; /* Values of R fields */
5429 int i1, i2; /* Indexes into fpr array */
5430
5431 RRE(inst, regs, r1, r2);
5432 HFPODD2_CHECK(r1, r2, regs);
5433 i1 = FPR2I(r1);
5434 i2 = FPR2I(r2);
5435
5436 if ((regs->fpr[i2] & 0x00FFFFFF) || regs->fpr[i2+1]
5437 || (regs->fpr[i2+FPREX] & 0x00FFFFFF)
5438 || regs->fpr[i2+FPREX+1]) {
5439 /* Copy register contents, clear the sign bit */
5440 regs->fpr[i1] = regs->fpr[i2] & 0x7FFFFFFF;
5441 regs->fpr[i1+1] = regs->fpr[i2+1];
5442
5443 /* Low order register */
5444 regs->fpr[i1+FPREX] = (((regs->fpr[i2] - (14 << 24)) & 0x7F000000))
5445 | (regs->fpr[i2+FPREX] & 0x00FFFFFF);
5446 regs->fpr[i1+FPREX+1] = regs->fpr[i2+FPREX+1];
5447
5448 /* Set condition code */
5449 regs->psw.cc = 2;
5450 } else {
5451 /* true zero */
5452 regs->fpr[i1] = 0;
5453 regs->fpr[i1+1] = 0;
5454 regs->fpr[i1+FPREX] = 0;
5455 regs->fpr[i1+FPREX+1] = 0;
5456
5457 /* Set condition code */
5458 regs->psw.cc = 0;
5459 }
5460
5461 } /* end DEF_INST(load_positive_float_ext_reg) */
5462
5463
5464 /*-------------------------------------------------------------------*/
5465 /* B361 LNXR - Load Negative Floating Point Extended Register [RRE] */
5466 /*-------------------------------------------------------------------*/
DEF_INST(load_negative_float_ext_reg)5467 DEF_INST(load_negative_float_ext_reg)
5468 {
5469 int r1, r2; /* Values of R fields */
5470 int i1, i2; /* Indexes into fpr array */
5471
5472 RRE(inst, regs, r1, r2);
5473 HFPODD2_CHECK(r1, r2, regs);
5474 i1 = FPR2I(r1);
5475 i2 = FPR2I(r2);
5476
5477 if ((regs->fpr[i2] & 0x00FFFFFF) || regs->fpr[i2+1]
5478 || (regs->fpr[i2+FPREX] & 0x00FFFFFF) || regs->fpr[i2+FPREX+1]) {
5479 /* Copy register contents, set the sign bit */
5480 regs->fpr[i1] = 0x80000000
5481 | regs->fpr[i2];
5482 regs->fpr[i1+1] = regs->fpr[i2+1];
5483
5484 /* Low order register */
5485 regs->fpr[i1+FPREX] = 0x80000000
5486 | (((regs->fpr[i2] - (14 << 24)) & 0x7F000000))
5487 | (regs->fpr[i2+FPREX] & 0x00FFFFFF);
5488 regs->fpr[i1+FPREX+1] = regs->fpr[i2+FPREX+1];
5489
5490 /* Set condition code */
5491 regs->psw.cc = 1;
5492 } else {
5493 /* true zero with sign */
5494 regs->fpr[i1] = 0x80000000;
5495 regs->fpr[i1+FPREX] = 0x80000000;
5496 regs->fpr[i1+1] = 0;
5497 regs->fpr[i1+FPREX+1] = 0;
5498
5499 /* Set condition code */
5500 regs->psw.cc = 0;
5501 }
5502
5503 } /* end DEF_INST(load_negative_float_ext_reg) */
5504
5505
5506 /*-------------------------------------------------------------------*/
5507 /* B362 LTXR - Load and Test Floating Point Extended Register [RRE] */
5508 /*-------------------------------------------------------------------*/
DEF_INST(load_and_test_float_ext_reg)5509 DEF_INST(load_and_test_float_ext_reg)
5510 {
5511 int r1, r2; /* Values of R fields */
5512 int i1, i2; /* Indexes into fpr array */
5513
5514 RRE(inst, regs, r1, r2);
5515 HFPODD2_CHECK(r1, r2, regs);
5516 i1 = FPR2I(r1);
5517 i2 = FPR2I(r2);
5518
5519 if ((regs->fpr[i2] & 0x00FFFFFF) || regs->fpr[i2+1]
5520 || (regs->fpr[i2+FPREX] & 0x00FFFFFF) || regs->fpr[i2+FPREX+1]) {
5521 /* Copy register contents */
5522 regs->fpr[i1] = regs->fpr[i2];
5523 regs->fpr[i1+1] = regs->fpr[i2+1];
5524
5525 /* Low order register */
5526 regs->fpr[i1+FPREX] = (regs->fpr[i2] & 0x80000000)
5527 | ((regs->fpr[i2] - (14 << 24)) & 0x7F000000)
5528 | (regs->fpr[i2+FPREX] & 0x00FFFFFF);
5529 regs->fpr[i1+FPREX+1] = regs->fpr[i2+FPREX+1];
5530
5531 /* Set condition code */
5532 regs->psw.cc = (regs->fpr[i2] & 0x80000000) ? 1 : 2;
5533 } else {
5534 /* true zero with sign */
5535 regs->fpr[i1] = regs->fpr[i2] & 0x80000000;
5536 regs->fpr[i1+FPREX] = regs->fpr[i1];
5537 regs->fpr[i1+1] = 0;
5538 regs->fpr[i1+FPREX+1] = 0;
5539
5540 /* Set condition code */
5541 regs->psw.cc = 0;
5542 }
5543
5544 } /* end DEF_INST(load_and_test_float_ext_reg) */
5545
5546
5547 /*-------------------------------------------------------------------*/
5548 /* B363 LCXR - Load Complement Float. Extended Register [RRE] */
5549 /*-------------------------------------------------------------------*/
DEF_INST(load_complement_float_ext_reg)5550 DEF_INST(load_complement_float_ext_reg)
5551 {
5552 int r1, r2; /* Values of R fields */
5553 int i1, i2; /* Indexes into fpr array */
5554
5555 RRE(inst, regs, r1, r2);
5556 HFPODD2_CHECK(r1, r2, regs);
5557 i1 = FPR2I(r1);
5558 i2 = FPR2I(r2);
5559
5560 if ((regs->fpr[i2] & 0x00FFFFFF) || regs->fpr[i2+1]
5561 || (regs->fpr[i2+FPREX] & 0x00FFFFFF) || regs->fpr[i2+FPREX+1]) {
5562 /* Copy register contents, invert sign bit */
5563 regs->fpr[i1] = regs->fpr[i2] ^ 0x80000000;
5564 regs->fpr[i1+1] = regs->fpr[i2+1];
5565
5566 /* Low order register */
5567 regs->fpr[i1+FPREX] = (regs->fpr[i1] & 0x80000000)
5568 |(((regs->fpr[i1] & 0x7F000000) - 0x0E000000) & 0x7F000000)
5569 | (regs->fpr[i2+FPREX] & 0x00FFFFFF);
5570 regs->fpr[i1+FPREX+1] = regs->fpr[i2+FPREX+1];
5571
5572 /* Set condition code */
5573 regs->psw.cc = (regs->fpr[i1] & 0x80000000) ? 1 : 2;
5574 } else {
5575 /* true zero with sign */
5576 regs->fpr[i1] = (regs->fpr[i2] ^ 0x80000000) & 0x80000000;
5577 regs->fpr[i1+FPREX] = regs->fpr[i1];
5578 regs->fpr[i1+1] = 0;
5579 regs->fpr[i1+FPREX+1] = 0;
5580
5581 /* Set condition code */
5582 regs->psw.cc = 0;
5583 }
5584
5585 } /* end DEF_INST(load_complement_float_ext_reg) */
5586
5587
5588 /*-------------------------------------------------------------------*/
5589 /* B366 LEXR - Load Rounded Float. Extended to Short Register [RRE] */
5590 /*-------------------------------------------------------------------*/
DEF_INST(load_rounded_float_ext_to_short_reg)5591 DEF_INST(load_rounded_float_ext_to_short_reg)
5592 {
5593 int r1, r2; /* Values of R fields */
5594 int i1, i2; /* Indexes into fpr array */
5595 EXTENDED_FLOAT from_fl;
5596 SHORT_FLOAT to_fl;
5597 int pgm_check;
5598
5599 RRE(inst, regs, r1, r2);
5600
5601 HFPREG_CHECK(r1, regs);
5602 HFPODD_CHECK(r2, regs);
5603 i1 = FPR2I(r1);
5604 i2 = FPR2I(r2);
5605
5606 /* Get register content */
5607 get_ef(&from_fl, regs->fpr + i2);
5608
5609 /* Rounding */
5610 to_fl.short_fract = (from_fl.ms_fract + 0x0000000000800000ULL) >> 24;
5611 to_fl.sign = from_fl.sign;
5612 to_fl.expo = from_fl.expo;
5613
5614 /* Handle overflow */
5615 if (to_fl.short_fract & 0x0F000000) {
5616 to_fl.short_fract >>= 4;
5617 (to_fl.expo)++;
5618 pgm_check = overflow_sf(&to_fl, regs);
5619 } else {
5620 pgm_check = 0;
5621 }
5622
5623 /* To register */
5624 store_sf(&to_fl, regs->fpr + i1);
5625
5626 /* Program check ? */
5627 if (pgm_check) {
5628 ARCH_DEP(program_interrupt) (regs, pgm_check);
5629 }
5630
5631 } /* end DEF_INST(load_rounded_float_ext_to_short_reg) */
5632
5633
5634 /*-------------------------------------------------------------------*/
5635 /* B367 FIXR - Load FP Integer Float. Extended Register [RRE] */
5636 /*-------------------------------------------------------------------*/
DEF_INST(load_fp_int_float_ext_reg)5637 DEF_INST(load_fp_int_float_ext_reg)
5638 {
5639 int r1, r2; /* Values of R fields */
5640 int i1, i2; /* Indexes into fpr array */
5641 EXTENDED_FLOAT fl;
5642 BYTE shift;
5643
5644 RRE(inst, regs, r1, r2);
5645 HFPODD2_CHECK(r1, r2, regs);
5646 i1 = FPR2I(r1);
5647 i2 = FPR2I(r2);
5648
5649 /* Get register content */
5650 get_ef(&fl, regs->fpr + i2);
5651
5652 if (fl.expo > 64) {
5653 if (fl.expo < 92) {
5654 /* Denormalize */
5655 shift = (92 - fl.expo) * 4;
5656 if (shift > 64) {
5657 fl.ls_fract = fl.ms_fract >> (shift - 64);
5658 fl.ms_fract = 0;
5659 } else if (shift == 64) {
5660 fl.ls_fract = fl.ms_fract;
5661 fl.ms_fract = 0;
5662 } else {
5663 fl.ls_fract = (fl.ls_fract >> shift)
5664 | (fl.ms_fract << (64 - shift));
5665 fl.ms_fract >>= shift;
5666 }
5667 fl.expo = 92;
5668 }
5669
5670 /* Normalize result */
5671 normal_ef(&fl);
5672
5673 /* To register */
5674 store_ef(&fl, regs->fpr + i1);
5675 } else {
5676 /* True zero */
5677 regs->fpr[i1] = 0;
5678 regs->fpr[i1+1] = 0;
5679 regs->fpr[i1+FPREX] = 0;
5680 regs->fpr[i1+FPREX+1] = 0;
5681 }
5682
5683 } /* end DEF_INST(load_fp_int_float_ext_reg) */
5684
5685
5686 /*-------------------------------------------------------------------*/
5687 /* B369 CXR - Compare Floating Point Extended Register [RRE] */
5688 /*-------------------------------------------------------------------*/
DEF_INST(compare_float_ext_reg)5689 DEF_INST(compare_float_ext_reg)
5690 {
5691 int r1, r2; /* Values of R fields */
5692 int i1, i2; /* Indexes into fpr array */
5693 EXTENDED_FLOAT fl;
5694 EXTENDED_FLOAT cmp_fl;
5695
5696 RRE(inst, regs, r1, r2);
5697 HFPODD2_CHECK(r1, r2, regs);
5698 i1 = FPR2I(r1);
5699 i2 = FPR2I(r2);
5700
5701 /* Get the operands */
5702 get_ef(&fl, regs->fpr + i1);
5703 get_ef(&cmp_fl, regs->fpr + i2);;
5704
5705 /* Compare extended */
5706 cmp_ef(&fl, &cmp_fl, regs);
5707
5708 } /* end DEF_INST(compare_float_ext_reg) */
5709
5710
5711 /*-------------------------------------------------------------------*/
5712 /* B377 FIER - Load FP Integer Floating Point Short Register [RRE] */
5713 /*-------------------------------------------------------------------*/
DEF_INST(load_fp_int_float_short_reg)5714 DEF_INST(load_fp_int_float_short_reg)
5715 {
5716 int r1, r2; /* Values of R fields */
5717 int i1, i2; /* Indexes into fpr array */
5718 SHORT_FLOAT fl;
5719
5720 RRE(inst, regs, r1, r2);
5721 HFPREG2_CHECK(r1, r2, regs);
5722 i1 = FPR2I(r1);
5723 i2 = FPR2I(r2);
5724
5725 /* Get register content */
5726 get_sf(&fl, regs->fpr + i2);
5727
5728 if (fl.expo > 64) {
5729 if (fl.expo < 70) {
5730 /* Denormalize */
5731 fl.short_fract >>= ((70 - fl.expo) * 4);
5732 fl.expo = 70;
5733 }
5734
5735 /* Normalize result */
5736 normal_sf(&fl);
5737
5738 /* To register */
5739 store_sf(&fl, regs->fpr + i1);
5740 } else {
5741 /* True zero */
5742 regs->fpr[i1] = 0;
5743 }
5744
5745 } /* end DEF_INST(load_fp_int_float_short_reg) */
5746
5747
5748 /*-------------------------------------------------------------------*/
5749 /* B37F FIDR - Load FP Integer Floating Point Long Register [RRE] */
5750 /*-------------------------------------------------------------------*/
DEF_INST(load_fp_int_float_long_reg)5751 DEF_INST(load_fp_int_float_long_reg)
5752 {
5753 int r1, r2; /* Values of R fields */
5754 int i1, i2; /* Indexes into fpr array */
5755 LONG_FLOAT fl;
5756
5757 RRE(inst, regs, r1, r2);
5758 HFPREG2_CHECK(r1, r2, regs);
5759 i1 = FPR2I(r1);
5760 i2 = FPR2I(r2);
5761
5762 /* Get register content */
5763 get_lf(&fl, regs->fpr + i2);
5764
5765 if (fl.expo > 64) {
5766 if (fl.expo < 78) {
5767 /* Denormalize */
5768 fl.long_fract >>= ((78 - fl.expo) * 4);
5769 fl.expo = 78;
5770 }
5771
5772 /* Normalize result */
5773 normal_lf(&fl);
5774
5775 /* To register */
5776 store_lf(&fl, regs->fpr + i1);
5777 } else {
5778 /* True zero */
5779 regs->fpr[i1] = 0;
5780 regs->fpr[i1+1] = 0;
5781 }
5782
5783 } /* end DEF_INST(load_fp_int_float_long_reg) */
5784
5785
5786 /*-------------------------------------------------------------------*/
5787 /* B3B4 CEFR - Convert from Fixed to Float. Short Register [RRE] */
5788 /*-------------------------------------------------------------------*/
DEF_INST(convert_fixed_to_float_short_reg)5789 DEF_INST(convert_fixed_to_float_short_reg)
5790 {
5791 int r1, r2; /* Values of R fields */
5792 int i1, i2; /* Indexes into fpr array */
5793 LONG_FLOAT fl;
5794 S64 fix;
5795
5796 RRE(inst, regs, r1, r2);
5797 HFPREG_CHECK(r1, regs);
5798 i1 = FPR2I(r1);
5799 i2 = FPR2I(r2);
5800
5801 /* get fixed value */
5802 fix = regs->GR_L(r2);
5803 if (fix & 0x0000000080000000)
5804 fix |= 0xFFFFFFFF00000000ULL;
5805
5806 if (fix) {
5807 if (fix < 0) {
5808 fl.sign = NEG;
5809 fl.long_fract = (-fix);
5810 } else {
5811 fl.sign = POS;
5812 fl.long_fract = fix;
5813 }
5814 fl.expo = 78;
5815
5816 /* Normalize result */
5817 normal_lf(&fl);
5818
5819 /* To register (converting to short float) */
5820 regs->fpr[i1] = ((U32)fl.sign << 31)
5821 | ((U32)fl.expo << 24)
5822 | (fl.long_fract >> 32);
5823 } else {
5824 /* true zero */
5825 regs->fpr[i1] = 0;
5826 }
5827
5828 } /* end DEF_INST(convert_fixed_to_float_short_reg) */
5829
5830
5831 /*-------------------------------------------------------------------*/
5832 /* B3B5 CDFR - Convert from Fixed to Float. Long Register [RRE] */
5833 /*-------------------------------------------------------------------*/
DEF_INST(convert_fixed_to_float_long_reg)5834 DEF_INST(convert_fixed_to_float_long_reg)
5835 {
5836 int r1, r2; /* Values of R fields */
5837 int i1; /* Index of R1 in fpr array */
5838 LONG_FLOAT fl;
5839 S64 fix;
5840
5841 RRE(inst, regs, r1, r2);
5842 HFPREG_CHECK(r1, regs);
5843 i1 = FPR2I(r1);
5844
5845 /* get fixed value */
5846 fix = regs->GR_L(r2);
5847 if (fix & 0x0000000080000000)
5848 fix |= 0xFFFFFFFF00000000ULL;
5849
5850 if (fix) {
5851 if (fix < 0) {
5852 fl.sign = NEG;
5853 fl.long_fract = (-fix);
5854 } else {
5855 fl.sign = POS;
5856 fl.long_fract = fix;
5857 }
5858 fl.expo = 78;
5859
5860 /* Normalize result */
5861 normal_lf(&fl);
5862
5863 /* To register */
5864 store_lf(&fl, regs->fpr + i1);
5865 } else {
5866 /* true zero */
5867 regs->fpr[i1] = 0;
5868 regs->fpr[i1+1] = 0;
5869 }
5870
5871 } /* end DEF_INST(convert_fixed_to_float_long_reg) */
5872
5873
5874 /*-------------------------------------------------------------------*/
5875 /* B3B6 CXFR - Convert from Fixed to Float. Extended Register [RRE] */
5876 /*-------------------------------------------------------------------*/
DEF_INST(convert_fixed_to_float_ext_reg)5877 DEF_INST(convert_fixed_to_float_ext_reg)
5878 {
5879 int r1, r2; /* Values of R fields */
5880 int i1; /* Index of R1 in fpr array */
5881 EXTENDED_FLOAT fl;
5882 S64 fix;
5883
5884 RRE(inst, regs, r1, r2);
5885 HFPODD_CHECK(r1, regs);
5886 i1 = FPR2I(r1);
5887
5888 /* get fixed value */
5889 fix = regs->GR_L(r2);
5890 if (fix & 0x0000000080000000)
5891 fix |= 0xFFFFFFFF00000000ULL;
5892
5893 if (fix) {
5894 if (fix < 0) {
5895 fl.sign = NEG;
5896 fl.ms_fract = (-fix);
5897 } else {
5898 fl.sign = POS;
5899 fl.ms_fract = fix;
5900 }
5901 fl.ls_fract = 0;
5902 fl.expo = 76; /* 64 + 12 digits) */
5903
5904 /* Normalize result */
5905 normal_ef(&fl);
5906
5907 /* To register */
5908 store_ef(&fl, regs->fpr + i1);
5909 } else {
5910 /* true zero */
5911 regs->fpr[i1] = 0;
5912 regs->fpr[i1+1] = 0;
5913 regs->fpr[i1+FPREX] = 0;
5914 regs->fpr[i1+FPREX+1] = 0;
5915 }
5916
5917 } /* end DEF_INST(convert_fixed_to_float_ext_reg) */
5918
5919
5920 /*-------------------------------------------------------------------*/
5921 /* B3C4 CEGR - Convert from Fix64 to Float. Short Register [RRE] */
5922 /*-------------------------------------------------------------------*/
DEF_INST(convert_fix64_to_float_short_reg)5923 DEF_INST(convert_fix64_to_float_short_reg)
5924 {
5925 int r1, r2; /* Values of R fields */
5926 int i1; /* Index of R1 in fpr array */
5927 SHORT_FLOAT fl;
5928 U64 fix;
5929
5930 RRE(inst, regs, r1, r2);
5931 HFPREG_CHECK(r1, regs);
5932 i1 = FPR2I(r1);
5933 fix = regs->GR_G(r2);
5934
5935 /* Test for negative value */
5936 if (fix & 0x8000000000000000ULL) {
5937 fix = ~fix + 1; /* fix = abs(fix); */
5938 fl.sign = NEG;
5939 } else
5940 fl.sign = POS;
5941
5942 if (fix) {
5943 fl.expo = 70;
5944
5945 /* Truncate fraction to 6 hexadecimal digits */
5946 while (fix & 0xFFFFFFFFFF000000ULL)
5947 {
5948 fix >>= 4;
5949 fl.expo += 1;
5950 }
5951 fl.short_fract = (U32)fix;
5952
5953 /* Normalize result */
5954 normal_sf(&fl);
5955
5956 /* To register */
5957 store_sf(&fl, regs->fpr + i1);
5958 } else {
5959 /* true zero */
5960 regs->fpr[i1] = 0;
5961 }
5962
5963 } /* end DEF_INST(convert_fix64_to_float_short_reg) */
5964
5965
5966 /*-------------------------------------------------------------------*/
5967 /* B3C5 CDGR - Convert from Fix64 to Float. Long Register [RRE] */
5968 /*-------------------------------------------------------------------*/
DEF_INST(convert_fix64_to_float_long_reg)5969 DEF_INST(convert_fix64_to_float_long_reg)
5970 {
5971 int r1, r2; /* Values of R fields */
5972 int i1; /* Index of R1 in fpr array */
5973 LONG_FLOAT fl;
5974 U64 fix;
5975
5976 RRE(inst, regs, r1, r2);
5977 HFPREG_CHECK(r1, regs);
5978 i1 = FPR2I(r1);
5979 fix = regs->GR_G(r2);
5980
5981 /* Test for negative value */
5982 if (fix & 0x8000000000000000ULL) {
5983 fix = ~fix + 1; /* fix = abs(fix); */
5984 fl.sign = NEG;
5985 } else
5986 fl.sign = POS;
5987
5988 if (fix) {
5989 fl.long_fract = fix;
5990 fl.expo = 78;
5991
5992 /* Truncate fraction to 14 hexadecimal digits */
5993 while (fl.long_fract & 0xFF00000000000000ULL)
5994 {
5995 fl.long_fract >>= 4;
5996 fl.expo += 1;
5997 }
5998
5999 /* Normalize result */
6000 normal_lf(&fl);
6001
6002 /* To register */
6003 store_lf(&fl, regs->fpr + i1);
6004 } else {
6005 /* true zero */
6006 regs->fpr[i1] = 0;
6007 regs->fpr[i1+1] = 0;
6008 }
6009
6010 } /* end DEF_INST(convert_fix64_to_float_long_reg) */
6011
6012
6013 /*-------------------------------------------------------------------*/
6014 /* B3C6 CXGR - Convert from Fix64 to Float. Extended Register [RRE] */
6015 /*-------------------------------------------------------------------*/
DEF_INST(convert_fix64_to_float_ext_reg)6016 DEF_INST(convert_fix64_to_float_ext_reg)
6017 {
6018 int r1, r2; /* Values of R fields */
6019 int i1; /* Index of R1 in fpr array */
6020 EXTENDED_FLOAT fl;
6021 U64 fix;
6022
6023 RRE(inst, regs, r1, r2);
6024 HFPODD_CHECK(r1, regs);
6025 i1 = FPR2I(r1);
6026 fix = regs->GR_G(r2);
6027
6028 /* Test for negative value */
6029 if (fix & 0x8000000000000000ULL) {
6030 fix = ~fix + 1; /* fix = abs(fix); */
6031 fl.sign = NEG;
6032 } else
6033 fl.sign = POS;
6034
6035 if (fix) {
6036 fl.ms_fract = fix >> 16; /* Fraction high (12 digits) */
6037 fl.ls_fract = fix << 48; /* Fraction low (16 digits) */
6038 fl.expo = 80;
6039
6040 /* Normalize result */
6041 normal_ef(&fl);
6042
6043 /* To register */
6044 store_ef(&fl, regs->fpr + i1);
6045 } else {
6046 /* true zero */
6047 regs->fpr[i1] = 0;
6048 regs->fpr[i1+1] = 0;
6049 regs->fpr[i1+FPREX] = 0;
6050 regs->fpr[i1+FPREX+1] = 0;
6051 }
6052
6053 } /* end DEF_INST(convert_fix64_to_float_ext_reg) */
6054
6055
6056 /*-------------------------------------------------------------------*/
6057 /* B3B8 CFER - Convert from Float. Short to Fixed Register [RRF] */
6058 /*-------------------------------------------------------------------*/
DEF_INST(convert_float_short_to_fixed_reg)6059 DEF_INST(convert_float_short_to_fixed_reg)
6060 {
6061 int r1, r2; /* Values of R fields */
6062 int i2; /* Index of R2 in fpr array */
6063 int m3; /* Value of mask field */
6064 SHORT_FLOAT fl;
6065 BYTE shift;
6066 U32 lsfract;
6067
6068 RRF_M(inst, regs, r1, r2, m3);
6069 HFPM_CHECK(m3, regs);
6070 HFPREG_CHECK(r2, regs);
6071 i2 = FPR2I(r2);
6072
6073 /* Get register content */
6074 get_sf(&fl, regs->fpr + i2);
6075
6076 if (fl.short_fract) {
6077 /* not zero */
6078 normal_sf(&fl);
6079
6080 if (fl.expo > 72) {
6081 /* exeeds range by exponent */
6082 regs->GR_L(r1) = fl.sign ? 0x80000000UL : 0x7FFFFFFFUL;
6083 regs->psw.cc = 3;
6084 return;
6085 }
6086 if (fl.expo > 70) {
6087 /* to be left shifted */
6088 fl.short_fract <<= ((fl.expo - 70) * 4);
6089 if (fl.sign) {
6090 /* negative */
6091 if (fl.short_fract > 0x80000000UL) {
6092 /* exeeds range by value */
6093 regs->GR_L(r1) = 0x80000000UL;
6094 regs->psw.cc = 3;
6095 return;
6096 }
6097 } else {
6098 /* positive */
6099 if (fl.short_fract > 0x7FFFFFFFUL) {
6100 /* exeeds range by value */
6101 regs->GR_L(r1) = 0x7FFFFFFFUL;
6102 regs->psw.cc = 3;
6103 return;
6104 }
6105 }
6106 } else if ((fl.expo > 64)
6107 && (fl.expo < 70)) {
6108 /* to be right shifted and to be rounded */
6109 shift = ((70 - fl.expo) * 4);
6110 lsfract = fl.short_fract << (32 - shift);
6111 fl.short_fract >>= shift;
6112
6113 if (m3 == 1) {
6114 /* biased round to nearest */
6115 if (lsfract & 0x80000000UL) {
6116 fl.short_fract++;
6117 }
6118 } else if (m3 == 4) {
6119 /* round to nearest */
6120 if ((lsfract > 0x80000000UL)
6121 || ((fl.short_fract & 0x00000001UL)
6122 && (lsfract == 0x80000000UL))) {
6123 fl.short_fract++;
6124 }
6125 } else if (m3 == 6) {
6126 /* round toward + */
6127 if ((fl.sign == POS)
6128 && lsfract) {
6129 fl.short_fract++;
6130 }
6131 } else if (m3 == 7) {
6132 /* round toward - */
6133 if ((fl.sign == NEG)
6134 && lsfract) {
6135 fl.short_fract++;
6136 }
6137 }
6138 } else if (fl.expo == 64) {
6139 /* to be rounded */
6140 lsfract = fl.short_fract << 8;
6141 fl.short_fract = 0;
6142
6143 if (m3 == 1) {
6144 /* biased round to nearest */
6145 if (lsfract & 0x80000000UL) {
6146 fl.short_fract++;
6147 }
6148 } else if (m3 == 4) {
6149 /* round to nearest */
6150 if (lsfract > 0x80000000UL) {
6151 fl.short_fract++;
6152 }
6153 } else if (m3 == 6) {
6154 /* round toward + */
6155 if ((fl.sign == POS)
6156 && lsfract) {
6157 fl.short_fract++;
6158 }
6159 } else if (m3 == 7) {
6160 /* round toward - */
6161 if ((fl.sign == NEG)
6162 && lsfract) {
6163 fl.short_fract++;
6164 }
6165 }
6166 } else if (fl.expo < 64) {
6167 fl.short_fract = 0;
6168 if (((m3 == 6)
6169 && (fl.sign == POS))
6170 || ((m3 == 7)
6171 && (fl.sign == NEG))) {
6172 fl.short_fract++;
6173 }
6174 }
6175 if (fl.sign) {
6176 /* negative */
6177 regs->GR_L(r1) = -((S32) fl.short_fract);
6178 regs->psw.cc = 1;
6179 } else {
6180 /* positive */
6181 regs->GR_L(r1) = fl.short_fract;
6182 regs->psw.cc = 2;
6183 }
6184 } else {
6185 /* zero */
6186 regs->GR_L(r1) = 0;
6187 regs->psw.cc = 0;
6188 }
6189
6190 } /* end DEF_INST(convert_float_short_to_fixed_reg) */
6191
6192
6193 /*-------------------------------------------------------------------*/
6194 /* B3B9 CFDR - Convert from Float. Long to Fixed Register [RRF] */
6195 /*-------------------------------------------------------------------*/
DEF_INST(convert_float_long_to_fixed_reg)6196 DEF_INST(convert_float_long_to_fixed_reg)
6197 {
6198 int r1, r2; /* Values of R fields */
6199 int i2; /* Index of R2 in fpr array */
6200 int m3; /* Value of mask field */
6201 LONG_FLOAT fl;
6202 BYTE shift;
6203 U64 lsfract;
6204
6205 RRF_M(inst, regs, r1, r2, m3);
6206 HFPM_CHECK(m3, regs);
6207 HFPREG_CHECK(r2, regs);
6208 i2 = FPR2I(r2);
6209
6210 /* Get register content */
6211 get_lf(&fl, regs->fpr + i2);
6212
6213 if (fl.long_fract) {
6214 /* not zero */
6215 normal_lf(&fl);
6216
6217 if (fl.expo > 72) {
6218 /* exeeds range by exponent */
6219 regs->GR_L(r1) = fl.sign ? 0x80000000UL : 0x7FFFFFFFUL;
6220 regs->psw.cc = 3;
6221 return;
6222 }
6223 if (fl.expo > 64) {
6224 /* to be right shifted and to be rounded */
6225 shift = ((78 - fl.expo) * 4);
6226 lsfract = fl.long_fract << (64 - shift);
6227 fl.long_fract >>= shift;
6228
6229 if (m3 == 1) {
6230 /* biased round to nearest */
6231 if (lsfract & 0x8000000000000000ULL) {
6232 fl.long_fract++;
6233 }
6234 } else if (m3 == 4) {
6235 /* round to nearest */
6236 if ((lsfract > 0x8000000000000000ULL)
6237 || ((fl.long_fract & 0x0000000000000001ULL)
6238 && (lsfract == 0x8000000000000000ULL))) {
6239 fl.long_fract++;
6240 }
6241 } else if (m3 == 6) {
6242 /* round toward + */
6243 if ((fl.sign == POS)
6244 && lsfract) {
6245 fl.long_fract++;
6246 }
6247 } else if (m3 == 7) {
6248 /* round toward - */
6249 if ((fl.sign == NEG)
6250 && lsfract) {
6251 fl.long_fract++;
6252 }
6253 }
6254 if (fl.expo == 72) {
6255 if (fl.sign) {
6256 /* negative */
6257 if (fl.long_fract > 0x80000000UL) {
6258 /* exeeds range by value */
6259 regs->GR_L(r1) = 0x80000000UL;
6260 regs->psw.cc = 3;
6261 return;
6262 }
6263 } else {
6264 /* positive */
6265 if (fl.long_fract > 0x7FFFFFFFUL) {
6266 /* exeeds range by value */
6267 regs->GR_L(r1) = 0x7FFFFFFFUL;
6268 regs->psw.cc = 3;
6269 return;
6270 }
6271 }
6272 }
6273 } else if (fl.expo == 64) {
6274 /* to be rounded */
6275 lsfract = fl.long_fract << 8;
6276 fl.long_fract = 0;
6277
6278 if (m3 == 1) {
6279 /* biased round to nearest */
6280 if (lsfract & 0x8000000000000000ULL) {
6281 fl.long_fract++;
6282 }
6283 } else if (m3 == 4) {
6284 /* round to nearest */
6285 if (lsfract > 0x8000000000000000ULL) {
6286 fl.long_fract++;
6287 }
6288 } else if (m3 == 6) {
6289 /* round toward + */
6290 if ((fl.sign == POS)
6291 && lsfract) {
6292 fl.long_fract++;
6293 }
6294 } else if (m3 == 7) {
6295 /* round toward - */
6296 if ((fl.sign == NEG)
6297 && lsfract) {
6298 fl.long_fract++;
6299 }
6300 }
6301 } else {
6302 /* fl.expo < 64 */
6303 fl.long_fract = 0;
6304 if (((m3 == 6)
6305 && (fl.sign == POS))
6306 || ((m3 == 7)
6307 && (fl.sign == NEG))) {
6308 fl.long_fract++;
6309 }
6310 }
6311 if (fl.sign) {
6312 /* negative */
6313 regs->GR_L(r1) = -((S32) fl.long_fract);
6314 regs->psw.cc = 1;
6315 } else {
6316 /* positive */
6317 regs->GR_L(r1) = fl.long_fract;
6318 regs->psw.cc = 2;
6319 }
6320 } else {
6321 /* zero */
6322 regs->GR_L(r1) = 0;
6323 regs->psw.cc = 0;
6324 }
6325
6326 } /* end DEF_INST(convert_float_long_to_fixed_reg) */
6327
6328
6329 /*-------------------------------------------------------------------*/
6330 /* B3BA CFXR - Convert from Float. Extended to Fixed Register [RRF] */
6331 /*-------------------------------------------------------------------*/
DEF_INST(convert_float_ext_to_fixed_reg)6332 DEF_INST(convert_float_ext_to_fixed_reg)
6333 {
6334 int r1, r2; /* Values of R fields */
6335 int i2; /* Index of R2 in fpr array */
6336 int m3; /* Value of mask field */
6337 EXTENDED_FLOAT fl;
6338 BYTE shift;
6339 U64 lsfract;
6340
6341 RRF_M(inst, regs, r1, r2, m3);
6342 HFPM_CHECK(m3, regs);
6343 HFPODD_CHECK(r2, regs);
6344 i2 = FPR2I(r2);
6345
6346 /* Get register content */
6347 get_ef(&fl, regs->fpr + i2);
6348
6349 if (fl.ms_fract || fl.ls_fract) {
6350 /* not zero */
6351 normal_ef(&fl);
6352
6353 if (fl.expo > 72) {
6354 /* exeeds range by exponent */
6355 regs->GR_L(r1) = fl.sign ? 0x80000000UL : 0x7FFFFFFFUL;
6356 regs->psw.cc = 3;
6357 return;
6358 }
6359 if (fl.expo > 64) {
6360 /* to be right shifted and to be rounded */
6361 shift = ((92 - fl.expo - 16) * 4);
6362 lsfract = fl.ms_fract << (64 - shift);
6363 fl.ms_fract >>= shift;
6364
6365 if (m3 == 1) {
6366 /* biased round to nearest */
6367 if (lsfract & 0x8000000000000000ULL) {
6368 fl.ms_fract++;
6369 }
6370 } else if (m3 == 4) {
6371 /* round to nearest */
6372 if (((lsfract & 0x8000000000000000ULL)
6373 && ((lsfract & 0x7FFFFFFFFFFFFFFFULL)
6374 || fl.ls_fract))
6375 || ( (fl.ms_fract & 0x0000000000000001ULL)
6376 && (lsfract == 0x8000000000000000ULL)
6377 && (fl.ls_fract == 0))) {
6378 fl.ms_fract++;
6379 }
6380 } else if (m3 == 6) {
6381 /* round toward + */
6382 if ((fl.sign == POS)
6383 && (lsfract
6384 || fl.ls_fract)) {
6385 fl.ms_fract++;
6386 }
6387 } else if (m3 == 7) {
6388 /* round toward - */
6389 if ((fl.sign == NEG)
6390 && (lsfract
6391 || fl.ls_fract)) {
6392 fl.ms_fract++;
6393 }
6394 }
6395 } else if (fl.expo == 64) {
6396 /* to be rounded */
6397 lsfract = fl.ms_fract << 16;
6398 fl.ms_fract = 0;
6399
6400 if (m3 == 1) {
6401 /* biased round to nearest */
6402 if (lsfract & 0x8000000000000000ULL) {
6403 fl.ms_fract++;
6404 }
6405 } else if (m3 == 4) {
6406 /* round to nearest */
6407 if ((lsfract & 0x8000000000000000ULL)
6408 && ((lsfract & 0x7FFFFFFFFFFFFFFFULL)
6409 || fl.ls_fract)) {
6410 fl.ms_fract++;
6411 }
6412 } else if (m3 == 6) {
6413 /* round toward + */
6414 if ((fl.sign == POS)
6415 && (lsfract
6416 || fl.ls_fract)) {
6417 fl.ms_fract++;
6418 }
6419 } else if (m3 == 7) {
6420 /* round toward - */
6421 if ((fl.sign == NEG)
6422 && (lsfract
6423 || fl.ls_fract)) {
6424 fl.ms_fract++;
6425 }
6426 }
6427 } else {
6428 /* fl.expo < 64 */
6429 fl.ms_fract = 0;
6430 if (((m3 == 6)
6431 && (fl.sign == POS))
6432 || ((m3 == 7)
6433 && (fl.sign == NEG))) {
6434 fl.ms_fract++;
6435 }
6436 }
6437 if (fl.sign) {
6438 /* negative */
6439 if (fl.ms_fract > 0x80000000UL) {
6440 /* exeeds range by value */
6441 regs->GR_L(r1) = 0x80000000UL;
6442 regs->psw.cc = 3;
6443 return;
6444 }
6445 regs->GR_L(r1) = -((S32) fl.ms_fract);
6446 regs->psw.cc = 1;
6447 } else {
6448 /* positive */
6449 if (fl.ms_fract > 0x7FFFFFFFUL) {
6450 /* exeeds range by value */
6451 regs->GR_L(r1) = 0x7FFFFFFFUL;
6452 regs->psw.cc = 3;
6453 return;
6454 }
6455 regs->GR_L(r1) = fl.ms_fract;
6456 regs->psw.cc = 2;
6457 }
6458 } else {
6459 /* zero */
6460 regs->GR_L(r1) = 0;
6461 regs->psw.cc = 0;
6462 }
6463
6464 } /* end DEF_INST(convert_float_ext_to_fixed_reg) */
6465
6466
6467 /*-------------------------------------------------------------------*/
6468 /* B3C8 CGER - Convert from Float. Short to Fix64 Register [RRF] */
6469 /*-------------------------------------------------------------------*/
DEF_INST(convert_float_short_to_fix64_reg)6470 DEF_INST(convert_float_short_to_fix64_reg)
6471 {
6472 int r1, r2; /* Values of R fields */
6473 int i2; /* Index of R2 in fpr array */
6474 int m3; /* Value of mask field */
6475 SHORT_FLOAT fl;
6476 BYTE shift;
6477 U64 intpart;
6478 U32 lsfract;
6479
6480 RRF_M(inst, regs, r1, r2, m3);
6481 HFPM_CHECK(m3, regs);
6482 HFPREG_CHECK(r2, regs);
6483 i2 = FPR2I(r2);
6484
6485 /* Get register content */
6486 get_sf(&fl, regs->fpr + i2);
6487
6488 if (fl.short_fract) {
6489 /* not zero */
6490 normal_sf(&fl);
6491
6492 if (fl.expo > 80) {
6493 /* exeeds range by exponent */
6494 regs->GR_G(r1) = fl.sign ? 0x8000000000000000ULL : 0x7FFFFFFFFFFFFFFFULL;
6495 regs->psw.cc = 3;
6496 return;
6497 }
6498 if (fl.expo > 70) {
6499 /* to be left shifted */
6500 intpart = (U64)fl.short_fract << ((fl.expo - 70) * 4);
6501 if (fl.sign) {
6502 /* negative */
6503 if (intpart > 0x8000000000000000ULL) {
6504 /* exeeds range by value */
6505 regs->GR_G(r1) = 0x8000000000000000ULL;
6506 regs->psw.cc = 3;
6507 return;
6508 }
6509 } else {
6510 /* positive */
6511 if (intpart > 0x7FFFFFFFFFFFFFFFULL) {
6512 /* exeeds range by value */
6513 regs->GR_G(r1) = 0x7FFFFFFFFFFFFFFFULL;
6514 regs->psw.cc = 3;
6515 return;
6516 }
6517 }
6518 } else if ((fl.expo > 64)
6519 && (fl.expo < 70)) {
6520 /* to be right shifted and to be rounded */
6521 shift = ((70 - fl.expo) * 4);
6522 lsfract = fl.short_fract << (32 - shift);
6523 intpart = fl.short_fract >> shift;
6524
6525 if (m3 == 1) {
6526 /* biased round to nearest */
6527 if (lsfract & 0x80000000UL) {
6528 intpart++;
6529 }
6530 } else if (m3 == 4) {
6531 /* round to nearest */
6532 if ((lsfract > 0x80000000UL)
6533 || ((intpart & 0x0000000000000001ULL)
6534 && (lsfract == 0x80000000UL))) {
6535 intpart++;
6536 }
6537 } else if (m3 == 6) {
6538 /* round toward + */
6539 if ((fl.sign == POS)
6540 && lsfract) {
6541 intpart++;
6542 }
6543 } else if (m3 == 7) {
6544 /* round toward - */
6545 if ((fl.sign == NEG)
6546 && lsfract) {
6547 intpart++;
6548 }
6549 }
6550 } else if (fl.expo == 64) {
6551 /* to be rounded */
6552 lsfract = fl.short_fract << 8;
6553 intpart = 0;
6554
6555 if (m3 == 1) {
6556 /* biased round to nearest */
6557 if (lsfract & 0x80000000UL) {
6558 intpart++;
6559 }
6560 } else if (m3 == 4) {
6561 /* round to nearest */
6562 if (lsfract > 0x80000000UL) {
6563 intpart++;
6564 }
6565 } else if (m3 == 6) {
6566 /* round toward + */
6567 if ((fl.sign == POS)
6568 && lsfract) {
6569 intpart++;
6570 }
6571 } else if (m3 == 7) {
6572 /* round toward - */
6573 if ((fl.sign == NEG)
6574 && lsfract) {
6575 intpart++;
6576 }
6577 }
6578 } else if (fl.expo < 64) {
6579 intpart = 0;
6580 if (((m3 == 6)
6581 && (fl.sign == POS))
6582 || ((m3 == 7)
6583 && (fl.sign == NEG))) {
6584 intpart++;
6585 }
6586 } else /* fl.expo == 70 */ {
6587 /* no shift or round required */
6588 intpart = (U64)fl.short_fract;
6589 }
6590 if (fl.sign) {
6591 /* negative */
6592 if (intpart == 0x8000000000000000ULL)
6593 regs->GR_G(r1) = 0x8000000000000000ULL;
6594 else
6595 regs->GR_G(r1) = -((S64)intpart);
6596 regs->psw.cc = 1;
6597 } else {
6598 /* positive */
6599 regs->GR_G(r1) = intpart;
6600 regs->psw.cc = 2;
6601 }
6602 } else {
6603 /* zero */
6604 regs->GR_G(r1) = 0;
6605 regs->psw.cc = 0;
6606 }
6607
6608 } /* end DEF_INST(convert_float_short_to_fix64_reg) */
6609
6610
6611 /*-------------------------------------------------------------------*/
6612 /* B3C9 CGDR - Convert from Float. Long to Fix64 Register [RRF] */
6613 /*-------------------------------------------------------------------*/
DEF_INST(convert_float_long_to_fix64_reg)6614 DEF_INST(convert_float_long_to_fix64_reg)
6615 {
6616 int r1, r2; /* Values of R fields */
6617 int i2; /* Index of R2 in fpr array */
6618 int m3; /* Value of mask field */
6619 LONG_FLOAT fl;
6620 BYTE shift;
6621 U64 lsfract;
6622
6623 RRF_M(inst, regs, r1, r2, m3);
6624 HFPM_CHECK(m3, regs);
6625 HFPREG_CHECK(r2, regs);
6626 i2 = FPR2I(r2);
6627
6628 /* Get register content */
6629 get_lf(&fl, regs->fpr + i2);
6630
6631 if (fl.long_fract) {
6632 /* not zero */
6633 normal_lf(&fl);
6634
6635 if (fl.expo > 80) {
6636 /* exeeds range by exponent */
6637 regs->GR_G(r1) = fl.sign ? 0x8000000000000000ULL : 0x7FFFFFFFFFFFFFFFULL;
6638 regs->psw.cc = 3;
6639 return;
6640 }
6641 if (fl.expo > 78) {
6642 /* to be left shifted */
6643 fl.long_fract <<= ((fl.expo - 78) * 4);
6644 if (fl.sign) {
6645 /* negative */
6646 if (fl.long_fract > 0x8000000000000000ULL) {
6647 /* exeeds range by value */
6648 regs->GR_G(r1) = 0x8000000000000000ULL;
6649 regs->psw.cc = 3;
6650 return;
6651 }
6652 } else {
6653 /* positive */
6654 if (fl.long_fract > 0x7FFFFFFFFFFFFFFFULL) {
6655 /* exeeds range by value */
6656 regs->GR_G(r1) = 0x7FFFFFFFFFFFFFFFULL;
6657 regs->psw.cc = 3;
6658 return;
6659 }
6660 }
6661 } else if ((fl.expo > 64)
6662 && (fl.expo < 78)) {
6663 /* to be right shifted and to be rounded */
6664 shift = ((78 - fl.expo) * 4);
6665 lsfract = fl.long_fract << (64 - shift);
6666 fl.long_fract >>= shift;
6667
6668 if (m3 == 1) {
6669 /* biased round to nearest */
6670 if (lsfract & 0x8000000000000000ULL) {
6671 fl.long_fract++;
6672 }
6673 } else if (m3 == 4) {
6674 /* round to nearest */
6675 if ((lsfract > 0x8000000000000000ULL)
6676 || ((fl.long_fract & 0x0000000000000001ULL)
6677 && (lsfract == 0x8000000000000000ULL))) {
6678 fl.long_fract++;
6679 }
6680 } else if (m3 == 6) {
6681 /* round toward + */
6682 if ((fl.sign == POS)
6683 && lsfract) {
6684 fl.long_fract++;
6685 }
6686 } else if (m3 == 7) {
6687 /* round toward - */
6688 if ((fl.sign == NEG)
6689 && lsfract) {
6690 fl.long_fract++;
6691 }
6692 }
6693 } else if (fl.expo == 64) {
6694 /* to be rounded */
6695 lsfract = fl.long_fract << 8;
6696 fl.long_fract = 0;
6697
6698 if (m3 == 1) {
6699 /* biased round to nearest */
6700 if (lsfract & 0x8000000000000000ULL) {
6701 fl.long_fract++;
6702 }
6703 } else if (m3 == 4) {
6704 /* round to nearest */
6705 if (lsfract > 0x8000000000000000ULL) {
6706 fl.long_fract++;
6707 }
6708 } else if (m3 == 6) {
6709 /* round toward + */
6710 if ((fl.sign == POS)
6711 && lsfract) {
6712 fl.long_fract++;
6713 }
6714 } else if (m3 == 7) {
6715 /* round toward - */
6716 if ((fl.sign == NEG)
6717 && lsfract) {
6718 fl.long_fract++;
6719 }
6720 }
6721 } else if (fl.expo < 64) {
6722 fl.long_fract = 0;
6723 if (((m3 == 6)
6724 && (fl.sign == POS))
6725 || ((m3 == 7)
6726 && (fl.sign == NEG))) {
6727 fl.long_fract++;
6728 }
6729 }
6730 if (fl.sign) {
6731 /* negative */
6732 if (fl.long_fract == 0x8000000000000000ULL)
6733 regs->GR_G(r1) = 0x8000000000000000ULL;
6734 else
6735 regs->GR_G(r1) = -((S64)fl.long_fract);
6736 regs->psw.cc = 1;
6737 } else {
6738 /* positive */
6739 regs->GR_G(r1) = fl.long_fract;
6740 regs->psw.cc = 2;
6741 }
6742 } else {
6743 /* zero */
6744 regs->GR_G(r1) = 0;
6745 regs->psw.cc = 0;
6746 }
6747
6748 } /* end DEF_INST(convert_float_long_to_fix64_reg) */
6749
6750
6751 /*-------------------------------------------------------------------*/
6752 /* B3CA CGXR - Convert from Float. Extended to Fix64 Register [RRF] */
6753 /*-------------------------------------------------------------------*/
DEF_INST(convert_float_ext_to_fix64_reg)6754 DEF_INST(convert_float_ext_to_fix64_reg)
6755 {
6756 int r1, r2; /* Values of R fields */
6757 int i2; /* Index of R2 in fpr array */
6758 int m3; /* Value of mask field */
6759 EXTENDED_FLOAT fl;
6760 BYTE shift;
6761 U64 intpart;
6762 U64 lsfract;
6763
6764 RRF_M(inst, regs, r1, r2, m3);
6765 HFPM_CHECK(m3, regs);
6766 HFPODD_CHECK(r2, regs);
6767 i2 = FPR2I(r2);
6768
6769 /* Get register content */
6770 get_ef(&fl, regs->fpr + i2);
6771
6772 if (fl.ms_fract || fl.ls_fract) {
6773 /* not zero */
6774 normal_ef(&fl);
6775
6776 if (fl.expo > 80) {
6777 /* exeeds range by exponent */
6778 regs->GR_G(r1) = fl.sign ? 0x8000000000000000ULL : 0x7FFFFFFFFFFFFFFFULL;
6779 regs->psw.cc = 3;
6780 return;
6781 }
6782 if (fl.expo > 64) {
6783 /* to be right shifted and to be rounded */
6784 shift = ((92 - fl.expo) * 4);
6785 if (shift > 64) {
6786 intpart = fl.ms_fract >> (shift - 64);
6787 lsfract = (fl.ls_fract >> (128 - shift))
6788 | (fl.ms_fract << (128 - shift));
6789 } else if (shift < 64) {
6790 intpart = (fl.ls_fract >> shift)
6791 | (fl.ms_fract << (64 - shift));
6792 lsfract = fl.ls_fract << (64 - shift);
6793 } else /* shift == 64 */ {
6794 intpart = fl.ms_fract;
6795 lsfract = fl.ls_fract;
6796 }
6797
6798 if (m3 == 1) {
6799 /* biased round to nearest */
6800 if (lsfract & 0x8000000000000000ULL) {
6801 intpart++;
6802 }
6803 } else if (m3 == 4) {
6804 /* round to nearest */
6805 if ((lsfract > 0x8000000000000000ULL)
6806 || ((intpart & 0x0000000000000001ULL)
6807 && (lsfract == 0x8000000000000000ULL))) {
6808 intpart++;
6809 }
6810 } else if (m3 == 6) {
6811 /* round toward + */
6812 if ((fl.sign == POS)
6813 && lsfract) {
6814 intpart++;
6815 }
6816 } else if (m3 == 7) {
6817 /* round toward - */
6818 if ((fl.sign == NEG)
6819 && lsfract) {
6820 intpart++;
6821 }
6822 }
6823 } else if (fl.expo == 64) {
6824 /* to be rounded */
6825 lsfract = (fl.ms_fract << 16) | (fl.ls_fract >> 48);
6826 intpart = 0;
6827
6828 if (m3 == 1) {
6829 /* biased round to nearest */
6830 if (lsfract & 0x8000000000000000ULL) {
6831 intpart++;
6832 }
6833 } else if (m3 == 4) {
6834 /* round to nearest */
6835 if (lsfract > 0x8000000000000000ULL) {
6836 intpart++;
6837 }
6838 } else if (m3 == 6) {
6839 /* round toward + */
6840 if ((fl.sign == POS)
6841 && lsfract) {
6842 intpart++;
6843 }
6844 } else if (m3 == 7) {
6845 /* round toward - */
6846 if ((fl.sign == NEG)
6847 && lsfract) {
6848 intpart++;
6849 }
6850 }
6851 } else {
6852 /* fl.expo < 64 */
6853 intpart = 0;
6854 if (((m3 == 6)
6855 && (fl.sign == POS))
6856 || ((m3 == 7)
6857 && (fl.sign == NEG))) {
6858 intpart++;
6859 }
6860 }
6861 if (fl.sign) {
6862 /* negative */
6863 if (intpart > 0x8000000000000000ULL) {
6864 /* exeeds range by value */
6865 regs->GR_G(r1) = 0x8000000000000000ULL;
6866 regs->psw.cc = 3;
6867 return;
6868 }
6869 if (intpart == 0x8000000000000000ULL)
6870 regs->GR_G(r1) = 0x8000000000000000ULL;
6871 else
6872 regs->GR_G(r1) = -((S64)intpart);
6873 regs->psw.cc = 1;
6874 } else {
6875 /* positive */
6876 if (intpart > 0x7FFFFFFFFFFFFFFFULL) {
6877 /* exeeds range by value */
6878 regs->GR_G(r1) = 0x7FFFFFFFFFFFFFFFULL;
6879 regs->psw.cc = 3;
6880 return;
6881 }
6882 regs->GR_G(r1) = intpart;
6883 regs->psw.cc = 2;
6884 }
6885 } else {
6886 /* zero */
6887 regs->GR_G(r1) = 0;
6888 regs->psw.cc = 0;
6889 }
6890
6891 } /* end DEF_INST(convert_float_ext_to_fix64_reg) */
6892
6893
6894 /*-------------------------------------------------------------------*/
6895 /* ED24 LDE - Load Lengthened Floating Point Short to Long [RXE] */
6896 /*-------------------------------------------------------------------*/
DEF_INST(load_lengthened_float_short_to_long)6897 DEF_INST(load_lengthened_float_short_to_long)
6898 {
6899 int r1; /* Value of R field */
6900 int i1; /* Index of R1 in fpr array */
6901 int b2; /* Base of effective addr */
6902 VADR effective_addr2; /* Effective address */
6903
6904 RXE(inst, regs, r1, b2, effective_addr2);
6905 HFPREG_CHECK(r1, regs);
6906 i1 = FPR2I(r1);
6907
6908 /* Update first 32 bits of register from operand address */
6909 regs->fpr[i1] = ARCH_DEP(vfetch4) (effective_addr2, b2, regs);
6910
6911 /* Zero register content */
6912 regs->fpr[i1+1] = 0;
6913
6914 } /* end DEF_INST(load_lengthened_float_short_to_long) */
6915
6916
6917 /*-------------------------------------------------------------------*/
6918 /* ED25 LXD - Load Lengthened Floating Point Long to Extended [RXE] */
6919 /*-------------------------------------------------------------------*/
DEF_INST(load_lengthened_float_long_to_ext)6920 DEF_INST(load_lengthened_float_long_to_ext)
6921 {
6922 int r1; /* Value of R field */
6923 int i1; /* Index of R1 in fpr array */
6924 int b2; /* Base of effective addr */
6925 VADR effective_addr2; /* Effective address */
6926 U32 wk;
6927 U64 wkd;
6928
6929 RXE(inst, regs, r1, b2, effective_addr2);
6930 HFPODD_CHECK(r1, regs);
6931 i1 = FPR2I(r1);
6932
6933 /* Get the 2nd operand */
6934 wkd = ARCH_DEP(vfetch8) (effective_addr2, b2, regs);
6935 wk = wkd >> 32;
6936
6937 if (wkd & 0x00FFFFFFFFFFFFFFULL) {
6938 /* Back to register */
6939 regs->fpr[i1] = wk;
6940 regs->fpr[i1+1] = wkd;
6941
6942 /* Low order register */
6943 regs->fpr[i1+FPREX] = (wk & 0x80000000)
6944 | ((wk - (14 << 24)) & 0x7F000000);
6945 } else {
6946 /* true zero with sign */
6947 regs->fpr[i1] = (wk & 0x80000000);
6948 regs->fpr[i1+FPREX] = regs->fpr[i1];
6949 regs->fpr[i1+1] = 0;
6950 }
6951 regs->fpr[i1+FPREX+1] = 0;
6952
6953 } /* end DEF_INST(load_lengthened_float_long_to_ext) */
6954
6955
6956 /*-------------------------------------------------------------------*/
6957 /* ED26 LXE - Load Lengthened Float. Short to Extended [RXE] */
6958 /*-------------------------------------------------------------------*/
DEF_INST(load_lengthened_float_short_to_ext)6959 DEF_INST(load_lengthened_float_short_to_ext)
6960 {
6961 int r1; /* Value of R field */
6962 int i1; /* Index of R1 in fpr array */
6963 int b2; /* Base of effective addr */
6964 VADR effective_addr2; /* Effective address */
6965 U32 wk;
6966
6967 RXE(inst, regs, r1, b2, effective_addr2);
6968 HFPODD_CHECK(r1, regs);
6969 i1 = FPR2I(r1);
6970
6971 /* Get the 2nd operand */
6972 wk = ARCH_DEP(vfetch4) (effective_addr2, b2, regs);
6973
6974 if (wk & 0x00FFFFFF) {
6975 /* Back to register */
6976 regs->fpr[i1] = wk;
6977
6978 /* Zero register content */
6979 regs->fpr[i1+1] = 0;
6980
6981 /* Low order register */
6982 regs->fpr[i1+FPREX] = (wk & 0x80000000)
6983 | ((wk - (14 << 24)) & 0x7F000000);
6984 regs->fpr[i1+FPREX+1] = 0;
6985 } else {
6986 /* true zero with sign */
6987 regs->fpr[i1] = (wk & 0x80000000);
6988 regs->fpr[i1+FPREX] = regs->fpr[i1];
6989 regs->fpr[i1+1] = 0;
6990 regs->fpr[i1+FPREX+1] = 0;
6991 }
6992
6993 } /* end DEF_INST(load_lengthened_float_short_to_ext) */
6994
6995
6996 /*-------------------------------------------------------------------*/
6997 /* ED34 SQE - Square Root Floating Point Short [RXE] */
6998 /*-------------------------------------------------------------------*/
DEF_INST(squareroot_float_short)6999 DEF_INST(squareroot_float_short)
7000 {
7001 int r1; /* Value of R field */
7002 int i1; /* Index of R1 in fpr array */
7003 int b2; /* Base of effective addr */
7004 VADR effective_addr2; /* Effective address */
7005 SHORT_FLOAT sq_fl;
7006 SHORT_FLOAT fl;
7007
7008 RXE(inst, regs, r1, b2, effective_addr2);
7009 HFPREG_CHECK(r1, regs);
7010 i1 = FPR2I(r1);
7011
7012 /* Get the 2nd operand */
7013 vfetch_sf(&fl, effective_addr2, b2, regs );
7014
7015 /* short square root subroutine */
7016 sq_sf(&sq_fl, &fl, regs);
7017
7018 /* Back to register */
7019 store_sf(&sq_fl, regs->fpr + i1);
7020
7021 } /* end DEF_INST(squareroot_float_short) */
7022
7023
7024 /*-------------------------------------------------------------------*/
7025 /* ED35 SQD - Square Root Floating Point Long [RXE] */
7026 /*-------------------------------------------------------------------*/
DEF_INST(squareroot_float_long)7027 DEF_INST(squareroot_float_long)
7028 {
7029 int r1; /* Value of R field */
7030 int i1; /* Index of R1 in fpr array */
7031 int b2; /* Base of effective addr */
7032 VADR effective_addr2; /* Effective address */
7033 LONG_FLOAT sq_fl;
7034 LONG_FLOAT fl;
7035
7036 RXE(inst, regs, r1, b2, effective_addr2);
7037 HFPREG_CHECK(r1, regs);
7038 i1 = FPR2I(r1);
7039
7040 /* Get the 2nd operand */
7041 vfetch_lf(&fl, effective_addr2, b2, regs );
7042
7043 /* long square root subroutine */
7044 sq_lf(&sq_fl, &fl, regs);
7045
7046 /* Back to register */
7047 store_lf(&sq_fl, regs->fpr + i1);
7048
7049 } /* end DEF_INST(squareroot_float_long) */
7050
7051
7052 /*-------------------------------------------------------------------*/
7053 /* ED37 MEE - Multiply Floating Point Short [RXE] */
7054 /*-------------------------------------------------------------------*/
DEF_INST(multiply_float_short)7055 DEF_INST(multiply_float_short)
7056 {
7057 int r1; /* Value of R field */
7058 int i1; /* Index of R1 in fpr array */
7059 int b2; /* Base of effective addr */
7060 VADR effective_addr2; /* Effective address */
7061 SHORT_FLOAT fl;
7062 SHORT_FLOAT mul_fl;
7063 int pgm_check;
7064
7065 RXE(inst, regs, r1, b2, effective_addr2);
7066 HFPREG_CHECK(r1, regs);
7067 i1 = FPR2I(r1);
7068
7069 /* Get the operands */
7070 get_sf(&fl, regs->fpr + i1);
7071 vfetch_sf(&mul_fl, effective_addr2, b2, regs );
7072
7073 /* multiply short to long */
7074 pgm_check = mul_sf(&fl, &mul_fl, OVUNF, regs);
7075
7076 /* Back to register */
7077 store_sf(&fl, regs->fpr + i1);
7078
7079 /* Program check ? */
7080 if (pgm_check) {
7081 ARCH_DEP(program_interrupt) (regs, pgm_check);
7082 }
7083
7084 } /* end DEF_INST(multiply_float_short) */
7085 #endif /* FEATURE_HFP_EXTENSIONS */
7086
7087
7088 #if defined(FEATURE_FPS_EXTENSIONS)
7089 /*-------------------------------------------------------------------*/
7090 /* B365 LXR - Load Floating Point Extended Register [RRE] */
7091 /*-------------------------------------------------------------------*/
DEF_INST(load_float_ext_reg)7092 DEF_INST(load_float_ext_reg)
7093 {
7094 int r1, r2; /* Values of R fields */
7095 int i1, i2; /* Indexes into fpr array */
7096
7097 RRE(inst, regs, r1, r2);
7098
7099 HFPODD2_CHECK(r1, r2, regs);
7100 i1 = FPR2I(r1);
7101 i2 = FPR2I(r2);
7102
7103 /* Copy register R2 contents to register R1 */
7104 regs->fpr[i1] = regs->fpr[i2];
7105 regs->fpr[i1+1] = regs->fpr[i2+1];
7106 regs->fpr[i1+FPREX] = regs->fpr[i2+FPREX];
7107 regs->fpr[i1+FPREX+1] = regs->fpr[i2+FPREX+1];
7108
7109 } /* end DEF_INST(load_float_ext_reg) */
7110
7111
7112 /*-------------------------------------------------------------------*/
7113 /* B374 LZER - Load Zero Floating Point Short Register [RRE] */
7114 /*-------------------------------------------------------------------*/
DEF_INST(load_zero_float_short_reg)7115 DEF_INST(load_zero_float_short_reg)
7116 {
7117 int r1, r2; /* Values of R fields */
7118 int i1; /* Index of R1 in fpr array */
7119
7120 RRE(inst, regs, r1, r2);
7121 HFPREG_CHECK(r1, regs);
7122 i1 = FPR2I(r1);
7123
7124 /* Set all bits of register R1 to zeros */
7125 regs->fpr[i1] = 0;
7126
7127 } /* end DEF_INST(load_zero_float_short_reg) */
7128
7129
7130 /*-------------------------------------------------------------------*/
7131 /* B375 LZDR - Load Zero Floating Point Long Register [RRE] */
7132 /*-------------------------------------------------------------------*/
DEF_INST(load_zero_float_long_reg)7133 DEF_INST(load_zero_float_long_reg)
7134 {
7135 int r1, r2; /* Values of R fields */
7136 int i1; /* Index of R1 in fpr array */
7137
7138 RRE(inst, regs, r1, r2);
7139 HFPREG_CHECK(r1, regs);
7140 i1 = FPR2I(r1);
7141
7142 /* Set all bits of register R1 to zeros */
7143 regs->fpr[i1] = 0;
7144 regs->fpr[i1+1] = 0;
7145
7146 } /* end DEF_INST(load_zero_float_long_reg) */
7147
7148
7149 /*-------------------------------------------------------------------*/
7150 /* B376 LZXR - Load Zero Floating Point Extended Register [RRE] */
7151 /*-------------------------------------------------------------------*/
DEF_INST(load_zero_float_ext_reg)7152 DEF_INST(load_zero_float_ext_reg)
7153 {
7154 int r1, r2; /* Values of R fields */
7155 int i1; /* Index of R1 in fpr array */
7156
7157 RRE(inst, regs, r1, r2);
7158
7159 HFPODD_CHECK(r1, regs);
7160 i1 = FPR2I(r1);
7161
7162 /* Set all bits of register R1 to zeros */
7163 regs->fpr[i1] = 0;
7164 regs->fpr[i1+1] = 0;
7165 regs->fpr[i1+FPREX] = 0;
7166 regs->fpr[i1+FPREX+1] = 0;
7167
7168 } /* end DEF_INST(load_zero_float_ext_reg) */
7169 #endif /*defined(FEATURE_FPS_EXTENSIONS)*/
7170
7171
7172 #if defined(FEATURE_HFP_MULTIPLY_ADD_SUBTRACT)
7173 /*-------------------------------------------------------------------*/
7174 /* B32E MAER - Multiply and Add Floating Point Short Register [RRF] */
7175 /*-------------------------------------------------------------------*/
DEF_INST(multiply_add_float_short_reg)7176 DEF_INST(multiply_add_float_short_reg)
7177 {
7178 int r1, r2, r3; /* Values of R fields */
7179 int i1, i2, i3; /* Indexes into fpr array */
7180 SHORT_FLOAT fl1, fl2, fl3;
7181 int pgm_check;
7182
7183 RRF_R(inst, regs, r1, r2, r3);
7184 HFPREG2_CHECK(r1, r2, regs);
7185 HFPREG_CHECK(r3, regs);
7186 i1 = FPR2I(r1);
7187 i2 = FPR2I(r2);
7188 i3 = FPR2I(r3);
7189
7190 /* Get the operands */
7191 get_sf(&fl1, regs->fpr + i1);
7192 get_sf(&fl2, regs->fpr + i2);
7193 get_sf(&fl3, regs->fpr + i3);
7194
7195 /* Multiply third and second operands */
7196 mul_sf(&fl2, &fl3, NOOVUNF, regs);
7197
7198 /* Add the first operand with normalization */
7199 pgm_check = add_sf(&fl1, &fl2, NORMAL, NOSIGEX, regs);
7200
7201 /* Store result back to first operand register */
7202 store_sf(&fl1, regs->fpr + i1);
7203
7204 /* Program check ? */
7205 if (pgm_check) {
7206 ARCH_DEP(program_interrupt) (regs, pgm_check);
7207 }
7208
7209 } /* end DEF_INST(multiply_add_float_short_reg) */
7210
7211
7212 /*-------------------------------------------------------------------*/
7213 /* B32F MSER - Multiply and Subtract Floating Point Short Reg [RRF] */
7214 /*-------------------------------------------------------------------*/
DEF_INST(multiply_subtract_float_short_reg)7215 DEF_INST(multiply_subtract_float_short_reg)
7216 {
7217 int r1, r2, r3; /* Values of R fields */
7218 int i1, i2, i3; /* Indexes into fpr array */
7219 SHORT_FLOAT fl1, fl2, fl3;
7220 int pgm_check;
7221
7222 RRF_R(inst, regs, r1, r2, r3);
7223 HFPREG2_CHECK(r1, r2, regs);
7224 HFPREG_CHECK(r3, regs);
7225 i1 = FPR2I(r1);
7226 i2 = FPR2I(r2);
7227 i3 = FPR2I(r3);
7228
7229 /* Get the operands */
7230 get_sf(&fl1, regs->fpr + i1);
7231 get_sf(&fl2, regs->fpr + i2);
7232 get_sf(&fl3, regs->fpr + i3);
7233
7234 /* Multiply third and second operands */
7235 mul_sf(&fl2, &fl3, NOOVUNF, regs);
7236
7237 /* Invert the sign of the first operand */
7238 fl1.sign = ! (fl1.sign);
7239
7240 /* Subtract the first operand with normalization */
7241 pgm_check = add_sf(&fl1, &fl2, NORMAL, NOSIGEX, regs);
7242
7243 /* Store result back to first operand register */
7244 store_sf(&fl1, regs->fpr + i1);
7245
7246 /* Program check ? */
7247 if (pgm_check) {
7248 ARCH_DEP(program_interrupt) (regs, pgm_check);
7249 }
7250
7251 } /* end DEF_INST(multiply_subtract_float_short_reg) */
7252
7253
7254 /*-------------------------------------------------------------------*/
7255 /* B33E MADR - Multiply and Add Floating Point Long Register [RRF] */
7256 /*-------------------------------------------------------------------*/
DEF_INST(multiply_add_float_long_reg)7257 DEF_INST(multiply_add_float_long_reg)
7258 {
7259 int r1, r2, r3; /* Values of R fields */
7260 int i1, i2, i3; /* Indexes into fpr array */
7261 LONG_FLOAT fl1, fl2, fl3;
7262 int pgm_check;
7263
7264 RRF_R(inst, regs, r1, r2, r3);
7265 HFPREG2_CHECK(r1, r2, regs);
7266 HFPREG_CHECK(r3, regs);
7267 i1 = FPR2I(r1);
7268 i2 = FPR2I(r2);
7269 i3 = FPR2I(r3);
7270
7271 /* Get the operands */
7272 get_lf(&fl1, regs->fpr + i1);
7273 get_lf(&fl2, regs->fpr + i2);
7274 get_lf(&fl3, regs->fpr + i3);
7275
7276 /* Multiply long third and second operands */
7277 mul_lf(&fl2, &fl3, NOOVUNF, regs);
7278
7279 /* Add the first operand with normalization */
7280 pgm_check = add_lf(&fl1, &fl2, NORMAL, NOSIGEX, regs);
7281
7282 /* Store result back to first operand register */
7283 store_lf(&fl1, regs->fpr + i1);
7284
7285 /* Program check ? */
7286 if (pgm_check) {
7287 ARCH_DEP(program_interrupt) (regs, pgm_check);
7288 }
7289
7290 } /* end DEF_INST(multiply_add_float_long_reg) */
7291
7292
7293 /*-------------------------------------------------------------------*/
7294 /* B33F MSDR - Multiply and Subtract Floating Point Long Reg [RRF] */
7295 /*-------------------------------------------------------------------*/
DEF_INST(multiply_subtract_float_long_reg)7296 DEF_INST(multiply_subtract_float_long_reg)
7297 {
7298 int r1, r2, r3; /* Values of R fields */
7299 int i1, i2, i3; /* Indexes into fpr array */
7300 LONG_FLOAT fl1, fl2, fl3;
7301 int pgm_check;
7302
7303 RRF_R(inst, regs, r1, r2, r3);
7304 HFPREG2_CHECK(r1, r2, regs);
7305 HFPREG_CHECK(r3, regs);
7306 i1 = FPR2I(r1);
7307 i2 = FPR2I(r2);
7308 i3 = FPR2I(r3);
7309
7310 /* Get the operands */
7311 get_lf(&fl1, regs->fpr + i1);
7312 get_lf(&fl2, regs->fpr + i2);
7313 get_lf(&fl3, regs->fpr + i3);
7314
7315 /* Multiply long third and second operands */
7316 mul_lf(&fl2, &fl3, NOOVUNF, regs);
7317
7318 /* Invert the sign of the first operand */
7319 fl1.sign = ! (fl1.sign);
7320
7321 /* Subtract the first operand with normalization */
7322 pgm_check = add_lf(&fl1, &fl2, NORMAL, NOSIGEX, regs);
7323
7324 /* Store result back to first operand register */
7325 store_lf(&fl1, regs->fpr + i1);
7326
7327 /* Program check ? */
7328 if (pgm_check) {
7329 ARCH_DEP(program_interrupt) (regs, pgm_check);
7330 }
7331
7332 } /* end DEF_INST(multiply_subtract_float_long_reg) */
7333
7334
7335 /*-------------------------------------------------------------------*/
7336 /* ED2E MAE - Multiply and Add Floating Point Short [RXF] */
7337 /*-------------------------------------------------------------------*/
DEF_INST(multiply_add_float_short)7338 DEF_INST(multiply_add_float_short)
7339 {
7340 int r1, r3; /* Values of R fields */
7341 int i1, i3; /* Indexes into fpr array */
7342 int b2; /* Base of effective addr */
7343 VADR effective_addr2; /* Effective address */
7344 SHORT_FLOAT fl1, fl2, fl3;
7345 int pgm_check;
7346
7347 RXF(inst, regs, r1, r3, b2, effective_addr2);
7348 HFPREG2_CHECK(r1, r3, regs);
7349 i1 = FPR2I(r1);
7350 i3 = FPR2I(r3);
7351
7352 /* Get the operands */
7353 get_sf(&fl1, regs->fpr + i1);
7354 vfetch_sf(&fl2, effective_addr2, b2, regs );
7355 get_sf(&fl3, regs->fpr + i3);
7356
7357 /* Multiply third and second operands */
7358 mul_sf(&fl2, &fl3, NOOVUNF, regs);
7359
7360 /* Add the first operand with normalization */
7361 pgm_check = add_sf(&fl1, &fl2, NORMAL, NOSIGEX, regs);
7362
7363 /* Back to register */
7364 store_sf(&fl1, regs->fpr + i1);
7365
7366 /* Program check ? */
7367 if (pgm_check) {
7368 ARCH_DEP(program_interrupt) (regs, pgm_check);
7369 }
7370
7371 } /* end DEF_INST(multiply_add_float_short) */
7372
7373
7374 /*-------------------------------------------------------------------*/
7375 /* ED2F MSE - Multiply and Subtract Floating Point Short [RXF] */
7376 /*-------------------------------------------------------------------*/
DEF_INST(multiply_subtract_float_short)7377 DEF_INST(multiply_subtract_float_short)
7378 {
7379 int r1, r3; /* Values of R fields */
7380 int i1, i3; /* Indexes into fpr array */
7381 int b2; /* Base of effective addr */
7382 VADR effective_addr2; /* Effective address */
7383 SHORT_FLOAT fl1, fl2, fl3;
7384 int pgm_check;
7385
7386 RXF(inst, regs, r1, r3, b2, effective_addr2);
7387 HFPREG2_CHECK(r1, r3, regs);
7388 i1 = FPR2I(r1);
7389 i3 = FPR2I(r3);
7390
7391 /* Get the operands */
7392 get_sf(&fl1, regs->fpr + i1);
7393 vfetch_sf(&fl2, effective_addr2, b2, regs );
7394 get_sf(&fl3, regs->fpr + i3);
7395
7396 /* Multiply third and second operands */
7397 mul_sf(&fl2, &fl3, NOOVUNF, regs);
7398
7399 /* Invert the sign of the first operand */
7400 fl1.sign = ! (fl1.sign);
7401
7402 /* Subtract the first operand with normalization */
7403 pgm_check = add_sf(&fl1, &fl2, NORMAL, NOSIGEX, regs);
7404
7405 /* Back to register */
7406 store_sf(&fl1, regs->fpr + i1);
7407
7408 /* Program check ? */
7409 if (pgm_check) {
7410 ARCH_DEP(program_interrupt) (regs, pgm_check);
7411 }
7412
7413 } /* end DEF_INST(multiply_subtract_float_short) */
7414
7415
7416 /*-------------------------------------------------------------------*/
7417 /* ED3E MAD - Multiply and Add Floating Point Long [RXF] */
7418 /*-------------------------------------------------------------------*/
DEF_INST(multiply_add_float_long)7419 DEF_INST(multiply_add_float_long)
7420 {
7421 int r1, r3; /* Values of R fields */
7422 int i1, i3; /* Indexes into fpr array */
7423 int b2; /* Base of effective addr */
7424 VADR effective_addr2; /* Effective address */
7425 LONG_FLOAT fl1, fl2, fl3;
7426 int pgm_check;
7427
7428 RXF(inst, regs, r1, r3, b2, effective_addr2);
7429 HFPREG2_CHECK(r1, r3, regs);
7430 i1 = FPR2I(r1);
7431 i3 = FPR2I(r3);
7432
7433 /* Get the operands */
7434 get_lf(&fl1, regs->fpr + i1);
7435 vfetch_lf(&fl2, effective_addr2, b2, regs );
7436 get_lf(&fl3, regs->fpr + i3);
7437
7438 /* Multiply long third and second operands */
7439 mul_lf(&fl2, &fl3, NOOVUNF, regs);
7440
7441 /* Add long first operand with normalization */
7442 pgm_check = add_lf(&fl1, &fl2, NORMAL, NOSIGEX, regs);
7443
7444 /* Back to register */
7445 store_lf(&fl1, regs->fpr + i1);
7446
7447 /* Program check ? */
7448 if (pgm_check) {
7449 ARCH_DEP(program_interrupt) (regs, pgm_check);
7450 }
7451
7452 } /* end DEF_INST(multiply_add_float_long) */
7453
7454
7455 /*-------------------------------------------------------------------*/
7456 /* ED3F MSD - Multiply and Subtract Floating Point Long [RXF] */
7457 /*-------------------------------------------------------------------*/
DEF_INST(multiply_subtract_float_long)7458 DEF_INST(multiply_subtract_float_long)
7459 {
7460 int r1, r3; /* Values of R fields */
7461 int i1, i3; /* Indexes into fpr array */
7462 int b2; /* Base of effective addr */
7463 VADR effective_addr2; /* Effective address */
7464 LONG_FLOAT fl1, fl2, fl3;
7465 int pgm_check;
7466
7467 RXF(inst, regs, r1, r3, b2, effective_addr2);
7468 HFPREG2_CHECK(r1, r3, regs);
7469 i1 = FPR2I(r1);
7470 i3 = FPR2I(r3);
7471
7472 /* Get the operands */
7473 get_lf(&fl1, regs->fpr + i1);
7474 vfetch_lf(&fl2, effective_addr2, b2, regs );
7475 get_lf(&fl3, regs->fpr + i3);
7476
7477 /* Multiply long third and second operands */
7478 mul_lf(&fl2, &fl3, NOOVUNF, regs);
7479
7480 /* Invert the sign of the first operand */
7481 fl1.sign = ! (fl1.sign);
7482
7483 /* Subtract long with normalization */
7484 pgm_check = add_lf(&fl1, &fl2, NORMAL, NOSIGEX, regs);
7485
7486 /* Back to register */
7487 store_lf(&fl1, regs->fpr + i1);
7488
7489 /* Program check ? */
7490 if (pgm_check) {
7491 ARCH_DEP(program_interrupt) (regs, pgm_check);
7492 }
7493
7494 } /* end DEF_INST(multiply_subtract_float_long) */
7495 #endif /*defined(FEATURE_HFP_MULTIPLY_ADD_SUBTRACT)*/
7496
7497
7498 #if defined(FEATURE_HFP_UNNORMALIZED_EXTENSION)
7499 /*-------------------------------------------------------------------*/
7500 /* B338 MAYLR - Multiply and Add Unnorm. Long to Ext. Low Reg. [RRF] */
7501 /*-------------------------------------------------------------------*/
DEF_INST(multiply_add_unnormal_float_long_to_ext_low_reg)7502 DEF_INST(multiply_add_unnormal_float_long_to_ext_low_reg)
7503 {
7504 int r1, r2, r3; /* Values of R fields */
7505 int i1, i2, i3; /* Indexes into fpr array */
7506 LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */
7507 LONG_FLOAT fl1; /* Addend */
7508 EXTENDED_FLOAT fxp1; /* Intermediate product */
7509 EXTENDED_FLOAT fxadd; /* Addend in extended format */
7510 EXTENDED_FLOAT fxres; /* Extended result */
7511
7512 RRF_R(inst, regs, r1, r2, r3)
7513 HFPREG2_CHECK(r2, r3, regs);
7514 HFPREG_CHECK(r1, regs);
7515 i1 = FPR2I(r1);
7516 i2 = FPR2I(r2);
7517 i3 = FPR2I(r3);
7518
7519 /* Get the operands */
7520 get_lf(&fl1, regs->fpr + i1);
7521 get_lf(&fl2, regs->fpr + i2);
7522 get_lf(&fl3, regs->fpr + i3);
7523
7524 /* Calculate intermediate product */
7525 ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fxp1);
7526
7527 /* Convert Addend to extended format */
7528 ARCH_DEP(lf_to_ef_unnorm)(&fxadd, &fl1);
7529
7530 /* Add the addend to the intermediate product */
7531 ARCH_DEP(add_ef_unnorm)(&fxp1, &fxadd, &fxres);
7532
7533 /* Place low-order part of result in register */
7534 ARCH_DEP(store_ef_unnorm_lo)(&fxres, regs->fpr + i1);
7535
7536 } /* end DEF_INST(multiply_add_unnormal_float_long_to_ext_low_reg) */
7537
7538
7539 /*-------------------------------------------------------------------*/
7540 /* B339 MYLR - Multiply Unnormalized Long to Ext. Low FP Reg. [RRF] */
7541 /*-------------------------------------------------------------------*/
DEF_INST(multiply_unnormal_float_long_to_ext_low_reg)7542 DEF_INST(multiply_unnormal_float_long_to_ext_low_reg)
7543 {
7544 int r1, r2, r3; /* Values of R fields */
7545 int i1, i2, i3; /* Indexes into fpr array */
7546 LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */
7547 EXTENDED_FLOAT fx1; /* Intermediate result */
7548
7549 RRF_R(inst, regs, r1, r2, r3);
7550 HFPREG2_CHECK(r2, r3, regs);
7551 HFPREG_CHECK(r1, regs);
7552 i1 = FPR2I(r1);
7553 i2 = FPR2I(r2);
7554 i3 = FPR2I(r3);
7555
7556 /* Get the operands */
7557 get_lf(&fl2, regs->fpr + i2);
7558 get_lf(&fl3, regs->fpr + i3);
7559
7560 /* Calculate intermediate result */
7561 ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fx1);
7562
7563 /* Place low-order part of result in register */
7564 ARCH_DEP(store_ef_unnorm_lo)(&fx1, regs->fpr + i1);
7565
7566 } /* end DEF_INST(multiply_unnormal_float_long_to_ext_low_reg) */
7567
7568
7569 /*-------------------------------------------------------------------*/
7570 /* B33A MAYR - Multiply and Add Unnorm. Long to Ext. Reg. [RRF] */
7571 /*-------------------------------------------------------------------*/
DEF_INST(multiply_add_unnormal_float_long_to_ext_reg)7572 DEF_INST(multiply_add_unnormal_float_long_to_ext_reg)
7573 {
7574 int r1, r2, r3; /* Values of R fields */
7575 int i1, i2, i3; /* Indexes into fpr array */
7576 LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */
7577 LONG_FLOAT fl1; /* Addend */
7578 EXTENDED_FLOAT fxp1; /* Intermediate product */
7579 EXTENDED_FLOAT fxadd; /* Addend in extended format */
7580 EXTENDED_FLOAT fxres; /* Extended result */
7581
7582 RRF_R(inst, regs, r1, r2, r3);
7583 HFPREG2_CHECK(r2, r3, regs);
7584 HFPREG_CHECK(r1, regs);
7585 /* Either the low- or high-numbered register of a pair is valid */
7586 i1 = FPR2I(r1);
7587 i2 = FPR2I(r2);
7588 i3 = FPR2I(r3);
7589
7590 /* Get the operands */
7591 get_lf(&fl1, regs->fpr + i1);
7592 get_lf(&fl2, regs->fpr + i2);
7593 get_lf(&fl3, regs->fpr + i3);
7594
7595 /* Calculate intermediate product */
7596 ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fxp1);
7597
7598 /* Convert Addend to extended format */
7599 ARCH_DEP(lf_to_ef_unnorm)(&fxadd, &fl1);
7600
7601 /* Add the addend to the intermediate product */
7602 ARCH_DEP(add_ef_unnorm)(&fxp1, &fxadd, &fxres);
7603
7604 /* Place result in register */
7605 r1 &= 13; /* Convert to the low numbered register */
7606 i1 = FPR2I(r1);
7607 ARCH_DEP(store_ef_unnorm)(&fxres, regs->fpr + i1);
7608
7609 } /* end DEF_INST(multiply_add_unnormal_float_long_to_ext_reg) */
7610
7611
7612 /*-------------------------------------------------------------------*/
7613 /* B33B MYR - Multiply Unnormalized Long to Extended Reg [RRF] */
7614 /*-------------------------------------------------------------------*/
DEF_INST(multiply_unnormal_float_long_to_ext_reg)7615 DEF_INST(multiply_unnormal_float_long_to_ext_reg)
7616 {
7617 int r1, r2, r3; /* Values of R fields */
7618 int i1, i2, i3; /* Indexes into fpr array */
7619 LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */
7620 EXTENDED_FLOAT fx1; /* Intermediate result */
7621
7622 RRF_R(inst, regs, r1, r2, r3);
7623 HFPODD_CHECK(r1, regs);
7624 HFPREG2_CHECK(r2, r3, regs);
7625 i1 = FPR2I(r1);
7626 i2 = FPR2I(r2);
7627 i3 = FPR2I(r3);
7628
7629 /* Get the operands */
7630 get_lf(&fl2, regs->fpr + i2);
7631 get_lf(&fl3, regs->fpr + i3);
7632
7633 /* Calculate intermediate result */
7634 ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fx1);
7635
7636 /* Place result in register */
7637 ARCH_DEP(store_ef_unnorm)(&fx1, regs->fpr + i1);
7638
7639 } /* DEF_INST(multiply_unnormal_float_long_to_ext_reg) */
7640
7641
7642 /*-------------------------------------------------------------------*/
7643 /* B33C MAYHR - Multiply and Add Unnorm. Long to Ext. High Reg [RRF] */
7644 /*-------------------------------------------------------------------*/
DEF_INST(multiply_add_unnormal_float_long_to_ext_high_reg)7645 DEF_INST(multiply_add_unnormal_float_long_to_ext_high_reg)
7646 {
7647 int r1, r2, r3; /* Values of R fields */
7648 int i1, i2, i3; /* Indexes into fpr array */
7649 LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */
7650 LONG_FLOAT fl1; /* Addend */
7651 EXTENDED_FLOAT fxp1; /* Intermediate product */
7652 EXTENDED_FLOAT fxadd; /* Addend in extended format */
7653 EXTENDED_FLOAT fxres; /* Extended result */
7654
7655 RRF_R(inst, regs, r1, r2, r3);
7656 HFPREG2_CHECK(r2, r3, regs);
7657 HFPREG_CHECK(r1, regs);
7658 i1 = FPR2I(r1);
7659 i2 = FPR2I(r2);
7660 i3 = FPR2I(r3);
7661
7662 /* Get the operands */
7663 get_lf(&fl1, regs->fpr + i1);
7664 get_lf(&fl2, regs->fpr + i2);
7665 get_lf(&fl3, regs->fpr + i3);
7666
7667 /* Calculate intermediate product */
7668 ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fxp1);
7669
7670 /* Convert Addend to extended format */
7671 ARCH_DEP(lf_to_ef_unnorm)(&fxadd, &fl1);
7672
7673 /* Add the addend to the intermediate product */
7674 ARCH_DEP(add_ef_unnorm)(&fxp1, &fxadd, &fxres);
7675
7676 /* Place high-order part of result in register */
7677 ARCH_DEP(store_ef_unnorm_hi)(&fxres, regs->fpr + i1);
7678
7679 } /* end DEF_INST(multiply_add_unnormal_float_long_to_ext_high_reg) */
7680
7681
7682 /*-------------------------------------------------------------------*/
7683 /* B33D MYHR - Multiply Unnormalized Long to Ext. High FP Reg[RRF] */
7684 /*-------------------------------------------------------------------*/
DEF_INST(multiply_unnormal_float_long_to_ext_high_reg)7685 DEF_INST(multiply_unnormal_float_long_to_ext_high_reg)
7686 {
7687 int r1, r2, r3; /* Values of R fields */
7688 int i1, i2, i3; /* Indexes into fpr array */
7689 LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */
7690 EXTENDED_FLOAT fx1; /* Intermediate result */
7691
7692 RRF_R(inst, regs, r1, r2, r3);
7693 HFPODD_CHECK(r1, regs);
7694 HFPREG2_CHECK(r2, r3, regs);
7695 i1 = FPR2I(r1);
7696 i2 = FPR2I(r2);
7697 i3 = FPR2I(r3);
7698
7699 /* Get the operands */
7700 get_lf(&fl2, regs->fpr + i2);
7701 get_lf(&fl3, regs->fpr + i3);
7702
7703 /* Calculate intermediate result */
7704 ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fx1);
7705
7706 /* Place high-order part of result in register */
7707 ARCH_DEP(store_ef_unnorm_hi)(&fx1, regs->fpr + i1);
7708
7709 } /* end DEF_INST(multiply_unnormal_float_long_to_ext_high_reg) */
7710
7711
7712 /*-------------------------------------------------------------------*/
7713 /* ED38 MAYL - Multiply and Add Unnorm. Long to Ext. Low FP [RXF] */
7714 /*-------------------------------------------------------------------*/
DEF_INST(multiply_add_unnormal_float_long_to_ext_low)7715 DEF_INST(multiply_add_unnormal_float_long_to_ext_low)
7716 {
7717 int r1, r3; /* Values of R fields */
7718 int i1, i3; /* Indexes into fpr array */
7719 int b2; /* Base of effective addr */
7720 VADR effective_addr2; /* Effective address */
7721 LONG_FLOAT fl2,fl3; /* Multiplier/Multiplicand */
7722 LONG_FLOAT fl1; /* Addend */
7723 EXTENDED_FLOAT fxp1; /* Intermediate product */
7724 EXTENDED_FLOAT fxadd; /* Addend in extended format */
7725 EXTENDED_FLOAT fxres; /* Extended result */
7726
7727 RXF(inst, regs, r1, r3, b2, effective_addr2);
7728 HFPREG2_CHECK(r1, r3, regs);
7729 i1 = FPR2I(r1);
7730 i3 = FPR2I(r3);
7731
7732 /* Get the operands */
7733 get_lf(&fl1, regs->fpr + i1);
7734 vfetch_lf(&fl2, effective_addr2, b2, regs );
7735 get_lf(&fl3, regs->fpr + i3);
7736
7737 /* Calculate intermediate product */
7738 ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fxp1);
7739
7740 /* Convert Addend to extended format */
7741 ARCH_DEP(lf_to_ef_unnorm)(&fxadd, &fl1);
7742
7743 /* Add the addend to the intermediate product */
7744 ARCH_DEP(add_ef_unnorm)(&fxp1, &fxadd, &fxres);
7745
7746 /* Place low-order part of result in register */
7747 ARCH_DEP(store_ef_unnorm_lo)(&fxres, regs->fpr + i1);
7748
7749 } /* end DEF_INST(multiply_add_unnormal_float_long_to_ext_low) */
7750
7751
7752 /*-------------------------------------------------------------------*/
7753 /* ED39 MYL - Multiply Unnormalized Long to Extended Low FP [RXF] */
7754 /*-------------------------------------------------------------------*/
DEF_INST(multiply_unnormal_float_long_to_ext_low)7755 DEF_INST(multiply_unnormal_float_long_to_ext_low)
7756 {
7757 int r1, r3; /* Values of R fields */
7758 int i1, i3; /* Indexes into fpr array */
7759 int b2; /* Base of effective addr */
7760 VADR effective_addr2; /* Effective address */
7761 LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */
7762 EXTENDED_FLOAT fx1; /* Intermediate result */
7763
7764 RXF(inst, regs, r1, r3, b2, effective_addr2);
7765 HFPREG2_CHECK(r1, r3, regs);
7766 i1 = FPR2I(r1);
7767 i3 = FPR2I(r3);
7768
7769 /* Get the operands */
7770 vfetch_lf(&fl2, effective_addr2, b2, regs );
7771 get_lf(&fl3, regs->fpr + i3);
7772
7773 /* Calculate intermediate result */
7774 ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fx1);
7775
7776 /* Place low-order part of result in register */
7777 ARCH_DEP(store_ef_unnorm_lo)(&fx1, regs->fpr + i1);
7778
7779 } /* end DEF_INST(multiply_unnormal_float_long_to_ext_low) */
7780
7781
7782 /*-------------------------------------------------------------------*/
7783 /* ED3A MAY - Multiply and Add Unnorm. Long to Extended FP [RXF] */
7784 /*-------------------------------------------------------------------*/
DEF_INST(multiply_add_unnormal_float_long_to_ext)7785 DEF_INST(multiply_add_unnormal_float_long_to_ext)
7786 {
7787 int r1, r3; /* Values of R fields */
7788 int i1, i3; /* Indexes into fpr array */
7789 int b2; /* Base of effective addr */
7790 VADR effective_addr2; /* Effective address */
7791 LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */
7792 LONG_FLOAT fl1; /* Addend */
7793 EXTENDED_FLOAT fxp1; /* Intermediate product */
7794 EXTENDED_FLOAT fxadd; /* Addend in extended format */
7795 EXTENDED_FLOAT fxres; /* Extended result */
7796
7797 RXF(inst, regs, r1, r3, b2, effective_addr2);
7798 HFPREG2_CHECK(r1, r3, regs);
7799 /* Either the low- or high-numbered register of a pair is valid */
7800 i1 = FPR2I(r1);
7801 i3 = FPR2I(r3);
7802
7803 /* Get the operands */
7804 get_lf(&fl1, regs->fpr + i1);
7805 vfetch_lf(&fl2, effective_addr2, b2, regs );
7806 get_lf(&fl3, regs->fpr + i3);
7807
7808 /* Calculate intermediate product */
7809 ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fxp1);
7810
7811 /* Convert Addend to extended format */
7812 ARCH_DEP(lf_to_ef_unnorm)(&fxadd, &fl1);
7813
7814 /* Add the addend to the intermediate product */
7815 ARCH_DEP(add_ef_unnorm)(&fxp1, &fxadd, &fxres);
7816
7817 /* Place result in register */
7818 r1 &= 13; /* Convert to the low numbered register */
7819 i1 = FPR2I(r1);
7820 ARCH_DEP(store_ef_unnorm)(&fxres, regs->fpr + i1);
7821
7822 } /* end DEF_INST(multiply_add_unnormal_float_long_to_ext) */
7823
7824
7825 /*-------------------------------------------------------------------*/
7826 /* ED3B MY - Multiply Unnormalized Long to Extended FP [RXF] */
7827 /*-------------------------------------------------------------------*/
DEF_INST(multiply_unnormal_float_long_to_ext)7828 DEF_INST(multiply_unnormal_float_long_to_ext)
7829 {
7830 int r1, r3; /* Values of R fields */
7831 int i1, i3; /* Indexes into fpr array */
7832 int b2; /* Base of effective addr */
7833 VADR effective_addr2; /* Effective address */
7834 LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */
7835 EXTENDED_FLOAT fx1; /* Intermediate result */
7836
7837 RXF(inst, regs, r1, r3, b2, effective_addr2);
7838 HFPODD_CHECK(r1, regs);
7839 HFPREG_CHECK(r3, regs);
7840 i1 = FPR2I(r1);
7841 i3 = FPR2I(r3);
7842
7843 /* Get the operands */
7844 vfetch_lf(&fl2, effective_addr2, b2, regs );
7845 get_lf(&fl3, regs->fpr + i3);
7846
7847 /* Calculate intermediate result */
7848 ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fx1);
7849
7850 /* Place result in register */
7851 ARCH_DEP(store_ef_unnorm)(&fx1, regs->fpr + i1);
7852
7853 } /* end DEF_INST(multiply_unnormal_float_long_to_ext) */
7854
7855
7856 /*-------------------------------------------------------------------*/
7857 /* ED3C MAYH - Multiply and Add Unnorm. Long to Extended High [RXF] */
7858 /*-------------------------------------------------------------------*/
DEF_INST(multiply_add_unnormal_float_long_to_ext_high)7859 DEF_INST(multiply_add_unnormal_float_long_to_ext_high)
7860 {
7861 int r1, r3; /* Values of R fields */
7862 int i1, i3; /* Indexes into fpr array */
7863 int b2; /* Base of effective addr */
7864 VADR effective_addr2; /* Effective address */
7865 LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */
7866 LONG_FLOAT fl1; /* Addend */
7867 EXTENDED_FLOAT fxp1; /* Intermediate product */
7868 EXTENDED_FLOAT fxadd; /* Addend in extended format */
7869 EXTENDED_FLOAT fxres; /* Extended result */
7870
7871 RXF(inst, regs, r1, r3, b2, effective_addr2);
7872 HFPREG2_CHECK(r1, r3, regs);
7873 i1 = FPR2I(r1);
7874 i3 = FPR2I(r3);
7875
7876 /* Get the operands */
7877 get_lf(&fl1, regs->fpr + i1);
7878 vfetch_lf(&fl2, effective_addr2, b2, regs );
7879 get_lf(&fl3, regs->fpr + i3);
7880
7881 /* Calculate intermediate product */
7882 ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fxp1);
7883
7884 /* Convert Addend to extended format */
7885 ARCH_DEP(lf_to_ef_unnorm)(&fxadd, &fl1);
7886
7887 /* Add the addend to the intermediate product */
7888 ARCH_DEP(add_ef_unnorm)(&fxp1, &fxadd, &fxres);
7889
7890 /* Place high-order part of result in register */
7891 ARCH_DEP(store_ef_unnorm_hi)(&fxres, regs->fpr + i1);
7892
7893 } /* end DEF_INST(multiply_add_unnormal_float_long_to_ext_high) */
7894
7895
7896 /*-------------------------------------------------------------------*/
7897 /* ED3D MYH - Multiply Unnormalized Long to Extended High FP [RXF] */
7898 /*-------------------------------------------------------------------*/
DEF_INST(multiply_unnormal_float_long_to_ext_high)7899 DEF_INST(multiply_unnormal_float_long_to_ext_high)
7900 {
7901 int r1, r3; /* Values of R fields */
7902 int i1, i3; /* Indexes into fpr array */
7903 int b2; /* Base of effective addr */
7904 VADR effective_addr2; /* Effective address */
7905 LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */
7906 EXTENDED_FLOAT fx1; /* Intermediate result */
7907
7908 RXF(inst, regs, r1, r3, b2, effective_addr2);
7909 HFPREG2_CHECK(r1, r3, regs);
7910 i1 = FPR2I(r1);
7911 i3 = FPR2I(r3);
7912
7913 /* Get the operands */
7914 vfetch_lf(&fl2, effective_addr2, b2, regs );
7915 get_lf(&fl3, regs->fpr + i3);
7916
7917 /* Calculate intermediate result */
7918 ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fx1);
7919
7920 /* Place high-order part of result in register */
7921 ARCH_DEP(store_ef_unnorm_hi)(&fx1, regs->fpr + i1);
7922
7923 } /* end DEF_INST(multiply_unnormal_float_long_to_ext_high) */
7924 #endif /*defined(FEATURE_HFP_UNNORMALIZED_EXTENSION)*/
7925
7926
7927 #if defined(FEATURE_LONG_DISPLACEMENT)
7928 /*-------------------------------------------------------------------*/
7929 /* ED64 LEY - Load Floating Point Short (Long Displacement) [RXY] */
7930 /*-------------------------------------------------------------------*/
DEF_INST(load_float_short_y)7931 DEF_INST(load_float_short_y)
7932 {
7933 int r1; /* Value of R field */
7934 int i1; /* Index of R1 in fpr array */
7935 int b2; /* Base of effective addr */
7936 VADR effective_addr2; /* Effective address */
7937
7938 RXY(inst, regs, r1, b2, effective_addr2);
7939 HFPREG_CHECK(r1, regs);
7940 i1 = FPR2I(r1);
7941
7942 /* Update first 32 bits of register from operand address */
7943 regs->fpr[i1] = ARCH_DEP(vfetch4) (effective_addr2, b2, regs);
7944
7945 } /* end DEF_INST(load_float_short_y) */
7946
7947
7948 /*-------------------------------------------------------------------*/
7949 /* ED65 LDY - Load Floating Point Long (Long Displacement) [RXY] */
7950 /*-------------------------------------------------------------------*/
DEF_INST(load_float_long_y)7951 DEF_INST(load_float_long_y)
7952 {
7953 int r1; /* Value of R field */
7954 int i1; /* Index of R1 in fpr array */
7955 int b2; /* Base of effective addr */
7956 VADR effective_addr2; /* Effective address */
7957 U64 dreg; /* Double word workarea */
7958
7959 RXY(inst, regs, r1, b2, effective_addr2);
7960 HFPREG_CHECK(r1, regs);
7961 i1 = FPR2I(r1);
7962
7963 /* Fetch value from operand address */
7964 dreg = ARCH_DEP(vfetch8) (effective_addr2, b2, regs);
7965
7966 /* Update register contents */
7967 regs->fpr[i1] = dreg >> 32;
7968 regs->fpr[i1+1] = dreg;
7969
7970 } /* end DEF_INST(load_float_long_y) */
7971
7972
7973 /*-------------------------------------------------------------------*/
7974 /* ED66 STEY - Store Floating Point Short (Long Displacement) [RXY] */
7975 /*-------------------------------------------------------------------*/
DEF_INST(store_float_short_y)7976 DEF_INST(store_float_short_y)
7977 {
7978 int r1; /* Value of R field */
7979 int i1; /* Index of R1 in fpr array */
7980 int b2; /* Base of effective addr */
7981 VADR effective_addr2; /* Effective address */
7982
7983 RXY(inst, regs, r1, b2, effective_addr2);
7984 HFPREG_CHECK(r1, regs);
7985 i1 = FPR2I(r1);
7986
7987 /* Store register contents at operand address */
7988 ARCH_DEP(vstore4) (regs->fpr[i1], effective_addr2, b2, regs);
7989
7990 } /* end DEF_INST(store_float_short_y) */
7991
7992
7993 /*-------------------------------------------------------------------*/
7994 /* ED67 STDY - Store Floating Point Long (Long Displacement) [RXY] */
7995 /*-------------------------------------------------------------------*/
DEF_INST(store_float_long_y)7996 DEF_INST(store_float_long_y)
7997 {
7998 int r1; /* Value of R field */
7999 int i1; /* Index of R1 in fpr array */
8000 int b2; /* Base of effective addr */
8001 VADR effective_addr2; /* Effective address */
8002 U64 dreg; /* Double word workarea */
8003
8004 RXY(inst, regs, r1, b2, effective_addr2);
8005 HFPREG_CHECK(r1, regs);
8006 i1 = FPR2I(r1);
8007
8008 /* Store register contents at operand address */
8009 dreg = ((U64)regs->fpr[i1] << 32)
8010 | regs->fpr[i1+1];
8011 ARCH_DEP(vstore8) (dreg, effective_addr2, b2, regs);
8012
8013 } /* end DEF_INST(store_float_long_y) */
8014 #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/
8015
8016
8017 #endif /* FEATURE_HEXADECIMAL_FLOATING_POINT */
8018
8019 #if !defined(_GEN_ARCH)
8020
8021 #if defined(_ARCHMODE2)
8022 #define _GEN_ARCH _ARCHMODE2
8023 #include "float.c"
8024 #endif
8025
8026 #if defined(_ARCHMODE3)
8027 #undef _GEN_ARCH
8028 #define _GEN_ARCH _ARCHMODE3
8029 #include "float.c"
8030 #endif
8031
8032 #endif /*!defined(_GEN_ARCH)*/
8033
8034
8035 /* end of float.c */
8036