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_cifloatx80 floatx80_exp(floatx80 Fm); 158c2ecf20Sopenharmony_cifloatx80 floatx80_ln(floatx80 Fm); 168c2ecf20Sopenharmony_cifloatx80 floatx80_sin(floatx80 rFm); 178c2ecf20Sopenharmony_cifloatx80 floatx80_cos(floatx80 rFm); 188c2ecf20Sopenharmony_cifloatx80 floatx80_arcsin(floatx80 rFm); 198c2ecf20Sopenharmony_cifloatx80 floatx80_arctan(floatx80 rFm); 208c2ecf20Sopenharmony_cifloatx80 floatx80_log(floatx80 rFm); 218c2ecf20Sopenharmony_cifloatx80 floatx80_tan(floatx80 rFm); 228c2ecf20Sopenharmony_cifloatx80 floatx80_arccos(floatx80 rFm); 238c2ecf20Sopenharmony_cifloatx80 floatx80_pow(floatx80 rFn, floatx80 rFm); 248c2ecf20Sopenharmony_cifloatx80 floatx80_pol(floatx80 rFn, floatx80 rFm); 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic floatx80 floatx80_rsf(struct roundingData *roundData, floatx80 rFn, floatx80 rFm) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci return floatx80_sub(roundData, rFm, rFn); 298c2ecf20Sopenharmony_ci} 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic floatx80 floatx80_rdv(struct roundingData *roundData, floatx80 rFn, floatx80 rFm) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci return floatx80_div(roundData, rFm, rFn); 348c2ecf20Sopenharmony_ci} 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic floatx80 (*const dyadic_extended[16])(struct roundingData*, floatx80 rFn, floatx80 rFm) = { 378c2ecf20Sopenharmony_ci [ADF_CODE >> 20] = floatx80_add, 388c2ecf20Sopenharmony_ci [MUF_CODE >> 20] = floatx80_mul, 398c2ecf20Sopenharmony_ci [SUF_CODE >> 20] = floatx80_sub, 408c2ecf20Sopenharmony_ci [RSF_CODE >> 20] = floatx80_rsf, 418c2ecf20Sopenharmony_ci [DVF_CODE >> 20] = floatx80_div, 428c2ecf20Sopenharmony_ci [RDF_CODE >> 20] = floatx80_rdv, 438c2ecf20Sopenharmony_ci [RMF_CODE >> 20] = floatx80_rem, 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci /* strictly, these opcodes should not be implemented */ 468c2ecf20Sopenharmony_ci [FML_CODE >> 20] = floatx80_mul, 478c2ecf20Sopenharmony_ci [FDV_CODE >> 20] = floatx80_div, 488c2ecf20Sopenharmony_ci [FRD_CODE >> 20] = floatx80_rdv, 498c2ecf20Sopenharmony_ci}; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cistatic floatx80 floatx80_mvf(struct roundingData *roundData, floatx80 rFm) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci return rFm; 548c2ecf20Sopenharmony_ci} 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistatic floatx80 floatx80_mnf(struct roundingData *roundData, floatx80 rFm) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci rFm.high ^= 0x8000; 598c2ecf20Sopenharmony_ci return rFm; 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistatic floatx80 floatx80_abs(struct roundingData *roundData, floatx80 rFm) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci rFm.high &= 0x7fff; 658c2ecf20Sopenharmony_ci return rFm; 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic floatx80 (*const monadic_extended[16])(struct roundingData*, floatx80 rFm) = { 698c2ecf20Sopenharmony_ci [MVF_CODE >> 20] = floatx80_mvf, 708c2ecf20Sopenharmony_ci [MNF_CODE >> 20] = floatx80_mnf, 718c2ecf20Sopenharmony_ci [ABS_CODE >> 20] = floatx80_abs, 728c2ecf20Sopenharmony_ci [RND_CODE >> 20] = floatx80_round_to_int, 738c2ecf20Sopenharmony_ci [URD_CODE >> 20] = floatx80_round_to_int, 748c2ecf20Sopenharmony_ci [SQT_CODE >> 20] = floatx80_sqrt, 758c2ecf20Sopenharmony_ci [NRM_CODE >> 20] = floatx80_mvf, 768c2ecf20Sopenharmony_ci}; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ciunsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci FPA11 *fpa11 = GET_FPA11(); 818c2ecf20Sopenharmony_ci floatx80 rFm; 828c2ecf20Sopenharmony_ci unsigned int Fm, opc_mask_shift; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci Fm = getFm(opcode); 858c2ecf20Sopenharmony_ci if (CONSTANT_FM(opcode)) { 868c2ecf20Sopenharmony_ci rFm = getExtendedConstant(Fm); 878c2ecf20Sopenharmony_ci } else { 888c2ecf20Sopenharmony_ci switch (fpa11->fType[Fm]) { 898c2ecf20Sopenharmony_ci case typeSingle: 908c2ecf20Sopenharmony_ci rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle); 918c2ecf20Sopenharmony_ci break; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci case typeDouble: 948c2ecf20Sopenharmony_ci rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble); 958c2ecf20Sopenharmony_ci break; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci case typeExtended: 988c2ecf20Sopenharmony_ci rFm = fpa11->fpreg[Fm].fExtended; 998c2ecf20Sopenharmony_ci break; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci default: 1028c2ecf20Sopenharmony_ci return 0; 1038c2ecf20Sopenharmony_ci } 1048c2ecf20Sopenharmony_ci } 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20; 1078c2ecf20Sopenharmony_ci if (!MONADIC_INSTRUCTION(opcode)) { 1088c2ecf20Sopenharmony_ci unsigned int Fn = getFn(opcode); 1098c2ecf20Sopenharmony_ci floatx80 rFn; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci switch (fpa11->fType[Fn]) { 1128c2ecf20Sopenharmony_ci case typeSingle: 1138c2ecf20Sopenharmony_ci rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); 1148c2ecf20Sopenharmony_ci break; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci case typeDouble: 1178c2ecf20Sopenharmony_ci rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); 1188c2ecf20Sopenharmony_ci break; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci case typeExtended: 1218c2ecf20Sopenharmony_ci rFn = fpa11->fpreg[Fn].fExtended; 1228c2ecf20Sopenharmony_ci break; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci default: 1258c2ecf20Sopenharmony_ci return 0; 1268c2ecf20Sopenharmony_ci } 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci if (dyadic_extended[opc_mask_shift]) { 1298c2ecf20Sopenharmony_ci rFd->fExtended = dyadic_extended[opc_mask_shift](roundData, rFn, rFm); 1308c2ecf20Sopenharmony_ci } else { 1318c2ecf20Sopenharmony_ci return 0; 1328c2ecf20Sopenharmony_ci } 1338c2ecf20Sopenharmony_ci } else { 1348c2ecf20Sopenharmony_ci if (monadic_extended[opc_mask_shift]) { 1358c2ecf20Sopenharmony_ci rFd->fExtended = monadic_extended[opc_mask_shift](roundData, rFm); 1368c2ecf20Sopenharmony_ci } else { 1378c2ecf20Sopenharmony_ci return 0; 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci } 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci return 1; 1428c2ecf20Sopenharmony_ci} 143