xref: /OK3568_Linux_fs/kernel/arch/arm/nwfpe/single_cpdo.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun     NetWinder Floating Point Emulator
4*4882a593Smuzhiyun     (c) Rebel.COM, 1998,1999
5*4882a593Smuzhiyun     (c) Philip Blundell, 2001
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include "fpa11.h"
12*4882a593Smuzhiyun #include "softfloat.h"
13*4882a593Smuzhiyun #include "fpopcode.h"
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun float32 float32_exp(float32 Fm);
16*4882a593Smuzhiyun float32 float32_ln(float32 Fm);
17*4882a593Smuzhiyun float32 float32_sin(float32 rFm);
18*4882a593Smuzhiyun float32 float32_cos(float32 rFm);
19*4882a593Smuzhiyun float32 float32_arcsin(float32 rFm);
20*4882a593Smuzhiyun float32 float32_arctan(float32 rFm);
21*4882a593Smuzhiyun float32 float32_log(float32 rFm);
22*4882a593Smuzhiyun float32 float32_tan(float32 rFm);
23*4882a593Smuzhiyun float32 float32_arccos(float32 rFm);
24*4882a593Smuzhiyun float32 float32_pow(float32 rFn, float32 rFm);
25*4882a593Smuzhiyun float32 float32_pol(float32 rFn, float32 rFm);
26*4882a593Smuzhiyun 
float32_rsf(struct roundingData * roundData,float32 rFn,float32 rFm)27*4882a593Smuzhiyun static float32 float32_rsf(struct roundingData *roundData, float32 rFn, float32 rFm)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun 	return float32_sub(roundData, rFm, rFn);
30*4882a593Smuzhiyun }
31*4882a593Smuzhiyun 
float32_rdv(struct roundingData * roundData,float32 rFn,float32 rFm)32*4882a593Smuzhiyun static float32 float32_rdv(struct roundingData *roundData, float32 rFn, float32 rFm)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun 	return float32_div(roundData, rFm, rFn);
35*4882a593Smuzhiyun }
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun static float32 (*const dyadic_single[16])(struct roundingData *, float32 rFn, float32 rFm) = {
38*4882a593Smuzhiyun 	[ADF_CODE >> 20] = float32_add,
39*4882a593Smuzhiyun 	[MUF_CODE >> 20] = float32_mul,
40*4882a593Smuzhiyun 	[SUF_CODE >> 20] = float32_sub,
41*4882a593Smuzhiyun 	[RSF_CODE >> 20] = float32_rsf,
42*4882a593Smuzhiyun 	[DVF_CODE >> 20] = float32_div,
43*4882a593Smuzhiyun 	[RDF_CODE >> 20] = float32_rdv,
44*4882a593Smuzhiyun 	[RMF_CODE >> 20] = float32_rem,
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	[FML_CODE >> 20] = float32_mul,
47*4882a593Smuzhiyun 	[FDV_CODE >> 20] = float32_div,
48*4882a593Smuzhiyun 	[FRD_CODE >> 20] = float32_rdv,
49*4882a593Smuzhiyun };
50*4882a593Smuzhiyun 
float32_mvf(struct roundingData * roundData,float32 rFm)51*4882a593Smuzhiyun static float32 float32_mvf(struct roundingData *roundData, float32 rFm)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun 	return rFm;
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun 
float32_mnf(struct roundingData * roundData,float32 rFm)56*4882a593Smuzhiyun static float32 float32_mnf(struct roundingData *roundData, float32 rFm)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun 	return rFm ^ 0x80000000;
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun 
float32_abs(struct roundingData * roundData,float32 rFm)61*4882a593Smuzhiyun static float32 float32_abs(struct roundingData *roundData, float32 rFm)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun 	return rFm & 0x7fffffff;
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun static float32 (*const monadic_single[16])(struct roundingData*, float32 rFm) = {
67*4882a593Smuzhiyun 	[MVF_CODE >> 20] = float32_mvf,
68*4882a593Smuzhiyun 	[MNF_CODE >> 20] = float32_mnf,
69*4882a593Smuzhiyun 	[ABS_CODE >> 20] = float32_abs,
70*4882a593Smuzhiyun 	[RND_CODE >> 20] = float32_round_to_int,
71*4882a593Smuzhiyun 	[URD_CODE >> 20] = float32_round_to_int,
72*4882a593Smuzhiyun 	[SQT_CODE >> 20] = float32_sqrt,
73*4882a593Smuzhiyun 	[NRM_CODE >> 20] = float32_mvf,
74*4882a593Smuzhiyun };
75*4882a593Smuzhiyun 
SingleCPDO(struct roundingData * roundData,const unsigned int opcode,FPREG * rFd)76*4882a593Smuzhiyun unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun 	FPA11 *fpa11 = GET_FPA11();
79*4882a593Smuzhiyun 	float32 rFm;
80*4882a593Smuzhiyun 	unsigned int Fm, opc_mask_shift;
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	Fm = getFm(opcode);
83*4882a593Smuzhiyun 	if (CONSTANT_FM(opcode)) {
84*4882a593Smuzhiyun 		rFm = getSingleConstant(Fm);
85*4882a593Smuzhiyun 	} else if (fpa11->fType[Fm] == typeSingle) {
86*4882a593Smuzhiyun 		rFm = fpa11->fpreg[Fm].fSingle;
87*4882a593Smuzhiyun 	} else {
88*4882a593Smuzhiyun 		return 0;
89*4882a593Smuzhiyun 	}
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
92*4882a593Smuzhiyun 	if (!MONADIC_INSTRUCTION(opcode)) {
93*4882a593Smuzhiyun 		unsigned int Fn = getFn(opcode);
94*4882a593Smuzhiyun 		float32 rFn;
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 		if (fpa11->fType[Fn] == typeSingle &&
97*4882a593Smuzhiyun 		    dyadic_single[opc_mask_shift]) {
98*4882a593Smuzhiyun 			rFn = fpa11->fpreg[Fn].fSingle;
99*4882a593Smuzhiyun 			rFd->fSingle = dyadic_single[opc_mask_shift](roundData, rFn, rFm);
100*4882a593Smuzhiyun 		} else {
101*4882a593Smuzhiyun 			return 0;
102*4882a593Smuzhiyun 		}
103*4882a593Smuzhiyun 	} else {
104*4882a593Smuzhiyun 		if (monadic_single[opc_mask_shift]) {
105*4882a593Smuzhiyun 			rFd->fSingle = monadic_single[opc_mask_shift](roundData, rFm);
106*4882a593Smuzhiyun 		} else {
107*4882a593Smuzhiyun 			return 0;
108*4882a593Smuzhiyun 		}
109*4882a593Smuzhiyun 	}
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	return 1;
112*4882a593Smuzhiyun }
113