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_ciunion float64_components { 1562306a36Sopenharmony_ci float64 f64; 1662306a36Sopenharmony_ci unsigned int i[2]; 1762306a36Sopenharmony_ci}; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cifloat64 float64_exp(float64 Fm); 2062306a36Sopenharmony_cifloat64 float64_ln(float64 Fm); 2162306a36Sopenharmony_cifloat64 float64_sin(float64 rFm); 2262306a36Sopenharmony_cifloat64 float64_cos(float64 rFm); 2362306a36Sopenharmony_cifloat64 float64_arcsin(float64 rFm); 2462306a36Sopenharmony_cifloat64 float64_arctan(float64 rFm); 2562306a36Sopenharmony_cifloat64 float64_log(float64 rFm); 2662306a36Sopenharmony_cifloat64 float64_tan(float64 rFm); 2762306a36Sopenharmony_cifloat64 float64_arccos(float64 rFm); 2862306a36Sopenharmony_cifloat64 float64_pow(float64 rFn, float64 rFm); 2962306a36Sopenharmony_cifloat64 float64_pol(float64 rFn, float64 rFm); 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistatic float64 float64_rsf(struct roundingData *roundData, float64 rFn, float64 rFm) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci return float64_sub(roundData, rFm, rFn); 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic float64 float64_rdv(struct roundingData *roundData, float64 rFn, float64 rFm) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci return float64_div(roundData, rFm, rFn); 3962306a36Sopenharmony_ci} 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic float64 (*const dyadic_double[16])(struct roundingData*, float64 rFn, float64 rFm) = { 4262306a36Sopenharmony_ci [ADF_CODE >> 20] = float64_add, 4362306a36Sopenharmony_ci [MUF_CODE >> 20] = float64_mul, 4462306a36Sopenharmony_ci [SUF_CODE >> 20] = float64_sub, 4562306a36Sopenharmony_ci [RSF_CODE >> 20] = float64_rsf, 4662306a36Sopenharmony_ci [DVF_CODE >> 20] = float64_div, 4762306a36Sopenharmony_ci [RDF_CODE >> 20] = float64_rdv, 4862306a36Sopenharmony_ci [RMF_CODE >> 20] = float64_rem, 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci /* strictly, these opcodes should not be implemented */ 5162306a36Sopenharmony_ci [FML_CODE >> 20] = float64_mul, 5262306a36Sopenharmony_ci [FDV_CODE >> 20] = float64_div, 5362306a36Sopenharmony_ci [FRD_CODE >> 20] = float64_rdv, 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic float64 float64_mvf(struct roundingData *roundData,float64 rFm) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci return rFm; 5962306a36Sopenharmony_ci} 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic float64 float64_mnf(struct roundingData *roundData,float64 rFm) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci union float64_components u; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci u.f64 = rFm; 6662306a36Sopenharmony_ci#ifdef __ARMEB__ 6762306a36Sopenharmony_ci u.i[0] ^= 0x80000000; 6862306a36Sopenharmony_ci#else 6962306a36Sopenharmony_ci u.i[1] ^= 0x80000000; 7062306a36Sopenharmony_ci#endif 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci return u.f64; 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistatic float64 float64_abs(struct roundingData *roundData,float64 rFm) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci union float64_components u; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci u.f64 = rFm; 8062306a36Sopenharmony_ci#ifdef __ARMEB__ 8162306a36Sopenharmony_ci u.i[0] &= 0x7fffffff; 8262306a36Sopenharmony_ci#else 8362306a36Sopenharmony_ci u.i[1] &= 0x7fffffff; 8462306a36Sopenharmony_ci#endif 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci return u.f64; 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic float64 (*const monadic_double[16])(struct roundingData *, float64 rFm) = { 9062306a36Sopenharmony_ci [MVF_CODE >> 20] = float64_mvf, 9162306a36Sopenharmony_ci [MNF_CODE >> 20] = float64_mnf, 9262306a36Sopenharmony_ci [ABS_CODE >> 20] = float64_abs, 9362306a36Sopenharmony_ci [RND_CODE >> 20] = float64_round_to_int, 9462306a36Sopenharmony_ci [URD_CODE >> 20] = float64_round_to_int, 9562306a36Sopenharmony_ci [SQT_CODE >> 20] = float64_sqrt, 9662306a36Sopenharmony_ci [NRM_CODE >> 20] = float64_mvf, 9762306a36Sopenharmony_ci}; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ciunsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd) 10062306a36Sopenharmony_ci{ 10162306a36Sopenharmony_ci FPA11 *fpa11 = GET_FPA11(); 10262306a36Sopenharmony_ci float64 rFm; 10362306a36Sopenharmony_ci unsigned int Fm, opc_mask_shift; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci Fm = getFm(opcode); 10662306a36Sopenharmony_ci if (CONSTANT_FM(opcode)) { 10762306a36Sopenharmony_ci rFm = getDoubleConstant(Fm); 10862306a36Sopenharmony_ci } else { 10962306a36Sopenharmony_ci switch (fpa11->fType[Fm]) { 11062306a36Sopenharmony_ci case typeSingle: 11162306a36Sopenharmony_ci rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle); 11262306a36Sopenharmony_ci break; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci case typeDouble: 11562306a36Sopenharmony_ci rFm = fpa11->fpreg[Fm].fDouble; 11662306a36Sopenharmony_ci break; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci default: 11962306a36Sopenharmony_ci return 0; 12062306a36Sopenharmony_ci } 12162306a36Sopenharmony_ci } 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20; 12462306a36Sopenharmony_ci if (!MONADIC_INSTRUCTION(opcode)) { 12562306a36Sopenharmony_ci unsigned int Fn = getFn(opcode); 12662306a36Sopenharmony_ci float64 rFn; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci switch (fpa11->fType[Fn]) { 12962306a36Sopenharmony_ci case typeSingle: 13062306a36Sopenharmony_ci rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle); 13162306a36Sopenharmony_ci break; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci case typeDouble: 13462306a36Sopenharmony_ci rFn = fpa11->fpreg[Fn].fDouble; 13562306a36Sopenharmony_ci break; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci default: 13862306a36Sopenharmony_ci return 0; 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci if (dyadic_double[opc_mask_shift]) { 14262306a36Sopenharmony_ci rFd->fDouble = dyadic_double[opc_mask_shift](roundData, rFn, rFm); 14362306a36Sopenharmony_ci } else { 14462306a36Sopenharmony_ci return 0; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci } else { 14762306a36Sopenharmony_ci if (monadic_double[opc_mask_shift]) { 14862306a36Sopenharmony_ci rFd->fDouble = monadic_double[opc_mask_shift](roundData, rFm); 14962306a36Sopenharmony_ci } else { 15062306a36Sopenharmony_ci return 0; 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci } 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci return 1; 15562306a36Sopenharmony_ci} 156