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