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 (c) Philip Blundell, 2001
61da177e4SLinus Torvalds
71da177e4SLinus Torvalds Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
81da177e4SLinus Torvalds
91da177e4SLinus Torvalds */
101da177e4SLinus Torvalds
111da177e4SLinus Torvalds #include "fpa11.h"
121da177e4SLinus Torvalds #include "softfloat.h"
131da177e4SLinus Torvalds #include "fpopcode.h"
141da177e4SLinus Torvalds
151da177e4SLinus Torvalds float32 float32_exp(float32 Fm);
161da177e4SLinus Torvalds float32 float32_ln(float32 Fm);
171da177e4SLinus Torvalds float32 float32_sin(float32 rFm);
181da177e4SLinus Torvalds float32 float32_cos(float32 rFm);
191da177e4SLinus Torvalds float32 float32_arcsin(float32 rFm);
201da177e4SLinus Torvalds float32 float32_arctan(float32 rFm);
211da177e4SLinus Torvalds float32 float32_log(float32 rFm);
221da177e4SLinus Torvalds float32 float32_tan(float32 rFm);
231da177e4SLinus Torvalds float32 float32_arccos(float32 rFm);
241da177e4SLinus Torvalds float32 float32_pow(float32 rFn, float32 rFm);
251da177e4SLinus Torvalds float32 float32_pol(float32 rFn, float32 rFm);
261da177e4SLinus Torvalds
float32_rsf(struct roundingData * roundData,float32 rFn,float32 rFm)27f148af25SRichard Purdie static float32 float32_rsf(struct roundingData *roundData, float32 rFn, float32 rFm)
281da177e4SLinus Torvalds {
29f148af25SRichard Purdie return float32_sub(roundData, rFm, rFn);
301da177e4SLinus Torvalds }
311da177e4SLinus Torvalds
float32_rdv(struct roundingData * roundData,float32 rFn,float32 rFm)32f148af25SRichard Purdie static float32 float32_rdv(struct roundingData *roundData, float32 rFn, float32 rFm)
331da177e4SLinus Torvalds {
34f148af25SRichard Purdie return float32_div(roundData, rFm, rFn);
351da177e4SLinus Torvalds }
361da177e4SLinus Torvalds
37f148af25SRichard Purdie static float32 (*const dyadic_single[16])(struct roundingData *, float32 rFn, float32 rFm) = {
381da177e4SLinus Torvalds [ADF_CODE >> 20] = float32_add,
391da177e4SLinus Torvalds [MUF_CODE >> 20] = float32_mul,
401da177e4SLinus Torvalds [SUF_CODE >> 20] = float32_sub,
411da177e4SLinus Torvalds [RSF_CODE >> 20] = float32_rsf,
421da177e4SLinus Torvalds [DVF_CODE >> 20] = float32_div,
431da177e4SLinus Torvalds [RDF_CODE >> 20] = float32_rdv,
441da177e4SLinus Torvalds [RMF_CODE >> 20] = float32_rem,
451da177e4SLinus Torvalds
461da177e4SLinus Torvalds [FML_CODE >> 20] = float32_mul,
471da177e4SLinus Torvalds [FDV_CODE >> 20] = float32_div,
481da177e4SLinus Torvalds [FRD_CODE >> 20] = float32_rdv,
491da177e4SLinus Torvalds };
501da177e4SLinus Torvalds
float32_mvf(struct roundingData * roundData,float32 rFm)51f148af25SRichard Purdie static float32 float32_mvf(struct roundingData *roundData, float32 rFm)
521da177e4SLinus Torvalds {
531da177e4SLinus Torvalds return rFm;
541da177e4SLinus Torvalds }
551da177e4SLinus Torvalds
float32_mnf(struct roundingData * roundData,float32 rFm)56f148af25SRichard Purdie static float32 float32_mnf(struct roundingData *roundData, float32 rFm)
571da177e4SLinus Torvalds {
581da177e4SLinus Torvalds return rFm ^ 0x80000000;
591da177e4SLinus Torvalds }
601da177e4SLinus Torvalds
float32_abs(struct roundingData * roundData,float32 rFm)61f148af25SRichard Purdie static float32 float32_abs(struct roundingData *roundData, float32 rFm)
621da177e4SLinus Torvalds {
631da177e4SLinus Torvalds return rFm & 0x7fffffff;
641da177e4SLinus Torvalds }
651da177e4SLinus Torvalds
66f148af25SRichard Purdie static float32 (*const monadic_single[16])(struct roundingData*, float32 rFm) = {
671da177e4SLinus Torvalds [MVF_CODE >> 20] = float32_mvf,
681da177e4SLinus Torvalds [MNF_CODE >> 20] = float32_mnf,
691da177e4SLinus Torvalds [ABS_CODE >> 20] = float32_abs,
701da177e4SLinus Torvalds [RND_CODE >> 20] = float32_round_to_int,
711da177e4SLinus Torvalds [URD_CODE >> 20] = float32_round_to_int,
721da177e4SLinus Torvalds [SQT_CODE >> 20] = float32_sqrt,
731da177e4SLinus Torvalds [NRM_CODE >> 20] = float32_mvf,
741da177e4SLinus Torvalds };
751da177e4SLinus Torvalds
SingleCPDO(struct roundingData * roundData,const unsigned int opcode,FPREG * rFd)76f148af25SRichard Purdie unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
771da177e4SLinus Torvalds {
781da177e4SLinus Torvalds FPA11 *fpa11 = GET_FPA11();
791da177e4SLinus Torvalds float32 rFm;
801da177e4SLinus Torvalds unsigned int Fm, opc_mask_shift;
811da177e4SLinus Torvalds
821da177e4SLinus Torvalds Fm = getFm(opcode);
831da177e4SLinus Torvalds if (CONSTANT_FM(opcode)) {
841da177e4SLinus Torvalds rFm = getSingleConstant(Fm);
851da177e4SLinus Torvalds } else if (fpa11->fType[Fm] == typeSingle) {
861da177e4SLinus Torvalds rFm = fpa11->fpreg[Fm].fSingle;
871da177e4SLinus Torvalds } else {
881da177e4SLinus Torvalds return 0;
891da177e4SLinus Torvalds }
901da177e4SLinus Torvalds
911da177e4SLinus Torvalds opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
921da177e4SLinus Torvalds if (!MONADIC_INSTRUCTION(opcode)) {
931da177e4SLinus Torvalds unsigned int Fn = getFn(opcode);
941da177e4SLinus Torvalds float32 rFn;
951da177e4SLinus Torvalds
961da177e4SLinus Torvalds if (fpa11->fType[Fn] == typeSingle &&
971da177e4SLinus Torvalds dyadic_single[opc_mask_shift]) {
981da177e4SLinus Torvalds rFn = fpa11->fpreg[Fn].fSingle;
99f148af25SRichard Purdie rFd->fSingle = dyadic_single[opc_mask_shift](roundData, rFn, rFm);
1001da177e4SLinus Torvalds } else {
1011da177e4SLinus Torvalds return 0;
1021da177e4SLinus Torvalds }
1031da177e4SLinus Torvalds } else {
1041da177e4SLinus Torvalds if (monadic_single[opc_mask_shift]) {
105f148af25SRichard Purdie rFd->fSingle = monadic_single[opc_mask_shift](roundData, rFm);
1061da177e4SLinus Torvalds } else {
1071da177e4SLinus Torvalds return 0;
1081da177e4SLinus Torvalds }
1091da177e4SLinus Torvalds }
1101da177e4SLinus Torvalds
1111da177e4SLinus Torvalds return 1;
1121da177e4SLinus Torvalds }
113