xref: /openbmc/linux/arch/arm/nwfpe/extended_cpdo.c (revision 74ba9207)
174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds     NetWinder Floating Point Emulator
41da177e4SLinus Torvalds     (c) Rebel.COM, 1998,1999
51da177e4SLinus Torvalds 
61da177e4SLinus Torvalds     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
71da177e4SLinus Torvalds 
81da177e4SLinus Torvalds */
91da177e4SLinus Torvalds 
101da177e4SLinus Torvalds #include "fpa11.h"
111da177e4SLinus Torvalds #include "softfloat.h"
121da177e4SLinus Torvalds #include "fpopcode.h"
131da177e4SLinus Torvalds 
141da177e4SLinus Torvalds floatx80 floatx80_exp(floatx80 Fm);
151da177e4SLinus Torvalds floatx80 floatx80_ln(floatx80 Fm);
161da177e4SLinus Torvalds floatx80 floatx80_sin(floatx80 rFm);
171da177e4SLinus Torvalds floatx80 floatx80_cos(floatx80 rFm);
181da177e4SLinus Torvalds floatx80 floatx80_arcsin(floatx80 rFm);
191da177e4SLinus Torvalds floatx80 floatx80_arctan(floatx80 rFm);
201da177e4SLinus Torvalds floatx80 floatx80_log(floatx80 rFm);
211da177e4SLinus Torvalds floatx80 floatx80_tan(floatx80 rFm);
221da177e4SLinus Torvalds floatx80 floatx80_arccos(floatx80 rFm);
231da177e4SLinus Torvalds floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm);
241da177e4SLinus Torvalds floatx80 floatx80_pol(floatx80 rFn, floatx80 rFm);
251da177e4SLinus Torvalds 
floatx80_rsf(struct roundingData * roundData,floatx80 rFn,floatx80 rFm)26f148af25SRichard Purdie static floatx80 floatx80_rsf(struct roundingData *roundData, floatx80 rFn, floatx80 rFm)
271da177e4SLinus Torvalds {
28f148af25SRichard Purdie 	return floatx80_sub(roundData, rFm, rFn);
291da177e4SLinus Torvalds }
301da177e4SLinus Torvalds 
floatx80_rdv(struct roundingData * roundData,floatx80 rFn,floatx80 rFm)31f148af25SRichard Purdie static floatx80 floatx80_rdv(struct roundingData *roundData, floatx80 rFn, floatx80 rFm)
321da177e4SLinus Torvalds {
33f148af25SRichard Purdie 	return floatx80_div(roundData, rFm, rFn);
341da177e4SLinus Torvalds }
351da177e4SLinus Torvalds 
36f148af25SRichard Purdie static floatx80 (*const dyadic_extended[16])(struct roundingData*, floatx80 rFn, floatx80 rFm) = {
371da177e4SLinus Torvalds 	[ADF_CODE >> 20] = floatx80_add,
381da177e4SLinus Torvalds 	[MUF_CODE >> 20] = floatx80_mul,
391da177e4SLinus Torvalds 	[SUF_CODE >> 20] = floatx80_sub,
401da177e4SLinus Torvalds 	[RSF_CODE >> 20] = floatx80_rsf,
411da177e4SLinus Torvalds 	[DVF_CODE >> 20] = floatx80_div,
421da177e4SLinus Torvalds 	[RDF_CODE >> 20] = floatx80_rdv,
431da177e4SLinus Torvalds 	[RMF_CODE >> 20] = floatx80_rem,
441da177e4SLinus Torvalds 
451da177e4SLinus Torvalds 	/* strictly, these opcodes should not be implemented */
461da177e4SLinus Torvalds 	[FML_CODE >> 20] = floatx80_mul,
471da177e4SLinus Torvalds 	[FDV_CODE >> 20] = floatx80_div,
481da177e4SLinus Torvalds 	[FRD_CODE >> 20] = floatx80_rdv,
491da177e4SLinus Torvalds };
501da177e4SLinus Torvalds 
floatx80_mvf(struct roundingData * roundData,floatx80 rFm)51f148af25SRichard Purdie static floatx80 floatx80_mvf(struct roundingData *roundData, floatx80 rFm)
521da177e4SLinus Torvalds {
531da177e4SLinus Torvalds 	return rFm;
541da177e4SLinus Torvalds }
551da177e4SLinus Torvalds 
floatx80_mnf(struct roundingData * roundData,floatx80 rFm)56f148af25SRichard Purdie static floatx80 floatx80_mnf(struct roundingData *roundData, floatx80 rFm)
571da177e4SLinus Torvalds {
581da177e4SLinus Torvalds 	rFm.high ^= 0x8000;
591da177e4SLinus Torvalds 	return rFm;
601da177e4SLinus Torvalds }
611da177e4SLinus Torvalds 
floatx80_abs(struct roundingData * roundData,floatx80 rFm)62f148af25SRichard Purdie static floatx80 floatx80_abs(struct roundingData *roundData, floatx80 rFm)
631da177e4SLinus Torvalds {
641da177e4SLinus Torvalds 	rFm.high &= 0x7fff;
651da177e4SLinus Torvalds 	return rFm;
661da177e4SLinus Torvalds }
671da177e4SLinus Torvalds 
68f148af25SRichard Purdie static floatx80 (*const monadic_extended[16])(struct roundingData*, floatx80 rFm) = {
691da177e4SLinus Torvalds 	[MVF_CODE >> 20] = floatx80_mvf,
701da177e4SLinus Torvalds 	[MNF_CODE >> 20] = floatx80_mnf,
711da177e4SLinus Torvalds 	[ABS_CODE >> 20] = floatx80_abs,
721da177e4SLinus Torvalds 	[RND_CODE >> 20] = floatx80_round_to_int,
731da177e4SLinus Torvalds 	[URD_CODE >> 20] = floatx80_round_to_int,
741da177e4SLinus Torvalds 	[SQT_CODE >> 20] = floatx80_sqrt,
751da177e4SLinus Torvalds 	[NRM_CODE >> 20] = floatx80_mvf,
761da177e4SLinus Torvalds };
771da177e4SLinus Torvalds 
ExtendedCPDO(struct roundingData * roundData,const unsigned int opcode,FPREG * rFd)78f148af25SRichard Purdie unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
791da177e4SLinus Torvalds {
801da177e4SLinus Torvalds 	FPA11 *fpa11 = GET_FPA11();
811da177e4SLinus Torvalds 	floatx80 rFm;
821da177e4SLinus Torvalds 	unsigned int Fm, opc_mask_shift;
831da177e4SLinus Torvalds 
841da177e4SLinus Torvalds 	Fm = getFm(opcode);
851da177e4SLinus Torvalds 	if (CONSTANT_FM(opcode)) {
861da177e4SLinus Torvalds 		rFm = getExtendedConstant(Fm);
871da177e4SLinus Torvalds 	} else {
881da177e4SLinus Torvalds 		switch (fpa11->fType[Fm]) {
891da177e4SLinus Torvalds 		case typeSingle:
901da177e4SLinus Torvalds 			rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
911da177e4SLinus Torvalds 			break;
921da177e4SLinus Torvalds 
931da177e4SLinus Torvalds 		case typeDouble:
941da177e4SLinus Torvalds 			rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble);
951da177e4SLinus Torvalds 			break;
961da177e4SLinus Torvalds 
971da177e4SLinus Torvalds 		case typeExtended:
981da177e4SLinus Torvalds 			rFm = fpa11->fpreg[Fm].fExtended;
991da177e4SLinus Torvalds 			break;
1001da177e4SLinus Torvalds 
1011da177e4SLinus Torvalds 		default:
1021da177e4SLinus Torvalds 			return 0;
1031da177e4SLinus Torvalds 		}
1041da177e4SLinus Torvalds 	}
1051da177e4SLinus Torvalds 
1061da177e4SLinus Torvalds 	opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
1071da177e4SLinus Torvalds 	if (!MONADIC_INSTRUCTION(opcode)) {
1081da177e4SLinus Torvalds 		unsigned int Fn = getFn(opcode);
1091da177e4SLinus Torvalds 		floatx80 rFn;
1101da177e4SLinus Torvalds 
1111da177e4SLinus Torvalds 		switch (fpa11->fType[Fn]) {
1121da177e4SLinus Torvalds 		case typeSingle:
1131da177e4SLinus Torvalds 			rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
1141da177e4SLinus Torvalds 			break;
1151da177e4SLinus Torvalds 
1161da177e4SLinus Torvalds 		case typeDouble:
1171da177e4SLinus Torvalds 			rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
1181da177e4SLinus Torvalds 			break;
1191da177e4SLinus Torvalds 
1201da177e4SLinus Torvalds 		case typeExtended:
1211da177e4SLinus Torvalds 			rFn = fpa11->fpreg[Fn].fExtended;
1221da177e4SLinus Torvalds 			break;
1231da177e4SLinus Torvalds 
1241da177e4SLinus Torvalds 		default:
1251da177e4SLinus Torvalds 			return 0;
1261da177e4SLinus Torvalds 		}
1271da177e4SLinus Torvalds 
1281da177e4SLinus Torvalds 		if (dyadic_extended[opc_mask_shift]) {
129f148af25SRichard Purdie 			rFd->fExtended = dyadic_extended[opc_mask_shift](roundData, rFn, rFm);
1301da177e4SLinus Torvalds 		} else {
1311da177e4SLinus Torvalds 			return 0;
1321da177e4SLinus Torvalds 		}
1331da177e4SLinus Torvalds 	} else {
1341da177e4SLinus Torvalds 		if (monadic_extended[opc_mask_shift]) {
135f148af25SRichard Purdie 			rFd->fExtended = monadic_extended[opc_mask_shift](roundData, rFm);
1361da177e4SLinus Torvalds 		} else {
1371da177e4SLinus Torvalds 			return 0;
1381da177e4SLinus Torvalds 		}
1391da177e4SLinus Torvalds 	}
1401da177e4SLinus Torvalds 
1411da177e4SLinus Torvalds 	return 1;
1421da177e4SLinus Torvalds }
143