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
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*---------------------------------------------------------------------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  |  reg_mul.c                                                                |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  |                                                                           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  | Multiply one FPU_REG by another, put the result in a destination FPU_REG. |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  |                                                                           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  | Copyright (C) 1992,1993,1997                                              |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  |                  E-mail   billm@suburbia.net                              |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  |                                                                           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  | Returns the tag of the result if no exceptions or errors occurred.        |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  |                                                                           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  +---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) /*---------------------------------------------------------------------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  | The destination may be any FPU_REG, including one of the source FPU_REGs. |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  +---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include "fpu_emu.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include "exception.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include "reg_constant.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include "fpu_system.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)   Multiply two registers to give a register result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)   The sources are st(deststnr) and (b,tagb,signb).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)   The destination is st(deststnr).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)   */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) /* This routine must be called with non-empty source registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) int FPU_mul(FPU_REG const *b, u_char tagb, int deststnr, int control_w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	FPU_REG *a = &st(deststnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	FPU_REG *dest = a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	u_char taga = FPU_gettagi(deststnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	u_char saved_sign = getsign(dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	u_char sign = (getsign(a) ^ getsign(b));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	int tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	if (!(taga | tagb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		/* Both regs Valid, this should be the most common case. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		tag =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 		    FPU_u_mul(a, b, dest, control_w, sign,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 			      exponent(a) + exponent(b));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		if (tag < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 			setsign(dest, saved_sign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 			return tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		FPU_settagi(deststnr, tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		return tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	if (taga == TAG_Special)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		taga = FPU_Special(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	if (tagb == TAG_Special)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		tagb = FPU_Special(b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	if (((taga == TAG_Valid) && (tagb == TW_Denormal))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	    || ((taga == TW_Denormal) && (tagb == TAG_Valid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	    || ((taga == TW_Denormal) && (tagb == TW_Denormal))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 		FPU_REG x, y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 		if (denormal_operand() < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 			return FPU_Exception;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		FPU_to_exp16(a, &x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 		FPU_to_exp16(b, &y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		tag = FPU_u_mul(&x, &y, dest, control_w, sign,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 				exponent16(&x) + exponent16(&y));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		if (tag < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 			setsign(dest, saved_sign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 			return tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		FPU_settagi(deststnr, tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		return tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	} else if ((taga <= TW_Denormal) && (tagb <= TW_Denormal)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		if (((tagb == TW_Denormal) || (taga == TW_Denormal))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		    && (denormal_operand() < 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 			return FPU_Exception;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		/* Must have either both arguments == zero, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		   one valid and the other zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		   The result is therefore zero. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		/* The 80486 book says that the answer is +0, but a real
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		   80486 behaves this way.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		   IEEE-754 apparently says it should be this way. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		setsign(dest, sign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		return TAG_Zero;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	/* Must have infinities, NaNs, etc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	else if ((taga == TW_NaN) || (tagb == TW_NaN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		return real_2op_NaN(b, tagb, deststnr, &st(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	} else if (((taga == TW_Infinity) && (tagb == TAG_Zero))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		   || ((tagb == TW_Infinity) && (taga == TAG_Zero))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		return arith_invalid(deststnr);	/* Zero*Infinity is invalid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	} else if (((taga == TW_Denormal) || (tagb == TW_Denormal))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		   && (denormal_operand() < 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		return FPU_Exception;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	} else if (taga == TW_Infinity) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		FPU_copy_to_regi(a, TAG_Special, deststnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		setsign(dest, sign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		return TAG_Special;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	} else if (tagb == TW_Infinity) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		FPU_copy_to_regi(b, TAG_Special, deststnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		setsign(dest, sign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		return TAG_Special;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #ifdef PARANOID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		EXCEPTION(EX_INTERNAL | 0x102);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		return FPU_Exception;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #endif /* PARANOID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }