00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00076 #if !defined(__BIGENDIAN__) || !defined(VARIANT_spe)
00077 # error BIGENDIAN PPC WITH SPE APU REQUIRED
00078 #endif
00079
00080
00081
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
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
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
00230
00231
00239 typedef struct {
00240
00243 uint32_t spefscr;
00244
00245 } appenv_type;
00246
00251 typedef enum {
00252
00253
00254
00255 PPC_XO_evfsabs = 644,
00256 PPC_XO_evfsnabs = 645,
00257 PPC_XO_evfsneg = 646,
00259
00260
00261 PPC_XO_evfsadd = 640,
00262 PPC_XO_evfssub = 641,
00263 PPC_XO_evfsmul = 648,
00264 PPC_XO_evfsdiv = 649,
00266
00267
00268 PPC_XO_evfscmpgt = 652,
00269 PPC_XO_evfscmplt = 653,
00270 PPC_XO_evfscmpeq = 654,
00272
00273
00274 PPC_XO_evfststgt = 668,
00275 PPC_XO_evfststlt = 669,
00276 PPC_XO_evfststeq = 670,
00278
00279
00280 PPC_XO_evfscfsi = 657,
00281 PPC_XO_evfscfui = 656,
00283
00284
00285 PPC_XO_evfscfsf = 659,
00286 PPC_XO_evfscfuf = 658,
00288
00289
00290 PPC_XO_evfsctsi = 661,
00291 PPC_XO_evfsctui = 660,
00293
00294
00295 PPC_XO_evfsctsiz = 666,
00296 PPC_XO_evfsctuiz = 664,
00298
00299
00300 PPC_XO_evfsctsf = 663,
00301 PPC_XO_evfsctuf = 662,
00303
00304
00305 PPC_XO_efsabs = 708,
00306 PPC_XO_efsnabs = 709,
00307 PPC_XO_efsneg = 710,
00309
00310
00311 PPC_XO_efsadd = 704,
00312 PPC_XO_efssub = 705,
00313 PPC_XO_efsmul = 712,
00314 PPC_XO_efsdiv = 713,
00316
00317
00318 PPC_XO_efscmpgt = 716,
00319 PPC_XO_efscmplt = 717,
00320 PPC_XO_efscmpeq = 718,
00322
00323
00324 PPC_XO_efststgt = 732,
00325 PPC_XO_efststlt = 733,
00326 PPC_XO_efststeq = 734,
00328
00329
00330 PPC_XO_efscfsi = 721,
00331 PPC_XO_efscfui = 720,
00333
00334
00335 PPC_XO_efscfsf = 723,
00336 PPC_XO_efscfuf = 722,
00338
00339
00340 PPC_XO_efsctsi = 725,
00341 PPC_XO_efsctui = 724,
00343
00344
00345 PPC_XO_efsctsiz = 730,
00346 PPC_XO_efsctuiz = 728,
00348
00349
00350 PPC_XO_efsctsf = 727,
00351 PPC_XO_efsctuf = 726,
00353
00354
00355 PPC_XO_efdabs = 740,
00356 PPC_XO_efdnabs = 741,
00357 PPC_XO_efdneg = 742,
00359
00360
00361 PPC_XO_efdadd = 736,
00362 PPC_XO_efdsub = 737,
00363 PPC_XO_efdmul = 744,
00364 PPC_XO_efddiv = 745,
00366
00367
00368 PPC_XO_efdcmpgt = 748,
00369 PPC_XO_efdcmplt = 749,
00370 PPC_XO_efdcmpeq = 750,
00372
00373
00374 PPC_XO_efdtstgt = 764,
00375 PPC_XO_efdtstlt = 765,
00376 PPC_XO_efdtsteq = 766,
00378
00379
00380 PPC_XO_efdcfsi = 753,
00381 PPC_XO_efdcfui = 752,
00383
00384
00385 PPC_XO_efdcfsid = 739,
00386 PPC_XO_efdcfuid = 738,
00388
00389
00390 PPC_XO_efdcfsf = 755,
00391 PPC_XO_efdcfuf = 754,
00393
00394
00395 PPC_XO_efdctsi = 757,
00396 PPC_XO_efdctui = 756,
00398
00399
00400 PPC_XO_efdctsidz = 747,
00401 PPC_XO_efdctuidz = 746,
00403
00404
00405 PPC_XO_efdctsiz = 762,
00406 PPC_XO_efdctuiz = 760,
00408
00409
00410 PPC_XO_efdctsf = 759,
00411 PPC_XO_efdctuf = 758,
00413
00414
00415 PPC_XO_efdcfs = 751,
00417
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
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
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
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683 if (SIGFPE != SIGCODE_SIGNO(sigcode)) goto err_unsup;
00684
00685
00686
00687
00688
00689 if (NULL != *pdata) {
00690
00691
00692
00693 ctx = getappenv(pdata);
00694
00695 DPRINTF("ctx 0x%p\n", ctx);
00696
00697 } else {
00698
00699
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
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
00774
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
00805
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
00820
00821
00822
00823 switch ((ppc_xo_type) op.evx_t.xo) {
00824
00825
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
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
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
00975
00976
00977
00978
00979
00980 assert(roundonly && "unexpected exception");
00981
00982 break;
00983
00984
00985
00986 default:
00987
00988 goto err_unsup;
00989
00990 }
00991
00992
00993
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
01020
01021
01022 switch ((ppc_xo_type) op.evx_t.xo) {
01023
01024
01025
01026 case PPC_XO_evfsadd:
01027 case PPC_XO_evfssub:
01028 case PPC_XO_evfsmul:
01029 case PPC_XO_evfsdiv:
01030
01031
01032
01033 case PPC_XO_evfscmpgt:
01034 case PPC_XO_evfscmplt:
01035 case PPC_XO_evfscmpeq:
01036
01037
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
01056
01057
01058
01059 case PPC_XO_evfscfsi:
01060 case PPC_XO_evfscfui:
01061
01062
01063
01064 case PPC_XO_evfscfsf:
01065 case PPC_XO_evfscfuf:
01066
01067
01068
01069 case PPC_XO_evfsctsi:
01070 case PPC_XO_evfsctui:
01071
01072
01073
01074 case PPC_XO_evfsctsiz:
01075 case PPC_XO_evfsctuiz:
01076
01077
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
01097
01098 case PPC_XO_efsadd:
01099 case PPC_XO_efssub:
01100 case PPC_XO_efsmul:
01101 case PPC_XO_efsdiv:
01102
01103
01104
01105 case PPC_XO_efscmpgt:
01106 case PPC_XO_efscmplt:
01107 case PPC_XO_efscmpeq:
01108
01109
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
01118
01119
01120
01121 case PPC_XO_efscfsi:
01122 case PPC_XO_efscfui:
01123
01124
01125
01126 case PPC_XO_efscfsf:
01127 case PPC_XO_efscfuf:
01128
01129
01130
01131 case PPC_XO_efsctsi:
01132 case PPC_XO_efsctui:
01133
01134
01135
01136 case PPC_XO_efsctsiz:
01137 case PPC_XO_efsctuiz:
01138
01139
01140
01141 case PPC_XO_efsctsf:
01142 case PPC_XO_efsctuf:
01143
01144
01145
01146 case PPC_XO_efdcfsi:
01147 case PPC_XO_efdcfui:
01148
01149
01150
01151 case PPC_XO_efdcfsf:
01152 case PPC_XO_efdcfuf:
01153
01154
01155
01156 case PPC_XO_efdcfs:
01157
01158 b32 = load32(regs, op.evx_t.b);
01159
01160 break;
01161
01162
01163
01164 case PPC_XO_efdadd:
01165 case PPC_XO_efdsub:
01166 case PPC_XO_efdmul:
01167 case PPC_XO_efddiv:
01168
01169
01170
01171 case PPC_XO_efdcmpgt:
01172 case PPC_XO_efdcmplt:
01173 case PPC_XO_efdcmpeq:
01174
01175
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
01184
01185
01186
01187 case PPC_XO_efdcfsid:
01188 case PPC_XO_efdcfuid:
01189
01190
01191
01192 case PPC_XO_efdctsi:
01193 case PPC_XO_efdctui:
01194
01195
01196
01197 case PPC_XO_efdctsidz:
01198 case PPC_XO_efdctuidz:
01199
01200
01201
01202 case PPC_XO_efdctsiz:
01203 case PPC_XO_efdctuiz:
01204
01205
01206
01207 case PPC_XO_efdctsf:
01208 case PPC_XO_efdctuf:
01209
01210
01211
01212 case PPC_XO_efscfd:
01213
01214 b64 = load64(regs, op.evx_t.b);
01215
01216 break;
01217
01218
01219
01220 case PPC_XO_evfsabs:
01221 case PPC_XO_evfsnabs:
01222 case PPC_XO_evfsneg:
01223
01224
01225
01226 case PPC_XO_efsabs:
01227 case PPC_XO_efsnabs:
01228 case PPC_XO_efsneg:
01229
01230
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
01249
01250
01251 switch ((ppc_xo_type) op.evx_t.xo) {
01252
01253
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
01726
01727 case PPC_XO_efscfd:
01728
01729 t32 = float64_to_float32(b64, sfenv);
01730
01731 break;
01732
01733
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
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
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
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
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
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
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
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
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
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
01898
01899 case PPC_XO_efdcfs:
01900
01901 t64 = float32_to_float64(b32, sfenv);
01902
01903 break;
01904
01905
01906
01907 case PPC_XO_evfsabs:
01908 case PPC_XO_evfsnabs:
01909 case PPC_XO_evfsneg:
01910
01911
01912
01913 case PPC_XO_efsabs:
01914 case PPC_XO_efsnabs:
01915 case PPC_XO_efsneg:
01916
01917
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
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
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
01972
01973 ctx->spefscr |= sticky;
01974
01975
01976
01977 regs->u2.spefscr = spefscr | (ctx->spefscr & SPEFSCR_STICKY_EXC_MASK);
01978
01979
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
02002
02003
02004
02005
02006
02007
02008
02009
02010 if (0 == result || FPE_FLTRES == SIGCODE_CODE(sigcode)) {
02011
02012 switch ((ppc_xo_type) op.evx_t.xo) {
02013
02014
02015
02016 case PPC_XO_evfsadd:
02017 case PPC_XO_evfssub:
02018 case PPC_XO_evfsmul:
02019 case PPC_XO_evfsdiv:
02020
02021
02022
02023 case PPC_XO_evfscfsi:
02024 case PPC_XO_evfscfui:
02025
02026
02027
02028 case PPC_XO_evfscfsf:
02029 case PPC_XO_evfscfuf:
02030
02031
02032
02033 case PPC_XO_evfsctsi:
02034 case PPC_XO_evfsctui:
02035
02036
02037
02038 case PPC_XO_evfsctsiz:
02039 case PPC_XO_evfsctuiz:
02040
02041
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
02061
02062 case PPC_XO_efsadd:
02063 case PPC_XO_efssub:
02064 case PPC_XO_efsmul:
02065 case PPC_XO_efsdiv:
02066
02067
02068
02069 case PPC_XO_efscfsi:
02070 case PPC_XO_efscfui:
02071
02072
02073
02074 case PPC_XO_efscfsf:
02075 case PPC_XO_efscfuf:
02076
02077
02078
02079 case PPC_XO_efsctsi:
02080 case PPC_XO_efsctui:
02081
02082
02083
02084 case PPC_XO_efsctsiz:
02085 case PPC_XO_efsctuiz:
02086
02087
02088
02089 case PPC_XO_efsctsf:
02090 case PPC_XO_efsctuf:
02091
02092
02093
02094 case PPC_XO_efscfd:
02095
02096
02097
02098 case PPC_XO_efdctsi:
02099 case PPC_XO_efdctui:
02100
02101
02102
02103 case PPC_XO_efdctsiz:
02104 case PPC_XO_efdctuiz:
02105
02106
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
02116
02117 case PPC_XO_efdadd:
02118 case PPC_XO_efdsub:
02119 case PPC_XO_efdmul:
02120 case PPC_XO_efddiv:
02121
02122
02123
02124 case PPC_XO_efdcfsi:
02125 case PPC_XO_efdcfui:
02126
02127
02128
02129 case PPC_XO_efdcfsid:
02130 case PPC_XO_efdcfuid:
02131
02132
02133
02134 case PPC_XO_efdcfsf:
02135 case PPC_XO_efdcfuf:
02136
02137
02138
02139 case PPC_XO_efdctsidz:
02140 case PPC_XO_efdctuidz:
02141
02142
02143
02144 case PPC_XO_efdcfs:
02145
02146 store64(regs, op.evx_t.t, t64);
02147
02148 break;
02149
02150
02151
02152 case PPC_XO_evfststgt:
02153 case PPC_XO_evfststlt:
02154 case PPC_XO_evfststeq:
02155
02156
02157
02158 case PPC_XO_efststgt:
02159 case PPC_XO_efststlt:
02160 case PPC_XO_efststeq:
02161
02162
02163
02164 case PPC_XO_efdtstgt:
02165 case PPC_XO_efdtstlt:
02166 case PPC_XO_efdtsteq:
02167
02168
02169
02170 case PPC_XO_evfscmpgt:
02171 case PPC_XO_evfscmplt:
02172 case PPC_XO_evfscmpeq:
02173
02174
02175
02176 case PPC_XO_efscmpgt:
02177 case PPC_XO_efscmplt:
02178 case PPC_XO_efscmpeq:
02179
02180
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
02214
02215 case PPC_XO_evfsabs:
02216 case PPC_XO_evfsnabs:
02217 case PPC_XO_evfsneg:
02218
02219
02220
02221 case PPC_XO_efsabs:
02222 case PPC_XO_efsnabs:
02223 case PPC_XO_efsneg:
02224
02225
02226
02227 case PPC_XO_efdabs:
02228 case PPC_XO_efdnabs:
02229 case PPC_XO_efdneg:
02230
02231 break;
02232
02233 }
02234
02235
02236
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 }
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 }
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 }
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 }
02341
02342
02352 static
02353 inline
02354 uint32_t
02355 float32_sign(
02356 const float32 f )
02357 {
02358
02359 return (f >> 31);
02360
02361 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
02582
02583
02593 static
02594 inline
02595 uint64_t
02596 float64_sign(
02597 const float64 f )
02598 {
02599
02600 return msb64(f);
02601
02602 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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
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
02904
02905
02906 result = v;
02907
02908 } else {
02909
02910
02911
02912
02913
02914 e->float_exception_flags |= float_flag_overflow;
02915 result = UINT32_MAX;
02916
02917 }
02918
02919 } else {
02920
02921
02922
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 }
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 }
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
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
02990
02991
02992 result = v;
02993
02994 } else {
02995
02996
02997
02998
02999
03000 e->float_exception_flags |= float_flag_overflow;
03001 result = UINT32_MAX;
03002
03003 }
03004
03005 } else {
03006
03007
03008
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 }
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 }
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
03069
03070
03071
03072
03073
03074 return (!msb64(v)) ? int64_to_float64(v, e) : float64_mul_pow2(int64_to_float64(v >> 1, e), 1);
03075
03076 }
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
03105
03106
03107 if (!float64_is_infnan(f)) {
03108
03109
03110
03111
03112
03113 if (float64_biased_exp(f) < (1023 + 64)) {
03114
03115
03116
03117
03118
03119 result = float64_to_int64(f, e);
03120
03121 } else {
03122
03123
03124
03125
03126
03127
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
03136
03137
03138
03139
03140 result <<= 1;
03141
03142 }
03143
03144 }
03145
03146 } else {
03147
03148
03149
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
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 }
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
03195
03196
03197 return (0 != v) ? float32_mul_pow2(int32_to_float32(v, e), -31) : 0;
03198
03199 }
03200
03201
03210 static
03211 inline
03212 float64
03213 q31_to_float64(
03214 const q31 v,
03215 run_options * const e )
03216 {
03217
03218
03219
03220
03221 return (0 != v) ? float64_mul_pow2(int32_to_float64(v, e), -31) : 0;
03222
03223 }
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
03247
03248
03249 if (float32_biased_exp(f) < 127) {
03250
03251
03252
03253
03254
03255
03256
03257
03258
03259
03260 result = float32_to_int32(float32_mul_pow2(f, 31), e);
03261
03262 } else if (float32_is_nan(f)) {
03263
03264
03265
03266
03267
03268 e->float_exception_flags |= float_flag_invalid;
03269 result = 0;
03270
03271 } else {
03272
03273
03274
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
03286
03287
03288 result = 0;
03289
03290 }
03291
03292 return result;
03293
03294 }
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
03318
03319
03320 if (float64_biased_exp(f) < 1023) {
03321
03322
03323
03324
03325
03326
03327
03328
03329
03330
03331 result = float64_to_int32(float64_mul_pow2(f, 31), e);
03332
03333 } else if (float64_is_nan(f)) {
03334
03335
03336
03337
03338
03339 e->float_exception_flags |= float_flag_invalid;
03340 result = 0;
03341
03342 } else {
03343
03344
03345
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
03357
03358
03359 result = 0;
03360
03361 }
03362
03363 return result;
03364
03365 }
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
03390
03391
03392 return (0 != v) ? float32_mul_pow2(uint32_to_float32(v, e), -32) : 0;
03393
03394 }
03395
03396
03405 static
03406 inline
03407 float64
03408 uq32_to_float64(
03409 const uq32 v,
03410 run_options * const e )
03411 {
03412
03413
03414
03415
03416 return (0 != v) ? float64_mul_pow2(uint32_to_float64(v, e), -32) : 0;
03417
03418 }
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
03442
03443
03444 if (!float32_is_neg(f) && float32_biased_exp(f) < 127) {
03445
03446
03447
03448
03449
03450
03451
03452
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
03461
03462
03463 result = v;
03464
03465 } else {
03466
03467
03468
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
03480
03481
03482 e->float_exception_flags |= float_flag_invalid;
03483 result = 0;
03484
03485 } else {
03486
03487
03488
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
03500
03501
03502 result = 0;
03503
03504 }
03505
03506 return result;
03507
03508 }
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
03533
03534
03535 if (!float64_is_neg(f) && float64_biased_exp(f) < 1023) {
03536
03537
03538
03539
03540
03541
03542
03543
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
03552
03553
03554 result = v;
03555
03556 } else {
03557
03558
03559
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
03571
03572
03573 e->float_exception_flags |= float_flag_invalid;
03574 result = 0;
03575
03576 } else {
03577
03578
03579
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
03591
03592
03593 result = 0;
03594
03595 }
03596
03597 return result;
03598
03599 }
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 }
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 }
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 }
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 }
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 }
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 }
03903
03904
04038 __SRCVERSION( "$URL: http://svn.ott.qnx.com/product/trunk/lib/ieee754/fpassist/ppc/efp_assist.c $ $Rev: 236661 $" );