efp_assist.c

Go to the documentation of this file.
00001 /*
00002  * $QNXLicenseC:
00003  * Copyright 2009, QNX Software Systems. All Rights Reserved.
00004  *
00005  * You must obtain a written license from and pay applicable license fees to QNX
00006  * Software Systems before you may reproduce, modify or distribute this software,
00007  * or any work that includes all or part of this software.   Free development
00008  * licenses are available for evaluation and non-commercial purposes.  For more
00009  * information visit http://licensing.qnx.com or email licensing@qnx.com.
00010  *
00011  * This file may contain contributions from others.  Please review this entire
00012  * file for other proprietary rights or license notices, as well as the QNX
00013  * Development Suite License Guide at http://licensing.qnx.com/license-guide/
00014  * for other information.
00015  * $
00016  */
00017 
00076 #if !defined(__BIGENDIAN__) || !defined(VARIANT_spe)
00077 # error BIGENDIAN PPC WITH SPE APU REQUIRED
00078 #endif
00079 
00080 /*****************************************************************************
00081  * INCLUDES
00082  ****************************************************************************/
00083 
00084 #include "efp_assist.h"
00085 
00086 #include <stddef.h>
00087 #include <stdint.h>
00088 #include <stdbool.h>
00089 #include <string.h>
00090 #include <malloc.h>
00091 #include <signal.h>
00092 #include <sys/fault.h>
00093 #include <fcntl.h>
00094 #include <assert.h>
00095 
00096 #include <kernel/macros.h>
00097 #include <ppc/opcode.h>
00098 #include <ppc/bookecpu.h>
00099 
00100 #include "softfloat.h"
00101 
00102 /*****************************************************************************
00103  * DEFINES
00104  ****************************************************************************/
00105 
00108 #define SPEFSCR_VECT_HI_EXC_MASK                \
00109     (PPCBKE_APU_SPE_SPEFSCR_FXH                 \
00110      |PPCBKE_APU_SPE_SPEFSCR_FGH                \
00111      |PPCBKE_APU_SPE_SPEFSCR_FINVH              \
00112      |PPCBKE_APU_SPE_SPEFSCR_FDBZH              \
00113      |PPCBKE_APU_SPE_SPEFSCR_FUNFH              \
00114      |PPCBKE_APU_SPE_SPEFSCR_FOVFH)
00115 
00118 #define SPEFSCR_VECT_LO_EXC_MASK                \
00119     (PPCBKE_APU_SPE_SPEFSCR_FX                  \
00120      |PPCBKE_APU_SPE_SPEFSCR_FG                 \
00121      |PPCBKE_APU_SPE_SPEFSCR_FINV               \
00122      |PPCBKE_APU_SPE_SPEFSCR_FDBZ               \
00123      |PPCBKE_APU_SPE_SPEFSCR_FUNF               \
00124      |PPCBKE_APU_SPE_SPEFSCR_FOVF)
00125 
00128 #define SPEFSCR_EFP_ALL_EXC_MASK                \
00129     (SPEFSCR_VECT_HI_EXC_MASK                   \
00130      |SPEFSCR_VECT_LO_EXC_MASK)
00131 
00134 #define SPEFSCR_STICKY_EXC_MASK                 \
00135     (PPCBKE_APU_SPE_SPEFSCR_FINXS               \
00136      |PPCBKE_APU_SPE_SPEFSCR_FINVS              \
00137      |PPCBKE_APU_SPE_SPEFSCR_FDBZS              \
00138      |PPCBKE_APU_SPE_SPEFSCR_FUNFS              \
00139      |PPCBKE_APU_SPE_SPEFSCR_FOVFS)
00140 
00143 #define SPEFSCR_ENABLE_EXC_MASK                 \
00144     (PPCBKE_APU_SPE_SPEFSCR_FINXE               \
00145      |PPCBKE_APU_SPE_SPEFSCR_FINVE              \
00146      |PPCBKE_APU_SPE_SPEFSCR_FDBZE              \
00147      |PPCBKE_APU_SPE_SPEFSCR_FUNFE              \
00148      |PPCBKE_APU_SPE_SPEFSCR_FOVFE)
00149 
00152 #define SPEFSCR_NEEDED_EXC_MASK                 \
00153     (PPCBKE_APU_SPE_SPEFSCR_FINVE               \
00154      |PPCBKE_APU_SPE_SPEFSCR_FDBZE              \
00155      |PPCBKE_APU_SPE_SPEFSCR_FUNFE              \
00156      |PPCBKE_APU_SPE_SPEFSCR_FOVFE)
00157 
00160 #define SPEFSCR_STICKY_EXC_SHIFT (57-42)
00161 
00162 /*****************************************************************************
00163  * MACROS
00164  ****************************************************************************/
00165 
00168 #define NELEM(A) (sizeof(A)/sizeof(*(A)))
00169 
00192 #define LOADHI(V,N) __asm__ volatile ("evmergehi %0,%0,%1" : "=b" (V) : "i" (N))
00193 
00217 #define STOREHI(V,N) __asm__ volatile ("evmergelo %1,%0,%1" : : "b" (V), "i" (N))
00218 
00219 #if !defined(NDEBUG)
00220 # include <stdio.h>
00222 # define DPRINTF(format, ...) fprintf(stderr, format, ## __VA_ARGS__)
00223 #else
00224 
00225 # define DPRINTF(format, ...)
00226 #endif
00227 
00228 /*****************************************************************************
00229  * TYPE DEFINITIONS
00230  ****************************************************************************/
00231 
00239 typedef struct {
00240 
00243     uint32_t spefscr;
00244 
00245 } appenv_type;
00246 
00251 typedef enum {
00252 
00253     // Vector Monadic
00254 
00255     PPC_XO_evfsabs = 644,                         
00256     PPC_XO_evfsnabs = 645,                        
00257     PPC_XO_evfsneg = 646,                         
00259     // Vector Arithmetic
00260 
00261     PPC_XO_evfsadd = 640,                         
00262     PPC_XO_evfssub = 641,                         
00263     PPC_XO_evfsmul = 648,                         
00264     PPC_XO_evfsdiv = 649,                         
00266     // Vector Compare
00267 
00268     PPC_XO_evfscmpgt = 652,                       
00269     PPC_XO_evfscmplt = 653,                       
00270     PPC_XO_evfscmpeq = 654,                       
00272     // Vector Test
00273 
00274     PPC_XO_evfststgt = 668,                       
00275     PPC_XO_evfststlt = 669,                       
00276     PPC_XO_evfststeq = 670,                       
00278     // Vector Convert From Integer
00279 
00280     PPC_XO_evfscfsi = 657,                        
00281     PPC_XO_evfscfui = 656,                        
00283     // Vector Convert From Fraction
00284 
00285     PPC_XO_evfscfsf = 659,                        
00286     PPC_XO_evfscfuf = 658,                        
00288     // Vector Convert To Integer
00289 
00290     PPC_XO_evfsctsi = 661,                        
00291     PPC_XO_evfsctui = 660,                        
00293     // Vector Convert To Integer Zero Rounded
00294 
00295     PPC_XO_evfsctsiz = 666,                       
00296     PPC_XO_evfsctuiz = 664,                       
00298     // Vector Convert To Fraction
00299 
00300     PPC_XO_evfsctsf = 663,                        
00301     PPC_XO_evfsctuf = 662,                        
00303     // Single Monadic
00304 
00305     PPC_XO_efsabs = 708,                          
00306     PPC_XO_efsnabs = 709,                         
00307     PPC_XO_efsneg = 710,                          
00309     // Single Arithmetic
00310 
00311     PPC_XO_efsadd = 704,                          
00312     PPC_XO_efssub = 705,                          
00313     PPC_XO_efsmul = 712,                          
00314     PPC_XO_efsdiv = 713,                          
00316     // Single Compare
00317 
00318     PPC_XO_efscmpgt = 716,                        
00319     PPC_XO_efscmplt = 717,                        
00320     PPC_XO_efscmpeq = 718,                        
00322     // Single Test
00323 
00324     PPC_XO_efststgt = 732,                        
00325     PPC_XO_efststlt = 733,                        
00326     PPC_XO_efststeq = 734,                        
00328     // Single Convert From Integer
00329 
00330     PPC_XO_efscfsi = 721,                         
00331     PPC_XO_efscfui = 720,                         
00333     // Single Convert From Fraction
00334 
00335     PPC_XO_efscfsf = 723,                         
00336     PPC_XO_efscfuf = 722,                         
00338     // Single Convert To Integer
00339 
00340     PPC_XO_efsctsi = 725,                         
00341     PPC_XO_efsctui = 724,                         
00343     // Single Convert To Integer Zero Rounded
00344 
00345     PPC_XO_efsctsiz = 730,                        
00346     PPC_XO_efsctuiz = 728,                        
00348     // Single Convert To Fraction
00349 
00350     PPC_XO_efsctsf = 727,                         
00351     PPC_XO_efsctuf = 726,                         
00353     // Double Monadic
00354 
00355     PPC_XO_efdabs = 740,                          
00356     PPC_XO_efdnabs = 741,                         
00357     PPC_XO_efdneg = 742,                          
00359     // Double Arithmetic
00360 
00361     PPC_XO_efdadd = 736,                          
00362     PPC_XO_efdsub = 737,                          
00363     PPC_XO_efdmul = 744,                          
00364     PPC_XO_efddiv = 745,                          
00366     // Double Compare
00367 
00368     PPC_XO_efdcmpgt = 748,                        
00369     PPC_XO_efdcmplt = 749,                        
00370     PPC_XO_efdcmpeq = 750,                        
00372     // Double Test
00373 
00374     PPC_XO_efdtstgt = 764,                        
00375     PPC_XO_efdtstlt = 765,                        
00376     PPC_XO_efdtsteq = 766,                        
00378     // Double Convert From Integer
00379 
00380     PPC_XO_efdcfsi = 753,                         
00381     PPC_XO_efdcfui = 752,                         
00383     // Double Convert From Integer Doubleword
00384 
00385     PPC_XO_efdcfsid = 739,                        
00386     PPC_XO_efdcfuid = 738,                        
00388     // Double Convert From Fraction
00389 
00390     PPC_XO_efdcfsf = 755,                         
00391     PPC_XO_efdcfuf = 754,                         
00393     // Double Convert To Integer
00394 
00395     PPC_XO_efdctsi = 757,                         
00396     PPC_XO_efdctui = 756,                         
00398     // Double Convert To Integer Doubleword Zero Rounded
00399 
00400     PPC_XO_efdctsidz = 747,                       
00401     PPC_XO_efdctuidz = 746,                       
00403     // Double Convert To Integer Zero Rounded
00404 
00405     PPC_XO_efdctsiz = 762,                        
00406     PPC_XO_efdctuiz = 760,                        
00408     // Double Convert To Fraction
00409 
00410     PPC_XO_efdctsf = 759,                         
00411     PPC_XO_efdctuf = 758,                         
00413     // Double Convert From Single
00414 
00415     PPC_XO_efdcfs = 751,                          
00417     // Single Convert From Double
00418 
00419     PPC_XO_efscfd = 719                           
00421 } ppc_xo_type;
00422 
00425 typedef uint32_t q31;
00426 
00429 typedef uint32_t uq32;
00430 
00431 /*****************************************************************************
00432  * LOCAL PROTOTYPES
00433  ****************************************************************************/
00434 
00435 static inline appenv_type *getappenv(void *const *const pdata);
00436 static inline run_options *getsfenv(void *const *const pdata);
00437 static inline uint32_t msb32(const uint32_t v);
00438 static inline uint32_t float32_sign(const float32 f);
00439 static inline uint32_t float32_biased_exp(const float32 f);
00440 static inline uint32_t float32_fraction(const float32 f);
00441 static inline flag float32_is_neg(const float32 f);
00442 static inline flag float32_is_infnan(const float32 f);
00443 static inline float32 float32_abs(const float32 f);
00444 static inline flag float32_gt(const float32 a, const float32 b, run_options *const e);
00445 static inline flag float32_gt_quiet(const float32 a, const float32 b, run_options *const e);
00446 static inline float32 float32_mul_pow2(const float32 f, const int pow2);
00447 static inline uint64_t msb64(const uint64_t v);
00448 static inline uint64_t float64_sign(const float64 f);
00449 static inline uint64_t float64_biased_exp(const float64 f);
00450 static inline uint64_t float64_fraction(const float64 f);
00451 static inline flag float64_is_neg(const float64 f);
00452 static inline flag float64_is_infnan(const float64 f);
00453 static inline float64 float64_abs(const float64 f);
00454 static inline flag float64_gt(const float64 a, const float64 b, run_options *const e);
00455 static inline flag float64_gt_quiet(const float64 a, const float64 b, run_options *const e);
00456 static inline float64 float64_mul_pow2(const float64 f, const int pow2);
00457 static inline int64 float64_to_int64_round_to_zero(const float64 f, run_options *const e);
00458 static inline float32 uint32_to_float32(const uint32 v, run_options *const e);
00459 static inline float64 uint32_to_float64(const uint32 v, run_options *const e);
00460 static uint32 float32_to_uint32(const float32 f, run_options *const e);
00461 static inline uint32 float32_to_uint32_round_to_zero(const float32 f, run_options *const e);
00462 static uint32 float64_to_uint32(const float64 f, run_options *const e);
00463 static inline uint32 float64_to_uint32_round_to_zero(const float64 f, run_options *const e);
00464 static inline float64 uint64_to_float64(const uint64 v, run_options *const e);
00465 static uint64 float64_to_uint64_round_to_zero(const float64 f, run_options *const e);
00466 static inline float32 q31_to_float32(const q31 v, run_options *const e);
00467 static inline float64 q31_to_float64(const q31 v, run_options *const e);
00468 static q31 float32_to_q31(const float32 f, run_options *const e);
00469 static q31 float64_to_q31(const float64 f, run_options *const e);
00470 static inline float32 uq32_to_float32(const uq32 v, run_options *const e);
00471 static inline float64 uq32_to_float64(const uq32 v, run_options *const e);
00472 static uq32 float32_to_uq32(const float32 f, run_options *const e);
00473 static uint64 float64_to_uq32(const float64 f, run_options *const e);
00474 static inline float32 load32(const PPC_CPU_REGISTERS *const regs, const unsigned n);
00475 static inline void store32(PPC_CPU_REGISTERS *const regs, const unsigned n, const float32 v);
00476 static float32 loadh32(const PPC_CPU_REGISTERS *const regs __attribute__ ((unused )), const unsigned n);
00477 static void storeh32(PPC_CPU_REGISTERS *const regs __attribute__ ((unused )), const unsigned n, const float32 v);
00478 static float64 load64(const PPC_CPU_REGISTERS *const regs, const unsigned n);
00479 static void store64(PPC_CPU_REGISTERS *const regs, const unsigned n, const float64 v);
00480 
00481 /*****************************************************************************
00482  * FUNCTIONS
00483  ****************************************************************************/
00484 
00641 int
00642 _math_emulator(
00643       const int                         sigcode,
00644       void ** const                     pdata,
00645       PPC_CPU_REGISTERS * const         regs )
00646 {
00647 
00648     int result = sigcode;
00649     appenv_type * ctx = NULL;
00650     uint32_t spefscr;
00651     union ppc_instr op;
00652     bool exclo, exchi, roundonly;
00653     flag float_rounding_mode;
00654     int sfidx = 0;
00655     run_options sfopts[2];
00656     run_options * sfenv = NULL;
00657     run_options * sfenvlo = NULL;
00658     run_options * sfenvhi = NULL;
00659     float32 t32, a32, b32;
00660     float32 th32, ah32, bh32;
00661     float64 t64, a64, b64;
00662     int cmp = 0, cmphi = 0;
00663 
00664     assert(NULL != pdata);
00665     assert(NULL != regs);
00666 
00667     DPRINTF(">>>>>>>>>>>>>>>>>>>> ENTER\n");
00668     DPRINTF("sigcode %08x\n", (uint32_t) sigcode);
00669     DPRINTF("pdata  0x%p\n", pdata);
00670     DPRINTF("*pdata 0x%p\n", *pdata);
00671     DPRINTF("regs   0x%p\n", regs);
00672 
00673     /* PR67571: E500v1 cores (e.g. MPC8555CDS) do not support double
00674      * precision embedded floating point instructions.  If an E500v2
00675      * SPE image is inadvertently installed on such a platform, the
00676      * following check provides active feedback for the exception
00677      * delivered by the CPU.  It also serves to catch any other
00678      * unexpected cases where the PPC kernel might try to dispatch
00679      * SIGILLs - emulation requests - to the fpassist library.
00680      * However this does, unfortunately, introduce code which handles
00681      * configuration errors into the main code path. */
00682 
00683     if (SIGFPE != SIGCODE_SIGNO(sigcode)) goto err_unsup;
00684 
00685     /*
00686      *    Get a context to maintain application softfloat env.
00687      */
00688 
00689     if (NULL != *pdata) {
00690 
00691         /* use existing context */
00692 
00693         ctx = getappenv(pdata);
00694 
00695         DPRINTF("ctx    0x%p\n", ctx);
00696 
00697     } else {
00698 
00699         /* allocate a new context */
00700 
00701         const size_t sz =
00702               sizeof(PPC_FPU_REGISTERS)
00703               + sizeof(run_options)
00704               + sizeof(appenv_type);
00705 
00706         *pdata = _smalloc(sz);
00707 
00708         if (NULL == *pdata) goto err_oom;
00709 
00710         memset(*pdata, '\0', sz);
00711 
00712         softfloat_env_init(getsfenv(pdata));
00713 
00714         ctx = getappenv(pdata);
00715 
00716         DPRINTF("ctx [new] %p\n", ctx);
00717 
00718         __asm__ volatile ("mfspefscr %0" : "=r" (ctx->spefscr));
00719 
00720         DPRINTF("mfspefscr %08x\n", ctx->spefscr);
00721 
00722     }
00723 
00724     assert(NULL != *pdata);
00725     assert(NULL != ctx);
00726 
00727     /*
00728      *    Set or get application exception flags and mask.
00729      */
00730 
00731     if (~0U == regs->iar) {
00732 
00733         switch (regs->u.usprg0) {
00734 
00735             case O_RDONLY:
00736 
00737                 __asm__ volatile ("mfspefscr %0" : "=r" (spefscr));
00738 
00739                 DPRINTF("mfspefscr %08x\n", spefscr);
00740 
00741                 spefscr &= ~SPEFSCR_ENABLE_EXC_MASK;
00742                 spefscr |= (ctx->spefscr & (SPEFSCR_ENABLE_EXC_MASK | SPEFSCR_STICKY_EXC_MASK));
00743 
00744                 regs->u2.spefscr = spefscr;
00745 
00746                 DPRINTF("O_RDONLY  %08x\n", regs->u2.spefscr);
00747 
00748                 goto ok_fpstatus;
00749 
00750             case O_WRONLY:
00751 
00752                 DPRINTF("O_WRONLY  %08x\n", regs->u2.spefscr);
00753 
00754                 ctx->spefscr = spefscr = (uint32_t) regs->u2.spefscr;
00755 
00756                 spefscr |= SPEFSCR_NEEDED_EXC_MASK;
00757 
00758                 DPRINTF("mtspefscr %08x\n", spefscr);
00759 
00760                 __asm__ volatile ("mtspefscr %0" : : "r" (spefscr));
00761 
00762                 goto ok_fpstatus;
00763 
00764             default:
00765 
00766                 goto err_fpstatus;
00767 
00768         }
00769 
00770     }
00771 
00772     /*
00773      *    Examine the SPEFSCR to check the exception type and rounding
00774      *    mode.
00775      */
00776 
00777     spefscr = (uint32_t) regs->u2.spefscr;
00778 
00779     DPRINTF("spefscr %08x\n", spefscr);
00780 
00781     exclo = (0 != (spefscr & SPEFSCR_VECT_LO_EXC_MASK));
00782     exchi = (0 != (spefscr & SPEFSCR_VECT_HI_EXC_MASK));
00783 
00784     switch (spefscr & PPCBKE_APU_SPE_SPEFSCR_FRMC_MASK) {
00785         case PPCBKE_APU_SPE_SPEFSCR_FRMC_NEAR:
00786             float_rounding_mode = float_round_nearest_even;
00787             break;
00788         case PPCBKE_APU_SPE_SPEFSCR_FRMC_ZERO:
00789             float_rounding_mode = float_round_to_zero;
00790             break;
00791         case PPCBKE_APU_SPE_SPEFSCR_FRMC_PINF:
00792             float_rounding_mode = float_round_up;
00793             break;
00794         case PPCBKE_APU_SPE_SPEFSCR_FRMC_NINF:
00795             float_rounding_mode = float_round_down;
00796             break;
00797     }
00798 
00799     roundonly = !exclo && !exchi && (FPE_FLTRES == SIGCODE_CODE(sigcode));
00800 
00801     assert((exclo || exchi || roundonly) && "no exception indicated");
00802 
00803     /*
00804      *    Check the primary opcode.
00805      *    (All EFP opcodes have primary opcode 4.)
00806      */
00807 
00808     DPRINTF("regs->iar 0x%p\n", (uint32_t *) regs->iar);
00809 
00810     op.op_code = (*(uint32_t *)regs->iar);
00811 
00812     DPRINTF("op.op_code %08x\n", op.op_code);
00813     DPRINTF("op.evx_t.op %u\n", op.evx_t.op);
00814     DPRINTF("op.evx_t.xo %u\n", op.evx_t.xo);
00815 
00816     if (4 != op.evx_t.op) goto err_unsup;
00817 
00818     /*
00819      *    Validate the operation and allocate sufficient softfloat
00820      *    environments.
00821      */
00822 
00823     switch ((ppc_xo_type) op.evx_t.xo) {
00824 
00825         // Vector operations
00826 
00827         case PPC_XO_evfsadd:
00828         case PPC_XO_evfssub:
00829         case PPC_XO_evfsmul:
00830         case PPC_XO_evfsdiv:
00831 
00832         case PPC_XO_evfscmpgt:
00833         case PPC_XO_evfscmplt:
00834         case PPC_XO_evfscmpeq:
00835 
00836         case PPC_XO_evfststgt:
00837         case PPC_XO_evfststlt:
00838         case PPC_XO_evfststeq:
00839 
00840         case PPC_XO_evfscfsf:
00841         case PPC_XO_evfscfuf:
00842 
00843         case PPC_XO_evfscfsi:
00844         case PPC_XO_evfscfui:
00845 
00846         case PPC_XO_evfsctsf:
00847         case PPC_XO_evfsctuf:
00848 
00849         case PPC_XO_evfsctsi:
00850         case PPC_XO_evfsctui:
00851 
00852         case PPC_XO_evfsctsiz:
00853         case PPC_XO_evfsctuiz:
00854 
00855             DPRINTF("vector op\n");
00856 
00857             if (exclo || roundonly) {
00858 
00859                 sfenvlo = & sfopts[sfidx++];
00860 
00861                 DPRINTF("sfenvlo\n");
00862 
00863             }
00864 
00865             if (exchi || roundonly) {
00866 
00867                 sfenvhi = & sfopts[sfidx++];
00868 
00869                 DPRINTF("sfenvhi\n");
00870 
00871             }
00872 
00873             assert((sfenvlo || sfenvhi) && "unexpected vector no-op");
00874 
00875             break;
00876 
00877         // Non-vector operations
00878 
00879         case PPC_XO_efsadd:
00880         case PPC_XO_efssub:
00881         case PPC_XO_efsmul:
00882         case PPC_XO_efsdiv:
00883 
00884         case PPC_XO_efscmpgt:
00885         case PPC_XO_efscmplt:
00886         case PPC_XO_efscmpeq:
00887 
00888         case PPC_XO_efststgt:
00889         case PPC_XO_efststlt:
00890         case PPC_XO_efststeq:
00891 
00892         case PPC_XO_efscfsf:
00893         case PPC_XO_efscfuf:
00894 
00895         case PPC_XO_efscfsi:
00896         case PPC_XO_efscfui:
00897 
00898         case PPC_XO_efsctsf:
00899         case PPC_XO_efsctuf:
00900 
00901         case PPC_XO_efsctsi:
00902         case PPC_XO_efsctui:
00903 
00904         case PPC_XO_efsctsiz:
00905         case PPC_XO_efsctuiz:
00906 
00907         case PPC_XO_efdadd:
00908         case PPC_XO_efdsub:
00909         case PPC_XO_efdmul:
00910         case PPC_XO_efddiv:
00911 
00912         case PPC_XO_efdcmpgt:
00913         case PPC_XO_efdcmplt:
00914         case PPC_XO_efdcmpeq:
00915 
00916         case PPC_XO_efdtstgt:
00917         case PPC_XO_efdtstlt:
00918         case PPC_XO_efdtsteq:
00919 
00920         case PPC_XO_efdcfsf:
00921         case PPC_XO_efdcfuf:
00922 
00923         case PPC_XO_efdcfsi:
00924         case PPC_XO_efdcfui:
00925 
00926         case PPC_XO_efdcfsid:
00927         case PPC_XO_efdcfuid:
00928 
00929         case PPC_XO_efdctsf:
00930         case PPC_XO_efdctuf:
00931 
00932         case PPC_XO_efdctsi:
00933         case PPC_XO_efdctui:
00934 
00935         case PPC_XO_efdctsidz:
00936         case PPC_XO_efdctuidz:
00937 
00938         case PPC_XO_efdctsiz:
00939         case PPC_XO_efdctuiz:
00940 
00941         case PPC_XO_efdcfs:
00942         case PPC_XO_efscfd:
00943 
00944             DPRINTF("non-vector op\n");
00945 
00946             if (exclo || roundonly) {
00947 
00948                 sfenv = & sfopts[sfidx++];
00949 
00950                 DPRINTF("sfenv\n");
00951 
00952             }
00953 
00954             assert(sfenv && "unexpected non-vector no-op");
00955 
00956             assert(!exchi && "unexpected hi-word exception");
00957 
00958             break;
00959 
00960         // Non-rounded operations
00961 
00962         case PPC_XO_evfsabs:
00963         case PPC_XO_evfsnabs:
00964         case PPC_XO_evfsneg:
00965 
00966         case PPC_XO_efsabs:
00967         case PPC_XO_efsnabs:
00968         case PPC_XO_efsneg:
00969 
00970         case PPC_XO_efdabs:
00971         case PPC_XO_efdnabs:
00972         case PPC_XO_efdneg:
00973 
00974             /* None of these opcodes is supposed to generate any data
00975              * exceptions; however if the rounding mode is +inf/-inf,
00976              * the rounding exception is delivered unconditionally
00977              * after the result has been computed, even though the
00978              * rounding mode is not relevant to the result. */
00979 
00980             assert(roundonly && "unexpected exception");
00981 
00982             break;
00983 
00984         // Unsupported operations
00985 
00986         default:
00987 
00988             goto err_unsup;
00989 
00990     }
00991 
00992     /*
00993      *    Initialize the required softfloat envs appropriately.
00994      */
00995 
00996     if (sfidx > 0) {
00997 
00998         int i;
00999 
01000         assert((size_t) sfidx <= NELEM(sfopts));
01001 
01002         for (i = 0; i < sfidx; ++i) {
01003 
01004             softfloat_env_init(& sfopts[i]);
01005 
01006             sfopts[i].float_rounding_mode = float_rounding_mode;
01007 
01008         }
01009 
01010     } else {
01011 
01012         DPRINTF("no emulation needed\n");
01013 
01014         goto done;
01015 
01016     }
01017 
01018     /*
01019      *    Extract operands from extended opcode.
01020      */
01021 
01022     switch ((ppc_xo_type) op.evx_t.xo) {
01023 
01024         // Vector Arithmetic
01025 
01026         case PPC_XO_evfsadd:
01027         case PPC_XO_evfssub:
01028         case PPC_XO_evfsmul:
01029         case PPC_XO_evfsdiv:
01030 
01031         // Vector Compare
01032 
01033         case PPC_XO_evfscmpgt:
01034         case PPC_XO_evfscmplt:
01035         case PPC_XO_evfscmpeq:
01036 
01037         // Vector Test
01038 
01039         case PPC_XO_evfststgt:
01040         case PPC_XO_evfststlt:
01041         case PPC_XO_evfststeq:
01042 
01043             if (NULL != sfenvlo) {
01044 
01045                 a32 = load32(regs, op.evx_t.a);
01046 
01047             }
01048 
01049             if (NULL != sfenvhi) {
01050 
01051                 ah32 = loadh32(regs, op.evx_t.a);
01052 
01053             }
01054 
01055             /*FALLTHRU*/
01056 
01057         // Vector Convert From Integer
01058 
01059         case PPC_XO_evfscfsi:
01060         case PPC_XO_evfscfui:
01061 
01062         // Vector Convert From Fraction
01063 
01064         case PPC_XO_evfscfsf:
01065         case PPC_XO_evfscfuf:
01066 
01067         // Vector Convert To Integer
01068 
01069         case PPC_XO_evfsctsi:
01070         case PPC_XO_evfsctui:
01071 
01072         // Vector Convert To Integer Zero Rounded
01073 
01074         case PPC_XO_evfsctsiz:
01075         case PPC_XO_evfsctuiz:
01076 
01077         // Vector Convert To Fraction
01078 
01079         case PPC_XO_evfsctsf:
01080         case PPC_XO_evfsctuf:
01081 
01082             if (NULL != sfenvlo) {
01083 
01084                 b32 = load32(regs, op.evx_t.b);
01085 
01086             }
01087 
01088             if (NULL != sfenvhi) {
01089 
01090                 bh32 = loadh32(regs, op.evx_t.b);
01091 
01092             }
01093 
01094             break;
01095 
01096         // Single Arithmetic
01097 
01098         case PPC_XO_efsadd:
01099         case PPC_XO_efssub:
01100         case PPC_XO_efsmul:
01101         case PPC_XO_efsdiv:
01102 
01103         // Single Compare
01104 
01105         case PPC_XO_efscmpgt:
01106         case PPC_XO_efscmplt:
01107         case PPC_XO_efscmpeq:
01108 
01109         // Single Test
01110 
01111         case PPC_XO_efststgt:
01112         case PPC_XO_efststlt:
01113         case PPC_XO_efststeq:
01114 
01115             a32 = load32(regs, op.evx_t.a);
01116 
01117             /*FALLTHRU*/
01118 
01119         // Single Convert From Integer
01120 
01121         case PPC_XO_efscfsi:
01122         case PPC_XO_efscfui:
01123 
01124         // Single Convert From Fraction
01125 
01126         case PPC_XO_efscfsf:
01127         case PPC_XO_efscfuf:
01128 
01129         // Single Convert To Integer
01130 
01131         case PPC_XO_efsctsi:
01132         case PPC_XO_efsctui:
01133 
01134         // Single Convert To Integer Zero Rounded
01135 
01136         case PPC_XO_efsctsiz:
01137         case PPC_XO_efsctuiz:
01138 
01139         // Single Convert To Fraction
01140 
01141         case PPC_XO_efsctsf:
01142         case PPC_XO_efsctuf:
01143 
01144         // Double Convert From Integer
01145 
01146         case PPC_XO_efdcfsi:
01147         case PPC_XO_efdcfui:
01148 
01149         // Double Convert From Fraction
01150 
01151         case PPC_XO_efdcfsf:
01152         case PPC_XO_efdcfuf:
01153 
01154         // Double Convert From Single
01155 
01156         case PPC_XO_efdcfs:
01157 
01158             b32 = load32(regs, op.evx_t.b);
01159 
01160             break;
01161 
01162         // Double Arithmetic
01163 
01164         case PPC_XO_efdadd:
01165         case PPC_XO_efdsub:
01166         case PPC_XO_efdmul:
01167         case PPC_XO_efddiv:
01168 
01169         // Double Compare
01170 
01171         case PPC_XO_efdcmpgt:
01172         case PPC_XO_efdcmplt:
01173         case PPC_XO_efdcmpeq:
01174 
01175         // Double Test
01176 
01177         case PPC_XO_efdtstgt:
01178         case PPC_XO_efdtstlt:
01179         case PPC_XO_efdtsteq:
01180 
01181             a64 = load64(regs, op.evx_t.a);
01182 
01183             /*FALLTHRU*/
01184 
01185         // Double Convert From Integer Doubleword
01186 
01187         case PPC_XO_efdcfsid:
01188         case PPC_XO_efdcfuid:
01189 
01190         // Double Convert To Integer
01191 
01192         case PPC_XO_efdctsi:
01193         case PPC_XO_efdctui:
01194 
01195         // Double Convert To Integer Doubleword Zero Rounded
01196 
01197         case PPC_XO_efdctsidz:
01198         case PPC_XO_efdctuidz:
01199 
01200         // Double Convert To Integer Zero Rounded
01201 
01202         case PPC_XO_efdctsiz:
01203         case PPC_XO_efdctuiz:
01204 
01205         // Double Convert To Fraction
01206 
01207         case PPC_XO_efdctsf:
01208         case PPC_XO_efdctuf:
01209 
01210         // Single Convert From Double
01211 
01212         case PPC_XO_efscfd:
01213 
01214             b64 = load64(regs, op.evx_t.b);
01215 
01216             break;
01217 
01218         // Vector Monadic
01219 
01220         case PPC_XO_evfsabs:
01221         case PPC_XO_evfsnabs:
01222         case PPC_XO_evfsneg:
01223 
01224         // Single Monadic
01225 
01226         case PPC_XO_efsabs:
01227         case PPC_XO_efsnabs:
01228         case PPC_XO_efsneg:
01229 
01230         // Double Monadic
01231 
01232         case PPC_XO_efdabs:
01233         case PPC_XO_efdnabs:
01234         case PPC_XO_efdneg:
01235 
01236             break;
01237 
01238     }
01239 
01240     DPRINTF("a64  %016llx\n", a64);
01241     DPRINTF("b64  %016llx\n", b64);
01242     DPRINTF("a32  %08x\n", a32);
01243     DPRINTF("b32  %08x\n", b32);
01244     DPRINTF("ah32 %08x\n", ah32);
01245     DPRINTF("bh32 %08x\n", bh32);
01246 
01247     /*
01248      *    Emulate operation using softfloat.
01249      */
01250 
01251     switch ((ppc_xo_type) op.evx_t.xo) {
01252 
01253         // Vector Arithmetic
01254 
01255         case PPC_XO_evfsadd:
01256 
01257             if (NULL != sfenvlo) {
01258 
01259                 t32 = float32_add(a32, b32, sfenvlo);
01260 
01261             }
01262 
01263             if (NULL != sfenvhi) {
01264 
01265                 th32 = float32_add(ah32, bh32, sfenvhi);
01266 
01267             }
01268 
01269             break;
01270 
01271         case PPC_XO_evfssub:
01272 
01273             if (NULL != sfenvlo) {
01274 
01275                 t32 = float32_sub(a32, b32, sfenvlo);
01276 
01277             }
01278 
01279             if (NULL != sfenvhi) {
01280 
01281                 th32 = float32_sub(ah32, bh32, sfenvhi);
01282 
01283             }
01284 
01285             break;
01286 
01287         case PPC_XO_evfsmul:
01288 
01289             if (NULL != sfenvlo) {
01290 
01291                 t32 = float32_mul(a32, b32, sfenvlo);
01292 
01293             }
01294 
01295             if (NULL != sfenvhi) {
01296 
01297                 th32 = float32_mul(ah32, bh32, sfenvhi);
01298 
01299             }
01300 
01301             break;
01302 
01303         case PPC_XO_evfsdiv:
01304 
01305             if (NULL != sfenvlo) {
01306 
01307                 t32 = float32_div(a32, b32, sfenvlo);
01308 
01309             }
01310 
01311             if (NULL != sfenvhi) {
01312 
01313                 th32 = float32_div(ah32, bh32, sfenvhi);
01314 
01315             }
01316 
01317             break;
01318 
01319         // Vector Compare
01320 
01321         case PPC_XO_evfscmpgt:
01322 
01323             if (NULL != sfenvlo) {
01324 
01325                 cmp = float32_gt(a32, b32, sfenvlo);
01326 
01327             }
01328 
01329             if (NULL != sfenvhi) {
01330 
01331                 cmphi = float32_gt(ah32, bh32, sfenvhi);
01332 
01333             }
01334 
01335             break;
01336 
01337         case PPC_XO_evfscmplt:
01338 
01339             if (NULL != sfenvlo) {
01340 
01341                 cmp = float32_lt(a32, b32, sfenvlo);
01342 
01343             }
01344 
01345             if (NULL != sfenvhi) {
01346 
01347                 cmphi = float32_lt(ah32, bh32, sfenvhi);
01348 
01349             }
01350 
01351             break;
01352 
01353         case PPC_XO_evfscmpeq:
01354 
01355             if (NULL != sfenvlo) {
01356 
01357                 cmp = float32_eq_signaling(a32, b32, sfenvlo);
01358 
01359             }
01360 
01361             if (NULL != sfenvhi) {
01362 
01363                 cmphi = float32_eq_signaling(ah32, bh32, sfenvhi);
01364 
01365             }
01366 
01367             break;
01368 
01369         // Vector Test
01370 
01371         case PPC_XO_evfststgt:
01372 
01373             if (NULL != sfenvlo) {
01374 
01375                 cmp = float32_gt_quiet(a32, b32, sfenvlo);
01376 
01377             }
01378 
01379             if (NULL != sfenvhi) {
01380 
01381                 cmphi = float32_gt_quiet(ah32, bh32, sfenvhi);
01382 
01383             }
01384 
01385             break;
01386 
01387         case PPC_XO_evfststlt:
01388 
01389             if (NULL != sfenvlo) {
01390 
01391                 cmp = float32_lt_quiet(a32, b32, sfenvlo);
01392 
01393             }
01394 
01395             if (NULL != sfenvhi) {
01396 
01397                 cmphi = float32_lt_quiet(ah32, bh32, sfenvhi);
01398 
01399             }
01400 
01401             break;
01402 
01403         case PPC_XO_evfststeq:
01404 
01405             if (NULL != sfenvlo) {
01406 
01407                 cmp = float32_eq(a32, b32, sfenvlo);
01408 
01409             }
01410 
01411             if (NULL != sfenvhi) {
01412 
01413                 cmphi = float32_eq(ah32, bh32, sfenvhi);
01414 
01415             }
01416 
01417             break;
01418 
01419         // Vector Convert From Integer
01420 
01421         case PPC_XO_evfscfsi:
01422 
01423             if (NULL != sfenvlo) {
01424 
01425                 t32 = int32_to_float32(b32, sfenvlo);
01426 
01427             }
01428 
01429             if (NULL != sfenvhi) {
01430 
01431                 th32 = int32_to_float32(bh32, sfenvhi);
01432 
01433             }
01434 
01435             break;
01436 
01437         case PPC_XO_evfscfui:
01438 
01439             if (NULL != sfenvlo) {
01440 
01441                 t32 = uint32_to_float32(b32, sfenvlo);
01442 
01443             }
01444 
01445             if (NULL != sfenvhi) {
01446 
01447                 th32 = uint32_to_float32(bh32, sfenvhi);
01448 
01449             }
01450 
01451             break;
01452 
01453         // Vector Convert From Fraction
01454 
01455         case PPC_XO_evfscfsf:
01456 
01457             if (NULL != sfenvlo) {
01458 
01459                 t32 = q31_to_float32(b32, sfenvlo);
01460 
01461             }
01462 
01463             if (NULL != sfenvhi) {
01464 
01465                 th32 = q31_to_float32(bh32, sfenvhi);
01466 
01467             }
01468 
01469             break;
01470 
01471         case PPC_XO_evfscfuf:
01472 
01473             if (NULL != sfenvlo) {
01474 
01475                 t32 = uq32_to_float32(b32, sfenvlo);
01476 
01477             }
01478 
01479             if (NULL != sfenvhi) {
01480 
01481                 th32 = uq32_to_float32(bh32, sfenvhi);
01482 
01483             }
01484 
01485             break;
01486 
01487         // Vector Convert To Integer Zero Rounded
01488 
01489         case PPC_XO_evfsctsiz:
01490 
01491             if (NULL != sfenvlo) {
01492 
01493                 t32 = float32_to_int32_round_to_zero(b32, sfenvlo);
01494 
01495             }
01496 
01497             if (NULL != sfenvhi) {
01498 
01499                 th32 = float32_to_int32_round_to_zero(bh32, sfenvhi);
01500 
01501             }
01502 
01503             break;
01504 
01505         case PPC_XO_evfsctuiz:
01506 
01507             if (NULL != sfenvlo) {
01508 
01509                 t32 = float32_to_uint32_round_to_zero(b32, sfenvlo);
01510 
01511             }
01512 
01513             if (NULL != sfenvhi) {
01514 
01515                 th32 = float32_to_uint32_round_to_zero(bh32, sfenvhi);
01516 
01517             }
01518 
01519             break;
01520 
01521         // Vector Convert To Integer
01522 
01523         case PPC_XO_evfsctsi:
01524 
01525             if (NULL != sfenvlo) {
01526 
01527                 t32 = float32_to_int32(b32, sfenvlo);
01528 
01529             }
01530 
01531             if (NULL != sfenvhi) {
01532 
01533                 th32 = float32_to_int32(bh32, sfenvhi);
01534 
01535             }
01536 
01537             break;
01538 
01539         case PPC_XO_evfsctui:
01540 
01541             if (NULL != sfenvlo) {
01542 
01543                 t32 = float32_to_uint32(b32, sfenvlo);
01544 
01545             }
01546 
01547             if (NULL != sfenvhi) {
01548 
01549                 th32 = float32_to_uint32(bh32, sfenvhi);
01550 
01551             }
01552 
01553             break;
01554 
01555         // Vector Convert To Fraction
01556 
01557         case PPC_XO_evfsctsf:
01558 
01559             if (NULL != sfenvlo) {
01560 
01561                 t32 = float32_to_q31(b32, sfenvlo);
01562 
01563             }
01564 
01565             if (NULL != sfenvhi) {
01566 
01567                 th32 = float32_to_q31(bh32, sfenvhi);
01568 
01569             }
01570 
01571             break;
01572 
01573         case PPC_XO_evfsctuf:
01574 
01575             if (NULL != sfenvlo) {
01576 
01577                 t32 = float32_to_uq32(b32, sfenvlo);
01578 
01579             }
01580 
01581             if (NULL != sfenvhi) {
01582 
01583                 th32 = float32_to_uq32(bh32, sfenvhi);
01584 
01585             }
01586 
01587             break;
01588 
01589         // Single Arithmetic
01590 
01591         case PPC_XO_efsadd:
01592 
01593             t32 = float32_add(a32, b32, sfenv);
01594 
01595             break;
01596 
01597         case PPC_XO_efssub:
01598 
01599             t32 = float32_sub(a32, b32, sfenv);
01600 
01601             break;
01602 
01603         case PPC_XO_efsmul:
01604 
01605             t32 = float32_mul(a32, b32, sfenv);
01606 
01607             break;
01608 
01609         case PPC_XO_efsdiv:
01610 
01611             t32 = float32_div(a32, b32, sfenv);
01612 
01613             break;
01614 
01615         // Single Compare
01616 
01617         case PPC_XO_efscmpgt:
01618 
01619             cmp = float32_gt(a32, b32, sfenv);
01620 
01621             break;
01622 
01623         case PPC_XO_efscmplt:
01624 
01625             cmp = float32_lt(a32, b32, sfenv);
01626 
01627             break;
01628 
01629         case PPC_XO_efscmpeq:
01630 
01631             cmp = float32_eq_signaling(a32, b32, sfenv);
01632 
01633             break;
01634 
01635         // Single Test
01636 
01637         case PPC_XO_efststgt:
01638 
01639             cmp = float32_gt_quiet(a32, b32, sfenv);
01640 
01641             break;
01642 
01643         case PPC_XO_efststlt:
01644 
01645             cmp = float32_lt_quiet(a32, b32, sfenv);
01646 
01647             break;
01648 
01649         case PPC_XO_efststeq:
01650 
01651             cmp = float32_eq(a32, b32, sfenv);
01652 
01653             break;
01654 
01655         // Single Convert To Integer Zero Rounded
01656 
01657         case PPC_XO_efsctsiz:
01658 
01659             t32 = float32_to_int32_round_to_zero(b32, sfenv);
01660 
01661             break;
01662 
01663         case PPC_XO_efsctuiz:
01664 
01665             t32 = float32_to_uint32_round_to_zero(b32, sfenv);
01666 
01667             break;
01668 
01669         // Single Convert From Integer
01670 
01671         case PPC_XO_efscfsi:
01672 
01673             t32 = int32_to_float32(b32, sfenv);
01674 
01675             break;
01676 
01677         case PPC_XO_efscfui:
01678 
01679             t32 = uint32_to_float32(b32, sfenv);
01680 
01681             break;
01682 
01683         // Single Convert From Fraction
01684 
01685         case PPC_XO_efscfsf:
01686 
01687             t32 = q31_to_float32(b32, sfenv);
01688 
01689             break;
01690 
01691         case PPC_XO_efscfuf:
01692 
01693             t32 = uq32_to_float32(b32, sfenv);
01694 
01695             break;
01696 
01697         // Single Convert To Integer
01698 
01699         case PPC_XO_efsctsi:
01700 
01701             t32 = float32_to_int32(b32, sfenv);
01702 
01703             break;
01704 
01705         case PPC_XO_efsctui:
01706 
01707             t32 = float32_to_uint32(b32, sfenv);
01708 
01709             break;
01710 
01711         // Single Convert To Fraction
01712 
01713         case PPC_XO_efsctsf:
01714 
01715             t32 = float32_to_q31(b32, sfenv);
01716 
01717             break;
01718 
01719         case PPC_XO_efsctuf:
01720 
01721             t32 = float32_to_uq32(b32, sfenv);
01722 
01723             break;
01724 
01725         // Single Convert From Double
01726 
01727         case PPC_XO_efscfd:
01728 
01729             t32 = float64_to_float32(b64, sfenv);
01730 
01731             break;
01732 
01733         // Double Arithmetic
01734 
01735         case PPC_XO_efdadd:
01736 
01737             t64 = float64_add(a64, b64, sfenv);
01738 
01739             break;
01740 
01741         case PPC_XO_efdsub:
01742 
01743             t64 = float64_sub(a64, b64, sfenv);
01744 
01745             break;
01746 
01747         case PPC_XO_efdmul:
01748 
01749             t64 = float64_mul(a64, b64, sfenv);
01750 
01751             break;
01752 
01753         case PPC_XO_efddiv:
01754 
01755             t64 = float64_div(a64, b64, sfenv);
01756 
01757             break;
01758 
01759         // Double Compare
01760 
01761         case PPC_XO_efdcmpgt:
01762 
01763             cmp = float64_gt(a64, b64, sfenv);
01764 
01765             break;
01766 
01767         case PPC_XO_efdcmplt:
01768 
01769             cmp = float64_lt(a64, b64, sfenv);
01770 
01771             break;
01772 
01773         case PPC_XO_efdcmpeq:
01774 
01775             cmp = float64_eq_signaling(a64, b64, sfenv);
01776 
01777             break;
01778 
01779         // Double Test
01780 
01781         case PPC_XO_efdtstgt:
01782 
01783             cmp = float64_gt_quiet(a64, b64, sfenv);
01784 
01785             break;
01786 
01787         case PPC_XO_efdtstlt:
01788 
01789             cmp = float64_lt_quiet(a64, b64, sfenv);
01790 
01791             break;
01792 
01793         case PPC_XO_efdtsteq:
01794 
01795             cmp = float64_eq(a64, b64, sfenv);
01796 
01797             break;
01798 
01799         // Double Convert From Integer
01800 
01801         case PPC_XO_efdcfsi:
01802 
01803             t64 = int32_to_float64(b32, sfenv);
01804 
01805             break;
01806 
01807         case PPC_XO_efdcfui:
01808 
01809             t64 = uint32_to_float64(b32, sfenv);
01810 
01811             break;
01812 
01813         // Double Convert From Integer Doubleword
01814 
01815         case PPC_XO_efdcfsid:
01816 
01817             t64 = int64_to_float64(b64, sfenv);
01818 
01819             break;
01820 
01821         case PPC_XO_efdcfuid:
01822 
01823             t64 = uint64_to_float64(b64, sfenv);
01824 
01825             break;
01826 
01827         // Double Convert From Fraction
01828 
01829         case PPC_XO_efdcfsf:
01830 
01831             t64 = q31_to_float64(b32, sfenv);
01832 
01833             break;
01834 
01835         case PPC_XO_efdcfuf:
01836 
01837             t64 = uq32_to_float64(b32, sfenv);
01838 
01839             break;
01840 
01841         // Double Convert To Integer
01842 
01843         case PPC_XO_efdctsi:
01844 
01845             t32 = float64_to_int32(b64, sfenv);
01846 
01847             break;
01848 
01849         case PPC_XO_efdctui:
01850 
01851             t32 = float64_to_uint32(b64, sfenv);
01852 
01853             break;
01854 
01855         // Double Convert To Integer Doubleword Zero Rounded
01856 
01857         case PPC_XO_efdctsidz:
01858 
01859             t64 = float64_to_int64_round_to_zero(b64, sfenv);
01860 
01861             break;
01862 
01863         case PPC_XO_efdctuidz:
01864 
01865             t64 = float64_to_uint64_round_to_zero(b64, sfenv);
01866 
01867             break;
01868 
01869         // Double Convert To Integer Zero Rounded
01870 
01871         case PPC_XO_efdctsiz:
01872 
01873             t32 = float64_to_int32_round_to_zero(b64, sfenv);
01874 
01875             break;
01876 
01877         case PPC_XO_efdctuiz:
01878 
01879             t32 = float64_to_uint32_round_to_zero(b64, sfenv);
01880 
01881             break;
01882 
01883         // Double Convert To Fraction
01884 
01885         case PPC_XO_efdctsf:
01886 
01887             t32 = float64_to_q31(b64, sfenv);
01888 
01889             break;
01890 
01891         case PPC_XO_efdctuf:
01892 
01893             t32 = float64_to_uq32(b64, sfenv);
01894 
01895             break;
01896 
01897         // Double Convert From Single
01898 
01899         case PPC_XO_efdcfs:
01900 
01901             t64 = float32_to_float64(b32, sfenv);
01902 
01903             break;
01904 
01905         // Vector Monadic
01906 
01907         case PPC_XO_evfsabs:
01908         case PPC_XO_evfsnabs:
01909         case PPC_XO_evfsneg:
01910 
01911         // Single Monadic
01912 
01913         case PPC_XO_efsabs:
01914         case PPC_XO_efsnabs:
01915         case PPC_XO_efsneg:
01916 
01917         // Double Monadic
01918 
01919         case PPC_XO_efdabs:
01920         case PPC_XO_efdnabs:
01921         case PPC_XO_efdneg:
01922 
01923             break;
01924 
01925     }
01926 
01927     DPRINTF("t64  %016llx\n", t64);
01928     DPRINTF("t32  %08x\n", t32);
01929     DPRINTF("th32 %08x\n", th32);
01930     DPRINTF("cmp   %d\n", cmp);
01931     DPRINTF("cmphi %d\n", cmphi);
01932 
01933   done:
01934 
01935     /*
01936      *    Update SPEFSCR sticky flags and handle masking.
01937      */
01938 
01939     {
01940 
01941         flag flags = 0;
01942         uint32_t sticky = 0;
01943 
01944         if (NULL != sfenvhi || NULL != sfenvlo) {
01945 
01946             if (NULL != sfenvhi) flags |= sfenvhi->float_exception_flags;
01947             if (NULL != sfenvlo) flags |= sfenvlo->float_exception_flags;
01948 
01949         } else if (NULL != sfenv) {
01950 
01951             flags |= sfenv->float_exception_flags;
01952 
01953         } else {
01954 
01955             /* no emulation was done so use register sticky flags directly */
01956 
01957             sticky = (spefscr & SPEFSCR_STICKY_EXC_MASK);
01958 
01959         }
01960 
01961         if (0 != flags) {
01962 
01963             if (flags & float_flag_divbyzero) sticky |= PPCBKE_APU_SPE_SPEFSCR_FDBZS;
01964             if (flags & float_flag_inexact) sticky |= PPCBKE_APU_SPE_SPEFSCR_FINXS;
01965             if (flags & float_flag_invalid) sticky |= PPCBKE_APU_SPE_SPEFSCR_FINVS;
01966             if (flags & float_flag_overflow) sticky |= PPCBKE_APU_SPE_SPEFSCR_FOVFS;
01967             if (flags & float_flag_underflow) sticky |= PPCBKE_APU_SPE_SPEFSCR_FUNFS;
01968 
01969         }
01970 
01971         /* set the sticky flags in the app env */
01972 
01973         ctx->spefscr |= sticky;
01974 
01975         /* propagate the app sticky flags to the SPEFSCR register */
01976 
01977         regs->u2.spefscr = spefscr | (ctx->spefscr & SPEFSCR_STICKY_EXC_MASK);
01978 
01979         /* prevent signal delivery if no unmasked app exceptions occurred */
01980 
01981         if (!((ctx->spefscr & SPEFSCR_ENABLE_EXC_MASK) & (sticky >> SPEFSCR_STICKY_EXC_SHIFT))) {
01982 
01983             result = 0;
01984 
01985         }
01986 
01987         DPRINTF("flags             %08x\n", flags);
01988 
01989         DPRINTF("STICKY_MASK       %08x\n", SPEFSCR_STICKY_EXC_MASK);
01990         DPRINTF("ENABLE_MASK       %08x\n", SPEFSCR_ENABLE_EXC_MASK);
01991         DPRINTF("TRAP_SHIFT        %8d\n",  SPEFSCR_STICKY_EXC_SHIFT);
01992 
01993         DPRINTF("sticky            %08x\n", sticky);
01994         DPRINTF("ctx->spefscr      %08x\n", ctx->spefscr);
01995         DPRINTF("spefscr           %08x\n", spefscr);
01996         DPRINTF("regs->u2.spefscr  %08x\n", regs->u2.spefscr);
01997 
01998     }
01999 
02000     /*
02001      *    Store results, if any, and advance the IAR.
02002      *
02003      *    If no signal is being raised, or if this was a rounding
02004      *    exception, save the result(s) and advance the IAR.  (This is
02005      *    done for signalled rounding exceptions so that the signal
02006      *    handler gets the same IAR regardless of whether fpassist is
02007      *    active or not.)
02008      */
02009 
02010     if (0 == result || FPE_FLTRES == SIGCODE_CODE(sigcode)) {
02011 
02012         switch ((ppc_xo_type) op.evx_t.xo) {
02013 
02014             // Vector Arithmetic
02015 
02016             case PPC_XO_evfsadd:
02017             case PPC_XO_evfssub:
02018             case PPC_XO_evfsmul:
02019             case PPC_XO_evfsdiv:
02020 
02021                 // Vector Convert From Integer
02022 
02023             case PPC_XO_evfscfsi:
02024             case PPC_XO_evfscfui:
02025 
02026                 // Vector Convert From Fraction
02027 
02028             case PPC_XO_evfscfsf:
02029             case PPC_XO_evfscfuf:
02030 
02031                 // Vector Convert To Integer
02032 
02033             case PPC_XO_evfsctsi:
02034             case PPC_XO_evfsctui:
02035 
02036                 // Vector Convert To Integer Zero Rounded
02037 
02038             case PPC_XO_evfsctsiz:
02039             case PPC_XO_evfsctuiz:
02040 
02041                 // Vector Convert To Fraction
02042 
02043             case PPC_XO_evfsctsf:
02044             case PPC_XO_evfsctuf:
02045 
02046                 if (NULL != sfenvlo) {
02047 
02048                     store32(regs, op.evx_t.t, t32);
02049 
02050                 }
02051 
02052                 if (NULL != sfenvhi) {
02053 
02054                     storeh32(regs, op.evx_t.t, th32);
02055 
02056                 }
02057 
02058                 break;
02059 
02060                 // Single Arithmetic
02061 
02062             case PPC_XO_efsadd:
02063             case PPC_XO_efssub:
02064             case PPC_XO_efsmul:
02065             case PPC_XO_efsdiv:
02066 
02067                 // Single Convert From Integer
02068 
02069             case PPC_XO_efscfsi:
02070             case PPC_XO_efscfui:
02071 
02072                 // Single Convert From Fraction
02073 
02074             case PPC_XO_efscfsf:
02075             case PPC_XO_efscfuf:
02076 
02077                 // Single Convert To Integer
02078 
02079             case PPC_XO_efsctsi:
02080             case PPC_XO_efsctui:
02081 
02082                 // Single Convert To Integer Zero Rounded
02083 
02084             case PPC_XO_efsctsiz:
02085             case PPC_XO_efsctuiz:
02086 
02087                 // Single Convert To Fraction
02088 
02089             case PPC_XO_efsctsf:
02090             case PPC_XO_efsctuf:
02091 
02092                 // Single Convert From Double
02093 
02094             case PPC_XO_efscfd:
02095 
02096                 // Double Convert To Integer
02097 
02098             case PPC_XO_efdctsi:
02099             case PPC_XO_efdctui:
02100 
02101                 // Double Convert To Integer Zero Rounded
02102 
02103             case PPC_XO_efdctsiz:
02104             case PPC_XO_efdctuiz:
02105 
02106                 // Double Convert To Fraction
02107 
02108             case PPC_XO_efdctsf:
02109             case PPC_XO_efdctuf:
02110 
02111                 store32(regs, op.evx_t.t, t32);
02112 
02113                 break;
02114 
02115                 // Double Arithmetic
02116 
02117             case PPC_XO_efdadd:
02118             case PPC_XO_efdsub:
02119             case PPC_XO_efdmul:
02120             case PPC_XO_efddiv:
02121 
02122                 // Double Convert From Integer
02123 
02124             case PPC_XO_efdcfsi:
02125             case PPC_XO_efdcfui:
02126 
02127                 // Double Convert From Integer Doubleword
02128 
02129             case PPC_XO_efdcfsid:
02130             case PPC_XO_efdcfuid:
02131 
02132                 // Double Convert From Fraction
02133 
02134             case PPC_XO_efdcfsf:
02135             case PPC_XO_efdcfuf:
02136 
02137                 // Double Convert To Integer Doubleword Zero Rounded
02138 
02139             case PPC_XO_efdctsidz:
02140             case PPC_XO_efdctuidz:
02141 
02142                 // Double Convert From Single
02143 
02144             case PPC_XO_efdcfs:
02145 
02146                 store64(regs, op.evx_t.t, t64);
02147 
02148                 break;
02149 
02150                 // Vector Test
02151 
02152             case PPC_XO_evfststgt:
02153             case PPC_XO_evfststlt:
02154             case PPC_XO_evfststeq:
02155 
02156                 // Single Test
02157 
02158             case PPC_XO_efststgt:
02159             case PPC_XO_efststlt:
02160             case PPC_XO_efststeq:
02161 
02162                 // Double Test
02163 
02164             case PPC_XO_efdtstgt:
02165             case PPC_XO_efdtstlt:
02166             case PPC_XO_efdtsteq:
02167 
02168                 // Vector Compare
02169 
02170             case PPC_XO_evfscmpgt:
02171             case PPC_XO_evfscmplt:
02172             case PPC_XO_evfscmpeq:
02173 
02174                 // Single Compare
02175 
02176             case PPC_XO_efscmpgt:
02177             case PPC_XO_efscmplt:
02178             case PPC_XO_efscmpeq:
02179 
02180                 // Double Compare
02181 
02182             case PPC_XO_efdcmpgt:
02183             case PPC_XO_efdcmplt:
02184             case PPC_XO_efdcmpeq:
02185 
02186                 {
02187 
02188                     uint32_t cr = (uint32_t) regs->cr;
02189                     uint32_t field;
02190 
02191                     if (cmphi && cmp) {
02192                         field = UINT32_C(0xf);
02193                     } else if (cmphi) {
02194                         field = UINT32_C(0xa);
02195                     } else if (cmp) {
02196                         field = UINT32_C(0x6);
02197                     } else {
02198                         field = UINT32_C(0x0);
02199                     }
02200 
02201                     cr &= ~(UINT32_C(0xf) << ((7 - op.evx_bf_t.bf) * 4));
02202                     cr |=  (field         << ((7 - op.evx_bf_t.bf) * 4));
02203 
02204                     DPRINTF("regs->cr %08x\n", regs->cr);
02205                     DPRINTF("cr       %08x\n", cr);
02206 
02207                     regs->cr = cr;
02208 
02209                 }
02210 
02211                 break;
02212 
02213                 // Vector Monadic
02214 
02215             case PPC_XO_evfsabs:
02216             case PPC_XO_evfsnabs:
02217             case PPC_XO_evfsneg:
02218 
02219                 // Single Monadic
02220 
02221             case PPC_XO_efsabs:
02222             case PPC_XO_efsnabs:
02223             case PPC_XO_efsneg:
02224 
02225                 // Double Monadic
02226 
02227             case PPC_XO_efdabs:
02228             case PPC_XO_efdnabs:
02229             case PPC_XO_efdneg:
02230 
02231                 break;
02232 
02233         }
02234 
02235         /*
02236          *    Advance IAR.
02237          */
02238 
02239         regs->iar += sizeof(op);
02240 
02241     }
02242 
02243     DPRINTF("<<<<<<<<<<<<<<<<<<<< EXIT %08x\n", (uint32_t) result);
02244 
02245     return result;
02246 
02247   err_unsup:
02248 
02249     DPRINTF("<<<<<<<<<<<<<<<<<<<< EXIT err_unsup\n");
02250 
02251     return result;
02252 
02253   err_oom:
02254 
02255     DPRINTF("<<<<<<<<<<<<<<<<<<<< EXIT err_oom\n");
02256 
02257     return MAKE_SIGCODE(SIGFPE, FPE_NOMEM, FLTFPE);
02258 
02259   err_fpstatus:
02260 
02261     DPRINTF("<<<<<<<<<<<<<<<<<<<< EXIT err_fpstatus\n");
02262 
02263     return MAKE_SIGCODE(SIGILL, 0, FLTILL);
02264 
02265   ok_fpstatus:
02266 
02267     DPRINTF("<<<<<<<<<<<<<<<<<<<< EXIT ok_fpstatus\n");
02268 
02269     return 0;
02270 
02271 } /* _math_emulator */
02272 
02273 
02276 
02285 static
02286 inline
02287 appenv_type *
02288 getappenv(
02289       void * const * const              pdata )
02290 {
02291 
02292     assert(NULL != pdata);
02293     return (appenv_type *) ((uint8_t *) *pdata + sizeof(PPC_FPU_REGISTERS) + sizeof(run_options));
02294 
02295 } /* getappenv */
02296 
02297 
02306 static
02307 inline
02308 run_options *
02309 getsfenv(
02310       void * const * const              pdata )
02311 {
02312 
02313     assert(NULL != pdata);
02314     return (run_options *) ((uint8_t *) *pdata + sizeof(PPC_FPU_REGISTERS));
02315 
02316 } /* getsfenv */
02317 
02318 
02323 
02331 static
02332 inline
02333 uint32_t
02334 msb32(
02335       const uint32_t                    v )
02336 {
02337 
02338     return (v & (UINT32_C(1) << 31));
02339 
02340 } /* msb32 */
02341 
02342 
02352 static
02353 inline
02354 uint32_t
02355 float32_sign(
02356       const float32                     f )
02357 {
02358 
02359     return (f >> 31);
02360 
02361 } /* float32_sign */
02362 
02363 
02378 static
02379 inline
02380 uint32_t
02381 float32_biased_exp(
02382       const float32                     f )
02383 {
02384 
02385     return ((f >> 23) & UINT32_C(0xff));
02386 
02387 } /* float32_biased_exp */
02388 
02389 
02401 static
02402 inline
02403 uint32_t
02404 float32_fraction(
02405       const float32                     f )
02406 {
02407 
02408     return (f & UINT32_C(0x7fffff));
02409 
02410 } /* float32_fraction */
02411 
02412 
02422 static
02423 inline
02424 flag
02425 float32_is_neg(
02426       const float32                     f )
02427 {
02428 
02429     return float32_sign(f);
02430 
02431 } /* float32_is_neg */
02432 
02433 
02443 static
02444 inline
02445 flag
02446 float32_is_infnan(
02447       const float32                     f )
02448 {
02449 
02450     return (UINT32_C(0xff) == float32_biased_exp(f));
02451 
02452 } /* float32_is_infnan */
02453 
02454 
02459 
02467 static
02468 inline
02469 float32
02470 float32_abs(
02471       const float32                     f )
02472 {
02473 
02474     return (f & ~(UINT32_C(1) << 31));
02475 
02476 } /* float32_abs */
02477 
02478 
02490 static
02491 inline
02492 flag
02493 float32_gt(
02494       const float32                     a,
02495       const float32                     b,
02496       run_options * const               e )
02497 {
02498 
02499     const flag result = float32_le(a, b, e);
02500 
02501     return !(e->float_exception_flags & float_flag_invalid) ? !result : 0;
02502 
02503 } /* float32_gt */
02504 
02505 
02518 static
02519 inline
02520 flag
02521 float32_gt_quiet(
02522       const float32                     a,
02523       const float32                     b,
02524       run_options * const               e )
02525 {
02526 
02527     const flag result = float32_le_quiet(a, b, e);
02528 
02529     return !(e->float_exception_flags & float_flag_invalid) ? !result : 0;
02530 
02531 } /* float32_gt_quiet */
02532 
02533 
02547 static
02548 inline
02549 float32
02550 float32_mul_pow2(
02551       const float32                     f,
02552       const int                         pow2 )
02553 {
02554 
02555     return (f + ((int32_t)pow2 << 23));
02556 
02557 } /* float32_mul_pow2 */
02558 
02559 
02564 
02572 static
02573 inline
02574 uint64_t
02575 msb64(
02576       const uint64_t                    v )
02577 {
02578 
02579     return (v & (UINT64_C(1) << 63));
02580 
02581 } /* msb64 */
02582 
02583 
02593 static
02594 inline
02595 uint64_t
02596 float64_sign(
02597       const float64                     f )
02598 {
02599 
02600     return msb64(f);
02601 
02602 } /* float64_sign */
02603 
02604 
02619 static
02620 inline
02621 uint64_t
02622 float64_biased_exp(
02623       const float64                     f )
02624 {
02625 
02626     return ((f >> 52) & UINT64_C(0x3ff));
02627 
02628 } /* float64_biased_exp */
02629 
02630 
02642 static
02643 inline
02644 uint64_t
02645 float64_fraction(
02646       const float64                     f )
02647 {
02648 
02649     return (f & UINT64_C(0xffffffffffffff));
02650 
02651 } /* float64_fraction */
02652 
02653 
02663 static
02664 inline
02665 flag
02666 float64_is_neg(
02667       const float64                     f )
02668 {
02669 
02670     return float64_sign(f);
02671 
02672 } /* float64_is_neg */
02673 
02674 
02684 static
02685 inline
02686 flag
02687 float64_is_infnan(
02688       const float64                     f )
02689 {
02690 
02691     return (UINT64_C(0x3ff) == float64_biased_exp(f));
02692 
02693 } /* float64_is_infnan */
02694 
02695 
02700 
02708 static
02709 inline
02710 float64
02711 float64_abs(
02712       const float64                     f )
02713 {
02714 
02715     return (f & ~(UINT64_C(1) << 63));
02716 
02717 } /* float64_abs */
02718 
02719 
02731 static
02732 inline
02733 flag
02734 float64_gt(
02735       const float64                     a,
02736       const float64                     b,
02737       run_options * const               e )
02738 {
02739 
02740     const flag result = float64_le(a, b, e);
02741 
02742     return !(e->float_exception_flags & float_flag_invalid) ? !result : 0;
02743 
02744 } /* float64_gt */
02745 
02746 
02759 static
02760 inline
02761 flag
02762 float64_gt_quiet(
02763       const float64                     a,
02764       const float64                     b,
02765       run_options * const               e )
02766 {
02767 
02768     const flag result = float64_le_quiet(a, b, e);
02769 
02770     return !(e->float_exception_flags & float_flag_invalid) ? !result : 0;
02771 
02772 } /* float64_gt_quiet */
02773 
02774 
02788 static
02789 inline
02790 float64
02791 float64_mul_pow2(
02792       const float64                     f,
02793       const int                         pow2 )
02794 {
02795 
02796     return (f + ((int64_t)pow2 << 52));
02797 
02798 } /* float64_mul_pow2 */
02799 
02800 
02812 static
02813 inline
02814 int64
02815 float64_to_int64_round_to_zero(
02816       const float64                     f,
02817       run_options * const               e )
02818 {
02819 
02820     e->float_rounding_mode = float_round_to_zero;
02821 
02822     return float64_to_int64(f, e);
02823 
02824 } /* float64_to_int32_round_to_zero */
02825 
02826 
02831 
02832 
02841 static
02842 inline
02843 float32
02844 uint32_to_float32(
02845       const uint32                      v,
02846       run_options * const               e )
02847 {
02848 
02849     return int64_to_float32(v, e);
02850 
02851 } /* uint32_to_float32 */
02852 
02853 
02862 static
02863 inline
02864 float64
02865 uint32_to_float64(
02866       const uint32                      v,
02867       run_options * const               e )
02868 {
02869 
02870     return int64_to_float64(v, e);
02871 
02872 } /* uint32_to_float64 */
02873 
02874 
02883 static
02884 uint32
02885 float32_to_uint32(
02886       const float32                     f,
02887       run_options * const               e )
02888 {
02889 
02890     uint32 result;
02891 
02892     if (!float32_is_neg(f)) {
02893 
02894         /*
02895          *    Positive value (including +0, +subnorm, +inf, +NaN).
02896          */
02897 
02898         const int64 v = float32_to_int64(f, e);
02899 
02900         if (v <= UINT32_MAX || (e->float_exception_flags & float_flag_invalid)) {
02901 
02902             /*
02903              *    In range (or else complete failure), use softfloat result
02904              */
02905 
02906             result = v;
02907 
02908         } else {
02909 
02910             /*
02911              *    Overflow of uint32, return UINT32_MAX
02912              */
02913 
02914             e->float_exception_flags |= float_flag_overflow;
02915             result = UINT32_MAX;
02916 
02917         }
02918 
02919     } else {
02920 
02921         /*
02922          *    Negative value (including -0, -inf and -NaN)
02923          */
02924 
02925         e->float_exception_flags |= (float32_is_infnan(f) ? float_flag_invalid : float_flag_overflow);
02926         result = 0;
02927 
02928     }
02929 
02930     return result;
02931 
02932 } /* float32_to_uint32 */
02933 
02934 
02946 static
02947 inline
02948 uint32
02949 float32_to_uint32_round_to_zero(
02950       const float32                     f,
02951       run_options * const               e )
02952 {
02953 
02954     e->float_rounding_mode = float_round_to_zero;
02955 
02956     return float32_to_uint32(f, e);
02957 
02958 } /* float32_to_uint32_round_to_zero */
02959 
02960 
02969 static
02970 uint32
02971 float64_to_uint32(
02972       const float64                     f,
02973       run_options * const               e )
02974 {
02975 
02976     uint32 result;
02977 
02978     if (!float64_is_neg(f)) {
02979 
02980         /*
02981          *    Positive value (including +0, +subnorm, +inf, +NaN).
02982          */
02983 
02984         const int64 v = float64_to_int64(f, e);
02985 
02986         if (v <= UINT32_MAX || (e->float_exception_flags & float_flag_invalid)) {
02987 
02988             /*
02989              *    In range (or else complete failure), use softfloat result
02990              */
02991 
02992             result = v;
02993 
02994         } else {
02995 
02996             /*
02997              *    Overflow of uint32, return UINT32_MAX
02998              */
02999 
03000             e->float_exception_flags |= float_flag_overflow;
03001             result = UINT32_MAX;
03002 
03003         }
03004 
03005     } else {
03006 
03007         /*
03008          *    Negative value (including -0, -inf and -NaN)
03009          */
03010 
03011         e->float_exception_flags |= (float32_is_infnan(f) ? float_flag_invalid : float_flag_overflow);
03012         result = 0;
03013 
03014     }
03015 
03016     return result;
03017 
03018 } /* float64_to_uint32 */
03019 
03020 
03032 static
03033 inline
03034 uint32
03035 float64_to_uint32_round_to_zero(
03036       const float64                     f,
03037       run_options * const               e )
03038 {
03039 
03040     e->float_rounding_mode = float_round_to_zero;
03041 
03042     return float64_to_uint32(f, e);
03043 
03044 } /* float64_to_uint32_round_to_zero */
03045 
03046 
03051 
03060 static
03061 inline
03062 float64
03063 uint64_to_float64(
03064       const uint64                      v,
03065       run_options * const               e )
03066 {
03067 
03068     /* For values with MSB set, divide by two, convert as an int64,
03069      * and finally multiply by two.  The fact that the MSB is set
03070      * means that the LSB is guaranteed to be lost in the conversion
03071      * anyway (even if it weren't shifted off). (Note that zero always
03072      * goes through the first branch.) */
03073 
03074     return (!msb64(v)) ? int64_to_float64(v, e) : float64_mul_pow2(int64_to_float64(v >> 1, e), 1);
03075 
03076 } /* uint64_to_float64 */
03077 
03078 
03090 static
03091 uint64
03092 float64_to_uint64_round_to_zero(
03093       const float64                     f,
03094       run_options * const               e )
03095 {
03096 
03097     uint64 result;
03098 
03099     e->float_rounding_mode = float_round_to_zero;
03100 
03101     if (!float64_is_neg(f)) {
03102 
03103         /*
03104          *    Positive value (including +0, +subnorm, +inf, +NaN).
03105          */
03106 
03107         if (!float64_is_infnan(f)) {
03108 
03109             /*
03110              *    Positive value (including +0, +subnorm).
03111              */
03112 
03113             if (float64_biased_exp(f) < (1023 + 64)) {
03114 
03115                 /*
03116                  *    Positive, fits in an int64 (including +0, +subnorm)
03117                  */
03118 
03119                 result = float64_to_int64(f, e);
03120 
03121             } else {
03122 
03123                 /*
03124                  *    Positive, larger than an int64.
03125                  *
03126                  *    Divide by two and convert as int64.  (Note that
03127                  *    no mantissa bits are lost in this process.)
03128                  */
03129 
03130                 result = float64_to_int64(float64_mul_pow2(f, -1), e);
03131 
03132                 if (!(e->float_exception_flags & (float_flag_invalid | float_flag_overflow))) {
03133 
03134                     /*
03135                      *    In range and successful, so multiply by two.
03136                      *
03137                      *    Otherwise, leave softfloat result alone.
03138                      */
03139 
03140                     result <<= 1;
03141 
03142                 }
03143 
03144             }
03145 
03146         } else {
03147 
03148             /*
03149              *    NaN or +inf
03150              */
03151 
03152             e->float_exception_flags |= float_flag_invalid;
03153             result = (float64_is_nan(f) ? 0 : UINT64_MAX);
03154 
03155         }
03156 
03157     } else {
03158 
03159         /*
03160          *    Negative value (including -0, -inf and -NaN)
03161          */
03162 
03163         e->float_exception_flags |= (float32_is_infnan(f) ? float_flag_invalid : float_flag_overflow);
03164         result = 0;
03165 
03166     }
03167 
03168     return result;
03169 
03170 } /* float64_to_uint64_round_to_zero */
03171 
03172 
03177 
03186 static
03187 inline
03188 float32
03189 q31_to_float32(
03190       const q31                         v,
03191       run_options * const               e )
03192 {
03193 
03194     /* Perform a normal int32 conversion, then shift the decimal point
03195      * 31 places to the left.  (Note zero always converts to +0.) */
03196 
03197     return (0 !=  v) ? float32_mul_pow2(int32_to_float32(v, e), -31) : 0;
03198 
03199 } /* q31_to_float32 */
03200 
03201 
03210 static
03211 inline
03212 float64
03213 q31_to_float64(
03214       const q31                         v,
03215       run_options * const               e )
03216 {
03217 
03218     /* Perform a normal int32 conversion, then shift the decimal point
03219      * 31 places to the left.  (Note zero always converts to +0.) */
03220 
03221     return (0 !=  v) ? float64_mul_pow2(int32_to_float64(v, e), -31) : 0;
03222 
03223 } /* q31_to_float64 */
03224 
03225 
03234 static
03235 q31
03236 float32_to_q31(
03237       const float32                     f,
03238       run_options * const               e )
03239 {
03240 
03241     q31 result;
03242 
03243     if (0 != float32_abs(f)) {
03244 
03245         /*
03246          *    Non-zero value.
03247          */
03248 
03249         if (float32_biased_exp(f) < 127) {
03250 
03251             /*
03252              *    Absolute value less than one (including subnorm, but not zero).
03253              *
03254              *    Shift decimal point 31 places to the right and
03255              *    convert as int32.  Biased exponents smaller than 96
03256              *    (-31 unbiased), including subnorms, will yield zero
03257              *    (as they should).
03258              */
03259 
03260             result = float32_to_int32(float32_mul_pow2(f, 31), e);
03261 
03262         } else if (float32_is_nan(f)) {
03263 
03264             /*
03265              *    NaN
03266              */
03267 
03268             e->float_exception_flags |= float_flag_invalid;
03269             result = 0;
03270 
03271         } else {
03272 
03273             /*
03274              *    Overflow of Q31 (including +inf, -inf)
03275              */
03276 
03277             e->float_exception_flags |= (float32_is_infnan(f) ? float_flag_invalid : float_flag_overflow);
03278             result = (float32_is_neg(f) ? INT32_MIN : INT32_MAX);
03279 
03280         }
03281 
03282     } else {
03283 
03284         /*
03285          *    Zero (both +0 and -0).
03286          */
03287 
03288         result = 0;
03289 
03290     }
03291 
03292     return result;
03293 
03294 } /* float32_to_q31 */
03295 
03296 
03305 static
03306 q31
03307 float64_to_q31(
03308       const float64                     f,
03309       run_options * const               e )
03310 {
03311 
03312     q31 result;
03313 
03314     if (0 != float64_abs(f)) {
03315 
03316         /*
03317          *    Non-zero value.
03318          */
03319 
03320         if (float64_biased_exp(f) < 1023) {
03321 
03322             /*
03323              *    Absolute value less than one (including subnorm, but not zero).
03324              *
03325              *    Shift decimal point 31 places to the right and
03326              *    convert as int32.  Biased exponents smaller than 992
03327              *    (-31 unbiased), including subnorms, will yield zero
03328              *    (as they should).
03329              */
03330 
03331             result = float64_to_int32(float64_mul_pow2(f, 31), e);
03332 
03333         } else if (float64_is_nan(f)) {
03334 
03335             /*
03336              *    NaN
03337              */
03338 
03339             e->float_exception_flags |= float_flag_invalid;
03340             result = 0;
03341 
03342         } else {
03343 
03344             /*
03345              *    Overflow q31 (including +inf, -inf)
03346              */
03347 
03348             e->float_exception_flags |= (float32_is_infnan(f) ? float_flag_invalid : float_flag_overflow);
03349             result = float64_is_neg(f) ? INT32_MIN : INT32_MAX;
03350 
03351         }
03352 
03353     } else {
03354 
03355         /*
03356          *    Zero (both +0 and -0)
03357          */
03358 
03359         result = 0;
03360 
03361     }
03362 
03363     return result;
03364 
03365 } /* float64_to_q31 */
03366 
03367 
03372 
03381 static
03382 inline
03383 float32
03384 uq32_to_float32(
03385       const uq32                        v,
03386       run_options * const               e )
03387 {
03388 
03389     /* Perform a normal uint32 conversion, then shift the decimal point
03390      * 32 places to the left.  (Note zero always converts to +0.) */
03391 
03392     return (0 !=  v) ? float32_mul_pow2(uint32_to_float32(v, e), -32) : 0;
03393 
03394 } /* uq32_to_float32 */
03395 
03396 
03405 static
03406 inline
03407 float64
03408 uq32_to_float64(
03409       const uq32                        v,
03410       run_options * const               e )
03411 {
03412 
03413     /* Perform a normal uint32 conversion, then shift the decimal point
03414      * 32 places to the left.  (Note zero always converts to +0.) */
03415 
03416     return (0 !=  v) ? float64_mul_pow2(uint32_to_float64(v, e), -32) : 0;
03417 
03418 } /* uq32_to_float64 */
03419 
03420 
03429 static
03430 uq32
03431 float32_to_uq32(
03432       const float32                     f,
03433       run_options * const               e )
03434 {
03435 
03436     uq32 result;
03437 
03438     if (0 != float32_abs(f)) {
03439 
03440         /*
03441          *    Non-zero value.
03442          */
03443 
03444         if (!float32_is_neg(f) && float32_biased_exp(f) < 127) {
03445 
03446             /*
03447              *    Positive value less than one (including subnorm, but not zero).
03448              *
03449              *    Shift decimal point 32 places to the right and
03450              *    convert as int64.  Biased exponents smaller than 95
03451              *    (-32 unbiased), including subnorms, will yield zero
03452              *    (as they should).
03453              */
03454 
03455             const int64 v = float32_to_int64(float32_mul_pow2(f, 32), e);
03456 
03457             if (v <= UINT32_MAX || (e->float_exception_flags & float_flag_invalid)) {
03458 
03459                 /*
03460                  *    In range (or else complete failure), use softfloat result.
03461                  */
03462 
03463                 result = v;
03464 
03465             } else {
03466 
03467                 /*
03468                  *    Overflow
03469                  */
03470 
03471                 e->float_exception_flags |= float_flag_overflow;
03472                 result = UINT32_MAX;
03473 
03474             }
03475 
03476         } else if (float32_is_nan(f)) {
03477 
03478             /*
03479              *    NaN
03480              */
03481 
03482             e->float_exception_flags |= float_flag_invalid;
03483             result = 0;
03484 
03485         } else {
03486 
03487             /*
03488              *    Overflow uq32 (including +inf, -inf, -subnorm, -norm)
03489              */
03490 
03491             e->float_exception_flags |= (float32_is_infnan(f) ? float_flag_invalid : float_flag_overflow);
03492             result = (float32_is_neg(f) ? 0 : UINT32_MAX);
03493 
03494         }
03495 
03496     } else {
03497 
03498         /*
03499          *    Zero (both +0 and -0)
03500          */
03501 
03502         result = 0;
03503 
03504     }
03505 
03506     return result;
03507 
03508 } /* float32_to_uq32 */
03509 
03510 
03519 static
03520 uint64
03521 float64_to_uq32(
03522       const float64                     f,
03523       run_options * const               e )
03524 {
03525 
03526 
03527     uq32 result;
03528 
03529     if (0 != float64_abs(f)) {
03530 
03531         /*
03532          *    Non-zero value.
03533          */
03534 
03535         if (!float64_is_neg(f) && float64_biased_exp(f) < 1023) {
03536 
03537             /*
03538              *    Positive value less than one (including subnorm, but not zero).
03539              *
03540              *    Shift decimal point 32 places to the right and
03541              *    convert as int64.  Biased exponents smaller than 991
03542              *    (-32 unbiased), including subnorms, will yield zero
03543              *    (as they should).
03544              */
03545 
03546             const int64 v = float64_to_int64(float64_mul_pow2(f, 32), e);
03547 
03548             if (v <= UINT32_MAX || (e->float_exception_flags & float_flag_invalid)) {
03549 
03550                 /*
03551                  *    In range (or else complete failure), use softfloat result
03552                  */
03553 
03554                 result = v;
03555 
03556             } else {
03557 
03558                 /*
03559                  *    Overflow uq32 (including +inf, -inf, -subnorm, -norm)
03560                  */
03561 
03562                 e->float_exception_flags |= float_flag_overflow;
03563                 result = UINT32_MAX;
03564 
03565             }
03566 
03567         } else if (float64_is_nan(f)) {
03568 
03569             /*
03570              *    NaN
03571              */
03572 
03573             e->float_exception_flags |= float_flag_invalid;
03574             result = 0;
03575 
03576         } else {
03577 
03578             /*
03579              *    Overflow uq32 (including +inf, -inf, -subnorm, -norm)
03580              */
03581 
03582             e->float_exception_flags |= (float64_is_infnan(f) ? float_flag_invalid : float_flag_overflow);
03583             result = (float64_is_neg(f) ? 0 : UINT32_MAX);
03584 
03585         }
03586 
03587     } else {
03588 
03589         /*
03590          *    Zero (both +0 and -0)
03591          */
03592 
03593         result = 0;
03594 
03595     }
03596 
03597     return result;
03598 
03599 } /* float64_to_uq32 */
03600 
03601 
03606 
03616 static
03617 inline
03618 float32
03619 load32(
03620       const PPC_CPU_REGISTERS * const   regs,
03621       const unsigned                    n )
03622 {
03623 
03624     assert(NULL != regs);
03625     assert(n < 32);
03626 
03627     return regs->gpr[n];
03628 
03629 } /* load32 */
03630 
03631 
03640 static
03641 inline
03642 void
03643 store32(
03644       PPC_CPU_REGISTERS * const         regs,
03645       const unsigned                    n,
03646       const float32                     v )
03647 {
03648 
03649     assert(NULL != regs);
03650     assert(n < 32);
03651 
03652     regs->gpr[n] = v;
03653 
03654     return;
03655 
03656 } /* store32 */
03657 
03658 
03668 static
03669 float32
03670 loadh32(
03671       const PPC_CPU_REGISTERS * const   regs __attribute__((unused)),
03672       const unsigned                    n )
03673 {
03674 
03675     float32 result;
03676 
03677     assert(NULL != regs);
03678     assert(n < 32);
03679 
03680     switch (n) {
03681         case  0: LOADHI(result,  0); break;
03682         case  1: LOADHI(result,  1); break;
03683         case  2: LOADHI(result,  2); break;
03684         case  3: LOADHI(result,  3); break;
03685         case  4: LOADHI(result,  4); break;
03686         case  5: LOADHI(result,  5); break;
03687         case  6: LOADHI(result,  6); break;
03688         case  7: LOADHI(result,  7); break;
03689         case  8: LOADHI(result,  8); break;
03690         case  9: LOADHI(result,  9); break;
03691         case 10: LOADHI(result, 10); break;
03692         case 11: LOADHI(result, 11); break;
03693         case 12: LOADHI(result, 12); break;
03694         case 13: LOADHI(result, 13); break;
03695         case 14: LOADHI(result, 14); break;
03696         case 15: LOADHI(result, 15); break;
03697         case 16: LOADHI(result, 16); break;
03698         case 17: LOADHI(result, 17); break;
03699         case 18: LOADHI(result, 18); break;
03700         case 19: LOADHI(result, 19); break;
03701         case 20: LOADHI(result, 20); break;
03702         case 21: LOADHI(result, 21); break;
03703         case 22: LOADHI(result, 22); break;
03704         case 23: LOADHI(result, 23); break;
03705         case 24: LOADHI(result, 24); break;
03706         case 25: LOADHI(result, 25); break;
03707         case 26: LOADHI(result, 26); break;
03708         case 27: LOADHI(result, 27); break;
03709         case 28: LOADHI(result, 28); break;
03710         case 29: LOADHI(result, 29); break;
03711         case 30: LOADHI(result, 30); break;
03712         case 31: LOADHI(result, 31); break;
03713     }
03714 
03715     return result;
03716 
03717 } /* load32 */
03718 
03719 
03728 static
03729 void
03730 storeh32(
03731       PPC_CPU_REGISTERS * const         regs __attribute__((unused)),
03732       const unsigned                    n,
03733       const float32                     v )
03734 {
03735 
03736     assert(NULL != regs);
03737     assert(n < 32);
03738 
03739     switch (n) {
03740         case  0: STOREHI(v,  0); break;
03741         case  1: STOREHI(v,  1); break;
03742         case  2: STOREHI(v,  2); break;
03743         case  3: STOREHI(v,  3); break;
03744         case  4: STOREHI(v,  4); break;
03745         case  5: STOREHI(v,  5); break;
03746         case  6: STOREHI(v,  6); break;
03747         case  7: STOREHI(v,  7); break;
03748         case  8: STOREHI(v,  8); break;
03749         case  9: STOREHI(v,  9); break;
03750         case 10: STOREHI(v, 10); break;
03751         case 11: STOREHI(v, 11); break;
03752         case 12: STOREHI(v, 12); break;
03753         case 13: STOREHI(v, 13); break;
03754         case 14: STOREHI(v, 14); break;
03755         case 15: STOREHI(v, 15); break;
03756         case 16: STOREHI(v, 16); break;
03757         case 17: STOREHI(v, 17); break;
03758         case 18: STOREHI(v, 18); break;
03759         case 19: STOREHI(v, 19); break;
03760         case 20: STOREHI(v, 20); break;
03761         case 21: STOREHI(v, 21); break;
03762         case 22: STOREHI(v, 22); break;
03763         case 23: STOREHI(v, 23); break;
03764         case 24: STOREHI(v, 24); break;
03765         case 25: STOREHI(v, 25); break;
03766         case 26: STOREHI(v, 26); break;
03767         case 27: STOREHI(v, 27); break;
03768         case 28: STOREHI(v, 28); break;
03769         case 29: STOREHI(v, 29); break;
03770         case 30: STOREHI(v, 30); break;
03771         case 31: STOREHI(v, 31); break;
03772     }
03773 
03774     return;
03775 
03776 } /* store32 */
03777 
03778 
03788 static
03789 float64
03790 load64(
03791       const PPC_CPU_REGISTERS * const   regs,
03792       const unsigned                    n )
03793 {
03794 
03795     union { float64 f; uint32_t u[2]; } result;
03796 
03797     assert(NULL != regs);
03798     assert(n < 32);
03799 
03800     switch (n) {
03801         case  0: LOADHI(result.u[0],  0); break;
03802         case  1: LOADHI(result.u[0],  1); break;
03803         case  2: LOADHI(result.u[0],  2); break;
03804         case  3: LOADHI(result.u[0],  3); break;
03805         case  4: LOADHI(result.u[0],  4); break;
03806         case  5: LOADHI(result.u[0],  5); break;
03807         case  6: LOADHI(result.u[0],  6); break;
03808         case  7: LOADHI(result.u[0],  7); break;
03809         case  8: LOADHI(result.u[0],  8); break;
03810         case  9: LOADHI(result.u[0],  9); break;
03811         case 10: LOADHI(result.u[0], 10); break;
03812         case 11: LOADHI(result.u[0], 11); break;
03813         case 12: LOADHI(result.u[0], 12); break;
03814         case 13: LOADHI(result.u[0], 13); break;
03815         case 14: LOADHI(result.u[0], 14); break;
03816         case 15: LOADHI(result.u[0], 15); break;
03817         case 16: LOADHI(result.u[0], 16); break;
03818         case 17: LOADHI(result.u[0], 17); break;
03819         case 18: LOADHI(result.u[0], 18); break;
03820         case 19: LOADHI(result.u[0], 19); break;
03821         case 20: LOADHI(result.u[0], 20); break;
03822         case 21: LOADHI(result.u[0], 21); break;
03823         case 22: LOADHI(result.u[0], 22); break;
03824         case 23: LOADHI(result.u[0], 23); break;
03825         case 24: LOADHI(result.u[0], 24); break;
03826         case 25: LOADHI(result.u[0], 25); break;
03827         case 26: LOADHI(result.u[0], 26); break;
03828         case 27: LOADHI(result.u[0], 27); break;
03829         case 28: LOADHI(result.u[0], 28); break;
03830         case 29: LOADHI(result.u[0], 29); break;
03831         case 30: LOADHI(result.u[0], 30); break;
03832         case 31: LOADHI(result.u[0], 31); break;
03833     }
03834 
03835     result.u[1] = regs->gpr[n];
03836 
03837     return result.f;
03838 
03839 } /* load64 */
03840 
03841 
03850 static
03851 void
03852 store64(
03853       PPC_CPU_REGISTERS * const         regs,
03854       const unsigned                    n,
03855       const float64                     v )
03856 {
03857 
03858     const union { float64 f; uint32_t u[2]; } data = { v };
03859 
03860     assert(NULL != regs);
03861     assert(n < 32);
03862 
03863     switch (n) {
03864         case  0: STOREHI(data.u[0],  0); break;
03865         case  1: STOREHI(data.u[0],  1); break;
03866         case  2: STOREHI(data.u[0],  2); break;
03867         case  3: STOREHI(data.u[0],  3); break;
03868         case  4: STOREHI(data.u[0],  4); break;
03869         case  5: STOREHI(data.u[0],  5); break;
03870         case  6: STOREHI(data.u[0],  6); break;
03871         case  7: STOREHI(data.u[0],  7); break;
03872         case  8: STOREHI(data.u[0],  8); break;
03873         case  9: STOREHI(data.u[0],  9); break;
03874         case 10: STOREHI(data.u[0], 10); break;
03875         case 11: STOREHI(data.u[0], 11); break;
03876         case 12: STOREHI(data.u[0], 12); break;
03877         case 13: STOREHI(data.u[0], 13); break;
03878         case 14: STOREHI(data.u[0], 14); break;
03879         case 15: STOREHI(data.u[0], 15); break;
03880         case 16: STOREHI(data.u[0], 16); break;
03881         case 17: STOREHI(data.u[0], 17); break;
03882         case 18: STOREHI(data.u[0], 18); break;
03883         case 19: STOREHI(data.u[0], 19); break;
03884         case 20: STOREHI(data.u[0], 20); break;
03885         case 21: STOREHI(data.u[0], 21); break;
03886         case 22: STOREHI(data.u[0], 22); break;
03887         case 23: STOREHI(data.u[0], 23); break;
03888         case 24: STOREHI(data.u[0], 24); break;
03889         case 25: STOREHI(data.u[0], 25); break;
03890         case 26: STOREHI(data.u[0], 26); break;
03891         case 27: STOREHI(data.u[0], 27); break;
03892         case 28: STOREHI(data.u[0], 28); break;
03893         case 29: STOREHI(data.u[0], 29); break;
03894         case 30: STOREHI(data.u[0], 30); break;
03895         case 31: STOREHI(data.u[0], 31); break;
03896     }
03897 
03898     regs->gpr[n] = data.u[1];
03899 
03900     return;
03901 
03902 } /* store64 */
03903 
03904 
04038 __SRCVERSION( "$URL: http://svn.ott.qnx.com/product/trunk/lib/ieee754/fpassist/ppc/efp_assist.c $ $Rev: 236661 $" );

Generated on Fri Nov 13 15:38:37 2009 for fpassist for PPC SPE by  doxygen 1.5.9