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(&regs->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(&regs->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(&regs->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(&regs->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(&regs->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(&regs->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(&regs->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(&regs->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(&regs->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