Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)     NetWinder Floating Point Emulator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)     (c) Rebel.COM, 1998,1999
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)     (c) Philip Blundell, 2001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include "fpa11.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include "fpopcode.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) unsigned int EmulateCPDO(const unsigned int opcode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	FPA11 *fpa11 = GET_FPA11();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	FPREG *rFd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	unsigned int nType, nDest, nRc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	struct roundingData roundData;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	/* Get the destination size.  If not valid let Linux perform
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	   an invalid instruction trap. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	nDest = getDestinationSize(opcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	if (typeNone == nDest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	roundData.mode = SetRoundingMode(opcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	roundData.precision = SetRoundingPrecision(opcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	roundData.exception = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	/* Compare the size of the operands in Fn and Fm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	   Choose the largest size and perform operations in that size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	   in order to make use of all the precision of the operands.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	   If Fm is a constant, we just grab a constant of a size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	   matching the size of the operand in Fn. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	if (MONADIC_INSTRUCTION(opcode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 		nType = nDest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 		nType = fpa11->fType[getFn(opcode)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	if (!CONSTANT_FM(opcode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 		register unsigned int Fm = getFm(opcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 		if (nType < fpa11->fType[Fm]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 			nType = fpa11->fType[Fm];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	rFd = &fpa11->fpreg[getFd(opcode)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	switch (nType) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	case typeSingle:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		nRc = SingleCPDO(&roundData, opcode, rFd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	case typeDouble:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		nRc = DoubleCPDO(&roundData, opcode, rFd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) #ifdef CONFIG_FPE_NWFPE_XP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	case typeExtended:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		nRc = ExtendedCPDO(&roundData, opcode, rFd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		nRc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	/* The CPDO functions used to always set the destination type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	   to be the same as their working size. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	if (nRc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		/* If the operation succeeded, check to see if the result in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 		   destination register is the correct size.  If not force it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		   to be. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		fpa11->fType[getFd(opcode)] = nDest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) #ifdef CONFIG_FPE_NWFPE_XP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		if (nDest != nType) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 			switch (nDest) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 			case typeSingle:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 				{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 					if (typeDouble == nType)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 						rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 					else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 						rFd->fSingle = floatx80_to_float32(&roundData, rFd->fExtended);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 			case typeDouble:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 				{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 					if (typeSingle == nType)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 						rFd->fDouble = float32_to_float64(rFd->fSingle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 					else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 						rFd->fDouble = floatx80_to_float64(&roundData, rFd->fExtended);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 			case typeExtended:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 				{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 					if (typeSingle == nType)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 						rFd->fExtended = float32_to_floatx80(rFd->fSingle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 					else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 						rFd->fExtended = float64_to_floatx80(rFd->fDouble);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		if (nDest != nType) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 			if (nDest == typeSingle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 				rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 				rFd->fDouble = float32_to_float64(rFd->fSingle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	if (roundData.exception)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		float_raise(roundData.exception);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	return nRc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }