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