162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci NetWinder Floating Point Emulator 462306a36Sopenharmony_ci (c) Rebel.COM, 1998,1999 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci Direct questions, comments to Scott Bambrough <scottb@netwinder.org> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci*/ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include "fpa11.h" 1162306a36Sopenharmony_ci#include "softfloat.h" 1262306a36Sopenharmony_ci#include "fpopcode.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_cifloatx80 floatx80_exp(floatx80 Fm); 1562306a36Sopenharmony_cifloatx80 floatx80_ln(floatx80 Fm); 1662306a36Sopenharmony_cifloatx80 floatx80_sin(floatx80 rFm); 1762306a36Sopenharmony_cifloatx80 floatx80_cos(floatx80 rFm); 1862306a36Sopenharmony_cifloatx80 floatx80_arcsin(floatx80 rFm); 1962306a36Sopenharmony_cifloatx80 floatx80_arctan(floatx80 rFm); 2062306a36Sopenharmony_cifloatx80 floatx80_log(floatx80 rFm); 2162306a36Sopenharmony_cifloatx80 floatx80_tan(floatx80 rFm); 2262306a36Sopenharmony_cifloatx80 floatx80_arccos(floatx80 rFm); 2362306a36Sopenharmony_cifloatx80 floatx80_pow(floatx80 rFn, floatx80 rFm); 2462306a36Sopenharmony_cifloatx80 floatx80_pol(floatx80 rFn, floatx80 rFm); 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic floatx80 floatx80_rsf(struct roundingData *roundData, floatx80 rFn, floatx80 rFm) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci return floatx80_sub(roundData, rFm, rFn); 2962306a36Sopenharmony_ci} 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistatic floatx80 floatx80_rdv(struct roundingData *roundData, floatx80 rFn, floatx80 rFm) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci return floatx80_div(roundData, rFm, rFn); 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic floatx80 (*const dyadic_extended[16])(struct roundingData*, floatx80 rFn, floatx80 rFm) = { 3762306a36Sopenharmony_ci [ADF_CODE >> 20] = floatx80_add, 3862306a36Sopenharmony_ci [MUF_CODE >> 20] = floatx80_mul, 3962306a36Sopenharmony_ci [SUF_CODE >> 20] = floatx80_sub, 4062306a36Sopenharmony_ci [RSF_CODE >> 20] = floatx80_rsf, 4162306a36Sopenharmony_ci [DVF_CODE >> 20] = floatx80_div, 4262306a36Sopenharmony_ci [RDF_CODE >> 20] = floatx80_rdv, 4362306a36Sopenharmony_ci [RMF_CODE >> 20] = floatx80_rem, 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci /* strictly, these opcodes should not be implemented */ 4662306a36Sopenharmony_ci [FML_CODE >> 20] = floatx80_mul, 4762306a36Sopenharmony_ci [FDV_CODE >> 20] = floatx80_div, 4862306a36Sopenharmony_ci [FRD_CODE >> 20] = floatx80_rdv, 4962306a36Sopenharmony_ci}; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic floatx80 floatx80_mvf(struct roundingData *roundData, floatx80 rFm) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci return rFm; 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic floatx80 floatx80_mnf(struct roundingData *roundData, floatx80 rFm) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci rFm.high ^= 0x8000; 5962306a36Sopenharmony_ci return rFm; 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistatic floatx80 floatx80_abs(struct roundingData *roundData, floatx80 rFm) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci rFm.high &= 0x7fff; 6562306a36Sopenharmony_ci return rFm; 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic floatx80 (*const monadic_extended[16])(struct roundingData*, floatx80 rFm) = { 6962306a36Sopenharmony_ci [MVF_CODE >> 20] = floatx80_mvf, 7062306a36Sopenharmony_ci [MNF_CODE >> 20] = floatx80_mnf, 7162306a36Sopenharmony_ci [ABS_CODE >> 20] = floatx80_abs, 7262306a36Sopenharmony_ci [RND_CODE >> 20] = floatx80_round_to_int, 7362306a36Sopenharmony_ci [URD_CODE >> 20] = floatx80_round_to_int, 7462306a36Sopenharmony_ci [SQT_CODE >> 20] = floatx80_sqrt, 7562306a36Sopenharmony_ci [NRM_CODE >> 20] = floatx80_mvf, 7662306a36Sopenharmony_ci}; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ciunsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci FPA11 *fpa11 = GET_FPA11(); 8162306a36Sopenharmony_ci floatx80 rFm; 8262306a36Sopenharmony_ci unsigned int Fm, opc_mask_shift; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci Fm = getFm(opcode); 8562306a36Sopenharmony_ci if (CONSTANT_FM(opcode)) { 8662306a36Sopenharmony_ci rFm = getExtendedConstant(Fm); 8762306a36Sopenharmony_ci } else { 8862306a36Sopenharmony_ci switch (fpa11->fType[Fm]) { 8962306a36Sopenharmony_ci case typeSingle: 9062306a36Sopenharmony_ci rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle); 9162306a36Sopenharmony_ci break; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci case typeDouble: 9462306a36Sopenharmony_ci rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble); 9562306a36Sopenharmony_ci break; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci case typeExtended: 9862306a36Sopenharmony_ci rFm = fpa11->fpreg[Fm].fExtended; 9962306a36Sopenharmony_ci break; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci default: 10262306a36Sopenharmony_ci return 0; 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20; 10762306a36Sopenharmony_ci if (!MONADIC_INSTRUCTION(opcode)) { 10862306a36Sopenharmony_ci unsigned int Fn = getFn(opcode); 10962306a36Sopenharmony_ci floatx80 rFn; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci switch (fpa11->fType[Fn]) { 11262306a36Sopenharmony_ci case typeSingle: 11362306a36Sopenharmony_ci rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); 11462306a36Sopenharmony_ci break; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci case typeDouble: 11762306a36Sopenharmony_ci rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); 11862306a36Sopenharmony_ci break; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci case typeExtended: 12162306a36Sopenharmony_ci rFn = fpa11->fpreg[Fn].fExtended; 12262306a36Sopenharmony_ci break; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci default: 12562306a36Sopenharmony_ci return 0; 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci if (dyadic_extended[opc_mask_shift]) { 12962306a36Sopenharmony_ci rFd->fExtended = dyadic_extended[opc_mask_shift](roundData, rFn, rFm); 13062306a36Sopenharmony_ci } else { 13162306a36Sopenharmony_ci return 0; 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci } else { 13462306a36Sopenharmony_ci if (monadic_extended[opc_mask_shift]) { 13562306a36Sopenharmony_ci rFd->fExtended = monadic_extended[opc_mask_shift](roundData, rFm); 13662306a36Sopenharmony_ci } else { 13762306a36Sopenharmony_ci return 0; 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci return 1; 14262306a36Sopenharmony_ci} 143