xref: /OK3568_Linux_fs/kernel/arch/arm/nwfpe/extended_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 
6*4882a593Smuzhiyun     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include "fpa11.h"
11*4882a593Smuzhiyun #include "softfloat.h"
12*4882a593Smuzhiyun #include "fpopcode.h"
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun floatx80 floatx80_exp(floatx80 Fm);
15*4882a593Smuzhiyun floatx80 floatx80_ln(floatx80 Fm);
16*4882a593Smuzhiyun floatx80 floatx80_sin(floatx80 rFm);
17*4882a593Smuzhiyun floatx80 floatx80_cos(floatx80 rFm);
18*4882a593Smuzhiyun floatx80 floatx80_arcsin(floatx80 rFm);
19*4882a593Smuzhiyun floatx80 floatx80_arctan(floatx80 rFm);
20*4882a593Smuzhiyun floatx80 floatx80_log(floatx80 rFm);
21*4882a593Smuzhiyun floatx80 floatx80_tan(floatx80 rFm);
22*4882a593Smuzhiyun floatx80 floatx80_arccos(floatx80 rFm);
23*4882a593Smuzhiyun floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm);
24*4882a593Smuzhiyun floatx80 floatx80_pol(floatx80 rFn, floatx80 rFm);
25*4882a593Smuzhiyun 
floatx80_rsf(struct roundingData * roundData,floatx80 rFn,floatx80 rFm)26*4882a593Smuzhiyun static floatx80 floatx80_rsf(struct roundingData *roundData, floatx80 rFn, floatx80 rFm)
27*4882a593Smuzhiyun {
28*4882a593Smuzhiyun 	return floatx80_sub(roundData, rFm, rFn);
29*4882a593Smuzhiyun }
30*4882a593Smuzhiyun 
floatx80_rdv(struct roundingData * roundData,floatx80 rFn,floatx80 rFm)31*4882a593Smuzhiyun static floatx80 floatx80_rdv(struct roundingData *roundData, floatx80 rFn, floatx80 rFm)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun 	return floatx80_div(roundData, rFm, rFn);
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun static floatx80 (*const dyadic_extended[16])(struct roundingData*, floatx80 rFn, floatx80 rFm) = {
37*4882a593Smuzhiyun 	[ADF_CODE >> 20] = floatx80_add,
38*4882a593Smuzhiyun 	[MUF_CODE >> 20] = floatx80_mul,
39*4882a593Smuzhiyun 	[SUF_CODE >> 20] = floatx80_sub,
40*4882a593Smuzhiyun 	[RSF_CODE >> 20] = floatx80_rsf,
41*4882a593Smuzhiyun 	[DVF_CODE >> 20] = floatx80_div,
42*4882a593Smuzhiyun 	[RDF_CODE >> 20] = floatx80_rdv,
43*4882a593Smuzhiyun 	[RMF_CODE >> 20] = floatx80_rem,
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 	/* strictly, these opcodes should not be implemented */
46*4882a593Smuzhiyun 	[FML_CODE >> 20] = floatx80_mul,
47*4882a593Smuzhiyun 	[FDV_CODE >> 20] = floatx80_div,
48*4882a593Smuzhiyun 	[FRD_CODE >> 20] = floatx80_rdv,
49*4882a593Smuzhiyun };
50*4882a593Smuzhiyun 
floatx80_mvf(struct roundingData * roundData,floatx80 rFm)51*4882a593Smuzhiyun static floatx80 floatx80_mvf(struct roundingData *roundData, floatx80 rFm)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun 	return rFm;
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun 
floatx80_mnf(struct roundingData * roundData,floatx80 rFm)56*4882a593Smuzhiyun static floatx80 floatx80_mnf(struct roundingData *roundData, floatx80 rFm)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun 	rFm.high ^= 0x8000;
59*4882a593Smuzhiyun 	return rFm;
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun 
floatx80_abs(struct roundingData * roundData,floatx80 rFm)62*4882a593Smuzhiyun static floatx80 floatx80_abs(struct roundingData *roundData, floatx80 rFm)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun 	rFm.high &= 0x7fff;
65*4882a593Smuzhiyun 	return rFm;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun static floatx80 (*const monadic_extended[16])(struct roundingData*, floatx80 rFm) = {
69*4882a593Smuzhiyun 	[MVF_CODE >> 20] = floatx80_mvf,
70*4882a593Smuzhiyun 	[MNF_CODE >> 20] = floatx80_mnf,
71*4882a593Smuzhiyun 	[ABS_CODE >> 20] = floatx80_abs,
72*4882a593Smuzhiyun 	[RND_CODE >> 20] = floatx80_round_to_int,
73*4882a593Smuzhiyun 	[URD_CODE >> 20] = floatx80_round_to_int,
74*4882a593Smuzhiyun 	[SQT_CODE >> 20] = floatx80_sqrt,
75*4882a593Smuzhiyun 	[NRM_CODE >> 20] = floatx80_mvf,
76*4882a593Smuzhiyun };
77*4882a593Smuzhiyun 
ExtendedCPDO(struct roundingData * roundData,const unsigned int opcode,FPREG * rFd)78*4882a593Smuzhiyun unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun 	FPA11 *fpa11 = GET_FPA11();
81*4882a593Smuzhiyun 	floatx80 rFm;
82*4882a593Smuzhiyun 	unsigned int Fm, opc_mask_shift;
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	Fm = getFm(opcode);
85*4882a593Smuzhiyun 	if (CONSTANT_FM(opcode)) {
86*4882a593Smuzhiyun 		rFm = getExtendedConstant(Fm);
87*4882a593Smuzhiyun 	} else {
88*4882a593Smuzhiyun 		switch (fpa11->fType[Fm]) {
89*4882a593Smuzhiyun 		case typeSingle:
90*4882a593Smuzhiyun 			rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
91*4882a593Smuzhiyun 			break;
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 		case typeDouble:
94*4882a593Smuzhiyun 			rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble);
95*4882a593Smuzhiyun 			break;
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 		case typeExtended:
98*4882a593Smuzhiyun 			rFm = fpa11->fpreg[Fm].fExtended;
99*4882a593Smuzhiyun 			break;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 		default:
102*4882a593Smuzhiyun 			return 0;
103*4882a593Smuzhiyun 		}
104*4882a593Smuzhiyun 	}
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
107*4882a593Smuzhiyun 	if (!MONADIC_INSTRUCTION(opcode)) {
108*4882a593Smuzhiyun 		unsigned int Fn = getFn(opcode);
109*4882a593Smuzhiyun 		floatx80 rFn;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 		switch (fpa11->fType[Fn]) {
112*4882a593Smuzhiyun 		case typeSingle:
113*4882a593Smuzhiyun 			rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
114*4882a593Smuzhiyun 			break;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 		case typeDouble:
117*4882a593Smuzhiyun 			rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
118*4882a593Smuzhiyun 			break;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 		case typeExtended:
121*4882a593Smuzhiyun 			rFn = fpa11->fpreg[Fn].fExtended;
122*4882a593Smuzhiyun 			break;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 		default:
125*4882a593Smuzhiyun 			return 0;
126*4882a593Smuzhiyun 		}
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 		if (dyadic_extended[opc_mask_shift]) {
129*4882a593Smuzhiyun 			rFd->fExtended = dyadic_extended[opc_mask_shift](roundData, rFn, rFm);
130*4882a593Smuzhiyun 		} else {
131*4882a593Smuzhiyun 			return 0;
132*4882a593Smuzhiyun 		}
133*4882a593Smuzhiyun 	} else {
134*4882a593Smuzhiyun 		if (monadic_extended[opc_mask_shift]) {
135*4882a593Smuzhiyun 			rFd->fExtended = monadic_extended[opc_mask_shift](roundData, rFm);
136*4882a593Smuzhiyun 		} else {
137*4882a593Smuzhiyun 			return 0;
138*4882a593Smuzhiyun 		}
139*4882a593Smuzhiyun 	}
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	return 1;
142*4882a593Smuzhiyun }
143