1*74ba9207SThomas 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 union float64_components {
151da177e4SLinus Torvalds float64 f64;
161da177e4SLinus Torvalds unsigned int i[2];
171da177e4SLinus Torvalds };
181da177e4SLinus Torvalds
191da177e4SLinus Torvalds float64 float64_exp(float64 Fm);
201da177e4SLinus Torvalds float64 float64_ln(float64 Fm);
211da177e4SLinus Torvalds float64 float64_sin(float64 rFm);
221da177e4SLinus Torvalds float64 float64_cos(float64 rFm);
231da177e4SLinus Torvalds float64 float64_arcsin(float64 rFm);
241da177e4SLinus Torvalds float64 float64_arctan(float64 rFm);
251da177e4SLinus Torvalds float64 float64_log(float64 rFm);
261da177e4SLinus Torvalds float64 float64_tan(float64 rFm);
271da177e4SLinus Torvalds float64 float64_arccos(float64 rFm);
281da177e4SLinus Torvalds float64 float64_pow(float64 rFn, float64 rFm);
291da177e4SLinus Torvalds float64 float64_pol(float64 rFn, float64 rFm);
301da177e4SLinus Torvalds
float64_rsf(struct roundingData * roundData,float64 rFn,float64 rFm)31f148af25SRichard Purdie static float64 float64_rsf(struct roundingData *roundData, float64 rFn, float64 rFm)
321da177e4SLinus Torvalds {
33f148af25SRichard Purdie return float64_sub(roundData, rFm, rFn);
341da177e4SLinus Torvalds }
351da177e4SLinus Torvalds
float64_rdv(struct roundingData * roundData,float64 rFn,float64 rFm)36f148af25SRichard Purdie static float64 float64_rdv(struct roundingData *roundData, float64 rFn, float64 rFm)
371da177e4SLinus Torvalds {
38f148af25SRichard Purdie return float64_div(roundData, rFm, rFn);
391da177e4SLinus Torvalds }
401da177e4SLinus Torvalds
41f148af25SRichard Purdie static float64 (*const dyadic_double[16])(struct roundingData*, float64 rFn, float64 rFm) = {
421da177e4SLinus Torvalds [ADF_CODE >> 20] = float64_add,
431da177e4SLinus Torvalds [MUF_CODE >> 20] = float64_mul,
441da177e4SLinus Torvalds [SUF_CODE >> 20] = float64_sub,
451da177e4SLinus Torvalds [RSF_CODE >> 20] = float64_rsf,
461da177e4SLinus Torvalds [DVF_CODE >> 20] = float64_div,
471da177e4SLinus Torvalds [RDF_CODE >> 20] = float64_rdv,
481da177e4SLinus Torvalds [RMF_CODE >> 20] = float64_rem,
491da177e4SLinus Torvalds
501da177e4SLinus Torvalds /* strictly, these opcodes should not be implemented */
511da177e4SLinus Torvalds [FML_CODE >> 20] = float64_mul,
521da177e4SLinus Torvalds [FDV_CODE >> 20] = float64_div,
531da177e4SLinus Torvalds [FRD_CODE >> 20] = float64_rdv,
541da177e4SLinus Torvalds };
551da177e4SLinus Torvalds
float64_mvf(struct roundingData * roundData,float64 rFm)56f148af25SRichard Purdie static float64 float64_mvf(struct roundingData *roundData,float64 rFm)
571da177e4SLinus Torvalds {
581da177e4SLinus Torvalds return rFm;
591da177e4SLinus Torvalds }
601da177e4SLinus Torvalds
float64_mnf(struct roundingData * roundData,float64 rFm)61f148af25SRichard Purdie static float64 float64_mnf(struct roundingData *roundData,float64 rFm)
621da177e4SLinus Torvalds {
631da177e4SLinus Torvalds union float64_components u;
641da177e4SLinus Torvalds
651da177e4SLinus Torvalds u.f64 = rFm;
661da177e4SLinus Torvalds #ifdef __ARMEB__
671da177e4SLinus Torvalds u.i[0] ^= 0x80000000;
681da177e4SLinus Torvalds #else
691da177e4SLinus Torvalds u.i[1] ^= 0x80000000;
701da177e4SLinus Torvalds #endif
711da177e4SLinus Torvalds
721da177e4SLinus Torvalds return u.f64;
731da177e4SLinus Torvalds }
741da177e4SLinus Torvalds
float64_abs(struct roundingData * roundData,float64 rFm)75f148af25SRichard Purdie static float64 float64_abs(struct roundingData *roundData,float64 rFm)
761da177e4SLinus Torvalds {
771da177e4SLinus Torvalds union float64_components u;
781da177e4SLinus Torvalds
791da177e4SLinus Torvalds u.f64 = rFm;
801da177e4SLinus Torvalds #ifdef __ARMEB__
811da177e4SLinus Torvalds u.i[0] &= 0x7fffffff;
821da177e4SLinus Torvalds #else
831da177e4SLinus Torvalds u.i[1] &= 0x7fffffff;
841da177e4SLinus Torvalds #endif
851da177e4SLinus Torvalds
861da177e4SLinus Torvalds return u.f64;
871da177e4SLinus Torvalds }
881da177e4SLinus Torvalds
89f148af25SRichard Purdie static float64 (*const monadic_double[16])(struct roundingData *, float64 rFm) = {
901da177e4SLinus Torvalds [MVF_CODE >> 20] = float64_mvf,
911da177e4SLinus Torvalds [MNF_CODE >> 20] = float64_mnf,
921da177e4SLinus Torvalds [ABS_CODE >> 20] = float64_abs,
931da177e4SLinus Torvalds [RND_CODE >> 20] = float64_round_to_int,
941da177e4SLinus Torvalds [URD_CODE >> 20] = float64_round_to_int,
951da177e4SLinus Torvalds [SQT_CODE >> 20] = float64_sqrt,
961da177e4SLinus Torvalds [NRM_CODE >> 20] = float64_mvf,
971da177e4SLinus Torvalds };
981da177e4SLinus Torvalds
DoubleCPDO(struct roundingData * roundData,const unsigned int opcode,FPREG * rFd)99f148af25SRichard Purdie unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
1001da177e4SLinus Torvalds {
1011da177e4SLinus Torvalds FPA11 *fpa11 = GET_FPA11();
1021da177e4SLinus Torvalds float64 rFm;
1031da177e4SLinus Torvalds unsigned int Fm, opc_mask_shift;
1041da177e4SLinus Torvalds
1051da177e4SLinus Torvalds Fm = getFm(opcode);
1061da177e4SLinus Torvalds if (CONSTANT_FM(opcode)) {
1071da177e4SLinus Torvalds rFm = getDoubleConstant(Fm);
1081da177e4SLinus Torvalds } else {
1091da177e4SLinus Torvalds switch (fpa11->fType[Fm]) {
1101da177e4SLinus Torvalds case typeSingle:
1111da177e4SLinus Torvalds rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle);
1121da177e4SLinus Torvalds break;
1131da177e4SLinus Torvalds
1141da177e4SLinus Torvalds case typeDouble:
1151da177e4SLinus Torvalds rFm = fpa11->fpreg[Fm].fDouble;
1161da177e4SLinus Torvalds break;
1171da177e4SLinus Torvalds
1181da177e4SLinus Torvalds default:
1191da177e4SLinus Torvalds return 0;
1201da177e4SLinus Torvalds }
1211da177e4SLinus Torvalds }
1221da177e4SLinus Torvalds
1231da177e4SLinus Torvalds opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
1241da177e4SLinus Torvalds if (!MONADIC_INSTRUCTION(opcode)) {
1251da177e4SLinus Torvalds unsigned int Fn = getFn(opcode);
1261da177e4SLinus Torvalds float64 rFn;
1271da177e4SLinus Torvalds
1281da177e4SLinus Torvalds switch (fpa11->fType[Fn]) {
1291da177e4SLinus Torvalds case typeSingle:
1301da177e4SLinus Torvalds rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle);
1311da177e4SLinus Torvalds break;
1321da177e4SLinus Torvalds
1331da177e4SLinus Torvalds case typeDouble:
1341da177e4SLinus Torvalds rFn = fpa11->fpreg[Fn].fDouble;
1351da177e4SLinus Torvalds break;
1361da177e4SLinus Torvalds
1371da177e4SLinus Torvalds default:
1381da177e4SLinus Torvalds return 0;
1391da177e4SLinus Torvalds }
1401da177e4SLinus Torvalds
1411da177e4SLinus Torvalds if (dyadic_double[opc_mask_shift]) {
142f148af25SRichard Purdie rFd->fDouble = dyadic_double[opc_mask_shift](roundData, rFn, rFm);
1431da177e4SLinus Torvalds } else {
1441da177e4SLinus Torvalds return 0;
1451da177e4SLinus Torvalds }
1461da177e4SLinus Torvalds } else {
1471da177e4SLinus Torvalds if (monadic_double[opc_mask_shift]) {
148f148af25SRichard Purdie rFd->fDouble = monadic_double[opc_mask_shift](roundData, rFm);
1491da177e4SLinus Torvalds } else {
1501da177e4SLinus Torvalds return 0;
1511da177e4SLinus Torvalds }
1521da177e4SLinus Torvalds }
1531da177e4SLinus Torvalds
1541da177e4SLinus Torvalds return 1;
1551da177e4SLinus Torvalds }
156