18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci NetWinder Floating Point Emulator 48c2ecf20Sopenharmony_ci (c) Rebel.COM, 1998,1999 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci Direct questions, comments to Scott Bambrough <scottb@netwinder.org> 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci*/ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include "fpa11.h" 118c2ecf20Sopenharmony_ci#include "softfloat.h" 128c2ecf20Sopenharmony_ci#include "fpopcode.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ciunion float64_components { 158c2ecf20Sopenharmony_ci float64 f64; 168c2ecf20Sopenharmony_ci unsigned int i[2]; 178c2ecf20Sopenharmony_ci}; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cifloat64 float64_exp(float64 Fm); 208c2ecf20Sopenharmony_cifloat64 float64_ln(float64 Fm); 218c2ecf20Sopenharmony_cifloat64 float64_sin(float64 rFm); 228c2ecf20Sopenharmony_cifloat64 float64_cos(float64 rFm); 238c2ecf20Sopenharmony_cifloat64 float64_arcsin(float64 rFm); 248c2ecf20Sopenharmony_cifloat64 float64_arctan(float64 rFm); 258c2ecf20Sopenharmony_cifloat64 float64_log(float64 rFm); 268c2ecf20Sopenharmony_cifloat64 float64_tan(float64 rFm); 278c2ecf20Sopenharmony_cifloat64 float64_arccos(float64 rFm); 288c2ecf20Sopenharmony_cifloat64 float64_pow(float64 rFn, float64 rFm); 298c2ecf20Sopenharmony_cifloat64 float64_pol(float64 rFn, float64 rFm); 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic float64 float64_rsf(struct roundingData *roundData, float64 rFn, float64 rFm) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci return float64_sub(roundData, rFm, rFn); 348c2ecf20Sopenharmony_ci} 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic float64 float64_rdv(struct roundingData *roundData, float64 rFn, float64 rFm) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci return float64_div(roundData, rFm, rFn); 398c2ecf20Sopenharmony_ci} 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cistatic float64 (*const dyadic_double[16])(struct roundingData*, float64 rFn, float64 rFm) = { 428c2ecf20Sopenharmony_ci [ADF_CODE >> 20] = float64_add, 438c2ecf20Sopenharmony_ci [MUF_CODE >> 20] = float64_mul, 448c2ecf20Sopenharmony_ci [SUF_CODE >> 20] = float64_sub, 458c2ecf20Sopenharmony_ci [RSF_CODE >> 20] = float64_rsf, 468c2ecf20Sopenharmony_ci [DVF_CODE >> 20] = float64_div, 478c2ecf20Sopenharmony_ci [RDF_CODE >> 20] = float64_rdv, 488c2ecf20Sopenharmony_ci [RMF_CODE >> 20] = float64_rem, 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci /* strictly, these opcodes should not be implemented */ 518c2ecf20Sopenharmony_ci [FML_CODE >> 20] = float64_mul, 528c2ecf20Sopenharmony_ci [FDV_CODE >> 20] = float64_div, 538c2ecf20Sopenharmony_ci [FRD_CODE >> 20] = float64_rdv, 548c2ecf20Sopenharmony_ci}; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistatic float64 float64_mvf(struct roundingData *roundData,float64 rFm) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci return rFm; 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic float64 float64_mnf(struct roundingData *roundData,float64 rFm) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci union float64_components u; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci u.f64 = rFm; 668c2ecf20Sopenharmony_ci#ifdef __ARMEB__ 678c2ecf20Sopenharmony_ci u.i[0] ^= 0x80000000; 688c2ecf20Sopenharmony_ci#else 698c2ecf20Sopenharmony_ci u.i[1] ^= 0x80000000; 708c2ecf20Sopenharmony_ci#endif 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci return u.f64; 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic float64 float64_abs(struct roundingData *roundData,float64 rFm) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci union float64_components u; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci u.f64 = rFm; 808c2ecf20Sopenharmony_ci#ifdef __ARMEB__ 818c2ecf20Sopenharmony_ci u.i[0] &= 0x7fffffff; 828c2ecf20Sopenharmony_ci#else 838c2ecf20Sopenharmony_ci u.i[1] &= 0x7fffffff; 848c2ecf20Sopenharmony_ci#endif 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci return u.f64; 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic float64 (*const monadic_double[16])(struct roundingData *, float64 rFm) = { 908c2ecf20Sopenharmony_ci [MVF_CODE >> 20] = float64_mvf, 918c2ecf20Sopenharmony_ci [MNF_CODE >> 20] = float64_mnf, 928c2ecf20Sopenharmony_ci [ABS_CODE >> 20] = float64_abs, 938c2ecf20Sopenharmony_ci [RND_CODE >> 20] = float64_round_to_int, 948c2ecf20Sopenharmony_ci [URD_CODE >> 20] = float64_round_to_int, 958c2ecf20Sopenharmony_ci [SQT_CODE >> 20] = float64_sqrt, 968c2ecf20Sopenharmony_ci [NRM_CODE >> 20] = float64_mvf, 978c2ecf20Sopenharmony_ci}; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ciunsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci FPA11 *fpa11 = GET_FPA11(); 1028c2ecf20Sopenharmony_ci float64 rFm; 1038c2ecf20Sopenharmony_ci unsigned int Fm, opc_mask_shift; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci Fm = getFm(opcode); 1068c2ecf20Sopenharmony_ci if (CONSTANT_FM(opcode)) { 1078c2ecf20Sopenharmony_ci rFm = getDoubleConstant(Fm); 1088c2ecf20Sopenharmony_ci } else { 1098c2ecf20Sopenharmony_ci switch (fpa11->fType[Fm]) { 1108c2ecf20Sopenharmony_ci case typeSingle: 1118c2ecf20Sopenharmony_ci rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle); 1128c2ecf20Sopenharmony_ci break; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci case typeDouble: 1158c2ecf20Sopenharmony_ci rFm = fpa11->fpreg[Fm].fDouble; 1168c2ecf20Sopenharmony_ci break; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci default: 1198c2ecf20Sopenharmony_ci return 0; 1208c2ecf20Sopenharmony_ci } 1218c2ecf20Sopenharmony_ci } 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20; 1248c2ecf20Sopenharmony_ci if (!MONADIC_INSTRUCTION(opcode)) { 1258c2ecf20Sopenharmony_ci unsigned int Fn = getFn(opcode); 1268c2ecf20Sopenharmony_ci float64 rFn; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci switch (fpa11->fType[Fn]) { 1298c2ecf20Sopenharmony_ci case typeSingle: 1308c2ecf20Sopenharmony_ci rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle); 1318c2ecf20Sopenharmony_ci break; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci case typeDouble: 1348c2ecf20Sopenharmony_ci rFn = fpa11->fpreg[Fn].fDouble; 1358c2ecf20Sopenharmony_ci break; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci default: 1388c2ecf20Sopenharmony_ci return 0; 1398c2ecf20Sopenharmony_ci } 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci if (dyadic_double[opc_mask_shift]) { 1428c2ecf20Sopenharmony_ci rFd->fDouble = dyadic_double[opc_mask_shift](roundData, rFn, rFm); 1438c2ecf20Sopenharmony_ci } else { 1448c2ecf20Sopenharmony_ci return 0; 1458c2ecf20Sopenharmony_ci } 1468c2ecf20Sopenharmony_ci } else { 1478c2ecf20Sopenharmony_ci if (monadic_double[opc_mask_shift]) { 1488c2ecf20Sopenharmony_ci rFd->fDouble = monadic_double[opc_mask_shift](roundData, rFm); 1498c2ecf20Sopenharmony_ci } else { 1508c2ecf20Sopenharmony_ci return 0; 1518c2ecf20Sopenharmony_ci } 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci return 1; 1558c2ecf20Sopenharmony_ci} 156