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 (c) Philip Blundell, 2001 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci Direct questions, comments to Scott Bambrough <scottb@netwinder.org> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci*/ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "fpa11.h" 1262306a36Sopenharmony_ci#include "softfloat.h" 1362306a36Sopenharmony_ci#include "fpopcode.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_cifloat32 float32_exp(float32 Fm); 1662306a36Sopenharmony_cifloat32 float32_ln(float32 Fm); 1762306a36Sopenharmony_cifloat32 float32_sin(float32 rFm); 1862306a36Sopenharmony_cifloat32 float32_cos(float32 rFm); 1962306a36Sopenharmony_cifloat32 float32_arcsin(float32 rFm); 2062306a36Sopenharmony_cifloat32 float32_arctan(float32 rFm); 2162306a36Sopenharmony_cifloat32 float32_log(float32 rFm); 2262306a36Sopenharmony_cifloat32 float32_tan(float32 rFm); 2362306a36Sopenharmony_cifloat32 float32_arccos(float32 rFm); 2462306a36Sopenharmony_cifloat32 float32_pow(float32 rFn, float32 rFm); 2562306a36Sopenharmony_cifloat32 float32_pol(float32 rFn, float32 rFm); 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic float32 float32_rsf(struct roundingData *roundData, float32 rFn, float32 rFm) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci return float32_sub(roundData, rFm, rFn); 3062306a36Sopenharmony_ci} 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic float32 float32_rdv(struct roundingData *roundData, float32 rFn, float32 rFm) 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci return float32_div(roundData, rFm, rFn); 3562306a36Sopenharmony_ci} 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic float32 (*const dyadic_single[16])(struct roundingData *, float32 rFn, float32 rFm) = { 3862306a36Sopenharmony_ci [ADF_CODE >> 20] = float32_add, 3962306a36Sopenharmony_ci [MUF_CODE >> 20] = float32_mul, 4062306a36Sopenharmony_ci [SUF_CODE >> 20] = float32_sub, 4162306a36Sopenharmony_ci [RSF_CODE >> 20] = float32_rsf, 4262306a36Sopenharmony_ci [DVF_CODE >> 20] = float32_div, 4362306a36Sopenharmony_ci [RDF_CODE >> 20] = float32_rdv, 4462306a36Sopenharmony_ci [RMF_CODE >> 20] = float32_rem, 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci [FML_CODE >> 20] = float32_mul, 4762306a36Sopenharmony_ci [FDV_CODE >> 20] = float32_div, 4862306a36Sopenharmony_ci [FRD_CODE >> 20] = float32_rdv, 4962306a36Sopenharmony_ci}; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic float32 float32_mvf(struct roundingData *roundData, float32 rFm) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci return rFm; 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic float32 float32_mnf(struct roundingData *roundData, float32 rFm) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci return rFm ^ 0x80000000; 5962306a36Sopenharmony_ci} 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic float32 float32_abs(struct roundingData *roundData, float32 rFm) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci return rFm & 0x7fffffff; 6462306a36Sopenharmony_ci} 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistatic float32 (*const monadic_single[16])(struct roundingData*, float32 rFm) = { 6762306a36Sopenharmony_ci [MVF_CODE >> 20] = float32_mvf, 6862306a36Sopenharmony_ci [MNF_CODE >> 20] = float32_mnf, 6962306a36Sopenharmony_ci [ABS_CODE >> 20] = float32_abs, 7062306a36Sopenharmony_ci [RND_CODE >> 20] = float32_round_to_int, 7162306a36Sopenharmony_ci [URD_CODE >> 20] = float32_round_to_int, 7262306a36Sopenharmony_ci [SQT_CODE >> 20] = float32_sqrt, 7362306a36Sopenharmony_ci [NRM_CODE >> 20] = float32_mvf, 7462306a36Sopenharmony_ci}; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ciunsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd) 7762306a36Sopenharmony_ci{ 7862306a36Sopenharmony_ci FPA11 *fpa11 = GET_FPA11(); 7962306a36Sopenharmony_ci float32 rFm; 8062306a36Sopenharmony_ci unsigned int Fm, opc_mask_shift; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci Fm = getFm(opcode); 8362306a36Sopenharmony_ci if (CONSTANT_FM(opcode)) { 8462306a36Sopenharmony_ci rFm = getSingleConstant(Fm); 8562306a36Sopenharmony_ci } else if (fpa11->fType[Fm] == typeSingle) { 8662306a36Sopenharmony_ci rFm = fpa11->fpreg[Fm].fSingle; 8762306a36Sopenharmony_ci } else { 8862306a36Sopenharmony_ci return 0; 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20; 9262306a36Sopenharmony_ci if (!MONADIC_INSTRUCTION(opcode)) { 9362306a36Sopenharmony_ci unsigned int Fn = getFn(opcode); 9462306a36Sopenharmony_ci float32 rFn; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci if (fpa11->fType[Fn] == typeSingle && 9762306a36Sopenharmony_ci dyadic_single[opc_mask_shift]) { 9862306a36Sopenharmony_ci rFn = fpa11->fpreg[Fn].fSingle; 9962306a36Sopenharmony_ci rFd->fSingle = dyadic_single[opc_mask_shift](roundData, rFn, rFm); 10062306a36Sopenharmony_ci } else { 10162306a36Sopenharmony_ci return 0; 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci } else { 10462306a36Sopenharmony_ci if (monadic_single[opc_mask_shift]) { 10562306a36Sopenharmony_ci rFd->fSingle = monadic_single[opc_mask_shift](roundData, rFm); 10662306a36Sopenharmony_ci } else { 10762306a36Sopenharmony_ci return 0; 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci } 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci return 1; 11262306a36Sopenharmony_ci} 113